Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3515129
  • 博文数量: 1805
  • 博客积分: 135
  • 博客等级: 入伍新兵
  • 技术积分: 3345
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-19 20:01
文章分类

全部博文(1805)

文章存档

2017年(19)

2016年(80)

2015年(341)

2014年(438)

2013年(349)

2012年(332)

2011年(248)

分类: LINUX

2015-03-16 18:16:55

原文地址:在linux内核中读写文件 作者:suiming2005

VFS的支持下,用户态进程读写任何类型的文件系统都可以使用readwrite着两个系统调用,但是在linux内核中没有这样的系统调用我们如何操作文件呢?我们知道readwrite在进入内核态之后,实际执行的是sys_readsys_write,但是查看内核源代码,发现这些操作文件的函数都没有导出(使用EXPORT_SYMBOL导出),也就是说在内核模块中是不能使用的,那如何是好?

通过查看sys_open的源码我们发现,其主要使用了do_filp_open()函数,该函数在fs/namei.c中,而在改文件中,filp_open函数也是调用了do_filp_open函数,并且接口和sys_open函数极为相似,调用参数也和sys_open一样,并且使用EXPORT_SYMBOL导出了,所以我们猜想该函数可以打开文件,功能和open一样。使用同样的查找方法,我们找出了一组在内核中操作文件的函数,如下:

功能 函数原型

打开文件 struct file *filp_open(const char *filename, int flags, int mode) 

读取文件 ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos) 

写文件 ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_t *pos) 

关闭文件 int filp_close(struct file *filp, fl_owner_t id) 

我们注意到在vfs_readvfs_write函数中,其参数buf指向的用户空间的内存地址,如果我们直接使用内核空间的指针,则会返回-EFALUT。所以我们需要使用

set_fs()get_fs()宏来改变内核对内存地址检查的处理方式,所以在内核空间对文件的读写流程为:

mm_segment_t fs = get_fs(); 

set_fs(KERNEL_FS); 

//vfs_write(); 

vfs_read(); 

set_fs(fs);

下面为一个在内核中对文件操作的例子:

#include  

#include  

#include  

#include  

static char buf[] = "你好"; 

static char buf1[10]; 

  

int __init hello_init(void) 

    struct file *fp; 

    mm_segment_t fs; 

    loff_t pos; 

    printk("hello enter\n"); 

    fp = filp_open("/home/niutao/kernel_file", O_RDWR | O_CREAT, 0644); 

    if (IS_ERR(fp)) { 

        printk("create file error\n"); 

        return -1; 

    } 

    fs = get_fs(); 

    set_fs(KERNEL_DS); 

    pos = 0; 

    vfs_write(fp, buf, sizeof(buf), &pos); 

    pos = 0; 

    vfs_read(fp, buf1, sizeof(buf), &pos); 

    printk("read: %s\n", buf1); 

    filp_close(fp, NULL); 

    set_fs(fs); 

    return 0; 

void __exit hello_exit(void) 

    printk("hello exit\n"); 

  

module_init(hello_init); 

module_exit(hello_exit); 

MODULE_LICENSE("GPL");

from http://xyp1222.blog.163.com/blog/static/12381746520114664634868/


阅读(1460) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~