Linux 为什么要包装函数?

Linux 为什么要包装函数?,linux,kernel,c,Linux,Kernel,C,为什么Linux内核有时会使用非常相似的名称实现一个函数的多个版本,而只包装另一个函数?例如: static void clocksource\u选择(void) { __时钟源_选择(假); } 静态无效时钟源\选择\回退(无效) { __时钟源_选择(真); } 您给出的示例不是一个很好的示例,因为它与Linux内核无关。这只是基本的软件工程 当您有两个功能需要具有非常接近的功能时,您可以采用几种方法 您可以实现该函数两次。我们不喜欢这样做,因为这会造成代码重复。这还意味着,如果您需要更改代

为什么Linux内核有时会使用非常相似的名称实现一个函数的多个版本,而只包装另一个函数?例如:

static void clocksource\u选择(void)
{
__时钟源_选择(假);
}
静态无效时钟源\选择\回退(无效)
{
__时钟源_选择(真);
}

您给出的示例不是一个很好的示例,因为它与Linux内核无关。这只是基本的软件工程

当您有两个功能需要具有非常接近的功能时,您可以采用几种方法

  • 您可以实现该函数两次。我们不喜欢这样做,因为这会造成代码重复。这还意味着,如果您需要更改代码公共区域中的某些内容,您需要记住在两个位置进行更改

  • 您可以将公共代码拆分为自己的函数,并从每个函数调用该函数。如果可能的话,这是最好的解决办法。问题是这并不总是可能的。这可能不可能,因为公共代码需要太多的上下文,或者因为它需要在整个函数中展开。这使我们有权:

  • 创建一个内部“公共”函数,并用一个参数说明要提供哪些功能。只需编写代码,并在两个函数需要执行不同操作的地方放置一个
    if
    。这就是内核在您的示例中采用的路径

  • 话虽如此,还有另一种情况,具体到Linux内核,其中两个函数看起来几乎完全相同。在i386平台上,
    stat
    系统调用不是执行两次,而是执行三次:

    • oldstat
      18号系统调用
    • stat
      syscall号码106
    • stat64
      syscall号码195
    原因是Linux内核承诺在其用户空间内核界面上实现完全的向后兼容性。当某个函数由于某种原因而被替换时,如
    stat
    所发生的情况,不是一次,而是两次(如果您计算
    fstatat
    ,则三次),旧的系统调用条目需要保留并保持可操作性


    但是,如果您查看实际的实现,您会注意到它们之间的差别很小,它们最终都调用了几乎相同的函数。

    有时您希望将此函数传递给需要特定签名的其他函数。或者存储在需要特定签名的函数表中。或符合特定的接口。或者只是为了方便/可读性。也可能是其他原因。在您的示例中,您没有注意到两个包装函数传递包装函数的值不同吗?“非常相似的名称,只是包装了另一个函数”,这在这里并没有真正完成
    clocksource\u select()
    \u clocksource\u select()
    具有不同的函数签名。