Linux下进程间通信的原理
了解 Linux IPC 相关的概念和原理有助于我们理解 Binder 通信原理。因此,在介绍 Binder 跨进程通信原理之前,我们先聊聊 Linux 系统下传统的进程间通信是如何实现。
⼀、基本概念
Linux 进程间通信的原理图如下图所⽰:
可以看出来,Liunx 中跨进程通信涉及到的⼀些基本概念如下:
进程隔离
进程空间划分:⽤户空间(User Space)/内核空间(Kernel Space)
系统调⽤:⽤户态/内核态
1. 进程隔离
简单的说就是操作系统中,进程与进程间内存是不共享的。两个进程就像两个平⾏的世界,A 进程没法直接访问 B 进程的数据,这就是进程隔离的通俗解释。
A 进程和
B 进程之间要进⾏数据交互就得采⽤特殊的通信机制:进程间通信(IPC)。
2. 进程空间划分
操作系统的核⼼是内核,独⽴于普通的应⽤程序,可以访问受保护的内存空间,也可以访问底层硬件设备的权限。
为了保护⽤户进程不能直接操作内核,保证内核的安全,操作系统从逻辑上将虚拟空间划分为⽤户空间(User Space)和内核空间(Kernel Space)。简单的说就是,内核空间(Kernel)是系统内核运⾏的空间,⽤户空间(User Space)是⽤户程序运⾏的空间。为了保证安全性,它们之间是隔离的。
3. 系统调⽤:⽤户态与内核态
虽然从逻辑上进⾏了⽤户空间和内核空间的划分,但不可避免的⽤户空间需要访问内核资源,⽐如⽂件
操作、访问⽹络等等。为了突破隔离限制,就需要借助系统调⽤来实现。系统调⽤是⽤户空间访问内核空间的唯⼀⽅式,保证了所有的资源访问都是在内核的控制下进⾏的,避免了⽤户程序对系统资源的越权访问,提升了系统安全性和稳定性。
Linux 使⽤两级保护机制:0 级供系统内核使⽤,3 级供⽤户程序使⽤。
进程通信方式当⼀个任务(进程)执⾏系统调⽤⽽在内核代码中执⾏时,称进程处于内核运⾏态(内核态)。此时处理器处于特权级最⾼的(0级)内核代码中执⾏。当进程处于内核态时,执⾏的内核代码会使⽤当前进程的内核栈。每个进程都有⾃⼰的内核栈。当进程在执⾏⽤户⾃⼰的代码的时候,我们称其处于⽤户运⾏态(⽤户态)。此时处理器在特权级最低的(3级)⽤户代码中运⾏。
系统调⽤主要通过如下两个函数来实现:
copy_from_user() //将数据从⽤户空间拷贝到内核空间
copy_to_user() //将数据从内核空间拷贝到⽤户空间
⼆、Linux下的传统IPC通信原理
通常的做法是消息发送⽅将要发送的数据存放在内存缓存区中,通过系统调⽤进⼊内核态。然后内核程
序在内核空间分配内存,开辟⼀块内核缓存区,调⽤ copyfromuser() 函数将数据从⽤户空间的内存缓存区拷贝到内核空间的内核缓存区中。同样的,接收⽅进程在接收数据时在⾃⼰的⽤户空间开辟⼀块内存缓存区,然后内核程序调⽤ copytouser() 函数将数据从内核缓存区拷贝到接收进程的内存缓存区。这样数据发送⽅进程和数据接收⽅进程就完成了⼀次数据传输,我们称完成了⼀次进程间通信。
三、传统的IPC通信存在的问题
1. 性能低下:⼀次数据传递需要经历内存缓存区 --> 内核缓存区 --> 内存缓存区,需要 2 次数据拷贝;
2. 接收端⽆法确定存储空间:接收数据的缓存区由数据接收进程提供,但是接收进程并不知道需要多⼤的空间来存放将要传递过来的数据,因此只能开辟尽可能⼤的内存空间或者先调⽤ API 接收消息头来获取消息体的⼤⼩,这两种做法不是浪费空间就是浪费时间.
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论