进程间通信——管道

管道有两种:无名管道和有名管道。管道是半双工通讯。管道只在内存上开辟空间,不会在磁盘上开辟空间。

半双工通讯指数据可以沿两个方向传送,但同一时刻只能有一个方向的传送


先来说说无名管道吧:

无名管道是由调用pipe函数创建的;函数原型如下:

#include <unistd.h> //头文件

int pipe(int filedes[2]);//函数原型     

返回值:成功返回0,出错返回-1

参数filedes返回两个文件描述符:filedes[0]为读而打开,filedes[1]为写而打开


无名管道它们只能在具有公共祖先的进程之间使用。通常,一个管道由一个进程创建,然后该进程调用fork,此后父、子进程之间就可以应用该管道。


调用fork之后做什么取决于我们想要有的数据流的方向。对于从父进程到子进程的管道,则父进程应关闭管道的读端(fd[0]),

子进程则关闭写端(fd[1]).对于从子进程到父进程的管道,则与之相反。


下面我们用代码来简单实现无名管道:

void main()
{
	int fd[2];
	pipe(fd);//创建无名管道,并且将fd[0]绑定为读,fd[1]绑定为写
	pid_t pid = fork(); //创建子进程
	assert(pid != -1);
	
	//这是从子进程到父进程的管道
	if(pid == 0)
	{
		close(fd[0]); //子进程关闭读端
		while(1)
		{
			printf("please input data: ");  
			fflush(stdout);
			char buff[128] = {0};
			fgets(buff, 128, stdin);   //输入数据到buff中
			buff[strlen(buff) - 1] = 0;
			if(strcmp(buff, "end") == 0) //以‘end’结束
			{
				break;
			}
			write(fd[1], buff, strlen(buff));  //将buff中的数据写入到管道中
		}
		close(fd[1]);  //写完关闭写端
	}
	else
	{
		close(fd[1]); //父进程关闭写端
		while(1)
		{
			char buff[128] = {0};
			int n = read(fd[0], buff, 127); //从管道读端读取数据,读到buff中
			if(n == 0)
			{
				break;
			}
			
			//打开一个文件a.txt,没有的话在当前路径下创建
			int fda = open("a.txt", O_WRONLY | O_CREAT | O_APPEND, 0664); 

			assert(fda != -1);
			write(fda, buff, n); //将buff中的数据写到a.txt中
			close(fda);//关闭文件
		}
		close(fd[0]); //读完关闭管道的读端
	}
}


接下来我们看看有名管道(FIFO):

FIFO,管道只能由相关进程使用,这些相关进程的共同的祖先进程创建了管道。但是,通过FIFO,不相关的进程也能交换数据。

FIFO是一种文件类型。创建FIFO类似创建文件。

#include <sys/stat.h>

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

返回值,成功则返回0,出错返回-1;

pathname:是创建的文件名字

mode:创建新文件时使用,eg:O_APPEND,O_CREAT (这个和open函数第三个参数一样,具体见open参数)。

如果已经用mkfifo创建了一个FIFO,就可用open打开它。


当打开一个FIFO时,非阻塞标志(O_NONBLOCK)会产生下列影响。

没有指定O_NONBLOCK:open使用时会阻塞运行:如果只有只读打开或者只写打开的时候,open函数会阻塞,直到另一个进程以另一种方式打开此文件。

指定了O_NONBLOCK,则只读的open会立即返回。但是,如果没有进程已经为读而打开一个FIFO,name只写open将会出错返回-1.


read读取数据时:如果没有进程给管道里写数据,read会阻塞,直到有数据或写端关闭。


管道文件如果进行读操作,读了之后文件内存就清空,不存在了。


代码简单实现:

void main()
{
	int fd = open("FIFO", O_WRONLY); //A进程以只写的方式打开,open会阻塞,直到另一个进程以另一种方式打开
	assert(fd != -1);

	printf("fifo file open over\n");
	sleep(1);
	int n = write(fd, "hello word", strlen("hello word")); //往FIFO里面写了hello word
	close(fd);
	printf("data write file\n");
}
void main()
{
	
	int fd = open("FIFO", O_RDONLY);//B进程以只读打开
	assert(fd != -1);

	printf("fifo file open over\n");
	char buff[128] = {0};
	int n = read(fd, buff, 127); //从FIFO里面读数据,读到buff中
	close(fd);
	printf("buff = %s\n", buff); 
	printf("data write file\n");
}

A进程会阻塞在open,等到B进程运行,以另一种方式打开FIFO时,A进程才不阻塞,往下运行,写入数据,B进程从FIFO管道文件中读数据。





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值