普通管道和命名管道

来源:互联网 发布:同期数据对比表格模板 编辑:程序博客网 时间:2024/06/10 02:27
管道分为普通管道和命名管道;两者都是半双工的。
普通管道只能用于父子进程或兄弟进程间的通信,因为普通管道通过fork调用来拷贝文件描述符的,在文件系统中,普通管道并不对应物理文件。
命名管道在文件系统中有物理文件存在,因此可以用于非亲属的进程间通信。

1、普通管道

#include<unistd.h>

int pipe(int fd[2])
用于创建管道,创建后fd[0]和fd[1]在同一个进程用,再用fork系统调用产生子进程,父子进程一个关闭读端fd[0],另一个关闭写端fd[1],之后就可以用于通信了,用普通的I/O函数read、write、close即可。
如果管道输入端关闭,从管道读数据会以为读到了数据的末尾,读函数返回读到的字节数为0。
向管道写数据时,如果管道缓冲区有空闲,则会写入,否则一直阻塞。管道的缓冲区在内存,是有限的,一般为缓冲区分配一个页面的大小。如果管道读端关闭,则写数据会出错,产生信号SIFPIPE。

管道传输的是无格式的字节流,用管道通信时双方要约定好数据格式

在shell中使用|就是用了管道通信,如经常使用的grep操作。

#include<stdio.h>#include<unistd.h>#include<sys/types.h>#include<errno.h>char readbuf[100];char writebuf[100];int main(){int fd[2];pid_t pid;if(pipe(fd)<0)printf("create pipe error\n");if((pid=fork())<0){printf("fork error\n");exit(-1);}if(pid==0)//子进程{close(fd[0]);//关闭读端strcpy(writebuf,"hello world");int num=write(fd[1],writebuf,strlen(writebuf));printf("child wirite %d bytes\n",num);close(fd[1]);printf("child close fd[1]\n");sleep(10);//等待父进程读}else if(pid>0)//父进程{close(fd[1]);//关闭写端sleep(5);//等待,确保子进程写入数据printf("\n");int num=read(fd[0],readbuf,100);printf("read data is %s\n",readbuf);close(fd[0]);exit(1);}return 1;}

2、命名管道

命名管道以文件的形式存在于文件系统中,及时无亲缘关系的进程在系统中打开该文件即可通信。命令管道遵守FIFO先进先出,对命名管道读
总是从开始处返回数据,对它写则是添加到末尾,不支持lseek等操作。
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char * pathname, mode_t mode)
创建命名管道用mkfifo,第一个参数是路径,第二个参数是模式,与open相同。如果第一个参数是已存在的路径名,则会出错返回EEXIST。用I/O操作
函数即可操作命名管道,只是比普通管道多了个open操作。
命名管道不同于普通文件,命名管道打开时,要有两个进程,一个读一个写来打开。
如果当前进程打开操作是为读而打开FIFO时,若已经有相应进程为写而打开该FIFO,则当前打开操作将成功返回;否则,可能阻塞直到有相应进程为写而打开该FIFO(当前打开操作设置了阻塞标志);或者,成功返回(当前打开操作没有设置阻塞标志)。
如果当前进程打开操作是为写而打开FIFO时,如果已经有相应进程为读而打开该FIFO,则当前打开操作将成功返回;否则,可能阻塞直到有相应进程为读而打开该FIFO(当前打开操作设置了阻塞标志);或者,返回ENXIO错误(当前打开操作没有设置阻塞标志)
在管道使用完后,用unlink删除管道。
fifo1.c建管道,写数据
#include<sys/types.h>#include<sys/stat.h>#include<errno.h>#include<fcntl.h>#define PATH "/tmp/namedpipe"char buf[100];int main(){int fd;if(mkfifo(PATH,O_CREAT|O_EXCL)<0)printf("can't create namedpipo\n");if((fd=open(PATH,O_WRONLY,0))!=-1)printf("open namedpipe success\n");strcpy(buf,"this is a test namedpipe program");int num=write(fd,buf,strlen(buf));if(num>0)printf("write data length is %d\n",num);return 1;}

fifo2.c读管道数据,之后删除管道
#include<sys/types.h>#include<sys/stat.h>#include<errno.h>#include<fcntl.h>#define PATH "/tmp/namedpipe"char buf[100];int main(){int fd;fd=open(PATH,O_RDONLY,0);if(fd<0)printf("open namedpipe error\n");if(fd>0)printf("open named pipe success\n");int num=read(fd,buf,100);if(num>0){printf("read data length is %d\n",num);printf("read data is %s\n",buf);}unlink(PATH);return 1;}





1 0
原创粉丝点击