Unix高級環(huán)境編程:進(jìn)程控制

無標(biāo)題.png

計算機(jī)啟動的過程

系統(tǒng)啟動的經(jīng)過可以匯整成底下的流程的:
1注整、加載 BIOS 的硬件資訊與進(jìn)行自我測試,并依據(jù)配置取得第一個可啟動的裝置傲诵;
2龙考、讀取并運(yùn)行第一個啟動裝置內(nèi) MBR 的 boot Loader (亦即是 grub, spfdisk 等程序);
3期揪、依據(jù) boot loader 的配置加載 Kernel 掉奄,Kernel 會開始偵測硬件與加載驅(qū)動程序;
4凤薛、在硬件驅(qū)動成功后姓建,Kernel 會主動呼叫 init 程序,而 init 會取得 run-level 資訊缤苫;
5速兔、init 運(yùn)行 /etc/rc.d/rc.sysinit 文件來準(zhǔn)備軟件運(yùn)行的作業(yè)環(huán)境 (如網(wǎng)絡(luò)、時區(qū)等)活玲;
6涣狗、init 運(yùn)行 run-level 的各個服務(wù)之啟動 (script 方式);
7翼虫、init 運(yùn)行 /etc/rc.d/rc.local 文件屑柔;
8、init 運(yùn)行終端機(jī)模擬程序 mingetty 來啟動 login 程序珍剑,最后就等待使用者登陸啦;

進(jìn)程0和進(jìn)程1

ps -A

內(nèi)核是一個大的程序死陆,可以控制硬件招拙,也可以創(chuàng)建、運(yùn)行措译、終止别凤、控制所有的進(jìn)程。當(dāng)內(nèi)核被加載到內(nèi)存后领虹,首先就會有完成內(nèi)核初始化的函數(shù)start_kernel()從無到有的創(chuàng)建一個內(nèi)核線程swap规哪,并設(shè)置其PID為0,即進(jìn)程0塌衰;它也叫閑逛進(jìn)程诉稍;進(jìn)程0![Uploading 捕獲_653996.PNG . . .]
執(zhí)行的是cpu_idle()函數(shù),該函數(shù)僅有一條hlt匯編指令最疆,就是在系統(tǒng)閑置時用來降低電力的使用和減少熱的產(chǎn)生。同時進(jìn)程0的PCB叫做init_task,在很多鏈表中起了表頭的作用疲眷。

sysproc進(jìn)程锈候。管理換入與換出的進(jìn)程,對系統(tǒng)中運(yùn)行的進(jìn)程進(jìn)行合理地調(diào)度。 將進(jìn)程從硬盤交換區(qū)調(diào)入內(nèi)存的過程稱為換入仍源;將進(jìn)程從內(nèi)存調(diào)到硬盤交換 區(qū)的過程稱為換出心褐。該進(jìn)程是unix核心創(chuàng)建的第一個進(jìn)程,有多個LWPs笼踩。

<strong>進(jìn)程0kernel啟動時創(chuàng)建的第一個進(jìn)程逗爹,時進(jìn)程1的父進(jìn)程,負(fù)責(zé)其他進(jìn)程的調(diào)度</strong>
<strong>進(jìn)程調(diào)度init函數(shù)戳表,負(fù)責(zé)系統(tǒng)初始化</strong>

整個linux系統(tǒng)的所有進(jìn)程也是一個樹形結(jié)構(gòu)桶至。樹根是系統(tǒng)自動構(gòu)造的,即在內(nèi)核態(tài)下執(zhí)行的0號進(jìn)程匾旭,它是所有進(jìn)程的祖先镣屹。由0號進(jìn)程創(chuàng)建1號進(jìn)程(內(nèi)核態(tài)),1號負(fù)責(zé)執(zhí)行內(nèi)核的部分初始化工作及進(jìn)行系統(tǒng)配置价涝,并創(chuàng)建若干個用于高速緩存和虛擬主存管理的內(nèi)核線程女蜈。隨后,1號進(jìn)程調(diào)用execve()運(yùn)行可執(zhí)行程序init色瘩,并演變成用戶態(tài)1號進(jìn)程伪窖,即init進(jìn)程。它按照配置文件/etc/initab的要求居兆,完成系統(tǒng)啟動工作覆山,創(chuàng)建編號為1號、2號...的若干終端注冊進(jìn)程getty泥栖。

在多處理器系統(tǒng)中簇宽,每個CPU都有一個進(jìn)程0,主要打開機(jī)器電源吧享,計算機(jī)的BIOS就啟動一個CPU魏割,同時禁用其他CPU。運(yùn)行的CPU 上的swapper進(jìn)程初初始化內(nèi)核數(shù)據(jù)結(jié)構(gòu)钢颂,然后激活其他的并且使用copy_process()函數(shù)創(chuàng)建另外的swapper進(jìn)程钞它,把0 傳遞給新創(chuàng)建的swapper進(jìn)程作為他們進(jìn)程的PID.

fork()

進(jìn)程在內(nèi)存里有三部分的數(shù)據(jù)——代碼段、堆棧段和數(shù)據(jù)段殊鞭。這三個部分是構(gòu)成一個完整的執(zhí)行序列的必要的部分遭垛。
代碼段——存放了程序代碼的內(nèi)存空間。這個最容易理解钱豁,不就是程序在機(jī)器內(nèi)的表示而已嘛耻卡。注意假如機(jī)器中有數(shù)個進(jìn)程運(yùn)行相同的一個程序,那么它們就可以使用相同的代碼段牲尺。也就是說如果fork()出來了一個子進(jìn)程卵酪,子進(jìn)程和父進(jìn)程實際上使用的是相同的代碼段幌蚊。
堆棧段——存放的就是子程序的返回地址、子程序的參數(shù)以及程序的局部變量溃卡。
數(shù)據(jù)段——全局變量和靜態(tài)變量

父子進(jìn)程使用相同的代碼段溢豆,但是會擁有各自的數(shù)據(jù)段和堆棧段。

void main()  
{  
    pid_t pid;  
    pid=fork();  
    if(pid==0)  
    {  
        //子進(jìn)程任務(wù)  
    }  
    else if(pid>0)  
    {  
        //父進(jìn)程任務(wù)  
    }  
}  

執(zhí)行過程是這樣的:
1.操作系統(tǒng)分配內(nèi)存給父進(jìn)程瘸羡,包括上面提到的三個段漩仙,就是會在堆棧段里有一塊空間是用來存放pid變量的。
2.接著內(nèi)核調(diào)度父進(jìn)程執(zhí)行fork()函數(shù)(這個函數(shù)里實際上使用了系統(tǒng)調(diào)用)犹赖,這時候子進(jìn)程才會出現(xiàn)队他,內(nèi)核會將父進(jìn)程的數(shù)據(jù)段和堆棧段作一個拷貝給子進(jìn)程,注意這時子進(jìn)程的堆棧段里一定會有一個空間用來存放pid變量峻村!然后系統(tǒng)調(diào)用成功麸折,內(nèi)核給父進(jìn)程堆棧段里的pid變量賦上子進(jìn)程的pid號,而給子進(jìn)程堆棧段里的pid變量賦上0粘昨。
3.接下來還是交給內(nèi)核調(diào)度決定執(zhí)行的是子進(jìn)程還是父進(jìn)程(一般內(nèi)核會先給子進(jìn)程執(zhí)行)垢啼。如果是父進(jìn)程,它的下一句代碼就是判斷pid變量的大小张肾,它會去它的堆棧段里存放pid變量的地方取出pid來進(jìn)行比較芭析,它會發(fā)現(xiàn)pid>0,所以接下來它就去執(zhí)行——父進(jìn)程任務(wù)吞瞪;如果是子進(jìn)程馁启,由于同樣的代碼段,它也會去比較它自己的pid變量芍秆,發(fā)現(xiàn)pid=0进统,所以接下來它會去執(zhí)行——子進(jìn)程任務(wù)。

沒有一個函數(shù)可以使父進(jìn)程獲取起所有子進(jìn)程
一個進(jìn)程只會有一個父進(jìn)程

父子進(jìn)程先后問題

運(yùn)行結(jié)果

父子進(jìn)程利用共享內(nèi)存通信

父子進(jìn)程共享內(nèi)存通信

fork與vfork的區(qū)別

1.vfork保證子進(jìn)程先運(yùn)行浪听,在它調(diào)用exec或exit之后父進(jìn)程才可能被調(diào)度運(yùn)行。如果在調(diào)用這兩個函數(shù)之前子進(jìn)程依賴于父進(jìn)程的進(jìn)一步動作眉菱,則會導(dǎo)致死鎖迹栓。
2.fork要拷貝父進(jìn)程的進(jìn)程環(huán)境;而vfork則不需要完全拷貝父進(jìn)程的進(jìn)程環(huán)境俭缓,在子進(jìn)程沒有調(diào)用exec和exit之前克伊,子進(jìn)程與父進(jìn)程共享進(jìn)程環(huán)境,相當(dāng)于線程的概念华坦,此時父進(jìn)程阻塞等待愿吹。

為什么會有vfork呢?
因為以前的fork當(dāng)它創(chuàng)建一個子進(jìn)程時,將會創(chuàng)建一個新的地址空間惜姐,并且拷貝父進(jìn)程的資源犁跪,然后將會有兩種行為:
1.執(zhí)行從父進(jìn)程那里拷貝過來的代碼段
2.調(diào)用一個exec執(zhí)行一個新的代碼段

當(dāng)進(jìn)程調(diào)用exec函數(shù)時椿息,一個新程序替換了當(dāng)前進(jìn)程的正文,數(shù)據(jù)坷衍,堆和棧段寝优。這樣,前面的拷貝工作就是白費(fèi)力氣了枫耳,這種情況下乏矾,聰明的人就想出了vfork。vfork并不復(fù)制父進(jìn)程的進(jìn)程環(huán)境迁杨,子進(jìn)程在父進(jìn)程的地址空間中運(yùn)行钻心,所以子進(jìn)程不能進(jìn)行寫操作,并且在兒子“霸占”著老子的房子時候铅协,要委屈老子一下了捷沸,讓他在外面歇著(阻塞),一旦兒子執(zhí)行了exec或者exit后警医,相當(dāng)于兒子買了自己的房子了亿胸,這時候就相當(dāng)于分家了。

exit和return

1.exit用于結(jié)束正在運(yùn)行的整個程序预皇,它將參數(shù)返回給OS侈玄,把控制權(quán)交給操作系統(tǒng);而return 是退出當(dāng)前函數(shù)吟温,返回函數(shù)值序仙,把控制權(quán)交給調(diào)用函數(shù)。

  1. exit是系統(tǒng)調(diào)用級別鲁豪,它表示一個進(jìn)程的結(jié)束潘悼;而return 是語言級別的,它表示調(diào)用堆棧的返回爬橡。
  2. 在main函數(shù)結(jié)束時治唤,會隱式地調(diào)用exit函數(shù),所以一般程序執(zhí)行到main()結(jié)尾時糙申,則結(jié)束主進(jìn)程宾添。exit將刪除進(jìn)程使用的內(nèi)存空間,同時把錯誤信息返回給父進(jìn)程柜裸。
  3. void exit(int status); 一般status為0缕陕,表示正常退出,非0表示非正常退出疙挺。

exit函數(shù)和return函數(shù)的主要區(qū)別是:

1)exit用于在程序運(yùn)行的過程中隨時結(jié)束程序扛邑,其參數(shù)是返回給OS的。也可以這么講:exit函數(shù)是退出應(yīng)用程序,并將應(yīng)用程序的一個狀態(tài)返回給OS铐然,這個狀態(tài)標(biāo)識了應(yīng)用程序的一些運(yùn)行信息蔬崩。
main函數(shù)結(jié)束時也會隱式地調(diào)用exit函數(shù)恶座,exit函數(shù)運(yùn)行時首先會執(zhí)行由atexit()函數(shù)登記的函數(shù),然后會做一些自身的清理工作舱殿,同時刷新所有輸出流奥裸、關(guān)閉所有打開的流并且關(guān)閉通過標(biāo)準(zhǔn)I/O函數(shù)tmpfile()創(chuàng)建的臨時文件。
exit是系統(tǒng)調(diào)用級別的沪袭,它表示了一個進(jìn)程的結(jié)束湾宙,它將刪除進(jìn)程使用的內(nèi)存空間,同時把錯誤信息返回父進(jìn)程冈绊。通常情況:exit(0)表示程序正常, exit(1)和exit(-1)表示程序異常退出侠鳄,exit(2)表示系統(tǒng)找不到指定的文件。在整個程序中死宣,只要調(diào)用exit就結(jié)束伟恶。

2)return是語言級別的,它表示了調(diào)用堆棧的返回毅该;return是返回函數(shù)值并退出函數(shù)博秫,通常0為正常退出,非0為非正常退出眶掌,請注意挡育,如果是在主函數(shù)main, 自然也就結(jié)束當(dāng)前進(jìn)程了(也就是說,在main()里面朴爬,你可以用return n即寒,也能夠直接用exit(n)來做),如果不是在main函數(shù)中召噩,那就是退回上一層調(diào)用母赵。在多個進(jìn)程時,如果有時要檢測上個進(jìn)程是否正常退出具滴,就要用到上個進(jìn)程的返回值凹嘲。

exit()與_exit()的區(qū)別


_exit 函數(shù)的作用是:直接使進(jìn)程停止運(yùn)行,清除其使用的內(nèi)存空間构韵,并清除其在內(nèi)核的各種數(shù)據(jù)結(jié)構(gòu)施绎;exit 函數(shù)則在這些基礎(chǔ)上做了一些小動作,在執(zhí)行退出之前還加了若干道工序贞绳。exit() 函數(shù)與 _exit() 函數(shù)的最大區(qū)別在于exit()函數(shù)在調(diào)用exit 系統(tǒng)調(diào)用前要檢查文件的打開情況,把文件緩沖區(qū)中的內(nèi)容寫回文件致稀。也就是圖中的“清理I/O緩沖”冈闭。

結(jié)果

實際用戶 有效用戶 保存的設(shè)置用戶

文件的訪問權(quán)限包括讀寫和執(zhí)行。判斷某個進(jìn)程對文件有何權(quán)限時抖单,內(nèi)核會將非超級用戶進(jìn)程的有效ID與文件的所有者ID進(jìn)行比較萎攒,當(dāng)然遇八,也可能需要比較有效組ID,這關(guān)系到具體的權(quán)限測試方法耍休,先不在這里說明刃永。而超級用戶創(chuàng)建的進(jìn)程是允許訪問整個文件系統(tǒng)的。它的有效ID等于0羊精。不過斯够,這里還有一點需要說明的是,僅僅有合適的有效ID喧锦,還不一定就能獲得所有或者部分權(quán)限读规。你需要得到被訪問文件的允許,這就是文件訪問權(quán)限位(用戶讀燃少、用戶寫束亏、組讀等)的責(zé)任了。

這里又牽涉到一個“ID”阵具,即文件的所有者ID碍遍。文件的所有者ID是什么呢?創(chuàng)建文件是由某用戶的進(jìn)程實現(xiàn)的吧阳液?所以在創(chuàng)建新文件的時候怕敬,就將該進(jìn)程的有效ID作為該文件的所有者ID了。APUE里面有時又將文件的所有者ID稱為“文件的用戶ID”趁舀。

一般情況下赖捌,進(jìn)程的有效用戶ID就被設(shè)成執(zhí)行該進(jìn)程的實際用戶ID。比如矮烹,用戶usr01執(zhí)行了進(jìn)程process越庇,process的有效用戶ID就設(shè)成了用戶usr01的ID(實際用戶ID)。但是有的時候奉狈,一個進(jìn)程可能要去執(zhí)行其他用戶創(chuàng)建的文件卤唉。這時,該進(jìn)程的有效ID和該文件的所有者ID是不同的(記住文件的所有者Id就是最初創(chuàng)建它的進(jìn)程有效ID)仁期。但是如果文件設(shè)置了“設(shè)置用戶ID位”或者“設(shè)置組ID位”桑驱,那么該進(jìn)程在執(zhí)行該文件的時候,就會將進(jìn)程的有效ID臨時更改為文件的所有者ID跛蛋。

設(shè)置用戶ID:設(shè)置用戶ID是由exec函數(shù)復(fù)制有效用戶ID得來的熬的。所以說設(shè)置用戶ID是進(jìn)程有效ID的副本。為什么要保留進(jìn)程有效ID的副本呢赊级?剛才講到文件有設(shè)置用戶ID位時押框,內(nèi)核會將執(zhí)行進(jìn)程的有效ID臨時更改為文件的所有者ID。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末理逊,一起剝皮案震驚了整個濱河市橡伞,隨后出現(xiàn)的幾起案子盒揉,更是在濱河造成了極大的恐慌,老刑警劉巖兑徘,帶你破解...
    沈念sama閱讀 211,496評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件刚盈,死亡現(xiàn)場離奇詭異,居然都是意外死亡挂脑,警方通過查閱死者的電腦和手機(jī)藕漱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,187評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來最域,“玉大人谴分,你說我怎么就攤上這事《浦” “怎么了牺蹄?”我有些...
    開封第一講書人閱讀 157,091評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長薄翅。 經(jīng)常有香客問我沙兰,道長,這世上最難降的妖魔是什么翘魄? 我笑而不...
    開封第一講書人閱讀 56,458評論 1 283
  • 正文 為了忘掉前任鼎天,我火速辦了婚禮,結(jié)果婚禮上暑竟,老公的妹妹穿的比我還像新娘斋射。我一直安慰自己,他們只是感情好但荤,可當(dāng)我...
    茶點故事閱讀 65,542評論 6 385
  • 文/花漫 我一把揭開白布罗岖。 她就那樣靜靜地躺著,像睡著了一般腹躁。 火紅的嫁衣襯著肌膚如雪桑包。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,802評論 1 290
  • 那天纺非,我揣著相機(jī)與錄音哑了,去河邊找鬼。 笑死烧颖,一個胖子當(dāng)著我的面吹牛弱左,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播炕淮,決...
    沈念sama閱讀 38,945評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼科贬,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起榜掌,我...
    開封第一講書人閱讀 37,709評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎乘综,沒想到半個月后憎账,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,158評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡卡辰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,502評論 2 327
  • 正文 我和宋清朗相戀三年胞皱,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片九妈。...
    茶點故事閱讀 38,637評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡反砌,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出萌朱,到底是詐尸還是另有隱情宴树,我是刑警寧澤,帶...
    沈念sama閱讀 34,300評論 4 329
  • 正文 年R本政府宣布晶疼,位于F島的核電站酒贬,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏翠霍。R本人自食惡果不足惜锭吨,卻給世界環(huán)境...
    茶點故事閱讀 39,911評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望寒匙。 院中可真熱鬧零如,春花似錦、人聲如沸锄弱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,744評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽棵癣。三九已至辕翰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間狈谊,已是汗流浹背喜命。 一陣腳步聲響...
    開封第一講書人閱讀 31,982評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留河劝,地道東北人壁榕。 一個月前我還...
    沈念sama閱讀 46,344評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像赎瞎,于是被迫代替她去往敵國和親牌里。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,500評論 2 348

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