メモ帳
メモ帳
スポンサーサイト
--年--月--日 (--) --:-- | 編集
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
/procファイルを使う
2007年05月18日 (金) 10:52 | 編集
/procファイルって何?
 ソフトウェアが作成する特殊なファイルシステムらしい。
 カーネルが情報を外部にエクスポートするために使用するらしい。

デバイスドライバの情報を簡単に外部(ユーザ空間)に出せるって考えればいいのかな?
デバッグなんかでprintkでコンソールに情報を出すのもいいけど
タイミングがシビアなドライバだとprintkの処理による処理落ちで内部処理が
変わってきちゃうからそんなのとかの回避に使うといいみたい。

まずは関数から
エントリーを作成する関数がこれ。
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)

長い。
引数1:nameは作成するファイル名。
引数2:modeはファイルの保護マスク。保護マスクって何?デフォルトモードは0らしい。
引数3:baseはファイルが作成されるディレクトリ。NULLだと/procになる。
引数4:read_procは/proc読み出すときに呼ばれる関数を指定。
引数5:dataは謎。カーネルは無視するけどread_procには渡されるとか。

で、引数4のread_procってのは
int (*read_proc) (char *page, char **start, off_t offset, int count, int *eof, void *data)
って関数を使うらしい。
引数1:pageはデータを書き込む先のバッファ
引数2:startは対照のデータがpageのどこをさしているかを示す
引数3:offsetはアクセスしている位置
引数4:countはread出来る最大文字数
引数5:eofはデータがすべて書かれたときに返す値
引数6:dataは内部処理に使うらしい


エントリーの逆も必要なわけで。
void remove_proc_entry(const char *name, struct proc_dir_entry *base)
引数1:nameは生成のときのnameと一緒
引数2:baseも生成のときのbaseと一緒

で、今回は読み取り関数だけを使用する場合だけど、書き込みも出来るらしい。
それの覚書はまた今度。

で、いつもどおり続きに動くかわからないサンプルコード。
いいかげんな関数の説明より、実装例を見たほうがたぶん簡単。
例)

/* includeは省略 */

#define DRV_VERSION 1.0.0
#define LOCAL_VERSION 0.0.1


//cdevを定義。
struct cdev hoge_cdev;

static int hoge_read_proc( char* page, char** start, off_t offset,
                   int count, int* eof, void* data )
{
int len = 0;

    /* セマフォで排他処理開始(セマフォ確保) */
if ( down_interruptible( &proc_sem ) ) {
printk("down_interruptible error\n" );
return -ERESTARTSYS;
}

len += sprintf(page + len, "hoge Driver Version : %s - %s \n", DRV_VERSION , LOCAL_VERSION);
len += sprintf(page + len, "hoge Driver Compiled : "__DATE__" "__TIME__"\n");

    /* セマフォで排他処理終了(セマフォ解放) */
up( &proc_sem );
return len;
}

int hoge_open(struct inode *inode, struct file *filp)
{
  //なんかopen処理
}
int hoge_close(struct inode *inode, struct file *filp)
{
  //なんかrelease処理
}
static long tuner_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
  //なんかioctl処理
}

//ファイルオペレーション構造体
//このサンプルドライバを使ってopenとかcloseとかioctlを呼び出すと
//hoge_openやらhoge_closeやらhoge_ioctlが呼び出される。
static struct file_operations fops =
{
  .owner = THIS_MODULE,
  .unlocked_ioctl = hoge_ioctl,
  .open = hoge_open,
  .release = hoge_close,

};

static int __init hoge_init(void)
{

  //適当。
  int hoge_major = 202, hoge_minor = 0;
  dev_t hoge_dev_t;
  struct proc_dir_entry *hoge_entry = 0;

  /* procファイルのエントリ作成 */
  hoge_entry = create_proc_read_entry("driver/hogeinfo", 0, NULL, hoge_read_proc, NULL);
  if(hoge_entry == NULL) return -1;


#if 1
  /* 自分で指定したメジャー番号を使いたいときはこっち */
  /* MKDEV(メジャー番号, マイナー番号)ってマクロでdev_t生成*/
  hoge_dev_t = MKDEV(hoge_major, hoge_minor)
  register_chrdev_region(hoge_dev_t, 1, "hoge")
#else
  /* 空いているメジャー番号を動的に取得したいときはこっち */
  alloc_chrdev_region(&hoge_dev_t, hoge_minor, 1, "hoge");
#endif
  cdev_init(&hoge_cdev, &hoge_fops);
  hoge_cdev.owner = THIS_MODULE;

  ret = cdev_add(&hoge_cdev, , 1);
  if(ret < 0){
    remove_proc_entry("driver/hogeinfo", NULL);
    return -1;
  }
  return 0;
}

static void __exit hoge_exit(void)
{
  remove_proc_entry("driver/hogeinfo", NULL);
  cdev_del(&hoge_cdev);
  unregister_chrdev_region(hoge_dev_t, 1);
}

module_init(hoge_init);
module_exit(hoge_exit);

こんな感じかしら。
で、これをロードしてコンソールで
# cat /proc/driver/hogeinfo
って打てば
hoge Driver Version : 1.0.0 - 0.0.1
hoge Driver Compiled : xxxxxxxxxx
って出力されるはず。
hoge_read_proc内のセマフォについてはまたそのうち。
コメント
この記事へのコメント
コメントを投稿する
URL :
コメント :
パスワード :
秘密 : 管理者にだけ表示を許可する
 
トラックバック
この記事のトラックバックURL
この記事へのトラックバック
copyright © 2004 Powered By FC2 allrights reserved. / template: sukechan
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。