关于EXPORT_SYMBOL_GPL()问题,起源于我的毕业设计中要在linux下写一个模块,用于监视目标进程的系统调用,对其中的写操作进行重定向.这其中就涉及到在内核态下截获了write-syscall以后将他需要写的buf写到我事先创建的文件中.
因此我需要在内核态下的写文件的函数,查看了内核文件/fs/read_write.c,里面是read,write类底层对sys-call的上层封装.我原先希望可以直接使用sys_write,但是由于linux出于安全因素,拒绝将sys-call导出到全局符号表,因此编译的内核会有sys_write undefined 的警告,当 insmod 模块的时候会产生未知symbol的错误.
我顺着这条道走下去,考虑到sys-call是面向user用户空间,让application使用的,我在网上搜索到改变内存空间的方法,主要就是set_fs(),get_ds()这两个函数来完成内存空间切换.一般定义的宏如下:
#define BEGIN_KMEM {mm_segment_t old = get_fs();set_fs(get_ds())}
#define END_KMEM {set_fs(old);}
前面一个宏主要是先记录下内存空间的首地址,再设置内存空间的首地址为用户空间首地址,进行内存空间切换
后一个宏主要是将内存空间切换回去.
这两个宏的使用主要是因为sys-call在调用前会进行各个参数的内存空间检查,如果发现内存空间不正确,将会产生段错误.
然而网上的方法主要是针对2.4内核下的,在2.6.30下无法成功.在百般无奈下我选择了重新编译内核,使用EXPORT_SYMBOL_GPL()这个宏将使用到的sys-calls导出.
导出方法就是到函数定义的文件中:如需要将sys_write导出,首先进入/fs/read_write.c中,在系统调用定义后面使用EXPORT_SYMBOL_GPL(sys_write)即可.
如果注意一点就会发现,每个文件都有许多的EXPORT_SYMBOL(),这个宏也是将函数导出让所有模块都可以使用.而EXPORT_SYMBOL_GPL()这个宏主要是给有GPL认证的模块使用.
重新编译内核,在内核中确实可以使用sys_write 等函数进行操作,不过后来想了一下,毕竟如果要有比较好的移植性,修改内核这种方法还是不太好.于是咨询了一下同学,他给出一个函数filp_open(),返回值是一个struct file,在file里面可以有files_operation结构指针,在此结构中可以使用write()函数进行文件写操作.我使用这个宏进行文件的读写还比较顺利.
今天就写到这吧.
由于需要使用到mkdir()进行目录的创建.下一次会将使用mkdir()遇到的相关的问题进行解析.
阅读(2786) | 评论(0) | 转发(0) |