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");