平時
網路部分的東西碰的多些,這塊一開始還真不知道怎麼寫,因為肯定和在
使用者空間下是不同的。google過後,得到以下答案。一般可以用兩種方法:第一種是用
系統呼叫。第二種方法是filp->open()等函式。下面分別來說下這兩種方法。
1 利用系統呼叫:
sys_open,sys_write,sys_read等。
其實分析過sys_open可以知道,最後呼叫的也是filp->open。
sys_open ==> do_sys_open ==> filp->open
在linux
sir上的乙個帖子,上面乙個版主說: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可為正或負。
檔案讀取 LINUX核心
file i o in kernel module by flyduck 2001 03 21 define kernel define module include include include include include include include define eof 1 defin...
linux 讀取檔案
linux讀取檔案是經常要用到的操作,以下示例 說明看注釋 讀取檔案snlist.txt中的每一行內容賦給sn變數 while read sn doecho sn is sn 判斷是否是檔案 if d sn then echo sn not existed else 對sn進行 拆分並獲取最後乙個結...
Linux上讀取檔案
linux上讀取檔案的方法 bin bash this is a script fortest exec config file 1 該指令碼傳乙個檔名為引數 file no 1 echo config file exec config file 將 config file中的內容作為exec的標準...