星期二, 3月 11, 2014

Reference from :愛做夢的蘆薈

在embedded的設備上,driver需要讀取某些設定檔並根據設定值設定硬體,除了ioctl, file read/write之外,最簡單的方式莫過於直接在kernel space進行設定檔的讀寫,不過通常”寫入”這個功能很少用到,所以我略過這個東西不提
在kernel讀取檔案的方式非常簡單,小弟粗分為三個步驟,這三個步驟後方所列的就是kernel的API
1.Open file: filp_open
2.Read file: f_op->read
3.Close file: filp_close
程式的範例請直接參考下面所列,
程式裡面比較值得一提的是get_fs和set_fs,kernel會根據set_fs的設定值決定要不要檢查讀/寫memory的界限,如果set_fs傳入的參數是kernel_ds,那kernel會bypass memory 界限的檢查,經過這樣的設定,才能正確取得檔案資料
#include <linux/kernel.h> 
#include <linux/module.h> 
#include <linux/init.h> 
#include <linux/slab.h> 
#include <linux/unistd.h> 
#include <linux/sched.h> 
#include <linux/fs.h> 
#include <linux/file.h> 
#include <linux/mm.h> 
#include <asm/uaccess.h> 
 
mm_segment_t oldfs;
 
struct file *openFile(char *path,int flag,int mode) { struct file *fp;
 
fp=filp_open(pathflag0)if (fp) return fpelse return NULL}
 
int readFile(struct file *fp,char *buf,int readlen) { if (fp->f_op && fp->f_op->read) return fp->f_op->read(fp,buf,readlen, &fp->f_pos)else return -1}
 
int closeFile(struct file *fp) { filp_close(fp,NULL)return 0}
 
void initKernelEnv(void) { oldfs = get_fs()set_fs(KERNEL_DS)}
 
static int __init readfile_init(void) { char buf[1024]struct file *fpint ret;
 
initKernelEnv()fp=openFile("/etc/myconfig",O_RDONLY,0)if (fp!=NULL) { memset(buf,0,1024)if ((ret=readFile(fp,buf,1024))>0) printk("buf:%s\n",buf)else printk("read file error %d\n",ret)closeFile(fp)} set_fs(oldfs)return 0}
 
static void __exit readfile_exit(void) {
 
printk("read file module remove successfully\n")} module_init(readfile_init)module_exit(readfile_exit);
 
MODULE_DESCRIPTION("read a file in kernel module")MODULE_AUTHOR("Joey Cheng")MODULE_LICENSE("GPL")MODULE_ALIAS("read file module");