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

首頁 > 學院 > 操作系統 > 正文

進程間通信之管道

2024-06-28 13:27:56
字體:
來源:轉載
供稿:網友
進程間通信之管道

管道是UNIX系統ipC的最古老的形式,并且所有UNIX系統都提供此種通信機制。管道有下面兩種局限性:

(1)歷史上,它們是半雙工的(即數據只能在一個方向上流動)?,F在,某些系統提供全雙工管道,但是為了最佳的可移植性,我們決不應預先假定系統使用此特性。

(2)它們只能在具有公共祖先的進程之間使用。通常,一個管道由一個進程創建,然后該進程調用fork,此后父、子進程之間就可應用該管道。

(FIFO沒有第二種局限性,UNIX域套接字和命名流管道則沒有這兩種局限性。)

盡管有這兩種局限性,半雙工管道仍是最常用的IPC形式。每當你在管道線中鍵入一個由shell執行的命令序列時,shell為每一條命令單獨創建一進程,然后將前一條命令進程的標準輸出用管道與后一條命令的標準輸入相連接。

管道是由調用pipe函數而創建的:

#include <unistd.h>int pipe(int filedes[2]);返回值:若成功則返回0,若出錯則返回-1

經由參數filedes返回的兩個文件描述符:filedes[0]為讀而打開,filedes[1]為寫而打開。filedes[1]的輸出是filedes[0]的輸入。

POSIX.1允許實現支持全雙工管道。對于這些實現,filedes[0]和filedes[1]以讀/寫方式打開。

有兩種方式來描繪一個半雙工管道,見圖15-1。左半圖顯示了管道的兩端在一個進程中相互連接,右半圖則說明數據通過內核在管道中流動。

index index1

圖15-1 觀察半雙工管道的兩種方法

fstat函數(見http://www.CUOXin.com/nufangrensheng/p/3501385.html)對管道的每一端都返回一個FIFO類型的文件描述符,可以用S_ISFIFO()宏來測試管道。

POSIX.1規定stat結構的st_size成員對于管道是未定義的。但是當fstat函數應用于管道讀端的文件描述符時,很多系統在st_size中存放管道中可用于讀的字節數。但是,這是不可移植的。

單個進程中的管道幾乎沒有任何用處。通常,調用pipe的進程接著調用fork,這樣就創建了從父進程到子進程(或反向)的IPC通道。圖15-2顯示了這種情況。

index

圖15-2 調用fork之后的半雙工通道

調用fork之后做什么取決于我們想要有的數據流的方向。對于從父進程到子進程的管道,父進程關閉管道的讀端(fd[0]),子進程則關閉寫端(fd[1])。圖15-3顯示了在此之后描述符的安排。

20140129092031328

圖15-3 從父進程到子進程的管道

為了構造從子進程到父進程的管道,父進程關閉fd[1],子進程關閉fd[0]。

當管道的一端被關閉后,下列兩條規則其作用:

(1)當讀一個寫端已被關閉的管道時,在所有數據都被讀取后,read返回0,以指示達到了文件結尾處。(從技術方面考慮,管道的寫端還有進程時,就不會產生文件的結束??梢詮椭埔粋€管道的描述符,使得有多個進程對它具有寫打開文件描述符。但是,通常一個管道只有一個讀進程、一個寫進程。而對于一個單一的FIFO常常有多個寫進程。)

(2)如果寫一個讀端已被關閉的管道,則產生信號SIGPIPE。如果忽略該信號或者捕捉該信號并從其處理程序返回,則write返回-1,errno設置為EPIPE。

在寫管道(或FIFO)時,常量PIPE_BUF規定了內核中管道緩沖區的大小。如果對管道調用write,而且要求寫的字節數小于等于PIPE_BUF,則此操作不會與其他進程對同一管道(或FIFO)的write操作穿插進行(當然,其他進程要求寫的字節數也都小于等于PIPE_BUF)。但是,若有多個進程同時寫一個管道(或FIFO),而且有進程(一個或幾個)要求寫的字節數超過PIPE_BUF字節數時,則寫操作的數據可能相互穿插。用pathconf或fpathconf函數(見http://www.CUOXin.com/nufangrensheng/p/3496323.html中表6)可以確定PIPE_BUF的值。

實例

程序清單15-1創建了一個從父進程到子進程的管道,并且父進程經由該管道向子進程傳送數據。

程序清單15-1 經由管道父進程向子進程傳送數據

#include "apue.h"intmain(void){    int      n;    int      fd[2];    pid_t    pid;    char     line[MAXLINE];    if(pipe(fd) < 0)        err_sys("pipe error");    if((pid = fork()) < 0)    {        err_sys("fork error");    }    else if(pid > 0)    /* parent */    {        close(fd[0]);        write(fd[1], "hello world/n", 12);    }    else    /* child */    {        close(fd[1]);        n = read(fd[0], line, MAXLINE);        write(STDOUT_FILENO, line, n);    }    exit(0);}

在上面的例子中,直接對管道描述符調用read和write。更好的方法是將管道描述符復制為標準輸入和標準輸出。在此之后通常子進程執行另一個程序,該程序或者從標準輸入(已創建的管道)讀數據,或者將數據寫至其標準輸出(該管道)。

實例

試編寫一個程序,其功能是每次一頁顯示已產生的輸出。已經有很多UNIX系統實用程序具有分頁功能,因此無需再構造一個新的分頁程序,而是調用用戶最喜愛的分頁程序。為了避免先將所有數據寫到一個臨時文件中,然后在調用系統中有關程序顯示該文件,我們希望將輸出通過管道直接送到分頁程序。為此,先創建一個管道,調用fork產生一個子進程,使子進程的標準輸入成為管道的讀端,然后調用exec,執行用戶喜愛的分頁程序。程序清單15-2顯示了如何實現這些操作。(本例要求在命令行中有一個參數說明要顯示文件的名稱。通常,這種類型的程序要求在終端上顯示的數據已經在存儲器中。)

程序清單15-2 將文件復制到分頁程序

#include "apue.h"#include <sys/wait.h>#define DEF_PAGER    "/bin/more"    /* default pager PRogram */intmain(int argc, char *argv[]){    int      n;    int      fd[2];    pid_t    pid;    char    *pager, *argv0;    char     line[MAXLINE];    FILE    *fp;    if(argc != 2)        err_quit("usage: a.out <pathname>");    if((fp = fopen(argv[1], "r")) == NULL)        err_sys("can't open %s", argv[1]);    if(pipe(fd) < 0)        err_sys("pipe error");    if((pid = fork()) < 0)    {        err_sys("fork error");    }    else if(pid > 0)    /* parent */    {        close(fd[0]);    /* close read end */                /* parent copies argv[1] to pipe */        while(fgets(line, MAXLINE, fp) != NULL)        {            n = strlen(line);            if(write(fd[1], line, n) != n)                err_sys("write error to pipe");        }        if(ferror(fp))            err_sys("fgets error");        close(fd[1]);    /* close write end of pipe for reader */                if(waitpid(pid, NULL, 0) < 0)            err_sys("waitpid error");                exit(0);        }    else            /* child */    {        close(fd[1]);    /* close write end */        if(fd[0] != STDIN_FILENO)        {            if(dup2(fd[0], STDIN_FILENO) != STDIN_FILENO)                err_sys("dup2 error to stdin");            close(fd[0]);    /* don't need this after dup2 */        }            /* get arguments for execl() */        if((pager = getenv("PAGER")) == NULL)                pager = DEF_PAGER;        if((argv0 = strrchr(pager, '/')) != NULL)            argv0++;        /* step past rightmost slash */        else            argv0 = pager;        /* no slash in pager */                if(execl(pager, argv0, (char *)0) < 0)            err_sys("execl error for %s", pager);    }    exit(0);}

在調用fork之前先創建一個管道。fork之后父進程關閉其讀端,子進程關閉其寫端。子進程然后調用dup2,使其標準輸入成為管道的讀端。當執行分頁程序時,其標準輸入將是管道的讀端。

當我們將一個描述符復制到另一個時(在進程中,fd[0]復制到標準輸入),應當注意在復制之前該描述符的值并不是所希望的值。如果該描述符已經具有所希望的值,并且我們先調用dup2,然后調用close則將關閉此進程中只有該單個描述符所代表的打開文件。(回憶http://www.CUOXin.com/nufangrensheng/p/3498736.html中所述,當dup2中的兩個參數值相等時的操作。)

請注意,我們是如何使用環境變量PAGER試圖獲得用戶分頁程序名稱的。如果這種操作沒有成功,則使用系統默認值。這是環境變量的常見用法。

實例

回憶http://www.CUOXin.com/nufangrensheng/p/3510306.html中的5個函數:TELL_WAIT、TELL_PARENT、TELL_CHILD、WAIT_PARENT以及WAIT_CHILD。http://www.CUOXin.com/nufangrensheng/p/3516427.html中的程序清單10-17提供了一個使用信號的實現。程序清單15-3則是一個使用管道的實現。

程序清單15-3 使父、子進程同步的例程

#include "apue.h"static int pfd1[2], pfd2[2];voidTELL_WAIT(void){    if(pipe(pfd1) < 0 || pipe(pfd2) < 0)        err_sys("pipe error");}voidTELL_PARENT(pid_t pid){    if(write(pfd2[1], "c", 1) != 1)        err_sys("write error");}voidWAIT_PARENT(void){    char c;        if(read(pfd1[0], &c, 1) != 1)        err_sys("read error");    if(c != 'p')        err_quit("WAIT_PARENT: incorrect data");}voidTELL_CHILD(pid_t pid){    if(write(pfd1[1], "p", 1) != 1)        err_sys("write error");}void WAIT_CHILD(void){    char c;        if(read(pfd2[0], &c, 1) != 1)        err_sys("read error");    if(c != "c")        err_quit("WAIT_CHILD: incorrect data");}

如圖15-4所示,在fork之前創建了兩個管道。父進程在調用TELL_CHILD時,寫一個字符“p”至上一個管道,子進程在調用TELL_PARENT時,經由下一個管道寫一個字符“c”。相應的WAIT_xxx函數調用read讀這個字符,沒有讀到字符時阻塞(睡眠等待)。

未命名

圖15-4 用兩個管道實現父子進程同步

請注意,每一個管道都有一個額外的讀取進程,這沒有關系。也就是說,除了子進程從pfd1[0]讀取,父進程也有上一個管道的讀端。因為父進程并沒有執行對該管道的讀操作,所以這不會產生任何影響。

本篇博文內容摘自《UNIX環境高級編程》(第二版),僅作個人學習記錄所用。關于本書可參考:http://www.apuebook.com/。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美一级大胆视频| 在线a欧美视频| 久久久www成人免费精品张筱雨| 青青青国产精品一区二区| 成人乱人伦精品视频在线观看| 国产视频精品在线| 日韩精品日韩在线观看| 2020久久国产精品| 国产乱人伦真实精品视频| 国产欧美日韩最新| 深夜福利国产精品| 欧美成人激情视频免费观看| 91久久精品美女| 欧美极品美女视频网站在线观看免费| 成人免费在线视频网站| 日韩成人久久久| 日本久久久久亚洲中字幕| 欧美精品做受xxx性少妇| 一区二区三区视频在线| 韩国v欧美v日本v亚洲| 成人黄色免费片| 亚洲毛片在线免费观看| 成人免费大片黄在线播放| 亚洲欧洲成视频免费观看| 亚洲精品国产综合久久| 欧美成人午夜激情视频| 国产精品久久久久久亚洲影视| 午夜精品久久久久久久白皮肤| 92裸体在线视频网站| 久久精品国产2020观看福利| 国产日韩欧美日韩大片| 欧美怡红院视频一区二区三区| 91亚洲国产成人精品性色| 亚洲精品www久久久| 91精品啪在线观看麻豆免费| 亚洲一区二区在线播放| 7777kkkk成人观看| 国产精品久久99久久| 国产精品中文字幕在线观看| 欧美裸体视频网站| 欧美成人三级视频网站| 国产精品国产亚洲伊人久久| 91久久久久久国产精品| 日本亚洲精品在线观看| 丝袜美腿精品国产二区| 久久精品国产v日韩v亚洲| 91精品视频网站| 日本久久久久久久久久久| 欧美裸体xxxx极品少妇| 国产欧美va欧美va香蕉在线| 久久人人看视频| 成人免费看黄网站| 成人国产精品一区| 日韩亚洲综合在线| 欧美最顶级的aⅴ艳星| 午夜精品久久久久久久久久久久| 成人网在线观看| 国产精品免费一区| 欧美高清视频在线观看| 日韩精品在线观看网站| 中日韩午夜理伦电影免费| 色婷婷av一区二区三区在线观看| 国产精品久久久久久av福利软件| 色吧影院999| 亚洲综合在线中文字幕| 亚洲精品大尺度| 日韩成人黄色av| 欧美成人三级视频网站| 国产欧美一区二区三区在线看| 88xx成人精品| 亚洲国产精品人人爽夜夜爽| 国产精品久久久久久久久| 91在线高清免费观看| 久久精品亚洲94久久精品| 51久久精品夜色国产麻豆| 国产精品久久久久av免费| 久久精品视频中文字幕| 国产福利视频一区二区| 青青草99啪国产免费| 亚洲精品国产拍免费91在线| 精品二区三区线观看| 日韩电影在线观看永久视频免费网站| 日韩av在线网页| 全亚洲最色的网站在线观看| 欧美一级黄色网| 国产精品美乳一区二区免费| 亚洲人成五月天| 久久天堂av综合合色| 久久久99久久精品女同性| 国产成人福利视频| 亚洲va欧美va在线观看| 青青在线视频一区二区三区| 久久av在线播放| 日韩欧美在线视频免费观看| 欧美裸体视频网站| 亚洲人成77777在线观看网| 久热爱精品视频线路一| 亚洲欧洲成视频免费观看| 成人免费网视频| 热久久美女精品天天吊色| 欧美一级大片视频| 精品香蕉在线观看视频一| 国产精品视频一区国模私拍| www日韩中文字幕在线看| 亚洲视频在线观看网站| 日韩精品免费观看| 粉嫩老牛aⅴ一区二区三区| 日韩欧美在线视频日韩欧美在线视频| 亚洲人成电影网站色…| 欧美激情精品久久久久| 久久精品欧美视频| 欧美亚洲成人免费| 欧美不卡视频一区发布| 亚洲成人黄色网址| 亚洲免费小视频| 欧美午夜精品久久久久久人妖| 欧美成人性生活| 亚洲精品自在久久| 亚洲丁香久久久| 一区二区三区久久精品| 91av在线视频观看| 亚洲xxxx3d| 国产一区二区三区在线视频| 色综合久久悠悠| 国产精品久久久久久久久久尿| 成人h猎奇视频网站| 亚洲网在线观看| 亚洲www视频| 成人av在线网址| 欧美黄色小视频| 韩国精品久久久999| 日韩高清电影好看的电视剧电影| 国产精品香蕉av| 日韩中文字幕在线免费观看| 久久精品成人一区二区三区| 中日韩美女免费视频网站在线观看| 永久免费毛片在线播放不卡| 亚洲毛片在线观看| 日韩中文在线中文网三级| 成人黄色在线观看| 国产v综合ⅴ日韩v欧美大片| 91夜夜揉人人捏人人添红杏| 亚洲色图18p| 国产精品青草久久久久福利99| 91高潮精品免费porn| 51久久精品夜色国产麻豆| 精品一区精品二区| 成人有码在线视频| 国产精品扒开腿做| 久久久久久久久久久免费精品| 欧美成人精品在线| 91精品视频免费| 久久久久久国产精品| 国产一区欧美二区三区| 国产脚交av在线一区二区| 亚洲在线免费观看| 欧美wwwxxxx| 亚洲片在线观看| 热久久免费视频精品| 亚洲天堂开心观看| 精品国产自在精品国产浪潮| 久久久免费高清电视剧观看| 国产极品精品在线观看| 日本高清视频精品|