4.2.4 init_post函数

来源:互联网 发布:关于淘宝店 编辑:程序博客网 时间:2024/06/09 14:21

4.2.4  init_post函数

到init_post函数为止,内核的初始化已经进入尾声,第一个用户空间进程init将姗姗来迟。

代码清单4.4  init_post函数

  1. 774 static int noinline init_post(void)  
  2. 775 {  
  3. 776     free_initmem();  
  4. 777     unlock_kernel();  
  5. 778     mark_rodata_ro();  
  6. 779     system_state = SYSTEM_RUNNING;  
  7. 780     numa_default_policy();  
  8. 781   
  9. 782     if (sys_open((const char __user *) "/dev/
    console", O_RDWR, 0) 
    < 0)  
  10. 783         printk(KERN_WARNING "Warning: unable 
    to open an initial console.\n");  
  11. 784   
  12. 785     (void) sys_dup(0);  
  13. 786     (void) sys_dup(0);  
  14. 787   
  15. 788     if (ramdisk_execute_command) {  
  16. 789         run_init_process(ramdisk_execute_command);  
  17. 790         printk(KERN_WARNING "Failed to execute %s\n",  
  18. 791                 ramdisk_execute_command);  
  19. 792     }  
  20. 793   
  21. 794     /*  
  22. 795      * We try each of these until one succeeds.  
  23. 796      *  
  24. 797      * The Bourne shell can be used instead of init if we are  
  25. 798      * trying to recover a really broken machine.  
  26. 799      */  
  27. 800     if (execute_command) {  
  28. 801         run_init_process(execute_command);  
  29. 802         printk(KERN_WARNING "Failed to execute %s.  Attempting "  
  30. 803                     "defaults...\n", execute_command);  
  31. 804     }  
  32. 805     run_init_process("/sbin/init");  
  33. 806     run_init_process("/etc/init");  
  34. 807     run_init_process("/bin/init");  
  35. 808     run_init_process("/bin/sh");  
  36. 809   
  37. 810     panic("No init found.  Try passing initoption to kernel.");  
  38. 811 } 

第776行,到此,内核初始化已经接近尾声了,所有的初始化函数都已经被调用,因此free_initmem函数可以舍弃内存的__init_begin至__init_end(包括.init.setup、.initcall.init等节)之间的数据。

所有使用__init标记过的函数和使用__initdata标记过的数据,在free_initmem函数执行后,都不能使用,它们曾经获得的内存现在可以重新用于其他目的。

第782行,如果可能,打开控制台设备,这样init进程就拥有一个控制台,并可以从中读取输入信息,也可以向其中写入信息。

实际上init进程除了打印错误信息以外,并不使用控制台,但是如果调用的是shell或者其他需要交互的进程,而不是init,那么就需要一个可以交互的输入源。如果成功执行open,/dev/console即成为init的标准输入源(文件描述符0)。

第785~786行,调用dup打开/dev/console文件描述符两次。这样,该控制台设备就也可以供标准输出和标准错误使用(文件描述符1和2)。假设第782行的open成功执行(正常情况),init进程现在就拥有3个文件描述符--标准输入、标准输出以及标准错误。

第788~804行,如果内核命令行中给出了到init进程的直接路径(或者别的可替代的程序),这里就试图执行init。

因为当kernel_execve函数成功执行目标程序时并不返回,只有失败时,才能执行相关的表达式。接下来的几行会在几个地方查找init,按照可能性由高到低的顺序依次是: /sbin/init,这是init标准的位置;/etc/init和/bin/init,两个可能的位置。

第805~807行,这些是init可能出现的所有地方。如果在这3个地方都没有发现init,也就无法找到它的同名者了,系统可能就此崩溃。因此,第808行会试图建立一个交互的shell(/bin/sh)来代替,希望root用户可以修复这种错误并重新启动机器。

第810行,由于某些原因,init甚至不能创建shell。当前面的所有情况都失败时,调用panic。这样内核就会试图同步磁盘,确保其状态一致。如果超过了内核选项中定义的时间,它也可能会重新启动机器。

原创地址:http://book.51cto.com/art/201007/213609.htm

0 0
原创粉丝点击