今天在看lkm 代码的时候看到C中以下语句,来一起看看。
//代码中对sct的定义,在我看的代码里表示的是sys_call_table
unsigned long **sct;
//这里面的##表示的是连接符
# define HOOK_SCT(sct, name) \
do { \
real_##name = (void *)sct[__NR_##name]; \
sct[__NR_##name] = (void *)fake_##name; \
} while (0)
# define UNHOOK_SCT(sct, name) \
sct[__NR_##name] = (void *)real_##name
举个例子,比如说我调用这个宏 --> HOOK_SCT(sct,getdents);
那么表示的意思是:
real_getdents = (void *)sct[__NR__getdents];
sct[__NR_getdents] = (void *)fake_getdents;
说一说C语言里的宏定义中的 #,##表示的是含义;
#:它是一个指示符,指示其及后面的变量名替代一个字符串;
##:它是一个连接符,表示它和他后面的变量名合并在一起;
在做内核驱动代码兼容性的时候,往往需要判断内核的版本,然后再选择不同的参数;
/*driver code*/
/*......others codes......*/
#include <linux/version.h>
/*......others codes......*/
#if LINUX_VERSION_CODE>= KERNEL_VERSION(2,6,36)
/*......codes under version newer than 2.6.36......*/
#else
/*......codes under version older than 2.6.36......*/
#endif
/*......others codes......*/
举个实际例子:
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)
static int (*proc_filldir)(void *__buf, const char *name, int namelen, loff_t offset, u64 ino, unsigned d_type);
static int (*root_filldir)(void *__buf, const char *name, int namelen, loff_t offset, u64 ino, unsigned d_type);
#else
static int (*proc_filldir)(struct dir_context *, const char *, int, loff_t, u64, unsigned);
static int (*root_filldir)(struct dir_context *, const char *, int, loff_t, u64, unsigned);
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0)
static int (*proc_iterate)(struct file *file, void *dirent, filldir_t filldir);
static int (*root_iterate)(struct file *file, void *dirent, filldir_t filldir);
#define ITERATE_NAME readdir
#define ITERATE_PROTO struct file *file, void *dirent, filldir_t filldir
#define FILLDIR_VAR filldir
#define REPLACE_FILLDIR(ITERATE_FUNC, FILLDIR_FUNC) \
{ \
ret = ITERATE_FUNC(file, dirent, &FILLDIR_FUNC);\
}
#else
static int (*proc_iterate)(struct file *file, struct dir_context *);
static int (*root_iterate)(struct file *file, struct dir_context *);
#define ITERATE_NAME iterate
#define ITERATE_PROTO struct file *file, struct dir_context *ctx
#define FILLDIR_VAR ctx->actor
#define REPLACE_FILLDIR(ITERATE_FUNC, FILLDIR_FUNC) \
{ \
*((filldir_t *)&ctx->actor) = &FILLDIR_FUNC; \
ret = ITERATE_FUNC(file, ctx); \
}
#endif
再看看Linux 内核驱动中对系统架构的判断;
#ifdef CONFIG_X86
# include "x86/hook.c"
#else
# error Target CPU architecture is NOT supported !!!
#endif
这里的CONFIG_X64表示的是整个x86的架构,并不是代表x86_32,这个还是要区分开的;
真正判断是32位还是64位可以查看CONFIG_64BIT值;
curtis@curtis-virtual-machine:$ cat /boot/config-4.2.0-42-generic | grep CONFIG_X86
CONFIG_X86_64=y
CONFIG_X86=y
curtis@curtis-virtual-machine:$ cat /boot/config-4.2.0-42-generic | grep CONFIG_64
CONFIG_64BIT=y
C语言添加打印信息的时候可以打印文件名、函数、行号,和printk()类似;
printf("file -->%s line --> %d function --> %s\n",__FILE__,__LINE__,__FUNCTION__);