精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

OHOS3.0啟動流程分析丨init階段

開發 前端
內核啟動完是init階段,源碼的路徑在 base\startup\init_lite\services\src\main.c,雖然文件夾命名為init_lite,但是init部分的代碼是小型系統(small system)和標準系統(standard system)通用的。

[[429808]]

想了解更多內容,請訪問:

51CTO和華為官方合作共建的鴻蒙技術社區

https://harmonyos.51cto.com

init階段

內核啟動完是init階段,源碼的路徑在 base\startup\init_lite\services\src\main.c,雖然文件夾命名為init_lite,但是init部分的代碼是小型系統(small system)和標準系統(standard system)通用的。相關碼倉啟動模塊init進程 (gitee.com)

接下來參考linux內核梳理下啟動流程,

1.關閉輸入輸出

/dev/null,空設備,特殊的設備文件,丟棄一切寫入其中的數據(但報告寫入操作成功),讀取它則會立即得到一個EOF。其作用是對stdin/stdout/stderr進行保護,把文件描述符0,1,2分配出去,以后再分配的時候就不會將stdin/stdout/stderr打開,以達到保護目的。

  1. // base\startup\init_lite\services\src\device.c 
  2. void CloseStdio(void) 
  3.     int fd = open("/dev/null", O_RDWR | O_CLOEXEC); 
  4.     if (fd < 0) { 
  5.         return
  6.     } 
  7.     dup2(fd, 0); 
  8.     dup2(fd, 1); 
  9.     dup2(fd, 2); 
  10.     close(fd); 

2.在串口打印調試信息

寫入/dev/kmsg的信息,可以在dmesg(開機信息)中查看。

  1. // base\startup\init_lite\services\log\init_log.c 
  2. void OpenLogDevice(void) 
  3.     int fd = open("/dev/kmsg", O_WRONLY | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IRGRP); 
  4.     if (fd >= 0) { 
  5.         g_fd = fd; 
  6.     } 
  7.     return

 標準系統空實現,不深究了。

  1. // base\startup\init_lite\services\src\main.c 
  2. static void PrintSysInfo() 
  3. #ifdef OHOS_LITE 
  4.     const char* sysInfo = GetVersionId(); 
  5.     if (sysInfo != NULL) { 
  6.         INIT_LOGE("%s", sysInfo); 
  7.         return
  8.     } 
  9.     INIT_LOGE("main, GetVersionId failed!"); 
  10. #endif 

3.掛載目錄,建立索引節點

  1. // base\startup\init_lite\services\src\device.c 
  2. void MountBasicFs(void) 
  3.     mount("tmpfs""/dev""tmpfs", MS_NOSUID, "mode=0755" 
  4.     mkdir("/dev/pts", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) 
  5.     mount("devpts""/dev/pts""devpts", 0, NULL
  6.     mount("proc""/proc""proc", 0, "hidepid=2"
  7.     mount("sysfs""/sys""sysfs", 0, NULL
  8.     mount("selinuxfs""/sys/fs/selinux""selinuxfs", 0, NULL
  9. void CreateDeviceNode(void) 
  10.     mknod("/dev/kmsg", S_IFCHR | DEFAULT_NO_AUTHORITY_MODE, makedev(MEM_MAJOR, DEV_KMSG_MINOR) 
  11.     mknod("/dev/null", S_IFCHR | DEFAULT_RW_MODE, makedev(MEM_MAJOR, DEV_NULL_MINOR) 
  12.     mknod("/dev/random", S_IFCHR | DEFAULT_RW_MODE, makedev(MEM_MAJOR, DEV_RANDOM_MINOR) 
  13.     mknod("/dev/urandom", S_IFCHR | DEFAULT_RW_MODE, makedev(MEM_MAJOR, DEV_URANDOM_MINOR) 

4.開啟DevKmsg

注釋很清楚了,printk_devkmsg默認是流控的,設置為on取消流控。

  1. // base\startup\init_lite\services\log\init_log.c 
  2. void EnableDevKmsg(void) 
  3.     /* printk_devkmsg default value is ratelimit, We need to set "on" and remove the restrictions */ 
  4.     int fd = open("/proc/sys/kernel/printk_devkmsg", O_WRONLY | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IRGRP); 
  5.     ...         
  6.     write(fd, "on", strlen("on") + 1); 
  7.     close(fd); 
  8.     fd = -1; 
  9.     return

5.建立Socket文件夾

/dev/unix/socket/不過這個干啥用的,還沒搞清楚。

  1. MakeSocketDir("/dev/unix/socket/", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); 
  2. // base\startup\init_lite\services\src\device.c 
  3. int MakeSocketDir(const char *path, mode_t mode) 
  4.     int rc = mkdir("/dev/unix/", mode); 
  5.     ...  
  6.     rc = mkdir("/dev/unix/socket/", mode); 
  7.     ... 

6.Singnal初始化

  1. // base\startup\init_lite\services\src\init_signal_handler.c 
  2. void SignalInitModule() 
  3.     int ret = uv_signal_init(uv_default_loop(), &g_sigchldHandler); 
  4.     int ret1 = uv_signal_init(uv_default_loop(), &g_sigtermHandler); 
  5.     if (ret != 0 && ret1 != 0) { 
  6.         INIT_LOGW("initialize signal handler failed"); 
  7.         return
  8.     } 
  9.  
  10.     if (uv_signal_start(&g_sigchldHandler, UVSignalHandler, SIGCHLD) != 0) { 
  11.         INIT_LOGW("start SIGCHLD handler failed"); 
  12.     } 
  13.     if (uv_signal_start(&g_sigtermHandler, UVSignalHandler, SIGTERM) != 0) { 
  14.         INIT_LOGW("start SIGTERM handler failed"); 
  15.     } 

7.執行命令腳本文件

兼容常規的*.rc文件,是執行linux運行命令的腳本文件。

  1. // base\startup\init_lite\services\src\init_adapter.c 
  2. void ExecuteRcs() 
  3. #if (defined __LINUX__) && (defined NEED_EXEC_RCS_LINUX) 
  4.     pid_t retPid = fork(); 
  5.     if (retPid < 0) { 
  6.         INIT_LOGE("ExecuteRcs, fork failed! err %d.", errno); 
  7.         return
  8.     } 
  9.  
  10.     // child process 
  11.     if (retPid == 0) { 
  12.         INIT_LOGI("ExecuteRcs, child process id %d.", getpid()); 
  13.         if (execle("/bin/sh""sh""/etc/init.d/rcS"NULLNULL) != 0) { 
  14.             INIT_LOGE("ExecuteRcs, execle failed! err %d.", errno); 
  15.         } 
  16.         _exit(0x7f); // 0x7f: user specified 
  17.     } 
  18.  
  19.     // init process 
  20.     sem_t sem; 
  21.     if (sem_init(&sem, 0, 0) != 0) { 
  22.         INIT_LOGE("ExecuteRcs, sem_init failed, err %d.", errno); 
  23.         return
  24.     } 
  25.     SignalRegWaitSem(retPid, &sem); 
  26.  
  27.     // wait until rcs process exited 
  28.     if (sem_wait(&sem) != 0) { 
  29.         INIT_LOGE("ExecuteRcs, sem_wait failed, err %d.", errno); 
  30.     } 
  31. #endif 

8.【重要】解析并執行*.cfg文件。

OHOS3.0中的命令腳本文件是*.cfg,采用JSON格式,存儲的信息更多一些。前面都是啟動系統的一些準備工作,而接下來才是重要部分。還是用個表格來分析。

base\startup\init_lite\services\src\init_read_cfg.c

a.初始化服務參數的工作區

  1. // base\startup\init_lite\services\param\service\param_service.c 
  2. void InitParamService() 
  3.     int ret = InitParamWorkSpace(&g_paramWorkSpace, 0, g_initContext); 
  4.     PARAM_CHECK(ret == 0, return"Init parameter workspace fail"); 

b.解析init.cfg文件

  1. ./base/startup/init_lite/services/etc/init.cfg 
  2. ./base/update/updater/services/etc/init.cfg 
  3. ./out/ohos-arm-release/packages/phone/system/etc/init.cfg 
  4. ./out/ohos-arm-release/packages/phone/updater/etc/init.cfg 
  5. ./out/ohos-arm-release/obj/base/startup/init_lite/services/base/startup/init_lite/services/etc/init.cfg 
  6. ./out/ohos-arm-release/obj/base/update/updater/services/base/update/updater/services/etc/init.cfg 
  7. ./device/hisilicon/hi3516dv300/updater/init.cfg 

編譯框架使用的哪個init.cfg還有待確定。

  1. // base\startup\init_lite\services\src\init_read_cfg.c 
  2. void ParseInitCfg(const char *configFile) // 文件路徑"/etc/init.cfg" 
  3.     ... 
  4.     char *fileBuf = ReadFileToBuf(configFile);  // 讀取*.cfg文件 
  5.     cJSON* fileRoot = cJSON_Parse(fileBuf);     // 解析成JSON 
  6.     ... 
  7.     ParseInitCfgContents(fileRoot); 
  8.     ... 
  9. ---------------------------------------------------------------------- 
  10. static void ParseInitCfgContents(const cJSON *root) // JSON格式的init.cfg 
  11.     ... 
  12.     ParseAllServices(root);     // ①.解析"services"部分,并執行 
  13.     ... 
  14.     ParseAllJobs(root);         // Liteos走這邊 
  15.     ParseTriggerConfig(root);   // Linux走這邊,②.解析"jobs"部分,并執行 
  16.     ... 
  17.     ParseAllImports(root);      // ③.提取init.cfg中"import"的部分,并執行 

①.解析"services"部分,并執行

  1. // base\startup\init_lite\services\src\init_service_manager.c 
  2. void ParseAllServices(const cJSON* fileRoot) 
  3.     int servArrSize = 0; 
  4.     cJSON* serviceArr = GetArrItem(fileRoot, &servArrSize, "services"); 
  5.     ... // 截取 init.cfg 中的"services"部分 
  6.     ///////////////////////////////// 參考格式 
  7.         "services" : [{ 
  8.             "name" : "ueventd"
  9.             "path" : ["/system/bin/ueventd"], 
  10.             "critical" : 1 
  11.             }, { 
  12.             "name" : "console"
  13.             "path" : ["/system/bin/sh"], 
  14.             "disabled" : 1, 
  15.             "console" : 1, 
  16.             "uid" : "root"
  17.             "gid" : ["shell""log""readproc"
  18.             }] 
  19.     ///////////////////////////////// 參考格式 
  20.     ... // 默認服務數量不能超過100 
  21.     Service* retServices = (Service*)realloc(g_services, sizeof(Service) * (g_servicesCnt + servArrSize)); 
  22.     ...  
  23.     // Skip already saved services, 
  24.     Service* tmp = retServices + g_servicesCnt; 
  25.     if (memset_s(tmp, sizeof(Service) * servArrSize, 0, sizeof(Service) * servArrSize) != EOK) { 
  26.         free(retServices); 
  27.         retServices = NULL
  28.         return
  29.     } 
  30.     // 【重要】然后使用一個for循環遍歷服務數組 
  31.     for (int i = 0; i < servArrSize; ++i) { 
  32.         cJSON* curItem = cJSON_GetArrayItem(serviceArr, i); 
  33.         if (CheckServiceKeyName(curItem) != SERVICE_SUCCESS) { 
  34.             ReleaseServiceMem(&tmp[i]); 
  35.             tmp[i].attribute |= SERVICE_ATTR_INVALID; 
  36.             continue
  37.         } 
  38.         int ret = ParseOneService(curItem, &tmp[i]); 
  39.         if (ret != SERVICE_SUCCESS) {       // 如果服務啟動失敗 
  40.             // release resources if it fails 
  41.             ReleaseServiceMem(&tmp[i]); 
  42.             tmp[i].attribute |= SERVICE_ATTR_INVALID; 
  43.             INIT_LOGE("Parse information for service %s failed. ", tmp[i].name); 
  44.             continue
  45.         } else {                            // 如果服務啟動成功 
  46.             INIT_LOGD("service[%d] name=%s, uid=%d, critical=%d, disabled=%d"
  47.                 i, tmp[i].name, tmp[i].servPerm.uID, (tmp[i].attribute & SERVICE_ATTR_CRITICAL) ? 1 : 0, 
  48.                 (tmp[i].attribute & SERVICE_ATTR_DISABLED) ? 1 : 0); 
  49.         } 
  50.         if (GetServiceSocket(curItem, &tmp[i]) != SERVICE_SUCCESS) { 
  51.             if (tmp[i].socketCfg != NULL) { 
  52.                 FreeServiceSocket(tmp[i].socketCfg); 
  53.                 tmp[i].socketCfg = NULL
  54.             } 
  55.         } 
  56.         if (GetServiceOnRestart(curItem, &tmp[i]) == SERVICE_FAILURE) { 
  57.             INIT_LOGE("Failed Get Service OnRestart service"); 
  58.         } 
  59.     } 
  60.     // Increase service counter. 
  61.     RegisterServices(retServices, servArrSize);  // 最后注冊服務 
  62. ---------------------------------------------------------------------- 
  63. void RegisterServices(Service* services, int servicesCnt) 
  64.     if (services == NULL) { 
  65.         return
  66.     } 
  67.     g_services = services; 
  68.     g_servicesCnt += servicesCnt; 
  69.     // 到這里init.cfg中的"services"部分就已經解析并執行完畢了。 

②.解析"jobs"部分,并執行

  1. // base\startup\init_lite\services\param\trigger\trigger_processor.c 
  2. int ParseTriggerConfig(const cJSON *fileRoot) 
  3.     ... 
  4.     int ret = InitTriggerWorkSpace(&g_triggerWorkSpace);    // 初始化觸發器的工作空間 
  5.     ... 
  6.     cJSON *triggers = cJSON_GetObjectItemCaseSensitive(fileRoot, "jobs");   // 提取init.cfg中"jobs"的部分 
  7.     ... 
  8.     int size = cJSON_GetArraySize(triggers); 
  9.     ... 
  10.     for (int i = 0; i < size; ++i) { 
  11.         cJSON *item = cJSON_GetArrayItem(triggers, i); 
  12.         ParseTrigger(&g_triggerWorkSpace, item); 
  13.     } 
  14.     return 0; 
  15. ---------------------------------------------------------------------- 
  16. // 截取init.cfg中jobs段的部分代碼,格式如下 
  17. "jobs" : [{ 
  18.             "name" : "pre-init"
  19.             "cmds" : [ 
  20.                 "write /proc/sys/kernel/sysrq 0"
  21.                 ... 
  22.                 "mkdir /data"
  23.             ] 
  24.         }, { 
  25.             "name" : "init"
  26.             "cmds" : [ 
  27.                 "copy /proc/cmdline /dev/urandom"
  28.                 ... 
  29.                 "domainname localdomain" 
  30.             ] 
  31.         }, { 
  32.             "name" : "param:sys.boot_from_charger_mode=1"
  33.             "condition" : "sys.boot_from_charger_mode=1"
  34.             "cmds" : [ 
  35.                 "trigger post-init" 
  36.             ] 
  37.         }, 
  38.           ... 
  39.     ], 
  40. // base\startup\init_lite\services\param\trigger\trigger_manager.c 
  41. int ParseTrigger(TriggerWorkSpace *workSpace, const cJSON *triggerItem) 
  42.     ... // 提取init.cfg中jobs段的"name"的部分 
  43.     char *name = cJSON_GetStringValue(cJSON_GetObjectItem(triggerItem, "name")); 
  44.     ... // 提取init.cfg中jobs段的"condition"的部分 
  45.     char *condition = cJSON_GetStringValue(cJSON_GetObjectItem(triggerItem, "condition"));   
  46.     int index = GetTriggerIndex(name); 
  47.     ... 
  48.     u_int32_t offset = 0; 
  49.     TriggerNode *trigger = GetTriggerByName(workSpace, name, &offset); 
  50.     if (trigger == NULL) { 
  51.         offset = AddTrigger(workSpace, indexname, condition); 
  52.         PARAM_CHECK(offset > 0, return -1, "Failed to create trigger %s"name); 
  53.         trigger = GetTriggerByIndex(workSpace, offset); 
  54.     } else { 
  55.         if (condition != NULL) { 
  56.             PARAM_LOGE("Warning parseTrigger %s %s"name, condition); 
  57.         } 
  58.     } 
  59.     PARAM_LOGD("ParseTrigger %s %u"name, offset); 
  60.  
  61.     // 添加命令行 
  62.     cJSON* cmdItems = cJSON_GetObjectItem(triggerItem, "cmds"); // 提取init.cfg中jobs段的"cmds"的部分 
  63.     ... 
  64.     int cmdLinesCnt = cJSON_GetArraySize(cmdItems); // 獲取命令數量 
  65.     ... 
  66.     for (int i = 0; i < cmdLinesCnt; ++i) { // 循環執行 
  67.         char *cmdLineStr = cJSON_GetStringValue(cJSON_GetArrayItem(cmdItems, i)); 
  68.         ... 
  69.         size_t cmdLineLen = strlen(cmdLineStr); 
  70.         const char *matchCmd = GetMatchCmd(cmdLineStr); 
  71.         if (matchCmd == NULL && strncmp(cmdLineStr, "trigger ", strlen("trigger ")) == 0) { 
  72.             matchCmd = "trigger "
  73.         } 
  74.         ... 
  75.         size_t matchLen = strlen(matchCmd); 
  76.         if (matchLen == cmdLineLen) { 
  77.             offset = AddCommand(workSpace, trigger, matchCmd, NULL); 
  78.         } else { 
  79.             offset = AddCommand(workSpace, trigger, matchCmd, cmdLineStr + matchLen); 
  80.         } 
  81.         PARAM_CHECK(offset > 0, continue"Failed to add command %s", cmdLineStr); 
  82.     } 
  83.     return 0; 

③.提取init.cfg中"import"的部分,并執行

  1. // base\startup\init_lite\services\src\init_import.c 
  2. void ParseAllImports(const cJSON *root) 
  3. {     
  4.     ///////////////////////////////// 參考格式 
  5.         "import" : [ 
  6.             "/etc/init.usb.cfg"
  7.             "/etc/init.usb.configfs.cfg"
  8.             "/etc/init.usb.cfg"
  9.             "/etc/init.Hi3516DV300.usb.cfg"
  10.             "/etc/init.Hi3516DV300.cfg" 
  11.     ],     
  12.     ///////////////////////////////// 
  13.     cJSON *importAttr = cJSON_GetObjectItemCaseSensitive(root, "import");   // 提取init.cfg中"import"的部分 
  14.     ... 
  15.     int importAttrSize = cJSON_GetArraySize(importAttr); 
  16.     for (int i = 0; i < importAttrSize; i++) {  // 循環取出每一項 
  17.         cJSON *importItem = cJSON_GetArrayItem(importAttr, i); 
  18.         ... 
  19.         char *importContent = cJSON_GetStringValue(importItem); 
  20.         ... 
  21. // Only OHOS L2 support parameter. 
  22. #ifndef OHOS_LITE //這里有啥意義,前面都已經判斷過了 
  23.         if (ExtractCfgFile(&cfgFile, importContent) < 0) { 
  24.             INIT_LOGW("Failed to import from %s", importContent); 
  25.             if (cfgFile != NULL) { 
  26.                 free(cfgFile); 
  27.                 cfgFile = NULL
  28.             } 
  29.             continue
  30.         } 
  31. #else 
  32.         cfgFile = importContent; 
  33. #endif 
  34.         INIT_LOGI("Import %s...", cfgFile); 
  35.         ParseInitCfg(cfgFile);  // 取出"import"中的路徑,解析方法和init.cfg解析方式一致。 
  36.         ... 
  37.     } 
  38.     INIT_LOGD("parse import file done"); 
  39.     return

到這里init.cfg就解析并執行完畢了,需要注意的是,import導入的cfg文件是最后才執行的。

c.解析執行/system/etc/init/*.cfg文件

和import的原理類似,遍歷system/etc/init文件夾下的*.cfg文件,并執行。我感覺寫在init.cfg的import中應該也是可以的。

  1. // base\startup\init_lite\services\src\init_read_cfg.c 
  2. static void ParseOtherCfgs() 
  3.     ReadCfgs("/system/etc/init"); 
  4.     return
  5. ------------------------------------ 
  6. static void ReadCfgs(const char *dirPath) 
  7.     DIR *pDir = opendir(dirPath); 
  8.     ... 
  9.     struct dirent *dp; 
  10.     while ((dp = readdir(pDir)) != NULL) { 
  11.         char fileName[FILE_NAME_MAX_SIZE]; 
  12.         if (snprintf_s(fileName, FILE_NAME_MAX_SIZE, FILE_NAME_MAX_SIZE - 1, "%s/%s", dirPath, dp->d_name) == -1) { 
  13.             INIT_LOGE("ParseCfgs snprintf_s failed."); 
  14.             closedir(pDir); 
  15.             return
  16.         } 
  17.         struct stat st; 
  18.         if (stat(fileName, &st) == 0) { 
  19.             if (strstr(dp->d_name, ".cfg") == NULL) { 
  20.                 continue
  21.             } 
  22.             INIT_LOGI("ReadCfgs :%s from %s success.", fileName, dirPath); 
  23.             ParseInitCfg(fileName);  // 和init.cfg同樣的解析方式 
  24.         } 
  25.     } 
  26.     closedir(pDir); 
  27.     return

d.PostTrigger

PostTrigger(EVENT_BOOT, “pre-init”, strlen(“pre-init”));

  1. // base\startup\init_lite\services\param\trigger\trigger_processor.c 
  2. void PostTrigger(EventType type, const char *content, u_int32_t contentLen) 
  3. {     
  4.     ///////////////////////////////////// 參考TriggerDataEvent 
  5.     typedef struct { 
  6.         uv_work_t request; 
  7.         EventType type; 
  8.         u_int32_t contentSize; 
  9.         char content[0]; 
  10.     } TriggerDataEvent; 
  11.     ///////////////////////////////////// 
  12.     ... 
  13.     TriggerDataEvent *event = (TriggerDataEvent *)malloc(sizeof(TriggerDataEvent) + contentLen + 1); 
  14.     ... 
  15.     event->type = type;  // = EVENT_BOOT 
  16.     event->request.data = (void *)((char*)event + sizeof(uv_work_t)); 
  17.     event->contentSize = contentLen;  // = strlen("pre-init"
  18.     event->content[contentLen] = '\0'; // "pre-init"[strlen("pre-init")],設置結束符'\0' 
  19.     SendTriggerEvent(event); 
  20.     ... 
  21. ---------------------------------------------------------------------------- 
  22. static void SendTriggerEvent(TriggerDataEvent *event) 
  23.     .... 
  24.     int ctrlSize = strlen("sys.powerctrl="); 
  25.     if (strncmp(event->content, "sys.powerctrl=", ctrlSize) == 0) {  // 如果event->content為"sys.powerctrl=" 
  26.         char *cmdParam = NULL
  27.         const char *matchCmd = GetCmdInfo(event->content + ctrlSize, event->contentSize - ctrlSize, &cmdParam); 
  28.         if (matchCmd != NULL) { 
  29.             DoCmdByName(matchCmd, cmdParam); 
  30.         } else { 
  31.             PARAM_LOGE("SendTriggerEvent cmd %s not found", event->content); 
  32.         } 
  33.     } else if (strncmp(event->content, "ohos.ctl.start=", strlen("ohos.ctl.start=")) == 0) { // 如果是"ohos.ctl.start=" 
  34.         DoCmdByName("start ", event->content + strlen("ohos.ctl.start=")); 
  35.     } else if (strncmp(event->content, "ohos.ctl.stop=", strlen("ohos.ctl.stop=")) == 0) {  // 如果是"ohos.ctl.stop=" 
  36.         DoCmdByName("stop ", event->content + strlen("ohos.ctl.stop=")); 
  37.     } else {  // 否則執行uv_queue_work(),uv_queue_work是將ProcessEvent提交給子線程執行,完成后通知主線程,防止阻塞 
  38.         uv_queue_work(uv_default_loop(), &event->request, ProcessEvent, ProcessAfterEvent); 
  39.         event = NULL
  40.     } 
  41.     ... 
  42. ----------------------------------------------------------------------- 
  43. // base\startup\init_lite\services\src\init_cmds.c 
  44. void DoCmdByName(const char *name, const char *.cmdContent) 
  45.     ... 
  46.     size_t cmdCnt = sizeof(CMD_TABLE) / sizeof(CMD_TABLE[0]); 
  47.     unsigned int i = 0; 
  48.     for (; i < cmdCnt; ++i) { 
  49.         if (strncmp(name, CMD_TABLE[i].name, strlen(CMD_TABLE[i].name)) == 0) { 
  50.             CMD_TABLE[i].DoFuncion(cmdContent, CMD_TABLE[i].maxArg); 
  51.             break; 
  52.         } 
  53.     } 
  54.     if (i == cmdCnt) { 
  55.         INIT_LOGE("DoCmd, unknown cmd name %s."name); 
  56.     } 

9.啟動參數服務

使用Libuv庫,官網地址。作為Nodejs的底層。

相關的API可以參考網址,uv_run

  1. // base\startup\init_lite\services\param\service\param_service.c 
  2. int StartParamService() 
  3.     PARAM_LOGI("StartParamService."); 
  4.     uv_fs_t req; 
  5.     uv_fs_unlink(uv_default_loop(), &req, PIPE_NAME, NULL); 
  6.  
  7.     uv_pipe_t pipeServer; 
  8.     int ret = uv_pipe_init(uv_default_loop(), &pipeServer, 0); 
  9.     ... 
  10.     ret = uv_pipe_bind(&pipeServer, PIPE_NAME); 
  11.     ... 
  12.     ret = chmod(PIPE_NAME, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); 
  13.     ... 
  14.     ret = uv_listen((uv_stream_t*)&pipeServer, SOMAXCONN, OnConnection); 
  15.     ... 
  16.     uv_run(uv_default_loop(), UV_RUN_DEFAULT);  // 運行事件循環,直到不再有活動和引用的句柄或請求。 
  17.     ... 

至此,init啟動結束,進入pause()。總結下來init首先會執行一些通用的準備操作,同時兼容常規linux內核啟動腳本,之后在執行鴻蒙init.cfg和單板相關*.cfg。以上分析都是我個人見解,如有錯誤歡迎指正。

想了解更多內容,請訪問:

51CTO和華為官方合作共建的鴻蒙技術社區

https://harmonyos.51cto.com

 

責任編輯:jianghua 來源: 鴻蒙社區
相關推薦

2021-12-09 10:11:04

鴻蒙HarmonyOS應用

2021-09-26 10:22:41

鴻蒙HarmonyOS應用

2021-11-23 15:35:05

鴻蒙HarmonyOS應用

2017-08-31 14:40:54

Linuxinit進程app啟動

2017-06-07 12:25:37

Shuffle代碼Map階段處理

2021-11-05 11:57:07

網絡流程Window

2021-10-29 16:36:53

AMSAndroidActivityMan

2022-06-21 11:02:27

系統移植鴻蒙

2021-09-18 14:26:49

Linux Linux 啟動流程Linux 系統

2009-12-29 16:21:46

silverlight

2021-12-02 10:05:01

鴻蒙HarmonyOS應用

2022-08-29 17:34:05

鴻蒙操作系統

2009-10-27 15:06:15

Linux內核啟動

2021-09-22 08:51:34

Android

2021-06-03 09:32:21

云計算云廠商ICT

2015-10-13 18:26:23

TalkingData

2021-06-21 09:25:18

鴻蒙HarmonyOS應用

2024-07-15 09:58:03

OpenRestyNginx日志

2023-09-15 07:39:44

分布式數據庫系統高并發

2010-11-15 10:50:43

Oracle啟動模式
點贊
收藏

51CTO技術棧公眾號

久久视频免费看| gogogo高清免费观看在线视频| 噜噜噜久久,亚洲精品国产品| 亚洲一级网站| 亚洲亚裔videos黑人hd| 日韩高清在线一区二区| 国产社区精品视频| 欧美激情一区二区三区蜜桃视频 | 四虎精品在线观看| 亚洲风情在线资源站| 日本不卡一区二区三区视频| 国产精品欧美久久久久天天影视| 亚洲高清自拍| 中国china体内裑精亚洲片| 日批视频免费看| 91在线成人| 亚洲成在人线免费| 制服国产精品| 男女污污视频在线观看| 国产精品一区一区三区| 国产精品电影观看| 中文字幕亚洲高清| 亚洲国产一区二区三区在线播放| 亚洲精品永久免费| 91成人在线观看喷潮蘑菇| 国产黄色一区| 精品毛片三在线观看| 糖心vlog在线免费观看| 成人在线免费观看| 久久综合丝袜日本网| 国产福利一区二区三区在线观看| 中文字幕一区二区三区四区视频| 亚洲专区免费| 午夜精品久久久久久久久久久久| 一级片一级片一级片| 青青一区二区三区| 亚洲天堂视频在线观看| 青青草视频成人| 国产精品x8x8一区二区| 日韩午夜av一区| 亚洲免费成人在线视频| 国产精品99精品一区二区三区∴| 日韩欧中文字幕| 91丨porny丨探花| 高h视频在线播放| 最新高清无码专区| 永久域名在线精品| 免费黄网站在线播放| 亚洲国产精品国自产拍av| 欧美日韩免费高清| 九色视频成人自拍| 久久精品视频一区二区| 欧美精品尤物在线| 巨骚激情综合| 国产精品色呦呦| 亚洲一卡二卡| 国产婷婷视频在线| 日韩美女精品在线| 超碰97在线看| 丁香花在线高清完整版视频| 亚洲午夜精品在线| 玩弄中年熟妇正在播放| 自拍偷拍亚洲视频| 欧美亚洲禁片免费| 一区二区三区 日韩| 久久69成人| 麻豆精品在线观看| 国产精品三级美女白浆呻吟| 中文字幕乱码在线观看| 美腿丝袜一区二区三区| 成人激情电影一区二区| 精品久久久免费视频| 粉嫩高潮美女一区二区三区 | 亚洲欧美乱综合| 97超碰国产精品| 天天综合av| 欧美丝袜丝交足nylons图片| 在线观看免费的av| 97久久亚洲| 国产视频在线一区二区| 欧美一区二区三区观看| 欧美三级小说| 国产999在线观看| 亚洲综合网av| 丰满亚洲少妇av| 欧美重口乱码一区二区| 免费黄网在线观看| 午夜在线成人av| www.99av.com| 一区二区精彩视频| 亚洲色图校园春色| 午夜免费激情视频| 性久久久久久| 91精品国产高清久久久久久91裸体 | 99热6这里只有精品| 伊人狠狠色j香婷婷综合| 欧洲亚洲妇女av| 国产毛片毛片毛片毛片毛片| bt7086福利一区国产| 亚洲精品国产一区| av手机免费在线观看| 欧美日韩一区中文字幕| 国产a级黄色片| 99九九热只有国产精品| 欧美怡红院视频一区二区三区| 性少妇xx生活| 亚洲国产专区校园欧美| 国产裸体写真av一区二区 | 九九热只有这里有精品| 日韩成人亚洲| 亚洲国产日韩精品在线| 成人黄色短视频| 一区二区日韩免费看| 成人亚洲激情网| 国产区高清在线| 欧美日韩国产在线播放| 天天久久综合网| 国产一区网站| 88xx成人精品| 丰满人妻熟女aⅴ一区| 国产精品亲子伦对白| 国产欧美在线一区| 白嫩白嫩国产精品| 美女久久久久久久久久久| 国产美女www爽爽爽| 99精品在线观看视频| 毛片av在线播放| **日韩最新| 视频直播国产精品| 欧美性受xxx黑人xyx性爽| 91麻豆免费视频| 缅甸午夜性猛交xxxx| 亚洲成人影音| 欧美成人在线影院| 99久久精品国产一区色| 亚洲欧洲www| 天天干天天玩天天操| 国产一区二区三区四区五区| 午夜精品福利视频| 熟妇人妻系列aⅴ无码专区友真希| 一区二区在线观看免费 | 精品成人18| 久久国内精品一国内精品| 中文字幕永久在线观看| 国产色产综合色产在线视频| 丝袜老师办公室里做好紧好爽| 高清日韩中文字幕| 韩日精品中文字幕| 天天操天天干天天| 欧美性少妇18aaaa视频| 精品人妻一区二区三区香蕉 | 久久久综合色| 国产美女久久精品| 欧美精品hd| 日韩一区二区视频| 五月婷婷一区二区| 成人黄色网址在线观看| 欧美三级在线观看视频| 日韩电影不卡一区| 国产成人a亚洲精品| 高h视频在线| 欧美剧在线免费观看网站| 操她视频在线观看| 国产福利91精品一区二区三区| 美女av免费观看| 加勒比中文字幕精品| 55夜色66夜色国产精品视频| 黄色小视频在线免费观看| 精品视频免费在线| 青青草精品在线视频| 成人99免费视频| 精品久久久久久无码国产| 日韩理论片av| 超碰97在线人人| 老司机深夜福利在线观看| 国产一区二区三区视频| 国产精品欧美综合亚洲| 亚洲成人免费影院| jizz中文字幕| 国产福利一区二区三区| 国产美女无遮挡网站| 日韩成人三级| 国产成人一区二区三区免费看| 九九热线视频只有这里最精品| 最近免费中文字幕视频2019| 亚洲精品国产手机| 日本高清不卡一区| 欧美 日韩 国产 一区二区三区| 成人午夜大片免费观看| 亚洲天堂av线| 激情久久婷婷| 一区二区三视频| 欧美精品中文| 91热精品视频| 女生影院久久| 欧美黑人xxx| 97视频在线观看网站| 精品久久久久久久一区二区蜜臀| 91久久国产综合久久91| 一级女性全黄久久生活片免费| 少妇按摩一区二区三区| 国产精品亚洲视频| 五月天婷婷激情视频| 今天的高清视频免费播放成人| 日韩欧美亚洲精品| 国产成人澳门| 96精品久久久久中文字幕| 国产超碰精品| 97激碰免费视频| av中文字幕在线观看| 亚洲桃花岛网站| 天天操天天射天天| 欧美一级欧美一级在线播放| 日韩久久久久久久久久| 亚洲成人av中文| 永久免费看黄网站| 中文字幕永久在线不卡| 亚洲av综合一区二区| 成人性色生活片| 一级黄色免费毛片| 久久99在线观看| wwwwxxxx日韩| 老牛嫩草一区二区三区日本| 久久这里只有精品18| 亚洲欧美偷拍自拍| 亚洲一区二区三区乱码| 国产日产一区| 欧美一区二区三区四区夜夜大片 | 视频一区日韩| 国产日韩欧美在线播放| 日韩欧美2区| 日本久久中文字幕| 日韩三级影视| 日韩免费av一区二区| 超碰国产一区| 日韩av成人在线| 中文在线免费视频| 欧美怡春院一区二区三区| аⅴ资源天堂资源库在线| 高清一区二区三区四区五区| 欧美人与动牲性行为| 欧美第一黄网免费网站| 91精品久久| 日韩欧美的一区| 国内毛片毛片毛片毛片| 欧美一区二区网站| 国产精品网红福利| 亚洲精品一区二区三区区别| 91精品国产色综合久久不卡电影| 91美女精品网站| 欧美日韩aaa| 国产乱叫456在线| 欧美一区二区成人| 空姐吹箫视频大全| 亚洲精品999| 日本一区视频| 国产一区二区三区18| 午夜国产福利在线| 久久精品影视伊人网| 国产福利在线播放麻豆| 色综合视频网站| 美女av在线免费看| 国产91色在线播放| 欧美天堂在线| 99re在线国产| 日韩中出av| 亚洲欧洲国产精品久久| 91tv精品福利国产在线观看| 97久久国产亚洲精品超碰热 | www国产精品视频| h网站久久久| 91高潮在线观看| 欧美天堂一区二区| 国产精品初高中精品久久| 日韩av三区| 亚洲精品在线免费| 欧美区亚洲区| 久久久久久久久久久久久国产精品| 三级一区在线视频先锋| 中文字幕国产高清| 99久久99久久精品免费观看| 日韩av片在线| 亚洲国产另类精品专区| 男人的天堂av网站| 日韩一级片网站| 你懂的视频在线免费| www.精品av.com| 鲁鲁在线中文| 成人av番号网| 天天久久夜夜| 日本成人性视频| 免费亚洲视频| 女教师高潮黄又色视频| 国产日韩精品一区二区三区在线| 国产黄色片在线免费观看| 欧美性猛交xxxx偷拍洗澡| 国产三级在线观看视频| 亚洲日韩欧美视频| 激情av在线播放| 国产日韩欧美视频在线| 日韩伦理一区二区三区| 强开小嫩苞一区二区三区网站| 羞羞答答国产精品www一本| 在线观看视频在线观看| 国产片一区二区| 日本熟妇色xxxxx日本免费看| 欧美午夜精品理论片a级按摩| 色屁屁草草影院ccyycom| 久久久久北条麻妃免费看| 欧美极品免费| 九九热久久66| 亚洲午夜激情在线| 91国内在线播放| 国产欧美日韩另类一区| www日韩精品| 日韩免费观看高清完整版 | 亚洲一区二区在线免费观看视频| 波多野结衣黄色网址| 亚洲激情在线视频| 欧美v亚洲v| 97久久夜色精品国产九色| 不卡中文字幕| 久久午夜夜伦鲁鲁一区二区| 99久久综合狠狠综合久久| 欧美成人aaa片一区国产精品| 欧美日韩精品系列| 国产九色在线| 欧日韩在线观看| 亚州av日韩av| 日韩少妇内射免费播放| 成人少妇影院yyyy| 妺妺窝人体色www聚色窝仙踪| 这里只有精品99re| 日本最新在线视频| 国产日韩欧美91| 国产大片一区| 三级性生活视频| 亚洲欧洲性图库| 97精品久久人人爽人人爽| 亚洲性猛交xxxxwww| 日本免费一区二区三区四区| 蜜桃视频在线观看成人| 一区二区毛片| 国产男男chinese网站| 欧美性猛交xxxx富婆| 欧美高清成人| 国产精品爱久久久久久久| 精品久久久久久久| 国产精品区在线| 亚洲欧美日韩久久| www.我爱av| 海角国产乱辈乱精品视频| 老司机精品在线| 无码人妻丰满熟妇区毛片18| 久久午夜国产精品| 这里只有精品999| 日韩在线欧美在线| 欧美激情精品| 成人免费观看cn| 久久久91精品国产一区二区精品| 亚洲av无码不卡| 久久精品99久久香蕉国产色戒| 国产一区二区三区精品在线观看| 免费看日本黄色| 久久久亚洲午夜电影| 在线免费a视频| 色综合久久天天综线观看| 另类ts人妖一区二区三区| 国产a视频免费观看| 国产精品午夜久久| 国产哺乳奶水91在线播放| 午夜精品一区二区三区在线 | 免费看日本毛片| 国产亚洲成av人在线观看导航| 一级黄色片视频| 欧美国产第一页| 国产成人短视频在线观看| 中文字幕在线观看日| 亚洲一二三四在线| 成人亚洲性情网站www在线观看| 成人春色激情网| 亚洲精品社区| 欧美日韩国产一二三区| 精品国产伦一区二区三区观看方式| 色是在线视频| 在线看视频不卡| av男人天堂一区| 亚洲中文一区二区三区| 午夜剧场成人观在线视频免费观看| 国产成人三级| 一二三区视频在线观看| 欧美综合欧美视频| 国产色婷婷在线| 亚洲v国产v在线观看| 波多野洁衣一区| 一级片视频网站| 日本成熟性欧美| 国产综合精品| 羞羞在线观看视频| 日韩精品视频免费在线观看|