www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁(yè) > 芯聞號(hào) > 充電吧
[導(dǎo)讀]概述 本文通過(guò)簡(jiǎn)要分析init進(jìn)程源碼,梳理其處理流程,重點(diǎn)關(guān)注init進(jìn)程如何啟動(dòng)應(yīng)用程序,總結(jié)啟動(dòng)腳本文件的編寫(xiě)思路 init進(jìn)程源碼分析 init進(jìn)程是linux內(nèi)核啟動(dòng)的第一個(gè)進(jìn)程,

概述

本文通過(guò)簡(jiǎn)要分析init進(jìn)程源碼,梳理其處理流程,重點(diǎn)關(guān)注init進(jìn)程如何啟動(dòng)應(yīng)用程序,總結(jié)啟動(dòng)腳本文件的編寫(xiě)思路

init進(jìn)程源碼分析

init進(jìn)程是linux內(nèi)核啟動(dòng)的第一個(gè)進(jìn)程,怎么知道的?從內(nèi)核源碼linux-2.6.xxx/init/main.c代碼的kernel_init()函數(shù)分析,可以發(fā)現(xiàn),內(nèi)核會(huì)根據(jù)uboot傳入的參數(shù)來(lái)啟動(dòng)第一個(gè)進(jìn)程,一般都是init

怎么啟動(dòng)的呢,調(diào)用kernel_execve()函數(shù)完成的,猜測(cè)是從根文件系統(tǒng)的/sbin/init來(lái)啟動(dòng)的,linux的任何應(yīng)用程序都是基于文件系統(tǒng)的,啟動(dòng)應(yīng)用程序前提是根文件系統(tǒng)已經(jīng)掛載好了。好,那么根文件系統(tǒng)又是從哪里來(lái)的呢,是由busybox這個(gè)工具配置編譯生成的,所以要分析init源碼,要去busybox里找init的源碼

源碼位置:/busybox/init/init.c,在其中查找main()函數(shù),發(fā)現(xiàn)只有init_main(),沒(méi)有main(),可以猜測(cè)busybox是通過(guò)一些方法將init進(jìn)程的入口修改為init_main(),實(shí)際上所有busybox的命令工具都是一個(gè)到busybox程序的鏈接,

cd /sbin
ls -l init
lrwxrwxrwx 1 root 0 14 Nov 16 2016 init -> ../bin/busybox

可以看到,init進(jìn)程其實(shí)是到busybox的鏈接,不用管它,知道init進(jìn)程的入口是init_main()函數(shù)就行了

#if DEBUG_SEGV_HANDLER
    {
        struct sigaction sa;
        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();
......
/* Make sure environs is set to something sane */
putenv((char *) "HOME=/");
putenv((char *) bb_PATH_root_path);
putenv((char *) "SHELL=/bin/sh");
putenv((char *) "USER=root"); /* needed? why? */

這一段是init進(jìn)程最開(kāi)始要做的事情,設(shè)置一些信號(hào)相關(guān)的東西,初始化console,然后設(shè)置環(huán)境變量,跟啟動(dòng)app似乎沒(méi)有什么關(guān)系,不用管,繼續(xù)往下看

/* Check if we are supposed to be in single user mode */
if (argv[1]
 && (strcmp(argv[1], "single") == 0 || strcmp(argv[1], "-s") == 0 || LONE_CHAR(argv[1], '1'))
) {
    /* ??? shouldn't we set RUNLEVEL="b" here? */
    /* Start a shell on console */
    new_init_action(RESPAWN, bb_default_login_shell, "");
} else {
    /* Not in single user mode - see what inittab says */

    /* NOTE that if CONFIG_FEATURE_USE_INITTAB is NOT defined,
     * then parse_inittab() simply adds in some default
     * actions (i.e., INIT_SCRIPT and a pair
     * of "askfirst" shells) */
    parse_inittab();
}

這一段代碼是一個(gè)if判斷,注釋說(shuō)如果是single user mode,則走上半段代碼,如果不是single user mode,則調(diào)用parse_inittab() 函數(shù),因?yàn)閮?nèi)核啟動(dòng)init進(jìn)程沒(méi)有傳入附加參數(shù),所以argv[1]不存在,程序走parse_inittab()

注釋還說(shuō)如果沒(méi)有定義CONFIG_FEATURE_USE_INITTAB 這個(gè)宏,程序會(huì)執(zhí)行一些默認(rèn)的action,那怎么知道這個(gè)宏定義了沒(méi)有呢,猜測(cè)這個(gè)宏應(yīng)該是對(duì)busybox配置時(shí)的選項(xiàng),好,怎么查看busybox配置呢,和linux內(nèi)核配置一樣的道理,結(jié)合make menuconfig和各級(jí)config文件來(lái)看

是否定義了宏CONFIG_FEATURE_USE_INITTAB?

在busybox中執(zhí)行make meunconfig,進(jìn)入熟悉的配置界面

大概瀏覽一下,和init有關(guān)系的好像有個(gè)Init Utilities項(xiàng),進(jìn)去

這里面有一項(xiàng)“Support reading an inittab file”,這個(gè)配置項(xiàng)是選中的,描述中有“inittab”這個(gè)單詞,和init源碼中說(shuō)到的parse_inittab()很相似,好,make menuconfig先放到一邊,來(lái)看看配置文件,打開(kāi)頂層目錄的Config.in,全局搜一下”init”,發(fā)現(xiàn)只有最下面有:

source init/Config.in

進(jìn)入init文件夾,打開(kāi)其中的Config.in文件,發(fā)現(xiàn)配置項(xiàng)

config FEATURE_USE_INITTAB
    bool "Support reading an inittab file"
    default y
    depends on INIT
    help
      Allow init to read an inittab file when the system boot.

猜測(cè)沒(méi)錯(cuò),CONFIG_FEATURE_USE_INITTAB這個(gè)宏確實(shí)定義了,回到init源碼分析,進(jìn)入parse_inittab()函數(shù)。首先看到這個(gè)函數(shù)前有一大段注釋?zhuān)纯此f(shuō)什么

/* NOTE that if CONFIG_FEATURE_USE_INITTAB is NOT defined,
 * then parse_inittab() simply adds in some default
 * actions (i.e., runs INIT_SCRIPT and then starts a pair
 * of "askfirst" shells).  If CONFIG_FEATURE_USE_INITTAB
 * _is_ defined, but /etc/inittab is missing, this
 * results in the same set of default behaviors.
 */

前面的話和之前的if判斷意思差不多,如果定義了XXX這個(gè)宏,但是/etc/inittab這個(gè)文件沒(méi)有,也會(huì)走默認(rèn)的action,好,大概猜想一下,parse_inttab()函數(shù)好像和要分析的app啟動(dòng)有點(diǎn)關(guān)系了,如果定義了XXX宏,就去解析/etc/inittab這個(gè)文件,執(zhí)行里面的東西,如果沒(méi)有定義XXX宏或者/etc/inittab文件不存在,執(zhí)行一些默認(rèn)的東西

好,搞清楚一件事,/etc/inittab這個(gè)文件很重要,可能需要自己來(lái)創(chuàng)建這個(gè)文件,往里面寫(xiě)東西,但是寫(xiě)什么內(nèi)容呢?目前還不知道。那如果不走/etc/inittab這一條路呢,默認(rèn)會(huì)執(zhí)行的action又是什么意思?來(lái)分析一下parse_inittab()這個(gè)函數(shù)

static void parse_inittab(void)
{
#if ENABLE_FEATURE_USE_INITTAB
    char *token[4];
    parser_t *parser = config_open2("/etc/inittab", fopen_for_read);

    if (parser == NULL)
#endif
    {
        /* No inittab file - set up some default behavior */
        /* Sysinit */
        new_init_action(SYSINIT, INIT_SCRIPT, "");
        /* Askfirst shell on tty1-4 */
        new_init_action(ASKFIRST, bb_default_login_shell, "");
//TODO: VC_1 instead of ""? "" is console -> ctty problems -> angry users
        new_init_action(ASKFIRST, bb_default_login_shell, VC_2);
        new_init_action(ASKFIRST, bb_default_login_shell, VC_3);
        new_init_action(ASKFIRST, bb_default_login_shell, VC_4);
        /* Reboot on Ctrl-Alt-Del */
        new_init_action(CTRLALTDEL, "reboot", "");
        /* Umount all filesystems on halt/reboot */
        new_init_action(SHUTDOWN, "umount -a -r", "");
        /* Swapoff on halt/reboot */
        new_init_action(SHUTDOWN, "swapoff -a", "");
        /* Restart init when a QUIT is received */
        new_init_action(RESTART, "init", "");
        return;
    }

#if ENABLE_FEATURE_USE_INITTAB
    /* optional_tty:ignored_runlevel:action:command
     * Delims are not to be collapsed and need exactly 4 tokens
     */
    while (config_read(parser, token, 4, 0, "#:",
                PARSE_NORMAL & ~(PARSE_TRIM | PARSE_COLLAPSE))) {
        /* order must correspond to SYSINIT..RESTART constants */
        static const char actions[] ALIGN1 =
            "sysinit