分析Linux內(nèi)核創(chuàng)建一個新進程的過程

.
ret_from_fork

分析fork函數(shù)對應(yīng)的系統(tǒng)調(diào)用處理過程

啟動保護fork命令的menuOS

設(shè)置斷點進行調(diào)試

進程的創(chuàng)建

從了解進程的創(chuàng)建,進程間調(diào)度切換蹬挺,來從總體把握進程工作

當(dāng)前進程復(fù)制一個子進程肄梨,然后進行修改

fork一個子進程的代碼

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc , char * argv[])
{
    int pid;
    pid = fork();
    if(pid<0)
    {
        fprintf(stderr,"Fork Failed !");
        exit(-1);
    }
    else if (pid==0)
    {
        printf("This is Child Process!\n");
     }
    else
    {
        printf("This is Parent Process !\n");
        wait(NULL);
        printf("Child Complete!\n:);
    }

}

-fork()是用戶態(tài)用于創(chuàng)建子進程的系統(tǒng)調(diào)用
-pid<0時打印出錯信息
-子進程中fork()返回值為0奥邮,父進程中fork()返回值為進程pid值
-所以else if和else都將被執(zhí)行
理解進程創(chuàng)建過程復(fù)雜代碼的方法

創(chuàng)建一個新進程在內(nèi)核中的執(zhí)行過程
-fork、vfork和clone三個系統(tǒng)調(diào)用都可以創(chuàng)建一個新進程关顷,而且都是通過調(diào)用do_fork來實現(xiàn)進程的創(chuàng)建
-創(chuàng)建新進程是通過復(fù)制當(dāng)前進程來實現(xiàn)
-復(fù)制一個PCB task_struct
-給新進程分配一個新內(nèi)核堆棧
-修改進程數(shù)據(jù)如pid、進程鏈表等
-從用戶態(tài)代碼中可以看到fork()函數(shù)返回兩次武福,在父進程和子進程中各返回一次议双,父進程從系統(tǒng)調(diào)用中返回,子進程從系統(tǒng)調(diào)用中返回涉及了子進程的內(nèi)核堆棧數(shù)據(jù)狀態(tài)和task_struct中thread記錄的sp和ip的一致性問題捉片,在copy_thread in copy_process里設(shè)定

do_fork

long do_fork(unsigned long clone_flags,
          unsigned long stack_start,
          unsigned long stack_size,
          int __user *parent_tidptr,
          int __user *child_tidptr)
{
    struct task_struct *p;
    int trace = 0;
    long nr;

    /*
     * Determine whether and which event to report to ptracer.  When
     * called from kernel_thread or CLONE_UNTRACED is explicitly
     * requested, no event is reported; otherwise, report if the event
     * for the type of forking is enabled.
     */
    if (!(clone_flags & CLONE_UNTRACED)) {
        if (clone_flags & CLONE_VFORK)
            trace = PTRACE_EVENT_VFORK;
        else if ((clone_flags & CSIGNAL) != SIGCHLD)
            trace = PTRACE_EVENT_CLONE;
        else
            trace = PTRACE_EVENT_FORK;

        if (likely(!ptrace_event_enabled(current, trace)))
            trace = 0;
    }

    p = copy_process(clone_flags, stack_start, stack_size,
             child_tidptr, NULL, trace);
    /*
     * Do this prior waking up the new thread - the thread pointer
     * might get invalid after that point, if the thread exits quickly.
     */
    if (!IS_ERR(p)) {
        struct completion vfork;
        struct pid *pid;

        trace_sched_process_fork(current, p);

        pid = get_task_pid(p, PIDTYPE_PID);
        nr = pid_vnr(pid);

        if (clone_flags & CLONE_PARENT_SETTID)
            put_user(nr, parent_tidptr);

        if (clone_flags & CLONE_VFORK) {
            p->vfork_done = &vfork;
            init_completion(&vfork);
            get_task_struct(p);
        }

        wake_up_new_task(p);

        /* forking complete and child started to run, tell ptracer */
        if (unlikely(trace))
            ptrace_event_pid(trace, pid);

        if (clone_flags & CLONE_VFORK) {
            if (!wait_for_vfork_done(p, &vfork))
                ptrace_event_pid(PTRACE_EVENT_VFORK_DONE, pid);
        }

        put_pid(pid);
    } else {
        nr = PTR_ERR(p);
    }
    return nr;
}

copy process創(chuàng)建進程內(nèi)容
-dup_task_struct復(fù)制pcb平痰,分配新空間
-然后初始化賦值子進程信息
-copy thread從子進程pid內(nèi)核堆棧位置棧底汞舱,拷貝內(nèi)核堆棧數(shù)據(jù)和指定新進程的第一條指令地址

創(chuàng)建的新進程從哪里開始執(zhí)行

·p->thread.ip = (unsigned long) ret_from_fork;·
ret_from_fork返回了子進程調(diào)度的第一條指令
在復(fù)制內(nèi)核堆棧時只復(fù)制了其中一部分SAVE_ALLL相關(guān)的部分,int指令和cpu壓棧內(nèi)容宗雇,即最棧底的部分
ret_from_fork會跳轉(zhuǎn)syscall exit兵拢,最終返回用戶態(tài),此時返回到子進程用戶空間
所以創(chuàng)建的新進程從ret_from_fork開始執(zhí)行

王瀟洋
原創(chuàng)作品轉(zhuǎn)載請注明出處
《Linux內(nèi)核分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末逾礁,一起剝皮案震驚了整個濱河市说铃,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌嘹履,老刑警劉巖腻扇,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異砾嫉,居然都是意外死亡幼苛,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進店門焕刮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來舶沿,“玉大人,你說我怎么就攤上這事配并±ǖ矗” “怎么了?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵溉旋,是天一觀的道長畸冲。 經(jīng)常有香客問我,道長观腊,這世上最難降的妖魔是什么邑闲? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮梧油,結(jié)果婚禮上苫耸,老公的妹妹穿的比我還像新娘。我一直安慰自己儡陨,他們只是感情好褪子,可當(dāng)我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著迄委,像睡著了一般褐筛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上叙身,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天渔扎,我揣著相機與錄音,去河邊找鬼信轿。 笑死晃痴,一個胖子當(dāng)著我的面吹牛残吩,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播倘核,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼泣侮,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了紧唱?” 一聲冷哼從身側(cè)響起活尊,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎漏益,沒想到半個月后蛹锰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡绰疤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年铜犬,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片轻庆。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡癣猾,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出余爆,到底是詐尸還是另有隱情纷宇,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布龙屉,位于F島的核電站呐粘,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏转捕。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一唆垃、第九天 我趴在偏房一處隱蔽的房頂上張望五芝。 院中可真熱鬧,春花似錦辕万、人聲如沸枢步。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽醉途。三九已至,卻和暖如春砖茸,著一層夾襖步出監(jiān)牢的瞬間隘擎,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工凉夯, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留货葬,地道東北人采幌。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像震桶,于是被迫代替她去往敵國和親休傍。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內(nèi)容