Linux多任务编程——进程
進(jìn)程編程常用函數(shù)
1--- fork
pitd_t fork(void);
創(chuàng)建一個(gè)新的子進(jìn)程,其父進(jìn)程為調(diào)用 fork() 函數(shù)的進(jìn)程;
返回值:成功:子進(jìn)程返回 0,父進(jìn)程返回 子進(jìn)程 PID;失敗 返回 -1;
*1>新創(chuàng)建的子進(jìn)程PID,與父進(jìn)程PID不同;
*2>子進(jìn)程 從 fork() 返回值開(kāi)始運(yùn)行,返回值為 0;父進(jìn)程 fork() 返回新創(chuàng)建的子線程 PID
?
2--- exec函數(shù)族???
?????? exec函數(shù)族的作用是根據(jù)指定的文件名找到可執(zhí)行文件,并用它來(lái)取代調(diào)用進(jìn)程的內(nèi)容,換句話說(shuō),就是在調(diào)用進(jìn)程內(nèi)部執(zhí)行一個(gè)可執(zhí)行文件。這里的可執(zhí)行文件既可以是二進(jìn)制文件,也可以是任何Linux下可執(zhí)行的腳本文件。
?????? 與一般情況不同,exec函數(shù)族的函數(shù)執(zhí)行成功后不會(huì)返回,因?yàn)檎{(diào)用進(jìn)程的實(shí)體,包括代碼段,數(shù)據(jù)段和堆棧等都已經(jīng)被新的內(nèi)容取代,只留下進(jìn)程ID等一些表面上的信息仍保持原樣,頗有些神似"三十六計(jì)"中的"金蟬脫殼"。看上去還是舊的軀殼,卻已經(jīng)注入了新的靈魂。只有調(diào)用失敗了,它們才會(huì)返回一個(gè)-1,從原程序的調(diào)用點(diǎn)接著往下執(zhí)行。
可以使用 fork 創(chuàng)建一個(gè)子進(jìn)程,在子進(jìn)程中進(jìn)行 exec 函數(shù)的調(diào)用 去完成某些比較危險(xiǎn)的操作。使用時(shí)一定要注意這一點(diǎn)。
exec家族一共有六個(gè)函數(shù),分別是:
(1)int execl(const char *path, const char *arg, ......);
(2)int execle(const char *path, const char *arg, ...... , char * const envp[]);
(3)int execv(const char *path, char *const argv[]);
(4)int execve(const char *filename, char *const argv[], char *const envp[]);
(5)int execvp(const char *file, char * const argv[]);
(6)int execlp(const char *file, const char *arg, ......);
其中只有execve是真正意義上的系統(tǒng)調(diào)用,其它都是在此基礎(chǔ)上經(jīng)過(guò)包裝的庫(kù)函數(shù)。
1 #include <stdio.h> 2 #include <unistd.h> 3 4 int main() 5 { 6 /*調(diào)用execlp函數(shù),相當(dāng)于調(diào)用了 “ps -ef”命令*/ 7 if(execlp("ps", "ps", "-ef", NULL) < 0) 8 { 9 perror("ececlp error!"); 10 } 11 return 0; 12 }它們之間的區(qū)別:
第一個(gè)區(qū)別是:
?????? 前四個(gè)取路徑名做為參數(shù),后兩個(gè)取文件名做為參數(shù),如果文件名中不包含 “/” 則從PATH環(huán)境變量中搜尋可執(zhí)行文件, 如果找到了一個(gè)可執(zhí)行文件,但是該文件不是連接編輯程序產(chǎn)生的可執(zhí)行代碼文件,則當(dāng)做shell腳本處理。
第二個(gè)區(qū)別:
?????? 前兩個(gè)和最后一個(gè)函數(shù)中都包括“ l ”這個(gè)字母 ,而另三個(gè)都包括“ v ”, " l "代表 list即表 ,而" v "代表 vector即矢量,也是是前三個(gè)函數(shù)的參數(shù)都是以list的形式給出的,但最后要加一個(gè)空指針,如果用常數(shù)0來(lái)表示空指針,則必須將它強(qiáng)行轉(zhuǎn)換成字符指針,否則有可能出錯(cuò)。,而后三個(gè)都是以矢量的形式給出,即數(shù)組。
最后一個(gè)區(qū)別:
????? 與向新程序傳遞環(huán)境變量有關(guān),如第二個(gè)和第四個(gè)以e結(jié)尾的函數(shù),可以向函數(shù)傳遞一個(gè)指向環(huán)境字符串指針數(shù)組的指針。即自個(gè)定義各個(gè)環(huán)境變量,而其它四個(gè)則使用進(jìn)程中的環(huán)境變量。
?
3--- exit( ) 和 _exit( )
exit( )是標(biāo)準(zhǔn)庫(kù)函數(shù)(Standard library)
_exit( ) 時(shí)系統(tǒng)調(diào)用函數(shù)(system call)
exit( ) 和 _exit( ) 都是用來(lái)終止進(jìn)程的。當(dāng)程序執(zhí)行到 exit( )或 _exit( )時(shí),進(jìn)程會(huì)無(wú)條件地停止剩下的所有操作,清除各種數(shù)據(jù)結(jié)構(gòu),并終止本進(jìn)程的運(yùn)行。但是這連個(gè)函數(shù)還是有區(qū)別的:
?
4--- wait( ) 和 waitpid( )
wait( )函數(shù)用于父進(jìn)程(也就是調(diào)用它的進(jìn)程)阻塞,直到一個(gè)子進(jìn)程結(jié)束,或者接到一個(gè)指定信號(hào)為止,如果父進(jìn)程沒(méi)有子進(jìn)程或者其他進(jìn)程的子進(jìn)程已經(jīng)結(jié)束,則wait( )會(huì)立即返回 -1;
waitpid( )的作用和wait( )一樣,但并不一定等待第一個(gè)終止的子進(jìn)程。waitpid( )有若干個(gè)選項(xiàng),可以提供一個(gè)非阻塞版本的wait()功能。
函數(shù)原型:
pid_t wait(int *status); status 指向的整型對(duì)象用來(lái)保存進(jìn)程結(jié)束時(shí)的狀態(tài)。另外,子進(jìn)程的結(jié)束狀態(tài)可由linux中一些特定的宏來(lái)測(cè)定。
返回值 成功:已回收子進(jìn)程的進(jìn)程號(hào)。 失敗: -1
pid_t waitpid(pid_t pid, int *status, int options);
pid: pid > 0: 回收進(jìn)程 ID 為 pid 的子進(jìn)程
pid = -1:回收任何一個(gè)子進(jìn)程,此時(shí)和 wait()功能一樣
?? pid = 0:回收其組 ID 等于調(diào)用進(jìn)程的 ID 的任一子進(jìn)程
pid?< -1:回收其組 ID 等于 pid 的絕對(duì)值的任一子進(jìn)程
status:同wait()
options:WNOHANG:若指定的子進(jìn)程沒(méi)有結(jié)束,則 waitpid()不阻塞而立即返回,此時(shí)返回值為 0
? WUNRTACED:為了實(shí)現(xiàn)某種操作,由pid 指定的任一子進(jìn)程已被暫停,但其狀態(tài)自暫停依賴還未報(bào)告過(guò),則返回其狀態(tài)
返回值:>0:已結(jié)束運(yùn)行的子進(jìn)程的進(jìn)程號(hào)
0:使用 WNOHANG 且沒(méi)有子進(jìn)程退出
-1:出錯(cuò)
?
5--- 守護(hù)進(jìn)程
守護(hù)進(jìn)程也就是通常所說(shuō)的Daemon進(jìn)程,他是 Linux 中的后臺(tái)服務(wù)進(jìn)程。 通常在系統(tǒng)啟動(dòng)時(shí)開(kāi)始執(zhí)行, 在系統(tǒng)關(guān)閉時(shí)終止。
編寫(xiě)守護(hù)進(jìn)程的步驟(5步):
(1) 創(chuàng)建子進(jìn)程,父進(jìn)程退出。
1 if (0 < pid = fork()) {2 exit(0); /*父進(jìn)程退出*/3 }?
(2) 在子進(jìn)程中創(chuàng)建新會(huì)話 (兩個(gè)新的概念:進(jìn)程組、會(huì)話期)
進(jìn)程組:一個(gè)或多個(gè)進(jìn)程的集合。有進(jìn)程組由進(jìn)程組 ID 來(lái)唯一標(biāo)識(shí)。除了進(jìn)程號(hào)(PID)之外,進(jìn)程組 ID 也是一個(gè)進(jìn)程的必備屬性。
會(huì)話:會(huì)話是一個(gè)或多個(gè)進(jìn)程組的集合。
pit_t setsid(void);? 成功:返回該進(jìn)程組 ID 出錯(cuò):返回 -1
用于創(chuàng)建一個(gè)新的會(huì)話,并擔(dān)任該會(huì)話組的組長(zhǎng)。調(diào)用 setsid() 有下面三個(gè)作用。
① 讓進(jìn)程擺脫原會(huì)話的控制 ② 讓進(jìn)程擺脫原進(jìn)程組的控制 ③ 讓進(jìn)程擺脫原控制終端的控制
(3) 改變當(dāng)前目錄
通常做法是讓 “/” (根目錄)作為守護(hù)進(jìn)程的工作目錄
(4) 重設(shè)文件權(quán)限掩碼
umask(); 是設(shè)置文件權(quán)限掩碼的函數(shù),通常的使用方法是 umask(0);
(5) 關(guān)閉文件描述符
1 int num;2 num = getdtablesize(); // 獲取當(dāng)前進(jìn)程文件描述表大小3 for (i = 0; i < num; i++)4 {5 close(i);6 }?
轉(zhuǎn)載于:https://www.cnblogs.com/chen-farsight/p/6020795.html
總結(jié)
以上是生活随笔為你收集整理的Linux多任务编程——进程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: parseInt(08)或parseIn
- 下一篇: Linux 下的常用工具