【Linux】进程间通信机制——管道

进程间通信机制

进程间通信机制又称IPC机制,包括管道、信号量、共享内存、消息队列、套接字。
今天先简单介绍一下IPC机制之一的管道。

管道

在Linux系统中操作时,你一定会用到管道。
管道可以用来在两个进程之间传递数据,比如:

ps -ef | grep “bash”

其中‘|’就是管道,其作用就是将 ps 命令的结果写入管道文件,然后 grep 再从管道文件中读出该数据进行过滤。
那么现在大家可以思考一个问题:
如果进程 a 要将从键盘获取的数据循环传递给另一个进程 b, 用已具备的知识思考应该如何完成?
我们可以有很多种方法,比如:把进程a获取的数据放在一个文件中,然后再让进程b去获取。
但是,我们知道文件是存放在磁盘中的,从磁盘中获取数据速度肯定是非常慢的,那么我们可以把他放在内存中可以加快获取速度。
而我们的管道就是存放在内存中的,可以把进程a的数据暂时放在管道中,进程b从管道中获取数据。

有名管道

有名管道可以在任意两个进程之间通信。
有名管道的创建方法:

  1. 命令创建:
mkfifo fifo //fifo是管道名
  1. 系统调用创建
#include <sys/types.h>
#include <sys/stat.h>
//filename 是管道名 mode 是创建的文件访问权限
int mkfifo(const char *filename, mode_t mode);

命令创建结果如图:
在这里插入图片描述

现在我们通过有名管道来解决我们刚才思考的问题。
进程a的代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
#include <fcntl.h>

int main()
{
	int fd = open("FIFO", O_WRONLY);
	assert(fd != -1);

	printf("open FIFO success\n");

	while(1)
	{
		printf("please input: ");
		char buff[128] = {0};

		fgets(buff, 128, stdin);

		write(fd, buff, strlen(buff) - 1);

		if(strncmp(buff, "end", 3) == 0)
		{
			break;
		}
	}
	
	close(fd);
	exit(0);
}

进程b的代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
#include <fcntl.h>

int main()
{
	int fd = open("FIFO", O_RDONLY);
	assert(fd != -1);

	printf("open FIFO success\n");

	while(1)
	{
		char buff[128] = {0};
		int n = read(fd, buff, 127);

		if(n <= 0 || 0 == strncmp(buff, "end", 3))
		{
			break;
		}

		printf("%s\n", buff);
	}

	close(fd);
	exit(0);
}

运行结果如下:
在这里插入图片描述

无名管道

无名管道主要应用于父子进程间的通信。
无名管道的创建方式:

#include <unistd.h>
/*
pipe()成功返回 0,失败返回-1
fds[0]是管道读端的描述符
fds[1]是管道写端的描述符
*/
int pipe(int fds[2]);

无名管道代码演示:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>

int main()
{
	int fd[2];

	int res = pipe(fd);
	assert( res != -1 );

	pid_t pid = fork();

	assert( pid != -1 );

	if( pid == 0 )//子进程操作
	{
	    close(fd[1]);//关闭写端
		char buff[128] = {0};
		read(fd[0], buff, 127);
		printf("child read: %s\n", buff);
		close(fd[0]);//关闭读端
	}
	else
	{
		close(fd[0]);
		write(fd[1], "hello", 5);
		close(fd[1]);
	}

	exit(0);
}

运行结果如下:
在这里插入图片描述

管道的特点

  • 无论有名还是无名,写入管道的数据都在内存中
  • 管道是一种半双工通信方式(通信方式有单工、半双工、全双工)
  • 有名和无名管道的区别:有名可以在任意进程间使用,而无名主要在父子进程间。

那么管道是怎样实现的呢?
管道其实像一个循环队列一样,有头指针和尾指针控制管道间的数据。
具体表现为下图:
在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
C语言中,管道是一种进程间通信(IPC)机制,可以让不同的进程之间进行数据传输。一般情况下,管道都是由一个进程创建,在这个进程中,管道被用来读或写数据,另一个进程则可以从管道中读取或写入数据。 在C语言中,管道的创建可以使用pipe()函数实现。该函数的原型如下: ```c #include <unistd.h> int pipe(int fd[2]); ``` 其中,fd[0]表示读取管道数据的文件描述符,fd[1]表示写入管道数据的文件描述符。调用pipe()函数后,它会返回两个文件描述符,这两个文件描述符都可以用于读写管道数据。 下面是一个简单的例子,展示了如何使用管道进行进程间通信: ```c #include <stdio.h> #include <unistd.h> int main() { int fd[2]; pid_t pid; char buf[1024]; // 创建管道 if (pipe(fd) < 0) { printf("pipe error!\n"); return -1; } // 创建子进程 if ((pid = fork()) < 0) { printf("fork error!\n"); return -1; } else if (pid > 0) { // 父进程 close(fd[0]); // 关闭读取管道数据的文件描述符 write(fd[1], "hello world\n", 12); // 向管道中写入数据 } else { // 子进程 close(fd[1]); // 关闭写入管道数据的文件描述符 read(fd[0], buf, 1024); // 从管道中读取数据 printf("%s", buf); } return 0; } ``` 在上面的例子中,我们首先创建了一个管道,然后通过fork()函数创建了一个子进程。在父进程中,我们关闭了读取管道数据的文件描述符,然后通过write()函数向管道中写入了一段字符串。在子进程中,我们关闭了写入管道数据的文件描述符,然后通过read()函数从管道中读取数据,并将读取到的数据输出到控制台上。 需要注意的是,管道只能用于具有亲缘关系的进程间通信,也就是说,管道只能在父进程和它创建的子进程之间使用。如果要在不同的进程之间进行通信,可以使用其他的IPC机制,比如消息队列、共享内存等。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值