内核空间与用户空间的通信
在Linux中编程,特别是涉及内核驱动时,应用层程序经常需要和内核层驱动进行数据交换,比如内核检测到某个状态需要通知应用程序,或者应用程序的某个状态发生改变需用通知内核等等。
proc简介
/proc 文件系统是一种虚拟文件系统,它可以实现linux内核空间和用户空间的通信。与普通文件不同,这里的虚拟文件的内容都是动态创建的。
如果只是控制内核中的参数而不是传输较多数据的话,用“/proc”是很合适的。
proc实例实现的功能
读取路由器的工作模式到无线驱动中,根据当前的工作模式,对不同的报文做一些特殊处理。路由器当前的工作模式保存在配置文件中,通过脚本来读取配置文件,并将该值写入对应的proc文件即可。
内核空间程序
// 运行下面用户态的脚本后,路由器的工作模式就被写入msg中,内核空间直接使用msg的值即可
#include <linux/init.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/stat.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
MODULE_AUTHOR("yahai.zhang");
MODULE_DESCRIPTION("procfs get_operation_mode module.");
MODULE_LICENSE("GPL");
#define PROCNAME "operation_mode"
struct proc_dir_entry *proc_entry = NULL;
char msg[16]={0};
static int operation_file_read(struct file * file, char *data, size_t len, loff_t *off)
{
if(*off > 0)
return 0;
if(copy_to_user(data, msg, strlen(msg)))
return -EFAULT;
*off += strlen(msg);
return strlen(msg);
}
static int operation_file_write(struct file *file, const char *data, size_t len, loff_t *off)
{
memset(msg, 0, sizeof(char)*16);
if(copy_from_user(msg, (void*)data, len))
return -EFAULT;
return len;
}
static struct file_operations operationmode_ops = {
.read = operation_file_read,
.write = operation_file_write,
};
static int __init procMode_init(void)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
if(proc_entry = create_proc_entry(PROCNAME, 0666, NULL))
proc_entry->proc_fops = &operationmode_ops;
else
#else
if(!(proc_entry = proc_create(PROCNAME, 0666, NULL, &operationmode_ops)))
#endif
printk("!! FAIL to create %s PROC !!\n", PROCNAME);
return 0;
}
static void __exit procMode_exit(void)
{
remove_proc_entry(PROCNAME,NULL);
}
module_init(procMode_init);
module_exit(procMode_exit);
内核空间程序
# shell脚本,读取配置文件中路由器当前工作模式,并写数据到相应的proc文件
set_mode_to_kernel() {
mode=`uci get system.system.mode`
if [ "$mode" == "AP" ]; then
echo -e "ap\c" > /proc/operation_mode
else
echo -e "repeater\c" > /proc/operation_mode
fi
}
另外一种内核与用户空间通信方式方式是使用内核设备的读写或IOCTL来实现,以后再介绍。