Binder(一)Linux进程通信

用户空间、内核空间

Linux分为内核进程和用户进程:
1、内核进程共享一块内存空间,称为内核空间。
2、内核进程不能访问用户空间。
3、用户进程有自独立的地址空间,彼此隔离。
4、用户进程通过系统调用,从用户态陷入内核态,可以访问到内核空间。

用户空间&内核空间

进程通信的手段

1、共享内存
获取一块内存区域,两个用户进程都能够访问,便可实现进程间通信。

共享内存通信原理

2、系统调用
借用内核态可以访问内核空间的特性,通过内核空间进行数据传输:
用户进程A通过系统调用,进入内核态,向内核空间写入数据;
用户进程B通过系统调用,进入内核态,从内核空间读取数据。

系统调用通信原理

进程通信的本质:找到这样一块区域(如内存、磁盘、其他设备等),两个进程都能访问到,再通过这块区域进行数据交互。

Linux中的进程通信

linux中主要的进程通信包括以下几种:

通信方式 性能/拷贝 安全性 稳定性 用途
信号(signal) - - - 事件通知,不适用于信息交换
信号量(Semaphore) - - - 计数器,常被用作锁机制
管道(pipe) 低/2 - 1对1 -
消息队列(Message queues) 低/2 - - -
套接字(Socket) 低/2 C/S架构 -
共享内存(Share Memory) 高/0 考虑并发 用户维护 -
Binder 中/1 高:进程UID标识,鉴别身份 C/S架构 -

管道

管道是利用内核空间进行进程通信的,当进程创建一个管道之后,会返回两个文件描述符Fd[0]、Fd[1];Fd[0]用来读数据,Fd[1]用来写数据。

当进程创建一个管道之后的连接情况
当父进程创建子进程之后的连接情况

此时,如果想通过父进程向子进程通信,可以关闭父进程的Fd[0]和子进程的Fd[1];反之亦然。

父进程写、子进程读
父进程读、子进程写

管道的两次拷贝分别发生在Fd[1]写(将数据从用户空间拷贝到内核空间)、Fd[0]读(将数据从内核空间拷贝到用户空间)。管道通信需要满足几个条件:
1、互斥:读写操作必须互斥进行
2、同步:读写进程等待与唤醒
3、对方存在:只有判断对方存在时才能通信

消息队列

消息队列在内核空间维护了一个msgque链表。


内核空间维护了一个msgque链表
Send流程图

通过wait-signal实现send原语

Procedure Send(rec, a); { rec为接收进程, a为发送区}
Begin
Getbuf(a.size, i); {从自由区中申请空缓冲区i}
i.sender:=a.sender; {把消息从a处copy到缓冲区i}
i.size:=a.size;
i.text:=a.text;
i.next:=0;
GetID(PCB set, rec.j); {获接收进程内部标识符j}
wait(j.mutex);
insert(j.mq , i); {把缓冲区i挂到进程rec消息链尾}
signal(j.mutex);
signal(j.sm);
END

关于Socket相关资料,推荐以下文章:

1、Socket与内核调用深度分析
2、Linux中本机和本机Socket通信会走网卡吗?

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容