proc檔案的實現也需要編寫出乙個核心模組並插入核心。模組的編寫過程我們已經hello,module過了,而proc檔案的實現稍微複雜一些。
在linux核心模組編寫中,常常會有一些結構體,結構體中定義了很多函式指標,核心模組的編寫常常是圍繞著實現這些函式指標而進行的。實現了這些介面便可以呼叫相應的函式把相應的功能模組插入核心(拗口),以下是proc檔案的結構體介面描述:
//linux/proc_fs.h
//讀函式原型
typedef int (read_proc_t)(char *page, char **start, off_t off,
int count, int *eof, void *data);
//寫函式原型
typedef int (write_proc_t)(struct file *file, const char __user *buffer,
unsigned long count, void *data);
struct proc_dir_entry ;
/*建立乙個proc結構體
@name: proc檔案的名字
@mode:
@parent: proc檔案被建立的目錄
*/struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,struct proc_dir_entry *parent);
/*從核心中移除乙個proc檔案
*/void remove_proc_entry(const char *name, struct proc_dir_entry *parent) ;
已經有一些預定義的proc目錄可直接作為parent使用:
proc_dir_entry
在檔案系統中的位置
proc_root_fs
/proc
proc_net
/proc/net
proc_bus
/proc/bus
proc_root_driver
/proc/driver
write_proc_t 函式(寫函式):使用者空間到核心空間
很明顯,write_proc_t函式的實現賦予proc 寫語義,它的原型如下:
int (write_proc_t)(struct file *file, const char __user *buffer, unsigned long count, void *data);
引數file可忽略,buffer為使用者空間需要寫入的資料的頭指標,count 為使用者空間需要寫入核心的資料長度,data為proc結構體得私有資料,對應於 struct proc_dir_entry結構體中的data欄位。編碼過程中常常需要將使用者空間的資料拷貝到核心,因為使用者空間的指標不能在核心空間中使用(那不是很多拷貝,效率不是很低..),常見的拷貝函式有以下兩枚
/* copy buffer to user-space from kernel-space */
unsigned long copy_to_user( void __user *to, const void *from,unsigned long n );
/* copy buffer to kernel-space from user-space */
unsigned long copy_from_user( void *to,const void __user *from, unsigned long n );
__user巨集只是方便源**查詢而已,沒有實際語義。這兩個copy函式可能會造成阻塞,故只能在程序上下文中使用,如果在中斷上下文中使用,那恭喜你,你的核心會莫名的掛掉了。
read_proc_t 函式(讀函式):核心空間到使用者空間
typedef int (read_proc_t)(char *page, char **start, off_t off, int count, int *eof, void *data);
當某個程序讀取我們的proc檔案時,核心會分配乙個記憶體頁(即page_size大小的記憶體塊),核心模組將資料寫入到這張頁來返回資料到使用者空間。
以上引數中,page引數是為程序分配的記憶體頁,其中count定義了定義了可以寫入的最大字元數。在返回多頁資料(通常一頁是4k),我們需要使用start和off引數。當所有資料全部寫入後,就需要設定eof(檔案結束引數)。與write類似,data也是私有資料。此處提供的page緩衝區在核心空間。因此不必使用copy_to_user,而可以直接寫入。該函式返回寫入的位元組數。
start引數:start引數使用者實現返回大於一頁的資料。在read_proc_t方法被呼叫時,*start的初始值為null。如果保留*start為null,核心將家丁資料儲存在記憶體頁偏移量0的地方,並且忽略off引數。相反,如果我們將*start設為非空值,核心將認為由*start指向的資料是off引數指定的偏移量中的資料。通常返回少量資料的簡單read_proc函式可忽略start引數,複雜的read_proc函式將*start設定為頁面,並將請求偏移量處得資料放到記憶體頁。
start引數還有另一種用法,將在下文繼續討論。
以下內容實現乙個簡單的可讀寫的proc檔案例子:
#include#include#include#include#include#includemodule_license("gpl");
module_description("fortune cookie kernel module");
#define max_cookie_length page_size
//儲存proc結構體指標
static struct proc_dir_entry *proc_entry;
//儲存緩衝區指標
static char *cookie_pot;
// cookie_index=已經寫入的資料數目-1 。
static int cookie_index;
//遍歷標
static int next_fortune;
ssize_t fortune_write(struct file *filp,const char __user *buff,
unsigned long len, void *data)
if(copy_from_user(&cookie_pot[cookie_index],buff,len ) )
return -efault;
cookie_index+=len;
cookie_pot[cookie_index-1]=0;
return len;
}//每讀一次返回乙個之前寫入的字串。
int fortune_read(char *page,char **start,off_t off,
int count ,int *eof,void *data)
if( next_fortune >= cookie_index ) next_fortune= 0 ;
len=sprintf(page,"%s\n", &cookie_pot[ next_fortune ] ) ;
next_fortune+=len;
return len; }
int init_fortune_module(void)
else
}return ret;
}void cleanup_fortune_module(void)
module_init(init_fortune_module);
module_exit(cleanup_fortune_module);
上文實現了乙個可以讀寫的proc檔案。讀者可以往/proc/fortune中寫入字串後再讀取來檢視該模組的行為。
編寫乙個簡單的shell
include include include include include include include include void getloginname void gethostname void getdir p printf s p int main char argv 32 char...
編寫乙個簡單的死鎖
public class dead lock1 class runnable1 implements runnable catch exception e class runnable2 implements runnable catch exception e obj1 和 obj2 都是屬於類的...
乙個簡單的makefile的編寫
標頭檔案 part.h cpp檔案 包含part.h part.cpp cpp檔案 包含part.h partmain.cpp makefile編寫如下 main partmain.o part.o g o main partmain.o part.o partmain.o partmain.cpp...