使用fifo文件实现进程间通信

        fifo 文件是一种先进先出的特殊文件,即命名管道。从 man7 上可以看到 fifo 的相关信息,摘抄如下:

        A FIFO special file (a named pipe) is similar to a pipe, except
       that it is accessed as part of the filesystem.  It can be opened
       by multiple processes for reading or writing.  When processes are
       exchanging data via the FIFO, the kernel passes all data
       internally without writing it to the filesystem.  Thus, the FIFO
       special file has no contents on the filesystem; the filesystem
       entry merely serves as a reference point so that processes can
       access the pipe using a name in the filesystem.

       The kernel maintains exactly one pipe object for each FIFO
       special file that is opened by at least one process.  The FIFO
       must be opened on both ends (reading and writing) before data can
       be passed.  Normally, opening the FIFO blocks until the other end
       is opened also.

        根据上述描述可以知道,通过 fifo 文件能够实现进程间通信。下面代码展示了进程间通信的demo。在进程间通信时,设定 client 和 server。其中,client 发送数据,server 接收数据,并且同时启动多个 client,在 server 侧观察接收到的数据是否正常。

        通信过程中的结构体定义:

struct data {
	char name[16];
	int pid;
	int num;
};

        client.c 代码:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include "common.h"

const char *fifo = "/tmp/fifo";

int main(int argc, char *argv[])
{
	int idx = 0;
	struct data d;
	int fd;

	if (argc != 2) {
		printf("Usage: %s prompt\n", argv[0]);
		return -1;
	}

	fd = open(fifo, O_WRONLY);
	if (fd == -1) {
		perror("open fifo failed");
		return -1;
	}

	memset(d.name, 0, 16);
	strncpy(d.name, argv[1], 15);
	d.pid = getpid();

	printf("begin to send data ...\n");
	while (idx < 100) {
		d.num = idx++;
		write(fd, &d, sizeof(struct data));
		sleep(1);
	}

	return 0;
}

        server.c 代码:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include "common.h"

const char *fifo = "/tmp/fifo";

int main(void)
{
	int fd;
	struct data d;
	int ret;

	fd = open(fifo, O_RDONLY);
	if (fd == -1) {
		perror("open fifo failed");
		return -1;
	}

	printf("begin to receive data ...\n");
	while (1) {
		ret = read(fd, &d, sizeof(struct data));
		if (ret < sizeof(struct data))
			break;
		printf("%s, %d, %d\n", d.name, d.pid, d.num);
		sleep(1);
	}

	return 0;
}

运行效果:

1)创建 fifo 文件

$ mkfifo /tmp/fifo

2)启动第 1 个 client

$ ./client proc1

3)启动第 2 个 client

$ ./client proc2

4)启动 server

$ ./server
begin to receive data ...
proc2, 2348917, 0
proc1, 2348910, 0
proc2, 2348917, 1
proc1, 2348910, 1
proc2, 2348917, 2
proc1, 2348910, 2
proc2, 2348917, 3
proc1, 2348910, 3
...

        从运行结果来看,正如上面引用中的描述那样,client 在调用 open 打开 fifo 文件时,会发生阻塞,一直到 server 也调用 open 打开 fifo 文件为止。

注意:

        当打开 fifo 文件的某个进程退出时,其他打开该 fifo 文件的进程将会收到 SIGPIPE 信号,默认处理是退出当前进程,因此必要时需要对该信号进行自定义处理。

参考资料:

1. https://www.man7.org/linux/man-pages/man7/fifo.7.html

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值