linux字符设备框架

一,字符设备框架

此字符框架图,主要展现字符设备驱动框架核心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);

三,user open()访问驱动程序open()流程

进程: 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 ]---

  • 17
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bug猎人

非常非常非常感谢您的鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值