怎么做{} while(0)在宏中工作?

虽然本论坛和所有其他论坛已经多次讨论过这个话题,但我仍有疑问。 请帮忙。

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

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

如何禁用抢占?

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

它是如何重新安排的?

类似地,我已经看到了互斥锁和其他宏的宏。 这有什么用? 我理解以下问题,但不是上面的例子。

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

编辑:

rt_mutex_lock的以下代码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) 

在i2c驱动程序rt_mutex_lock(&adap->bus_lock);中的新内核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-while是为了使它们看起来更像是正常的函数调用; 围绕unbraced if语句和类似的东西有一些微妙的语法问题。 没有do-while宏可能看起来像普通的函数调用,但会以不同的方式工作。

我猜想在这种情况下,正在使用这些宏,因此某些函数调用会编译为空; 如果没有设置CONFIG_PREEMPT ,它看起来可能就是你所获得的内容,因此内核的某些部分只有在抢占时才会消失。 所以这些循环不会禁用抢占或重新安排任何东西; 在内核源代码的其他地方会有另一个定义(可能是一个真正的函数)。