内核printk原理介绍 - 知乎 (zhihu.com)
34.Linux-printk分析、使用prink调试驱动 (bbsmax.com)
【原创】计算机自制操作系统(Linux篇)五:内核开发之万丈高楼从地起---printk(理清pintf/vprintf;sprintf/vsprintf ;fprintf/vfprintf) - 知乎 (zhihu.com)
printk流程分析 - 知乎 (zhihu.com)
va_list、va_start和va_end使用 - insistYuan - 博客园 (cnblogs.com)
asmlinkage-SodaGreen_wyj-ChinaUnix博客
(34条消息) kernel里__printf(a, b)说明_茫茫大士的博客-CSDN博客_kernel __printf(2, 3)
Printk Index — The Linux Kernel documentation
(34条消息) 宋宝华:为了不忘却的纪念,评Linux 5.13内核_宋宝华的博客-CSDN博客
(34条消息) linux5.2内核的ringbuffer(无锁环形缓冲区)原理实现与源码分析(上)_你听不到的博客-CSDN博客_linux内核ringbuf实现
Lockless Ring Buffer Design — The Linux Kernel documentation
基于linux 6.1.12
files
/kernel/printk/printk.c
/include/linux/printk.h
/kernel/printk/printk_ringbuffer.c
/kernel/printk/printk_ringbuffer.h
data structure
3. overall call flow
3.1 write flow
(1)desc_reserve:从prb_desc数组中获取一个空闲的entry,若没有空闲的entry,则覆盖最老的entry。分配完成后将该描述符状态设置为desc_reserved
(2)设置该条log的seq序号
(3)data_alloc:从ring buffer中分配一段用于保存新log的空间,若空闲空间不足,则覆盖掉最老的数据,直到空间足够为止
(4)log data copy:将需要写入的数据拷贝到从log buffer中分配的空间中
(5)_prb_commit:将prb_desc的状态更新为desc_committed
(6)desc_make_final:将prb_desc的状态更新为desc_finalized,该操作后log写入完成且可被读取。
3.2 read flow
读取log时以seq序号为参数,并调用prb_read读取该seq对应的log,若读取失败则调用prb_first_seq获取该seq之后第一条可读的log,并重新读取。
(1)desc_read_finalized_seq:读取该条log对应的状态,若状态合法,则执行下面的log数据和信息读取操作,否则表明该条log已被覆盖、正在被修改或其描述符是空闲的。数据读取完成后,再次执行本函数重新读取其状态和seq号,若状态合法且seq号未变,表明在读的过程中,数据未被写操作修改。否则,表明在读的过程中,该条log的信息或数据已被log写接口覆盖修改了。若整个读流程成功,则数据读取完成,否则调用prb_first_seq获取下一条可读的log
(2)prb_first_seq:由于buffer中尾节点是最老的log数据,因此若待读取数据比尾结点数据还老,则表明该数据已被覆盖,将尾结点作为first seq读取即可。若该节点合法,但数据读取失败,则将下一个节点作为first seq读取。若缓冲区中无有效数据,则返回错误
4. 设计思想
如何通过细化数据,分而治之,通过添加 prb_desc_ring,以及采用 atomic_t 变量等方法来去除锁的消耗。