/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と一緒
で、今回は読み取り関数だけを使用する場合だけど、書き込みも出来るらしい。
それの覚書はまた今度。
で、いつもどおり続きに動くかわからないサンプルコード。
いいかげんな関数の説明より、実装例を見たほうがたぶん簡単。
ソフトウェアが作成する特殊なファイルシステムらしい。
カーネルが情報を外部にエクスポートするために使用するらしい。
デバイスドライバの情報を簡単に外部(ユーザ空間)に出せるって考えればいいのかな?
デバッグなんかで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内のセマフォについてはまたそのうち。
/* 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内のセマフォについてはまたそのうち。
Trackbacks.
-
*スポンサーサイト*/procファイルを使う* のトラックバックURLはこちら
- http://rosara.blog4.fc2.com/tb.php/11-e5e1e9ed
