Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/EmptyTag/158.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C {}while(0)如何在宏中工作?_C_Do While - Fatal编程技术网

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_表,代码更容易阅读

  • 类似的情况可能发生在两种状态(启用/禁用)中,其中一种状态需要宏执行某些操作,而另一种状态只是默认情况下发生的,因此其中一种状态的实现为“空”-您仍然使用宏,因为它使客户端代码更容易理解,因为它明确说明了启用或禁用事物的位置


在我看来,它重新定义了该函数,使其不起任何作用。@Mark:听起来很有说服力。ravspratapsingh:对于上面的两个语句,括号之间真的什么都没有,这是对的吗?或者你只是这样简化了代码?@paxdiablo:“可能的重复”并没有那么接近;它讨论了
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)