国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > Unix > 正文

《Unix環(huán)境高級編程》讀書筆記 第8章-進(jìn)程控制

2024-06-28 13:24:24
字體:
供稿:網(wǎng)友
《Unix環(huán)境高級編程》讀書筆記 第8章-進(jìn)程控制 1. 進(jìn)程標(biāo)識
  • 進(jìn)程ID標(biāo)識符是唯一、可復(fù)用的。大多數(shù)Unix系統(tǒng)實(shí)現(xiàn)延遲復(fù)用算法,使得賦予新建進(jìn)程的ID不同于最近終止所使用的ID
  • ID為0的進(jìn)程通常是調(diào)度進(jìn)程,也常被稱為交換進(jìn)程。它是內(nèi)核的一部分,是系統(tǒng)進(jìn)程。
  • ID為1的進(jìn)程通常是init進(jìn)程,在自舉過程結(jié)束時由內(nèi)核調(diào)用。該進(jìn)程負(fù)責(zé)在內(nèi)核自舉后啟動一個Unix系統(tǒng),它決不會終止,是一個普通的用戶進(jìn)程,但以超級用戶特權(quán)運(yùn)行。
  • ID為2的進(jìn)程是頁守護(hù)進(jìn)程,負(fù)責(zé)支持虛擬存儲器系統(tǒng)的分頁操作。
#include <unistd.h>pid_t getpid(void); Returns: PRocess ID of calling processpid_t getppid(void); Returns: parent process ID of calling processuid_t getuid(void); Returns: real user ID of calling processuid_t geteuid(void); Returns: effective user ID of calling processgid_t getgid(void); Returns: real group ID of calling processgid_t getegid(void); Returns: effective group ID of calling process
  • 注意:這些函數(shù)都沒有出錯返回。
2. 函數(shù)fork
  • fork函數(shù)被調(diào)用一次,返回兩次。子進(jìn)程中返回值是0,父進(jìn)程中返回值是子進(jìn)程的pid
  • 子進(jìn)程是父進(jìn)程的副本,子進(jìn)程獲得父進(jìn)程的數(shù)據(jù)空間、堆和棧的副本。注意,在是子進(jìn)程擁有的副本。父子進(jìn)程并不共享這些存儲空間部分。父子進(jìn)程共享正文段。
  • 由于在fork之后經(jīng)常跟隨著exec,所以現(xiàn)在的很多實(shí)現(xiàn)并不執(zhí)行一個父進(jìn)程數(shù)據(jù)段、堆和棧的完全副本。作為替代,使用了寫時復(fù)制技術(shù)。
  • 4種平臺都支持的變體:vfork;linux的變體:clone系統(tǒng)調(diào)用,允許調(diào)用者控制哪些部分由父子進(jìn)程共享。
  • fork之后是父進(jìn)程先執(zhí)行還是子進(jìn)程先執(zhí)行是不確定的
  • 父進(jìn)程中的所有打開文件描述符都被復(fù)制到子進(jìn)程中,父子進(jìn)程為每個相同的打開描述符共享一個文件表項(xiàng),故共享同一文件偏移量。如果父子進(jìn)程寫同一描述符執(zhí)行的文件,又沒有任何形式的同步,那么它們的輸出就會混合。
  • 在fork之后處理文件描述符有以下兩種常見的情況:
    1. 父進(jìn)程等待子進(jìn)程完成。這種情況下,父進(jìn)程無需對其描述符做任何處理。
    2. 父進(jìn)程和子進(jìn)程各自執(zhí)行不同的程序段。這種情況下,fork之后,父子進(jìn)程各自它們不需要使用的文件描述符。
  • strlen和sizeof的區(qū)別:前者不包括null字節(jié),一次函數(shù)調(diào)用;后者包括null字節(jié),編譯時計(jì)算

  • 除了文件描述符之外,父進(jìn)程的很多其他屬性也由子進(jìn)程繼承,包括:

    1. 實(shí)際用戶ID、實(shí)際組ID、有效用戶ID、有效組ID
    2. 附屬組ID
    3. 進(jìn)程組ID
    4. 會話ID
    5. 控制終端
    6. SUID和SGID標(biāo)志(stat結(jié)構(gòu)的st_mode成員)
    7. 當(dāng)前工作目錄
    8. 根目錄
    9. 文件模式創(chuàng)建屏蔽字umask
    10. 信號屏蔽和處理
    11. 對任一打開文件描述符的執(zhí)行時關(guān)閉(close-on-exec)標(biāo)志
    12. 環(huán)境
    13. 連接的共享存儲段
    14. 存儲映像
    15. 資源限制
    16. 是否繼承nice值由具體實(shí)現(xiàn)自行決定
  • 父進(jìn)程和子進(jìn)程之間的區(qū)別具體如下:

    1. fork的返回值不同
    2. pid不同
    3. 這兩個進(jìn)程的父進(jìn)程不同
    4. 子進(jìn)程的tms_utime、tms_stime、tms_cutime和tms_ustime的值設(shè)置為0
    5. 子進(jìn)程不繼承父進(jìn)程設(shè)置的文件鎖
    6. 子進(jìn)程的未處理鬧鐘被清除
    7. 子進(jìn)程的未處理信號集設(shè)置為空集
  • fork失敗的兩個主要原因:

    1. 系統(tǒng)中已經(jīng)有了太多的進(jìn)程
    2. 該實(shí)際用戶ID的進(jìn)程總數(shù)超過了系統(tǒng)限制
  • fork有以下兩種用法:

    1. 一個父進(jìn)程希望復(fù)制自己,使父進(jìn)程和子進(jìn)程同時執(zhí)行不同的代碼段。這在網(wǎng)絡(luò)服務(wù)器中是常見的。
    2. 一個進(jìn)程要執(zhí)行一個不同的程序。這對shell是常見的情況。某些系統(tǒng)將fork+exec組合成一個操作spawn
3. 函數(shù)vfork
  • vfork函數(shù)的調(diào)用序列和返回值與fork相同,但兩者的語義不同:
    1. vfork函數(shù)用于創(chuàng)建一個新進(jìn)程,而該新進(jìn)程的目的是exec一個新程序,故不將父進(jìn)程的地址空間完全復(fù)制到子進(jìn)程中,因?yàn)樽舆M(jìn)程會立即調(diào)用exec(或exit),于是也就不會引用該地址空間。不管在子進(jìn)程調(diào)用exec或exit之前,它在父進(jìn)程的空間中運(yùn)行。
    2. 另一個區(qū)別是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)致死鎖。
4. 函數(shù)exit
  • 5種正常終止方式:
    1. 從main中執(zhí)行return,等效于調(diào)用exit
    2. 調(diào)用exit函數(shù),調(diào)用各終止處理程序,關(guān)閉標(biāo)準(zhǔn)I/O流,最后調(diào)用_exit函數(shù)
    3. 調(diào)用_exit或_Exit
    4. 進(jìn)程的最后一個線程在其啟動例程執(zhí)行return語句,該進(jìn)程以終止?fàn)顟B(tài)0返回
    5. 進(jìn)程的最后一個線程調(diào)用pthread_exit,進(jìn)程終止?fàn)顟B(tài)總是0
  • 3種異常終止方式:
    1. 調(diào)用abort,它產(chǎn)生SIGABRT信號
    2. 當(dāng)進(jìn)程接收到某些信號時,信號可由進(jìn)程自身(如調(diào)用abort函數(shù))、其他進(jìn)程或內(nèi)核產(chǎn)生
    3. 最后一個線程對“取消”請求做出響應(yīng)
  • 不管進(jìn)程如何終止,最后都會執(zhí)行內(nèi)核中的同一段代碼。這段代碼為相應(yīng)的進(jìn)程關(guān)閉所有打開描述符,釋放它所使用的存儲器等。
  • 注意:“退出狀態(tài)”(3個exit函數(shù)的參數(shù)或main的返回值)區(qū)別于“終止?fàn)顟B(tài)”。在最后調(diào)用_exit時,內(nèi)核將退出狀態(tài)轉(zhuǎn)換為終止?fàn)顟B(tài)。

  • 如果父進(jìn)程在子進(jìn)程之前終止,則稱子進(jìn)程為孤兒進(jìn)程。子進(jìn)程 ppid變?yōu)?,稱這些進(jìn)程由init進(jìn)程收養(yǎng)。一個init進(jìn)程收養(yǎng)的進(jìn)程終止時,init會調(diào)用一個wait函數(shù)取得其終止?fàn)顟B(tài),防止它成為僵尸進(jìn)程。

  • 如果子進(jìn)程在父進(jìn)程之前終止,內(nèi)核為每個終止子進(jìn)程保存了一定量的信息,至少包括pid、該進(jìn)程的終止?fàn)顟B(tài)以及該進(jìn)程使用的CPU時間總量。內(nèi)核可以釋放終止進(jìn)程所使用的所有存儲區(qū),關(guān)閉其所有打開文件。在Unix術(shù)語中,一個已經(jīng)終止、但其父進(jìn)程尚未對其進(jìn)行善后處理(獲取終止子進(jìn)程的有關(guān)信息、釋放它仍占用的資源)的進(jìn)程被稱為僵尸進(jìn)程zombie/defunct。
5. 函數(shù)wait、waitpid
  • 當(dāng)一個進(jìn)程正常或異常終止時,內(nèi)核就向其父進(jìn)程發(fā)送SIGCHLD信號。子進(jìn)程終止是異步事件。
#include <sys/wait.h>pid_t wait(int *statloc);pid_t waitpid(pid_t pid, int *statloc, int options); Both return: process ID if OK, 0 (see later), or −1 on error
  • 調(diào)用wait或waitpid的進(jìn)程可能:
    1. 如果其所有子進(jìn)程都還在運(yùn)行,則阻塞
    2. 如果一個子進(jìn)程終止,正等待其父進(jìn)程獲取其終止?fàn)顟B(tài),則取得該子進(jìn)程的終止?fàn)顟B(tài)立即返回
    3. 如果它沒有任何子進(jìn)程,則立即出錯返回
  • 如果進(jìn)程由于收到SIGCHLD信號而調(diào)用wait,我們期望wait會立即返回。
  • wait與waitpid的區(qū)別
    1. waitpid有一選項(xiàng),可使調(diào)用者不阻塞
    2. waitpid可以控制它所等待的進(jìn)程
  • 若statloc不是NULL,則終止進(jìn)程的終止?fàn)顟B(tài)就存放在它所指向的單元內(nèi)。該整型狀態(tài)字由實(shí)現(xiàn)定義,其中某些位表示退出狀態(tài)(正常返回),其他位則指示信號編號(異常返回),有一位指示是否產(chǎn)生了core文件。

  • waitpid函數(shù)中的pid參數(shù)的解釋:

    pid == -1,等待任一子進(jìn)程,等價于wait函數(shù)pid > 0,等待pid等于該值的子進(jìn)程pid == 0,等待組ID等于調(diào)用進(jìn)程組ID的任一子進(jìn)程pid < 0,等待組ID等于pid絕對值的任一子進(jìn)程

  • waitpid函數(shù)中的options參數(shù):WNOHANG(不阻塞)、WCONTINUED、WUNTRACED

  • 如果一個進(jìn)程fork一個子進(jìn)程,但不要它等待子進(jìn)程終止,也不希望子進(jìn)程處于僵尸狀態(tài)直到父進(jìn)程終止,實(shí)現(xiàn)這一要求的訣竅是調(diào)用fork兩次。

#include "apue.h"#include <sys/wait.h>int main(void){ pid_t pid; if ((pid = fork()) < 0) {        err_sys("fork error"); } else if (pid == 0) { /* first child */ if ((pid = fork()) < 0)            err_sys("fork error"); else if (pid > 0)            exit(0); /* parent from second fork == first child *//** We’re the second child; our parent becomes init as soon* as our real parent calls exit() in the statement above.* Here’s where we’d continue executing, knowing that when* we’re done, init will reap our status.*/    sleep(2);    printf("second child, parent pid = %ld/n", (long)getppid());    exit(0);

發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 左贡县| 微博| 仁布县| 攀枝花市| 进贤县| 衡阳县| 资溪县| 绍兴市| 沅江市| 江华| 高青县| 商丘市| 成武县| 安福县| 郯城县| 灌云县| 蒙城县| 阜南县| 成安县| 达尔| 阜阳市| 浠水县| 屏东市| 凤凰县| 天祝| 城固县| 沽源县| 德安县| 苍南县| 商水县| 江都市| 高尔夫| 璧山县| 腾冲县| 大厂| 鄱阳县| 南乐县| 内黄县| 应城市| 巴马| 普定县|