重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
Android Init进程对信号的处理流程
创新互联是一家专注于成都网站建设、网站制作与策划设计,新余网站建设哪家好?创新互联做网站,专注于网站建设十年,网设计领域的专业建站公司;建站业务涵盖:新余等地区。新余做网站价格咨询:028-86922220在Android中,当一个进程退出(exit())时,会向它的父进程发送一个SIGCHLD信号。父进程收到该信号后,会释放分配给该子进程的系统资源;并且父进程需要调用wait()或waitpid()等待子进程结束。如果父进程没有做这种处理,且父进程初始化时也没有调用signal(SIGCHLD, SIG_IGN)来显示忽略对SIGCHLD的处理,这时子进程将一直保持当前的退出状态,不会完全退出。这样的子进程不能被调度,所做的只是在进程列表中占据一个位置,保存了该进程的PID、终止状态、CPU使用时间等信息;我们将这种进程称为“Zombie”进程,即僵尸进程。
在Linux中,设置僵尸进程的目的是维护子进程的一些信息,以供父进程后续查询获取。特殊的,如果一个父进程终止,那么它的所有僵尸子进程的父进程将被设置为Init进程(PID为1),并由Init进程负责回收这些僵尸进程(Init进程将wait()/waitpid()它们,并清除它们在进程列表中的信息)。
由于僵尸进程仍会在进程列表中占据一个位置,而Linux所支持的大进程数量是有限的;超过这个界限值后,我们就无法创建进程。所以,我们有必要清理那些僵尸进程,以保证系统的正常运作。
接下来,我们分析下Init进程是如何处理SIGCHLD信号的。
在Init.cpp中,我们是通过signal_handler_init()来初始化SIGCHLD信号处理的:
void signal_handler_init() { // Create a signalling mechanism for SIGCHLD. int s[2]; //socketpair()创造一对未命名的、相互连接的UNIX域套接字 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0, s) == -1) { ERROR("socketpair failed: %s\n", strerror(errno)); exit(1); } signal_write_fd = s[0]; signal_read_fd = s[1]; // Write to signal_write_fd if we catch SIGCHLD. struct sigaction act; memset(&act, 0, sizeof(act)); act.sa_handler = SIGCHLD_handler;//设置信号处理函数句柄,当有信号产生时,会向上面创建的socket写入数据,epoll监控到该socket对中的fd可读时,就会调用注册的函数去处理该事件 act.sa_flags = SA_NOCLDSTOP;//设置标志,表示只有当子进程终止时才接受SIGCHID信号 sigaction(SIGCHLD, &act, 0);//初始化SIGCHLD信号处理方式 reap_any_outstanding_children();//处理这之前退出的子进程 register_epoll_handler(signal_read_fd, handle_signal); }