概述本文简单分析了init进程的源码,梳理了它的处理流程,重点介绍了init进程是如何启动应用的,并总结了启动脚本的编写思路文件。init进程源码分析init进程如何知道linux内核启动的第一个进程?从内核源码linux-2.6.xxx/init/main.c的kernel_init()函数分析可以发现,内核会根据uboot传入的参数启动第一个进程,一般是第一个进程init是如何启动的。它是通过调用kernel_execve()函数来完成的。猜测是从根文件系统的/sbin/init启动的。Linux中的任何应用程序都是基于文件系统的。启动应用前提是根文件系统已经挂载。好的,那么根文件系统是从哪里来的呢?它是由工具busybox编译生成的,所以要分析init源码,去busybox找到init的源码源位置:/busybox/init/init.c,在里面找到main()函数,并发现只有init_main(),没有main()。可以猜测是busybox通过一些方法修改了init进程的入口为init_main()。其实busybox的所有命令工具都是一个busybox程序。链接,cd/sbinls-linitlrwxrwxrwx1root014Nov162016init->../bin/busybox,可以看到init进程其实就是busybox的链接,不用管,知道init进程的入口就是init_main()函数#ifDEBUG_SEGV_HANDLER{structsigactionsa;memset(&sa,0,sizeof(sa));sa.sa_sigaction=handle_sigsegv;sa.sa_flags=SA_SIGINFO;sigaction(SIGSEGV,&sa,NULL);...}#endif...console_init();set_sane_term();....../*确保environsisssettosomethingsane*/putenv((char*)"HOME=/");putenv((char*)bb_PATH_root_path);putenv((char*)"SHELL=/bin/sh");putenv((char*)"USER=root");/*needed?why?*/这一段是init进程首先要做的,设置一些信号相关的东西,初始化console,然后设置Environmentvariables貌似和启动app没有关系,不用管,继续往下看/*Checkifwearesupposedtobeinsingleusermode*/if(argv[1]&&(strcmp(argv[1],"single")==0||strcmp(argv[1],"-s")==0||LONE_CHAR(argv[1],'1'))){/*?*Notinsingleusermode-seewhatinittabsays*//*NOTEthatifCONFIG_FEATURE_USE_INITTABisNOTdefined,*thenparse_inittab()simplyaddsinsomedefault*actions(i.e.,INIT_SCRIPTandapair*of"askfirst"shells)*/parse_inittab();}如果这段代码是一个ifing判断,评论说,然后去前半段代码,如果不是单用户模式,调用parse_inittab()函数,因为内核启动init进程时没有传入额外的参数,所以argv[1]不存在,程序经过parse_inittab()注释说如果没有定义CONFIG_FEATURE_USE_INITTAB宏,程序会执行一些默认动作。你怎么知道这个宏是否被定义了?猜测这个宏应该是busybox配置的一个选项。那么,如何检查busybox配置呢?和linux内核配置一样,结合makemenuconfig和各级config文件,看是否定义了宏CONFIG_FEATURE_USE_INITTAB?在busybox中执行makemeunconfig,进入熟悉的配置界面看看。里面好像有一个initutilities项和init相关,里面有个项“Supportreadinganinittabfile”,选中这个配置项,描述里有“inittab”字样,很像初始化源代码中提到的parse_inittab()。好了,先把makemenuconfig放一边,我们看一下配置文件,打开顶层目录的Config.in,全局搜索“init”,只找到最下面:sourceinit/Config.in进入init文件夹,打开Config.in文件,找到配置项configFEATURE_USE_INITTABbool"Supportreadinganinittabfile"defaultydependsonINIThelpAllowinittoreadanittabfilewhenthesystemboot。猜对了,宏CONFIG_FEATURE_USE_INITTAB确实定义了,回到init源码分析,进入parse_inittab()函数,先看到这个函数前有一大段注释,看它写的是什么"shells").IfCONFIG_FEATURE_USE_INITTAB*_is_defined,但是/etc/inittabismissing,this*resultsinthesamesetofdefaultbehaviors.*/前面的话和前面的if判断意思差不多,如果定义了XXX宏,但是/etc/inittab文件没有,同样会去default的动作,嗯,大致猜一下,parse_inttab()函数好像跟要分析的app启动有关系,如果定义了XXX宏,就会解析/etc/inittab文件,执行里面的内容,如果XXXmacroisnotdefined或者/etc/inittab文件不存在,执行一些默认的东西就好了,弄清楚一件事,/etc/inittab文件很重要,你可能需要自己创建这个文件,写里面有东西,但是要写什么?唐还不知道。那么如果不走/etc/inittab这个路径,默认会执行的动作是什么意思呢?下面分析一下函数parse_inittab()setupsomedefaultbehavior*//*Sysinit*/new_init_action(SYSINIT,INIT_SCRIPT,"");/*Askfirstshellontty1-4*/new_init_action(ASKFIRST,bb_default_login_shell,"");//TODO:VC_1insteadof""?""isconsole->cttyproblems->angryusersnew_init_action(ASKFIRST,bb_default_login_shell,VC_2);new_init_action(ASKFIRST,bb_default_login_shell,VC_3);new_init_log_shell,ASKfa);/*重启Ctrl-Alt-Del*/new_init_action(CTRLALTDEL,"reboot","");/*Umountallfilesystemsonhalt/reboot*/new_init_action(SHUTDOWN,"umount-a-r","");/*Swapoffonhalt/reboot*/new_init_action(SHUTDOWN,"swapoff-a","");/*RestartinitwhenaQUITisreceived*/new_init_action(RESTART,"init","");返回;}#ifENABLE_FEATURE_USE_INITTAB/*optional_tty:ignored_runlevel:action:command*Delimsarenottobecollapsedandneedexactly4tokens*/while(config_read(parser,token,4,0,"#:",PARSE_NORMAL&~(PARSE_TRIM|PARSE_COLLAPSE))){/*顺序必须对应于SYSINIT..RESTART常量*/staticconstcharactions[]ALIGN1="sysinit\0""wait\0""once\0""respawn\0""askfirst\0""ctrlaltdel\0""关机\0""重启\0";intaction;char*tty=token[0];如果(!token[3])/*lessthan4tokens*/gotobad_entry;action=index_in_strings(actions,token[2]);if(action<0||!token[3][0])/*token[3]:command*/gotobad_entry;/*turn.*TTY->/dev/TTY*/if(tty[0]){tty=concat_path_file("/dev/",skip_dev_pfx(tty));}new_init_action(1<
