system_server crash现象研究

本文详细探讨了系统服务器崩溃现象,分析了系统服务器与Zygote进程之间的交互关系,以及Zygote如何在系统服务器崩溃后进行自我重启。同时,介绍了init进程如何监控并重新启动服务,确保系统的稳定运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

system_server crash现象研究

分类: android debug 1162人阅读 评论(1) 收藏 举报

现象:当system server进程crash时,发现zygote进程会被杀掉,此后Zyogote进程和system server被重新启动。


分析:在init解析init.rc时,Zygote进程作为一个服务被定义,且被声明为自动重启。因此一旦Zygote进程退出,则init会收到子进程退出信号从而重新启动zygote服务,进而Zygote启动System Server。同样,在System server被Zygote作为子进程启动后,Zygote通过信号监听该子进程状态,一旦退出Zygote将会杀死自身等待init再次运行。另外system server进程将监听service manager进程,如service manager退出则杀掉自身从而导致zygote被重启。


下面为相关代码:


Zygote启动system server入口:

libcore/dalvik/src/main/java/dalvik/system/Zygote.java

  1. /** 
  2.  * Special method to start the system server process. 
  3.  * @deprecated use {@link Zygote#forkSystemServer(int, int, int[], int, int[][])} 
  4.  */  
  5. @Deprecated  
  6. public static int forkSystemServer(int uid, int gid, int[] gids,  
  7.         boolean enableDebugger, int[][] rlimits) {  
  8.     int debugFlags = enableDebugger ? DEBUG_ENABLE_DEBUGGER : 0;  
  9.     return forkAndSpecialize(uid, gid, gids, debugFlags, rlimits);  
  10. }  

forkAndSpecialize是一个JNI函数,其定义见Dalvik_dalvik_system_Zygote_fork(),在其中注册信号处理函数,在有子进程退出时将检查进程pid,仅当中止的子进程pid为system server时才杀掉本进程(zygote进程)。

dalvik_system_Zygote.c

  1. /* native public static int fork(); */  
  2. static void Dalvik_dalvik_system_Zygote_fork(const u4* args, JValue* pResult)  
  3. {  
  4.     pid_t pid;  
  5.   
  6.     if (!gDvm.zygote) {  
  7.         dvmThrowException("Ljava/lang/IllegalStateException;",  
  8.             "VM instance not started with -Xzygote");  
  9.   
  10.         RETURN_VOID();  
  11.     }  
  12.   
  13.     if (!dvmGcPreZygoteFork()) {  
  14.         LOGE("pre-fork heap failed\n");  
  15.         dvmAbort();  
  16.     }  
  17.   
  18.     setSignalHandler();   //这里注册信号处理,以监测子进程状态  
  19.   
  20.     dvmDumpLoaderStats("zygote");  
  21.     pid = fork();  
  22.   
  23. #ifdef HAVE_ANDROID_OS  
  24.     if (pid == 0) {  
  25.         /* child process */  
  26.         extern int gMallocLeakZygoteChild;  
  27.         gMallocLeakZygoteChild = 1;  
  28.     }  
  29. #endif  
  30.   
  31.     RETURN_INT(pid);  
  32. }  
  33.   
  34. /* 
  35.  * configure sigchld handler for the zygote process 
  36.  * This is configured very late, because earlier in the dalvik lifecycle 
  37.  * we can fork() and exec() for the verifier/optimizer, and we 
  38.  * want to waitpid() for those rather than have them be harvested immediately. 
  39.  * 
  40.  * This ends up being called repeatedly before each fork(), but there's 
  41.  * no real harm in that. 
  42.  */  
  43. static void setSignalHandler()  
  44. {  
  45.     int err;  
  46.     struct sigaction sa;  
  47.   
  48.     memset(&sa, 0, sizeof(sa));  
  49.   
  50.     sa.sa_handler = sigchldHandler;          //信号处理函数地址   
  51.   
  52.     err = sigaction (SIGCHLD, &sa, NULL);    //设置子进程中止时的信号处理函数  
  53.   
  54.     if (err < 0) {  
  55.         LOGW("Error setting SIGCHLD handler: %s", strerror(errno));  
  56.     }  
  57. }  
  58.   
  59. /* 
  60.  * This signal handler is for zygote mode, since the zygote 
  61.  * must reap its children 
  62.  */  
  63. static void sigchldHandler(int s)  
  64. {  
  65.     pid_t pid;  
  66.     int status;  
  67.   
  68.     while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { //得到中止的子进程pid  
  69.         /* Log process-death status that we care about.  In general it is not 
  70.            safe to call LOG(...) from a signal handler because of possible 
  71.            reentrancy.  However, we know a priori that the current implementation 
  72.            of LOG() is safe to call from a SIGCHLD handler in the zygote process. 
  73.            If the LOG() implementation changes its locking strategy or its use 
  74.            of syscalls within the lazy-init critical section, its use here may 
  75.            become unsafe. */  
  76.         if (WIFEXITED(status)) {  
  77.             if (WEXITSTATUS(status)) {  
  78.                 LOG(LOG_DEBUG, ZYGOTE_LOG_TAG, "Process %d exited cleanly (%d)\n",  
  79.                     (int) pid, WEXITSTATUS(status));  
  80.             } else {  
  81.                 IF_LOGV(/*should use ZYGOTE_LOG_TAG*/) {  
  82.                     LOG(LOG_VERBOSE, ZYGOTE_LOG_TAG,  
  83.                         "Process %d exited cleanly (%d)\n",  
  84.                         (int) pid, WEXITSTATUS(status));  
  85.                 }  
  86.             }  
  87.         } else if (WIFSIGNALED(status)) {  
  88.             if (WTERMSIG(status) != SIGKILL) {  
  89.                 LOG(LOG_DEBUG, ZYGOTE_LOG_TAG,  
  90.                     "Process %d terminated by signal (%d)\n",  
  91.                     (int) pid, WTERMSIG(status));  
  92.             } else {  
  93.                 IF_LOGV(/*should use ZYGOTE_LOG_TAG*/) {  
  94.                     LOG(LOG_VERBOSE, ZYGOTE_LOG_TAG,  
  95.                         "Process %d terminated by signal (%d)\n",  
  96.                         (int) pid, WTERMSIG(status));  
  97.                 }  
  98.             }  
  99.         }  
  100.   
  101.         /* 
  102.          * If the just-crashed process is the system_server, bring down zygote 
  103.          * so that it is restarted by init and system server will be restarted 
  104.          * from there. 
  105.          */  
  106.         if (pid == gDvm.systemServerPid) { //仅当中止的子进程为system server时才杀掉本进程(zygote进程)  
  107.             LOG(LOG_INFO, ZYGOTE_LOG_TAG,  
  108.                 "Exit zygote because system server (%d) has terminated\n",  
  109.                 (int) pid);  
  110.             kill(getpid(), SIGKILL); //杀掉Zygote进程,将导致system server被init重启  
  111.         }  
  112.     }  
  113.   
  114.     if (pid < 0) {  
  115.         LOG(LOG_WARN, ZYGOTE_LOG_TAG,  
  116.             "Zygote SIGCHLD error in waitpid: %s\n",strerror(errno));  
  117.     }  
  118. }  


在Zygote被杀掉后,即init.rc中下面的service被杀掉:

  1. service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server   //启动SystemServer    
  2.     class zygote_services    
  3.     socket zygote stream 666    
  4.     onrestart write /sys/android_power/request_state wake    
  5.     onrestart write /sys/power/state on    
  6.     onrestart restart media    
  7.     onrestart restart netd    

init进程启动后将进入无限循环以监听init.rc中启动的service状态,如发现有service退出则会重新启动该service。以下为init进程监听子进程的代码:


system/core/init/init.c

  1. int main(int argc, char **argv)  
  2. {  
  3.     int fd_count = 0;  
  4.     struct pollfd ufds[4];  
  5.     char *tmpdev;  
  6.     char* debuggable;  
  7.     char tmp[32];  
  8.     int property_set_fd_init = 0;  
  9.     int signal_fd_init = 0;  
  10.     int keychord_fd_init = 0;  
  11.     struct rlimit rlim;  
  12.     struct rlimit rlim_new;  
  13.   
  14.     if (!strcmp(basename(argv[0]), "ueventd"))  
  15.         return ueventd_main(argc, argv);  
  16.   
  17.     /* clear the umask */  
  18.     umask(0);  
  19.   
  20.         /* Get the basic filesystem setup we need put 
  21.          * together in the initramdisk on / and then we'll 
  22.          * let the rc file figure out the rest. 
  23.          */  
  24.     mkdir("/dev", 0755);  
  25.     mkdir("/proc", 0755);  
  26.     mkdir("/sys", 0755);  
  27.   
  28.     mount("tmpfs""/dev""tmpfs", 0, "mode=0755");  
  29.     mkdir("/dev/pts", 0755);  
  30.     mkdir("/dev/socket", 0755);  
  31.     mount("devpts""/dev/pts""devpts", 0, NULL);  
  32.     mount("proc""/proc""proc", 0, NULL);  
  33.     mount("sysfs""/sys""sysfs", 0, NULL);  
  34.   
  35.         /* We must have some place other than / to create the 
  36.          * device nodes for kmsg and null, otherwise we won't 
  37.          * be able to remount / read-only later on. 
  38.          * Now that tmpfs is mounted on /dev, we can actually 
  39.          * talk to the outside world. 
  40.          */  
  41.     open_devnull_stdio();  
  42.     log_init();  
  43.       
  44.     init_parse_config_file("/init.rc"); //解析文件 /init.rc  
  45.   
  46.     /* pull the kernel commandline and ramdisk properties file in */  
  47.     import_kernel_cmdline(0);  
  48.   
  49.     get_hardware_name(hardware, &revision);  
  50.     snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware); //解析文件 /init.%hardware%.rc,如:init.goldfish.rc,应该是放硬件相关的内容  
  51.     init_parse_config_file(tmp);  
  52.   
  53.     action_for_each_trigger("early-init", action_add_queue_tail); //action列表中名为early-init的,将此action放在列表尾  
  54.   
  55.     queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done");  
  56.     queue_builtin_action(property_init_action, "property_init");  
  57.     queue_builtin_action(keychord_init_action, "keychord_init");  
  58.     queue_builtin_action(console_init_action, "console_init");  
  59.     queue_builtin_action(set_init_properties_action, "set_init_properties");  
  60.   
  61.     if (getrlimit(RLIMIT_CORE, &rlim)==0) {  
  62.             rlim_new.rlim_cur = rlim_new.rlim_max = RLIM_INFINITY;  
  63.             if (setrlimit(RLIMIT_CORE, &rlim_new)!=0) {  
  64.                  /* failed. try raising just to the old max */  
  65.                  rlim_new.rlim_cur = rlim_new.rlim_max =  rlim.rlim_max;  
  66.                  (void) setrlimit(RLIMIT_CORE, &rlim_new);  
  67.              }  
  68.     }  
  69.         /* execute all the boot actions to get us started */  
  70.     action_for_each_trigger("init", action_add_queue_tail);  
  71.     action_for_each_trigger("early-fs", action_add_queue_tail);  
  72.     action_for_each_trigger("fs", action_add_queue_tail);  
  73.     action_for_each_trigger("post-fs", action_add_queue_tail);  
  74.   
  75.     queue_builtin_action(property_service_init_action, "property_service_init");  
  76.     queue_builtin_action(signal_init_action, "signal_init");  
  77.     queue_builtin_action(check_startup_action, "check_startup");  
  78.   
  79.     /* execute all the boot actions to get us started */  
  80.     action_for_each_trigger("early-boot", action_add_queue_tail);  
  81.     action_for_each_trigger("boot", action_add_queue_tail);  
  82.   
  83.     queue_all_device_triggers();  
  84.     execute_one_command();  
  85.     device_triggers_enabled = 1;  
  86.   
  87.         /* run all property triggers based on current state of the properties */  
  88.     queue_builtin_action(queue_property_triggers_action, "queue_propety_triggers");  
  89.   
  90.   
  91. #if BOOTCHART  
  92.     queue_builtin_action(bootchart_init_action, "bootchart_init");  
  93. #endif  
  94.   
  95.     for(;;) { //无限循环  
  96.         int nr, i, timeout = -1;  
  97.   
  98.         execute_one_command();  
  99.         restart_processes();    //检查有无service需要重新启动  
  100.   
  101.         if (!property_set_fd_init && get_property_set_fd() > 0) {  
  102.             ufds[fd_count].fd = get_property_set_fd();  
  103.             ufds[fd_count].events = POLLIN;  
  104.             ufds[fd_count].revents = 0;  
  105.             fd_count++;  
  106.             property_set_fd_init = 1;  
  107.         }  
  108.         if (!signal_fd_init && get_signal_fd() > 0) {  
  109.             ufds[fd_count].fd = get_signal_fd();  
  110.             ufds[fd_count].events = POLLIN;  
  111.             ufds[fd_count].revents = 0;  
  112.             fd_count++;  
  113.             signal_fd_init = 1;  
  114.         }  
  115.         if (!keychord_fd_init && get_keychord_fd() > 0) {  
  116.             ufds[fd_count].fd = get_keychord_fd();  
  117.             ufds[fd_count].events = POLLIN;  
  118.             ufds[fd_count].revents = 0;  
  119.             fd_count++;  
  120.             keychord_fd_init = 1;  
  121.         }  
  122.   
  123.         if (process_needs_restart) {  
  124.             timeout = (process_needs_restart - gettime()) * 1000;  
  125.             if (timeout < 0)  
  126.                 timeout = 0;  
  127.         }  
  128.   
  129.         if (!action_queue_empty() || cur_action)  
  130.             timeout = 0;  
  131.   
  132. #if BOOTCHART  
  133.         if (bootchart_count > 0) {  
  134.             if (timeout < 0 || timeout > BOOTCHART_POLLING_MS)  
  135.                 timeout = BOOTCHART_POLLING_MS;  
  136.             if (bootchart_step() < 0 || --bootchart_count == 0) {  
  137.                 bootchart_finish();  
  138.                 bootchart_count = 0;  
  139.             }  
  140.         }  
  141. #endif  
  142.   
  143.         nr = poll(ufds, fd_count, timeout);  
  144.         if (nr <= 0)  
  145.             continue;  
  146.   
  147.         for (i = 0; i < fd_count; i++) {  
  148.             if (ufds[i].revents == POLLIN) {  
  149.                 if (ufds[i].fd == get_property_set_fd())  
  150.                     handle_property_set_fd();  
  151.                 else if (ufds[i].fd == get_keychord_fd())  
  152.                     handle_keychord();  
  153.                 else if (ufds[i].fd == get_signal_fd())  
  154.                     handle_signal();               //检查中止的子进程  
  155.             }  
  156.         }  
  157.     }  
  158.   
  159.     return 0;  
  160. }  

子进程退出处理函数

system/core/init/signal_handler.c

  1. void handle_signal(void)  
  2. {  
  3.     char tmp[32];  
  4.   
  5.     /* we got a SIGCHLD - reap and restart as needed */  
  6.     read(signal_recv_fd, tmp, sizeof(tmp));      //为什么读32字节?  
  7.     while (!wait_for_one_process(0)) //处理所有中断的子进程  
  8.         ;  
  9. }  

下面函数得到中止的进程pid并查到对应的Service,然后执行启动该服务前需执行的命令,并置服务标志位的SVC_RESTARTING。在init主函数循环中将根据该标志位启动服务。

  1. static int wait_for_one_process(int block) //block为0  
  2. {  
  3.     pid_t pid;  
  4.     int status;  
  5.     struct service *svc;  
  6.     struct socketinfo *si;  
  7.     time_t now;  
  8.     struct listnode *node;  
  9.     struct command *cmd;  
  10.   
  11.     while ( (pid = waitpid(-1, &status, block ? 0 : WNOHANG)) == -1 && errno == EINTR ); //得到中止的进程pid  
  12.     if (pid <= 0) return -1;      //无效pid,no action  
  13.   
  14.     svc = service_find_by_pid(pid); //查找pid对应service  
  15.     if (!svc) {  
  16.         ERROR("untracked pid %d exited\n", pid);  
  17.         return 0;  
  18.     }  
  19.   
  20.     if (!(svc->flags & SVC_ONESHOT)) { //此Service仅需运行一次  
  21.         kill(-pid, SIGKILL);  
  22.         NOTICE("process '%s' killing any children in process group\n", svc->name);  
  23.     }  
  24.   
  25.     /* remove any sockets we may have created */  
  26.     for (si = svc->sockets; si; si = si->next) { //关闭service中所有socket  
  27.         char tmp[128];  
  28.         snprintf(tmp, sizeof(tmp), ANDROID_SOCKET_DIR"/%s", si->name);  
  29.         unlink(tmp);  
  30.     }  
  31.   
  32.     svc->pid = 0;  
  33.     svc->flags &= (~SVC_RUNNING);  
  34.   
  35.         /* oneshot processes go into the disabled state on exit */  
  36.     if (svc->flags & SVC_ONESHOT) {  
  37.         svc->flags |= SVC_DISABLED;  
  38.     }  
  39.   
  40.         /* disabled processes do not get restarted automatically */  
  41.     if (svc->flags & SVC_DISABLED) {  
  42.         notify_service_state(svc->name, "stopped");  
  43.         return 0;  
  44.     }  
  45.   
  46.     now = gettime();  
  47.     if (svc->flags & SVC_CRITICAL) { //检查关键服务状态  
  48.         if (svc->time_crashed + CRITICAL_CRASH_WINDOW >= now) {  
  49.             if (++svc->nr_crashed > CRITICAL_CRASH_THRESHOLD) {  
  50.                 ERROR("critical process '%s' exited %d times in %d minutes; "  
  51.                       "rebooting into recovery mode\n", svc->name,  
  52.                       CRITICAL_CRASH_THRESHOLD, CRITICAL_CRASH_WINDOW / 60);  
  53.                 sync();  
  54.                 __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,  
  55.                          LINUX_REBOOT_CMD_RESTART2, "recovery");  
  56.                 return 0;  
  57.             }  
  58.         } else {  
  59.             svc->time_crashed = now;  
  60.             svc->nr_crashed = 1;  //为何设为1??  
  61.         }  
  62.     }  
  63.   
  64.     svc->flags |= SVC_RESTARTING;          //置位,以便下次运行restart_processes时启动该服务  
  65.   
  66.     /* Execute all onrestart commands for this service. */  
  67.     list_for_each(node, &svc->onrestart.commands) {     //运行服务启动前应执行的命令  
  68.         cmd = node_to_item(node, struct command, clist);  
  69.         cmd->func(cmd->nargs, cmd->args);  
  70.     }  
  71.     notify_service_state(svc->name, "restarting");  //更新此服务状态属性值为restarting  
  72.     return 0;  
  73. }  


system/core/init/init.c

  1. static void restart_processes()  
  2. {  
  3.     process_needs_restart = 0;  
  4.     service_for_each_flags(SVC_RESTARTING,  
  5.                            restart_service_if_needed);  
  6. }  
  7.   
  8. void service_for_each_flags(unsigned matchflags,  
  9.                             void (*func)(struct service *svc))  
  10. {  
  11.     struct listnode *node;  
  12.     struct service *svc;  
  13.     list_for_each(node, &service_list) {  
  14.         svc = node_to_item(node, struct service, slist);  
  15.         if (svc->flags & matchflags) {      //如果某个service的标志位SVC_RESTARTING置位  
  16.             func(svc);             //执行函数restart_service_if_needed以启动service  
  17.         }  
  18.     }  
  19. }   

启动service svc

  1. static void restart_service_if_needed(struct service *svc)  
  2. {  
  3.     time_t next_start_time = svc->time_started + 5;     //service上次启动的时间增加5秒  
  4.   
  5.     if (next_start_time <= gettime()) { //如果Service上次启动时间距今大于5秒  
  6.         svc->flags &= (~SVC_RESTARTING);  
  7.         service_start(svc, NULL);         //重新启动该service  
  8.         return;  
  9.     }...  
  10. }  



另外,system server进程会监听service manager进程状态。一旦service manager进程退出,system server进程会自动退出:

system_init.cpp


  1. class GrimReaper : public IBinder::DeathRecipient {  
  2. public:   
  3.     GrimReaper() { }  
  4.   
  5.     virtual void binderDied(const wp<IBinder>& who)  
  6.     {  
  7.         kill(getpid(), SIGKILL);     //杀掉自身进程  
  8.     }  
  9. };  
  10.   
  11. // namespace android  

  1. extern "C" status_t system_init()  
  2. {...      
  3.     sp<IServiceManager> sm = defaultServiceManager();      
  4.       
  5.     sp<GrimReaper> grim = new GrimReaper();  
  6.     sm->asBinder()->linkToDeath(grim, grim.get(), 0);  //监听ServiceManager binder对象  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值