今天是学习嵌入式的第33天

进程间通信 IPC

线程之间通信简单,直接读写全局共享变量就行。但是进程之间内存完全隔离,互相看不见对方的数据,必须靠操作系统提供的IPC手段传递数据。

常见方式:管道、信号、消息队列、共享内存、信号量。

1.管道

无名管道 pipe()

只能给有血缘关系进程用,比如父子进程。

调用pipe(fd),得到两个文件描述符 fd0读端,fd1写端。

子进程fork之后,父子进程都持有这两个文件描述符。一个往fd1写数据,另一个从fd0读数据。

半双工:单向数据流,数据只能从写端流向读端。

管道行为特点:

  1. 管道里面有数据,read直接读;没数据,read阻塞睡觉。

  2. 如果所有写端全部关闭,read读完现有数据直接返回0,不会阻塞。

  3. 如果所有读端全部关闭,再往管道write写,直接触发管道破裂,进程收到信号直接退出。

有名管道 mkfifo

又叫FIFO文件,在磁盘生成一个特殊文件,没有血缘关系进程也能通信。

注意:open打开有名管道的时候,读和写必须两边都到位,open才会成功,否则程序阻塞卡住。

2.信号

信号就是操作系统发给进程的简短通知,用来告诉进程发生某个事件。比如按Ctrl+C就是发送SIGINT信号。

进程收到信号有三种处理方式:

  1. 默认处理:系统自带行为,大部分信号会直接杀死程序。

  2. 忽略信号,收到啥也不干。9号SIGKILL、19号SIGSTOP这俩信号不能忽略,强制杀死/暂停。

  3. 捕获信号:收到信号就执行我们自己写的信号处理函数。

相关函数:

  1. signal():简单设置信号处理函数。

  2. kill(pid,信号编号):给指定pid进程发送信号。

  3. alarm(seconds):几秒之后,给自己进程发送SIGALRM闹钟信号。

  4. pause():让进程睡觉,直到收到一个信号才唤醒继续跑。

3.消息队列

内核开辟的消息缓冲区,多个进程可以往队列丢消息包,也可以按类型读取消息包。

命令ipcs查看IPC对象,ipcrm删除。

ftok:根据文件路径+一个小数字,生成唯一key值,用这个key来创建消息队列。

msgget:根据key拿到消息队列ID。

msgsnd:发送消息。

msgrcv:接收消息,可以指定只读取某一类消息。

msgctl:删除消息队列,获取消息队列状态。

优点:可以按消息类型筛选读取;缺点:拷贝数据,有开销。

4.共享内存(IPC里面速度最快)

内核开辟一块物理内存,多个进程把这块内存映射到自己的虚拟地址空间。所有进程直接读写同一块内存,数据不需要在内核和用户空间来回拷贝,速度拉满。

注意!共享内存本身不带同步保护!多进程同时读写会乱,必须搭配信号量/互斥锁控制访问时序。

流程:

1.shmget:创建共享内存,拿到shmid;

2.shmat:把共享内存映射到当前进程虚拟地址,得到内存首地址,之后直接指针读写;

3.shmdt:解除映射,断开进程和这块内存的联系;

4.shmctl:销毁共享内存。

5.信号灯集(System V信号量)

跟线程信号量用途差不多,但是可以跨进程使用。semget创建信号灯集合,semop执行P/V操作(申请释放资源),semctl初始化值、删除信号灯。

相关推荐
一隅论数智1 天前
给AI一张“业务概念地图“:本体如何从哲学走向企业智能
大数据·人工智能·经验分享·笔记·学习·学习方法·政务
倒头就睡的小比特1 天前
算法竞赛C++常用的STL
c++·算法
小羊没烦恼!1 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
未济1 天前
linux 配置环境变量
linux
傲世仙尊1 天前
目录即文件-Ext文件系统收尾篇
linux·c语言
XiHongShi20161 天前
STM32F407 RTC定时器例程,建议保存
stm32·单片机·学习
爱吃苹果的日记本1 天前
离散数学第六课
学习·离散数学
猎头南楼1 天前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
_艾伦 耶格尔.1 天前
进程间通信
linux