驱动程序加载(insmod)之后,通过什么样的手段来观测设备的运行状况呢?通常可以在file_operation对应的各个函数里面用printk(内核态常用的打印函数)打印出需要了解的调试信息。如果仔细留意的话可以发现在嵌入式系统的文件系统目录下通常会有proc目录,在该目录下可以通过cat interrupt去了解ARM嵌入式系统中ARM处理器中断的情况,通过cat devices可以了解device设备的状况。那么设备的运行状态是不是也可以通过proc来了解呢?答案是肯定的。因为proc也是一种Linux下用得比较多的用户态与内核态数据交换的方式,内核的很多数据都是通过这种方式给用户的,内核的很多参数也可以通过这种方式来让用户方便设置的。除了sysctl出口到/proc下的参数,proc提供的大部分内核参数是只读的。实际上,很多应用严重地依赖于proc,因此它几乎是必不可少的组件。那么如何来使用proc呢?首先一定要包含
procfs的头文件,如#include ,其次利用procfs提供的如下API函数。
1)struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode, struct proc_dir_entry *parent)
该函数用于创建一个正常的proc条目,参数name给出了要建立proc条目的名称,参数mode给出了建立的该proc条目的访问权限,参数parent指定建立的proc条目所在的目录。如果要在/proc下建立proc条目,parent应当为NULL,否则它应当为proc_mkdir。返回struct proc_dir_entry结构的指针。
2)extern void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
该函数用于删除上面函数创建的proc条目,参数name给出要删除的proc条目的名称,参数parent指定建立的proc条目所在的目录。
3)struct proc_dir_entry *proc_mkdir(const char * name, struct proc_dir _entry *parent)
该函数用于创建一个proc目录,参数name指定要创建的proc目录的名称,参数parent为该proc目录所在的目录。
4)extern struct proc_dir_entry *proc_mkdir_mode(const char *name, mode _t mode, struct- proc_dir_entry *parent)
该函数用于以一定的模式创建proc目录,参数name指定要创建的proc目录的名称,参数mode给出了建立的该proc目录的访问权限,参数parent为该proc目录所在的目录。
5)struct proc_dir_entry *proc_symlink(const char * name,struct proc_ dir_entry * parent, const char * dest)
该函数用于建立一个proc条目的符号链接,参数name给出要建立的符号链接proc条目的名称,参数parent指定符号链接所在的目录,参数dest指定链接到的proc条目名称。
6)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)
该函数用于建立一个规则的只读proc条目,参数name给出要建立proc条目的名称,参数mode给出了建立该proc条目的访问权限,参数base指定建立proc条目所在的目录,参数read_proc给出读取该proc条目的操作函数,参数data为该proc条目的专用数据,它将保存在该proc条目对应的struct file结构的private_data字段中。
7)struct proc_dir_entry *create_proc_info_entry(const char *name,mode_t mode, struct proc_dir_entry *base, get_info_t *get_info)
该函数用于创建一个info型的proc条目,参数name给出了要建立proc条目的名称,参数mode给出了建立该proc条目的访问权限,参数base指定建立proc条目所在的目录,参数get_info指定该proc条目的get_info操作函数。实际上get_info等同于read_proc,如果proc条目没有定义read_proc,对该proc条目的read操作将使用get_info取代,因此它在功能上非常类似于函数create_proc_read_entry。
8)struct proc_dir_entry *proc_net_create(const char *name, mode_t mode, get_info_t *get_info)
该函数用于在/proc/net目录下创建一个proc条目,参数name给出了要建立proc条目的名称,参数mode给出了建立该proc条目的访问权限,参数get_info指定该proc条目的get_info操作函数。
9)struct proc_dir_entry *proc_net_fops_create(const char *name, mode_t mode, struct file_operations *fops)
该函数也用于在/proc/net下创建proc条目,但是它也同时指定了对该proc条目的文件操作函数。
10)void proc_net_remove(const char *name)
该函数用于删除前面两个函数在/proc/net目录下创建的proc条目。参数name指定要删除的proc名称。
除了上述这些函数,值得一提的是结构struct proc_dir_entry,为了创建可读可写的proc条目并指定该proc条目的写操作函数,必须设置上面那些创建proc条目的函数返回指针指向的struct proc_dir_entry结构的write_proc字段,并指定该proc条目的访问权限有写权限。
读者可以通过cat和echo等文件操作函数来查看和设置这些proc文件。下面就在上面的mydriver.c里面增加一个可读的proc接口功能,来获取设备的运行状态。
注意要先在头文件引用部分添加#include ,
接着在mydriver_init(void)里面添加如下一句语句:
create_proc_read_entry("mydriver", 0, |
remove_proc_entry("mydriver", NULL); |
当然最重要的还是要定读取proc时的操作函数mydriver_stats,具体定义如下:
static int mydriver_stats(char *buf, char **start, off_t offset, p += sprintf(p, "mydriver TX stats: \n"); len = p - buf; |