IPC工作方式分析
实际应用中,需要在线程与线程间,线程与中断之间进行一定的数据通信,
主要分为两种:
- 只需要传递状态,不需要传输具体的数据(同步)
- 需要传输数据
因此,ipc大致可以分为两种:一种是线程间通信;一种是线程间同步。
- 线程间通信:邮箱,消息队列。
- 线程间同步:信号量、互斥量、事件集。
邮箱:
邮箱一次仅可传输4个字节数据内容(规定),在32位系统中,4个字节相当于一个指针的大小。
在需要传输较多数据时,创建结构体,使用指针指向的地址的方式传输。
发送和接受都支持阻塞机制。
线程和终端都可以发送邮件,但是中断服务函数不允许任何阻塞,中断发送邮件必须选择非阻塞方式。
终端服务函数不能接收邮件,因为中断不可阻塞。
多个线程可以向同一个邮箱发送和接收邮件。
一个线程可以从任何一个邮箱中接收和发送邮件。
支持FIFO,PRIO两种阻塞唤醒方式。
邮箱中有entery表示邮箱可用邮件数,in_offset,out_offset指针指向邮件存放地址偏移量,指针自加偏移4个字节。初始化为0,线程发送一个邮件到邮箱,entery + 1, in_offset +1, 若邮箱满了则in_offset清0,线程从邮箱接收一个邮件,entery - 1, offset + 1,邮箱空了则in_offset清零。
若邮箱中有邮件,接收线程接收时,其实是复制邮箱中的4字节地址的内容到接收地址中。
如果邮箱发送的是地址,则注定这个地址不能是局部变量的地址,所以发送的邮件不要用局部变量,局部变量如果发送了,那在接受时存放的是这个局部变量的指针,但是可能在接收完这个局部变量时就已经给释放掉了,这个时候就会存在野指针。
邮箱一般传地址的多,所以最好定义全局变量。消息传数据多,不限制局部变量或全局变量,但是也要放心传地址的情况。
消息队列:
消息队列是邮箱的
支持发送紧急消息,将消息放在队列的头部,(正常是放在尾部)。
当空闲消息链表上有空闲消息块时,线程或中断将消息复制到消息块上,然后将该消息块挂载在消息队列的尾部。如果无空闲消息块,要发送消息的线程和线程会收到错误码。
信号量:
信号量是实现线程间通信的机制,实现线程间同步或者临界资源的互斥访问
(裸机逻辑:在中断中进行标记,在退出中断之后进行轮询处理)
信号量属于内核对象,也在自身结构中包含内核对象类型的成员,通过该成员将信号量挂到系统对象容器里面。信号量由IPC容器管理。