实现可重启的系统调用

时间:2013-12-08 15:51:53

标签: linux linux-kernel linux-device-driver

如果我有一段驱动程序代码:

down_interruptible(&semA); //success
if(down_interruptible(&semB)) { //wait
   return -ERESTARTSYS;
}
up(&semA);
up(&semB);

我已经读过,如果驱动程序代码返回-ERESTARTSYS,VFS层可能会在没有用户知道的情况下处理重新启动系统调用。但是,如何释放锁,内存等资源呢?我们应该在返回-ERESTARTSYS之前撤消它们,否则内核会神奇地处理它?<​​/ p>

for ex:上面的代码应该是什么样的?

down_interruptible(&semA); //success
if(down_interruptible(&semB)) { //wait
   up(&semA);
   return -ERESTARTSYS;
}
up(&semA);
up(&semB);

我不确定使用这样的两个信号量是正常的,但我已经提到了它以理解这个概念。 如果可能的话,请在linux内核中指出我的实际代码,处理这种情况。

1 个答案:

答案 0 :(得分:4)

当您退出某个功能时(由于信号或任何其他错误),您必须释放您已经执行的所有锁定,否则您将无法将它们带走下次。 这同样适用于任何其他临时资源,如内存。

请注意,当您使用down_interruptible时,您必须始终检查返回值,否则您将不知道您是否确实获得了锁定。


处理错误的常见模式是以相反的顺序释放资源并使用一系列goto语句,这允许您组合正常和错误退出路径,从而减少错误:

int my_function(...)
{
    char *temp_buf;
    int err;

    err = -ENOMEM;
    temp_buf = kmalloc(123, GFP_KERNEL);
    if (!temp_buf)
        goto err_exit;

    err = -ERESTARTSYS;
    if (down_interruptible(&semA))
        goto err_free_temp;

    if (down_interruptible(&semB))
        goto err_unlock_A;

    strcpy(temp_buf, "do the needful ...");
    err = 0;

    up(&semB);
err_unlock_A:
    up(&semA);
err_free_temp:
    free(temp_buf);
err_exit:
    return err;
}