/procファイルシステムとカーネルを使用する(1)-初歩的な関係の確立


/procファイルシステムはLinuxカーネルの仮想ファイルシステムで、仮想とはディスクパーティション上のファイルシステムとは異なり、カーネルが起動した後、動作したときにのみ動的に作成されます.
/procの下の内容はカーネルの配置と動作の状態によって変化して、例えば/proc/meminfoというファイル、中の内容はメモリ情報で、異なる機械は自然に違います;また、/procディレクトリの下に数字で命名されたサブディレクトリもあり、各サブディレクトリの名前は数字であり、現在システムが実行しているプロセスに対応し、サブディレクトリの内容はプロセスに対応する情報である.
procには他にもたくさんの情報がありますが、ここでは一つ一つ説明しません.興味があればグーグルで話してもいいです.
Linuxカーネルは長年の発展を経て、/procディレクトリの下の林林林総、すでに非常に多くて、すでに新しい/sysファイルシステムの代替/procを開発しましたが、多くの伝統的なプログラムは依然として/procファイルシステムをカーネルとユーザープログラムのインタフェースとして使用しています.
カーネルをより効率的にするには、カーネル開発者のことです.カーネルを使用する開発者として、/procファイルシステムの使用方法を把握することも役に立ち、/sysファイルシステムの組織が厳密な構造に比べて、/procを使用するのは便利な場合があります.
くだらないことを言わないで、まずドアに入って、/procの最も基本的な操作を紹介します.
このセットでは、操作/procファイルシステムの3つの最も基本的な関数について説明します.
コードクリップ1は、カーネルコードの

  
  
  
  
  1. struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,  
  2.       struct proc_dir_entry *parent);  
  3.  
  4. struct proc_dir_entry *proc_mkdir(const char *name,
  5. struct proc_dir_entry *parent);  
  6.  
  7. void remove_proc_entry(const char *name, struct proc_dir_entry *parent);  
  8.  

まず、この例のすべてのコードはカーネルバージョン2.6.38.2を使用しています.システムはubuntu 11.04 amd 64です.注意してください.
この3つの関数は、関数名から意味が理解できます.最初のcreate_proc_entry()関数は、ノードを作成するために使用されます.つまり、ファイルを作成します.
2番目のproc_mkdir()関数はディレクトリを作成します.
3番目のremove_proc_entry()関数はノードを削除することですが、実際にはノードだけでなくproc_も削除できます.mkdir()関数で作成されたディレクトリ.
注意すべきは、procに関連する関数であり、操作の目標は/procディレクトリの下にある.では、関数パラメータを見てみましょう.
create_proc_entry()関数:nameはノードの名前で、文字列です.modeアクセス権は、8進数で表すことができ、chmodコマンドが使用する権限と同じです.parent親ディレクトリ、struct proc_であることに注意dir_entry構造で、NULLと書けば/procディレクトリを表します.
proc_mkdir()関数:nameサブディレクトリ名、文字列;parent親ディレクトリは、上記の説明と同じです.
remove_proc_entry()関数:パラメータは上と同じです.
関数の説明が終わりました.この3つの関数があれば着工できます.くだらないことは言わないで、コードを貼ってください.
コードクリップ2は自分で書いた小さなモジュールで、削除/procノードを確立する方法を示します.

  
  
  
  
  1. #include <linux/module.h>  
  2. #include <linux/init.h>  
  3. #include <linux/version.h>  
  4. #include <linux/proc_fs.h>  
  5.  
  6. MODULE_LICENSE("Dual BSD/GPL");  
  7. MODULE_AUTHOR("<[email protected]>");  
  8.  
  9. #define USER_ROOT_DIR "pt"  
  10. #define USER_ENTRY1   "pt_entry1"  
  11.  
  12. // user defined directory  
  13. static struct proc_dir_entry *pt_root;  
  14. static struct proc_dir_entry *pt_entry1;  
  15.  
  16. static int proc_test_init(void)  
  17. {  
  18.   // Create user root dir under /proc  
  19.   pt_root = proc_mkdir(USER_ROOT_DIR, NULL);  
  20.   if (NULL==pt_root)  
  21.   {  
  22.     printk(KERN_ALERT "Create dir /proc/%s error!
    "
    ,  
  23.         USER_ROOT_DIR);  
  24.     return -1;  
  25.   }  
  26.   printk(KERN_INFO "Create dir /proc/%s
    "
    , USER_ROOT_DIR);  
  27.  
  28.   // Create a test entry under USER_ROOT_DIR  
  29.   pt_entry1 = create_proc_entry(USER_ENTRY1,  
  30.       0666, pt_root);  
  31.   if (NULL == pt_entry1)  
  32.   {  
  33.     printk(KERN_ALERT "Create entry %s under /proc/%s error!
    "
    ,  
  34.         USER_ENTRY1, USER_ROOT_DIR);  
  35.     goto err_out;  
  36.   }  
  37.   printk(KERN_INFO "Create /proc/%s/%s
    "
    ,  
  38.       USER_ROOT_DIR, USER_ENTRY1);  
  39.  
  40.   pt_entry1->read_proc = NULL;  
  41.   pt_entry1->write_proc = NULL;  
  42.  
  43.   return 0;  
  44.  
  45. err_out:  
  46.   remove_proc_entry(USER_ROOT_DIR, pt_root);  
  47.   return -1;  
  48. }  
  49.  
  50. static void proc_test_exit(void)  
  51. {  
  52.   // Remove all entries  
  53.   remove_proc_entry(USER_ENTRY1, pt_root);  
  54.   remove_proc_entry(USER_ROOT_DIR, NULL);  
  55.   printk(KERN_INFO "All Proc Entry Removed!
    "
    );  
  56. }  
  57.  
  58. module_init(proc_test_init);  
  59. module_exit(proc_test_exit);  

標準的な2.6カーネルモジュールの書き方.proc_test_Init()関数はエントリ、proc_test_exit()関数は出口です.
最初は4つのヘッダファイルが導入され、そのうち3つはカーネルモジュールが標準化されたヘッダファイルで、4つ目は主役、proc_fs.h,前述したように,操作/procの関数は定義されている.
9行目、USER_ROOT_DIRは、/procディレクトリの下で作成するサブディレクトリ名を定義し、ユーザーのルートディレクトリでもあります.10行目、USER_ENTRY 1はUSERで定義したROOT_DIRの下に作成されたノード名.
13行目、14行目はそれぞれUSER_を定義していますROOT_DIRとUSER_ENTRY 1対応ディレクトリ構造pt_rootとpt_entry1.
操作したデータを紹介して、流れを話しましょう.
proc_test_Init()関数:
この関数は、モジュールをロードするときに実行されるエントリ関数で、カーネルによって自動的に呼び出されます.19行目、関数は最初からproc_を呼び出します.mkdir()関数、/procディレクトリの下にサブディレクトリを作成し、proc_に注意します.mkdir()関数の2番目のパラメータ、NULLは/procをルートディレクトリとして表します.
サブディレクトリUSER_ROOT_DIRが正常に確立されると、create_が呼び出されます.proc_entry()関数はファイルノードを確立し、関数の3番目のパラメータparentに注意し、NULLではなくpt_root,表示はUSER_ROOT_DIRをルートディレクトリとして使用します.
ファイルの作成に成功したらpt_を設定する必要がありますentry 1の読み書きコールバック関数はNULLであり、このような目的は、このファイルノードの読み書き操作を処理しないことである.
proc_test_exit()関数:
ユーザがrmmodを呼び出してカーネルモジュールをアンインストールするとカーネルに呼び出されます.この関数は、確立されたノードを削除します.remove_に注意してください.proc_entry()関数のparent実パラメータです.ここではエラーが発生しやすく、カーネルエラーが発生します.
最後にMakefileを貼ります.

  
  
  
  
  1. obj-m += proc_test1.o  
  2.  
  3. all:  
  4.     make -C /usr/src/linux-headers-2.6.38-8-generic M=`pwd` modules  
  5.  
  6. clean:  
  7.     make -C /usr/src/linux-headers-2.6.38-8-generic M=`pwd` clean 

実行の効果を確認します.
次に、モジュールをロードした後にファイルノードをリストします.

  
  
  
  
  1. root@iscsia:~/proc_test# ll /proc/pt/  
  2. total 0  
  3. -rw-rw-rw- 1 root root 0 2011-07-01 15:04 pt_entry1 

次はファイル読み込みノード/proc/pt/pt_entry1

  
  
  
  
  1. root@iscsia:~/proc_test# cat /proc/pt/pt_entry1   
  2. root@iscsia:~/proc_test#  

コールバック関数がNULLに設定されているので、何の結果もありません.
書き込みファイルノード/proc/pt/pt_entry1

  
  
  
  
  1. root@iscsia:~/proc_test# echo "hello,entry" > /proc/pt/pt_entry1  
  2. -bash: echo: write error: Input/output error 

書くのはあまり理想的ではないようですが、新聞を間違えました.pt_entry 1はあまり協力していませんね.そうですね.前はNULLに設定されていますから、人のせいにするわけにはいきません.ははは.次回は、自分の読み書き操作の仕方をご紹介します.