核心模組中對檔案的讀寫

2021-06-16 10:38:48 字數 3511 閱讀 6291

平時網路部分的東西碰的多些,這塊一開始還真不知道怎麼寫,因為肯定和在使用者空間下是不同的。google過後,得到以下答案。一般可以用兩種方法:第一種是用系統呼叫。第二種方法是filp->open()等函式。下面分別來說下這兩種方法。

1 利用系統呼叫:

sys_open,sys_write,sys_read等。

其實分析過sys_open可以知道,最後呼叫的也是filp->open。

sys_open ==> do_sys_open ==> filp->open

在linuxsir上的乙個帖子,上面乙個版主說:sys_open和程序緊密相關,往往不在核心中使用。

而其實sys_open最後也是呼叫了filp->open。

其實好像linux2.6.20後面就不推薦使用sys_open,那我們這裡就就後者進行詳細的介紹

2 filp->open等函式。

在模組中,使用者空間的open,read,write,llseek等函式都是不可以使用的。應該使用其在核心中對應的函式。可以使用filp->open配合struct file裡的read/write來進行對檔案的讀寫操作。

例子1:

#include

#include

#include

#include

#include

module_author("[email protected].");

module_description("kernel study and test.");

void fileread(const char * filename)

void filewrite(char* filename, char* data)

fs=get_fs();

set_fs(kernel_ds);

filp->f_op->write(filp, data, strlen(data),&filp->f_pos);

set_fs(fs);

filp_close(filp,null);

}int init_module()

void cleanup_module()

複製**

eg2:

#include

#include

#include

#include

#include

#include

#include/* get_fs(),set_fs(),get_ds() */

#define file_dir "/root/test.txt"

module_license("gpl");

module_author("[email protected]");

char *buff = "module read/write test";

char tmp[100];

static struct file *filp = null;

static int __init wr_test_init(void)

return 0;

}static void __exit wr_test_exit(void)

module_init(wr_test_init);

module_exit(wr_test_exit);

複製**

3.makefile

obj-m := os_attack.o

kdir := /lib/modules/$(uname -r)/build/

pwd := $(shell pwd)

all:module

module:

$(make) -c $(kdir) m=$(pwd) modules

clean:

rm -rf *.ko *.mod.c *.o module.* modules.* .*.cmd .tmp_versions

複製**

注意:在呼叫filp->f_op->read和filp->f_op->write等對檔案的操作之前,應該先設定fs。

預設情況下,filp->f_op->read或者filp->f_op->write會對傳進來的引數buff進行指標檢查。如果不是在使用者空間會拒絕訪問。因為是在核心模組中,所以buff肯定不在使用者空間,所以要增大其定址範圍。

拿filp->f_op->write為例來說明:

filp->f_op->write最終會呼叫access_ok ==> range_ok.

而range_ok會判斷訪問的位址是否在0 ~ addr_limit之間。如果在,則ok,繼續。如果不在,則禁止訪問。而核心空間傳過來的buff肯定大於addr_limit。所以要set_fs(get_ds())。

這些函式在asm/uaccess.h中定義。以下是這個標頭檔案中的部分內容:

#define make_mm_seg(s)    ((mm_segment_t) )

#define kernel_ds    make_mm_seg(-1ul)

#define user_ds        make_mm_seg(page_offset)

#define get_ds()    (kernel_ds)

#define get_fs()    (current_thread_info()->addr_limit)

#define set_fs(x)    (current_thread_info()->addr_limit = (x))

#define segment_eq(a, b)    ((a).seg == (b).seg)

可以看到set_fs(get_ds())改變了addr_limit的值。這樣就使得從模組中傳遞進去的引數也可以正常使用了。

在寫測試模組的時候,要實現的功能是寫進去什麼,然後讀出來放在tmp陣列中。但寫完了以後filp->f_ops已經在末尾了,這個時候讀是什麼也讀不到的,如果想要讀到資料,則應該改變filp->f-ops的值,這就要用到filp->f_op->llseek函式了。上網查了下,其中的引數需要記下筆記:

系統呼叫:

off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin)

offset是偏移量。

若origin是seek_set(0),則將該檔案的位移量設定為距檔案開始處offset 個位元組。

若origin是seek_cur(1),則將該檔案的位移量設定為其當前值加offset, offset可為正或負。

若origin是seek_end(2),則將該檔案的位移量設定為檔案長度加offset, offset可為正或負。

ok,that's all.

使用者空間                   核心open()                    sys_open(), filp_open()close()                   sys_close(), filp_close()read()                    sys_read(), filp_read()write()                   sys_write(), filp_write()

核心模組中對檔案的讀寫

平時網路部分的東西碰的多些,這塊一開始還真不知道怎麼寫,因為肯定和在使用者空間下是不同的。google過後,得到以下答案。一般可以用兩種方法 第一種是用系統呼叫。第二種方法是filp open 等函式。下面分別來說下這兩種方法。1 利用系統呼叫 sys open,sys write,sys read...

核心中對檔案的讀寫操作

在專案中,需要在核心裡讀取檔案內容到記憶體中,需要用到的函式有 struct file filp open const char filename,int flags,umode t mode int filp close struct file filp,fl owner t id static ...

python中對檔案的讀寫

檔案 將資料儲存到硬碟中 資料持久化 開啟檔案 open 檔案路徑,訪問模式 w write 寫入模式,只能寫,不能讀 f open 123.txt w 寫入資料 只能是字串 f.write hello world 關閉檔案 檔案操作完必須要關閉,否則檔案占用記憶體將無法釋放 記憶體洩漏 明知沒有用...