نظام Linux Dlopen في لغة C.

Nzam Linux Dlopen Fy Lght C



وظيفة المكتبة dlopen () هي وظيفة مفيدة للغاية في لغة C. تقوم الوظيفة بتحميل المكتبة في الذاكرة بعد فتح مكتبة جديدة. نستخدمه بشكل عام لتحميل رموز المكتبة غير المعروفة في وقت الترجمة. Dlopen () هي وظيفة يتم استخدامها في برامجنا. تقوم مكتبة DL بتنفيذ dlopen () المحدد في Dlfcn.h. مطلوب معلمتين لوظيفة dlopen: اسم ملف المكتبة والعلم. اسم الملف عبارة عن مكتبة ديناميكية ، وهي تحدد ما إذا كان سيتم حساب تبعيات المكتبة على الفور أم لا. تقوم dlopen () بإرجاع 'مقبض' والذي يجب اعتباره قيمة معتمة وتستخدم عمليات مكتبة DL الأخرى هذا. إذا فشلت محاولة التحميل ، ترجع dlopen () NULL. لكن dlopen () يُرجع نفس مقبض الملف إذا قام بتحميل نفس المكتبة عدة مرات.

أثناء استخدام وظيفة dlopen ، لا يقوم المترجم بفحص الأخطاء المحتملة لأنه غير مدرك للأنواع والنماذج الأولية التي نستخدمها. لا يبدو أن نشر وظيفة dlopen للتحميل القياسي يعززها ، باستثناء بعض المواقف البسيطة. بالمناسبة ، إنها طريقة لتحسين الاستبطان. عندما يتم استخدام الوحدة المشتركة حاليًا بواسطة برنامج آخر ، فإن تحسين تخطيط الذاكرة لا يهتم بشكل خاص بالتحميل الشرطي. لا تزيد مساحة الذاكرة عند تحميل مكتبة مستخدمة مسبقًا. يعد تجنب مراقبة المترجم أمرًا خطيرًا ويؤدي إلى كتابة أخطاء جيدة. بالإضافة إلى ذلك ، نحن نفتقر إلى إمكانية تحسين المترجم.

مثال 1:

الآن ، ضع في اعتبارك المثال التالي لمعرفة وظيفة وظيفة dlopen في لغة C. في الخطوة الأولى ، نقوم بتحميل بعض مكتبات لغة سي القياسية. هنا ، نقوم بتحميل المكتبة الجديدة 'dlfcn.h' والتي تُستخدم لتحديد وحدات الماكرو أثناء إنشاء وسيطة وضع dlopen.







بعد ذلك ، نقدم مكتبة أخرى داخل برنامجنا 'gnu / lib-name.h'. تم العثور على ملفات المكتبة المشتركة المضمنة في GNU libc بواسطة برامج المستخدم وفقًا لوحدات الماكرو التي تحددها. توفر مكتبة GNU C المكتبات الأساسية لأنظمة التشغيل GNU و GNU / Linux بالإضافة إلى مجموعة كبيرة من الأنظمة الأخرى المستندة إلى Linux. بعد ذلك ، لدينا طريقة التنفيذ الرئيسية. داخل ذلك ، نعلن عن كائن المؤشر 'مقبض' بالكلمة الأساسية الباطلة. نعلن عن دالة جيب للمؤشر لها نوع بيانات مزدوج. يوجد إعلان آخر عن كائن المؤشر 'خطأ' لمعالجة الخطأ.



بعد ذلك ، نستدعي وظيفة dlopen داخل كائن 'handle'. يأخذ dlopen وسيطتين: LIBM_SO و 'RTLD_LAZY'. هنا ، 'LIBM_SO' هو اسم ملف المكتبة الذي يوفر وظائف رياضية مثل الدوال المثلثية. هذه المكتبة المشتركة مطلوبة لأننا نستخدم وظيفة الجيب. 'RTLD_LAZY' هي وسيطة أخرى تستدعي وظيفة dlopen. عندما تتم الإشارة إلى رمز معين في المرة الأولى ، يجب إجراء عمليات النقل في الوقت الذي يحدده التطبيق.



نظرًا لأن العملية قد لا تشير إلى كل رمز في ملف كائن قابل للتنفيذ ، فإن تحديد RTLD LAZY يجب أن يعزز الأداء في عمليات التنفيذ التي تتيح ربط الرمز الديناميكي. بعد ذلك ، لدينا شرط if-else لمعالجة الخطأ عندما يفشل كائن المقبض في أداء وظيفة dlopen. نسمي dlerror لمسح الخطأ.





توفر الدالة dlerror () سلسلة منتهية بقيمة خالية يمكن قراءتها بواسطة الإنسان وتحدد الإبلاغ عن الخطأ الأخير الذي نتج عن استدعاء أحد استدعاءات واجهة برمجة التطبيقات dlopen منذ آخر استدعاء dlerror. بعد ذلك ، نضع الوظيفة على النحو التالي: '(* باطل **) (وجيب) = dlsym (مقبض ، خطيئة)'. نظرًا لأن هذا أمر غريب ، فإن الصب يتوافق مع ISO C الذي يتجنب التحذيرات من المترجم. نحن نستخدم وظيفة dlsym التي تحصل على مسار الرمز المحدد داخل وحدة الارتباط الديناميكي التي يمكن الوصول إليها عبر وظيفة dlopen ().

أيضًا ، نقوم بإجراء عملية if-else مرة أخرى للخطأ القياسي الذي يتم إنشاؤه عندما يكون dlerror () ليس NULL. بعد ذلك ، لدينا عبارة printf حيث نحدد قيمة الجيب المراد حسابها. في الخطوة الأخيرة ، نغلق هذا الكائن المشترك عن طريق استدعاء dlclose للمقبض الذي يعاد بواسطة dlopen ().



# تضمين
# تضمين
# تضمين
# تضمين

int
رئيسي ( int أرجك و شار ** أرجف )
{
فارغ * يتعامل ؛
مزدوج ( * لهم ) ( مزدوج ) ؛
شار * خطأ ؛

يتعامل = دلوبين ( LIBM_SO و RTLD_LAZY ) ؛
إذا ( ! يتعامل ) {
fprintf ( ستدير و '٪س ' و dlerror ( ) ) ؛
خروج ( EXIT_FAILURE ) ؛
}
dlerror ( ) ؛

* ( فارغ ** ) ( & لهم ) = dlsym ( يتعامل و 'بدون' ) ؛

إذا ( ( خطأ = dlerror ( ) ) ! = لا شيء ) {
fprintf ( ستدير و '٪س ' و خطأ ) ؛
خروج ( EXIT_FAILURE ) ؛
}

printf ( '٪F ' و ( * لهم ) ( 4.0 ) ) ؛
dlclose ( يتعامل ) ؛
خروج ( EXIT_SUCCESS ) ؛
}

نستخدم الخيار -ldl مع الأمر C compilation لأن هذه مكتبة لواجهة dlopen المرتبطة وهي مطلوبة. عندما يتم تنفيذ ملف dlopen ، فإنه يعرض قيمة الجيب للقيمة المحددة مسبقًا.

المثال الثاني:

الآن ، نأخذ مثالًا آخر لاستخدام دالة dlopen. نقوم بتحميل برنامجنا بجميع مكتبات C المطلوبة لتنفيذ كود dlopen. ثم نبدأ برنامجنا داخل الطريقة الرئيسية. هنا ، نحدد السلسلة مع إعلان المتغير “src”. ثم نعلن عن متغيرات المؤشر 'strlen' و 'handle' و 'error'.

بعد ذلك ، نسمي متغير المقبض وننشر وظيفة dlopen. تقوم وظيفة dlopen بإدخال المكتبة المشتركة 'libstr.so' لوظائف معالجة السلسلة والعلامة 'RTLD_LAZY' التي تم توضيحها بالفعل في المثال السابق. نستدعي دالة dlerror داخل متغير 'error' لمسح الخطأ الناتج عن دالة dlopen. يتم استخدام if-else لفحص الأخطاء.

بعد ذلك ، نحصل على عنوان وظيفة strlen باستخدام وظيفة dlsym ونتحقق من الأخطاء أثناء القيام بذلك. بعد ذلك ، نستخدم وظيفة printf لاستدعاء دالة strnlen لإرجاع طول السلسلة المحددة. في النهاية ، نغلق المكتبة المشتركة بوظيفة dlclose.

# تضمين
# تضمين
# تضمين
# تضمين
int رئيسي ( فارغ )
{
شار * src = 'مرحبًا Linux' ؛
int ( * سترلين ) ( مقدار ثابت شار * ) ؛
فارغ * يتعامل ؛
شار * خطأ ؛


يتعامل = دلوبين ( './libstr.so' و RTLD_LAZY ) ؛
خطأ = dlerror ( ) ؛
إذا ( ! يتعامل || خطأ ! = لا شيء ) { printf ( 'فشلت محاولة تحميل المكتبة! ٪س ' و خطأ ) ؛
إرجاع - 1 ؛ }

سترلين = dlsym ( يتعامل و 'strlen' ) ؛
خطأ = dlerror ( ) ؛
إذا ( ! سترلين || خطأ == لا شيء ) { printf ( '٪س ' و خطأ ) ؛ إرجاع - 1 ؛ }

printf ( 'طول السلسلة هو:٪ d ' و سترلين ( src ) ) ؛
dlclose ( يتعامل ) ؛
إرجاع 0 ؛
}

نستخدم الأمر التالي لتنفيذ البرنامج المحدد. هنا ، يتم استخدام علامة -lstr لوظيفة طول السلسلة ويتم استخدام ldl لملف مكتبة dlopen. يعطي البرنامج المترجم طول السلسلة كما هو موضح في الغلاف:

استنتاج

يتم توفير المعلومات المتعلقة بوظيفة dlopen للغة C في هذه المقالة. لدينا مقدمة موجزة عن وظيفة dlopen. ثم قمنا بتنفيذ مثالين. ترجع الدالة معرفًا يحدد المكتبة المفتوحة. يتم بعد ذلك تحديد عناوين الوظائف داخل المكتبة المفتوحة باستخدام هذا المعرف ووظيفة dlsym. يمكن العثور على عنوان الوظيفة داخل مكتبة تم فتحها بالفعل باستخدام dlopen باستخدام وظيفة dlsym.