当前位置:  开发笔记 > 运维 > 正文

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

如何解决《怎么做{}while(0)在宏中工作?》经验,为你挑选了2个好方法。

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

do{} while(0)in-macro 如何在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().这怎么锁定呢?



1> Justin..:

请参阅此链接以获得比我能给出的更好的解释.


+1只是为了弹出一个间接层,第一个引用就回答了这个问题:(来自Dave Miller)空语句会给编译器发出警告,这就是为什么你看到`#define FOO do {} while(0)` .

2> Jason Willia..:

@Kragen回答了做什么......虽然构造是为了 - 它基本上使得宏更安全使用.

但是,我不认为它回答了"这是如何工作的"这个问题:

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

该宏被定义为什么都不做.你为什么什么都不想做?

在某些情况下,您希望使用宏作为占位符来执行某些操作.例如,您可以在一个系统上编写代码,其中"抢占"不是问题,但您知道代码可能被移植到"抢占"需要一些特殊处理的系统.因此,您可以在第二个系统需要的任何地方使用宏(以便稍后可以轻松启用),但是对于第一个系统,您可以将该宏定义为空白宏.

在某些情况下,您可能希望执行由不同部分组成的任务(例如START_TABLE(); TABLE_ENTRY(1); TABLE_ENTRY(2); END_TABLE();).这样可以很好地清理表格.但是你发现你实际上并不需要END_TABLE()宏.为了保持客户端代码整洁,您可以保留定义的宏,并将其定义为不执行任何操作.这样,所有表都有一个END_TABLE,代码更容易阅读.

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

推荐阅读
小白也坚强_177
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有