Android1.6 启动init.c分析
来源:互联网 发布:mac系统优化工具 编辑:程序博客网 时间:2024/06/06 01:06
android的启动大致分为6步
第一步:上电后boot启动
第二步:boot启动内核
第三部:内核运行根目录下的init,加载init.rc
第四部:init 启动启动各个service 包括servicemanager,vold,mount等,然后启动papp_process -Xzygote 启动java虚拟机。
第五步:zygote启动SystemServer,然后由SystemServer启动各个管理器。
第六步:启动完成,进入桌面。
第一步和第二步不再分析。
我们主要从第三步init开始分析。
init主要完成6件事。
第一.创建文件系统,挂载各个系统目录。
第二.加载init.rc,解析,运行。
第三.创建一个socket 用于僵死的子进程回收。
第四.创建系统属性读取写入的socket。
第五.创建uevent socket,用于监视uevent。
第六.无限循环处理僵死进程回收,属性处理,uevent监控等。
我们逐个分析:
第一.创建文件系统如下:
mkdir("/dev", 0755); mkdir("/proc", 0755); mkdir("/sys", 0755); mount("tmpfs", "/dev", "tmpfs", 0, "mode=0755"); mkdir("/dev/pts", 0755); mkdir("/dev/socket", 0755); mount("devpts", "/dev/pts", "devpts", 0, NULL); mount("proc", "/proc", "proc", 0, NULL); mount("sysfs", "/sys", "sysfs", 0, NULL);
这部分最简单,相信大家都很熟悉。
第二.init.rc
引用块内容
第三.创建僵死进程回收处理
1.设置子进程僵死时的处理
act.sa_handler = sigchld_handler; act.sa_flags = SA_NOCLDSTOP; act.sa_mask = 0; act.sa_restorer = NULL; sigaction(SIGCHLD, &act, 0);
第一句是子进程僵死时的处理函数
static int signal_fd = -1;static void sigchld_handler(int s){ write(signal_fd, &s, 1);}
没头没脑的一个傻逼函数,刚看到时只能说一句,谁知道你在干嘛?
但当你到到2 和3的时候我想我们大家都懂得了。
第二句话的意思就是
SA_NOCLDSTOP
这个flag只对SIGCHLD信号有效,当这个flag设置的时候,系统会给终止的子进程发送一个信号,但是不会给已经停止的子进程发送信号。默认情况下,系统会向终止的子进程和停止的子进程都发送SIGCHLD信号。
其实也就是说当子进程僵死时sigchld_handler函数会被调用。
2.创建一个匿名通信管道,从signal_fd写入的数据可以在signal_recv_fd读取出来。
/* create a signalling mechanism for the sigchld handler */ if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) == 0) { signal_fd = s[0]; signal_recv_fd = s[1]; fcntl(s[0], F_SETFD, FD_CLOEXEC);//当创建进程关闭描述符时其他进程还可以使用 fcntl(s[0], F_SETFL, O_NONBLOCK);//不阻塞 fcntl(s[1], F_SETFD, FD_CLOEXEC); fcntl(s[1], F_SETFL, O_NONBLOCK); }
上面这些与第三点结合起来,我想你讲完全看懂。因为signal_recv_fd会在第3里面出现。也就是init的死循环里面。
3.监视signal_recv_fd,当进程僵死时在这里处理。
ufds[2].fd = signal_recv_fd;ufds[2].events = POLLIN;for(;;) { ..... nr = poll(ufds, fd_count, timeout); if (ufds[2].revents == POLLIN) { /* we got a SIGCHLD - reap and restart as needed */ read(signal_recv_fd, tmp, sizeof(tmp)); while (!wait_for_one_process(0)) ; continue; } ..... }
第四,属性处理
....property_init();//属性初始化....property_set_fd = start_property_service();//创建用于设置属性的socket进程间通讯....ufds[0].events = POLLIN;ufds[1].fd = property_set_fd;....for(;;) { int nr, i, timeout = -1; nr = poll(ufds, fd_count, timeout); if (ufds[1].revents == POLLIN) handle_property_set_fd(property_set_fd);//属性处理 ....}
property_init();属性处理我们暂不分析,我们主要分析start_property_service()和handle_property_set_fd(property_set_fd)函数。
#define PROP_PATH_RAMDISK_DEFAULT "/default.prop"#define PROP_PATH_SYSTEM_BUILD "/system/build.prop"#define PROP_PATH_SYSTEM_DEFAULT "/system/default.prop"#define PROP_PATH_LOCAL_OVERRIDE "/data/local.prop"int start_property_service(void){ int fd; load_properties_from_file(PROP_PATH_SYSTEM_BUILD);//加载属性文件 load_properties_from_file(PROP_PATH_SYSTEM_DEFAULT); load_properties_from_file(PROP_PATH_LOCAL_OVERRIDE); /* Read persistent properties after all default values have been loaded. */ load_persistent_properties(); fd = create_socket(PROP_SERVICE_NAME, SOCK_STREAM, 0666, 0, 0);//创建socket if(fd < 0) return -1; fcntl(fd, F_SETFD, FD_CLOEXEC);//这个大家都懂得了 fcntl(fd, F_SETFL, O_NONBLOCK); listen(fd, 8);//监听,最多8个线程同时读取 return fd;}
其实大多的处理都在create_socket函数里面,下面我们来看看
int create_socket(const char *name, int type, mode_t perm, uid_t uid, gid_t gid){ struct sockaddr_un addr; int fd, ret; fd = socket(PF_UNIX, type, 0);//PF_UNIX 协议主要用于进程间通讯 if (fd < 0) { ERROR("Failed to open socket '%s': %s\n", name, strerror(errno)); return -1; } memset(&addr, 0 , sizeof(addr)); addr.sun_family = AF_UNIX; snprintf(addr.sun_path, sizeof(addr.sun_path), ANDROID_SOCKET_DIR"/%s", name);//路径:/dev/socket/name ret = unlink(addr.sun_path); if (ret != 0 && errno != ENOENT) { ERROR("Failed to unlink old socket '%s': %s\n", name, strerror(errno)); goto out_close; } ret = bind(fd, (struct sockaddr *) &addr, sizeof (addr)); if (ret) { ERROR("Failed to bind socket '%s': %s\n", name, strerror(errno)); goto out_unlink; } chown(addr.sun_path, uid, gid); chmod(addr.sun_path, perm); INFO("Created socket '%s' with mode '%o', user '%d', group '%d'\n", addr.sun_path, perm, uid, gid); return fd;out_unlink: unlink(addr.sun_path);out_close: close(fd); return -1;}
create_socket函数建立了一个进程间IPC通讯的socket service,并且启动监听,非阻塞方式。
然后到了for循环的时候,一直在循环处理poll,如果有客户,那么handle_property_set_fd函数会被调用。
- Android1.6 启动init.c分析
- Android 启动分析 --- init.c (system/core/init/init.c)
- ARM启动代码分析(2440init.c)
- android启动过程中init.c文件分析
- android启动过程中init.c文件分析
- android启动代码init.c文件分析(一)
- android启动代码init.c文件分析(二)
- android启动代码init.c文件分析(三)
- android启动代码init.c文件分析(四)
- Android启动之init.c文件main函数分析
- Android-4.0.3-init.c启动源码分析
- Android启动过程分析——init.c(一)
- Android启动过程分析——init.c(二)
- Android启动init.c
- Android 启动分析 init进程 init.rc
- android init.c分析
- Android init 启动过程分析
- Android init 启动过程分析
- PXE+kickstart 无人值守批量装机(ftp推送方式)
- Leetcode 160. Intersection of Two Linked Lists
- 菜鸟第一篇文章,用于自勉。
- DX名词解释:深度缓存(depth buffer)
- 策略模式
- Android1.6 启动init.c分析
- 冒泡,插入,选择,归并,快速排序的C++实现
- jQuery 事件机制源代码分析1——jQuery事件机制整体架构
- css
- C语言内存分配问题和C语言中的内存
- Linux驱动开发、19-I2C子系统之客户驱动分析与移植
- ubutu安装配置jdk1.8
- 第十四周项目60-两个成员的类模版
- Card2D