1管道(無名管道)介紹
int pipe(int fd[2]); //成功返回0,失敗返回-1;
pipefd[0]元素的描述符為管道讀端,
只能用來讀;pipe[1]元素的描述符為管道寫端,只能用來寫。
在使用管道時,應(yīng)該將對自己來說沒有的一端關(guān)閉close(),然后再使用自己需要的一端read()或write()
2 管道讀寫規(guī)則
當(dāng)沒有數(shù)據(jù)可讀時
- O_NONBLOCK disable:read調(diào)用阻塞,即進程暫停執(zhí)行,一直等到有數(shù)據(jù)來到為止。
- O_NONBLOCK enable:read調(diào)用返回-1,errno值為EAGAIN。
當(dāng)管道滿的時候
- O_NONBLOCK disable: write調(diào)用阻塞,直到有進程讀走數(shù)據(jù)
- O_NONBLOCK enable:調(diào)用返回-1,errno值為EAGAIN
如果所有管道寫端對應(yīng)的文件描述符被關(guān)閉,則read返回0
如果所有管道讀端對應(yīng)的文件描述符被關(guān)閉,則write操作會產(chǎn)生信號SIGPIPE
當(dāng)要寫入的數(shù)據(jù)量不大于PIPE_BUF時,Linux將保證寫入的原子性。
當(dāng)要寫入的數(shù)據(jù)量大于PIPE_BUF時,linux將不再保證寫入的原子性。
3測試代碼
#include<sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
int main(void)
{
int pip_fd[2];
pid_t pid;
char buf_r[100];
char *buf_w;
int r_num;
if(pipe(pip_fd)<0)
{
printf("pipe create fail \n");
exit(1);
}
if((pid=fork())==-1)
{
printf("fork fail \n");
exit(1);
}else if(0==pid)//子進程
{
close(pip_fd[0]);
printf("write pip sleep 3 sec *****************************\n");
sleep(3);
if(-1!=write(pip_fd[1],"hello 123",strlen("hello 123")))
{
printf("write hello 123 \n");
}
if(-1!=write(pip_fd[1],"ok get 456",strlen("ok get 456")))
{
printf("write ok get 456 \n");
}
close(pip_fd[1]);
printf("writed *****************************\n");
exit(0);
}else
{
close(pip_fd[1]);
printf("start read====================\n ");
if((r_num=read(pip_fd[0],buf_r,100))>0)
{
printf("read len :%d -%s\n",r_num,buf_r);
}
close(pip_fd[0]);
printf("have readed====================\n ");
exit(0);
}
}
4非阻塞方式
當(dāng)管道中的數(shù)據(jù)被讀取后,管道為空。一個隨后的read()調(diào)用將默認的被阻塞,等待某些數(shù)據(jù)寫入。
若需要設(shè)置為非阻塞,則可做如下設(shè)置:
fcntl(filedes[0], F_SETFL, O_NONBLOCK);
fcntl(filedes[1], F_SETFL, O_NONBLOCK);