进程通信篇——2、有名管道

特点:
1)有名管道可以使互不相关的两个进程互相通信
2)有名管道可以通过路径名来指出,并且在文件系统中可见
有名管道的文件名在文件系统可见,但是管道中的数据在内存上
文件系统:一种管理文件的机制,对文件进行管理,维护
不支持如lseek() 操作
3)进程通过文件IO来操作有名管道(先打开,再读写)

管道创建
命令行
mkfifo fifo 创建名为“fifo”的管道,后期权限不足通过chmod修改
unlink fifo 删除名为“fifo”的管道
函数创建
int mkfifo(const char *pathname, mode_t mode);
int unlink(const char *pathname);
具体参数用法建议使用前man一下
管道的操作 参考博客链接:https://blog.csdn.net/aLingYun/article/details/100085981
有名管道在操作上和普通文件一样进行,如:open()、write()、read()、close() 等。但是,和无名管道一样,操作命名管道肯定要考虑默认情况下其阻塞特性。

1.以只读和只写方式 open 管道,并且没有指定非阻塞标志 O_NONBLOCK 。则:

open() 以只读方式打开 FIFO 时,要阻塞到另一个进程为写而打开此 FIFO;
open() 以只写方式打开 FIFO 时,要阻塞到另一个进程为读而打开此 FIFO。
通信过程中若写进程先退出了,就算命名管道里没有数据,调用 read() 函数从 FIFO 里读数据时不阻塞;若写进程又重新运行,则调用 read() 函数从 FIFO 里读数据时又恢复阻塞。
2.以只读和只写方式 open 管道,并指定非阻塞标志 O_NONBLOCK 。则 open() 函数不会阻塞。

非阻塞标志(O_NONBLOCK)打开的命名管道有以下特点:

先以只读方式打开,如果没有进程已经为写而打开一个 FIFO, 只读 open() 成功,并且 open() 不阻塞。
先以只写方式打开,如果没有进程已经为读而打开一个 FIFO,只写 open() 将出错返回 -1 。
read()、write() 读写命名管道中读数据时不阻塞。
3.以可读可写方式 open 管道,则 open() 函数不会阻塞。

特点:

read() 仍会阻塞,缓冲区满时,write() 也会阻塞;
通信过程中,读进程退出后,写进程向命名管道内写数据时,写进程不会退出。
通信过程中若写进程先退出了,如果名管道里没有数据,调用 read() 函数从 FIFO 里读数据时会阻塞,与第一种情况不同。

示例代码 发送进程

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>

#define N 32
int main(int argc, const char *argv[])
{
	int fd;
	int ret;
	ret = mkfifo("fifo", 0775);			//创建有名管道fifo
	if(ret < 0){
		if(errno == EEXIST){			//错误编号为管道已存在(其他进程用户创建),执行打开管道操作
			fd = open("fifo", O_RDWR);
			printf("fd = %d\n", fd);
		}
		else{							//创建失败
			perror("mkfifo error");
			return -1;
		}
	}
	else{								//创建成功并执行打开管道操作
		fd = open("fifo", O_RDWR);	
		printf("fd = %d\n", fd);
	}
	char buf[N] = "";
	while(1){
		fgets(buf, N, stdin);			//获取输入信息
		buf[strlen(buf) - 1] = '\0';

		write(fd, buf, strlen(buf));	//发送至管道

		if(strncmp(buf, "quit", 4) == 0){
			break;
		}
	}
	return 0;
}

示例代码接收端

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#define N 32
int main(int argc, const char *argv[])
{
	int fd;
	int ret;
	ret = mkfifo("fifo", 0775);					//创建有名管道fifo
	if(ret < 0){
		if(errno == EEXIST){								//错误编号为管道已存在(其他进程用户创建),执行打开管道操作
			fd = open("fifo", O_RDWR);
			printf("fd = %d\n", fd);
		}
		else{
			perror("mkfifo error");
			return -1;
		}
	}
	else{
		fd = open("fifo", O_RDWR);	
		printf("fd = %d\n", fd);
	}
	char buf[N] = "";
	while(1){
		memset(buf, 0, N);
		
		read(fd, buf, N);		//读取管道数据

		if(strncmp(buf, "quit", 4) == 0){
			break;
		}

		printf("read:%s\n", buf);
	}
	return 0;
}
在这里插入代码片
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值