#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
- 父進(jìn)程等待子進(jìn)程完成。這種情況下,父進(jìn)程無需對(duì)其描述符做任何處理。
- 父進(jìn)程和子進(jìn)程各自執(zhí)行不同的程序段。這種情況下,fork之后,父子進(jìn)程各自它們不需要使用的文件描述符。
strlen和sizeof的區(qū)別:前者不包括null字節(jié),一次函數(shù)調(diào)用;后者包括null字節(jié),編譯時(shí)計(jì)算
除了文件描述符之外,父進(jìn)程的很多其他屬性也由子進(jìn)程繼承,包括:
- 實(shí)際用戶ID、實(shí)際組ID、有效用戶ID、有效組ID
- 附屬組ID
- 進(jìn)程組ID
- 會(huì)話ID
- 控制終端
- SUID和SGID標(biāo)志(stat結(jié)構(gòu)的st_mode成員)
- 當(dāng)前工作目錄
- 根目錄
- 文件模式創(chuàng)建屏蔽字umask
- 信號(hào)屏蔽和處理
- 對(duì)任一打開文件描述符的執(zhí)行時(shí)關(guān)閉(close-on-exec)標(biāo)志
- 環(huán)境
- 連接的共享存儲(chǔ)段
- 存儲(chǔ)映像
- 資源限制
- 是否繼承nice值由具體實(shí)現(xiàn)自行決定
父進(jìn)程和子進(jìn)程之間的區(qū)別具體如下:
- fork的返回值不同
- pid不同
- 這兩個(gè)進(jìn)程的父進(jìn)程不同
- 子進(jìn)程的tms_utime、tms_stime、tms_cutime和tms_ustime的值設(shè)置為0
- 子進(jìn)程不繼承父進(jìn)程設(shè)置的文件鎖
- 子進(jìn)程的未處理鬧鐘被清除
- 子進(jìn)程的未處理信號(hào)集設(shè)置為空集
fork失敗的兩個(gè)主要原因:
- 系統(tǒng)中已經(jīng)有了太多的進(jìn)程
- 該實(shí)際用戶ID的進(jìn)程總數(shù)超過了系統(tǒng)限制
fork有以下兩種用法:
- 一個(gè)父進(jìn)程希望復(fù)制自己,使父進(jìn)程和子進(jìn)程同時(shí)執(zhí)行不同的代碼段。這在網(wǎng)絡(luò)服務(wù)器中是常見的。
- 一個(gè)進(jìn)程要執(zhí)行一個(gè)不同的程序。這對(duì)shell是常見的情況。某些系統(tǒng)將fork+exec組合成一個(gè)操作spawn
- vfork函數(shù)用于創(chuàng)建一個(gè)新進(jìn)程,而該新進(jìn)程的目的是exec一個(gè)新程序,故不將父進(jìn)程的地址空間完全復(fù)制到子進(jìn)程中,因?yàn)樽舆M(jìn)程會(huì)立即調(diào)用exec(或exit),于是也就不會(huì)引用該地址空間。不管在子進(jìn)程調(diào)用exec或exit之前,它在父進(jìn)程的空間中運(yùn)行。
- 另一個(gè)區(qū)別是vfork保證子進(jìn)程先運(yùn)行,在它調(diào)用exec或exit之后父進(jìn)程才可能被調(diào)度運(yùn)行。故如果在調(diào)用這兩個(gè)函數(shù)之前子進(jìn)程依賴于父進(jìn)程的進(jìn)一步動(dòng)作,則會(huì)導(dǎo)致死鎖。
正常終止方式:
- 從main中執(zhí)行return,等效于調(diào)用exit
- 調(diào)用exit函數(shù),調(diào)用各終止處理程序,關(guān)閉標(biāo)準(zhǔn)I/O流,最后調(diào)用_exit函數(shù)
- 調(diào)用_exit或_Exit
- 進(jìn)程的最后一個(gè)線程在其啟動(dòng)例程執(zhí)行return語句,該進(jìn)程以終止?fàn)顟B(tài)0返回
- 進(jìn)程的最后一個(gè)線程調(diào)用pthread_exit,進(jìn)程終止?fàn)顟B(tài)總是0
異常終止方式:
- 調(diào)用abort,它產(chǎn)生SIGABRT信號(hào)
- 當(dāng)進(jìn)程接收到某些信號(hào)時(shí),信號(hào)可由進(jìn)程自身(如調(diào)用abort函數(shù))、其他進(jìn)程或內(nèi)核產(chǎn)生
- 最后一個(gè)線程對(duì)“取消”請(qǐng)求做出響應(yīng)
注意:“退出狀態(tài)”(3個(gè)exit函數(shù)的參數(shù)或main的返回值)區(qū)別于“終止?fàn)顟B(tài)”。在最后調(diào)用_exit時(shí),內(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)。一個(gè)init進(jìn)程收養(yǎng)的進(jìn)程終止時(shí),init會(huì)調(diào)用一個(gè)wait函數(shù)取得其終止?fàn)顟B(tài),防止它成為僵尸進(jìn)程。
僵尸進(jìn)程zombie/defunct。#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
- 如果其所有子進(jìn)程都還在運(yùn)行,則阻塞
- 如果一個(gè)子進(jìn)程終止,正等待其父進(jìn)程獲取其終止?fàn)顟B(tài),則取得該子進(jìn)程的終止?fàn)顟B(tài)立即返回
- 如果它沒有任何子進(jìn)程,則立即出錯(cuò)返回
- waitpid有一選項(xiàng),可使調(diào)用者不阻塞
- waitpid可以控制它所等待的進(jìn)程
若statloc不是NULL,則終止進(jìn)程的終止?fàn)顟B(tài)就存放在它所指向的單元內(nèi)。該整型狀態(tài)字由實(shí)現(xiàn)定義,其中某些位表示退出狀態(tài)(正常返回),其他位則指示信號(hào)編號(hào)(異常返回),有一位指示是否產(chǎn)生了core文件。

waitpid函數(shù)中的pid參數(shù)的解釋:
pid == -1,等待任一子進(jìn)程,等價(jià)于wait函數(shù)pid > 0,等待pid等于該值的子進(jìn)程pid == 0,等待組ID等于調(diào)用進(jìn)程組ID的任一子進(jìn)程pid < 0,等待組ID等于pid絕對(duì)值的任一子進(jìn)程
waitpid函數(shù)中的options參數(shù):WNOHANG(不阻塞)、WCONTINUED、WUNTRACED
如果一個(gè)進(jìn)程fork一個(gè)子進(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);
新聞熱點(diǎn)
疑難解答
圖片精選