[LINUX内核编程]学习笔记(二)

linux内核————队列

linux内核——队列

定义:

struct __kfifo{
	unsigned int in;  //入队偏移,写索引
	unsigned int out;  //出队偏移,读索引
	unsigned int mask;
	unsigned int esize;
	void *data;
}

使用:

创建一个队列,该函数创建并初始化一个大小为size的kfifo:

 38 int __kfifo_alloc(struct __kfifo *fifo, unsigned int size,
 39                 size_t esize, gfp_t gfp_mask)
 40 {

 45         size = roundup_pow_of_two(size);
 46 
 47         fifo->in = 0;
 48         fifo->out = 0;
 49         fifo->esize = esize;
 50 
 51         if (size < 2) {
 52                 fifo->data = NULL;
 53                 fifo->mask = 0;
 54                 return -EINVAL;
 55         }
 56 
 57         fifo->data = kmalloc(size * esize, gfp_mask);
 58 
 59         if (!fifo->data) {
 60                 fifo->mask = 0;
 61                 return -ENOMEM;
 62         }
 63         fifo->mask = size - 1;
 64 
 65         return 0;
 66 }

判断一个整数是否是2的整数次幂

 static inline int is_power_of_2(unsigned long long n)
 {
	return (n!=0 &&(n&(n-1)==0))
 }

推入数据到队列的方法是kfifo_in()函数

 102 static void kfifo_copy_in(struct __kfifo *fifo, const void *src,
103                 unsigned int len, unsigned int off)
104 {
105         unsigned int size = fifo->mask + 1;
106         unsigned int esize = fifo->esize;
107         unsigned int l;
108 
109         off &= fifo->mask;  //该操作从数学角度将就是对长度fifo->mask的取模运算 
110         if (esize != 1) {
111                 off *= esize;
112                 size *= esize;
113                 len *= esize;
114         }
115         l = min(len, size - off);  //size-off代表的含义是当前in到缓冲区尾的大小,
116 	/*
			先从buffer中拷贝l字节到缓冲区剩余空间,l<=len,也<=从real_in开始到缓冲区结尾的空间 
			所以这个copy可能没拷贝完,但是不会造成缓冲区越界 
		*/
117         memcpy(fifo->data + off, src, l);  
		/*
			len > l时,拷贝buffer中剩余的内容,其实地址当然为buffer + l,而剩余的大小为len - l 
			当len == l时,下面的memcpy啥都不干
		*/
118         memcpy(fifo->data, src + l, len - l);
123         smp_wmb();
124 }
125 
126 unsigned int __kfifo_in(struct __kfifo *fifo,
127                 const void *buf, unsigned int len)  //buf指向的是请求入队的缓冲区,len表示的是请求写入的大小
128 {
129         unsigned int l;
131         l = kfifo_unused(fifo);//计算队列中剩余空间的大小,fifo->size-(fifo->in-fifo->out)
132         if (len > l)
133                 len = l;
135         kfifo_copy_in(fifo, buf, len, fifo->in);
136         fifo->in += len;
137         return len;
138 }

 kfifo的巧妙之处在于in和out定义为无符号类型,在put和get时,in和out都是增加,当达到最大值时,产生溢出,使得从0开始,进行循环使用

Linux内核一直是学习的难点:将近3000万行代码,5万多个源文件,代码庞大繁杂、代码很难看懂。《Linux内核编程》将突破以往传统的学习方式,采取更有效和科学的学习方法,多角度地对内核进行多层次分析,不局限于形式,不拘泥细节,目的只有一个:更轻松、更高效地去理解内核学习内核。为了更好地让学员掌握内核编程技能,更好地理解内核,本课程将采用并不局限于以下学习方法进行课程的录制:降维分析,化简为繁,将复杂的系统简单化用软件工程的方法分析内核:软件分层、模块化分解、框架迭代多角度立体分析Linux内核,目的只有一个:更好地理解内核利用Linux内核中的面向对象编程思想去分析复杂的子系统、子系统交互利用多任务编程的思想去分析Linux内核本套课程预计分为20个左右的小模块,每个模块一个专题,每个专题会陆续发布。拟录制的模块包括但不限于:模块机制、内核裁剪与配置、内核编译与启动、系统调用、中断、文件系统、调度、内存管理、内核同步、设备模型、字符驱动、块驱动、定时器、input、platform设备驱动、device tree、proc、sysfs、I/O...  本课程是《Linux内核编程》的入门篇,主要给大家介绍一下Linux内核开发、Linux驱动开发的就业行情、行业生态、需要掌握哪些技能、Linux内核学习方法、如何搭建Linux内核学习开发环境。 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值