linux内核空间的IO操作Word格式文档下载.docx
《linux内核空间的IO操作Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《linux内核空间的IO操作Word格式文档下载.docx(11页珍藏版)》请在冰点文库上搜索。
表明要打开或创建文件的名称(包括路径部分)。
open_mode:
文件的打开方式,O_RDONLY只读打开、O_WRONLY只写打开、O_RDWR读写打开、O_CREAT文件不存在则创建。
mode:
创建文件时使用,设置创建文件的权限,其它情况可以匆略设为0
示例
structfile*file=NULL;
file=filp_open(/root/test.txt,O_RDWR|O_CREAT,0);
//以读写方式(没有则创建)打开文件/root/test.txt。
并返回test.txt的文件指针给file.
函数filp_close(structfile*filp,fl_owner_tid)
关闭之前打开文件
函数原型:
intfilp_close(structfile*filp,fl_owner_tid);
structfile*filp:
打开文件的文件指针
fl_owner_tid:
一般传递NULL值,也可用current->
files作为实参。
filp_close(file,NULL);
//关闭指针为file的文件。
函数vfs_read(structfile*file,char__user*buf,size_tcount,loff_t*pos)
读取已经打开的文件到内存中
ssize_tvfs_read(structfile*file,char__user*buf,size_tcount,loff_t*pos)
{
ssize_tret;
if(!
(file->
f_mode&
FMODE_READ))//判断文件是否可读
return-EBADF;
file->
f_op||(!
f_op->
read&
&
!
aio_read))//是否定义文件读方法
return-EINVAL;
if(unlikely(!
access_ok(VERIFY_WRITE,buf,count)))
return-EFAULT;
ret=rw_verify_area(READ,file,pos,count);
//读校验,
if(ret>
=0)
{
count=ret;
if(file->
read)
ret=file->
read(file,buf,count,pos);
//调用文件读操作方法
else
ret=do_sync_read(file,buf,count,pos);
//通用文件模型读方法
0)
fsnotify_access(file->
f_path.dentry);
add_rchar(current,ret);
}
inc_syscr(current);
returnret;
}
通过filp_open我们已经可以在当前进程的文件描述表中找到了file,于是我们就可以调用保存在file中的文件操作方法(file_operation)file->
read(file,buf,count,pos)来具体的操作文件。
上面的代码实现并不复杂,在做了一些条件判断以后,如果该文件索引节点inode定义了文件的读实现方法的话,就调用此方法。
Linux下特殊文件读往往是用此方法,一些伪文件系统如:
proc,sysfs等,读写文件也是用此方法。
而如果没有定义此方法就会调用通用文件模型的读写方法.它最终就是读内存,或者需要从存储介质中去读数据.
structfile*file:
打开的文件返回的文件指针,(读的目标文件)
char__user*buf:
在用户空间开辟的一段内存空间的首地址,用来保存文件数据。
size_tcount:
指定读取文件中的多少内容。
单位字节
loff_t*pos:
文件起始位置偏移值,若从文件头读取,则偏移值为0.可以在文件自身的信息中获取
int*buf;
loff_t*pos=&
f_pos);
buf=(int*)kmalloc(fsize+100,GFP_KERNEL);
//分配一个文件自身大小+100字节边界的内存空间,将用来存放打开的文件,内存分配方式为kmalloc的flag标志GFP_KERNEL。
vfs_read(file,buf,fsize,pos);
//读文件(指针为file)到内存(buf为起始地址)中,读取字节数定为文件自身大小,偏移为自身.
函数vfs_write(structfile*file,constchar__user*buf,size_tcount,loff_t*pos)
将内存中的一段数据写到文件中
ssize_tvfs_write(structfile*file,constchar__user*buf,size_tcount,loff_t*pos)
FMODE_WRITE))
write&
aio_write))
access_ok(VERIFY_READ,buf,count)))
ret=rw_verify_area(WRITE,file,pos,count);
write)
write(file,buf,count,pos);
ret=do_sync_write(file,buf,count,pos);
fsnotify_modify(file->
add_wchar(current,ret);
inc_syscw(current);
可以看出这个函数和vfs_read()是差不多的,只是调用的文件操作方法不同而已(file->
write),如果没有定义file->
write,同样也需要do_sync_write()调用同样文件写操作,首先把数据写到内存中,然后在适当的时候把数据同步到具体的存储介质中去.
打开的文件返回的文件指针,(写的目标文件)
数据在内存中的位置,以该地址为起始的一段内存数据将要写到文件中
指定写入文件中的多少内容。
vfs_write(file,buf,fsize,pos);
获取文件的大小
我们可以利用文件的inode结构获得文件的大小,参考代码如下
structinode*inode=NULL;
file=filp_open(file_path,O_RDWR|O_CREAT,0);
inode=file->
f_dentry->
d_inode;
fsize=inode->
i_size;
printk(KERN_ALERT"
size=%d\n"
(int)fsize);
示例代码
此ko模块代码在arm架构的fpga上已经跑通。
因为涉及的参数比较多,为了清楚地重现重要步骤,对每步骤的函数进行了简单的封装。
参数的传递只要理解上面的介绍即可区分清楚。
执行流程在staticinthello_init(void)函数中
/*
*kernel_hello_file.c
*
*Createdon:
2010-11-9
*Author:
WangBaoYi(zats)
*Email:
wby0322@
*/
#include<
linux/kernel.h>
linux/init.h>
linux/module.h>
linux/fs.h>
linux/string.h>
linux/mm.h>
linux/syscalls.h>
asm/unistd.h>
asm/uaccess.h>
#defineFILE_PATH_READ"
/file_read_test"
//打开文件路径(包括文件名),未来将要读的
#defineFILE_PATH_WRITE"
/new_file_test"
//打开文件路径(包括文件名),未来将要写的
//保存打开文件的文件指针变量
//为了获取文件大小用的inode结构变量
int*file_buf;
//保存开辟的内存空间的地址的指针变量
loff_tfsize;
//保存文件大小的变量
mm_segment_told_fs;
//保存内存边界的变量
*kernel_file_open封装了文件打开函数
*参数为文件路径(包含文件名)。
*操作file类型结构变量。
*打开方式为读写(没有则创建)
staticintkernel_file_open(char*file_path)
file=filp_open(file_path,O_RDWR|O_CREAT,0);
if(IS_ERR(file))
printk("
Openfile%sfailed.\n"
file_path);
return0;
*kernel_file_size封装了获取文件大小函数
*参数为待获取大小的文件指针。
*操作inode类型结构变量。
*返回值为文件大小,单位字节
staticloff_tkernel_file_size(structfile*file)
inode=file->
fsize=inode->
printk(KERN_ALERT"
returnfsize;
*kernel_addr_limit_expend封装了内存边界扩展函数
*参数无。
staticintkernel_addr_limit_expend(void)
old_fs=get_fs();
set_fs(KERNEL_DS);
*kernel_addr_limit_resume封装了内存边界恢复函数
staticintkernel_addr_limit_resume(void)
set_fs(old_fs);
*kernel_file_read封装了读文件函数
*参数为open的文件指针,获取的文件大小
*返回值为读入到内存中的首地址。
void*kernel_file_read(structfile*file,loff_tfsize)
int*buf;
loff_t*pos=&
buf=(int*)kmalloc(fsize+100,GFP_KERNEL);
vfs_read(file,buf,fsize,pos);
returnbuf;
*kernel_file_write封装了读文件函数
*参数为open的文件指针,数据在内存中的地址,写入到文件的字节数
staticintkernel_file_write(structfile*file,int*buf,loff_tfsize)
vfs_write(file,buf,fsize,pos);
*ko的主函数
staticinthello_init(void)//ko的主函数
Y(^_^)YHelloWang`sfile.\n"
);
kernel_file_open(FILE_PATH_READ);
//打开文件file_read_test
kernel_file_size(file);
//获取file_read_test的大小
/*readfiletomem*/
kernel_addr_limit_expend();
//边界扩展
file_buf=kernel_file_read(file,fsize);
//读操作
filp_close(file,NULL);
//关闭文件file_read_test
kernel_addr_limit_resume();
//边界恢复
/*writememtofile*/
kernel_file_open(FILE_PATH_WRITE);
//打开文件new_file_test,没有则创建
kernel_file_write(file,file_buf,fsize);
//将前面读到内存中的数据,写入到文件new_file_test中
//关闭文件
staticvoidhello_exit(void)
BYEBYEfileY(^_^)Y\n"
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("
DualBSD/GPL"
MODULE_AUTHOR("
wby"
MODULE_DESCRIPTION("
AsimplehelloworldModulewithFile"
简单的效果图