鸟人的Android揭秘(13)——Init进程源代码分析(四)
来源:互联网 发布:充电桩软件 编辑:程序博客网 时间:2024/05/18 01:29
Android系统的文件节点都使用SELinux管理权限,前面介绍的init进程第一阶段初始化创建的文件节点,以及属性初始化过程创建的文件节点,是在加载sepolicy之前已经被创建了,在加载完sepolicy之后,需要重新设置相关的属性。代码3-13所示是根据file_contexts[1]文件的内容设置相应文件节点的上下文。
restorecon("/dev");restorecon("/dev/socket");restorecon("/dev/__properties__");restorecon("/property_contexts");restorecon_recursive("/sys");
代码 3-13 main()-设置SELinux访问权限
接下来创建套接字,以便init进程在收到子进程终止的SIGCHLD信号时调用相应的handler。
epoll_fd = epoll_create1(EPOLL_CLOEXEC);if (epoll_fd == -1) { ERROR("epoll_create1 failed: %s\n", strerror(errno)); exit(1);}signal_handler_init();
代码 3-14 main()-创建epoll和套接字
代码3-14中,首先调用epoll_create1()函数创建epoll的句柄,通知内核开始监听文件描述符(file description,fd)。epoll_create1()函数创建成功时也会占用一个文件描述符,EPOLL_CLOEXE参数的作用是通知内核在使用完该文件描述符后需要关闭,以免文件描述符资源耗尽,紧接着调用signal_handler_init()函数创建套接字,安装信号处理器,并将套接字描述符注册到epoll中,如代码3-15所示。
void signal_handler_init() { // Create a signalling mechanism for SIGCHLD. int s[2]; if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0, s) == -1) { (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; act.sa_flags = SA_NOCLDSTOP; sigaction(SIGCHLD, &act, 0); (2) register_epoll_handler(signal_read_fd, handle_signal); (3)}
代码 3-15 创建套接字,监听SIGCHLD事件
(1)调用socketpair()函数创建一对已经连接的非阻塞套接字,套接字描述符存储在二元数组s[2]中。这对套接字可以进行双工通信,每一个描述符既可以读也可以写。init进程使用s[0]作为输入端,s[1]作为输出端。
(2)安装子进程信号处理器。Linux进程通过互相发送/接收消息来实现进程间的通信,这些消息被称为“信号”。每个进程在处理其它进程发送的信号时,都要注册信号处理器。当进程的运行状态改变或终止时,就会产生某种信号,init进程是所有进程的父进程,当其子进程终止产生SIGCHLD信号时,init进程需要调用信号安装函数sigaction()并通过参数传递sigaction结构体配置,完成信号处理器的安装。此处sigaction结构体的sa_flags设置为SA_NOCLDSTOP,表示仅当进程终止时才接收SIGCHLD信号。当发生SIGCHLD信号时,调用此处的handler,即SIGCHLD_handler,实质是对套拼字signal_write_fd(s[0])执行写操作。
(3)将signal_read_fd(s[1])描述符和相应的handler注册到epoll中,当SIGCHLD信号产生时,signal_write_fd会被写入1,由于socketpair的绑定关系,这将触发信号对应的signal_read_fd收到数据,epoll监听到变化,调用此处注册的handler处理子进程的终止。
上述init进程调用signal_handler_init()函数后的处理过程可以用图3-7总结,即一旦收到子进程终止触发的SIGCHLD信号后,将利用信号处理器SIGCHLD_handler向signal_write_fd写入信息,epoll句柄监听到signal_read_fd接收到信息,将调用handle_signal处理。关于子进程处理的更详细内容,我们将在后面“进程的终止和重启”章节中进得讲解。
图 3-7 main()-signal_handler_init()函数处理子进程终止的过程
前面我们已经讲解了init进程如何初始化属性,在Android系统中,对属性的修改只能在init进程中进行,其它进程对属性只有读的权限,必须通过向init进程发送修改请求,由init接收请求后进行处理,接下来将进一步讲解这方面的内容。
[1] file_contexts的内容参考system/sepolicy/file_contexts。
- 鸟人的Android揭秘(13)——Init进程源代码分析(四)
- 鸟人的Android揭秘(10)——Init进程源代码分析(一)
- 鸟人的Android揭秘(11)——Init进程源代码分析(二)
- 鸟人的Android揭秘(12)——Init进程源代码分析(三)
- 鸟人的Android揭秘(14)——Init进程源代码分析(五)
- 鸟人的Android揭秘(9)——Init进程运行过程
- 鸟人的Android揭秘(4)——Android 源代码编译
- 鸟人的Android揭秘(1)——源代码构成
- 鸟人的Android揭秘(8)——搭建Android SDK开发环境(四)
- 鸟人的Android揭秘(2)——通过启动过程分析 Android Framework
- 鸟人的Android揭秘(3)——Android 编译环境搭建
- 鸟人的Android揭秘(5)——搭建Android SDK开发环境(一)
- 鸟人的Android揭秘(6)——搭建Android SDK开发环境(二)
- 鸟人的Android揭秘(7)——搭建Android SDK开发环境(三)
- Android init进程——源码分析
- Android启动流程分析(四) init进程分析
- android init 进程分析
- Android init进程分析
- GetLastError() 显示错误信息
- sklearn——朴素贝叶斯文本分类3
- javaScript中的this关键字
- python—pandas中DataFrame类型数据操作函数
- 批处理操作
- 鸟人的Android揭秘(13)——Init进程源代码分析(四)
- JFinal对日志管理的支持
- 为u-boot-2016 for tiny4412添加点灯调试代码
- 推荐系统评价
- HDU 2098 不同素数对
- the first day in CSDN
- POJ2184:Cow Exhibition(类01背包)
- CON1412 期末考后的休闲比赛[六花的勇者]
- 小白 android广播 小结