无名管道pipe与有名管道fifo

一、无名管道pipe:

1. 无名管道特点:

1)只能用于具有亲缘关系的进程之间的通信。

2)半双工的通信模式,具有固定的读端和写端。

3)管道可以看成是一种特殊的文件,对于它的读写可以使用文件IO如read、write函数。

2.管道创建与关闭

1)管道是基于文件描述符的通信方式。当一个管道建立时,它会创建两个文件描述符fd[0]和fd[1]。其中fd[0]用于读,fd[1]用于写管道。

2)构成了一个半双工的通道。

函数pipe()

头文件:#include<unistd.h>

函数原型:int pipe(int fd[])

函数参数:fd[]      包含两个文件描述符的数组,其中fd[0]固定用于读管道,fd[1]固定用于写管道

函数返回值:成功:0

                     失败:-1

创建管道使用pipe()函数,而其余的操作诸如读取管道read()、写入管道write()、关闭管道close()函数与文件IO的函数使用方式相同,

3. 无名管道读写注意点:

1)当管道中无数据时,读操作会阻塞。

2)无名管道只能实现以下一种方式:

方式1:父进程->子进程:父进程对自己的fd[1]执行写操作,数据流入管道内,然后子进程对自己的fd[0]执行读操作,得到管道内数据

方式2:子进程->父进程:子进程对自己的fd[1]执行写操作,数据流入管道内,然后父进程对自己的fd[0]执行读操作,得到管道内数据

3)只有在管道的读端存在时,向管道中写入数据才有意义。否则,向管道中写入数据的进程将收到内核传来的SIGPIPE信号(通常Broken pipe错误)。

示例程序:

/*************************************************************************

 @Author: wanghao

 @Created Time : Wed 23 May 2018 03:27:53 AMPDT

 @File Name: pipe_demo.c

 @Description:

 ************************************************************************/

#include <unistd.h>

#include <string.h>

#include <stdlib.h>

#include <stdio.h>

int main(void)

{

       intfd[2];

       if(pipe(fd)< 0){

              perror("pipeerror");

              exit(1);

       }

       pid_tpid;

       if((pid= fork())<0){

              perror("forkerror");

              exit(1);

       }elseif(pid > 0){

              close(fd[0]);

              intstart  =1,end =100;

              if(write(fd[1],&start,sizeof(int))!= sizeof(int)){   

                     perror("writeerror");

                     exit(1);

              }

              if(write(fd[1],&end,sizeof(int))!= sizeof(int)){

                     perror("writeerror");

                     exit(1);

              }

              close(fd[1]);

       }else{

              close(fd[1]);

              intstart,end;

              if(read(fd[0],&start,sizeof(int))<0){

                     perror("readerror");

                     exit(1);

              }

              if(read(fd[0],&end,sizeof(int))<0){

                     perror("readerror");

                     exit(1);

              }

              close(fd[0]);

              printf("childprocess read start: %d, end: %d\n",start,end);

       }

       exit(0);

}

二、有名管道fifo

1. FIFO特点

1)无名管道只能用于具有亲缘关系的进程之间

2)有名管道可以使不相关的两个进程互相通信。有名管道可以通过路径来指出,并且在文件系统中可见。

3)进程通过文件IO来操作有名管道。

4)有名管道遵循先进先出规则

5)不支持如lseek操作

2.创建fifo

函数mkfifo()

所需头文件:#include<sys/types.h>

                     #include<sys/stat.h>

函数原型:int mkfifo(const char *pathname,mode_t mode)

函数参数:pathname  要创建的有名管道的路径名与文件名

                mode         创建的有名管道的文件权限码,通常用八进制数字表示

函数返回值:成功:0

                  失败:-1

注:也可以使用mkfifo命令创建有名管道文件

创建fifo失败原因:

EACCESS 参数filename所指定的目录路径无可执行的权限

EEXIST 参数filename所指定的文件已存在

ENAMETOOLONG  参数filename路径名称太长

ENOENT 参数filename包含的目录不存在

ENOSPC 文件系统的剩余空间不足

EROFS 参数filename指定的文件存在于只读文件系统内

示例代码:

1. 首先通过mkfifo fifo创建fifo文件,当然也可以通过mkfifo函数创建

2. 读fifo文件代码如下:

/*************************************************************************

 @Author: wanghao

 @Created Time : Wed 23 May 2018 03:47:48 AMPDT

 @File Name: fifo_read_demo.c

 @Description:

 ************************************************************************/

#include <stdio.h>

#include <stdlib.h>

#include <fcntl.h>

#include <string.h>

int main(int argc,char *argv[])

{

       if(argc<2){

              printf("usage:%s fifo\n",argv[0]);

              exit(1);

       }

       printf("openfifo read...\n");

       intfd = open(argv[1],O_RDONLY);

       if(fd< 0){

              perror("openerror");

              exit(1);

       }else{

              printf("openfile success:%d\n",fd);

       }

       charbuf[512];

       memset(buf,0,sizeof(buf));

       while((read(fd,buf,sizeof(buf)))< 0){

              perror("readerror");

       }

       printf("%s\n",buf);

       close(fd);

       return0;

}

3. 写fifo文件代码如下:

/*************************************************************************

 @Author: wanghao

 @Created Time : Wed 23 May 2018 03:49:15 AMPDT

 @File Name: fifo_write_demo.c

 @Description:

 ************************************************************************/

#include <unistd.h>

#include <memory.h>

#include <stdlib.h>

#include <stdio.h>

#include <fcntl.h>

int main(int argc,char *argv[0])

{

       if(argc< 2){

              printf("usage:%s fifo\n",argv[0]);

              exit(1);

       }

       printf("openfifo write...\n");

       intfd = open(argv[1],O_WRONLY);

       if(fd< 0){

              perror("openerror");

              exit(1);

       }else{

              printf("openfifo success: %d\n",fd);

       }

       char*s = "1234567890";

       size_tsize = strlen(s);

       if(write(fd,s,size)!= size){

              perror("writeerror");

       }

       close(fd);

       exit(0);

}


猜你喜欢

转载自blog.csdn.net/weixin_42048417/article/details/80424472