天天看點

驅動中/proc檔案開發

       在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");
           

繼續閱讀