linux 用户态和内核态通信proc系统

    技术2023-06-13  64

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

    Processed: 0.013, SQL: 9