Linux proc file system for module development

來源:互聯網
上載者:User

建立一個 proc 檔案
根據對 proc 檔案的不同使用,核心提供了多種封裝函數來建立一個 proc 檔案。

方法一:
struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode, struct proc_dir_entry *parent)
這是最直接,封裝最少的建立方法。
參數 name 是要建立的 proc 檔案名稱。mode 是該檔案許可權值,例如 S_IRUGO,可傳入0表示採用系統預設值。parent 指定該檔案的上層 proc 目錄項,如果為 NULL,表示建立在 /proc 根目錄下。
create_proc_entry() 完成的任務主要包括:檢測 mode 值,分配 proc_dir_entry 結構,註冊 proc_dir_entry。

方法二:
static inline struct proc_dir_entry *create_proc_read_entry(const char *name, mode_t mode, struct proc_dir_entry *base, read_proc_t *read_proc, void * data)
{
    struct proc_dir_entry *res=create_proc_entry(name,mode,base);
    if (res) {
        res->read_proc=read_proc;
        res->data=data;
    }
    return res;
}
如果要建立一個唯讀 proc 檔案,可以採用 create_proc_read_entry() 這個介面。這個介面其實就是給 proc_dir_entry 多賦了兩個值,其中 read_proc 是一個函數指標, data 是 read_proc 調用時傳給它一個參數。關於 read_proc 函數,接下來會另行分析。

方法三:
struct proc_dir_entry *proc_create(const char *name, mode_t mode, struct proc_dir_entry *parent, const struct file_operations *proc_fops)
如果要建立一個 proc 檔案,並且不用 proc_fs 預設提供的 file_operations 的話,可以使用 proc_create() 這個函數,通過最後一個參數來指定要建立的 proc 檔案的 file_operations。
每個 proc 檔案也都會用到 file_operations,在調用 create_proc_entry() 建立 proc 檔案時,其中一步是調用 proc_register(),proc_register() 會為 proc_dir_entry 提供一個預設的 file_operations,而 proc_create() 與 create_proc_entry() 唯一差別就是在調用 proc_register() 前先設定好 proc_dir_entry 的 file_operations,這樣在 proc_register() 時就不會設定使用 proc_fs 預設的 file_operations 了。
proc_fs 預設的 file_operations 定義如下:
static const struct file_operations proc_file_operations = {
    .llseek        = proc_file_lseek,
    .read        = proc_file_read,
    .write        = proc_file_write,
};
關於這個 proc_file_operations,後面會繼續講到。
proc_create() 一般在建立使用 seq_file 介面的 proc 檔案時會使用。

 

建立一個 proc 目錄
建立一個 proc 目錄就調用 struct proc_dir_entry *proc_mkdir(const char *name, struct proc_dir_entry *parent) 這個函數。參數name 是目錄名,parent 是該目錄的上層 proc 目錄項,如果為 NULL,表示建立在 /proc 根目錄下。

刪除一個 proc 項
要刪除一個 proc 檔案或目錄就調用 void remove_proc_entry(const char *name, struct proc_dir_entry *parent)

注意事項
proc 項建立時要避免已經存在同名的 proc 項,否則註冊時核心會報錯(但還是會成功返回那個 proc 項),在刪除時有時會刪不掉(尤其是 proc 目錄)。
刪除一個 proc 目錄會把這個目錄所有的 proc 檔案都刪除。

讀 proc 檔案
proc 檔案的讀需要自己提供一個 read_proc_t 類型的函數放在 proc_dir_entry 結構中供 proc_file_read() 函數調用。下面是 read_proc_t 類型函數的定義:
typedef int (read_proc_t)(char *page, char **start, off_t off, int count, int *eof, void *data);
這個函數的定義很複雜,不過當 proc 檔案返回的資料量總是小於一個 PAGE_SIZE 時可以簡化使用。關於這個函數以及它的那一大串參數我覺得再怎麼解釋都解釋不全,所以還是留給自己去看 proc_file_read() 的代碼就明白了。

寫 proc 檔案
proc 檔案的寫很簡單。如果是使用 proc_fs 預設提供的 file_operations 的話,要自己實現一個 write_proc_t 類型的函數放在 proc_dir_entry 結構中供 proc_file_write() 函數調用。write_proc_t 類型函數的定義如下:
typedef int (write_proc_t)(struct file *file, const char __user *buffer, unsigned long count, void *data);
下面是 proc_file_write() 的實現:
static ssize_t proc_file_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
{
    struct inode *inode = file->f_path.dentry->d_inode;
    struct proc_dir_entry * dp;
 
    dp = PDE(inode);

    f (!dp->write_proc)
        return -EIO;

    /* FIXME: does this routine need ppos? probably... */
    return dp->write_proc(file, buffer, count, dp->data);
}
可見 proc 檔案的寫忽略了使用位移量。

如果是使用自己提供的 file_operations 的話,那還是要自己實現一個 write 函數賦給 file_operations 的 .write 指標。

一個例子
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>

static struct proc_dir_entry *mydir;
static struct proc_dir_entry *pfile;

static char msg[255];

static int myproc_read(char *page, char **start, off_t off, int count, int *eof, void *data)
{
        int len = strlen(msg);

        if (off >= len)
                return 0;

        if (count > len - off)
                count = len - off;

        memcpy(page + off, msg + off, count);
        return off + count;
}

static int myproc_write(struct file *file, const char __user *buffer, unsigned long count, void *data)
{
        unsigned long count2 = count;

        if (count2 >= sizeof(msg))
                count2 = sizeof(msg) - 1;

        if (copy_from_user(msg, buffer, count2))
                return -EFAULT;

        msg[count2] = '/0';
        return count;
}

static int __init myproc_init(void)
{
        mydir = proc_mkdir("mydir", NULL);
        if (!mydir) {
                printk(KERN_ERR "Can't create /proc/mydir/n");
                return -1;
        }

        pfile = create_proc_entry("pool", 0666, mydir);
        if (!pfile) {
                printk(KERN_ERR "Can't create /proc/mydir/pool/n");
                remove_proc_entry("mydir", NULL);
                return -1;
        }

        pfile->read_proc = myproc_read;
        pfile->write_proc = myproc_write;

        return 0;
}

static void __exit myproc_exit(void)
{
        remove_proc_entry("pool", mydir);
        remove_proc_entry("mydir", NULL);
}

module_init(myproc_init);
module_exit(myproc_exit);

這個例子建立一個 /proc/mydir/pool,它相當於一個池子,你向它寫什麼,你讀它的時候它就返回什麼,當然它的容量是有限的

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.