编写的驱动用户空间和内核空间数据交互
代码:006_kernel_user_data.c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/kdev_t.h>
#include <linux/device.h>
#include <linux/uaccess.h>
struct device_data{
dev_t dev_no; // 设备号
struct cdev cdev_test; // 字符设备结构体
struct class *class_test; // 类
struct device *device_test; // 设备
char kbuf[32];
};
struct device_data dev_data;
static int test_open(struct inode *inode,struct file *file)
{
// 打开驱动时,配置私有数据
file->private_data = &dev_data;
printk("open\n");
return 0;
}
static ssize_t test_read(struct file *file,char __user *buf, size_t size,loff_t *off){
//拿到私有数据
struct device_data *priv_data = (struct device_data *)file->private_data;
if(copy_to_user(buf,priv_data->kbuf , strlen(priv_data->kbuf))!=0){
printk("copy_to_user failed\n");
return -1;
}
printk("read\n");
return 0;
}
static ssize_t test_write(struct file *file,const char __user *buf, size_t size,loff_t *off){
// 拿到私有数据
struct device_data *priv_data = (struct device_data *)file->private_data;
if(size > sizeof(priv_data->kbuf)){
printk("data too large\n");
return -ENOSPC;
}
if(copy_from_user(priv_data->kbuf, buf, size)!=0){
printk("copy_from_user failed\n");
return -EFAULT;
}
priv_data->kbuf[size - 1] = '\0'; // 确保字符串终止
*off += size;
printk("write\n");
return size;
}
static int test_release(struct inode *inode,struct file *file)
{
printk("release\n");
return 0;
}
struct file_operations fops = {
.owner = THIS_MODULE,
.open = test_open,
.read = test_read,
.write = test_write,
.release = test_release,
};
//设备名称
static char* name = "006_kernel_user_data";
MODULE_LICENSE("GPL");
MODULE_AUTHOR("wyl");
MODULE_DESCRIPTION("006_kernel_user_data");
static int modulecdev_init(void)
{
int ret;
ret = alloc_chrdev_region(&dev_data.dev_no, 0, 1, name);
if (ret<0) {
printk("alloc_chrdev_region failed\n");
return ret;
}
printk("major:%d, minor:%d\n", MAJOR(dev_data.dev_no), MINOR(dev_data.dev_no));
cdev_init(&dev_data.cdev_test, &fops);
cdev_add(&dev_data.cdev_test, dev_data.dev_no, 1);
dev_data.class_test = class_create(THIS_MODULE, name); //创建类
dev_data.device_test = device_create(dev_data.class_test, NULL, dev_data.dev_no, NULL, name);
return 0;
}
static void modulecdev_exit(void)
{
// 1. 先销毁设备节点
device_destroy(dev_data.class_test, dev_data.dev_no);
// 2. 销毁类 (原代码缺失此步,必须添加)
class_destroy(dev_data.class_test);
// 3. 删除字符设备
cdev_del(&dev_data.cdev_test);
// 4. 最后注销设备号
unregister_chrdev_region(dev_data.dev_no, 1);
printk("modulecdev exit\n");
}
module_init(modulecdev_init);
module_exit(modulecdev_exit);
代码:app.c
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main()
{
int fd = open("/dev/006_kernel_user_data", O_RDWR);
char rbuf[64];
char wbuf[64];
if (fd < 0)
{
printf("open error\n");
return -1;
}
printf("open success\n");
// 用户 -> 内核:写入数据到驱动
strcpy(wbuf, "hello from user space!");
write(fd, wbuf, strlen(wbuf) + 1);
printf("write to kernel: %s\n", wbuf);
// 内核 -> 用户:从驱动读取数据
memset(rbuf, 0, sizeof(rbuf));
read(fd, rbuf, sizeof(rbuf));
printf("read from kernel: %s\n", rbuf);
close(fd);
return 0;
}