Linux内核读写文件
须要调试的驱动程中读写文件数据,例如说当驱动须要记录的日志比较多的情况下,可以将printk()函数复印的信息都讲到文件做后续剖析。在kernel中操作文件没有标准库可用,须要借助kernel的一些函数,这种函数主要有:filp_open()filp_close(),kernel_read(),kernel_write()这种函数在linux/fs.h和asm/uaccess.h头文件中申明。下边介绍主要步骤:
一、打开文件
filp_open()在kernel中可以打开文件,其原形如下:
strcutfile*filp_open(constchar*filename,intopen_mode,intmode);
该函数返回strcutfile*结构表针,供后继函数操作使用linux写入txt文件,该返回值用IS_ERR()来检验其有效性。
参数说明:
filename:表明要打开或创建文件的名称(包括路径部份)。在内核中打开的文件时须要注意打开的时机,很容易出现须要打开文件的驱动很早就加载并打开文件linux写入txt文件,但须要打开的文件所在设备还不有挂载到文件中,而造成打开失败。
open_mode:文件的打开方法,其取值与标准库中的open相应参数类似,可以取O_CREAT,O_RDWR,O_RDONLY等。
mode:创建文件时使用,设置创建文件的读写权限红旗linux系统下载,其它情况可以匆略设为0
二、读写文件
kernel中文件的读写操作可以使用kernel_read()和kernel_write,均为内核导入函数内核函数原型为:
ssize_t kernel_read(struct file *file, void *buf, size_t count, loff_t *pos)
{
ssize_t ret;
ret = rw_verify_area(READ, file, pos, count);
if (ret)
return ret;
return __kernel_read(file, buf, count, pos);
}
EXPORT_SYMBOL(kernel_read);
ssize_t kernel_write(struct file *file, const void *buf, size_t count,
loff_t *pos)
{
ssize_t ret;
ret = rw_verify_area(WRITE, file, pos, count);
if (ret)
return ret;
file_start_write(file);
ret = __kernel_write(file, buf, count, pos);
file_end_write(file);
return ret;
}
EXPORT_SYMBOL(kernel_write);
上面的参数和ring3读写是一样的,领到filp句柄以后就可以对文件进行读写操作了。
三、关闭文件
intfilp_close(structfile*filp,fl_owner_tid);
该函数的使用很简单,第二个参数通常传递NULL值,也有用current->files作为形参的。
使用以上函数的其它注意点:
虽然LinuxKernel组成员不赞同在kernel中独立的读写文件(这样做可能会影响到策略和安全问题),对内核须要的文件内容,最好由应用层配合完成。在可加载的kernelmodule中使用这些方法读写文件可能使模块加载失败,缘由是内核可能没有EXPORT你所须要的所有这种函数。
3.剖析以上个别函数的参数可以看出linux 发邮件,这种函数的正确运行须要依赖于进程环境,为此,有些函数不能在中断的handle或Kernel中不属于任可进程的代码中执行,否则可能出现崩溃,要防止此类情况发生,可以在kernel中创建内核线程,将这种函数放到线程环境下执行(创建内核线程的方法请参数kernel_thread()函数)。四、驱动代码
#include
#define MY_FILE "/tmp/log.txt"
char buf[256];
loff_t pos = 0;
struct file *filep = NULL;
static int __init init(void)
{
printk("Hello, I'm the module that intends to write messages to file.n");
if(filep == NULL) {
filep = filp_open(MY_FILE, O_RDWR | O_APPEND | O_CREAT, 0644);
}
if (IS_ERR(filep)) {
printk("Open file %s errorn", MY_FILE);
return -1;
}
sprintf(buf,"%sn", "This is test message!");
memset(buf, 0, sizeof(buf));
kernel_write(filep, buf, strlen(buf), &pos);
memset(buf, 0, sizeof(buf));
kernel_read(filep, buf, sizeof(buf), &pos);
printk("Read buf -> %sn", buf);
return 0;
}
static void __exit fini(void)
{
printk("Kernel read/write exitn");
if(filep != NULL) {
filp_close(filep, NULL);
}
}
module_init(init);
module_exit(fini);
MODULE_LICENSE("GPL");
注意事项:
1、当驱动须要持续读写文件的话,须要考虑并发的情况,须要给buf的读写加锁。
查看log日志:
curtis@curtis-Aspire-E5-471G:~/write_code/kernel_write$ dmesg
[145731.662192] Hello, I'm the module that intends to write messages to file.
[145731.662206] pos -> 0
[145731.662210] Read buf -> This is test message!
curtis@curtis-Aspire-E5-471G:~/write_code/kernel_write$ cat /tmp/log.txt
This is test message!
参考链接:Linux内核中读写文件数据的方式_wxie的Linux人生-CSDN博客
本文原创地址://q13zd.cn/dxwjsjwjwjwj.html编辑:刘遄,审核员:暂无