资源描述:
《Linux内核跟踪之ring buffer的实现》由会员上传分享,免费在线阅读,更多相关内容在教育资源-天天文库。
1、Linux内核跟踪之ringbuffer的实现一:前言 Ringbuffer是整个trace系统使用缓存管理的一种方式,由于trace可能在内核运行的任何时候发生,这种kernel的不确定状态决定了ringbuffer的写操作中不能有任何引起睡眠的操作,而且ringbuffer的操作频率极高,所以在ringbuffer实现里有很多高效的方式来处理多处理器,读写同步的机制.理解ringbuffer是我们理解整个kerneltrace的基础.本文分析的源代码版本为linuxkernel2.6.30,分析的代码基本位于kernel/trace/ring_buffer.c中.
2、另外,为了描述的方便,下文ringbuffer用RB来代替. 二:ringbuffer的基本数据结构 在深入到代码之前,我们先来看一下RB所用到的几个基本的数据结构,这样我们对RB就会有一个全局性的了解.整个RB的数据结构框架如下所示:2010-8-1317:29上传下载附件(35.65KB) ringbuffer用structring_buffer来表示,数据结构定义如下: structring_buffer{ /*RB中的页面数*/ unsigned pages; /*RB的标志,目前只有RB_FL_OVERWRITE可用*/ unsi
3、gned flags; /*ringbuffer中包含的cpu个数*/ int cpus; /*整个ringbuffer的禁用标志,用原子操作了防止竞争*/ atomic_t record_disabled; /*cpu位图*/ cpumask_var_t cpumask; /*RB访问锁*/ structmutex mutex; /*CPU的缓存区页面,每个CPU对应一项*/ structring_buffer_per_cpu **buffers; #ifdefCON**_H
4、OTPLUG_CPU /*多CPU情况下的cpuhotplug通知链表*/ structnotifier_block cpu_notify; #endif /*RB所用的时间,用来计数时间戳*/ u64 (*clock)(void); } 在RB的操作中,我们可以禁止全局的RB操作,例如,完全禁用掉Trace功能后,整个RB都是不允许再操做的,这时,就可以将原子变量record_disabled加1.相反的,如果启用的话,将其减1即可.只有当record_disabled的值等于0时,才允许操作RB. 同时,有些时候,要对RB的一些数
5、据进行更新,比如,我要重新设置一下RB的缓存区大小,这都需要串行操作,因此,在ring_buffer结构中有mutex成员,用来避免这些更改RB的操作的竞争. 每个cpu的缓存区结构为: structring_buffer_per_cpu{ /*该cpubuffer所在的CPU*/ int cpu; /*cpubuffer所属的RB*/ structring_buffer *buffer; /*读锁,用了避免读者的操行操作,有时在 *写者切换页面的时候,也需要持有此锁 */ spinlock_t reader_lock;
6、/*serializereaders*/ raw_spinlock_t lock; structlock_class_key lock_key; /*cpubuffer的页面链表*/ structlist_head pages; /*起始读位置*/ structbuffer_page *head_page;/*readfromhead*/ /*写位置*/ structbuffer_page *tail_page;/*writetotail*/ /*提交位置,只有当被写的页面提交过后 *才允许被读 */ str
7、uctbuffer_page *commit_page; /*committedpages*/ /*reader页面,用来交换读页面*/ structbuffer_page *reader_page; unsignedlong nmi_dropped; unsignedlong commit_overrun; unsignedlong overrun; unsignedlong read; local_t entries; /*最新的页面c