מערכת Linux Dlopen ב-C

M Rkt Linux Dlopen B C



פונקציית הספרייה dlopen() היא פונקציה שימושית מאוד בשפת C. הפונקציה טוענת את הספרייה לזיכרון לאחר פתיחת ספרייה חדשה. בדרך כלל אנו משתמשים בו כדי לטעון את סמלי הספרייה שאינם ידועים בזמן ההידור. Dlopen() היא פונקציה שנמצאת בשימוש בתוכניות שלנו. ספריית DL מיישמת dlopen(), המוגדר ב-Dlfcn.h. שני פרמטרים נדרשים עבור הפונקציה dlopen: שם קובץ הספרייה והדגל. שם הקובץ הוא ספרייה דינמית, והוא מגדיר אם התלות של הספרייה מחושבת מיד או לא. ה-dlopen() מחזיר 'handle' שיש להתייחס אליו כערך אטום ופעולות אחרות של ספריית DL משתמשות בזה. אם הניסיון לטעון לא מצליח, dlopen() מחזיר את NULL. אבל ה-dlopen() מחזיר את אותה ידית קובץ אם הוא טוען את אותה ספריה פעמים רבות.

בזמן השימוש בפונקציית dlopen, המהדר אינו בודק שגיאות פוטנציאליות מכיוון שהוא לא מודע לסוגים ואבות הטיפוס שבהם אנו משתמשים. נראה שהפריסה של פונקציית dlopen לטעינה סטנדרטית אינה מקודמת על ידה, למעט כמה מצבים קלים. אגב, זו גישה לשיפור התבוננות פנימית. כאשר המודול המשותף נמצא כעת בשימוש על ידי תוכנית אחרת, אופטימיזציית פריסת הזיכרון אינה מעוניינת במיוחד בטעינה מותנית. טביעת הרגל של הזיכרון אינה גדלה כאשר נטענת ספרייה ששימשה בעבר. הימנעות ממעקב מהדר היא מסוכנת וגורמת לכתיבת באגים טובה. בנוסף, חסרה לנו האופטימיזציה האפשרית של המהדר.

דוגמה 1:

כעת, שקול את הדוגמה הבאה כדי לראות את הפונקציונליות של הפונקציה dlopen בשפת C. בשלב הראשון, אנו טוענים מספר ספריות בתקן C. כאן, אנו טוענים את הספרייה החדשה 'dlfcn.h' המשמשת להגדרת פקודות המאקרו תוך בניית ארגומנט מצב dlopen.







לאחר מכן, אנו מציגים ספרייה נוספת בתוך התוכנית שלנו 'gnu/lib-name.h'. קבצי הספרייה המשותפת הכלולים ב-GNU libc נמצאים על ידי תוכניות המשתמש בהתאם לפקודות המאקרו שהיא מגדירה. ספריית GNU C מציעה את הספריות הבסיסיות עבור מערכות ההפעלה GNU ו-GNU/Linux וכן מגוון רחב של מערכות אחרות מבוססות לינוקס. לאחר מכן, יש לנו את יישום השיטה העיקרית. בתוך זה, אנו מכריזים על אובייקט המצביע 'handle' עם מילת המפתח void. אנו מכריזים על פונקציית סינוס מצביע בעלת סוג הנתונים כפול. קיימת הצהרה נוספת של אובייקט המצביע 'שגיאה' לטיפול בשגיאות.



לאחר מכן, אנו מפעילים את הפונקציה dlopen בתוך אובייקט 'הידית'. ה-dlopen לוקח שני ארגומנטים: LIBM_SO ו-'RTLD_LAZY'. כאן, 'LIBM_SO' הוא השם של קובץ הספרייה המספק פונקציות מתמטיות כמו פונקציות טריגונומטריות. ספרייה משותפת זו נדרשת מכיוון שאנו משתמשים בפונקציית הסינוס. 'RTLD_LAZY' הוא ארגומנט נוסף שקורא לפונקציה dlopen. כאשר סמל נתון מוזכר בפעם הראשונה, יש לבצע רילוקיישן במועד שנקבע על ידי היישום.



מכיוון שתהליך לא עשוי להתייחס לכל סמל בקובץ אובייקט בר הפעלה, ציון ה-RTLD LAZY אמור לשפר את הביצועים של יישומים המאפשרים כריכת סמלים דינמית. לאחר מכן, יש לנו תנאי if-else לטיפול בשגיאות כאשר אובייקט ה-handle לא מצליח לבצע את הפונקציה dlopen. אנו קוראים ל-dlerror כדי לנקות את השגיאה.





הפונקציה dlerror() מספקת מחרוזת עם סיומת Null הניתנת לקריאה אנושית ומציינת את הדיווח על השגיאה האחרונה שנגרמה מקריאה לאחת מקריאות ה-API של dlopen מאז הקריאה האחרונה של dlerror. לאחר מכן, נטיל את הפונקציה כך: '(*void**)(&sine)= dlsym(handle, sin)'. מכיוון שזה מוזר, הליהוק תואם ל-ISO C שמונע אזהרות מהמהדר. אנו משתמשים בפונקציית dlsym שמקבלת את הנתיב של סמל שצוין בתוך מודול קישור דינמי הנגיש באמצעות פונקציית dlopen()‎.

כמו כן, אנו מבצעים שוב את פעולת if-else עבור השגיאה הסטנדרטית שנוצרת כאשר ה-dlerror() אינו NULL. לאחר מכן, יש לנו משפט printf שבו אנו מציינים את ערך הסינוס לחישוב. בשלב האחרון, אנו סוגרים את האובייקט המשותף על ידי הפעלת ה-dlclose עבור הידית המוחזרת על ידי ה-dlopen().



#include
#include
#include
#include

int
רָאשִׁי ( int argc , לְהַשְׁחִיר ** argv )
{
בָּטֵל * ידית ;
לְהַכפִּיל ( * שֶׁלָהֶם ) ( לְהַכפִּיל ) ;
לְהַשְׁחִיר * שְׁגִיאָה ;

ידית = dlopen ( LIBM_SO , RTLD_LAZY ) ;
אם ( ! ידית ) {
fprintf ( סטדרר , '%s \n ' , דלרור ( ) ) ;
יְצִיאָה ( EXIT_FAILURE ) ;
}
דלרור ( ) ;

* ( בָּטֵל ** ) ( & שֶׁלָהֶם ) = dlsym ( ידית , 'לְלֹא' ) ;

אם ( ( שְׁגִיאָה = דלרור ( ) ) != ריק ) {
fprintf ( סטדרר , '%s \n ' , שְׁגִיאָה ) ;
יְצִיאָה ( EXIT_FAILURE ) ;
}

printf ( '%f \n ' , ( * שֶׁלָהֶם ) ( 4.0 ) ) ;
dlclose ( ידית ) ;
יְצִיאָה ( EXIT_SUCCESS ) ;
}

אנו משתמשים באפשרות -ldl עם פקודת הקומפילציה C מכיוון שזו הספרייה עבור הממשק המקושר dlopen והיא נדרשת. כאשר מתבצעת ביצוע הקובץ dlopen, הוא מציג את ערך הסינוס של הערך שניתן קודם לכן.

דוגמה 2:

כעת, ניקח דוגמה נוספת לשימוש בפונקציית dlopen. אנו טוענים את התוכנית שלנו עם כל ספריות ה-C הנדרשות ליישום הקוד dlopen. לאחר מכן, אנו מתחילים את התוכנית שלנו בשיטה הראשית. כאן, אנו מגדירים את המחרוזת עם ההצהרה של המשתנה 'src'. לאחר מכן אנו מכריזים על משתני המצביע 'strlen', 'handle' ו-'error'.

לאחר מכן, אנו קוראים למשתנה handle ופורסים את הפונקציה dlopen. הפונקציה dlopen מכניסה את הספרייה המשותפת 'libstr.so' עבור פונקציות טיפול במחרוזות ואת הדגל 'RTLD_LAZY' שכבר הודגם בדוגמה הקודמת. אנו מפעילים את פונקציית dlerror בתוך המשתנה 'שגיאה' כדי לנקות את השגיאה שנוצרה על ידי הפונקציה dlopen. ה-if-else משמש לבחינת השגיאות.

לאחר מכן, אנו משיגים את הכתובת של פונקציית strlen באמצעות הפונקציה dlsym ומאמתים את השגיאות תוך כדי פעולה זו. לאחר מכן, אנו משתמשים בפונקציה printf כדי לקרוא לפונקציה strnlen כדי להחזיר את אורך המחרוזת הנתונה. בסופו של דבר, נסגור את הספרייה המשותפת עם הפונקציה dlclose.

#include
#include
#include
#include
int רָאשִׁי ( בָּטֵל )
{
לְהַשְׁחִיר * src = 'שלום לינוקס' ;
int ( * סטרלן ) ( const לְהַשְׁחִיר * ) ;
בָּטֵל * ידית ;
לְהַשְׁחִיר * שְׁגִיאָה ;


ידית = dlopen ( './libstr.so' , RTLD_LAZY ) ;
שְׁגִיאָה = דלרור ( ) ;
אם ( ! ידית || שְׁגִיאָה != ריק ) { printf ( 'ניסיון טעינת הספרייה נכשל! \n %s \n ' , שְׁגִיאָה ) ;
לַחֲזוֹר - 1 ; }

סטרלן = dlsym ( ידית , 'סטרלן' ) ;
שְׁגִיאָה = דלרור ( ) ;
אם ( ! סטרלן || שְׁגִיאָה == ריק ) { printf ( '%s \n ' , שְׁגִיאָה ) ; לַחֲזוֹר - 1 ; }

printf ( 'אורך המחרוזת הוא:%d \n ' , סטרלן ( src ) ) ;
dlclose ( ידית ) ;
לַחֲזוֹר 0 ;
}

אנו משתמשים בפקודה הבאה לביצוע התוכנית הנתונה. כאן, הדגל -lstr משמש עבור פונקציית אורך המחרוזת וה-ldl משמש עבור קובץ הספרייה dlopen. התוכנית הקומפילטית נותנת את אורך המחרוזת כפי שמוצג במעטפת:

סיכום

המידע מסופק לגבי הפונקציה dlopen של שפת C במאמר זה. יש לנו הקדמה קצרה של הפונקציה dlopen. לאחר מכן, יישמנו שתי דוגמאות. הפונקציה מחזירה מזהה שמגדיר את הספרייה שנפתחה. הכתובות של הפונקציות בתוך הספרייה שנפתחה נקבעות לאחר מכן באמצעות מזהה זה ופונקציית dlsym. ניתן למצוא כתובת של פונקציה בתוך ספרייה שכבר נפתחה באמצעות dlopen באמצעות הפונקציה dlsym.