目录
sysfs 与 proc 相比有很多优点,最重要的莫过于设计上的清晰。一个 proc 虚拟文件可能有内部格式,如 /proc/scsi/scsi
,它是可读可写的,(其文件权限被错误地标记为了 0444 !,这是内核的一个BUG),并且读写格式不一样,代表不同的操作,应用程序中读到了这个文件的内容一般还需要进行字符串解析,而在写入时需要先用字符串格式化按指定的格式写入字符串进行操作;相比而言, sysfs 的设计原则是一个属性文件只做一件事情, sysfs 属性文件一般只有一个值,直接读取或写入。整个 /proc/scsi
目录在2.6内核中已被标记为过时(LEGACY),它的功能已经被相应的 /sys 属性文件所完全取代。新设计的内核机制应该尽量使用 sysfs 机制,而将 proc 保留给纯净的“进程文件系统”。
proc文件系统
调用接口如下。
创建目录
struct proc_dir_entry *proc_mkdir(const char *name,
struct proc_dir_entry *parent);
创建proc文件
struct proc_dir_entry *create_proc_entry( const char *name, mode_t mode,
struct proc_dir_entry *parent );
create_proc_entry函数用于创建一个一般的proc文件,其中name是文件名,比如“hello”,mode是文件模式,parent是要创建的proc文件的父目录(若parent = NULL则创建在/proc目录下)。create_proc_entry 的返回值是一个 proc_dir_entry 指针(或者为 NULL,说明在 create 时发生了错误)。然后就可以使用这个返回的指针来配置这个虚拟文件的其他参数,例如在对该文件执行读操作时应该调用的函数。
struct proc_dir_entry {
......
const struct file_operations *proc_fops; <==文件操作结构体
struct proc_dir_entry *next, *parent, *subdir;
void *data;
read_proc_t *read_proc; <==读回调
write_proc_t *write_proc; <==写回调
......
};
删除proc文件/目录
void remove_dir_entry(const char *name, struct proc_dir_entry *parent);
要从 /proc 中删除一个文件,可以使用 remove_proc_entry 函数。要使用这个函数,我们需要提供文件名字符串,以及这个文件在 /proc 文件系统中的位置(parent)。
proc文件读回调函数
static int (*proc_read)(char *page, char **start, off_t off, int count, int *eof, void *data);
我们可以使用 read_proc 函数从一个 /proc 项中读取数据(从内核空间到用户空间)。这个函数的原型如下:
int mod_read( char *page, char **start, off_t off,
int count, int *eof, void *data );
page参数是这些数据写入到的位置,其中count定义了可以写入的最大字符数。在返回多页数据(通常一页是4KB)时,我们需要使用start和off参数。当所有数据全部写入之后,就需要设置eof(文件结束参数)。与write类似,data表示的也是私有数据。此处提供的page缓存区在内核空间。因此我们可以直接写入,而不用调用copy_to_user。
proc文件写回调函数
static int proc_write_foobar(struct file *file, const char *buffer, unsigned long count, void *data);
proc文件实际上是一个叫做proc_dir_entry的struct(定义在proc_fs.h),该struct中有int read_proc和int write_proc两个元素,要实现proc的文件的读写就要给这两个元素赋值。但这里不是简单地将一个整数赋值过去就行了,需要实现两个回调函数。在用户或应用程序访问该proc文件时,就会调用这个函数,实现这个函数时只需将想要让用户看到的内容放入page即可。在用户或应用程序试图写入该proc文件时,就会调用这个函数,实现这个函数时需要接收用户写入的数据(buff参数)。
我们可以使用write_proc函数向/proc中写入一项。这个函数的原型如下:
int mod_write( struct file *filp, const char __user *buff, unsigned long len, void *data ); |
---|
filp参数实际上是一个打开文件结构(我们可以忽略这个参数)。buf