用户空间与内核空间通讯接口之procfs
来源:互联网 发布:墨西哥毒贩知乎 编辑:程序博客网 时间:2024/05/27 00:27
概述
procfs是比较老的一种用户态与内核态的数据交换方式,内核的很多数据都是通过这种方式出口给用户的,内核的很多参数也是通过这种方式来让用户方便设置的。除了sysctl出口到/proc下的参数,procfs提供的大部分内核参数是只读的。
创建实例
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结构的指针。
删除实例
void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
该函数用于删除上面函数创建的proc条目,参数name给出要删除的proc条目的名称,参数parent指定建立的proc条目所在的目录。
创建proc 目录
struct proc_dir_entry *proc_mkdir(const char * name, struct proc_dir_entry *parent)
该函数用于创建一个proc目录,参数name指定要创建的proc目录的名称,参数parent为该proc目录所在的目录。
可以通过cat和echo等文件操作函数来查看和设置这些proc文件。特别需要指出,bigprocfile是一个大文件(超过一个内存页),对于这种大文件,procfs有一些限制,因为它提供的缓存,只有一个页,因此必须特别小心,并对超过页的部分做特别的考虑,处理起来比较复杂并且很容易出错,所有procfs并不适合于大数据量的输入输出。
实例
Makefile
obj-m := test_procfs.otest_procfs-objs := procfs.oKERNELDIR = /lib/modules/$(shell uname -r)/build#KERNELDIR = /lib/modules/2.6.32-220.el6.x86_64/buildPWD := $(shell pwd)default: $(MAKE) -C $(KERNELDIR) M=$(PWD) modulesclean: $(MAKE) -C $(KERNELDIR) M=$(PWD) clean
#include <linux/kernel.h>#include <linux/module.h>#include <linux/proc_fs.h>#include <linux/sched.h>#include <linux/types.h>#include <asm/uaccess.h>#define STR_MAX_SIZE 255static int int_var;static char string_var[256];static char big_buffer[65536];static int big_buffer_len = 0;static struct proc_dir_entry * myprocroot;static int first_write_flag = 1;int int_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data){ count = sprintf(page, "%d", *(int *)data); printk("read int %d",count); return count;}int int_write_proc(struct file *file, const char __user *buffer,unsigned long count, void *data){ unsigned int c = 0, len = 0, val, sum = 0; int * temp = (int *)data; printk("int write start\r\n"); while (count) { if (get_user(c, buffer)) //从用户空间中得到数据 return -EFAULT; len++; buffer++; count--; if (c == 10 || c == 0) break; val = c - '0'; if (val > 9) return -EINVAL; sum *= 10; sum += val; } * temp = sum; printk("int write *tmp = %d", *temp); return len;}int string_read_proc(char *page, char **start, off_t off,int count, int *eof, void *data){ count = sprintf(page, "%s", (char *)data); printk("string_read_proc %s %d",data,count); return count;}int string_write_proc(struct file *file, const char __user *buffer, unsigned long count, void *data){ printk("string_write_proc start\r\n"); if (count > STR_MAX_SIZE) { count = 255; } copy_from_user(data, buffer, count); printk("string_write_proc %s", data); return count;}int bigfile_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data){ if (off > big_buffer_len) { * eof = 1; return 0; } if (count > PAGE_SIZE) { count = PAGE_SIZE; } if (big_buffer_len - off < count) { count = big_buffer_len - off; } memcpy(page, data, count); *start = page; return count;}int bigfile_write_proc(struct file *file, const char __user *buffer, unsigned long count, void *data){ char * p = (char *)data; if (first_write_flag) { big_buffer_len = 0; first_write_flag = 0; } if (65536 - big_buffer_len < count) { count = 65536 - big_buffer_len; first_write_flag = 1; } copy_from_user(p + big_buffer_len, buffer, count); big_buffer_len += count; return count;}static int __init procfs_exam_init(void){ #ifdef CONFIG_PROC_FS struct proc_dir_entry * entry; myprocroot = proc_mkdir("myproctest", NULL); entry = create_proc_entry("aint", 0644, myprocroot); if (entry) { entry->data = &int_var; entry->read_proc = &int_read_proc; entry->write_proc = &int_write_proc; } entry = create_proc_entry("astring", 0644, myprocroot); if (entry) { entry->data = &string_var; entry->read_proc = &string_read_proc; entry->write_proc = &string_write_proc; } entry = create_proc_entry("bigprocfile", 0644, myprocroot); if (entry) { entry->data = &big_buffer; entry->read_proc = &bigfile_read_proc; entry->write_proc = &bigfile_write_proc; } #else printk("This module requires the kernel to support procfs,\n"); #endif return 0;}static void __exit procfs_exam_exit(void){ #ifdef CONFIG_PROC_FS remove_proc_entry("aint", myprocroot); remove_proc_entry("astring", myprocroot); remove_proc_entry("bigprocfile", myprocroot); remove_proc_entry("myproctest", NULL); #endif}module_init(procfs_exam_init);module_exit(procfs_exam_exit);MODULE_LICENSE("GPL");
加载
insmod test_procfs.ko
测试
[root@localhost lytest]# cd -
/proc/myproctest
[root@localhost myproctest]# ls
aint astring bigprocfile
[root@localhost myproctest]# echo 1 > aint
[root@localhost myproctest]# cat aint
1
[root@localhost myproctest]# echo “abc” >astring
[root@localhost myproctest]# cat astring
abc
[root@localhost myproctest]# dmesg
卸载
rmmod test_procfs.ko
- 用户空间与内核空间通讯接口之procfs
- 用户空间与内核空间通讯接口之sysctl
- 内核与用户空间的接口procfs, sysctl, ioctl,netlink
- 用户与内核空间数据交换的方式(2)-procfs
- 用户与内核空间数据交换的方式(2)-procfs
- 用户与内核空间数据交换的方式(2)-procfs
- 用户空间与内核空间数据交换的方式(2)------procfs
- 用户空间与内核空间数据交换的方式(2)------procfs
- 用户空间与内核空间数据交换的方式(2)------procfs
- 用户空间与内核空间数据交换的方式(2)------procfs
- 用户空间与内核空间数据交换的方式(2)------procfs
- 用户空间与内核空间数据交换的方式(2)------procfs
- 用户空间和内核空间通讯之【Netlink 上】
- 用户空间和内核空间通讯之【Netlink 中】
- 用户空间和内核空间通讯之【Netlink 下】
- 用户空间和内核空间通讯之【proc文件系统】
- 用户空间和内核空间通讯之【系统调用】
- 用户空间和内核空间通讯之【proc文件系统】
- sql增删改查
- hdu 2037 今年暑假不AC (贪心)
- Codeforces Round #328 (Div. 2)(A B C D)
- Eclipse中的快捷键
- IOS 通知机制
- 用户空间与内核空间通讯接口之procfs
- hdu5523 Game
- HDOJ 5523 Game
- Eclipse 下C++ 多线程 pthread.h1
- php操作mongodb教程
- iOS自定义转场动画(4)——自定义模态跳转之dismiss与手势驱动
- js获取所有复选框中的值
- HDU 2076 夹角有多大(水~)
- android之Volley框架的使用(1)