尽管该论坛和所有其他论坛已经多次讨论了这个话题,但我仍然怀疑。请帮忙。

如何 do{} while(0) 在Linux内核中的宏观工作?例如,

#define preempt_disable()    do { } while (0)

它如何禁用抢占?

#define might_resched()    do { } while (0)

它如何重新安排?

同样,我也看到了Mutex锁和其他的宏。这有什么帮助?我理解以下问题,但不理解上述示例。

#define foo(x)    do { do something } while(0)

编辑:

下面的代码呢 rt_mutex_lock?

/**
 * rt_mutex_lock - lock a rt_mutex
 *
 * @lock: the rt_mutex to be locked
 */
void __sched rt_mutex_lock(struct rt_mutex *lock)
{
        might_sleep();
        rt_mutex_fastlock(lock, TASK_UNINTERRUPTIBLE, 0, rt_mutex_slowlock);
}
EXPORT_SYMBOL_GPL(rt_mutex_lock);


/*
 * debug aware fast / slowpath lock,trylock,unlock
 *
 * The atomic acquire/release ops are compiled away, when either the
 * architecture does not support cmpxchg or when debugging is enabled.
 */

static inline int rt_mutex_fastlock(struct rt_mutex *lock, 
    int state, int detect_deadlock, int (*slowfn)(struct rt_mutex *lock, 
    int state, struct hrtimer_sleeper *timeout, int detect_deadlock))
{
        if (!detect_deadlock && likely(rt_mutex_cmpxchg(lock, NULL, current))) {
                rt_mutex_deadlock_account_lock(lock, current);
                return 0;
        } else{
                return slowfn(lock, state, NULL, detect_deadlock);
        }
}

我很困惑,因为 rt_mutex_deadlock_account_lock 在内核的两个地方被定义:

kernel/rtmutex-debug.c:

void rt_mutex_deadlock_account_lock(struct rt_mutex *lock, 
    struct task_struct *task)
{
    //....
}

kernel/rtmutex.h:

#define rt_mutex_deadlock_account_lock(m, t) do { } while (0)

在新内核2.6.35.4中 rt_mutex_lock(&adap->bus_lock); 已更换 mutex_lock(). 。那么如何锁定呢?

有帮助吗?

解决方案

@Kragen回答了做什么...在构造是为了什么 - 基本上使宏观更安全。

但是,我认为它没有回答“这如何工作?”的问题:

#define preempt_disable()    do { } while (0)

宏定义为 没做什么. 。你为什么不做什么?

  • 在某些情况下,您想将宏用作做某事的占位符。例如,您可能会在一个系统上编写代码,其中“抢占”不是问题,但是您知道代码可能已移植到“抢占”需要一些特殊处理的系统中。因此,您可以在第二个系统需要的地方使用宏(以便以后易于启用处理),但是对于第一个系统,您然后将该宏定义为空白的宏。

  • 在某些情况下,您可能想执行由不同部分组成的任务(例如start_table(); table_entry(1); table_entry(2); end_table();)。这使您的桌子清晰地实现了一个不错的清晰实现。但是然后您发现实际上不需要end_table()宏。为了保持客户端代码整理,您将宏定义放置,然后将其定义为什么都不做。这样,您所有的表都有一个end_table,并且代码易于阅读。

  • 在一个状态需要宏来做某事的两个状态(启用/禁用)中可能会发生类似的情况,但是另一个状态默认情况下发生,因此实现一个状态是“空” - 您仍然使用宏,因为它使客户端代码更容易理解,因为它明确说明了启用或禁用事物的地方。

其他提示

这个链接 为了更好的解释。

iirc在宏中使用do-是使它们看起来更像是正常的功能调用。如果陈述和类似的话,围绕未解决的问题存在一些微妙的语法问题。没有做事时,宏可能看起来像是正常的功能调用,但会有所不同。

我猜想在这种情况下,这些宏正在使用,因此某些功能调用毫无根据。看起来这可能是您得到的 CONFIG_PREEMPT 没有设置,因此,只有在没有它的情况下,只有抢先的某些部分才能消失。因此,这些循环不会禁用抢先或重新安排任何东西;内核源中其他地方还会有另一个定义(可能是实际功能)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top