4、进程间通信(pipe、fifo、共享内存(shm、mmap函数实现代码))(linux系统编程)

本文介绍了Linux系统编程中的进程间通信(IPC),重点关注了管道(pipe)、命名管道(FIFO)和共享内存(通过mmap函数实现)。详细讲解了如何使用pipe进行父子进程通信,如何配置管道为非阻塞以及查看管道缓冲区大小。对于FIFO,阐述了其创建和通信流程。此外,还深入讨论了共享内存,包括通过mmap映射文件和匿名映射进行进程间通信的应用实例。
摘要由CSDN通过智能技术生成

进程间通信:

任何一个进程的全局变量在另一个进程中都看不到,
所以进程和进程之间不能相互访问,要交换数据必须通过内核,
在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,
进程2再从内核缓冲区把数据读走,

内核提供的这种机制称为进程间通信(IPC,InterProcess Communication)。

进程间通信的方式:

在进程间完成数据传递需要借助操作系统提供特殊的方法,
进程间的七大通信方式
signal、file、
pipe(管道(Pipe)及有名管道(named pipe):就是pipe和fifo)、
shm、sem、msg、socket。

如:文件(fifo 就是文件IO)、管道(管道是一种最基本的IPC机制,也称匿名管道,pipe)、
信号(signal)、信号量(semaphore)、共享内存(shm)、
消息队列(msg)、套接字(UNXI域套接字、网络套接字(Network socket))、(FIFO)命名管道等。
现今常用的进程间通信方式有:
管道 (使用最简单)
信号 (开销最小)
共享映射区 (无血缘关系)
本地套接字 (最稳定)

管道:

1 管道的本质是一块内核缓冲区,内部的实现是环形队列
2 管道有读写两端,读写两端是两个文件描述符
3 数据的流向是从管道的写端流到管道的读端(数据的流向是单项的)
4 数据被读走之后,在管道中就消失了
5 pipe只能用于有血缘关系的进程间通信
6 管道的读写两端是阻塞的
7 管道的大小默认4k,但是会根据实际情况做适当调整。

pipe用于父子进程间通信:

1、父进程创建pipe
2、父进程调用fork函数创建子进程
3、父进程关闭一端
4、子进程关闭一端
5、父进程和子进程分别执行read或者write操作
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>

int main()
{
   
	//创建管道
	//int pipe(int pipefd[2]);
	int fd[2];
	int ret = pipe(fd);
	if(ret<0)
	{
   
		perror("pipe error");
		return -1;
	}

	//创建子进程
	pid_t pid = fork();
	if(pid<0) 
	{
   
		perror("fork error");
		return -1;
	}
	else if(pid>0)
	{
   
		//关闭读端
		close(fd[0]);
		sleep(5);
		write(fd[1], "hello world", strlen("hello world"));	

		wait(NULL);
	}
	else 
	{
   
		//关闭写端
		close(fd[1]);
		
		char buf[64];
		memset(buf, 0x00, sizeof(buf));
		int n = read(fd[0], buf, sizeof(buf));//read函数是阻塞的,因此读到数据之前等父进程写完数据,再继续执行
		printf("read over, n==[%d], buf==[%s]\n", n, buf);
	
	}

	return 0;
}

利用pipe父子进程执行ps aux|grep bash思路分析

在这里插入图片描述

//使用pipe完成ps aux | grep bash操作

#include <stdio.h>
	#include <stdlib.h>
	#include <string.h>
	#include <sys/types.h>
	#include <unistd.h>
	#include <sys/wait.h>

	int main()
	{
   
		//创建管道
		//int pipe(int pipefd[2]);
		int fd[2];
		int ret = pipe(fd);
		if(ret<0)
		{
   
			perror("pipe error");
			return -1;
		}

		//创建子进程
		pid_t pid = fork();
		if(pid<0) 
		{
   
			perror("fork error");
			return -1;
		}
		else if(pid>0)
		{
   
			//关闭读端
			close(fd[0]);

			//将标准输出重定向到管道的写端
			dup2(fd[1], STDOUT_FILENO);
			
			execlp("ps", "ps", "aux", NULL);

			perror("execlp error");
			wait(NULL);//回收子进程
		}
		else 
		{
   
			//关闭写端
			close(fd[1]);
		
			//将标准输入重定向到管道的读端
			dup2(fd[0], STDIN_FILENO);

			execlp("grep", "grep", "--color=auto", "bash", NULL);

			perror("execlp error");
			
		}

		return 0;
	}

管道的读写行为

读操作
	有数据
		read正常读,返回读出的字节数
	无数据
		写端全部关闭
			read解除阻塞,返回0, 相当于读文件读到了尾部
#include<stdio.h>
				#include<stdlib.h>
				#include<string.h>
				#include<sys/types.h>
				#include<unistd.h>
				#include<fcntl.h>
				#include<sys/wait.h>

				int main(int argc,char *argv[])
				{
   
					
					int fd[2];
					int ret = pipe(fd);
					if(ret<0)
					{
   
						perror("pipe error");
						return -1;
					}
					
						write(fd[1],"hello world",strlen("hello world"));
					
						close(fd[1]);//关闭写端
						
						char buf[<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值