内核启动第一个程序

转自:http://blog.csdn.net/lwbeyond/article/details/8444535

从kernel_init()函数我们知道,init_post是最后执行的一个函数,我们来分析这个函数:

[cpp]  view plain  copy
  1. static int noinline init_post(void)  
  2. {  
  3.     free_initmem();  
  4.     unlock_kernel();  
  5.     mark_rodata_ro();  
  6.     system_state = SYSTEM_RUNNING;  
  7.     numa_default_policy();  
  8.   
  9.     /* 首先打开终端设备 */  
  10.     if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)  
  11.         printk(KERN_WARNING "Warning: unable to open an initial console.\n");  
  12.   
  13.     /* 然后复制两个,共三个,分别是stdin,stdout,stderr */  
  14.     (void) sys_dup(0);  
  15.     (void) sys_dup(0);  
  16.   
  17.     if (ramdisk_execute_command) {  
  18.         run_init_process(ramdisk_execute_command);  
  19.         printk(KERN_WARNING "Failed to execute %s\n",  
  20.                 ramdisk_execute_command);  
  21.     }  
  22.   
  23.     /* 
  24.      * We try each of these until one succeeds. 
  25.      * 
  26.      * The Bourne shell can be used instead of init if we are 
  27.      * trying to recover a really broken machine. 
  28.      */  
  29.   
  30.     /* 执行命令行传入的int=xxxx程序, 
  31.        如果没有就接着向下执行,如果成功则会一直运行不会向下执行。 
  32.      */  
  33.     if (execute_command) {  
  34.         run_init_process(execute_command);  
  35.         printk(KERN_WARNING "Failed to execute %s.  Attempting "  
  36.                     "defaults...\n", execute_command);  
  37.     }  
  38.       
  39.     /* 如果上面没有成功,则向下执行 */  
  40.     run_init_process("/sbin/init");  
  41.     run_init_process("/etc/init");  
  42.     run_init_process("/bin/init");  
  43.     run_init_process("/bin/sh");  
  44.   
  45.     panic("No init found.  Try passing init= option to kernel.");  
  46. }  
从上面可以看出如果执行命令里没有 init=xxx 的参数,那么就会依次向下执行

[cpp]  view plain  copy
  1. run_init_process("/sbin/init");  
  2. ......  

因为我们的执行命令里没有init=xxx参数,所以 init 就是我们的第一个进程

但是如果我们执行下面的命令:

[cpp]  view plain  copy
  1. ls -l /sbin/init  
  2. lrwxrwxrwx    1 messageb messageb       14 Dec 21  2012 /sbin/init -> ../bin/busybox  

我们发现第一个程序是链接到busybox的,也就是说启动是busybox程序,所以我们要分析busybox源码里的init.c源码。

打开 busybox 源码中的 init.c文件,分析int.c 是怎么解析 /etc/inittab 文件以及执行程序的:

[cpp]  view plain  copy
  1. init_main  
  2.     parse_inittab  
  3.         file = fopen(INITTAB, "r");  //打开配置文件  
  4.         new_init_action              //创建init_action结构,并加入init_action_list链表  
  5.           
  6.     run_actions(SYSINIT);      
  7.         waitfor(a, 0);               //执行应用程序,等待它执行完毕  
  8.                 run(a);              //创建process子进程  
  9.                 waitpid              //等待它结束  
  10.         delete_init_action(a);       //从init_action_list链表中删掉  
  11.                           
  12.     run_actions(WAIT);  
  13.         waitfor(a, 0);               //执行应用程序,等待它执行完毕  
  14.                 run(a);              //创建process子进程  
  15.                 waitpid              //等待它结束  
  16.         delete_init_action(a);       //从init_action_list链表中删掉  
  17.                       
  18.     run_actions(ONCE);  
  19.         run(a);                      //不等待了,运行完后直接结束  
  20.         delete_init_action(a);  
  21.                       
  22.     while (1) {  
  23.         run_actions(RESPAWN);  
  24.                 if (a->pid == 0) {  
  25.                     a->pid = run(a);  
  26.                 }  
  27.                       
  28.         run_actions(ASKFIRST);  
  29.                 if (a->pid == 0) {  
  30.                     a->pid = run(a);  
  31.                                         打印: "\nPlease press Enter to activate this console. ";  
  32.                                         等待回车  
  33.                 }  
  34.                       
  35.         wpid = wait(NULL);           //等待子进程退出  
  36.         while (wpid > 0) {  
  37.                 a->pid = 0;  
  38.         }  
  39.     }  

当然在busybox/example下,我们可以查到 inittab的格式说明:

[cpp]  view plain  copy
  1. # Format for each entry: <id>:<runlevels>:<action>:<process>  
id --> /dev/it  用于终端:stdin, stdout,stderr
runlevels       : 忽略
action             :执行时机
process         : 应用程序或脚本

这样第一个进程 init 就运行起来了

转载于:https://www.cnblogs.com/alan666/p/8312069.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值