字符驱动
参考: https://www.bilibili.com/video/av51099369?p=10
内核驱动
硬件 -》 驱动 -》 内核子系统(进程管理、内存管理、文件系统、设备控制、网络) -》系统调用
驱动的类型
- 字符设备驱动
- 块设备驱动
- 网络设备驱动
驱动的静态加载和动态加载
动态加载M选项,生成ko文件
区别
- 编译选项(编写进内核还是编写为驱动)
- 存在位置(驱动代码在内核镜像还是文件系统内)
- 加载时机
优势
- 热插拔
- 驱动调试
- 开机优化
字符设备驱动
相关概念
设备号
**dev_t **
实质是unsigned int 32位整数,高12位为主设备号(区分不同类别的设备)、低20位为次设备号(同类设备的多个设备)。
注册设备号int register_chrdev_region(dev_t from, unsigned count, const char *name)
设备信息的描述
struct cdev{
struct kobject kobj;
struct module *owner;
const struct file_operations *ops;
struct list_head list;
dev_t dev;
unsigned count; //已支持的设备
}
设备行为的描述
struct file_operations{
struct module *owner;
...
ssize_t (*read)(struct file*, char __user*, size_t, loff_t *);
ssize_t (*write)(struct file*, const char __user*, size_t, loff_t *);
int (*open)(struct inode*, struct file*);
int (*release)(struct inode *, struct file*);
...
}
相关注册函数
int cdev_add(struct cdev *p, dev_t dev, unsigned count)
方便内核统一管理
内核驱动源码
4次关联,5层结构:自定义函数(设备行为,如read、write、open) -> file_operations -> struct cdev -> 设备号 -> 设备文件(/dev/..)
int charDrvInit(void)
{
devNum = MKDEV(reg_major, reg_minor);
if( OK == register_chrdev_region(devNum, subDevNum, "testchar")){
printk(KERN_EMERG"register_chrdev_region ok\r\n");
}
else{
printk(KERN_EMERG"register_chrdev_region error ok\r\n");
return ERROR;
}
gDev = kzalloc(sizeof(struct cdev), GFP_KERNEL);
gFile = kzalloc(sizeof(struct file_operations), GFP_KERNEL);
gFile->open = testOpen;
gFile->read = testRead;
gFile->write = testWrite;
gFile->owner = THIS_MODULE;
cdev_init( gDev, gFile);
cdev_add( gDev, devNum, 3);
return 0;
}
void __exit charDevExit( void )
{
cdev_del(gDev);
unregister_chrdev_region( devNum, subDevNum);
return;
}
module_init( charDrvInit );
module_exit( charDevExit );
MODULE_LICENSE( "GPL" );
内核编译系统原理
make menuconfig
图形化配置,实质是遍历并显示所有目录下的kconfig文件。
tristate: 3种选择 y(编译进内核)/n/m
config MINI210_BUTTONS
tristate
depends on CPU_55PV210
default y
help
this is button ...
ID值:CONFIG_MINI210_BUTTONS = y/n/m
.config: 最终配置
make实质
遍历所有目录下的makefile,并且按照makefile的内容编译相关代码
onj-$(CONFIG_MINI210_BUTTONS) += mini210_button.o
obj-y: 编译进内核
obj-m: 编译为驱动
操作
- 在linux-2.6.32.2/drivers/char/Kconfig为charDev添加一个config条目。比如TEST_CHAR
- 修改linux-2.6.32.2/drivers/char/Makefile, 添加代码
obj-$(CONFIG_TEST_CHAR) += charDev.o - 把charDev.c拷贝到linux-2.6.32.2/drivers/char/下
- make munuconfig, 选中CONFIG_TEST_CHAR项目,设为M或者Y
- 重新编译

浙公网安备 33010602011771号