情况
我遵循这一点是为了更好地理解Linux内核。
这里有一个关于编写自定义/proc接口的示例。以下是上面链接的示例代码的一个片段-custom-proc.c
:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
#include <asm/types.h>
#omitted
int create_new_proc_entry(void) {
int i;
char *DATA = "Hello People";
len = strlen(DATA);
msg = kmalloc((size_t) DATA_SIZE, GFP_KERNEL); // +1 for
if (msg != NULL) {
printk(KERN_INFO "Allocated memory for msg");
} else {
return -1;
}
strncpy(msg, DATA, len+1);
for (i=0; i < len +1 ; i++) {
printk(KERN_INFO "%c", msg[i]);
if (msg[i] == ' ') {
printk(KERN_INFO "YES");
}
}
proc = proc_create_data(MY_PROC_ENTRY, 0666, NULL, &proc_fops, msg);
if (proc) {
return 0;
}
return -1;
}
由于proc_create_data
没有在示例中定义,我认为它必须在内核中的某个地方定义。我下载了内核5x,并在内核代码中搜索proc_create_data
的所有出现,发现它被定义的唯一位置是/include/linux/proc_fs.h
:
#Omitted
#define proc_create_data(name, mode, parent, proc_ops, data) ({ NULL; })
#Omitted
extern struct proc_dir_entry *proc_create_data(const char *, umode_t,
struct proc_dir_entry *,
const struct proc_ops *, void *)
就是这样。
我从这里读到,在C中,宏将被文本扩展,可以像函数一样使用它。
如果我在这里应用它,那么在所有的扩展之后,我将拥有
/include/linux/proc_fs.h
:
#omitted
extern struct proc_dir_entry ({ NULL; })
custom-proc.c
#omitted
proc = ({ NULL; })
这对我来说似乎不对。
我对编程并不陌生,但对C并不熟悉。我读过Brian W.Kernighan和Dennis m.Ritchie的The C programming Language
,但对宏的解释与上面的链接相同。
问题(主菜:(
如何理解内核中定义的proc_create_data
函数?
我不是在寻找一个非常详细的技术答案,只是一种解释代码的方法,这样我就可以跟随示例,并能够在需要时阅读更多的内核代码。
配菜我在某个地方听说,尽管内核是用C编写的,但它与";正常的";C.不过,我不确定这是真的,也不确定差异的程度。
如果这是";C语言的内核版本";如果有人知道这些技巧的解释链接,那将是很有帮助的。
我已经查看了以下资源,但找不到这样的信息:
- www.kernel.org
- https://kernelnewbies.org/
- Linux内核开发-Robert Love
- Linux系统编程-Robert Love
在proc_fs.h:中是这样的
#ifdef CONFIG_PROC_FS
extern struct proc_dir_entry *proc_create_data(const char *, umode_t,
struct proc_dir_entry *,
const struct proc_ops *,
void *);
#else /* CONFIG_PROC_FS */
#define proc_create_data(name, mode, parent, proc_ops, data) ({NULL;})
#endif
如果用户配置的内核不支持proc文件系统,那么函数调用将扩展为只返回NULL
的语句。请注意,({...})
是一个gcc扩展语句表达式-不要在代码中使用不可移植的扩展,而应该使用static inline
函数。语句表达式的返回值是最后一个使用的表达式的值——在本例中为NULL
。
如果CONFIG_PROC_FS
是从用户配置中定义的,那么proc/generic.c
在这里定义的函数就像任何其他函数一样,包括proc_fs.h
在内的源文件会看到函数声明,而不会看到宏。
我在Linux内核中找不到proc_create_data函数的定义
不用担心-在elixir中键入proc_create_data
会得到本答案中提到的所有3个定义。网络上甚至有多个索引内核源代码浏览器,以lxr为例(但我现在在lxr上看到内部错误(。如果没有,您可以使用ctags或GNUGLOBAL在计算机上索引源代码,然后浏览代码。
如何理解内核中定义的proc_create_data函数?
作为任何其他函数。不,宏没有用声明展开-编译器会看到宏或函数声明,具体取决于是否启用了PROC_FS
。
Side Dish我在某个地方听说,尽管内核是用C编写的,但它与";正常的";C.
Linux内核专门针对GNU GCC编译器,因此它倾向于使用GNU C扩展,有时标记为GNU C.