سؤال

كنت أقرأ LKMPG ( انظر القسم 4.1.4.إلغاء تسجيل جهاز ) ولم يكن من الواضح بالنسبة لي متى أستخدم try_module_get / module_put المهام.بعض أمثلة LKMPG تستخدمها، والبعض الآخر لا يستخدمها.

ولزيادة الارتباك، try_module_get يظهر 282 مرة في 193 ملفًا في المصدر 2.6.24، ولكن في برامج تشغيل أجهزة Linux ( LDD3 ) و برامج تشغيل أجهزة Linux الأساسية, ، فهي لا تظهر حتى في مثال رمز واحد.

اعتقدت ربما كانوا مرتبطين بالقديم register_chrdev الواجهة (تم استبدالها في 2.6 بواجهة cdev)، لكنها تظهر معًا في نفس الملفات 8 مرات فقط:

find -type f -name *.c | xargs grep -l try_module_get | sort -u | xargs grep -l register_chrdev | sort -u | grep -c .

إذن متى يكون من المناسب استخدام هذه الوظائف وهل هي مرتبطة باستخدام واجهة معينة أو مجموعة من الظروف؟

يحرر

لقد قمت بتحميل sched.c مثال من LKMPG وحاول التجربة التالية:

anon@anon:~/kernel-source/lkmpg/2.6.24$ tail /proc/sched -f &
Timer called 5041 times so far
[1] 14594

anon@anon:~$ lsmod | grep sched
sched                   2868  1 

anon@anon:~$ sudo rmmod sched
ERROR: Module sched is in use

هذا يقودني إلى الاعتقاد بأن النواة تقوم الآن بالمحاسبة الخاصة بها وأن عمليات الحصول/الوضع قد تكون قديمة.يمكن لأي شخص التحقق من هذا؟

هل كانت مفيدة؟

المحلول

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

المثال المحدد الذي قمت بربطه في LKMPG حيث الكود يحاول_module_get() في الأسلوب open() سيتم التعامل معه في النواة الحديثة عن طريق تعيين حقل .owner في struct file_operations:

struct file_operations fops = {
        .owner = THIS_MODULE,
        .open = device_open,
        //...
};

سيؤدي هذا إلى جعل كود VFS مرجعًا للوحدة النمطية قبل الاتصال بها، مما يؤدي إلى إزالة النافذة غير الآمنة - إما أن ينجح Try_module_get() قبل استدعاء .open()، أو أن Try_module_get() سيفشل ولن يتصل VFS مطلقًا بالوحدة.في كلتا الحالتين، لا نقوم مطلقًا بتشغيل تعليمات برمجية من وحدة تم إلغاء تحميلها بالفعل.

الوقت المناسب الوحيد لاستخدامtry_module_get() هو عندما تريد الحصول على مرجع على ملف مختلف الوحدة النمطية قبل الاتصال بها أو استخدامها بطريقة ما (على سبيل المثال، كما يفعل رمز فتح الملف في المثال الذي شرحته أعلاه).هناك عدد من استخدامات Try_module_get(THIS_MODULE) في مصدر kernel ولكن معظمها إن لم تكن جميعها عبارة عن أخطاء كامنة يجب تنظيفها.

السبب وراء عدم تمكنك من إلغاء تحميل المثال المجدول هو أن ملف

$ tail /proc/sched -f &

يبقي الأمر /proc/sched مفتوحًا، وبسبب ذلك

        Our_Proc_File->owner = THIS_MODULE;

في كود sched.c، يؤدي فتح /proc/sched إلى زيادة عدد المراجع لوحدة sched، والتي تمثل المرجع الوحيد الذي يعرضه lsmod.من خلال إلقاء نظرة سريعة على بقية التعليمات البرمجية، أعتقد أنه إذا قمت بتحرير /proc/sched عن طريق إنهاء أمر الذيل الخاص بك، فستكون قادرًا على إزالة الوحدة sched.

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