מנגנוני טיימר מאפשרים לך לתזמן את ליבת מערכת ההפעלה כדי להודיע לאפליקציה כאשר חלף זמן קבוע מראש. בדרך כלל תשתמש בהם על ידי מתן שתי פיסות מידע. ראשית, תצטרך לציין כמה זמן אמור לקחת הטיימר לפני מתן הודעה. שנית, תצטרך להכין פונקציית התקשרות חוזרת כדי לפעול כאשר ההודעה הזו מתרחשת.
גישה מסורתית לטיימרים
מנגנוני טיימר במערכות מבוססות לינוקס ו-Unix התפתחו כדי לשרת צרכים שונים. גישות שונות יכולות לעזור לך לפתור סוגים שונים של בעיות. עם זאת, לעתים קרובות תראה את הגרסה הראשונה של אזעקה() המנגנון עדיין בשימוש.
פונקציית האזעקה היא הדרך הפשוטה ביותר להשתמש בטיימר; הנה אב הטיפוס שלו:
לא חתוםintאזעקה(לא חתוםint שניות);
בשיטה זו, אתה יכול לציין רק את הזמן בשניות שלמות. כאשר הזמן חלף, מערכת ההפעלה שולחת את SIGALRM סימן לאפליקציה שלך. כדי לעבד את תפוגת הטיימר באפליקציה שלך, עליך להגדיר גם פונקציית התקשרות חוזרת.
הנה דוגמה לפונקציית מטפל באותות:
#לִכלוֹל
#לִכלוֹל
#לִכלוֹל
#לִכלוֹלבָּטֵלtimer_callback(int סימן)
{
זמן_ט עכשיו = זמן(ריק);
printf("אות %d נתפס ב-%li", signum, now);
}
intרָאשִׁי()
{
אות (SIGALRM, timer_callback);
אזעקה(1);
לִישׁוֹן(3);
לַחֲזוֹר0;
}
קוד זה מעלה א SIGALRM אות אחרי 1 שְׁנִיָה. אם ברצונך להגדיל את השהיית הטיימר לחמש שניות, פשוט התקשר אזעקה (5) במקום זאת. כדי לעצור את הטיימר, העבר ערך של 0: אזעקה (0).
כאשר הזמן נגמר, הטיימר שבו אתה משתמש לא יופעל מחדש מעת לעת. לדוגמה, אם אתה רוצה לעכב עוד שנייה, אתה צריך להפעיל מחדש את המנגנון עם שיחה נוספת אל אזעקה().
למרות קלות השימוש שלה, לשיטה זו יש כמה חסרונות:
- רק טיימר אחד בכל פעם.
- אין תמיכה בטיימר תקופתית.
- אתה יכול לתת את פרק הזמן רק בכפולות של שניות שלמות.
- אין דרך לדעת כמה זמן נשאר לטיימר.
שמור את הקוד לדוגמה שניתן לעיל בשם אזעקה.ג. מתי אתה קומפיל ורץ זה, התוכנית תקרא את timer_callback לתפקד לאחר שנייה אחת. לאחר מכן הוא ימתין את שתי השניות הנותרות עקב ה לישון (3) קו, ואז לסיים.
$ gcc -o אזעקה אזעקה.c
זמן $ ./אזעקה
אות 14 נתפס על 1653490465
אמיתי 0m1.004s
משתמש 0m0.000s
sys 0m0.003s
הסיבה לשימוש בפקודת הזמן היא להיות מסוגל לראות את הזמנים. אבל אם מסתכלים על התוצאה, זמן הריצה הכולל אינו שלוש שניות. זאת בשל ה SIGALRM אות מ אזעקה (1) כאשר השנייה הראשונה למעלה, בעוד ה syscall הנגרמת על ידי פונקציית השינה (3) פועלת. כאשר האות הזה מגיע, הוא קוטע את ה-Syscall היזום עבור לישון (3).
שימוש בטיימר אינטרוולים
מנגנון טיימר המרווחים היה זמין לראשונה בגרסה 4.2 BSD. זה היה מאוחר יותר מתוקנן על ידי POSIX. היתרונות העיקריים שלו על המסורתיים אזעקה() שיטת טיימר מבוססת הם:
- מספק רזולוציה של מיקרו שניות.
- זה מאפשר לשלוט על מדידת הזמן בפירוט רב יותר על פני שלושה מצבים שונים.
- אפשר להגדיר אותו פעם אחת ולגרום לו לעבוד מעת לעת.
- אפשר לברר כמה זמן הוא קיים בכל רגע נתון.
אבות טיפוס פונקציות המשמשים לפעולות טיימר מרווחים הם כדלקמן:
#לִכלוֹל
intsetitimer(int איזה, const struct itimerval *newValue, struct itimerval *oldValue);
intgetitimer(int אשר, struct itimerval *value);מבנהitimerval
{
מבנהזמןitInterval;// הערך הבא
מבנהזמןitValue;// ערך נוכחי
};
מבנהזמן
{
ארוך tv_sec;
ארוך tv_usec;
};
אם אתה רוצה להגדיר טיימר מרווחים, תצטרך להשתמש ב- itimerval מבנה. תצטרך להעביר ערך באמצעות מבנה זה כארגומנט השני ל- טיימר קבע פוּנקצִיָה.
לדוגמה, ניתן להגדיר טיימר מרווח שיודיע לאפליקציה שלך למשך שנייה אחת ולאחר מכן כל 300 מילישניות:
מבנהitimervalnewTimer;
מבנהitimervalותיק;newTimer.itValue.tv_sec = 1;
newTimer.itValue.tv_usec = 0;newTimer.itInterval.tv_sec = 0;
newTimer.itInterval.tv_usec = 300 * 1000;
setitimer (ITIMER_REAL, &newTimer, &oldTimer);
אם יש טיימר מרווח פעיל לפני הגדרת הערכים החדשים, הערכים שלו מועברים לכתובת המשתנה של itimerval סוג שניתן לפרמטר השלישי של הפונקציה.
ניתן להגדיר שלושה סוגים שונים של טיימרים עם מנגנון טיימר המרווחים. ציין את סוג הטיימר בפרמטר הראשון של setitimer():
סוג טיימר | אוֹת | הֶסבֵּר |
---|---|---|
ITIMER_REAL | SIGALRM | ללא תלות בזמן שהושקע על ידי האפליקציה, מחושב על פני כל הזמן שחלף. |
ITIMER_VIRTUAL | SIGVTALRM | מחושב לאורך זמן שהאפליקציה פועלת במצב משתמש בלבד. |
ITIMER_PROF | SIGPROF | מחושב על פני סכום הזמן שהאפליקציה משקיעה במצבי משתמש ומערכת כאחד. |
אתה יכול לראות מהטבלה הזו שה ITIMER_REAL סוג שולח א SIGALRM אות, בדיוק כמו ה אזעקה() פוּנקצִיָה.
שימוש בטיימר אינטרוולים ו אזעקה() באותה יישום יהיה מבלבל. למרות שאתה יכול לבצע בדיקה שניה על הזמן שנותר עם gettimer(), אין זה הגיוני להשתמש בהם בו זמנית.
הנה דוגמה להגדרת פונקציית מטפל האותות עם כותרת ניפוי באגים:
#לִכלוֹל
#לִכלוֹל
#לִכלוֹל
#לִכלוֹל
#לִכלוֹל
#לִכלוֹל
#לִכלוֹל
#לִכלוֹל "./debug.h"בָּטֵלtimer_callback(int סימן)
{
מבנהזמןעַכשָׁיו;
gettimeofday(&עכשיו, ריק);
printf("אות %d נתפס ב-%li.%03li ", signnum, now.tv_sec, now.tv_usec / 1000);
}intרָאשִׁי()
{
לא חתוםint נשאר = 3;מבנהitimervalnew_timer;
מבנהitimervalותיק;new_timer.it_value.tv_sec = 1;
new_timer.it_value.tv_usec = 0;
new_timer.it_interval.tv_sec = 0;
new_timer.it_interval.tv_usec = 300 * 1000;setitimer (ITIMER_REAL, &new_timer, &old_timer);
אות (SIGALRM, timer_callback);בזמן (שינה (נשאר) != 0)
{
אם (שגיאה == EINTR)
debugf("שינה נקטעת באות");
אַחֵר
errorf("שגיאת שינה %s", strerror (errno));
}
לַחֲזוֹר0;
}
הקוד לעיל משתמש ב- לִישׁוֹן() פונקציה לחכות שלוש שניות. במהלך זמן זה, טיימר מרווח פועל, תחילה למשך שנייה אחת, ולאחר מכן במרווח של 300 מילישניות.
להבנה טובה יותר, שמור והידור קוד לדוגמה עם השם interval.c:
$ gcc -o interval interval.c
$ זמן ./מרווח
אות 14 נתפס על 1653493614.325
ניפוי באגים: שינה מופרעת על ידי אות (מרווח ראשי.c: 36)
אות 14 נתפס על 1653493614.625
ניפוי באגים: שינה מופרעת על ידי אות (מרווח ראשי.c: 36)
אות 14 נתפס על 1653493614.925
ניפוי באגים: שינה מופרעת על ידי אות (מרווח ראשי.c: 36)
אות 14 נתפס על 1653493615.225
ניפוי באגים: שינה מופרעת על ידי אות (מרווח ראשי.c: 36)
אות 14 נתפס על 1653493615.525
...
כפי שניתן לראות מהפלט לאחר הפעלת הטיימר, הוא קורא לפונקציית ה-callback כל 300 אלפיות השנייה.
עם זאת, לאחר המתנה קצת יותר, תבחין שהיישום אינו מסתיים. הוא ממשיך להפעיל את פונקציית ה-callback כל 300 אלפיות השנייה. אם תגדיל את ערך המרווח באלפיות שניות, תראה שהיישום מסתיים. זה בגלל אזור השימוש של לִישׁוֹן() פוּנקצִיָה.
חשיבות השימוש בטיימרים בלינוקס
במיוחד עבור אפליקציות בזמן אמת, למנגנון הטיימר חשיבות רבה. זהו גם פתרון המשמש לאופטימיזציות של ביצועים. אתה יכול אפילו להשתמש בו כדי למדוד זמן פעולה או חביון באפליקציה שלך. חשוב להשתמש במנגנוני טיימר כדי לעקוב אחר הזמן שחלף ואירועי מעבר זמן.
כיצד להרכיב ולהתקין תוכנה ממקור בלינוקס
קרא הבא
נושאים קשורים
- תִכנוּת
- תִכנוּת
- עצות לינוקס
על הסופר
מהנדס ומפתח תוכנה חובב מתמטיקה וטכנולוגיה. הוא תמיד אהב מחשבים, מתמטיקה ופיזיקה. הוא פיתח פרויקטים של מנוע משחקים וכן למידת מכונה, רשתות עצביות מלאכותיות וספריות אלגברה ליניארית. יתר על כן ממשיך לעבוד על למידת מכונה ומטריצות ליניאריות.
הירשם לניוזלטר שלנו
הצטרף לניוזלטר שלנו לקבלת טיפים טכניים, ביקורות, ספרים אלקטרוניים בחינם ומבצעים בלעדיים!
לחץ כאן כדי להירשם