سؤال

على الرغم من أن هذا الموضوع قد تمت مناقشته عدة مرات في هذا المنتدى وجميع المنتديات الأخرى ، إلا أنني لا يزال لدي شكوك. الرجاء المساعدة.

كيف يمكن لل do{} while(0) في العمل الكلي في Linux kernel؟ فمثلا،

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

كيف تعطيل ما قبل؟

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

كيف يتم إعادة جدولة؟

وبالمثل ، رأيت وحدات الماكرو لأقفال Mutex وغيرها أيضًا. كيف يساعد هذا؟ أنا أفهم لمشكلة متابعة ولكن ليس للأمثلة أعلاه.

#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)

في New Kernel 2.6.35.4 في برنامج التشغيل I2C 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 والرمز أسهل في القراءة.

  • يمكن أن تحدث حالة مماثلة مع حالتين (تمكين/تعطيل) حيث تحتاج دولة إلى أن يقوم الماكرو بفعل شيء ما ، لكن الحالة الأخرى تحدث بشكل افتراضي ، وبالتالي فإن تنفيذ أحدهما "فارغ" - لا تزال تستخدم الماكرو لأنه يجعل إن رمز العميل أسهل في الفهم ، لأنه ينص صراحة على الأماكن التي يتم فيها تمكين الأشياء أو تعطيلها.

نصائح أخرى

نرى هذا الرابط للحصول على تفسير أفضل مما يمكنني تقديمه.

إن استخدام استخدام الماكرو هو جعلها تبدو أشبه بمثابة استدعاء وظيفة طبيعية ؛ هناك بعض مشكلات بناء الجملة الدقيقة حولها إذا كانت عبارات وأشياء من هذا القبيل. بدون القيام بالماكرو ، قد يبدو الماكرو وكأنه استدعاء وظيفة طبيعية ولكنه سيعمل بشكل مختلف.

أظن أنه في هذه الحالة يتم استخدام وحدات الماكرو هذه ، لذا فإن بعض مكالمات الوظائف تتجمع بعيدًا إلى لا شيء ؛ يبدو أن هذا قد يكون ما تحصل عليه إذا CONFIG_PREEMPT لم يتم تعيينه ، لذا فإن أجزاء معينة من النواة ضرورية فقط للاستباق ببساطة تتلاشى بدونها. لذلك لا تقوم تلك الحلقات بتعطيل أي شيء ما قبل أو إعادة جدولة أي شيء ؛ سيكون هناك تعريف آخر (ربما وظيفة حقيقية) في مكان آخر في مصدر kernel.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top