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

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

高級進程間通信之基于STREAMS的管道

2024-06-28 13:27:49
字體:
來源:轉載
供稿:網友
高級進程間通信之基于STREAMS的管道

基于STREAMS的管道(簡稱STREAMS管道,STREAMS pipe)是一個雙向(全雙工)管道。單個STREAMS管道就能向父、子進程提供雙向的數據流。

將http://www.CUOXin.com/nufangrensheng/p/3560130.html中圖15-1中的單向箭頭全部換成雙向箭頭,即為觀察STREAMS管道的兩種方式。

未命名

                               圖17-1 觀察STREAMS管道的兩種方式

如果從內部觀察STREAMS管道(圖17-2),可以看到它簡單得只包含兩個流首,每個流首的寫隊列(WQ)指向另一個流首的讀隊列(RQ),寫入管道一端的數據被放入另一端的讀隊列的消息中。

未命名

                 圖17-2 STREAMS管道的內部結構

因為STREAMS管道是一個流,所以可將STREAMS模塊壓入到該管道的任一端(圖17-3)。但是,如果我們在一端壓入了一個模塊,那么并不能在另一端彈出該模塊。如果想要刪除它,則必須從原壓入端刪除。

未命名

                         圖17-3 帶模塊的STREAMS管道內部結構

實例

下面用一個STREAMS管道再次實現程序清單15-9(http://www.CUOXin.com/nufangrensheng/p/3561379.html)中的協同進程實例。程序清單17-1是新的main函數。add2協同進程與程序清單15-8(http://www.CUOXin.com/nufangrensheng/p/3561379.html)中的相同。本程序調用了創建單個STREAMS管道的新函數s_pipe(見下個實例)。

程序清單17-1 用STREAMS管道驅動add2過濾進程的程序

#include "apue.h"static void sig_pipe(int);    /* our signal handler */intmain(void){    int      n;    int      fd[2];    pid_t    pid;    char     line[MAXLINE];    if(signal(SIGPIPE, sig_pipe) == SIG_ERR)        err_sys("signal error");    if(s_pipe(fd) < 0)    /* need only a single stream pipe */        err_sys("pipe error");    if((pid = fork()) < 0)    {        err_sys("fork error");    }    else if(pid > 0)    {        close(fd[1]);    /* parent */        while(fgets(line, MAXLINE, stdin) != NULL)        {            n = strlen(line);            if(write(fd[0], line, n) != n)                err_sys("write error to pipe");            if((n = read(fd[0], line, MAXLINE)) < 0)                err_sys("read error from pipe");            if(n == 0)            {                err_msg("child closed pipe");                break;                    }            line[n] = 0;    /* null terminate */            if(fputs(line, stdout) == EOF)                err_sys("fputs error");        }        if(ferror(stdin))            err_sys("fgets error on stdin");        exit(0);    }    else    {        close(fd[0]);        if(fd[1] != STDIN_FILENO && dup2(fd[1], STDIN_FILENO) != STDIN_FILENO)            err_sys("dup2 error to stdin");        if(fd[1] != STDOUT_FILENO && dup2(fd[1], STDOUT_FILENO) != STDOUT_FILENO)            err_sys("dup2 error to stdout");        if(execl("./add2", "add2", (char *)0) < 0)            err_sys("execl error");    }    exit(0);}static voidsig_pipe(int signo){    PRintf("SIGPIPE caught/n");    exit(1);}

父進程只使用fd[0],子進程只是用fd[1]。因為STREAMS管道的每一端都是全雙工的,所以父進程讀、寫fd[0],而子進程將fd[1]復制到標準輸入和標準輸出。圖17-4顯示了由此構成的各描述符。

未命名

                  圖17-4 為協作進程所作的描述符安排

s_pipe函數定義為與標準pipe函數類似。它的調用參數與pipe相同,但是返回的描述符以讀-寫模式打開。

實例:基于STREASMS的s_pipe函數

程序17-2 基于STREAMS的s_pipe函數版本(它只是簡單地調用創建全雙工管道的標準pipe函數)

#include "apue.h"/** Return a STREAMS-based pipe, with the two file descirptors * returned in fd[0] and fd[1].*/ints_pipe(int fd[2]){    return(pipe(fd));}

注意,POSIX.1允許實現支持全雙工管道。對于這些實現,filedes[0]和filedes[1]以讀/寫方式打開(http://www.CUOXin.com/nufangrensheng/p/3560130.html)。但是并不是所有實現都支持pipe創建全雙工管道。對于不支持pipe創建全雙工管道的系統上面實例運行會出錯:“Bad file descriptor”。此時,我們把s_pipe函數中return語句 改為:return(socketpair(AF_UNIX, SOCK_STREAM, 0, fd));即可,這里使用了UNIX域套接字接口,詳情請參考高級進程間通信之UNIX域套接字。

1、命名的STREAMS管道

通常,管道僅在相關進程之間使用:子進程繼承父進程的管道。在http://www.CUOXin.com/nufangrensheng/p/3561632.html曾介紹,無關進程可以使用FIFO進行通信,但是這僅僅提供單向通信。STREAMS機制提供了一種途徑,使得進程可以給予管道一個文件系統中的名字。這就避免了單向FIFO的問題。

我們可以用fattach函數給STREAMS管道一個文件系統中的名字。

#include <stropts.h>int fattach(int filedes, const char *path);返回值:若成功則返回0,若出錯則返回-1

path參數必須引用一個現存的文件,調用進程應當或者擁有該文件并且對它具有寫權限,或者正在以超級用戶特權運行。

一旦STREAMS管道連接到文件系統名字空間,那么原來使用該名字的底層文件就不再是可訪問的。打開該名字的任一進程將能訪問相應管道,而不是訪問原先的文件。在調用fattach之前打開底層文件的任一進程可以繼續訪問該文件。確實,一般而言,這些進程并不知道該名字現在引用了另外一個文件。

圖17-5顯示了連接到路徑名/tmp/pipe的一條通道。只有管道的一端連接到文件系統中一個名字上。另一端用來與打開該連接文件名的進程通信。雖然fattach函數可將任何種類的STREAMS文件描述符與文件系統中的一個名字相連接,但它最主要用于將一個名字給予一個STREAMS管道。

未命名

               圖17-5 一條管道安裝到文件系統的一個名字上

一個進程可以調用fdetach函數撤銷STREAMS管道文件與文件系統中名字的關聯關系。

#include <stropts.h>int fdetach(const char *path);返回值:若成功則返回0,若出錯則返回-1

在調用fdetach函數之后,先前依靠打開path而能訪問STREAMS管道的進程仍可繼續訪問該管道,但是在此之后打開path的進程將訪問駐留在文件系統中的底層文件。

2、唯一連接

雖然我們可以將STREAMS管道的一端連接到文件系統的名字空間,但是如果多個進程都想要用命名STREAMS管道與服務器進程通信,那么仍然存在問題。若幾個客戶進程同時將數據寫至一管道,那么這些數據就會混合交錯。即使我們保證客戶進程的字節數小于PIPE_BUF,使得寫操作是原子性的,但是仍無法保證服務器進程將數據送回所期望的某個客戶進程,也無法保證該客戶進程一定會讀此消息。當多個客戶進程同時讀一管道時,我們無法調度具體哪一個客戶進程去讀我們所發送的消息。

connld STREAMS模塊解決了這一問題。在將一個STREAMS管道連接到文件系統的一個名字之前,服務器進程可將connld模塊壓入要被連接管道的一端。其結果示于圖17-6。

2012080421302513

在圖17-6中,服務器進程已將管道的一端連接至/tmp/pipe。我們用虛線指示客戶進程正在打開所連接的STREAMS管道。一旦打開操作完成,則服務器進程、客戶進程和STREAMS管道之間的關系示于圖17-7中。

未命名

                                    圖17-7 用connld構造唯一連接

客戶進程絕不會接收到它所打開管道端的打開文件描述符。作為替代,操作系統創建了一個新管道,對客戶進程返回其一端,作為它打開/tmp/pipe的結果。系統將此新管道另一端的文件描述符經由已存在的連接管道發送給服務器進程,結果在客戶進程和服務器進程之間構成了唯一連接。

現在,我們將開發三個函數,使用這些函數可以創建在無關進程之間的唯一連接。這些函數模仿了在http://www.CUOXin.com/nufangrensheng/p/3565858.html中討論過的面向連接的套接字函數。在此處,我們使用STREAMS管道作為底層通信機制,在高級進程間通信之UNIX域套接字章節我們則將見到用UNIX域套接字實現的同樣這三個函數。

#include "apue.h"int serv_listen(const char *name);返回值:若成功則返回要偵聽的文件描述符,若出錯則返回負值int serv_accept(int listenfd, uid_t *uidptr);返回值:若成功則返回新文件描述符,若出錯則返回負值int cli_conn(const char *name);返回值:若成功則返回文件描述符,若出錯則返回負值

服務器進程調用serv_listen函數聲明它要在一個眾所周知的名字(文件系統中的某個路徑名)上偵聽客戶進程的連接請求。當客戶進程想要連接到服務器進程時,它們將使用該名字。serv_listen函數的返回值是STREAMS管道的服務器進程端。

程序清單17-3 使用STREAMS管道的serv_listen函數

#include "apue.h"#include <fcntl.h>#include <stropts.h>/* pipe permissions: user rw, group rw, others rw */#define FILE_MODE    (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)/** Establish an endpoint to listen for connect requests.* Returns fd if all ok, <0 on error*/int serv_listen(const char *name){    int     tempfd;    int     fd[2];    /*     * Create a file: mount point for fattach().    */    unlink(name);    if((tempfd = creat(name, FIFO_MODE)) < 0)        return(-1);    if(close(tempfd) < 0)        return(-2);    if(pipe(fd) < 0)        return(-3);        /*    * Push connld & fattach() on fd[1].     */    if(ioctl(fd[1], I_PUSH, "connld") < 0)    {        close(fd[0]);        close(fd[1]);        return(-4);    }    if(fattach(fd[1], name) < 0)    {        close(fd[0]);        close(fd[1]);        return(-5);    }    close(fd[1]);    /* fattach holds this end open */    return(fd[0]);    /* fd[0] is where client connections arrive */    }

服務器進程使用serv_accept函數等待客戶進程連接請求的到達。當一個請求到達時,系統自動創建一個新的STREAMS管道,serv_accept函數向服務器進程返回該STREAMS管道的另一端。另外,客戶進程的有效用戶ID存放在uidptr指向的存儲區中。

程序清單17-4 使用STREAMS管道的serv_accept函數

#include "apue.h"#include <stropts.h>/** Wait for a client connection to arrive, and accept it.* We also obtain the client's user ID.* Return new fd if all ok, <0 on error.*/int serv_accept(int listenfd, uid_t *uidptr){    struct strrecvfd    recvfd;        if(ioctl(listenfd, I_RECVFD, &recvfd) < 0)        return(-1);    /* could be EINTR if signal caught */    if(uidptr != NULL)        *uidptr = recvfd.uid;    /* effective uid of caller */    return(recvfd.fd);    /* return the new descriptor */}

客戶進程調用cli_conn函數連接至服務器進程??蛻暨M程指定的參數name必須與服務器進程調用serv_listen函數時所用的相同。函數返回時,客戶進程得到連接至服務器進程的文件描述符。

程序清單17-5 用STREAMS管道的cli_conn函數

#include "apue.h"#include <fcntl.h>#include <stropts.h>/** Create a client endpoint and connect to a server.* Return fd if all ok, <0 on error.*/intcli_conn(const char *name){    int    fd;    /* open the mounted stream */    if((fd = open(name, O_RDWR)) < 0)        return(-1);    if(isastream(fd) == 0)    {        close(fd);        return(-2);    }    return(fd);}

我們對返回的描述符是否引用STREAMS設備進行了二次檢驗,以防止服務器進程沒被啟動而路徑名仍存在于文件系統中。

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


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩av在线直播| 亚洲欧美日韩国产中文专区| 国产一区二区三区四区福利| 亚洲一区二区少妇| 超碰91人人草人人干| 456亚洲影院| 国产日韩欧美日韩| 欧美韩国理论所午夜片917电影| 5566成人精品视频免费| 日韩欧美高清在线视频| 91免费看国产| 91亚洲国产成人精品性色| 97av在线影院| 欧洲成人免费aa| 亚洲天堂色网站| 日韩免费看的电影电视剧大全| 国内精品伊人久久| www国产亚洲精品久久网站| 日韩禁在线播放| 久久99久久99精品免观看粉嫩| 日本精品久久久| 亚洲三级 欧美三级| 国产精品亚洲一区二区三区| 亚洲片在线观看| 91精品在线影院| 成人欧美在线视频| 欧美另类极品videosbest最新版本| 国产精品成人一区二区三区吃奶| 96精品视频在线| 成人黄色短视频在线观看| 日本高清视频精品| 日韩经典一区二区三区| 国产精品户外野外| 亚洲精品乱码久久久久久按摩观| 亚洲少妇中文在线| 久久综合伊人77777| 91在线国产电影| 26uuu另类亚洲欧美日本一| 久久久久久久久久久免费精品| 成人在线视频网站| 国产精品视频在线观看| 亚洲乱亚洲乱妇无码| 国产成人亚洲综合91精品| 国内精品久久久久久影视8| 亚洲一区二区久久久久久久| 久久精品视频网站| 精品一区二区三区四区| 色妞色视频一区二区三区四区| 国产a∨精品一区二区三区不卡| 97在线精品国自产拍中文| 成人黄色激情网| 2018日韩中文字幕| 亚洲福利视频二区| 日韩视频一区在线| 日韩专区中文字幕| 成人黄色免费片| 性欧美激情精品| 国产欧美精品一区二区| 国产精品一区久久久| 国产精品海角社区在线观看| 国产精品自拍偷拍| 欧美激情视频一区二区| 欲色天天网综合久久| 日韩高清人体午夜| 日韩a**中文字幕| 97超级碰在线看视频免费在线看| 97国产一区二区精品久久呦| 中文字幕亚洲一区二区三区| 国产精品综合网站| 国产精品电影观看| 欧美性猛交99久久久久99按摩| 国产一区二区在线播放| 亚洲精品电影在线| 日本精品视频在线播放| 亚洲欧美日韩直播| 国产精品久久久久久久久久小说| 麻豆成人在线看| 91av在线播放视频| 日本伊人精品一区二区三区介绍| 日韩亚洲成人av在线| 欧美精品久久久久a| 欧美一级大片在线免费观看| 国产精品视频一区二区三区四| 91免费综合在线| 国产一区二区激情| 91精品久久久久久久久青青| 亚洲成人av片| 亚洲一区二区在线| 久久青草精品视频免费观看| 日韩精品在线影院| 亚洲电影中文字幕| 亚洲国产精品国自产拍av秋霞| 国产ts人妖一区二区三区| 亚洲a在线播放| 亚洲电影免费观看| 欧美丝袜第一区| 精品电影在线观看| 91av福利视频| 成人国产精品久久久| 国产精品久久久久久久美男| 国产成人精品免高潮在线观看| 黄色成人在线免费| 欧美亚洲国产视频小说| 欧美一级黑人aaaaaaa做受| 亚洲字幕一区二区| 中文字幕日韩视频| 欧美中文在线字幕| 国产精品极品在线| 久久久久久国产| 国产精品视频网站| 久久国产精品99国产精| 国内精品久久久久影院 日本资源| 欧洲永久精品大片ww免费漫画| 欧美日韩成人在线播放| 国产精品三级美女白浆呻吟| 不卡av日日日| 蜜臀久久99精品久久久久久宅男| 欧美韩国理论所午夜片917电影| 91在线中文字幕| 91精品国产综合久久香蕉922| 91av免费观看91av精品在线| 国产情人节一区| 曰本色欧美视频在线| 97视频在线观看视频免费视频| 精品久久久久久久久久久| 成人综合国产精品| 日韩精品福利在线| 日韩精品极品在线观看| 国产一区二区三区高清在线观看| 中文字幕亚洲一区二区三区五十路| 国产一区二区三区在线播放免费观看| 欧美性受xxxx白人性爽| 97国产一区二区精品久久呦| 久久久视频免费观看| 久久视频在线播放| 欧美最猛性xxxx| 久久国产精品久久国产精品| 国产精品视频地址| 精品久久久久久久大神国产| 免费91麻豆精品国产自产在线观看| 国产精品入口免费视| 中日韩午夜理伦电影免费| 精品国产欧美一区二区三区成人| 久久精品夜夜夜夜夜久久| 欧美壮男野外gaytube| 欧美日韩激情视频8区| 久久久久久久久久久久av| 久久网福利资源网站| 日韩电影大全免费观看2023年上| 久久影院模特热| 亚洲精品99久久久久中文字幕| 亚洲色无码播放| 欧美巨大黑人极品精男| 国产精品成av人在线视午夜片| 亚洲欧美在线一区| 国产精品视频播放| 国产精品午夜视频| 96sao精品视频在线观看| 日本韩国欧美精品大片卡二| 国产精品一区av| 国产精品欧美一区二区三区奶水| 精品久久久久久国产| 中文国产成人精品久久一| 久久成人一区二区|