我是穿拖鞋的汉子,魔都中坚持长期主义的工程师。
时间马上走到2023年月底,都说工作是为了生活,但如果为了工作,没有了生活,是不是也是挺悲哀的一件事。
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/1f2a5fbf6edabe54cc35995aed675c7b.jpeg#pic_center)
老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师:
穷就是穷,穷不是吃苦,吃苦不是受穷的能力,是自己能够对一件事情长期聚焦的能力。它代表着自己要放弃自己的娱乐,放弃自己无效的社交,还要忍受着不被别人理解的孤独。它其实是一种自制能力和自控能力。比起此刻自己在享受什么,我更想让你知道为了达到目标,我在这些背后付出了什么!
本文接着上文,关于车载软件操作系统内核的关键技术IPC做一个解析。
高效IPC(Inter-Process Communication)技术
在现有车身电子电子架构中,无论是安全车控、智能驾驶还是智能座舱应用,都必然存在着多个任务并发执行的情况。每一个任务都可能对应着一个或多个进程,用户应用进程之间由于可靠性和信息安全的需要采用了各种严格的时隔离手段进行隔离,不能直接进行通信。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DOgjUApe-1677299066303)(https://files.mdnice.com/user/15344/1239d0e2-fc90-4776-b3ff-d8f35e1613bf.jpg)]
但是用户进程间的协作又必须要进行信息交互,因此只能依赖于操作系统内核提供的进程间通信机制来完成,业界称为IPC技术。IPC 机制在实现进程间的数据传递功能的同时,还需要内核通过对进程的运行状态和运行时间的控制来实现控制流从发送者进程到接收者进程的切换(返回的过程类似),从而直接影响系统运行效率。
目前宏内核架构和微内核架构的操作系统都能够提供一些常见的 IPC 通信机制,包括管道、消息队列、信号量、共享内存、套接字Socket等。具体应用场景和特点如下所示:
![](https://i-blog.csdnimg.cn/blog_migrate/0e4619ec984c275b014a278b0d9e0cc0.png)
![](https://i-blog.csdnimg.cn/blog_migrate/c9e1ee47b19d5a628834e74fc23abbe1.png)
![](https://i-blog.csdnimg.cn/blog_migrate/1f6f19d827b4ae6e4c0afe0b02fbb747.png)
![](https://i-blog.csdnimg.cn/blog_migrate/abcc8c4da0e1f378e123bf8a5767dcc8.png)
![](https://i-blog.csdnimg.cn/blog_migrate/a787366284c8ae080933c897f0ba77a2.png)
出于最小内核服务设计的考虑,在微内核架构系统中,类似于驱动,文件系统等传统的内核服务被移到了用户态,许多原本可以通过简单系统调用就可实现的内核功能也必须使用IPC机制来提供服务,在系统负荷较高的情况下可能会面临着比宏内核更加严重的效率问题。因此对微内核系统的研究一般都会将改进IPC效率作为优化系统性能的重要选择之一。
传统的微内核IPC机制设计是通过端口(port)和消息(message)来实现进程间接通信。通信的双方不需要显式指定另一方,而是通过端口进行通信,这样可以将用户进程本身和 IPC 通信隔离开,只要一个进程在内核拥有某个端口,就能通过这个端口和另一端的进程通信。进程之间通过端口流通的数据就是消息。
在微内核IPC通信机制优化方案当中,还有一些比较极端的手段,如迁移线程技术(thread migration)。如果把其他 IPC 通信机制看作将需要处理的数据发送到其他进程(或线程)进行处理的话,那么迁移线程技术就是把其他进程的代码拉进当前进程中运行,这样就会大量减少内核进程切换的代价,同时也能通过共享参数栈和寄存器来简化数据传输,减少序列化开销,优化并发,避免共享的全局数据结构。
在一些学术文献中,迁移线程模型被用在了LRPC(轻量级远程过程调用)技术当中。
![](https://i-blog.csdnimg.cn/blog_migrate/e82797931696a30ec61c7fcfd908bda7.png)
主流IPC的控制流转移
![](https://i-blog.csdnimg.cn/blog_migrate/15c3b034213067909c2b85ebc5b9daa9.png)
上面两张图是主流IPC和迁移线程IPC设计的对比。“要做到 ‘将代码拉到本地’ ,迁移线程首先需要对线程结构进行解耦,明确线程中哪些部分是对通信请求处理起关键作用的。然后,这部分允许被调用者(负责处理请求的逻辑)运行在调用者的上下文中,将跨进程调用变成更接近函数调用的形式。” ,由于篇幅原因,迁移线程模型的实现就不做详细介绍了,具体细节可参考相关文献。
在行业中,即使是一些成熟的系统也会针对特定应用场景提供改进的 IPC 机制,比如 Android 系统(宏内核)就使用了 Binder IPC 机制来改进进程通信效率。Binder IPC 机制中发起通信请求的用户态进程被称为客户端,执行某种服务的用户态进程都被称为服务端。Binder IPC 还引入了 Context Manager 进程来负责建立通信连接。当服务端在向内核及 Context Manager 注册时,内核 Binder 驱动及服务端进程会在内核中维护一个对应的 “线程池” 。
线程池中的每个线程都可以代表服务端处理客户端的请求并返回结果。客户端首先从内核和 Context Manager 处获取服务端信息,然后通过内核对服务端发起通信请求,内核会从对应的服务端线程池里找到空闲的线程来响应处理(通过内存映射方式仅用一次拷贝完成数据传递,比共享内存两次数据拷贝要快)。每个服务端在内核中对应的线程池大小可以通过消息来动态改变,内核 Binder 驱动也允许用户为服务端配置一个最大上限线程数,这样动态分配结合最大上限配置能够防止资源浪费和潜在的安全攻击。
需要特别强调的是,用户态的客户端,服务端和 Context Manager 进程间的交互(下图虚线部分)都不能直接交换信息,而是通过运行在内核的Binder驱动来间接完成(下图实线部分):
![](https://i-blog.csdnimg.cn/blog_migrate/7edba5f7bc5dbacbbba43a85a6351615.png)
在车用环境中,无论是基于宏内核还是基于微内核架构搭建的操作系统,使用什么样的IPC通信机制并不是固定的,需要根据不同的应用和需求目标进行灵活选择,必要时甚至会要求内核改进IPC通信机制。
伴随着车身芯片能力不断增加,具备操作系统的ECU数量也在增加。这个也驱动着电子电气架构不断演进。现在大多数高档车都有了域控制器,具备操作系统后会有并发多任务场景,IPC技术也会慢慢在车载软件操作系统中发挥重要的作用。
愿你我相信事件的力量,
做一个长期主义者!