最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Linux 創(chuàng)建子進程執(zhí)行任務的實現(xiàn)方法

 更新時間:2018年01月11日 09:37:06   作者:sparkdev  
下面小編就為大家分享一篇Linux 創(chuàng)建子進程執(zhí)行任務的實現(xiàn)方法,具有很好的參考價值,希望對大家有所幫助,一起跟隨小編過來看看吧

Linux 操作系統(tǒng)緊緊依賴進程創(chuàng)建來滿足用戶的需求。例如,只要用戶輸入一條命令,shell 進程就創(chuàng)建一個新進程,新進程運行 shell 的另一個拷貝并執(zhí)行用戶輸入的命令。Linux 系統(tǒng)中通過 fork/vfork 系統(tǒng)調(diào)用來創(chuàng)建新進程。本文將介紹如何使用 fork/vfork 系統(tǒng)調(diào)用來創(chuàng)建新進程并使用 exec 族函數(shù)在新進程中執(zhí)行任務。

fork 系統(tǒng)調(diào)用

要創(chuàng)建一個進程,最基本的系統(tǒng)調(diào)用是 fork:

# include <unistd.h>
pid_t fork(void);
pid_t vfork(void);

調(diào)用 fork 時,系統(tǒng)將創(chuàng)建一個與當前進程相同的新進程。通常將原有的進程稱為父進程,把新創(chuàng)建的進程稱為子進程。子進程是父進程的一個拷貝,子進程獲得同父進程相同的數(shù)據(jù),但是同父進程使用不同的數(shù)據(jù)段和堆棧段。子進程從父進程繼承大多數(shù)的屬性,但是也修改一些屬性,下表對比了父子進程間的屬性差異:

繼承屬性 差異
uid,gid,euid,egid 進程 ID
進程組 ID 父進程 ID
SESSION ID 子進程運行時間記錄
所打開文件及文件的偏移量 父進程對文件的鎖定
控制終端
設置用戶 ID 和 設置組 ID 標記位
根目錄與當前目錄
文件默認創(chuàng)建的權限掩碼
可訪問的內(nèi)存區(qū)段
環(huán)境變量及其它資源分配

下面是一個常見的演示 fork 工作原理的 demo(筆者的環(huán)境為 Ubuntu 16.04 desktop):

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
 pid_t pid;
 char *message;
 int n;
 pid = fork();
 if(pid < 0)
 {
  perror("fork failed");
  exit(1);
 }
 if(pid == 0)
 {
  printf("This is the child process. My PID is: %d. My PPID is: %d.\n", getpid(), getppid());
 }
 else
 {
  printf("This is the parent process. My PID is %d.\n", getpid());
 }
 return 0;
}

把上面的代碼保存到文件 forkdemo.c 文件中,并執(zhí)行下面的命令編譯:

$ gcc forkdemo.c -o forkdemo

然后運行編譯出來的 forkdemo 程序:

$ ./forkdemo

fork 函數(shù)的特點是 "調(diào)用一次,返回兩次":在父進程中調(diào)用一次,在父進程和子進程中各返回一次。在父進程中返回時的返回值為子進程的 PID,而在子進程中返回時的返回值為 0,并且返回后都將執(zhí)行 fork 函數(shù)調(diào)用之后的語句。如果 fork 函數(shù)調(diào)用失敗,則返回值為 -1。
我們細想會發(fā)現(xiàn),fork 函數(shù)的返回值設計還是很高明的。在子進程中 fork 函數(shù)返回 0,那么子進程仍然可以調(diào)用 getpid 函數(shù)得到自己的 PID,也可以調(diào)用 getppid 函數(shù)得到父進程 PID。在父進程中用 getpid 函數(shù)可以得到自己的 PID,如果想得到子進程的PID,唯一的辦法就是把 fork 函數(shù)的返回值記錄下來。
注意:執(zhí)行 forkdemo 程序時的輸出是會發(fā)生變化的,可能先打印父進程的信息,也可能先打印子進程的信息。

vfork 系統(tǒng)調(diào)用

vfork 系統(tǒng)調(diào)用和 fork 系統(tǒng)調(diào)用的功能基本相同。vfork 系統(tǒng)調(diào)用創(chuàng)建的進程共享其父進程的內(nèi)存地址空間,但是并不完全復制父進程的數(shù)據(jù)段,而是和父進程共享其數(shù)據(jù)段。為了防止父進程重寫子進程需要的數(shù)據(jù),父進程會被 vfork 調(diào)用阻塞,直到子進程退出或執(zhí)行一個新的程序。由于調(diào)用 vfork 函數(shù)時父進程被掛起,所以如果我們使用 vfork 函數(shù)替換 forkdemo 中的 fork 函數(shù),那么執(zhí)行程序時輸出信息的順序就不會變化了。

使用 vfork 創(chuàng)建的子進程一般會通過 exec 族函數(shù)執(zhí)行新的程序。接下來讓我們先了解下 exec 族函數(shù)。

exec 族函數(shù)

使用 fork/vfork 創(chuàng)建子進程后執(zhí)行的是和父進程相同的程序(但有可能執(zhí)行不同的代碼分支),子進程往往需要調(diào)用一個 exec 族函數(shù)以執(zhí)行另外一個程序。當進程調(diào)用 exec 族函數(shù)時,該進程的用戶空間代碼和數(shù)據(jù)完全被新程序替換,從新程序的起始處開始執(zhí)行。調(diào)用 exec 族函數(shù)并不創(chuàng)建新進程,所以調(diào)用 exec 族函數(shù)前后該進程的 PID 并不改變。

exec 族函數(shù)一共有六個:

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

函數(shù)名字中帶字母 "l" 的表示其參數(shù)個數(shù)不確定,帶字母 "v" 的表示使用字符串數(shù)組指針 argv 指向參數(shù)列表。
函數(shù)名字中含有字母 "p" 的表示可以自動在環(huán)境變量 PATH 指定的路徑中搜索要執(zhí)行的程序。
函數(shù)名字中含有字母 "e" 的函數(shù)比其它函數(shù)多一個參數(shù) envp。該參數(shù)是字符串數(shù)組指針,用于指定環(huán)境變量。調(diào)用這樣的函數(shù)時,可以由用戶自行設定子進程的環(huán)境變量,存放在參數(shù) envp 所指向的字符串數(shù)組中。

事實上,只有 execve 是真正的系統(tǒng)調(diào)用,其它五個函數(shù)最終都調(diào)用 execve。這些函數(shù)之間的關系如下圖所示(此圖來自互聯(lián)網(wǎng)):

exec 族函數(shù)的特征:調(diào)用 exec 族函數(shù)會把新的程序裝載到當前進程中。在調(diào)用過 exec 族函數(shù)后,進程中執(zhí)行的代碼就與之前完全不同了,所以 exec 函數(shù)調(diào)用之后的代碼是不會被執(zhí)行的。

在子進程中執(zhí)行任務

下面讓我們通過 vfork 和 execve 函數(shù)實現(xiàn)在子進程中執(zhí)行 ls 命令:

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
 pid_t pid;
 if((pid=vfork()) < 0)
 {
  printf("vfork error!\n");
  exit(1);
 }
 else if(pid==0)
 {
  printf("Child process PID: %d.\n", getpid());
  char *argv[ ]={"ls", "-al", "/home", NULL}; 
  char *envp[ ]={"PATH=/bin", NULL};
  if(execve("/bin/ls", argv, envp) < 0)
  {
   printf("subprocess error");
   exit(1);
  }
  // 子進程要么從 ls 命令中退出,要么從上面的 exit(1) 語句退出
  // 所以代碼的執(zhí)行路徑永遠也走不到這里,下面的 printf 語句不會被執(zhí)行
  printf("You should never see this message.");
 }
 else
 {
  printf("Parent process PID: %d.\n", getpid());
  sleep(1);
 }
 return 0;
}

把上面的代碼保存到文件 subprocessdemo.c 文件中,并執(zhí)行下面的命令編譯:

$ gcc subprocessdemo.c -o subprocessdemo

然后運行編譯出來的 subprocessdemo程序:

$ ./subprocessdemo

總結

fork/vfork 函數(shù)和 exec 族函數(shù)都是 Linux 系統(tǒng)中非常重要的概念。本文試圖通過簡單的 demo 來演示這些函數(shù)的基本用法,為理解 Linux 系統(tǒng)中父進程與子進程的概念提供一些直觀的感受。

相關文章

  • Ubuntu使用國內(nèi)源出現(xiàn)Hash Sum mismatch錯誤的解決

    Ubuntu使用國內(nèi)源出現(xiàn)Hash Sum mismatch錯誤的解決

    這篇文章主要介紹了Ubuntu使用國內(nèi)源出現(xiàn)Hash Sum mismatch錯誤的解決,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-04-04
  • 在Ubuntu 16.10安裝mysql workbench報未安裝軟件包 libpng12-0錯誤的解決方法

    在Ubuntu 16.10安裝mysql workbench報未安裝軟件包 libpng12-0錯誤的解決方法

    這篇文章主要介紹了在Ubuntu 16.10安裝mysql workbench報未安裝軟件包 libpng12-0錯誤的解決方法的相關資料,需要的朋友可以參考下
    2016-11-11
  • linux系統(tǒng)安裝zookeeper 服務的方法

    linux系統(tǒng)安裝zookeeper 服務的方法

    這篇文章主要介紹了linux 系統(tǒng)安裝zookeeper 服務的方法,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-11-11
  • VMware 12 下 Ubuntu 16.04 安裝圖文教程

    VMware 12 下 Ubuntu 16.04 安裝圖文教程

    這篇文章主要為大家詳細介紹了VMware 12 下 Ubuntu 16.04 安裝圖文教程,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-06-06
  • Apache 認證總結

    Apache 認證總結

    經(jīng)常上網(wǎng)的讀者會遇到這種情況:訪問一些網(wǎng)站的某些資源時,瀏覽器彈出一個對話框,要求輸入用戶名和密碼來獲取對資源的訪問。
    2009-05-05
  • 詳解linux 下安裝軟件tar.gz, rpm,deb的方法

    詳解linux 下安裝軟件tar.gz, rpm,deb的方法

    本篇文章主要介紹了linux 下安裝軟件tar.gz, rpm,deb的方法 ,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2016-12-12
  • 詳解CentOS如何使用NTP同步時間服務器

    詳解CentOS如何使用NTP同步時間服務器

    在Linux系統(tǒng)中,時間同步對于各種應用是非常關鍵的,例如,系統(tǒng)日志和許多監(jiān)控應用程序都需要在多個服務器之間保持時間同步,NTP協(xié)議是一種常見的協(xié)議,它使得您可以在系統(tǒng)之間同步時間,下面我們將詳細討論CentOS如何使用NTP同步時間服務器,需要的朋友可以參考下
    2023-11-11
  • Apache 添加虛擬目錄注意事項

    Apache 添加虛擬目錄注意事項

    Apache 添加虛擬目錄注意事項,使用apache的朋友可以參考下。
    2011-08-08
  • deepin linux 手動升級內(nèi)核的方法

    deepin linux 手動升級內(nèi)核的方法

    這篇文章主要介紹了deepin linux 手動升級內(nèi)核的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-12-12
  • ubuntu15.10下hadoop2.7.2的安裝與配置詳解

    ubuntu15.10下hadoop2.7.2的安裝與配置詳解

    今天小編就為大家分享一篇關于ubuntu15.10下hadoop2.7.2的安裝與配置詳解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-02-02

最新評論

商洛市| 莫力| 樟树市| 大理市| 左权县| 新邵县| 惠来县| 宜阳县| 台州市| 江华| 贵德县| 宜君县| 荃湾区| 北京市| 迁西县| 宝丰县| 同德县| 抚宁县| 仙游县| 通辽市| 连江县| 舞钢市| 桂阳县| 正蓝旗| 九龙县| 萨嘎县| 扎囊县| 湟源县| 荔浦县| 洞头县| 临桂县| 吴旗县| 天峨县| 凤冈县| 马山县| 汶川县| 郸城县| 嘉善县| 寻乌县| 台北县| 海安县|