国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

Linux|Centos|Ubuntu|系統進程|Fedora|注冊表|Bios|Solaris|Windows7|Windows10|Windows11|windows server|

服務器之家 - 服務器系統 - Linux - Linux 創建子進程執行任務的實現方法

Linux 創建子進程執行任務的實現方法

2022-02-25 16:58sparkdev Linux

下面小編就為大家分享一篇Linux 創建子進程執行任務的實現方法,具有很好的參考價值,希望對大家有所幫助,一起跟隨小編過來看看吧

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

fork 系統調用

要創建一個進程,最基本的系統調用是 fork:

?
1
2
3
# include <unistd.h>
pid_t fork(void);
pid_t vfork(void);

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

 

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

 

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#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 文件中,并執行下面的命令編譯:

?
1
$ gcc forkdemo.c -o forkdemo

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

?
1
$ ./forkdemo

Linux 創建子進程執行任務的實現方法

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

vfork 系統調用

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

使用 vfork 創建的子進程一般會通過 exec 族函數執行新的程序。接下來讓我們先了解下 exec 族函數。

exec 族函數

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

exec 族函數一共有六個:

?
1
2
3
4
5
6
7
#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[]);

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

事實上,只有 execve 是真正的系統調用,其它五個函數最終都調用 execve。這些函數之間的關系如下圖所示(此圖來自互聯網):

Linux 創建子進程執行任務的實現方法

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

在子進程中執行任務

下面讓我們通過 vfork 和 execve 函數實現在子進程中執行 ls 命令:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#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) 語句退出
  // 所以代碼的執行路徑永遠也走不到這里,下面的 printf 語句不會被執行
  printf("you should never see this message.");
 }
 else
 {
  printf("parent process pid: %d.\n", getpid());
  sleep(1);
 }
 return 0;
}

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

?
1
$ gcc subprocessdemo.c -o subprocessdemo

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

?
1
$ ./subprocessdemo

Linux 創建子進程執行任務的實現方法

總結

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

原文鏈接:https://www.cnblogs.com/sparkdev/p/8214455.html

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 中文字幕亚洲欧美日韩在线不卡 | 亚洲欧美日韩精品 | 日本精品中文字幕 | 亚洲成人精选 | 人人人射 | 免费骚视频 | 亚洲一页 | 精品在线一区二区三区 | 久久天天 | 精品成人av| 国产日韩精品视频 | 欧美一区二区最爽乱淫视频免费看 | 国产高清亚洲 | 97国产一区二区精品久久呦 | 在线观看91 | 日韩不卡 | 污视频网站在线观看 | 日本一区二区在线视频 | 亚洲福利一区二区 | 欧美精品第一页 | 特黄特黄的视频 | 亚洲欧美视频 | 中文字幕不卡一区 | www.天天操 | 亚洲一视频 | 欧美视频一二三区 | 视频在线一区 | 亚洲精品视频一区二区三区 | 国产精品久久久久久一区 | 99re免费视频精品全部 | 久久综合欧美 | 亚洲国产欧美在线 | 精品第一页 | 亚州成人| 日韩视频在线观看 | 中文字幕国产在线视频 | 欧美日韩免费在线 | 国产精品久久久久久久久费观看 | 欧美午夜精品久久久久久人妖 | 一级一片免费视频 | 亚洲综合激情 |