1、proc系统是一个虚拟的系统机器在一启动的时候就已经挂在上了,其原理我们不在分析。之后我们只管用proc系统就ok了。
内核提供了一些api来操作proc系统。这里主要就是创建目录proc_mkdir ,创建文件proc_create 和create_proc_entry,删除remove_proc_entry
2、proc_create 和create_proc_entry 都说有区别实质是一样的。区别在于proc_create 参数传入了file_operations *proc_fops,file_openrationes 结构是对文件的操作(不懂的可以查这里不做解释)其实内部也是一个指向pde->proc_fops = proc_fops; pde就是proc_create 和 create_proc_entry的返回值。如果我们用create_proc_entry可以后续自己给赋值。个人感觉不要太纠结这个。就是内核给你了不同的封装。实现的结果是一样的。不过人们现在都用proc_create,那么咱们也用这样显得高大上。
3、说完上面的创建了我们来看怎们对proc文件进行读写操作。
说道打开读写操作就用到了我们上面说的那个file_operations结构了。这里对其中的成员不做过多的解释只说我们用到的。结构及赋值如下
static const struct file_operations whitelist_proc_fops = { .owner = THIS_MODULE, .open = whitelist_proc_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release, .write = cciss_proc_write, };
4、文件的读其实就是用户态从内核态获取数据,因为我们的proc系统是内存的系统,就是所有的数据都在内存了存着,无论你是用链表还是数组,当用户调用读的时候我们就会copy_to_user 我们的数据。当用户写的时候我们就会copy_from_user 到我们的内核的数组或者链表存储。
5、咱们自己维护一套内存的系统管理很麻烦,尤其是多个page的读的时候,那么内核自己实现了一套接口是 seq_file .所以我们就直接调用就行了。但是seq_write好像没有用好,只有seq_read。还有就是在open的时候咱们可以给proc文件初始化内容,说白了就是在分配的内存中提前写点东西。
6、到此写完,总结一点咱们用proc文件其实就是操作一块内存,用户写的数据你写到你定义的内存,用户读你就从你内存中拷贝给用户。其实就这么简单。proc一般是内核给用户显示内容。或者用户简单的写一点内容。
自己写了一个例子
#include <linux/init.h> #include <linux/module.h> #include <linux/sched.h> #include <linux/kthread.h> #include <linux/fs.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/uaccess.h>
#define PORC_ROOTDIR "security" #define PORC_WHITELIST "whitelist"
struct proc_dir_entry *security_dir = NULL; struct proc_dir_entry *security_whitelist = NULL; static char *str = NULL;
static int my_proc_show(struct seq_file *m, void *v) { //可以在open的时候写上自己的内容就是在初始化内存的东西因为我用了seq所以建议都用他封装好的seq_printf
seq_printf(s, "11111111\n"); return 0; } static int whitelist_proc_open(struct inode *inode, struct file *file) { return single_open(file, my_proc_show, NULL); }
static ssize_t cciss_proc_write(struct file *file, const char __user *buf, size_t length, loff_t *ppos) { int err; char *buffer;
if (!buf || length > PAGE_SIZE - 1) return -EINVAL;
buffer = (char *)__get_free_page(GFP_KERNEL); if (!buffer) return -ENOMEM;
err = -EFAULT; if (copy_from_user(buffer, buf, length)) goto out; buffer[length] = '\0'; printk("%s\n",buffer); out: free_page((unsigned long)buffer); }
static int helloworld_exit(void) { remove_proc_entry(PORC_ROOTDIR, security_dir); remove_proc_entry(PORC_WHITELIST, security_dir); printk(KERN_INFO "see you.\n"); return 0; }
module_init(helloworld_init); module_exit(helloworld_exit); MODULE_LICENSE("GPL");