Linuxドライバでprocノードを作成する方法(例)


linuxカーネルでスイッチング変数を作る3つの方法の1つ:procファイルシステム(その他参照[https://blog.csdn.net/peterbig/article/details/18273665]).
コードの例
test_proc.c
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define IGH_EC_PROC_DIR "ethercat"
#define IGH_GFAR_PROC_NAME "gfar_log"

static int igh_gfar_proc_show(struct seq_file *m, void *v);
static int igh_gfar_proc_open(struct inode *inode, struct file *file);
static ssize_t igh_gfar_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *f_pos);
static int igh_gfar_proc_init(void);
static void igh_gfar_proc_exit(void);

static int igh_gfar_proc_show(struct seq_file *m, void *v)
{
	return 0;
}

static int igh_gfar_proc_open(struct inode *inode, struct file *file)
{
	return single_open(file, igh_gfar_proc_show, NULL);
}

static ssize_t igh_gfar_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *f_pos)
{
    char *tmp = kzalloc((count+1), GFP_KERNEL);
	if (!tmp)
		return -ENOMEM;
 
	if (copy_from_user(tmp,buffer,count)) {
		kfree(tmp);
		return -EFAULT;
	}
    printk("%s Get user str :%s
"
, __func__, tmp); kfree(tmp); return count; } ssize_t igh_ec_proc_read(struct file *file, char __user *buf, size_t len, loff_t *off) { int len_copy, ret; char data[32] = "1234566789"; // fl->f_pos , len if ((file->f_pos + len) > strlen(data)) // len, len_copy = strlen(data) - file->f_pos; else len_copy = len; // len, len ret = copy_to_user(buf, data+file->f_pos, len_copy); // , *off += len_copy - ret; // read/write off return len_copy - ret; } static struct file_operations igh_gfar_proc_fops = { .owner = THIS_MODULE, .open = igh_gfar_proc_open, .release = single_release, .read = igh_ec_proc_read, .llseek = seq_lseek, .write = igh_gfar_proc_write, }; struct proc_dir_entry *igh_gfar_proc_dir = NULL; static int igh_ec_proc_init(void) { struct proc_dir_entry* file; igh_gfar_proc_dir = proc_mkdir(IGH_EC_PROC_DIR, NULL); if (igh_gfar_proc_dir == NULL) { printk("%s proc create %s failed
"
, __func__, IGH_EC_PROC_DIR); return -EINVAL; } file = proc_create(IGH_GFAR_PROC_NAME, 0777, igh_gfar_proc_dir, &igh_gfar_proc_fops); if (!file) { printk("%s proc_create failed!
"
, __func__); return -ENOMEM; } return 0; } static void igh_gfar_proc_exit(void) { remove_proc_entry(IGH_GFAR_PROC_NAME, igh_gfar_proc_dir); remove_proc_entry(IGH_EC_PROC_DIR, NULL); } static int __init my_init(void) { igh_ec_proc_init(); return 0; } static void __exit my_exit(void) { igh_gfar_proc_exit(); } module_init(my_init); module_exit(my_exit); MODULE_AUTHOR("WXY"); MODULE_LICENSE("GPL");

Makefile
obj-m := test_proc.o
KERNELDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
modules:
        $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
        $(MAKE) -C $(KERNELDIR) M=$(PWD) clean

インストール方法のコンパイル
test_proc.cとMakefileを統一フォルダに入れる
  • $ make
  • $ sudo insmod test_proc.ko
  • $ echo “test” >/proc/ethercat/gfar_log
  • $dmesg(コマンドを実行するとカーネル印刷情報が表示されます)
  • 関数の説明
  • 作成関数
  • struct proc_dir_entry *proc_create(
    	const char *name, umode_t mode, struct proc_dir_entry *parent,
    	const struct file_operations *proc_fops);
    
          :
        name:/proc/       。 :"gfar_log"/proc/   demo  
        mode:    。 :066604440222  
        parent:   ,    NULL/proc   )
        proc_fops:        file_operations
           :   proc    
    
  • フォルダ関数の作成
  • struct proc_dir_entry *proc_mkdir(const char *name, struct proc_dir_entry *parent);
    
          :
        name:        
        parent:        ,           ,   proc   ,    NULL
  • 削除関数(ノードまたはディレクトリを削除)
  • void remove_proc_entry(const char *name,
    	struct proc_dir_entry *parent);
          :
        name:    proc  。
        parent:       。     struct proc_dir_entry
    

    適用方法
    Procノードの使用には、主にノードの作成と削除が含まれます.
    1.ノードの作成
    ノードを作成するための基本手順:
    ノードを作成する一般的な3つの方法
  • デフォルトでは/procパスで作成するにはproc_のみが必要ですcreateはノードを作成することができて、パラメータparentはNULLを伝えて、proc_を必要としませんmkdirはパスを作成します.例:proc_create(“myProc”, 0777, NULL, &igh_gen_proc_fops);
  • /procの既存ディレクトリの下でパラメータnameパス名にノード名を付ける組合せ例を作成する:proc_create(“myDir/myProc”, 0777, NULL, &igh_gen_proc_fops);
  • /procでディレクトリを作成してノードを作成するにはproc_を先に使用mkdirはノードディレクトリを作成し、proc_を使用します.create作成ノード上記のサンプルコード表示、proc_createのparentパラメータをprocにインポートするにはmkdirが返すインスタンス;

  • 2.ノードの削除
    ノードを作成する3つの方法に対応してノードを削除
  • 削除/procパス下のノードexitで関数remove_proc_entryはノードを削除します.procパスの下にあるので、親ディレクトリを削除する必要はありません.パラメータparentはNULLを送信します.
  • myDir/myノードを削除する例:remove_proc_entry(“myDir/my”, IGH_EC_PROC_DIR"/"IGH_GEN_PROC_NAME, NULL); myDirは/procパスの下で、パラメータparentがNULLを送信します.
  • 作成したフォルダとノードを削除するには、作成したノードを先に削除する必要があります.parentは親パスに転送され、フォルダremove_を削除します.proc_entry(IGH_GFAR_PROC_NAME, igh_gfar_proc_dir); remove_proc_entry(IGH_EC_PROC_DIR, NULL); 同様に、フォルダは/procの下にあるので、parentはNULLを伝えます.

  • 注意:
    read      proc       ,   cat         read  ,
              0              loff_t*ppo    ,
               0      read  。