一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

UNIX環(huán)境編程學習筆記(18)

 戴維圖書館 2018-06-28

lienhua34
2014-10-05

1 進程控制三部曲概述

UNIX 系統(tǒng)提供了 fork、exec、exit 和 wait 等基本的進程控制原語。通過這些進程控制原語,我們即可完成對進程創(chuàng)建、執(zhí)行和終止等基本操作。進程的控制可以劃分為三部曲,

· 第一部:fork 創(chuàng)建新進程。

· 第二部:exec 執(zhí)行新程序。

· 第三部:exit 和 wait 處理終止和等待終止。

2 第一部:fork 創(chuàng)建新進程

在一個現(xiàn)有的進程中,我們可以通過調(diào)用 fork 函數(shù)來創(chuàng)建一個新進程,

#include <unistd.h>
pid_t fork(void);
返回值:子進程中返回0,父進程中返回子進程ID,出錯則返回-1

由 fork 創(chuàng)建的新進程被稱為子進程。fork 函數(shù)調(diào)用一次,但返回兩次。兩次返回的唯一區(qū)別是:子進程返回值為 0,而父進程的返回值是新子進程的進程 ID。因為 UNIX 系統(tǒng)沒有提供一個函數(shù)以獲取某個進程的所有子進程 ID,所以父進程可以通過 fork 函數(shù)的返回值獲取其子進程的進程 ID,并進行后續(xù)的處理。而在子進程中,可以通過調(diào)用 getppid 函數(shù)獲取其父進程的進程 ID。

fork 函數(shù)返回之后,子進程和父進程都各自繼續(xù)執(zhí)行 fork 調(diào)用之后的指令。子進程是父進程的副本。例如,子進程獲得了父進程數(shù)據(jù)空間、堆和棧的副本。但是,父子進程共享正文段。

例子:

下面程序調(diào)用 fork 創(chuàng)建一個新進程,在父子進程中都分別打印當前進程 ID 和父進程 ID。

復制代碼
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
int
main(void)
{
    pid_t pid;
    printf("before fork\n");
    if ((pid = fork()) < 0) {
        printf("fork error: %s\n", strerror(errno));
        exit(-1);
     } else if (pid == 0) {
        printf("in child process, process ID: %d, parent process ID: %d\n", getpid(),  getppid());
    } else {
        printf("in parent process, process ID: %d, child process ID: %d\n", getpid(), pid);
        sleep(1);
    }
    exit(0);
}
復制代碼

編譯該程序,生成 forkdemo 文件,然后執(zhí)行該文件,

lienhua34:demo$ gcc -o forkdemo forkdemo.c
lienhua34:demo$ ./forkdemo
before fork
in parent process, process ID: 3499, child process ID: 3500
in child process, process ID: 3500, parent process ID: 3499

第二部:exec 執(zhí)行新程序

用 fork 函數(shù)創(chuàng)建子進程后,子進程往往要調(diào)用一種 exec 函數(shù)以執(zhí)行另一個程序。當進程調(diào)用一種 exec 函數(shù)時,該進程執(zhí)行的程序完全替換為新程序,而新程序則從其 main 函數(shù)開始執(zhí)行。調(diào)用 exec 并沒有創(chuàng)建新進程,所以進程 ID 沒有改變,exec 只是用一個新的程序替換了當前進程的正文、數(shù)據(jù)、堆和棧段。

UNIX 提供了 6 種不同的 exec 函數(shù)可供使用。我們在這里只說明其中的一種,

#include <unistd.h>
int execv(const char *pathname, char *const argv[]);
返回值:若出錯則返回-1,若成功則沒有返回值

其中 pathname 是進程要執(zhí)行的新程序文件的路徑,而 argv 參數(shù)則是要傳遞給新程序的參數(shù)列表。

例子:

我們有一個 sayhello.c 的程序文件,其代碼如下,

復制代碼
#include <stdio.h>
#include <stdlib.h>
int
main(void)
{
    printf("Hello World! process ID: %d\n", getpid());
    exit(0);
}
復制代碼

編譯 sayhello.c 程序,生成執(zhí)行文件 sayhello,

lienhua34:demo$ gcc -o sayhello sayhello.c
lienhua34:demo$ pwd
/home/lienhua34/program/c/apue/ch08/demo
lienhua34:demo$ ./sayhello
Hello World! process ID: 3545

在 execdemo.c 程序文件中,我們通過 fork 創(chuàng)建新進程,然后在子進程中調(diào)用 execv 函數(shù)執(zhí)行 sayhello 文件,其代碼如下,

復制代碼
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
char sayhelloPath[] = "/home/lienhua34/program/c/apue/ch08/demo/sayhello";
int
main(void)
{
    pid_t pid;
    if ((pid = fork()) < 0) {
        printf("fork error: %s\n", strerror(errno));
        exit(-1);
    } else if (pid == 0) {
        printf("in child process, process ID: %d, parent process ID: %d\n", getpid(), getppid());
        if (execv(sayhelloPath, NULL) < 0) {
            printf("execv error: %s\n", strerror(errno));
            exit(-1);
        }
    } else {
        printf("in parent process, process ID: %d, child process ID: %d\n", getpid(), pid);
        sleep(2);
    }
    exit(0);
}
復制代碼

編譯 execdemo.c 文件,生成并執(zhí)行 execdemo 文件,

lienhua34:demo$ gcc -o execdemo execdemo.c
lienhua34:demo$ ./execdemo
in parent process, process ID: 3561, child process ID: 3562
in child process, process ID: 3562, parent process ID: 3561
Hello World! process ID: 3562

從上面的運行結(jié)果可以看出,子進程(ID:3562)正常執(zhí)行 sayhello 文件。

4 第三部:exit 和 wait 處理終止和等待終止

exit 函數(shù)提供了進程終止的功能,在“進程終止”一文中,我們已經(jīng)學習了 exit 函數(shù)的基本知識。我們這里補充一下關(guān)于進程的終止狀態(tài)。在學習 exit 函數(shù)時,我們已經(jīng)知道 exit 函數(shù)的參數(shù)作為程序的退出狀態(tài)(exit status)。在進程終止時,內(nèi)核會將程序的退出狀態(tài)作為進程的終止狀態(tài)(termination status)。在進程異常終止的時候,內(nèi)核會產(chǎn)生一個指示其異常終止原因的終止狀態(tài)。無論進程是正常終止還是異常終止,該終止進程的父進程都可以通過 wait 或 waitpid 函數(shù)獲取其終止狀態(tài)。

在前面兩節(jié)中的 forkdemo.c 和 execdemo.c 程序中,fork 調(diào)用之后的父進程都調(diào)用了 sleep 函數(shù)休眠一下。這是因為,在調(diào)用 fork 函數(shù)之后是父進程先執(zhí)行還是子進程先執(zhí)行是不確定的。于是,我們在父進程中調(diào)用sleep 休眠一段時間,讓子進程先執(zhí)行結(jié)束(注:這樣子也不能確保)。

我們可以在父進程中調(diào)用 wait 來等待子進程結(jié)束,

#include <sys/wait.h>
pid_t wait(int *statloc);
返回值:若成功則返回進程ID,若出錯則返回-1

statloc 參數(shù)是一個整型指針。如果 statloc 不是一個空指針,則終止進程的終止狀態(tài)就存儲在該指針指向的內(nèi)存單元中。如果不關(guān)心終止狀態(tài),則可以將參數(shù)設置為 NULL。

進程調(diào)用 wait 會導致該調(diào)用者阻塞,直到某個子進程終止。如果調(diào)用wait 函數(shù)時,調(diào)用進程沒有任何子進程則立即出錯返回。

例子:

下面程序在上一節(jié)的 execdemo.c 基礎(chǔ)上,將 fork 之后父進程的 sleep語句替換成 wait 來等待子進程的結(jié)束。

復制代碼
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/wait.h>
char sayhelloPath[] = "/home/lienhua34/program/c/apue/ch08/demo/sayhello";
int
main(void)
{
    pid_t pid;
    int waitres;
    if ((pid = fork()) < 0) {
        printf("fork error: %s\n", strerror(errno));
        exit(-1);
    } else if (pid == 0) {
        printf("in child process, process ID: %d, parent process ID: %d\n", getpid(), getppid());
        if (execv(sayhelloPath, NULL) < 0) {
            printf("execv error: %s\n", strerror(errno));
            exit(-1);
       }
    } else {
        printf("in parent process, process ID: %d, child process ID: %d\n", getpid(), pid);
        if ((waitres = wait(NULL)) < 0) {
            printf("wait error: %s\n", strerror(errno));
            exit(-1);
        } else {
            printf("termination child process: %d\n", waitres);
        }
    }
    exit(0);
}
復制代碼

編譯該程序,生成并執(zhí)行 execdemo 文件,

復制代碼
lienhua34:demo$ gcc -o execdemo execdemo.c
lienhua34:demo$ ./execdemo
in parent process, process ID: 3795, child process ID: 3796
in child process, process ID: 3796, parent process ID: 3795
Hello World! process ID: 3796
termination child process: 3796
復制代碼

(done)

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    国产视频在线一区二区| 91精品欧美综合在ⅹ| 国产精品日韩欧美第一页| 日本一级特黄大片国产| 日本特黄特色大片免费观看| 九九热在线视频精品免费| 97人妻精品免费一区二区| 国产一级内片内射免费看| 视频一区二区三区自拍偷| 亚洲国产成人一区二区在线观看| 91欧美日韩精品在线| 国产免费一区二区三区不卡| 国产中文字幕一二三区| 高清亚洲精品中文字幕乱码| 亚洲精品成人综合色在线| 成人精品视频在线观看不卡| 国产免费一区二区不卡| 91免费一区二区三区| 成人免费观看视频免费| 搡老妇女老熟女一区二区| 91精品国产品国语在线不卡| 亚洲视频一区自拍偷拍另类| 青青免费操手机在线视频| 99久久精品视频一区二区| 精品国产品国语在线不卡| 国产精品视频一级香蕉| 欧美不卡一区二区在线视频| 91人妻久久精品一区二区三区| 久久热麻豆国产精品视频| 国产色偷丝袜麻豆亚洲| 亚洲高清中文字幕一区二区三区| 国产精品熟女乱色一区二区| 扒开腿狂躁女人爽出白浆av| 国产又色又粗又黄又爽| 91欧美日韩中在线视频| 亚洲欧美中文字幕精品| 国产精品午夜一区二区三区| 久久碰国产一区二区三区| 亚洲精品偷拍视频免费观看| 精品国产亚洲免费91| 欧美色欧美亚洲日在线|