日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux编程之pipe()函数

發(fā)布時間:2024/2/28 linux 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux编程之pipe()函数 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

管道是一種把兩個進程之間的標準輸入和標準輸出連接起來的機制,從而提供一種讓多個進程間通信的方法,當進程創(chuàng)建管道時,每次

都需要提供兩個文件描述符來操作管道。其中一個對管道進行寫操作,另一個對管道進行讀操作。對管道的讀寫與一般的IO系統(tǒng)函數(shù)一

致,使用write()函數(shù)寫入數(shù)據(jù),使用read()讀出數(shù)據(jù)。

#include<unistd.h>

int pipe(int filedes[2]);

返回值:成功,返回0,否則返回-1。參數(shù)數(shù)組包含pipe使用的兩個文件的描述符。fd[0]:讀管道,fd[1]:寫管道。

必須在fork()中調(diào)用pipe(),否則子進程不會繼承文件描述符。兩個進程不共享祖先進程,就不能使用pipe。但是可以使用命名管道。

?

當管道進行寫入操作的時候,如果寫入的數(shù)據(jù)小于128K則是非原子的,如果大于128K字節(jié),緩沖區(qū)的數(shù)據(jù)將被連續(xù)地寫入

管道,直到全部數(shù)據(jù)寫完為止,如果沒有進程讀取數(shù)據(jù),則將一直阻塞,如下:

在上例程序中,子進程一次性寫入128K數(shù)據(jù),當父進程將全部數(shù)據(jù)讀取完畢的時候,子進程的write()函數(shù)才結束阻塞并且

返回寫入信息。

命名管道FIFO

管道最大的劣勢就是沒有名字,只能用于有一個共同祖先進程的各個進程之間。FIFO代表先進先出,單它是一個單向數(shù)據(jù)流,也就是半雙工,和

管道不同的是:每個FIFO都有一個路徑與之關聯(lián),從而允許無親緣關系的進程訪問。 ?

? ? ? ? #include <sys/types.h>

? ? ? ? #include <sys/stat.h>

? ? ? int mkfifo(const char *pathname, mode_t mode);
? ? ?這里pathname是路徑名,mode是sys/stat.h里面定義的創(chuàng)建文件的權限.

以下示例程序來自:http://blog.chinaunix.net/uid-20498361-id-1940238.html

? 有親緣關系進程間的fifo的例子
?

/*
?* 有親緣關系的進程間的fifo的使用
?* fifo 使用的簡單例子
?*/

#include?"../all.h"

#define?FIFO_PATH?"/tmp/hover_fifo"


void?
do_sig(int?signo)
{
????if?(signo?==?SIGCHLD)
????????while?(waitpid(-1,?NULL,?WNOHANG)?>?0)
????????????;
}


int
main(void)
{
????int?ret;
????int?fdr,?fdw;
????pid_t?pid;

????char?words[10]?=?"123456789";
????char?buf[10]?=?{'\0'};????
????
????// 創(chuàng)建它,若存在則不算是錯誤,
????// 若想修改其屬性需要先打開得到fd,然后用fcntl來獲取屬性,然后設置屬性.

????if?(((ret?=?mkfifo(FIFO_PATH,?FILE_MODE))?==?-1)?

???????????????????? &&?(errno?!=?EEXIST))
????????perr_exit("mkfifo()");
????fprintf(stderr,?"fifo : %s created successfully!\n",?FIFO_PATH);

????signal(SIGCHLD,?do_sig);

????pid?=?fork();
????if?(pid?==?0)?{?// child

????????if?((fdr?=?open(FIFO_PATH,?O_WRONLY))?<?0)?// 打開fifo用來寫
????????????perr_exit("open()");
????????sleep(2);

??????? // 寫入數(shù)據(jù)
????????if?(write(fdr,?words,?sizeof(words))?!=?sizeof(words))?
????????????perr_exit("write");
????????fprintf(stderr,?"child write : %s\n",?words);
????????close(fdw);
????}?else?if?(pid?>?0)?{?// parent

????????if?((fdr?=?open(FIFO_PATH,?O_RDONLY))?<?0)?// 打開fifo用來讀

????????????perr_exit("open()");

????????fprintf(stderr,?"I father read, waiting for child ...\n");
????????if?(read(fdr,?buf,?9)?!=?9)?//讀數(shù)據(jù)
????????????perr_exit("read");

????????fprintf(stderr,?"father get buf : %s\n",?buf);
????????close(fdr);
????}
????// 到這里fifo管道并沒有被刪除,必須手動調(diào)用函數(shù)unlink或remove刪除.

????return?0;????
}
?


從例子上可以看出使用fifo時需要注意:
*fifo管道是先調(diào)用mkfifo創(chuàng)建,然后再用open打開得到fd來使用.
*在打開fifo時要注意,它是半雙工的的,一般不能使用O_RDWR打開,而只能用只讀或只寫打開.

? ?fifo可以用在非親緣關系的進程間,而它的真正用途是在服務器和客戶端之間. 由于它是半雙工的所以,如果要進行客戶端和服務器雙方的通信的話,

每個方向都必須建立兩個管道,一個用于讀,一個用于寫.

下面是一個服務器,對多個客戶端的fifo的例子:

server 端的例子:


?

/*
?* FIFO server
?*/

#include?"all.h"

int
main(void)
{
????int?fdw,?fdw2;
????int?fdr;
????char?clt_path[PATH_LEN]?=?{'\0'};
????char?buf[MAX_LINE]?=?{'\0'};
????char?*p;
????int?n;
????
????if?(mkfifo(FIFO_SVR,?FILE_MODE)?==?-1?&&?errno?!=?EEXIST)????
????????perr_exit("mkfifo()");????
????if?((fdr?=?open(FIFO_SVR,?O_RDONLY))?<?0)????
????????perr_exit("open()");
????/*?
???? * 根據(jù)fifo的創(chuàng)建規(guī)則, 若從一個空管道或fifo讀,?

???? * 而在讀之前管道或fifo有打開來寫的操作, 那么讀操作將會阻塞?
???? * 直到管道或fifo不打開來讀, 或管道或fifo中有數(shù)據(jù)為止.?

???? *

???? * 這里,我們的fifo本來是打開用來讀的,但是為了,read不返回0,

???? * 讓每次client端讀完都阻塞在fifo上,我們又打開一次來讀.
???? * 見unpv2 charper 4.7
???? */
????if?((fdw2?=?open(FIFO_SVR,?O_WRONLY))?<?0)????
????????fprintf(stderr,?"open()");
????
????while?(1)?{
????????/* read client fifo path from FIFO_SVR */

???? /* 這里由于FIFO_SVR有打開來寫的操作,所以當管道沒有數(shù)據(jù)時,?

????? * read會阻塞,而不是返回0.?

????? */
????????if?(read(fdr,?clt_path,?PATH_LEN)?<?0)?{
????????????fprintf(stderr,?"read fifo client path error : %s\n",?strerror(errno));????
????????????break;
????????}
????????if?((p?=?strstr(clt_path,?"\r\n"))?==?NULL)?{
????????????fprintf(stderr,?"clt_path error: %s\n",?clt_path);
????????????break;
????????}
????????*p?=?'\0';
????????DBG("clt_path",?clt_path);
????????if?(access(clt_path,?W_OK)?==?-1)?{?// client fifo ok, but no permission

????????????perror("access()");????
????????????continue;
????????}
????????/* open client fifo for write */
????????if?((fdw?=?open(clt_path,?O_WRONLY))?<?0)?{
????????????perror("open()");????
????????????continue;
????????}
????????if?((n?=?read(fdr,?buf,?WORDS_LEN))?>?0)?{?/* read server words is ok */
????????????printf("server read words : %s\n",?buf);
????????????buf[n]?=?'\0';
????????????write(fdw,?buf,?strlen(buf));????
????????}
????}
????
????close(fdw);????
????unlink(FIFO_SVR);
????exit(0);
}


客戶端的例子:

?

?

/*
?* Fifo client
?*
?*/
#include?"all.h"



int
main(void)
{
????int?fdr,?fdw;
????pid_t?pid;????
????char?clt_path[PATH_LEN]?=?{'\0'};
????char?buf[MAX_LINE]?=?{'\0'};
????char?buf_path[MAX_LINE]?=?{'\0'};
????
????snprintf(clt_path,?PATH_LEN,?FIFO_CLT_FMT,?(long)getpid());????????
????DBG("clt_path1 = ",?clt_path);
????snprintf(buf_path,?PATH_LEN,?"%s\r\n",?clt_path);

????if?(mkfifo(clt_path,?FILE_MODE)?==?-1?&&?errno?!=?EEXIST)????
????????perr_exit("mkfifo()");

????/* client open clt_path for read
???? * open server for write?
?????? */
????if?((fdw?=?open(FIFO_SVR,?O_WRONLY))?<?0)?
????????perr_exit("open()");
????
????/* write my fifo path to server */????
????if?(write(fdw,?buf_path,?PATH_LEN)?!=?PATH_LEN)????????
????????perr_exit("write()");
????if?(write(fdw,?WORDS,?WORDS_LEN)?<?0)????/* write words to fifo server */
????????perr_exit("error");

????if?((fdr?=?open(clt_path,?O_RDONLY))?<?0)????
????????perr_exit("open()");
????if?(read(fdr,?buf,?WORDS_LEN)?>?0)?{?????/* read reply from fifo server */
????????buf[WORDS_LEN]?=?'\0';
????????printf("server said : %s\n",?buf);
????}
????
????close(fdr);
????unlink(clt_path);
????
????exit(0);
}

?

總結

以上是生活随笔為你收集整理的linux编程之pipe()函数的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。