虽然本论坛和所有其他论坛已经多次讨论过这个话题,但我还是有疑问。请帮忙。
宏内的do{} while(0)
如何在Linux内核中运行?
例如,
#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 - 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中,i2c驱动程序rt_mutex_lock(&adap->bus_lock);
已替换mutex_lock()
。这怎么锁定呢?
答案 0 :(得分:11)
请参阅this link以获得比我能给出的更好的解释。
答案 1 :(得分:5)
@Kragen回答了做什么......虽然构造是为了 - 它基本上使宏更安全使用。
但是,我不认为它回答了“这是如何工作的?”的问题:
#define preempt_disable() do { } while (0)
宏定义为不执行任何操作。你为什么什么都不想做?
在某些情况下,您希望使用宏作为占位符来执行某些操作。例如,您可以在一个系统上编写代码,其中“抢占”不是问题,但您知道代码可能被移植到“抢占”需要一些特殊处理的系统。所以你在第二个系统需要它的地方使用一个宏(以便稍后可以轻松启用),但是对于第一个系统,你可以将该宏定义为空白宏。
在某些情况下,您可能希望执行由不同部分组成的任务,(例如START_TABLE(); TABLE_ENTRY(1); TABLE_ENTRY(2); END_TABLE();)。这样可以很好地清理表格。但是你发现你实际上并不需要END_TABLE()宏。为了保持客户端代码整洁,您可以保留定义的宏,并将其定义为不执行任何操作。这样,所有表都有一个END_TABLE,代码更容易阅读。
类似的情况可能发生在两个状态(启用/禁用),其中一个状态需要宏来执行某些操作,但另一个状态只是默认情况下发生,因此一个状态的实现是“空的” - 你仍然使用宏因为它使客户端代码更容易理解,因为它明确说明了启用或禁用事物的位置。
答案 2 :(得分:3)
IIRC在宏中使用do-while是为了使它们看起来更像是一个正常的函数调用;关于unbraced if语句和类似的东西,有一些微妙的语法问题。如果没有这样做,宏可能看起来像一个正常的函数调用,但会以不同的方式工作。
我想在这种情况下会使用那些宏,因此某些函数调用会编译为空;如果没有设置CONFIG_PREEMPT
,它看起来可能就是你得到的东西,所以内核中只有先发制人必需的部分才会在没有它的情况下消失。所以这些循环不会禁用抢占或重新安排任何东西;在内核源代码的其他地方会有另一个定义(可能是一个真正的函数)。