zoukankan      html  css  js  c++  java
  • 内核启动第一个程序

    转自: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. ");  
    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 ",  
    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... ", 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.                                         打印: " Please 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 就运行起来了

  • 相关阅读:
    进程之管道Pipe,数据共享Manager,进程池Poo
    进程之锁,信息量,事件,队列,生产者消费者模型,joinablequeue
    网络编程之sock server,自定义一个与sock server类相似的功能,支持多客户端通信
    网络编程之粘包解决方案
    进程之进程创建的两种方式,两种传值的方式,验证进程间数据隔离,join,守护进程,僵尸进程,孤儿进程
    毕业设计开题报告任务书参考文献格式和数量要求
    剑指offer-替换空格
    剑指offer-二维数组中的查找
    用forward和sendRedirect转发时的区别
    ServletContext实现显示用户在线人数
  • 原文地址:https://www.cnblogs.com/alan666/p/8312069.html
Copyright © 2011-2022 走看看