绘制此图,主要展现字符设备驱动框架核心init和open流程。
1. 确定主设备号
2. 构造一个file_operations结构体
static const struct file_operations myled_fops = {
.owner = THIS_MODULE,
.read = myled_read,
.write = myled_write,
.open = myled_open,
.release = myled_release,
};
3. 注册驱动:register_chrdev(主设备号,名,&file_operations)
register_chrdev(0, DEVICE_NAME, &myled_fops);
第一个参数是0表示动态分配主设备号。
4,生成设备结点
pdev->device = device_create(pdev->class, NULL, pdev->devno, NULL, "%s", DEVICE_NAME);
4. 入口函数
static int __init myled_init(void)
{
int ret = -1;
g_myled_struct.major = register_chrdev(0, DEVICE_NAME, &myled_fops);
if (g_myled_struct.major <= 0) {
pr_err("register_chrdev failed\n");
return ret;
}
g_myled_struct.led_class = class_create(THIS_MODULE, DEVICE_NAME);
if (IS_ERR(g_myled_struct.led_class)) {
printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
ret = PTR_ERR(g_myled_struct.led_class);
goto unregister_chrdev;
}
return platform_driver_register(&myled_driver);
unregister_chrdev:
unregister_chrdev(g_myled_struct.major, DEVICE_NAME);
return ret;
}
module_init(myled_init);
5. 出口函数
static void __exit myled_exit(void)
{
platform_driver_unregister(&myled_driver);
class_destroy(g_myled_struct.led_class);
unregister_chrdev(g_myled_struct.major, DEVICE_NAME);
}
module_exit(myled_exit);
进程: open("/dev/myled")
......
-> swi #val 导致swi异常
......
//SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, int, mode)
->sys_open()
->do_sys_open()
......
->init_special_inode()
inode->i_fop = &def_chr_fops;
inode->i_rdev = rdev;
->chrdev_open // 根据主设备号找到之前注册的file_operations
// 根据所打开的文件的属性,找到file_operations
filp->f_op = fops_get(p->ops);
filp->f_op->open(inode,filp); // 执行里面的open函数
->myled_open()
可在myled_open() 增加WARN_ON(1),通过dump信息查看调用流程:
[ 1618.842714] (0)[207:ledtest]------------[ cut here ]------------
[ 1618.846418] (0)[207:ledtest]WARNING: CPU: 0 PID: 207 at /home/book/c-example/4-system/linux/qemu-driver/myled/myled.c:59 myled_open+0x1c/0x58 [myled]
[ 1618.852160] Modules linked in: myled(O)
[ 1618.856417] (0)[207:ledtest]CPU: 0 PID: 207 Comm: ledtest Tainted: G W O 4.9.88-g8f6c88de-dirty #3
[ 1618.860494] (0)[207:ledtest]Hardware name: Freescale i.MX6 UltraLite (Device Tree)
[ 1618.864682] (0)[207:ledtest][<8020f34c>] (unwind_backtrace) from [<8020b668>] (show_stack+0x10/0x14)
[ 1618.868791] (0)[207:ledtest][<8020b668>] (show_stack) from [<804cf970>] (dump_stack+0x78/0x8c)
[ 1618.872845] (0)[207:ledtest][<804cf970>] (dump_stack) from [<8022e684>] (__warn+0xe8/0x100)
[ 1618.876950] (0)[207:ledtest][<8022e684>] (__warn) from [<8022e74c>] (warn_slowpath_null+0x20/0x28)
[ 1618.881125] (0)[207:ledtest][<8022e74c>] (warn_slowpath_null) from [<7f0004b4>] (myled_open+0x1c/0x58 [myled])
[ 1618.885599] (0)[207:ledtest][<7f0004b4>] (myled_open [myled]) from [<80309b08>] (chrdev_open+0xa4/0x188)
[ 1618.889863] (0)[207:ledtest][<80309b08>] (chrdev_open) from [<80303234>] (do_dentry_open.constprop.3+0x1e4/0x30c)
[ 1618.893996] (0)[207:ledtest][<80303234>] (do_dentry_open.constprop.3) from [<80312ac4>] (path_openat+0x338/0xf28)
[ 1618.898314] (0)[207:ledtest][<80312ac4>] (path_openat) from [<803144bc>] (do_filp_open+0x60/0xc4)
[ 1618.902065] (0)[207:ledtest][<803144bc>] (do_filp_open) from [<80304410>] (do_sys_open+0x114/0x1c4)
[ 1618.906137] (0)[207:ledtest][<80304410>] (do_sys_open) from [<80208280>] (ret_fast_syscall+0x0/0x40)
[ 1618.912254] (0)[207:ledtest]---[ end trace 02ccad5130174f77 ]---