这个标题可能听起来很愚蠢,但我以前从未见过这样的东西,而且我真的不知道如何描述它:
所以我刚写了第一个内核模块,并使用了一个链表,它使用了linux/list.h
头文件。在其中,有这个宏:
400 /**
401 * list_for_each_entry - iterate over list of given type
402 * @pos: the type * to use as a loop cursor.
403 * @head: the head for your list.
404 * @member: the name of the list_struct within the struct.
405 */
406 #define list_for_each_entry(pos, head, member) \
407 for (pos = list_entry((head)->next, typeof(*pos), member); \
408 prefetch(pos->member.next), &pos->member != (head); \
409 pos = list_entry(pos->member.next, typeof(*pos), member))
而且,我这样使用它(假设list_head
是列表的头部,list
是结构中的list_struct
:
struct thing *ptr;
list_for_each_entry(ptr, &list_head, list){
printk(KERN_INFO "contents: %s\n", ptr->something);
}
当我运行dmesg
时,列表中的每个项目都有一行...
所以,我的问题是: 这里发生了什么?我之前没有看到使用的宏就好像它们是这样的函数 - 编写一个以这种方式调用的宏的规则是什么?
我只是不明白为什么会这样,或者我如何编写我自己的宏,就像这样。
答案 0 :(得分:4)
宏只是文本扩展。没有魔法可言。您可以使用gcc -E
查看输出。在这种情况下:
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member); \
prefetch(pos->member.next), &pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
...
struct thing *ptr;
list_for_each_entry(ptr, &list_head, list){
printk(KERN_INFO "contents: %s\n", ptr->something);
}
扩展为:
struct thing *ptr;
for (ptr = list_entry((&list_head)->next, typeof(*ptr), list);
prefetch(ptr->list.next), &ptr->list != (&list_head);
ptr = list_entry(ptr->list.next, typeof(*ptr), list)) {
printk(KERN_INFO "contents: %s\n", ptr->something);
}
请注意,我没有在那里做任何艰苦的工作,我只是剪切&粘贴代码并通过gcc -E
(稍微整理了格式)。
循环(如您所见)在扩展代码中完成。
答案 1 :(得分:2)
要深入了解Linux内核,您需要在C中使用 solid 背景。至少要学习一本教程(如http://www.cprogramming.com/tutorial/c-tutorial.html)并完成它。 Linux专家使用各种毛发构造,既提高效率(每天在数百万台设备上运行数千次的代码),抽象复杂且容易出错的常见结构,也可用于帮助创建与架构无关的代码。宏当然是一个基本的工具,它们是C的一个有点神秘的角落。注意,内核也可以自由地使用所有类型的GCC扩展。