进程间通信——管道

进程间通信通过内核中的缓存实现,管道是其中一种方式。创建管道使用pipe()系统调用,常用于父子进程通信。管道单向传输,读写端需关闭一端以确保通信。当管道满或空时,相应操作会阻塞。管道容量有限,默认65536字节,可通过fcntl调整。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、进程间通信

    每个进程有独立的用户地址空间,所以一个进程是看不到另一个进程中的数据包括全局变量。进程间通信是需要通过内核来进行的,内核中开辟一块缓存,不同的进程将数据写到这里或从这里读取,从而实现不同进程之间的通信,内核提供的这种机制称为进程间通信。进程间通信方式有多种,不同的方式提供的共享资源形式不同或者提供者不同。管道就是这其中的一种。

2、管道的创建

    管道的创建使用pipe()系统调用,关于此系统调用可参见另一篇文章中的描述——高级IO函数

3、管道实现进程间通信

    管道一般用于有关系的进程之间的通信,例如父子进程之间的通信:

  • 父进程创建了一个管道,f[0]、f[1]分别为管道两端的文件描述符
  • 父进程通过fork函数创建子进程,此时子进程继承了父进程的管道,也有一对文件描述符f[0]、f[1]。
  • 由于管道只能单向传输数据,所以父子进程必须一个关闭f[0],另一个关闭f[1],才能实现通信。如下图所示,即为管道实现进程间通信的抽象描述。



    管道实现进程间通信代码示例:

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
int main()
{
	int fd[2];
	int ret = pipe(fd);
	if(ret == -1)
	{
		printf("pipe error\n");
		return 1;
	}

	pid_t id = fork();
	if(id == 0)   //子进程
	{
		close(fd[1]);
		char buf[100];
		while(1)
		{
			memset(buf, '\0', sizeof(buf));
			size_t s = read(fd[0], buf, sizeof(buf));
			if(s > 0)
			{
				buf[s - 1] = '\0';
				printf("%s", buf);
			}
			else
				break;
		}
		close(fd[0]);
		return 0;
	}
	else if(id > 0)  //父进程
	{
		close(fd[0]);
		char* wrbuf = "hello world";
		int i = 5;
		while(i--)
		{
			ret = write(fd[1], wrbuf, strlen(wrbuf));
			if(ret < 0)
			{
				printf("write error\n");
				break;
			}
			sleep(2);
		}
		close(fd[1]);
		int stat_loc;
		wait(&stat_loc);
		return 0;
	}
	else
	{
		printf("fork error\n");
		return 1;
	}
}

4、管道的读写状态

  • 当管道容量满时,且读端文件描述符引用计数大于0,则再次调用write会阻塞;
  • 当读端文件描述符引用计数等于0,写端再次调用write时,进程会收到SIGPIPE信号,导致进程终止;
  • 当管道数据为空时,且写端文件描述符引用计数大于0,则再次调用read会阻塞,直到有数据可读;
  • 当写端文件描述符引用计数等于0,读端再次调用read时,返回0,如同读到文件末尾(EOF)。

5、管道容量

    管道有一个容量限制,规定了如果应用程序没有将数据从管道中读走的话,该管道最多能被写入的数据字节数。当前的Linux,管道容量默认为65536字节,也可以使用fcntl函数修改管道容量。

    测试管道容量,可以采用对管道只写不读,当write阻塞时说明管道已满,计算write进去的数据字节数,即为管道容量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值