Zephyr内核对象--数据传递对象总结增补
本文分析数据传递对象传递数据的系统效能。
本文是做为Zephyr内核对–数据传递对象简介的增补篇对所有的数据传进行效能分析。 每种数据传递对象的分析可以参考下面文章 Zephyr内核对象-数据传递之FIFO/LIFO Zephyr内核对象-数据传递之Stack Zephyr内核对象-数据传递之Message Queue Zephyr内核对象-数据传递之邮箱 Zephyr内核对象-数据传递之管道
加锁方式 链接到标题
在数据传递过程中,内存有自旋锁和锁调度两种加锁方式:
自旋锁 链接到标题
本文只考虑单核CPU,在此情况下自旋锁退化为锁中断,我们假定没有配置非延迟中断,因此k_spin_lock将会锁所有的中断。 对应于k_spin_lock,可以使用k_spin_unlock,z_reschedule,z_pend_curr进行解锁
锁调度 链接到标题
k_sched_lock上锁后,不会再发生线程调度(但会响应中断),k_sched_unlock后恢复调度
数据传递方式分析和加锁影响 链接到标题
下面列出不同数据对象传递数据的方式,并列出传递时加锁的方式
queue/fifo/lifo 链接到标题
将数据的内存指针以链表形式管理,指针长度的数据copy
-
queue_insert k_spin_lock->链表插入->z_reschedule
-
z_impl_k_queue_get k_spin_lock -> 从链表移除 ->k_spin_unlock k_spin_lock -> z_pend_curr(无数据等待)
queue/fifo/lifo在传递数据的时候会锁中断,但由于只是链表操作,数据也只有指针长度,对系统效能影响不大。传递的是数据指针,数据0拷贝。
statck 链接到标题
将数据指针存放在堆栈中,指针长度的数据copy
-
z_impl_k_stack_push k_spin_lock -> 数据指针入栈 -> z_reschedule k_spin_lock -> k_spin_unlock(堆栈满)
-
z_impl_k_stack_pop k_spin_lock->数据指针出堆栈->k_spin_unlock k_spin_lock -> z_pend_curr(堆栈空,等数据)
在传递数据的时候会锁中断,但由于只是堆栈操作,单位数据也只有指针长度,对系统效能影响不大。传递的是数据指针,数据0拷贝。
消息列队 链接到标题
将消息以ring-buffer形式管理,一次传送copy的大小为消息的长度,消息可以包含所有数据,也可以只包含指向消息数据的指针,传递只copy消息,不copy消息数据指针指向的数据
z_impl_k_msgq_put 链接到标题
k_spin_lock -> copy消息大小->z_reschedule k_spin_lock-> z_pend_curr (等待发送) k_spin_lock-> k_spin_unlock(不等待发送)
z_impl_k_msgq_get 链接到标题
k_spin_lock->copy消息大小->z_reschedule k_spin_lock-> z_pend_curr (等待数据) k_spin_lock-> k_spin_unlock(不等待数据)
在传递数据的时候会锁中断,会对消息数据进行拷贝,为了减少对系统的影响,定义消息列队的消息时需要控制消息的长度,如果有大数据需要传递,只在消息里面传递数据的指针,传递数据0拷贝。
邮箱 链接到标题
将消息中包含消息数据指针,接收者将copy消息中数据指针指向所有数据,接收完后发送者才会退出。
mbox_message_put 链接到标题
k_spin_lock -> 匹配 ->等待接收copy数据z_pend_curr k_spin_lock -> z_pend_curr(未匹配,等待发送) k_spin_lock -> k_spin_unlock(未匹配,不等待发送)
k_mbox_get 链接到标题
k_spin_lock->匹配->k_spin_unlock->copy消息数据->通知copy完成 k_spin_lock-> k_spin_unlock(未匹配,等待接收消息) k_spin_lock-> k_spin_unlock(未匹配,不等待)
只在匹配时会锁中断,对系统效能影响不大。在传递数据的时必须进行数据拷贝,数据过大需要考虑使用消息队列做0拷贝动作
管道 链接到标题
要发送的所有数据都在管道内,接收者会copy所有管道内的数据
z_pipe_put_internal 链接到标题
k_spin_lock -> 有thread等待读pipe数据->z_sched_lock->k_spin_unlock->copy pipe数据->k_sched_unlock k_spin_lock -> 无thread等待读pipe数据->k_spin_unlock(不等待发送) k_spin_lock -> 无thread等待读pipe数据->z_sched_lock->k_spin_unlock->z_sched_unlock_no_reschedule->k_spin_unlock(等待发送)
z_impl_k_pipe_get 链接到标题
k_spin_lock -> 有thread等待写pipe数据->z_sched_lock->k_spin_unlock->copy pipe数据->k_sched_unlock k_spin_lock -> 无thread等待读pipe数据->k_spin_unlock(不等待接收) k_spin_lock -> 无thread等待读pipe数据->z_sched_lock->k_spin_unlock->z_sched_unlock_no_reschedule->k_spin_unlock(等待接收)
只在检查pipe时锁中断,对系统效能影响不大,但在传递数据时需要锁调度,且是拷贝所有数据,在拷贝数据期间其它线程均无法打断,如果数据过大会影响系统效能。