Android学习笔记9

在我的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     }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值