记录看到过的让人眼前一亮的C代码,通常是简洁高效的一些做法,如果有朋友觉得想要分享代码,欢迎在评论区共享哈。
1、移位操作
在linux-4.4/drivers/usb/dwc2/gadget.c看到
u32 daint, daintmask;
daint &= daintmask;
daint_out = daint >> DAINT_OUTEP_SHIFT;
daint_in = daint & ~(daint_out << DAINT_PUTEP_SHIFT)
通常我们的做法是通过val&0xFFFF这样的语法来获取位元,这种适合mask值固定的情况,但这里的mask是software在运行时配置的,所以就不适合常见的做法了。
2、container_of
通过结构体成员地址获得结构体地址
# define offsetof(typ, memb) ((unsigned long)((char *)&(((typ *)0)->memb)))
/**
* container_of - cast a member of a structure out to the containing structure
* @ptr: the pointer to the member.
* @type: the type of the container struct this is embedded in.
* @member: the name of the member within the struct.
*
*/
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
通过成员地址ptr-ptr在结构体中的偏移得到结构体变量的地址,说这代码漂亮嘛,其实也谈不上,就是C语言的一种用法,内核中很常见。
3、log2
#define LOG2(x) (((x & 0xaaaaaaaa) ? 1 : 0) + ((x & 0xcccccccc) ? 2 : 0) + \
((x & 0xf0f0f0f0) ? 4 : 0) + ((x & 0xff00ff00) ? 8 : 0) + \
((x & 0xffff0000) ? 16 : 0))
C语言宏实现的取对数
4、迭代器
这是一份内核搜索某一个class中的device的代码,首先要声明device结构的class(此处为sample_class),然后通过dev_set_name
设置device name,再通过device_add
告诉kernel。
struct device *dev;
struct class_dev_iter iter;
class_dev_iter_init(&iter, sample_class, NULL, NULL);
while ((dev = class_dev_iter_next(&iter))) {
if (strcmp(epc_name, dev_name(dev)))
continue;
// found,do something
class_dev_iter_exit(&iter);
err:
class_dev_iter_exit(&iter);
return ERR_PTR(ret);