Linux 内核驱动之话说C语言(一)

今天在看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__);

猜你喜欢

转载自blog.csdn.net/qq_42931917/article/details/109129708
今日推荐