linux内核宏如何用作函数?

The*_*ect 1 c linux macros kernel kernel-module

这样的标题听起来可能很愚蠢,但是我以前从未见过这样的东西,而且我真的不知道该如何描述它:

因此,我只是编写了第一个内核模块,并且使用了一个链表,该链表使用了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))
Run Code Online (Sandbox Code Playgroud)

而且,我用它是这样的(假设list_head是链表的头,并且listlist_struct在结构内):

struct thing *ptr;
list_for_each_entry(ptr, &list_head, list){
        printk(KERN_INFO "contents: %s\n", ptr->something);
}
Run Code Online (Sandbox Code Playgroud)

当我运行时dmesg,列表中的每个项目都有一行...

所以,我的问题是:这里发生了什么?我以前从未见过像这样的宏那样使用过的宏-编写以这种方式调用的宏的规则是什么?

我只是真的不明白为什么这样做,或者我将如何编写自己的宏以这种方式工作。

abl*_*igh 5

宏只是在文本上扩展。没有魔法在发生。您可以使用查看输出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);
}
Run Code Online (Sandbox Code Playgroud)

扩展为:

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);
}
Run Code Online (Sandbox Code Playgroud)

请注意,我在那里并没有做任何努力,只是剪切并粘贴了代码并进行了传递gcc -E(并略微整理了格式)。

循环(如您所见)是在扩展代码中完成的。