Linux进程间通信方式

1. 管道:简单

在这里插入图片描述

实现原理: 操作系统的内核借助环形队列机制,使用内核缓冲区实现。

特质: 1. 伪文件

	  2. 管道中的数据只能一次读取。

	  3. 数据在管道中,只能单向流动。


局限性:1. 自己写,不能自己读。

	   2. 数据不可以反复读。

	   3. 半双工通信。

	   4. 血缘关系进程间可用。

	pipe函数:	创建,并打开管道。

函数用法:

int pipe(int fd[2]);

参数:fd[0]: 读端

	 fd[1]: 写端。
一个管道通信的示例,父进程往管道里写,子进程从管道读,然后打印读取的内容:
1.	#include <stdio.h>  
2.	#include <stdlib.h>  
3.	#include <string.h>  
4.	#include <unistd.h>  
5.	#include <errno.h>  
6.	#include <pthread.h>  
7.	  
8.	void sys_err(const char *str)  
9.	{  
10.	    perror(str);  
11.	    exit(1);  
12.	}  
13.	  
14.	int main(int argc, char *argv[])  
15.	{  
16.	    int ret;  
17.	    int fd[2];  
18.	    pid_t pid;  
19.	  
20.	    char *str = "hello pipe\n";  
21.	    char buf[1024];  
22.	  
23.	    ret = pipe(fd);  
24.	    if (ret == -1)  
25.	        sys_err("pipe error");  
26.	  
27.	    pid = fork();  
28.	    if (pid > 0) {  
29.	        close(fd[0]);       // 关闭读段  
30.	        //sleep(3);  
31.	        write(fd[1], str, strlen(str));  
32.	        close(fd[1]);  
33.	    } else if (pid == 0) {  
34.	        close(fd[1]);       // 子进程关闭写段  
35.	        ret = read(fd[0], buf, sizeof(buf));  
36.	        printf("child read ret = %d\n", ret);  
37.	        write(STDOUT_FILENO, buf, ret);  
38.	  
39.	        close(fd[0]);  
40.	    }  
41.	  
42.	    return 0;  
43.	}  

2. 命名管道FIFO

管道的优劣:
	优点:1. 相比信号、套接字实现进程通信要简单很多
		 2. 可用于无血缘关系的进程间通信
	
	缺点:1.只能单向通信,双向通信需建立两个管道
         2.只能用于有血缘关系的进程间通信。该问题后来使用fifo命名管道解决。

命名管道函数:mkfifo

	读端,open fifo O_RDONLY

	写端,open fifo O_WRONLY

一个写fifo,一个读fifo,操作起来就像文件一样

在这里插入图片描述
在这里插入图片描述

2. 信号:开销小

  • 信号是软件层面上的“中断”。一旦信号产生,无论程序执行到什么位置,必须立即停止运行,处理信号。

  • 所有信号的产生及处理全部都是由【内核】完成的。

      产生信号:
    
      1. 按键产生:Ctrl+c、Ctrl+z
    
      2. 系统调用产生:kill
    
      3. 软件条件产生:	
      		alarm函数——设置定时器,发送14)SIGALARM信号
      		settime函数
    
      4. 硬件异常产生:除0操作、非法访问内存(段错误)
    
      5. 命令产生:kill命令
    
    
      signal实现指定的信号捕捉,并设置相关的操作函数handler
    

    概念:

      未决信号:产生与递达之间状态。  
    
      递达信号:产生并且送达到进程。直接被内核处理掉。
    
      信号处理方式: 执行默认处理动作、忽略、捕捉(自定义)
    
      本质是位图的两个信号集
      阻塞信号集(信号屏蔽字): 记录信号的屏蔽状态。
      一旦被屏蔽的信号,在解除屏蔽前,一直处于未决态。
    
      未决信号集:记录信号的处理状态。
      该信号集中的信号,表示已经产生,但尚未被处理。
    

在这里插入图片描述

3. mmap映射:非血缘关系进程间

存储映射I/O(Memory-mapped I/O) 使一个磁盘文件与存储空间中的一个缓冲区相映射。

从缓冲区中取数据,就相当于读文件中的相应字节。

与此类似,将数据存入缓冲区,则相应的字节就自动写入文件。
这样就可在不使用read、write函数的情况下,使地址指针完成I/O操作。
减少用户空间到内核空间的传输成本。

使用方法:首先通知内核,将一个指定文件映射到存储区域中。
这个映射工作可以通过mmap函数来实现。

mmap函数:

创建共享内存映射
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);		

参数:
	addr:指定映射区的首地址。通常传NULL,表示让系统自动分配

	length:共享内存映射区的大小。(<= 文件的实际大小)

	prot:共享内存映射区的读写属性。PROT_READ、PROT_WRITE、PROT_READ|PROT_WRITE

	flags:标注共享内存的共享属性。MAP_SHARED(修改会反映到磁盘上)、MAP_PRIVATE(修改不反映到磁盘上)

	fd:用于创建共享内存映射区的那个文件的 文件描述符。

	offset:默认0,表示映射文件全部。偏移位置。需是 4k 的整数倍。


释放映射区。
int munmap(void *addr, size_t length);		

addr是mmap函数的返回值
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值