תזמון של איכות השירות ב-SDV

מסגרת התזמון של איכות השירות (QoS) ב-SDV מספקת הקצאה דטרמיניסטית של משאבי CPU לחבילות שירות שמנוהלות על ידי Lifecycle Manager ‏ (LM). הפלטפורמה מאפשרת הפרדה ברורה בין פיתוח שירותים לבין כוונון מערכת ברמת הרכב, על ידי הפשטה של מאפייני תזמון של Linux ברמה נמוכה (מדיניות, עדיפות, Nice) להגדרות קבועות מראש לוגיות. כך אפשר לספק את רוחב הפס הדרוש לחישובים עבור עומסי עבודה קריטיים לבטיחות ורגישים לזמן, בזמן שהמערכת מגבילה את משימות הרקע כדי למנוע חוסר יציבות.

תפקידים ותחומי אחריות

מודל התזמון של SDV פועל לפי דפוס של אחריות מוקצית, כדי לוודא שהשירותים יישארו ניידים, וגם כדי לאפשר ליצרן הציוד המקורי (OEM) לכוון את המערכת.

תפקיד אחריות תוצר מרכזי
פלטפורמת SDV ‏ (Google) היא מגדירה את סכימת sdv_service_bundles_scheduling.proto, מטמיעה את הלוגיקה של אכיפת LM ומספקת את ספריית הלקוח sdv_service_bundles_scheduling. הגדרות של Protobuf וספריות פלטפורמה
OEM (משלב מערכות) ההגדרה מגדירה את הערכים הקונקרטיים של כל הגדרה קבועה מראש, למשל מה המשמעות של ELEVATED בחומרה ספציפית, ושולטת בהגדרה בכל המערכת. /product/etc/lifecycle_config.textproto
מפתח שירות בוחרים את השם המתאים של ההגדרה הקבועה מראש ללוגיקה ורושמים את הנתיב scheduling_config.textproto במניפסט של חבילת השירות. scheduling_config.textproto וגם sdv_service_bundles_manifest.textproto

תהליך עבודה טכני

  1. שילוב פלטפורמות: יצרן הציוד המקורי מגדיר את lifecycle_config.textproto הספציפי לרכב. בקובץ הזה מוגדרים פרופילי התזמון (הגדרות קבועות מראש) ברמת המערכת, והם ממופים למאפייני תזמון ספציפיים של Linux על סמך חומרת היעד.
  2. פיתוח חבילת שירותים: המפתח מאגד scheduling_config.textproto בחבילת ה-APEX שלו, וממליץ על הגדרה קבועה מראש לוגית (לדוגמה, ELEVATED) ומגדיר את כל שמות השרשורים הפנימיים.
  3. שילוב של חבילת שירותים: במהלך שלב שילוב הרכב, יצרן הציוד המקורי בודק את ההגדרה הקבועה מראש המומלצת של המפתח. יצרן ה-OEM יכול לשמור את הפרופיל המומלץ או לבטל אותו, למשל להחליף שירות ELEVATED בגרסה NORMAL, כדי לשפר את היציבות הכוללת של המערכת לפני חתימת ה-APEX.
  4. פתרון מאפיינים בזמן ריצה: כששירות מופעל, מנהל ה-LM מזהה את ההגדרה הקבועה מראש המורשית מתוך המניפסט של השירות ומאחזר את מאפייני הלינוקס התואמים מתוך הגדרת המערכת של יצרן הציוד המקורי.
  5. סנכרון ואכיפה של הפעלה: מודול LM מחיל את המאפיינים שנפתרו על תהליך השירות לפני שהוא מסמן לו להמשיך את הביצוע באמצעות פרוטוקול האות וההמשך.

מושגי ליבה

המושגים הבאים הם מרכזיים במסגרת התזמון של SDV.

תזמון של הגדרות קבועות מראש

הגדרות קבועות מראש של תזמון הן המנגנון העיקרי לניהול QoS ב-SDV. במקום להגדיר פרמטרים גולמיים של תזמון ב-Linux, המפתחים מפנים להגדרות קבועות מראש מוגדרות מראש לפי שם. בזמן הריצה, מנהל הזיכרון ממפה את השמות הלוגיים האלה למאפייני תזמון קונקרטיים של Linux.

ההגדרות הקבועות מראש הבאות מוגדרות כדוגמה ב-lifecycle_config.textproto:

שם ההגדרה הקבועה מראש מדיניות תזמון ערך nice טיפוסי תרחיש שימוש אופייני
NORMAL SCHED_OTHER 0 שירותים רגילים (מיזוג אוויר, מדיה, הגדרות)
ELEVATED SCHED_OTHER -10 רכיבי ליבה ותשתית של המערכת
IDLE SCHED_IDLE 19 ניתוח נתונים ברקע ורישום ביומן שאינו קריטי
CUSTOM בהגדרת משתמש -20 (התחלתי) שירותים שנדרשת לגביהם מדיניות בזמן אמת או שיוך

כשמחילים הגדרה קבועה מראש, מנהל הרישיונות משתמש בקריאת המערכת setpriority כדי להגדיר את הערך nice ברמת התהליך. ההגדרה הזו משפיעה על חלק המעבד היחסי שהתהליך מקבל במהלך התחרות, במסגרת מתזמן ה-CFS (Completely Fair Scheduler) של לינוקס שמוגדר כברירת מחדל.

הרשאות ואבטחה

כדי למנוע העלאת עדיפות לא מורשית, פלטפורמת SDV משתמשת במודל אבטחה מדורג שמבוסס על דומיינים של SELinux ועל יכולות של Linux.

דומיינים של אבטחה

  • untrusted_service_bundle: דומיין ברירת המחדל להגדרות קבועות מראש רגילות (NORMAL, ‏ ELEVATED, ‏ IDLE). ליבת המערכת מגבילה את התהליכים בדומיין הזה, ומונעת מהם לשנות את פרמטרי התזמון שלהם.
  • priority_service_bundle: מוענק לכל חבילת שירותים שמשתמשת בהגדרה קבועה מראש שבה is_privileged: true מוגדר ב-lifecycle_config.textproto ברמת המערכת. המעבר לדומיין הזה מעניק לתהליך את היכולת CAP_SYS_NICE, ומאפשר לו לנהל את הקצאת המשאבים שלו.

היכולת CAP_SYS_NICE

הפלטפורמה מעניקה את היכולת CAP_SYS_NICE לתהליכים בדומיין priority_service_bundle. ההרשאה הזו מאפשרת לתהליך לבצע את הפעולות הבאות:

  • להגדיל את ערך המאפיין nice מעבר לערך הראשוני שהוקצה לו.
  • משנים את מדיניות התזמון שלו לכיתות בזמן אמת כמו SCHED_FIFO או SCHED_RR.
  • מגדירים את הקצאת הליבה באמצעות sched_setaffinity.
  • הגדרת פרמטרים מיוחדים של תאריכי יעד ל-SCHED_DEADLINE.

הגבלת היכולת הזו לדומיין ייעודי מגנה על איזון התזמון בכל המערכת, כי היא מגבילה את השיבושים לשירותים שאושרו במפורש.

מדריך להגדרות

בקטע הזה מוסבר איך להגדיר את המערכת ליצרני ציוד מקורי (OEM) ולמפתחי שירותים.

מדריך OEM: הגדרות קבועות מראש למערכת כולה

יצרן הציוד המקורי מגדיר פרופילים של תזמון ב-/product/etc/lifecycle_config.textproto. הפלטפורמה מספקת דוגמה בכתובת lifecycle_management/config/lifecycle_config.textproto שיצרני ציוד מקורי (OEM) צריכים להתאים לפי החומרה של הרכב.

דוגמה: הגדרה קבועה מראש של נתונים בזמן אמת

יצרן ציוד מקורי (OEM) יכול להגדיר CRITICAL הגדרה מראש לשירותים שקשורים לבטיחות, שאסור שאפליקציות רגילות יפריעו להם:

# lifecycle_config.textproto
scheduling_presets {
  name: "CRITICAL"
  is_privileged: true
  thread_scheduling_configuration {
    policy: 1      # SCHED_FIFO
    priority: 80   # High real-time priority
  }
}

מדריך למפתחים: הגדרה של חבילת שירות

מפתחי שירותים ממליצים להגדיר מראש שמות לוגיים של שרשורים בקובץ scheduling_config.textproto. כדי שהפלטפורמה תוכל לגלות את הקובץ הזה, צריך לרשום את הנתיב שלו בקובץ sdv_service_bundles_manifest.textproto.

דוגמה: רישום של קובץ Manifest

# sdv_service_bundles_manifest.textproto
service_bundle_entries {
  name: "SensorService"
  scheduling_config_path: "configs/scheduling_config.textproto"
}

דוגמה: שימוש בהגדרות קבועות מראש רגילות

ברוב השירותים, מספיק להפנות לשם מוגדר מראש ב-scheduling_config.textproto:

# configs/scheduling_config.textproto
scheduling_preset_name: "ELEVATED"

דוגמה: תזמון של שרשורי worker שנוצרו על ידי שירות

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

אפשר להשתמש בהגדרת הרשאות ידנית רק בשירותים עם הרשאות מיוחדות שמשתמשים במטא-נתונים האלה כדי להגדיר מאפיינים לשרשורים פנימיים של עובדים:

# configs/scheduling_config.textproto
scheduling_preset_name: "CUSTOM"

# Map of logical thread names to their attributes (propagated as metadata)
thread_scheduling_configuration {
  key: "sensor-processing-thread"
  value {
    policy: 1        # SCHED_FIFO
    priority: 50
    cpu_affinity_ids: [2, 3]  # Pin to specific cores
  }
}

התנהגות המערכת ואכיפה

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

סנכרון של סטארטאפים

כדי למנוע משירות לפעול בעדיפות שגויה (גם במהלך שלב האתחול שלו), מנהל הרישוי (LM) והכלי להפעלת חבילות שירותים (SBR) משתמשים בפרוטוקול סנכרון מסוג 'אות והמשך':

  1. יצירת תהליך: ה-LM מבצע פיצול של תהליך ה-SBR. בשלב הזה, תהליך הצאצא של SBR פועל אבל מיד נכנס למצב חסימה, וממתין לאות ב-stdin שלו.
  2. החלת מאפיין: בזמן שהתהליך הצאצא חסום, מנהל הזיכרון משתמש בקריאת המערכת setpriority כדי להחיל את הערך nice המבוקש ומגדיר את מדיניות התזמון (לדוגמה, SCHED_IDLE).
  3. מעבר אבטחה: מנהל ה-LM מבצע את מעבר הדומיין של SELinux, ומעביר את התהליך הצאצא לדומיין untrusted_service_bundle או priority_service_bundle.
  4. אות: רק אחרי שכל הפרמטרים מוחלים בהצלחה, מודל ה-LM שולח אות של בייט אחד אל stdin של הילד או הילדה.
  5. ביצוע: ה-SBR מקבל את האות ומתחיל לטעון את ספריות השירות ולהפעיל את ה-methods של מחזור החיים.

ההשפעה על ה-thread הראשי ומחזור החיים

הפלטפורמה מסנכרנת לפני טעינת ספריות השירות, וכך שומרת על העדיפות המבוקשת של ה-thread הראשי לביצוע בכל הקריאות החוזרות של מחזור החיים:

  • onCreate: כל הקצאות המשאבים הראשוניות והזרקת התלות מתבצעות בעדיפות הנכונה.
  • onStart: ההגדרה הקבועה מראש שולטת במעבר למצב פעיל ובכל לולאות העבודה הראשוניות.
  • onStop ו-onDestroy: הפלטפורמה מבצעת פעולות ניקוי באותה עדיפות כדי למנוע מצב של חוסר משאבים לפעילויות קריטיות של המערכת במהלך כיבוי.

מאגר של פרוטוקולי Thread ב-Binder וירושה של עדיפות

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

כוונון עדין ברמת השרשור

חבילות שירותים שנדרש בהן בקרה מדויקת (לדוגמה, לולאות עיבוד בזמן אמת) צריכות להחיל הגדרות על השרשורים שלהן באופן ידני. כדי להחיל הגדרות ברמת השרשור, פועלים לפי השלבים הבאים:

  1. לבקש הגדרה קבועה מראש עם הרשאות מיוחדות (כאשר הערך של is_privileged: true מוגדר).
  2. משתמשים בפונקציה get_scheduling_configuration מהספרייה sdv_service_bundles_scheduling כדי לקרוא את thread_scheduling_configuration.
  3. החלת מאפיינים על שרשורי עובדים באמצעות sched_setattr.

אכיפה של SELinux ויכולות

הפלטפורמה משתמשת ב-SELinux וביכולת CAP_SYS_NICE של Linux כדי לאכוף הגדרות קבועות מראש של תזמון:

  • בשירותים שמשתמשים בהגדרות קבועות מראש כמו NORMAL או IDLE, תזמון מוגדר על ידי LM במהלך ההפעלה. בשירותים האלה אין אפשרות CAP_SYS_NICE, ואי אפשר לשנות את העדיפות או המדיניות שלהם.
  • לשירותים שמשתמשים בהגדרה קבועה מראש עם הרשאות מיוחדות (is_privileged: true) מוענקת יכולת CAP_SYS_NICE. כך הם יכולים לשלוט באופן ידני בתזמון של השרשורים הפנימיים שלהם, כפי שנדרש למשימות בזמן אמת.

אימות ודוגמאות

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

דוגמה לתזמון QoS

הדוגמה הזו, שנמצאת ב-samples/qos_scheduling, כוללת כמה שירותים לבדיקת ביצועים שנועדו לפעול במקביל ולדווח על ההתקדמות שלהם.

  • PerformanceTesterNormal: הרצה עם ההגדרה הקבועה מראש NORMAL.
  • PerformanceTesterElevated: הרצה עם ההגדרה הקבועה מראש ELEVATED.
  • PerformanceTesterRealtime: משתמש בהגדרה הקבועה מראש CUSTOM כדי להחיל SCHED_FIFO על השרשורים הפנימיים של העובד.
  • PolicyOffender: שירות אבחון שמנסה להגדיר עדיפות בזמן אמת תוך שימוש בהגדרה קבועה מראש של NORMAL. האימות הזה נועד לוודא שהפלטפורמה חוסמת בהצלחה העלאות לא מורשות.

הפעלת חבילת האימות

  1. מפעילים את הגדרת התיאום הספציפית ל-QoS:

    adb shell setprop persist.sdv.orchestrator_config_path /etc/orch/vm_qos_scheduling_orch_config.textproto

  2. מפעילים מחדש את המכשיר כדי להפעיל את השירותים בתחומי התזמון המתאימים:

    adb reboot

  3. מסננים את היומנים כדי לראות את תוצאות הביצועים ההשוואתיות:

    adb logcat | grep sdv_sample_qos_common

    שירות PerformanceTesterElevated מדווח על מספר יחידות עבודה גבוה משמעותית בהשוואה ל-PerformanceTesterNormal. השגיאות EPERM או SELinux denial נכללות ביומנים של שירות PolicyOffender.

תאימות לדורות קודמים

  • לצורך תאימות לאחור, כל חבילת שירות מדור קודם שצוין בה scheduling_config_path במניפסט, אבל לא צוין בה scheduling_preset_name בקובץ ההגדרות, נחשבת אוטומטית לשירות עם הרשאות. כך נשמרות היכולות הנדרשות (לדוגמה, CAP_SYS_NICE) לשירותים ישנים יותר שמסתמכים על כוונון ידני של השרשור.
  • הודעת ההגדרה הבסיסית DeadlineSchedulingConfiguration מתוזמנת לשינוי שם בגרסה עתידית. השם הנוכחי הוא היסטורי וכבר לא משקף בצורה מדויקת שההודעה מטפלת בכל סוגי התזמון, ולא רק בתזמון של מועדים אחרונים.