linux命名管道实现多进程间通信,Linux进程间通信-命名管道(示例代码)

本文介绍了进程间通信中的匿名管道和命名管道。匿名管道仅适用于父子进程,而命名管道则允许任意相关进程通过共享的FIFO文件进行数据传递。通过mkfifo函数可以创建命名管道,然后使用open函数以读写模式打开。当多个进程写入命名管道时,数据可能会交错,需要采取措施保证写操作的原子性。示例代码展示了如何使用命名管道进行读写操作。
摘要由CSDN通过智能技术生成

前面我们讲了进程间通信的一种方式,匿名管道。

我们知道,匿名管道只能用于父子关系的进程之间。那么没有这种关系的进程之间该如何进行数据传递呢?

1.什么是命名管道

匿名管道是在缓存中开辟的输出和输入文件流的空间,只能用于父子关系的进程之间。因为父子进程的输入和输出文件描述符是一致的。

命名管道是一种实际存在的FIFO文件,称作“管道文件”,用于不同进程之间,命名管道进程间打开同一个FIFO文件,进行数据传递。

我们可以像普通文件一样操作FIFO文件。

不同进程,引用同一个FIFO文件,进行数据传递。

2.创建命名管道

mkfifo函数:创建一个命名管道

int mkfifo(const char *filename,mode_t mode);

filename:指定FIFO文件的名称

mode:指定文件的读写权限

3.访问命名管道

打开FIFO文件有四种方式:

open(const char *filename,O_RDONLY);

open(const char *filename,O_RDONLY|O_NONBLOCK);

open(const char *filename,O_WRONLY);

open(const char *filename,O_WRONLY|O_NONBLOCK);

需要注意的是,不能以O_RDWR模式打开FIFO文件,

因为这样一个进程写入的数据会被该进程读取,FIFO一般只用做单向的数据传递。

open函数的第二个参数,表示是读管道,还是写管道。

O_NONBLOCK表示FIFO管道的读写是非阻塞的,默认的话,是阻塞的。

那么何为阻塞呢?

一个进程写模式打开管道的时候,必须有另一个进程以读模式打开;

或读模式的时候,必须有另一个进程写写模式打开,否则该进程open函数阻塞,直到满足以上关系。

非阻塞,意味着open函数会立即返回,若没有其他进程以只读方式打开,open返回-1,并且FIFO也不会被打开。

4.FIFO管道使用示例

下例有两个程序,fifowrite.c和fiforead.c分别写管道和读管道。

fifowrite.c中将一个文本文件data.txt,写到管道。

fiforead.c中从管道读取数据,并写到dataformfifo.txt文件中。

程序使用了默认的阻塞模式。

示例代码如下:

fifowrite.c

#include#include#include#include#include

intmain()

{const char *fifo_name = "/tmp/my_fifo";int pipe_fd = -1;int data_fd = -1;int res = 0;const int open_mode =O_WRONLY;char buffer[PIPE_BUF+1];if(access(fifo_name,F_OK)==-1)

{

res= mkfifo(fifo_name,0777);if(res!=0)

{

fprintf(stderr,"could not create fifo\n");

exit(EXIT_FAILURE);

}

}

printf("process %d opening fifo O_WRONLY\n",getpid());

pipe_fd=open(fifo_name,open_mode);

data_fd= open("data.txt",O_RDONLY);

printf("process %d result %d\n",getpid(),pipe_fd);if(pipe_fd!=-1)

{int bytes_read = 0;

bytes_read=read(data_fd,buffer,PIPE_BUF);while(bytes_read>0)

{

res=write(pipe_fd,buffer,bytes_read);if(res==-1)

{

fprintf(stderr,"write error\n");

exit(EXIT_FAILURE);

}

bytes_read=read(data_fd,buffer,PIPE_BUF);

buffer[bytes_read]=‘\0‘;

}

close(pipe_fd);

close(data_fd);

}else{

exit(EXIT_FAILURE);

}

printf("process %d finished.\n",getpid());

exit(EXIT_SUCCESS);

}

fiforead.c

#include#include#include#include#include

intmain()

{const char *fifo_name = "/tmp/my_fifo";int pipe_fd = -1;int data_fd = -1;int res = 0;int open_mode =O_RDONLY;char buffer[PIPE_BUF+1];int bytes_read = 0;int bytes_write = 0;

memset(buffer,‘\0‘,sizeof(buffer));

printf("process %d opening FIFO O_RDONLY\n",getpid());

pipe_fd=open(fifo_name,open_mode);

data_fd= open("dataformfifo.txt",O_WRONLY|O_CREAT,0644);

printf("process %d result %d\n",getpid(),pipe_fd);if(pipe_fd!=-1)

{do{

res=read(pipe_fd,buffer,PIPE_BUF);

bytes_write=write(data_fd,buffer,res);

bytes_read+=res;

}while(res>0);

close(pipe_fd);

close(data_fd);

}else{

exit(EXIT_FAILURE);

}

printf("process %d finished,%d bytes read\n",getpid(),bytes_read);

exit(EXIT_SUCCESS);

}

输出结果:

20180110193323714215.png

我们在shell中输入命令 ls -l /tmp/my_fifo查看FIFO管道文件的属性

20180110193323723004.png

可以看到,FIFO文件生成了,第一个字符‘p’,表示该文件是一个管道文件。

5.多个进程同时写管道

当多个进程同时写管道时,读管道取得的数据是杂乱的。

此时,我们可以控制每个进程,当要写入的数据超过某个大小时,才写管道,另外要以阻塞的方式打开FIFO。确保写操作的原子性。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值