亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > Linux Shell > 正文

Linux啟動新進程的幾種方法及比較

2020-07-27 18:55:14
字體:
來源:轉載
供稿:網友

有時候,我們需要在自己的程序(進程)中啟動另一個程序(進程)來幫助我們完成一些工作,那么我們需要怎么才能在自己的進程中啟動其他的進程呢?在Linux中提供了不少的方法來實現這一點,下面就來介紹一個這些方法及它們之間的區別。

一、system函數調用

system函數的原型為:

#include <stdlib.h> int system (const char *string); 

它的作用是,運行以字符串參數的形式傳遞給它的命令并等待該命令的完成。命令的執行情況就如同在shell中執行命令:sh -c string。如果無法啟動shell來運行這個命令,system函數返回錯誤代碼127;如果是其他錯誤,則返回-1。否則,system函數將返回該命令的退出碼。

注意:system函數調用用一個shell來啟動想要執行的程序,所以可以把這個程序放到后臺中執行,這里system函數調用會立即返回。

可以先先下面的例子,源文件為new_ps_system.c,代碼如下:

#include <stdlib.h> #include <stdio.h> int main() {   printf("Running ps with system/n");   //ps進程結束后才返回,才能繼續執行下面的代碼   system("ps au");// 1   printf("ps Done/n");   exit(0); } 

該程序調用ps程序打印所有與本用戶有關的進程,最后才打印ps Done。運行結果如下:

如果把注釋1的語句改為:system("ps au &");則system函數立即返回,不用等待ps進程結束即可執行下面的代碼。所以你看到的輸出,ps Done可能并不是出現在最后一行,而是在中間。

一般來說,使用system函數不是啟動其他進程的理想手段,因為它必須用一個shell來啟動需要的程序,即在啟動程序之前需要先啟動一個shell,而且對shell的環境的依賴也很大,因此使用system函數的效率不高。

二、替換進程映像――使用exec系列函數

exec系列函數由一組相關的函數組成,它們在進程的啟動方式和程序參數的表達方式上各有不同。但是exec系列函數都有一個共同的工作方式,就是把當前進程替換為一個新進程,也就是說你可以使用exec函數將程序的執行從一個程序切換到另一個程序,在新的程序啟動后,原來的程序就不再執行了,新進程由path或file參數指定。exec函數比system函數更有效。

exec系列函數的類型為:

#include <unistd.h> char **environ; int execl (const char *path, const char *arg0, ..., (char*)0); int execlp(const char *file, const char *arg0, ..., (char*)0); int execle(const char *path, const char *arg0, ..., (char*)0, char *const envp[]); int execv (const char *path, char *const argv[]); int execvp(cosnt char *file, char *const argv[]); int execve(const char *path, char *const argv[], char *const envp[]); 

這類函數可以分為兩大類,execl、execlp和execle的參數是可變的,以一個空指針結束,而execv、execvp和execve的第二個參數是一個字符串數組,在調用新進程時,argv作為新進程的main函數的參數。而envp可作為新進程的環境變量,傳遞給新的進程,從而變量它可用的環境變量。

承接上一個例子,如果想用exec系統函數來啟動ps進程,則這6個不同的函數的調用語句為:

注:arg0為程序的名字,所以在這個例子中全為ps。

char *const ps_envp[] = {"PATH=/bin:usr/bin", "TERM=console", 0}; char *const ps_argv[] = {"ps", "au", 0};  execl("/bin/ps", "ps", "au", 0); execlp("ps", "ps", "au", 0); execle("/bin/ps", "ps", "au", 0, ps_envp);  execv("/bin/ps", ps_argv); execvp("ps", ps_argv); execve("/bin/ps", ps_argv, ps_envp); 

下面我給出一個完整的例子,源文件名為new_ps_exec.c,代碼如下:

#include <unistd.h> #include <stdio.h> #include <stdlib.h>  int main() {   printf("Running ps with execlp/n");   execlp("ps", "ps", "au", (char*)0);   printf("ps Done");   exit(0); } 

運行結果如下:

細心的話,可以發現,最后的ps Done并沒有輸出,這是偶然嗎?并不是,因為我們并沒有再一次返回到程序new_ps_exec.exe上,因為調用execlp函數時,new_ps_exec.exe進程被替換為ps進程,當ps進程結束后,整個程序就結束了,并沒有回到原來的new_ps_exec.exe進程上,原本的進程new_ps_exec.exe不會再執行,所以語句printf("ps Done");根本沒有機會執行。

注意,一般情況下,exec函數是不會返回的,除非發生錯誤返回-1,由exec啟動的新進程繼承了原進程的許多特性,在原進程中已打開的文件描述符在新進程中仍將保持打開,但任何在原進程中已打開的目錄流都將在新進程中被關閉。

三、復制進程映像――fork函數

1、fork函數的應用

exec調用用新的進程替換當前執行的進程,而我們也可以用fork來復制一個新的進程,新的進程幾乎與原進程一模一樣,執行的代碼也完全相同,但新進程有自己的數據空間、環境和文件描述符。

fork函數的原型為:

#include <sys/type.h> #include <unistd.h>  pid_t fork(); 

注:在父進程中,fork返回的是新的子進程的PID,子進程中的fork返回的是0,我們可以通過這一點來判斷父進程和子進程,如果fork調用失敗,它返回-1.

繼承上面的例子,下面我給出一個調用ps的例子,源文件名為new_ps_fork.c,代碼如下:

#include <unistd.h> #include <sys/types.h> #include <stdio.h> #include <stdlib.h> int main() {   pid_t pid = fork();   switch(pid)   {   case -1:     perror("fork failed");     exit(1);     break;   case 0:     //這是在子進程中,調用execlp切換為ps進程     printf("/n");     execlp("ps", "ps", "au", 0);     break;   default:     //這是在父進程中,輸出相關提示信息     printf("Parent, ps Done/n");     break;   }   exit(0); } 

輸出結果為:

我們可以看到,之前在第二點中沒有出現的ps Done是打印出來了,但是順序卻有點不對,這是因為,父進程先于子程序執行,所以先輸出了Parent, ps Done,那有沒有辦法讓它在子進程輸出完之后再輸出,當然有,就是用wait和waitpid函數。注意,一般情況下,父進程與子進程的生命周期是沒有關系的,即便父進程退出了,子進程仍然可以正常運行。

2、等待一個進程

wait函數和waitpid函數的原型為:

#include <sys/types.h> #include <sys/wait.h>  pid_t wait(int *stat_loc); pid_t waitpid(pid_t pid, int *stat_loc, int options); 

wait用于在父進程中調用,讓父進程暫停執行等待子進程的結束,返回子進程的PID,如果stat_loc不是空指針,狀態信息將被寫入stat_loc指向的位置。

waitpid等待進程id為pid的子進程的結束(pid為-1,將返回任一子進程的信息),stat_loc參數的作用與wait函數相同,options用于改變waitpid的行為,其中有一個很重要的選項WNOHANG,它的作用是防止waippid調用者的執行掛起。如果子進程沒有結束或意外終止,它返回0,否則返回子進程的pid。

改變后的程序保存為源文件new_ps_fork2.c,代碼如下:

#include <unistd.h> #include <sys/types.h> #include <stdio.h> #include <stdlib.h>  int main() {   pid_t pid = fork();   int stat = 0;   switch(pid)   {   case -1:     perror("fork failed");     exit(1);     break;   case 0:     //這是在子進程中,調用execlp切換為ps進程     printf("/n");     execlp("ps", "ps", "au", 0);     break;   default:     //這是在父進程中,等待子進程結束并輸出相關提示信息     pid = wait(&stat);     printf("Child has finished: PID = %d/n", pid);     //檢查子進程的退出狀態     if(WIFEXITED(stat))       printf("Child exited with code %d/n", WEXITSTATUS(stat));     else       printf("Child terminated abnormally/n");     printf("Parent, ps Done/n");     break;   }   exit(0); } 

輸出為:

可以看到這次的輸出終于正常了,Parent的輸出也在子進程的輸出之后。

總結――三種啟動新進程方法的比較

首先是最簡單的system函數,它需要啟動新的shell并在新的shell是執行子進程,所以對環境的依賴較大,而且效率也不高。同時system函數要等待子進程的返回才能執行下面的語句。

exec系統函數是用新的進程來替換原先的進程,效率較高,但是它不會返回到原先的進程,也就是說在exec函數后面的所以代碼都不會被執行,除非exec調用失敗。然而exec啟動的新進程繼承了原進程的許多特性,在原進程中已打開的文件描述符在新進程中仍將保持打開,但需要注意,任何在原進程中已打開的目錄流都將在新進程中被關閉。

fork則是用當前的進程來復制出一個新的進程,新進程與原進程一模一樣,執行的代碼也完全相同,但新進程有自己的數據空間、環境變量和文件描述符,我們通常根據fork函數的返回值來確定當前的進程是子進程還是父進程,即它并不像exec那樣并不返回,而是返回一個pid_t的值用于判斷,我們還可以繼續執行fork后面的代碼。感覺用fork與exec系列函數就能創建很多需的進程。

以上就是本文的全部內容,希望本文的內容對大家的學習或者工作能帶來一定的幫助,同時也希望多多支持武林網!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
中文字幕欧美精品日韩中文字幕| 国产一区二区三区免费视频| 国产精品美女久久| 国产精品xxx视频| 91网站在线免费观看| 精品国产91久久久久久| 欧美大尺度在线观看| 欧美成人一二三| 美女精品视频一区| 亚洲精品成人av| 97精品国产aⅴ7777| 日韩精品电影网| 欧美影院在线播放| 国产精品久久久久77777| 91精品国产91久久久久久久久| 亚洲欧美资源在线| 2019中文字幕全在线观看| 久久国产精品久久久| 欧洲精品毛片网站| 性色av一区二区三区红粉影视| 国产精品香蕉av| 欧美激情第一页xxx| 欧美日韩人人澡狠狠躁视频| 黑人巨大精品欧美一区二区一视频| 在线精品国产成人综合| 欧美视频中文字幕在线| 欧美成在线视频| 亚洲女人天堂成人av在线| 主播福利视频一区| 一本色道久久综合狠狠躁篇的优点| 久久精品国产免费观看| 日韩欧美亚洲综合| 黑人巨大精品欧美一区免费视频| 欧美精品成人91久久久久久久| 精品久久久久久久大神国产| 一区二区三区www| 国产一区二区三区视频| 国产美女精彩久久| 热re99久久精品国产66热| 精品高清美女精品国产区| 久久欧美在线电影| 日韩欧美在线网址| 亚洲性视频网站| 亚洲国产91精品在线观看| 欧美视频在线免费看| 91成人国产在线观看| 欧美性极品xxxx娇小| 国产精品九九久久久久久久| 亚洲男人av电影| 国产精品欧美激情在线播放| 久久久www成人免费精品张筱雨| 久久久久久午夜| 精品视频在线播放色网色视频| 日本成人在线视频网址| 国产玖玖精品视频| 亚洲九九九在线观看| 国产日韩欧美另类| xvideos亚洲人网站| 国产精品影院在线观看| 91国产一区在线| 国产成人精品一区二区| 久久视频在线观看免费| 亚洲一区精品电影| 九九九热精品免费视频观看网站| 亚洲天堂成人在线视频| 国产婷婷色综合av蜜臀av| 日韩一区二区精品视频| 日本韩国在线不卡| 日韩av在线天堂网| xx视频.9999.com| 国产日本欧美视频| 精品少妇v888av| 成人午夜激情免费视频| 欧美亚洲午夜视频在线观看| 日韩中文字幕精品视频| 在线观看国产精品日韩av| 国产日韩欧美夫妻视频在线观看| 91丝袜美腿美女视频网站| 欧美国产日韩一区二区三区| 91色琪琪电影亚洲精品久久| 欧美一级电影免费在线观看| 久久成人国产精品| 欧美性受xxxx黑人猛交| 日韩激情片免费| 亚洲图片在线综合| 最近2019中文免费高清视频观看www99| 国外成人免费在线播放| 亚洲综合色激情五月| 国产成人精品久久亚洲高清不卡| 主播福利视频一区| 热久久美女精品天天吊色| 欧美日韩久久久久| 国内精品久久久久| 国产成人亚洲综合91| 日韩中文在线中文网三级| 亚洲黄一区二区| 91wwwcom在线观看| 国产亚洲欧美aaaa| 最近2019年手机中文字幕| 国产成人亚洲综合91| 日韩在线一区二区三区免费视频| 一本久久综合亚洲鲁鲁| 日本aⅴ大伊香蕉精品视频| 色偷偷av一区二区三区| 午夜精品一区二区三区在线播放| 成人国产精品一区二区| 中文字幕在线亚洲| 亚洲精品美女网站| 日韩欧美在线免费观看| 疯狂蹂躏欧美一区二区精品| 91成人免费观看网站| 欧美在线观看网站| 性欧美视频videos6一9| 中文字幕成人在线| 精品激情国产视频| 亚洲一级免费视频| 亚洲自拍另类欧美丝袜| 日韩欧美极品在线观看| 精品偷拍各种wc美女嘘嘘| 亚洲视频在线观看免费| 免费av在线一区| 亚洲精品电影网| 亚洲精品一区二区久| 国产精品久久久久久久久久东京| 欧美成人小视频| 国产精品日韩在线| 91精品视频在线播放| 国产精品电影久久久久电影网| 精品亚洲一区二区三区在线播放| 97在线看福利| 92国产精品久久久久首页| 中文字幕久热精品视频在线| 亚洲免费伊人电影在线观看av| 欧美极品美女视频网站在线观看免费| 欧美午夜女人视频在线| 久久精品一区中文字幕| 国产成人啪精品视频免费网| 久久精品人人做人人爽| 国产热re99久久6国产精品| 疯狂蹂躏欧美一区二区精品| 欧美精品免费在线观看| 久久久伊人日本| 国产欧美最新羞羞视频在线观看| 日韩精品在线免费| 久久久久久久久久久久久久久久久久av| 国产精品久久久久久久av大片| 欧美激情aaaa| www日韩中文字幕在线看| 91高清视频在线免费观看| 色综合久久久久久中文网| 成人在线国产精品| 日韩av网站在线| 欧美国产在线视频| 亚洲最大的网站| 国产精品极品美女在线观看免费| 精品亚洲男同gayvideo网站| 国模吧一区二区三区| 6080yy精品一区二区三区| 亚洲国产精久久久久久| 91精品国产91久久久久久久久| 欧美精品日韩三级| 国内精品久久久| 黑人巨大精品欧美一区二区三区| 亚洲欧洲偷拍精品|