Linux 内核读写文件
Linux 內核讀寫文件
需要調試的驅動程中讀寫文件數據,比如說當驅動需要記錄的日志比較多的情況下,可以將printk()函數打印的信息都寫到文件做后續分析。在kernel中操作文件沒有標準庫可用,需要利用kernel的一些函數,這些函數主要有: filp_open() filp_close(), kernel_read(),kernel_write()這些函數在linux/fs.h和asm/uaccess.h頭文件中聲明。下面介紹主要步驟:
一、打開文件
filp_open()在kernel中可以打開文件,其原形如下:
strcut file* filp_open(const char* filename, int open_mode, int mode);
該函數返回strcut file*結構指針,供后繼函數操作使用,該返回值用IS_ERR()來檢驗其有效性。
參數說明:
filename: 表明要打開或創建文件的名稱(包括路徑部分)。在內核中打開的文件時需要注意打開的時機,很容易出現需要打開文件的驅動很早就加載并打開文件,但需要打開的文件所在設備還不有掛載到文件系統中,而導致打開失敗。
open_mode: 文件的打開方式,其取值與標準庫中的open相應參數類似,可以取O_CREAT,O_RDWR,O_RDONLY等。
mode: 創建文件時使用,設置創建文件的讀寫權限,其它情況可以匆略設為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句柄之后就可以對文件進行讀寫操作了。
三、關閉文件
int filp_close(struct file*filp, fl_owner_t id);
該函數的使用很簡單,第二個參數一般傳遞NULL值,也有用current->files作為實參的。
使用以上函數的其它注意點:
3.分析以上某些函數的參數可以看出,這些函數的正確運行需要依賴于進程環境,因此,有些函數不能在中斷的handle或Kernel中不屬于任可進程的代碼中執行,否則可能出現崩潰,要避免這種情況發生,可以在kernel中創建內核線程,將這些函數放在線程環境下執行(創建內核線程的方式請參數kernel_thread()函數)。
四、驅動代碼
#include <asm/uaccess.h>#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 error\n", MY_FILE);return -1;}sprintf(buf,"%s\n", "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 -> %s\n", buf);return 0; }static void __exit fini(void) {printk("Kernel read/write exit\n");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博客
總結
以上是生活随笔為你收集整理的Linux 内核读写文件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 软件测试之逻辑覆盖测试理论总结(白话文)
- 下一篇: 使用 typescript ,提升 vu