系统模块
一、the system call函数
the system call 被定义在<sys/sysent.h>头文件中,其函数原型如下:
typedef int sy_call_t(struct thread *,void *),其中struct thread * ,指向当前正在运行的线程,void *,指向the system call参数结构。
注意:the system call参数驻留在user space ,而the system call 函数运行在kernel space.
二、the sysent structure
system call 项(entries)被定义在sysent 结构体中,其头文件为<sys/sysent.h>,其原型如下:
struct sysent{
int sy_narg; /*参数的个数*/
sy_call_t *sy_call; /*要执行的函数*/
au_event_t sy_auevent; /*检查(audit)跟system call联系的事件*/
};
附加一点,在freebsd中,sysent 结构体数组,也被在<sys/sysent.h>中声明。
extern struct sysent sysent[]; 无论何时,sysent 结构体被放置在sysent[]中。
三、the offset value
the offset value(即 the system call的个数)是一个唯一的整数值(0--456),每一个system call都被分配有一个值,这个值为了指示在sysent[]中她的sysent 结构体的偏移量。
在system call模块里,the offset value被明确的声明。其一般声明如下:
static int offset = NO_SYSCALL;这常量NO_SYSCALL设置偏移量(offset)下一个有效,或者打开sysent[]。
四、the syscall_module macro
写 a syscall module 时,需要用 SYSCALL_MODULE macro,其被定义在<sys/sysent.h>,如下:
#define SYSCALL_MODULE(name,offset,new_sysent,evh,arg)
static struct syscall_module_data name##_syscall_mod = {
evh, arg, offset, new_sysent, { 0, NULL}
};
static moduledata_t name##_mod = {
#name,
syscall_module_hanlder,
&name##_syscall_mod
};
DECLARE_MODULE(name,name##_mod,SI_SUB_DRIVERS,SI_ORDER_MIDDLE)
如果我们使用DECLARE_MODULE宏,我们必须设置syscall_module_data 和 moduledata结构体,而SYSCALL_MODULE不用。
SYSCALL_MODULE模块参数:name,指定模块名字字符串;offset,指定the system call 的偏移量值;new_sysent,指定完整的sysent 结构体指针;evh,指定事件句柄函数;arg,指定事件句柄函数的参数。
五、实例(a complete system call module)
/*sc_example.c*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/module.h>
#include <sys/sysent.h>
#include <sys/kernel.h>
#include <sys/systm.h>
/*the system call's arguments */
struct sc_example_args {
char *str;
};
/*the system call function */
static int sc_example(struct thread *td,void *syscall_args)
{
struct sc_example_args *uap;
uap = (struct sc_example_args *)syscall_args;
printf("%s\n",uap->str);
return(0);
}
/*the sysent for the new system call*/
static struct sysent sc_example_sysent = {
1, /*参数的个数*/
sc_example /*要执行的函数名字*/
};
/*the offset in sysent[] where the system call is to be allocated*/
static int offset = NO_SYSCALL;
/*the function called at load or unload.*/
static int load(struct module *module,int cmd,void *arg)
{
int error=0;
switch (cmd) {
case MOD_LOAD:
uprintf("system call load at offset %d.\n,offset");
break;
case MOD_UNLOAD:
uprintf("system call unload from offset \ %d.\n,offset");
break;
default:
error = EOPNOTSUPP;
break;
}
}
SYSCALL_MODULE(sc_example,&offset,&sc_example_sysent,load,NULL);
执行:
$ sudo kldload ./sc_example.ko
评论