Linux 内核读写文件
Linux 內(nèi)核讀寫文件
需要調(diào)試的驅(qū)動(dòng)程中讀寫文件數(shù)據(jù),比如說(shuō)當(dāng)驅(qū)動(dòng)需要記錄的日志比較多的情況下,可以將printk()函數(shù)打印的信息都寫到文件做后續(xù)分析。在kernel中操作文件沒(méi)有標(biāo)準(zhǔn)庫(kù)可用,需要利用kernel的一些函數(shù),這些函數(shù)主要有: filp_open() filp_close(), kernel_read(),kernel_write()這些函數(shù)在linux/fs.h和asm/uaccess.h頭文件中聲明。下面介紹主要步驟:
一、打開(kāi)文件
filp_open()在kernel中可以打開(kāi)文件,其原形如下:
strcut file* filp_open(const char* filename, int open_mode, int mode);
該函數(shù)返回strcut file*結(jié)構(gòu)指針,供后繼函數(shù)操作使用,該返回值用IS_ERR()來(lái)檢驗(yàn)其有效性。
參數(shù)說(shuō)明:
filename: 表明要打開(kāi)或創(chuàng)建文件的名稱(包括路徑部分)。在內(nèi)核中打開(kāi)的文件時(shí)需要注意打開(kāi)的時(shí)機(jī),很容易出現(xiàn)需要打開(kāi)文件的驅(qū)動(dòng)很早就加載并打開(kāi)文件,但需要打開(kāi)的文件所在設(shè)備還不有掛載到文件系統(tǒng)中,而導(dǎo)致打開(kāi)失敗。
open_mode: 文件的打開(kāi)方式,其取值與標(biāo)準(zhǔn)庫(kù)中的open相應(yīng)參數(shù)類似,可以取O_CREAT,O_RDWR,O_RDONLY等。
mode: 創(chuàng)建文件時(shí)使用,設(shè)置創(chuàng)建文件的讀寫權(quán)限,其它情況可以匆略設(shè)為0
二、讀寫文件
kernel中文件的讀寫操作可以使用kernel_read()和kernel_write,均為內(nèi)核導(dǎo)出函數(shù)內(nèi)核函數(shù)原型為:
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);里面的參數(shù)和ring3讀寫是一樣的,拿到filp句柄之后就可以對(duì)文件進(jìn)行讀寫操作了。
三、關(guān)閉文件
int filp_close(struct file*filp, fl_owner_t id);
該函數(shù)的使用很簡(jiǎn)單,第二個(gè)參數(shù)一般傳遞NULL值,也有用current->files作為實(shí)參的。
使用以上函數(shù)的其它注意點(diǎn):
3.分析以上某些函數(shù)的參數(shù)可以看出,這些函數(shù)的正確運(yùn)行需要依賴于進(jìn)程環(huán)境,因此,有些函數(shù)不能在中斷的handle或Kernel中不屬于任可進(jìn)程的代碼中執(zhí)行,否則可能出現(xiàn)崩潰,要避免這種情況發(fā)生,可以在kernel中創(chuàng)建內(nèi)核線程,將這些函數(shù)放在線程環(huán)境下執(zhí)行(創(chuàng)建內(nèi)核線程的方式請(qǐng)參數(shù)kernel_thread()函數(shù))。
四、驅(qū)動(dòng)代碼
#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");注意事項(xiàng):
1、當(dāng)驅(qū)動(dòng)需要持續(xù)讀寫文件的話,需要考慮并發(fā)的情況,需要給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內(nèi)核中讀寫文件數(shù)據(jù)的方法_wxie的Linux人生-CSDN博客
總結(jié)
以上是生活随笔為你收集整理的Linux 内核读写文件的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 软件测试之逻辑覆盖测试理论总结(白话文)
- 下一篇: 【Linux初始化init系统】