驱动开发之始,(二)字符设备驱动——Part3 简单的字符驱动实例
程序员文章站
2022-07-14 11:08:43
...
通过前面两章的知识汇总,我们了解字符设备驱动框架及其涉及的几个重要数据结构,为了加深理解,本章用一个简单的实例来演示字符设备驱动的开发过程,因为没有实际接硬件,并未实现对驱动进行复杂操作,在此只做一个初步认识,在后续的进阶部分,笔者再通过实际的字符驱动来进一步分析。
1.字符设备驱动 hello_module.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/kernel.h>
static int major = 88;
static int minor = 0;
static dev_t devno;
static struct cdev cdev;
static int hello_open(struct inode *inode, struct file *filep)
{
printk(KERN_ALERT "Hello lijunnan!\n");
return 0;
}
struct file_operations file_ops =
{
.open = hello_open
};
static int hello_init(void)
{
int ret;
printk(KERN_ALERT "hello_init!\n");
devno = MKDEV(major, minor);
ret = register_chrdev_region(devno, 1, "hello");
if(ret < 0)
{
printk("register chrdev region failed!\n");
return ret;
}
cdev_init(&cdev, &file_ops);
ret = cdev_add(&cdev, devno, 1);
if(ret < 0)
{
printk("cdev add failed!\n");
return ret;
}
return 0;
}
static void hello_exit(void)
{
cdev_del(&cdev);
unregister_chrdev_region(devno, 1);
printk(KERN_ALERT "See you next time!\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("LiJunnan");
a. 首先需要申请一个设备号,在此笔者通过动态分配获取一个dev_t,即register_chrdev_region()函数
b. 初始化cdev结构体,调用cdev_init(),将cdev和file_operations关联起来
c. 注册cdev结构,告诉内核该结构的信息,调用cdev_add()
d. 在file_operations结构中定义了open操作方法,通过系统调用open实现
e. 在卸载函数中需要移除字符设备,调用cdev_del(),并释放设备号unregister_chrdev_region()
2.应用程序hello_app.c
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main()
{
int fd = 0;
fd = open("/dev/hello_module", O_RDWR);
if(fd < 0)
{
printf("open failed!\n");
return -1;
}
printf("hello lijunnan\n");
close(fd);
return 0;
}
首先,我们安装内核模块,insmod hello_module.ko,在/proc/devices文件可以看到安装的内核模块
在系统与设备通信前,需要创建一个设备文件,这个文件存放在/dev目录下,系统默认情况下就已经成立了很多设备文件,我们也可以手动新建一些设备文件,使用mknod命令,格式如下:
mknod DEVNAME 设备类型 MAJOR MINOR
注意:
1.需要使用超级用户权限创建设备文件
2.设备文件的主设备号需要与内核模块设备号一致
3.修改新建设备文件的读写权限
最后,在执行./hello
下一篇: 2020-09-25