linux管道的那點(diǎn)事

原文地址:http://blog.chinaunix.net/uid-27034868-id-3394243.html

管道是一種兩個(gè)進(jìn)程間進(jìn)行單向通信的機(jī)制。因?yàn)楣艿纻鬟f數(shù)據(jù)的單向性,管道又稱為半雙工管道。管道的這一特點(diǎn)決定了器使用的局限性。管道是Linux支持的最初Unix IPC形式之一,具有以下特點(diǎn):

***數(shù)據(jù)只能由一個(gè)進(jìn)程流向另一個(gè)進(jìn)程(其中一個(gè)讀管道,一個(gè)寫管道);如果要進(jìn)行雙工通信,需要建 立兩個(gè)管道。

***管道只能用于父子進(jìn)程或者兄弟進(jìn)程間通信。,也就是說管道只能用于具有親緣關(guān)系的進(jìn)程間通信。

除了以上局限性,管道還有其他一些不足,如管道沒有名字(匿名管道),管道的緩沖區(qū)大小是受限制的。管道所傳輸?shù)氖菬o格式的字節(jié)流。這就需要管道輸入方和輸出方事先約定好數(shù)據(jù)格式。雖然有那么多不足,但對(duì)于一些簡單的進(jìn)程間通信,管道還是完全可以勝任的。

使用管道進(jìn)行通信時(shí),兩端的進(jìn)程向管道讀寫數(shù)據(jù)是通過創(chuàng)建管道時(shí),系統(tǒng)設(shè)置的文件描述符進(jìn)行的。從本質(zhì)上說,管道也是一種文件,但它又和一般的文件有所不同,可以克服使用文件進(jìn)行通信的兩個(gè)問題,這個(gè)文件只存在內(nèi)存中。

通過管道通信的兩個(gè)進(jìn)程,一個(gè)進(jìn)程向管道寫數(shù)據(jù),另外一個(gè)從中讀數(shù)據(jù)。寫入的數(shù)據(jù)每次都添加到管道緩沖區(qū)的末尾,讀數(shù)據(jù)的時(shí)候都是從緩沖區(qū)的頭部讀出數(shù)據(jù)的。

#include

int pipe(int pipefd[2]);

(匿名)管道兩端分別用描述符pipefd[0]及pipefd[1]來描述。需要注意的是,管道兩端的任務(wù)是固定的,一端只能用于讀,有描述符pipefd[0]表示,稱其為管道讀端;另一端只能用于寫,由描述符pipe[1]來表示,稱其為管道寫端。該函數(shù)創(chuàng)建的管道的兩端處于一個(gè)進(jìn)程中間,在實(shí)際應(yīng)用中沒有太大意義,因此,一個(gè)進(jìn)程在由pipe()創(chuàng)建管道后,一般再fork一個(gè)子進(jìn)程,然后通過管道實(shí)現(xiàn)父子進(jìn)程間的通信。在此不再作多介紹,下面看看有名管道吧。

管道的一個(gè)不足之處就是沒有名字,因此,只能用于具有親緣關(guān)系的進(jìn)程間通信,在有名管道(name pipe或FIFO)提出后,該限制得到了解決。FIFO不同與管道之處在與她提供一個(gè)路徑名與之關(guān)聯(lián),以FIFO的文件形式存儲(chǔ)在文件系統(tǒng)中。有名管道是一個(gè)設(shè)備文件,因此,即使進(jìn)程與創(chuàng)建FIFO的進(jìn)程不存在親緣關(guān)系,只要可以訪問該路徑,就能夠通過FIFO相互通信了。值得注意的是FIFO(First In First Out)總是按照先進(jìn)先出的原則工作,第一個(gè)被寫入的數(shù)據(jù)首先從管道中讀出。

在Linux中我們經(jīng)常使用管道重定向數(shù)據(jù)。比如:

下面介紹一下創(chuàng)建有名管道的系統(tǒng)調(diào)用,有兩個(gè),mknod和mkfifo

#include?

#include?

int mknod(const char *pathname, mode_t mode, dev_t dev);

int?mkfifo(?const?char?*pathname,?mode_t?mode?);

函數(shù)mknod參數(shù)中pathname為創(chuàng)建有名管道的全路徑名,mode為創(chuàng)建有名管道的模式,指明其存取權(quán)限;dev為設(shè)備值,該值取決于文件創(chuàng)建的種類,它只在創(chuàng)建設(shè)備文件是才會(huì)用到。這兩個(gè)函數(shù)調(diào)用成功都返回0,否則返回-1.

讀寫有名管道:

#include?

ssize_t?read?(int?fd?,?void?*?buf?,?size_t?nbytes)

ssize_t?write?(int?fd?,?void?*?buf?,?size_t?nbytes)

接下來給大家演示一下通過有名管道通信的聊天程序。。。

點(diǎn)擊(此處)折疊或打開

//李四.c

#include

#include

#include

#include

#include

#include

#include

#include

#define FIFO_READ"writefifo"http://另外一個(gè)程序只要把本程序

#define FIFO_WRITE"readfifo"http://拷貝一份然后調(diào)換這兩個(gè)宏即可

#define BUF_SIZE????1024

intleft=0;

void*read_buf()

{

intrfd=-1;

char buf[BUF_SIZE]={'\0'};

inti;

printf("等待對(duì)方……\n");

while((rfd=open(FIFO_READ,O_RDONLY))==-1){

sleep(1);

}

while(left!=1){

//printf("i=%d ",i++);

intlen=read(rfd,buf,BUF_SIZE);

if(len>0){

buf[len]='\0';

if(strcmp(buf,"不理你了")==0){

printf("\n對(duì)方已經(jīng)走開!\n");

left=1;

break;

//exit(0);

}

for(i=0;i

printf("\b");

printf("對(duì)方:%s\n",buf);

printf("我:");

fflush(stdout);

}

}

close(rfd);

returnNULL;

}

void*write_to()

{

intwfd;

char buf[BUF_SIZE];

intlen;

umask(0);

if(mkfifo(FIFO_WRITE,S_IFIFO|0666)){

printf("Can't create FIFO %s because %s",FIFO_WRITE,

strerror(errno));

exit(1);

}

umask(0);

wfd=open(FIFO_WRITE,O_WRONLY);

if(wfd==-1){

printf("open FIFO %s error: %s",FIFO_WRITE,strerror(errno));

exit(1);

}

while(left!=1){

printf("我: ");

fgets(buf,BUF_SIZE,stdin);

buf[strlen(buf)-1]='\0';

if(strcmp(buf,"不理你了")==0||left==1){

write(wfd,buf,strlen(buf));//通知對(duì)方

close(wfd);

unlink(FIFO_WRITE);

exit(0);

}

write(wfd,buf,strlen(buf));

fflush(stdin);

}

}

intmain(intargc,char*argv[])

{

pthread_t thIDr,thIDw;

pthread_create(&thIDr,NULL,(void*)read_buf,NULL);

pthread_create(&thIDw,NULL,(void*)write_to,NULL);

pthread_join(thIDr,NULL);

pthread_join(thIDw,NULL);

return 0;

}

學(xué)以置用,呵呵,效果如下:

注:本博客的文章除注明有“轉(zhuǎn)載”字樣的外,均為原創(chuàng),歡迎轉(zhuǎn)載,請(qǐng)注明文字出處,謝謝!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容