转载地址:http://blog.chinaunix.net/uid-25000873-id-4134037.html
在arch/xxx/kernel下有一个奇怪的文件:asm-offset.c。这个文件里面有一个main函数,而且里面的正文全是DEFINE(xxx, xxxx)的格式。这让阅读源码的人会感到困惑,这个文件的作用是什么呢?不卖关子:这个文件的目的是生成include/generated/asm-offsets.h。
include/generated/asm-offsets.h这个文件,里面定义了一些结构体内变量的相对便宜。通过这个宏,就可以在汇编代码访问到结构体内的某一个地址。拿asm-offset.c中一个语句来分析:
DEFINE(TSK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
在这个语句里面的两个宏定义是:
#define DEFINE(sym, val) \
asm volatile("\n->" #sym " %0 " #val : : "i" (val))
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#sym就是直接把sym格式化为字符串。
offsetof这个宏其目的就是为了找出结构体中某一个元素的偏移量。
把 DEFINE(TSK_ACTIVE_MM, offsetof(struct task_struct, active_mm));这个语句做了宏展开就成了:
->TSK_ACTIVE_MM 336 offsetof(struct task_struct, active_mm) //
asm-offset.c的展开就在其目录下的asm-offset.s文件里面,相关的生成规则在Kbuild文件里面。
核心的两个函数在于:
cmd_cc_s_c = $(CC) $(c_flags) -fverbose-asm -S -o $@ $<
define sed-y
"/^->/{s:->#\(.*\):/* \1 */:; \
s:^->\([^ ]*\) [\$$#]*\([-0-9]*\) \(.*\):#define \1 \2 /* \3 */:; \
s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \
s:->::; p;}"
endef
define cmd_offsets
(set -e; \
echo "#ifndef __ASM_OFFSETS_H__"; \
echo "#define __ASM_OFFSETS_H__"; \
echo "/*"; \
echo " * DO NOT MODIFY."; \
echo " *"; \
echo " * This file was generated by Kbuild"; \
echo " *"; \
echo " */"; \
echo ""; \
sed -ne $(sed-y) $<; \
echo ""; \
echo "#endif" ) > $@
endef
最后就在include/generated/asm-offsets.h中生成了
#define TSK_ACTIVE_MM 336 /* offsetof(struct task_struct, active_mm) // */
这样汇编代码中,就可以通过指针+偏移的方式访问到task_struct->active_mm变量了。