建设通同类网站,微信工作平台开发,浦口区网站建设经验丰富,问卷调查网站建设前言
内核驱动#xff1a;运行在内核态的动态模块#xff0c;遵循内核模块框架接口#xff0c;更倾向于插件。 应用程序#xff1a;运行在用户态的进程。 应用程序与内核驱动交互通过既定接口#xff0c;内核态和用户态访问依然遵循内核既定接口。
环境搭建
系统#…前言
内核驱动运行在内核态的动态模块遵循内核模块框架接口更倾向于插件。 应用程序运行在用户态的进程。 应用程序与内核驱动交互通过既定接口内核态和用户态访问依然遵循内核既定接口。
环境搭建
系统openEuler-20.03-LTS-SP3
yum install gcc kernel-devel编写源码
char_module.c
#include linux/module.h
#include linux/init.h
#include linux/fs.h
#include asm/uaccess.h
#include asm/device.h //下面这三个头文件是由于动态创建需要加的
#include linux/device.h
#include linux/cdev.hMODULE_LICENSE(GPL);#define DEVICE_NAME char_module
#define BUF_SIZE 32static struct class *cdev_class;
dev_t dev_num 0; // 这里是动态分配设备号和动态创建设备结点需要用到的
struct cdev dev_c;static char context_buf[BUF_SIZE]{this a test context buffer\0};static ssize_t read(struct file *, char *, size_t, loff_t *);
static ssize_t write(struct file *, const char *, size_t, loff_t *);
static int open(struct inode *, struct file *);
static int release(struct inode *, struct file *);// 初始化字符设备驱动的 file_operations 结构体
struct file_operations fops {.read read,.write write,.open open,.release release
};static int __init demo_init(void)
{int ret, err;printk(KERN_INFO %s: %s, DEVICE_NAME , __func__);// 注册设备驱动ret alloc_chrdev_region(dev_num, 0, 1, DEVICE_NAME); // 动态分配设备号if (ret){printk(demo_init register failure\n);unregister_chrdev_region(dev_num, 1);return ret;}printk(demo_init register success\n);// 初始化设备操作cdev_init(dev_c, fops);err cdev_add(dev_c, dev_num, 1);if (err){printk(KERN_NOTICE error %d adding cdev\n, err);unregister_chrdev_region(dev_num, 1);return err;}// 动态创建设备结点cdev_class class_create(THIS_MODULE, DEVICE_NAME); if (IS_ERR(cdev_class)){printk(ERR:cannot create a cdev_class\n);unregister_chrdev_region(dev_num, 1);return -1;}device_create(cdev_class, NULL, dev_num, 0, DEVICE_NAME);return ret;
}static void __exit demo_exit(void)
{printk(KERN_INFO %s: %s, DEVICE_NAME , __func__);// 注销设备驱动device_destroy(cdev_class, dev_num);class_destroy(cdev_class);unregister_chrdev_region(dev_num, 1);
}static ssize_t read(struct file *filp, char *buf, size_t len, loff_t *off)
{// 内核空间到用户空间copyprintk(KERN_INFO %s: %s, DEVICE_NAME , __func__);if (raw_copy_to_user(buf, context_buf, sizeof(context_buf))){return -EFAULT;}printk(KERN_INFO user space: %pF, buf);printk(KERN_INFO read: %pF; size: %ld; data: %s, context_buf, sizeof(context_buf), context_buf);return BUF_SIZE;
}static ssize_t write (struct file *filp, const char __user *buf, size_t len, loff_t *off)
{// 用户空间到内核空间copyprintk(KERN_INFO %s: %s, DEVICE_NAME , __func__);if (raw_copy_from_user(context_buf, buf, sizeof(context_buf))){return -EFAULT;}printk(KERN_INFO user space: %pF, buf);printk(KERN_INFO write: %pF; size: %ld; data: %s, context_buf, sizeof(context_buf), context_buf);return BUF_SIZE;
}static int open(struct inode *inodp, struct file *filp)
{printk(KERN_INFO %s: %s, DEVICE_NAME , __func__);return 0;
}static int release(struct inode *inodp, struct file *filp)
{printk(KERN_INFO %s: %s, DEVICE_NAME, __func__);return 0;
}module_init(demo_init);
module_exit(demo_exit);Makefile
ifneq ($(KERNELRELEASE),)
obj-m : char_module.oelse
PWD : $(shell pwd)
KVER : $(shell uname -r)
KDIR : /lib/modules/$(KVER)/build
all:$(MAKE) -C $(KDIR) M$(PWD) modules modules_install
clean:rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions modules.* Module.*
endifapp.c
#include stdio.h
#include fcntl.h
#include unistd.h
#include string.h#define CHAR_DEV_NAME /dev/char_moduleint main()
{int ret;int fd;char buf[32];fd open(CHAR_DEV_NAME, O_RDWR | O_NDELAY);if(fd 0){printf(open failed!\n);return -1;}int size read(fd, buf, 32);printf(read size: %d;\nbuffer:[%s]\n, size, buf);char *write_buf use a application wirte to driver buffer;int w_size write(fd, write_buf, strlen(write_buf));printf(write size: %d;\nbuffer:[%s]\n, w_size, write_buf);close(fd);return 0;
}构建并测试
驱动构建make insmod char_module.ko驱动信息确认 应用程序构建gcc app.c -o app
./app应用程序运行结果 查看驱动日志dmesg