新字符设备驱动中-goto对于错误的处理方法

一.  简介

本文学习Linux内核源码中的驱动对于错误的一种处理方法。使用 goto语句来处理错误。

本文以前面的驱动代码为例,即 3_newchrled工程代码为例,在此基础上进行举例说明。

二.  新的字符设备驱动框架中:goto对于错误的处理方法

3_newchrled工程中,newchrled.c文件中的函数,一般出错处理是直接 return 返回一个错误码。

如果在 Linux内核源码中搜索可以发现, 是使用了 goto语法进行的另一种处理方法。

这里以 newchrled.c文件中的入口函数为例,在此基础上使用 goto语法来处理错误:

/*驱动模块入口函数 */
static int __init newchrled_init(void)
{
    int ret = 0;
    unsigned int value = 0;
    printk("newchrled_init!\r\n");

/* 1. Led灯的IO初始化 */
    //地址映射
    IMX6ULL_CCM_CCGR1 = ioremap(CCM_CCGR1_BASE, 4);
    IMX6ULL_SW_MUX_GPIO1_IO03 = ioremap(SW_MUX_GPIO1_IO03_BASE, 4);
    IMX6ULL_SW_PAD_GPIO01_IO03 = ioremap(SW_PAD_GPIO1_IO03_BASE, 4);
    IMX6ULL_GDIR = ioremap(GPIO1_GDIR_BASE, 4);
    IMX6ULL_DR = ioremap(GPIO1_DR_BASE, 4);

.......................................................
/* 2. 注册字符设备 */
    //设备号的分配
    newchrled.major = 0;
    if(newchrled.major) //给定主设备号
    {
        newchrled.devid = MKDEV(newchrled.major, 0);
        ret = register_chrdev_region(newchrled.devid, NEWCHRLED_COUNT, NEWCHRLED);
    }
    else{ //没有给定主设备号
        ret = alloc_chrdev_region(&(newchrled.devid), 0, NEWCHRLED_COUNT, NEWCHRLED);	
        newchrled.major = MAJOR(newchrled.devid);
        newchrled.minor = MINOR(newchrled.devid);
    }
	if (ret < 0) {
		printk("register-chrdev failed!\n");
		goto fail_devid;
	}
    //初始化设备
    cdev_init(&newchrled.led_cdev, &fops);
    
    //注册设备
    ret = cdev_add(&newchrled.led_cdev, newchrled.devid, NEWCHRLED_COUNT);
    if(ret < 0)
    {
        printk("cdev_add failed!\r\n");
        goto fail_adddev;
    }

/* 3.自动创建设备节点 */
    //创建类
    newchrled.led_class = class_create(THIS_MODULE, NEWCHRLED); 
    if (IS_ERR(newchrled.led_class)) {
		ret = PTR_ERR(newchrled.led_class);
		goto fail_class;
	}   
    //创建设备
    newchrled.led_device = device_create(newchrled.led_class, NULL, newchrled.devid, NULL, NEWCHRLED);
    if (IS_ERR(newchrled.led_device)) {
		ret = PTR_ERR(newchrled.led_device);
		goto fail_dev_create;
	}  

    return 0;

fail_dev_create:
    class_destroy(newchrled.led_class);
fail_class:
    cdev_del(&newchrled.led_cdev);
fail_adddev:
    unregister_chrdev_region(newchrled.devid, NEWCHRLED_COUNT);
fail_devid:
    return ret;
}

可以看出,当出现错误的时候,直接使用 goto语句进行跳转,直接跳转到函数的末尾。

对于不同层级的错误,跳转到不同的错误项。而错误项的存放位置也是有前后顺序的,因为越是2、3、4等越深层级的错误,需要释放前面的一些资源后,才能返回。

你可能感兴趣的:(Linux驱动学习,linux,arm开发)