【问题标题】:mutex unlocking and request_module() behaviour互斥锁解锁和 request_module() 行为
【发布时间】:2017-03-13 15:23:54
【问题描述】:

我在 Linux 内核中观察到以下代码模式,例如 net/sched/act_api.c 或许多其他地方:

rtnl_lock();
rtnetlink_rcv_msg(skb, ...);
  replay:
  ret = process_msg(skb);
    ...
    /* try to obtain symbol which is in module. */
    /* if fail, try to load the module, otherwise use the symbol */
    a = get_symbol();
    if (a == NULL) {
       rtnl_unlock();
       request_module();
       rtnl_lock();
       /* now verify that we can obtain symbols from requested module and return EAGAIN.*/
       a = get_symbol();
       module_put();
       return -EAGAIN;
    }
  ...
  if (ret == -EAGAIN)
     goto replay;
  ...
rtnl_unlock();

request_module 成功后,我们感兴趣的符号在内核内存空间中可用,我们可以使用它。但是我不明白为什么要返回 EAGAIN 并重新读取符号,为什么不能在 request_module() 之后继续?

【问题讨论】:

  • 您正在查看哪个版本的内核源代码?上面的代码似乎在持有锁时返回-EAGAIN

标签: linux networking linux-kernel network-programming


【解决方案1】:

如果您查看 Linux 内核中的 current implementation,在您上面的代码(它是 tc_lookup_action_n())中,在第二次调用之后有一条等效于 get_symbol() 的注释,可以准确解释原因:

rtnl_unlock();
request_module("act_%s", act_name);
rtnl_lock();

a_o = tc_lookup_action_n(act_name);

/* We dropped the RTNL semaphore in order to
 * perform the module load.  So, even if we
 * succeeded in loading the module we have to
 * tell the caller to replay the request.  We
 * indicate this using -EAGAIN.
 */
if (a_o != NULL) {
    err = -EAGAIN;
    goto err_mod;
}

即使模块可以被请求和加载,由于信号量被丢弃以加载模块,这是一个可以休眠的操作(并且不是执行此函数的“标准方式”,该函数返回 @987654325 @ 发出信号。

编辑澄清:

如果我们查看添加新操作时的调用序列(这可能会导致加载所需的模块),我们会得到以下序列:tc_ctl_action() -> tcf_action_add() -> tcf_action_init() -> tcf_action_init_1() . 现在,如果将EAGAIN 错误“移回”到case RTM_NEWACTION: 中的tc_ctl_action(),我们会看到使用EAGAIN ret 值重复调用tcf_action_add

【讨论】:

  • 我当然在发布我的问题之前阅读了评论,但我不明白为什么如果信号量已被删除,调用者应该重新执行其请求。 rtnl_unlockrtnl_lock 之间有一个小窗口,可以安排另一个线程执行,这是这个原因吗?
  • 是的,完全正确:rtnl_unlock() 调用 netdev_run_todo() 明确地进行可以休眠的调用。此外,request_module()实际上是__request_module(true, mod),其中true表示我们等待模块加载,这也是一个可以休眠的操作。
猜你喜欢
  • 2018-05-23
  • 2021-02-03
  • 2022-07-31
  • 2010-12-17
  • 1970-01-01
  • 2021-11-23
  • 2010-11-22
  • 1970-01-01
相关资源
最近更新 更多