网站集约化平台建设分析,建设部人才交流中心网站,wordpress调用分类目录文章,手机网站关键词优化平时网络部分的东西碰的多些#xff0c;这块一开始还真不知道怎么写#xff0c;因为肯定和在用户空间下是不同的。google过后#xff0c;得到以下答案。一般可以用两种方法#xff1a;第一种是用系统调用。第二种方法是filp-open()等函数。下面分别来说下这两种方法。1…平时网络部分的东西碰的多些这块一开始还真不知道怎么写因为肯定和在用户空间下是不同的。google过后得到以下答案。一般可以用两种方法第一种是用系统调用。第二种方法是filp-open()等函数。下面分别来说下这两种方法。1 利用系统调用sys_open,sys_write,sys_read等。其实分析过sys_open可以知道最后调用的也是filp-open。sys_open do_sys_open filp-open在linuxsir上的一个帖子上面一个版主说sys_open和进程紧密相关往往不在内核中使用。而其实sys_open最后也是调用了filp-open。其实好像Linux2.6.20后面就不推荐使用sys_open,那我们这里就就后者进行详细的介绍2 filp-open等函数。在模块中用户空间的open,read,write,llseek等函数都是不可以使用的。应该使用其在内核中对应的函数。可以使用filp-open配合struct file里的read/write来进行对文件的读写操作。例子1#include linux/kernel.h #include linux/module.h #include linux/fs.h #include asm/uaccess.h #include linux/mm.h MODULE_AUTHOR(Kenthy163.com.); MODULE_DESCRIPTION(Kernel study and test.); void fileread(const char * filename) { struct file *filp; struct inode *inode; mm_segment_t fs; off_t fsize; char *buf; unsigned long magic; printk(1start....\n); filpfilp_open(filename,O_RDONLY,0); inodefilp-f_dentry-d_inode; magicinode-i_sb-s_magic; printk(1file system magic:%li \n,magic); printk(1super blocksize:%li \n,inode-i_sb-s_blocksize); printk(1inode %li \n,inode-i_ino); fsizeinode-i_size; printk(1file size:%i \n,(int)fsize); buf(char *) kmalloc(fsize1,GFP_ATOMIC); fsget_fs(); set_fs(KERNEL_DS); filp-f_op-read(filp,buf,fsize,(filp-f_pos)); set_fs(fs); buf[fsize]\0; printk(1The File Content is:\n); printk(1%s,buf); filp_close(filp,NULL); } void filewrite(char* filename, char* data){ struct file *filp; mm_segment_t fs;filp filp_open(filename, O_RDWR|O_APPEND, 0644);if(IS_ERR(filp)) { printk(open error...\n); return; } fsget_fs(); set_fs(KERNEL_DS); filp-f_op-write(filp, data, strlen(data),filp-f_pos); set_fs(fs); filp_close(filp,NULL);}int init_module() { char *filename/root/test1.c; printk(1Read File from Kernel.\n); fileread(filename); filewrite(filename, kernel write test\n); return 0; } void cleanup_module() { printk(1Good,Bye!\n); }复制代码eg2#includelinux/module.h#includelinux/kernel.h#includelinux/init.h#includelinux/types.h#includelinux/fs.h#includelinux/string.h#includeasm/uaccess.h /* get_fs(),set_fs(),get_ds() */#define FILE_DIR /root/test.txtMODULE_LICENSE(GPL);MODULE_AUTHOR(kenthy163.com);char *buff module read/write test;char tmp[100];static struct file *filp NULL;static int __init wr_test_init(void){ mm_segment_t old_fs; ssize_t ret; filp filp_open(FILE_DIR, O_RDWR | O_CREAT, 0644); // if(!filp) if(IS_ERR(filp)) printk(open error...\n); old_fs get_fs(); set_fs(get_ds()); filp-f_op-write(filp, buff, strlen(buff), filp-f_pos); filp-f_op-llseek(filp,0,0); ret filp-f_op-read(filp, tmp, strlen(buff), filp-f_pos); set_fs(old_fs); if(ret 0) printk(%s\n,tmp); else if(ret 0) printk(read nothing.............\n); else { printk(read error\n); return -1; } return 0;}static void __exit wr_test_exit(void){ if(filp) filp_close(filp,NULL);}module_init(wr_test_init);module_exit(wr_test_exit);复制代码3.Makefileobj-m : os_attack.oKDIR : /lib/modules/$(uname -r)/build/PWD : $(shell pwd)all:modulemodule: $(MAKE) -C $(KDIR) M$(PWD) modulesclean: rm -rf *.ko *.mod.c *.o Module.* modules.* .*.cmd .tmp_versions复制代码注意在调用filp-f_op-read和filp-f_op-write等对文件的操作之前应该先设置FS。默认情况下filp-f_op-read或者filp-f_op-write会对传进来的参数buff进行指针检查。如果不是在用户空间会拒绝访问。因为是在内核模块中所以buff肯定不在用户空间所以要增大其寻址范围。拿filp-f_op-write为例来说明filp-f_op-write最终会调用access_ok range_ok.而range_ok会判断访问的地址是否在0 addr_limit之间。如果在则ok继续。如果不在则禁止访问。而内核空间传过来的buff肯定大于addr_limit。所以要set_fs(get_ds())。这些函数在asm/uaccess.h中定义。以下是这个头文件中的部分内容#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })#define KERNEL_DS MAKE_MM_SEG(-1UL)#define USER_DS MAKE_MM_SEG(PAGE_OFFSET)#define get_ds() (KERNEL_DS)#define get_fs() (current_thread_info()-addr_limit)#define set_fs(x) (current_thread_info()-addr_limit (x))#define segment_eq(a, b) ((a).seg (b).seg)可以看到set_fs(get_ds())改变了addr_limit的值。这样就使得从模块中传递进去的参数也可以正常使用了。在写测试模块的时候要实现的功能是写进去什么然后读出来放在tmp数组中。但写完了以后filp-f_ops已经在末尾了这个时候读是什么也读不到的如果想要读到数据则应该改变filp-f-ops的值这就要用到filp-f_op-llseek函数了。上网查了下其中的参数需要记下笔记系统调用off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin)offset是偏移量。若origin是SEEK_SET(0)则将该文件的位移量设置为距文件开始处offset 个字节。若origin是SEEK_CUR(1)则将该文件的位移量设置为其当前值加offset, offset可为正或负。若origin是SEEK_END(2)则将该文件的位移量设置为文件长度加offset, offset可为正或负。ok,thats all.