日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > linux >内容正文

linux

Linux 内核读写文件

發(fā)布時(shí)間:2023/12/10 linux 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux 内核读写文件 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

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):

  • 其實(shí)Linux Kernel組成員不贊成在kernel中獨(dú)立的讀寫文件(這樣做可能會(huì)影響到策略和安全問(wèn)題),對(duì)內(nèi)核需要的文件內(nèi)容,最好由應(yīng)用層配合完成。
  • 在可加載的kernel module中使用這種方式讀寫文件可能使模塊加載失敗,原因是內(nèi)核可能沒(méi)有EXPORT你所需要的所有這些函數(shù)。
    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)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。