在linux驅動開發過程中,經常會遇到在/proc或者/tmpfs下增加檔案的情況,/tmpfs下的檔案通常都是對采集時間有要求,是以采集完成後儲存在相關的檔案中,系統需要時進行擷取。對應的資料通常也不是實時的,除非利用定時器或者信号配合先采集後進行擷取。對于/tmpfs下的檔案,可使用”ls -lh”檢視出檔案的實際大小。這說明檔案實際是被寫入了内容的,通常/tmpfs檔案會在應用層進行讀寫操作。
對應地/proc檔案一般隻是類似一個殼,實際上并不是把内容寫入檔案中,使用“ls -lh”檢視大小通常為0。/proc檔案是在擷取時(執行cat)實時采集并顯示出來,結果是實時的并且不占空間,跟/tmpfs相比,/proc檔案儲存在核心記憶體中, 因為讀取性能及對系統影響較小。
開發的步驟大緻為:
1、驅動加載時,利用proc_mkdir建立/proc檔案路徑。利用proc_create建立檔案。
2、實作檔案對應的file_operations結構,将相關處理函數注冊到Linux核心。
3、file_operations中相關函數接口的實作,一般情況下需實作.open(對應cat操作)和.write(對應echo操作)函數。
4、驅動解除安裝時,利用remove_proc_entry删除檔案路徑和檔案。
下面通過一個例子來展示/proc檔案的開發過程:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
struct proc_dir_entry *proc_ctcwifi_dir = NULL;
struct proc_dir_entry *ctcwifi_diag_enable = NULL;
unsigned char g_ctcwifiDiagEnable;
/*Interface implementation*/
ssize_t start_ctcwifiDiagEnable_write(struct file *fp,const char __user *buffer,
size_t count,loff_t *data)
{
int i = ;
unsigned char tmp = ;
while(buffer[i] == ' ')
{
i++;
}
tmp = buffer[i] - '0';
if((tmp == ) || (tmp == ))
{
g_ctcwifiDiagEnable = tmp;
}
else
{
printk("the input parameter out of range\n");
}
return count;
}
static int ctcwifiDiagEnable_proc_read(struct seq_file *m, void *v)
{
int len = ;
len = seq_printf(m, "%d\n", g_ctcwifiDiagEnable);
return len;
}
static int ctcwifiDiagEnable_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, ctcwifiDiagEnable_proc_read, NULL);
}
/*Implement related file_operations interfaces*/
struct file_operations diag_enable_ops=
{
.open = ctcwifiDiagEnable_proc_open, //對應cat
.read = seq_read,
.write = start_ctcwifiDiagEnable_write, //對應echo
.llseek = seq_lseek,
.release = single_release,
};
int wlan_ctcwifi_init(void)
{
/*create /proc/ctcwifi*/
proc_ctcwifi_dir = proc_mkdir("ctcwifi", NULL);
if(proc_ctcwifi_dir == NULL)
{
printk("\n Can't create /proc/ctcwifi\n");
return -;
}
/*create /proc/ctcwifi/diag_enable*/
if (( ctcwifi_diag_enable = proc_create("diag_enable", ,
proc_ctcwifi_dir, &diag_enable_ops)) == NULL )
{
printk("\n Can't create /proc/ctcwifi/diag_enable file\n");
return -;
}
return ;
}
int wlan_ctcwifi_exit(void)
{
/* remove /proc/ctcwifi/diag_enable */
if (ctcwifi_diag_enable)
{
remove_proc_entry("diag_enable", proc_ctcwifi_dir);
ctcwifi_diag_enable = NULL;
}
/* remove /proc/ctcwifi*/
if (proc_ctcwifi_dir)
{
remove_proc_entry("ctcwifi", NULL);
proc_ctcwifi_dir = NULL;
}
return ;
}
module_init(wlan_ctcwifi_init);
module_exit(wlan_ctcwifi_exit);
MODULE_AUTHOR("ZC");
MODULE_LICENSE("Dual BSD/GPL");