在我的mini2440开发板,文件系统是直接使用的其他人的。关于文件系统的启动,我在这里简单的先分析。
从网络上可以下载sdk,从sdk里面来分析,init进程的启动过程。
在Android系统启动时,内核引导参数上一般都会设置“init=/init”, 这样的话,如果内核成功挂载了这个文件系统之后,首先运行的就是这个根目录下的init程序。
[root@liyi init]# pwd
/home/liyi/mydroid/system/core/init
在init.c文件中直接查找main函数:
(1)安装SIGCHLD信号。
803 act.sa_handler = sigchld_handler;
804 act.sa_flags = SA_NOCLDSTOP;
805 act.sa_mask = 0;
806 act.sa_restorer = NULL;
807 sigaction(SIGCHLD, &act, 0);
(如果父进程不等待子进程结束,子进程将成为僵尸进程(zombie)从而占用系统资源。因此需要对SIGCHLD信号做出处理,回收僵尸进程的资源,避免造成不必要的资源浪费。)
(2)对umask进行清零。
810 umask(0);
当我们登录系统之后创建一个文件总是有一个默认权限的,那么这个权限是怎么来的呢?这就是umask干的事情。
设置为0之后,创建的文件具有666的权限,目录具有777的权限
(3)为rootfs建立必要的文件夹,并挂载适当的分区。
816 mkdir("/dev", 0755);
817 mkdir("/proc", 0755);
818 mkdir("/sys", 0755);
819
820 mount("tmpfs", "/dev", "tmpfs", 0, "mode=0755");
821 mkdir("/dev/pts", 0755);
822 mkdir("/dev/socket", 0755);
823 mount("devpts", "/dev/pts", "devpts", 0, NULL);
824 mount("proc", "/proc", "proc", 0, NULL);
825 mount("sysfs", "/sys", "sysfs", 0, NULL);
/dev (tmpfs)
/dev/pts (devpts)
/dev/socket
/proc (proc)
/sys (sysfs)
(4)创建/dev/null和/dev/kmsg节点,以及文件描述符号。
833 open_devnull_stdio();
834 log_init();
(5)解析/init.rc,将所有服务和操作信息加入链表。
837 parse_config_file("/init.rc");
(6)从/proc/cmdline中提取信息内核启动参数,并保存到全局变量。
import_kernel_cmdline(0);
根据设置,将cmdline保存到下面的变量中
55 static char console[32];
56 static char serialno[32];
57 static char bootmode[32];
58 static char baseband[32];
59 static char carrier[32];
60 static char bootloader[32];
61 static char hardware[32];
(7)先从上一步获得的全局变量中获取信息硬件信息和版本号,如果没有则从/proc/cpuinfo中提取,并保存到全局变量。
43 get_hardware_name();
把硬件名称意见版本号保存起来。
61 static char hardware[32];
62 static unsigned revision = 0;
(8)根据硬件信息选择一个/init.(硬件).rc,并解析,将服务和操作信息加入链表。
844 snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware);
845 parse_config_file(tmp);
在ramdisk根目录下有一个/init.(硬件).rc:init.goldfish.rc init程序会根据上一步获得的硬件信息是否解析该文件。
(9)执行链表中带有“early-init”触发的的命令。
847 action_for_each_trigger("early-init", action_add_queue_tail);
848 drain_action_queue();
(10)遍历/sys文件夹,是内核产生设备添加事件(为了自动产生设备节点)。
851 device_fd = device_init();
638 int device_init(void)
639 {
640 suseconds_t t0, t1;
641 int fd;
642
643 fd = open_uevent_socket();
644 if(fd < 0)
645 return -1;
646
647 fcntl(fd, F_SETFD, FD_CLOEXEC);
648 fcntl(fd, F_SETFL, O_NONBLOCK);
649
650 t0 = get_usecs();
651 coldboot(fd, "/sys/class");
652 coldboot(fd, "/sys/block");
653 coldboot(fd, "/sys/devices");
654 t1 = get_usecs();
655
656 log_event_print("coldboot %ld uS/n", ((long) (t1 - t0)));
657
658 return fd;
(11)初始化属性系统,并导入初始化属性文件。
853 property_init();
(12)从属性系统中得到ro.debuggable,若为1,则初始化keychord监听。
855 // only listen for keychords if ro.debuggable is true
856 debuggable = property_get("ro.debuggable");
857 if (debuggable && !strcmp(debuggable, "1")) {
858 keychord_fd = open_keychord();
859 }
(13)打开console,如果cmdline中沒有指定console则打开的/dev/console
861 if (console[0]) {
862 snprintf(tmp, sizeof(tmp), "/dev/%s", console);
863 console_name = strdup(tmp);
864 }
865
866 fd = open(console_name, O_RDWR);
867 if (fd >= 0)
868 have_console = 1;
869 close(fd);
(14)读取/initlogo.rle(一张565 rle 压缩位图),如果成功则在/dev/graphics/fb0显示Logo,如果失败则/dev/tty0设置TEXT模式并打开/dev/tty0,输出文本“ANDROID”字。
871 if( load_565rle_image(INIT_IMAGE_FILE) ) {
872 fd = open("/dev/tty0", O_WRONLY);
873 if (fd >= 0) {
874 const char *msg;
875 msg = "/n"
876 "/n"
877 "/n"
878 "/n"
879 "/n"
880 "/n"
881 "/n" // console is 40 cols x 30 lines
882 "/n"
883 "/n"
884 "/n"
885 "/n"
886 "/n"
887 "/n"
888 "/n"
889 " A N D R O I D ";
890 write(fd, msg, strlen(msg));
891 close(fd);
892 }
893 }
(15)判断cmdline 中的参数,并设置属性系统中的参数:
1、 如果 bootmode为
- factory,设置ro.factorytest值为1
- factory2,设置ro.factorytest值为2
- 其他的设置ro.factorytest值为0
2、如果有serialno参数,设置ro.serialno,不然为""
3、如果有bootmod参数,设置ro.bootmod,不然为"unknown"
4、如果有baseband参数,设置ro.baseband,不然为"unknown"
5、如果有carrier参数,设置ro.carrier,不然为"unknown"
6、如果有bootloader参数,则设置ro.bootloader,不然为"unknown"
7、通过全局变量(前面从/proc/cpuinfo中提取的)设置ro.hardware和ro.version。
898 if (!strcmp(bootmode,"factory"))
899 property_set("ro.factorytest", "1");
900 else if (!strcmp(bootmode,"factory2"))
901 property_set("ro.factorytest", "2");
902 else
903 property_set("ro.factorytest", "0");
904
905 property_set("ro.serialno", serialno[0] ? serialno : "");
906 property_set("ro.bootmode", bootmode[0] ? bootmode : "unknown");
907 property_set("ro.baseband", baseband[0] ? baseband : "unknown");
908 property_set("ro.carrier", carrier[0] ? carrier : "unknown");
909 property_set("ro.bootloader", bootloader[0] ? bootloader : "unknown");
910
911 property_set("ro.hardware", hardware);
912 snprintf(tmp, PROP_VALUE_MAX, "%d", revision);
913 property_set("ro.revision", tmp);
(16)运行所有触发标识为init的action。
915 /* execute all the boot actions to get us started */
916 action_for_each_trigger("init", action_add_queue_tail);
917 drain_action_queue();
(17)开始运行prooerty服务
919 /* read any property files on system or data and
920 * fire up the property service. This must happen
921 * after the ro.foo properties are set above so
922 * that /data/local.prop cannot interfere with them.
923 */
924 property_set_fd = start_property_service();
(18) create a signalling mechanism for the sigchld handler
926 /* create a signalling mechanism for the sigchld handler */
927 if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) == 0) {
928 signal_fd = s[0];
929 signal_recv_fd = s[1];
930 fcntl(s[0], F_SETFD, FD_CLOEXEC);
931 fcntl(s[0], F_SETFL, O_NONBLOCK);
932 fcntl(s[1], F_SETFD, FD_CLOEXEC);
933 fcntl(s[1], F_SETFL, O_NONBLOCK);
934 }
(19)make sure we actually have all the pieces we need :
936 /* make sure we actually have all the pieces we need */
937 if ((device_fd < 0) ||
938 (property_set_fd < 0) ||
939 (signal_recv_fd < 0)) {
940 ERROR("init startup failure/n");
941 return 1;
942 } device_fd(device init 完成)
(20) execute all the boot actions to get us started
944 /* execute all the boot actions to get us started */
945 action_for_each_trigger("early-boot", action_add_queue_tail);
946 action_for_each_trigger("boot", action_add_queue_tail);
947 drain_action_queue();
(21)run all property triggers based on current state of the properties
949 /* run all property triggers based on current state of the properties */
950 queue_all_property_triggers();
951 drain_action_queue();
(22)enable property triggers:
953 /* enable property triggers */
954 property_triggers_enabled = 1;
955
956 ufds[0].fd = device_fd;
957 ufds[0].events = POLLIN;
958 ufds[1].fd = property_set_fd;
959 ufds[1].events = POLLIN;
960 ufds[2].fd = signal_recv_fd;
961 ufds[2].events = POLLIN;
962 fd_count = 3;
963
964 if (keychord_fd > 0) {
965 ufds[3].fd = keychord_fd;
966 ufds[3].events = POLLIN;
967 fd_count++;
968 } else {
969 ufds[3].events = 0;
970 ufds[3].revents = 0;
971 }
(23)如果支持BOOTCHART
973 #if BOOTCHART
974 bootchart_count = bootchart_init();
975 if (bootchart_count < 0) {
976 ERROR("bootcharting init failure/n");
977 } else if (bootchart_count > 0) {
978 NOTICE("bootcharting started (period=%d ms)/n", bootchart_count*BOOTCHART_POLLING_MS);
979 } else {
980 NOTICE("bootcharting ignored/n");
981 }
982 #endif
(24)进入init的循环:
984 for(;;) {
985 int nr, i, timeout = -1;
986
987 for (i = 0; i < fd_count; i++)
988 ufds[i].revents = 0;
989
990 drain_action_queue();
991 restart_processes();
992
993 if (process_needs_restart) {
994 timeout = (process_needs_restart - gettime()) * 1000;
995 if (timeout < 0)
996 timeout = 0;
997 }
998
999 #if BOOTCHART
1000 if (bootchart_count > 0) {
1001 if (timeout < 0 || timeout > BOOTCHART_POLLING_MS)
1002 timeout = BOOTCHART_POLLING_MS;
1003 if (bootchart_step() < 0 || --bootchart_count == 0) {
1004 bootchart_finish();
1005 bootchart_count = 0;
1006 }
1007 }
1008 #endif
1009 nr = poll(ufds, fd_count, timeout);
1010 if (nr <= 0)
1011 continue;
1012
1013 if (ufds[2].revents == POLLIN) {
1014 /* we got a SIGCHLD - reap and restart as needed */
1015 read(signal_recv_fd, tmp, sizeof(tmp));
1016 while (!wait_for_one_process(0))
1017 ;
1018 continue;
1019 }
1020
1021 if (ufds[0].revents == POLLIN)
1022 handle_device_fd(device_fd);
1023
1024 if (ufds[1].revents == POLLIN)
1025 handle_property_set_fd(property_set_fd);
1026 if (ufds[3].revents == POLLIN)
1027 handle_keychord(keychord_fd);
1028 }