C {}while(0)如何在宏中工作?
虽然这个话题在这个论坛和所有其他论坛上都讨论过很多次,但我还是有疑问。请帮忙 宏中的C {}while(0)如何在宏中工作?,c,do-while,C,Do While,虽然这个话题在这个论坛和所有其他论坛上都讨论过很多次,但我还是有疑问。请帮忙 宏中的while(0)如何在Linux内核中工作? 比如说, #define preempt_disable() do { } while (0) 它如何禁用抢占 #define might_resched() do { } while (0) 如何重新安排 类似地,我也看到了用于互斥锁和其他锁的宏。这有什么帮助?我理解下面的问题,但不理解上面的例子 #define foo(x) do { 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\u mutex\u 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\u mutex\u deadlock\u account\u lock
在内核中的两个位置定义:
在内核/rtmutex debug.c
中:
void rt_mutex_deadlock_account_lock(struct rt_mutex *lock,
struct task_struct *task)
{
//....
}
在内核/rtmutex.h
中:
#define rt_mutex_deadlock_account_lock(m, t) do { } while (0)
在新内核2.6.35.4中的i2c驱动程序
rt_互斥锁(&adap->bus_锁)
已替换了互斥锁()。那么这个锁是怎么锁的呢?请参阅,以获得比我能给出的更好的解释。IIRC在宏中使用do while是为了使它们看起来更像一个正常的函数调用;无支撑if语句和类似的语句存在一些微妙的语法问题。如果没有do while,宏可能看起来像一个正常的函数调用,但工作方式不同
我猜在这种情况下,这些宏被使用,所以某些函数调用编译成了零;如果没有设置
CONFIG\u PREEMPT,您可能会得到这样的结果,因此内核中只有PREEMPT需要的某些部分在没有它的情况下就会消失。因此,这些循环不会禁用抢占或重新调度任何内容;内核源代码的其他地方会有另一个定义(可能是一个实函数)。@Kragen已经回答了do…while构造的用途——它基本上使宏的使用更加安全
然而,我不认为它回答了“这是如何工作的?”:
宏被定义为不执行任何操作。你为什么什么都不想做
- 在某些情况下,您希望使用宏作为执行某些操作的占位符。例如,您可能在一个系统上编写代码,其中“抢占”不是问题,但您知道代码可能被移植到“抢占”需要特殊处理的系统。因此,您可以在第二个系统需要的任何地方使用宏(以便以后很容易启用处理),但对于第一个系统,您可以将该宏定义为空白宏
- 在某些情况下,您可能希望执行由不同部分组成的任务(例如,开始_TABLE();表_ENTRY(1);表_ENTRY(2);结束_TABLE())。这使得表的实现非常清晰。但是您发现实际上并不需要END_TABLE()宏。为了保持客户机代码整洁,您需要定义宏,只需将其定义为不做任何事情。这样,所有表都有一个END_表,代码更容易阅读
- 类似的情况可能发生在两种状态(启用/禁用)中,其中一种状态需要宏执行某些操作,而另一种状态只是默认情况下发生的,因此其中一种状态的实现为“空”-您仍然使用宏,因为它使客户端代码更容易理解,因为它明确说明了启用或禁用事物的位置
do。。。虽然(0)
,但代码在循环体中有操作-与此处不同。所以这有点不同。我很清楚,内核作者有一些理由希望宏扩展到不仅仅是一个完全空的表达式,但让它扩展为零或只是一个注释乍一看似乎同样有用。在任何情况下,它都会导致OP在读取内核源代码时质疑它,因此我同意@Jonathan的观点,即它更多地是关于缺少主体,而不是do{}while(0)
的意思。@chiccodoro:这是内核的原始代码段,没有任何修改。我在这里关心的是,当do while(0)什么都不做时,它实际上是如何锁定的。谢谢,我理解这个抢占的东西是如何工作的,但仍然对互斥锁感到困惑。请看我关于rt_互斥锁的回复。我假设互斥锁是类似的——有一个“真实”的实现和一个“虚拟”的实现,它什么都不做。假设在某些情况下,如果内核被配置为永远不需要它,那么可能会使用虚拟的一个-也许如果没有启用配置SMP?+1只是为了弹出一个间接级别,这里的第一个引用回答了这个问题:(来自Dave Miller)空语句会从编译器发出警告,这就是为什么在(0)@justin和。。。链接已断开。如果你能找到镜像,请将相关信息添加到你的答案中。如果执行{},而(0)
不执行任何操作。编译器是否会因此而生成垃圾指令,或者循环将被优化掉?编译器现在有非常好的优化器,因此您不太可能在这样一个明显的空情况下找到浪费时间的优化器。
#define preempt_disable() do { } while (0)