驱动模块中的read,write(纯知识点的代码编写,非正式驱动代码)
struct cdev hello_cdev;
dev_t hello_devno; //dev_t = unsigned int
int hello_major = 250; //Documentation/devices.txt
int hello_minor = 0;
#define KBUFSIZE 50
char kbuf[KBUFSIZE]; //表示内核下的buf数组
int hello_open(struct inode *pinode, struct file *pfile)
{
//简单的打印,表示open函数的成功引用
printk(KERN_INFO "hello open! \n");
return 0;
}
int hello_release(struct inode *pinode, struct file *pfile)
{
//便是模块的成功释放
printk(KERN_INFO "hello release! \n");
return 0;
}
//用户层read调用会访问到此函数
ssize_t hello_read(struct file *pfile,
char __user *ubuf, size_t count, loff_t *ploff)
{
//如果写入的字节数大于内核中的内存字节数(目前给定的是50)则只取50
if (count > strlen(kbuf))
count = strlen(kbuf);
if (count < 0 )
return -EINVAL;
//将内核数据传递给应用 copy_to_user(to, from, size)
//返回值为0表示成功
if (copy_to_user(ubuf, kbuf, count)) {
printk(KERN_ERR "copy_to_user failed! \n");
return -EFAULT;
}
printk(KERN_INFO "KERNNEL: hello read! \n");
return count;
}
ssize_t hello_write(struct file *pfile,
const char __user *ubuf, size_t count, loff_t *ploff)
{
if (count > sizeof (kbuf))
count = sizeof (kbuf);
if (count < 0 )
return -EINVAL;
if (copy_from_user(kbuf, ubuf, count)) {
printk(KERN_ERR "copy_to_user failed! \n");
return -EFAULT;
}
printk(KERN_INFO "KERNNEL: kbuf = %s \n",
kbuf);
return count;
}
//用户调用
struct file_operations hello_ops = {
.owner = THIS_MODULE,
.open = hello_open,
.release = hello_release,
.read = hello_read,
.write = hello_write,
};
int hello_init(void)
{
//初始化字符设备流程
// 1. 组装设备号
// 2. 注册号
// 3. 初始化字符设备
// 4. 注册字符设备
int ret;
hello_devno = MKDEV(hello_major, hello_minor);//hello_major << 20 | hello_minor;
ret = register_chrdev_region(hello_devno, 1, "hello_char"); //cat /proc/devices hello_char
if (ret < 0) {
//诺上面注册号不成立则 动态分配字符设备
ret = alloc_chrdev_region(&hello_devno, 0, 1, "hello_char");
if (ret < 0) {
printk(KERN_ERR "register_chrdev_region failed! \n");
return ret;
}
}
//初始化字符设备对象
cdev_init(&hello_cdev, &hello_ops);
hello_cdev.owner = THIS_MODULE;
//将字符设备对象添加进内核
ret = cdev_add(&hello_cdev, hello_devno, 1);
if (ret < 0) {
unregister_chrdev_region(hello_devno, 1);
printk(KERN_ERR "cdev_add failed! \n");
return ret;
}
//给kbuf赋值
strncpy(kbuf, "kernel_data", sizeof ("kernel_data"));
printk(KERN_INFO "hello init! kbuf = %s \n", kbuf);
return 0;
}
void hello_exit(void)
{
cdev_del(&hello_cdev);
unregister_chrdev_region(hello_devno, 1);
printk(KERN_INFO "hello exit! \n");
}
module_init(hello_init); //加载模块后自动调用hello_init
module_exit(hello_exit); //释放模块
通过内核打印的日志中我们看出内核被加载并打印内核初始值为“kernel_data”(上面代码中复制即kernel _data)
执行write之后再read变成了hello hello,说明内核值被改变了(只是因为在write中给内核写入了hello hello)