1 / 33

תרגול מס' 7

תרגול מס' 7. כתיבת תסריטים ב- C-Shell בקרת תהליכים ב- Unix. תסריטים. הרצת תסריטים מבני בקרה ב- C-Shell דוגמאות השוואה בין C ו- C-Shell. אוטומטיזציה. נניח (מקרה היפותטי לחלוטין) שברשותנו קבצי בדיקה ופלט לתכנית שלנו וברצוננו לבדוק את נכונות התכנית מול קבצים אלו

courtney
Download Presentation

תרגול מס' 7

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. תרגול מס' 7 כתיבת תסריטים ב-C-Shell בקרת תהליכים ב-Unix

  2. תסריטים הרצת תסריטים מבני בקרה ב-C-Shell דוגמאות השוואה בין C ו-C-Shell מבוא לתכנות מערכות - 234122

  3. אוטומטיזציה • נניח (מקרה היפותטי לחלוטין) שברשותנו קבצי בדיקה ופלט לתכנית שלנו וברצוננו לבדוק את נכונות התכנית מול קבצים אלו • צריך לכתוב 3 פקודות לכל בדיקה • גם עם שימוש במנגנון ההיסטוריה הרצת הבדיקותמעיקה ולוקחת הרבה זמן מיותר • הפתרון:אוטומטיזציהשל הרצת הפקודות. ניצור קובץ אשר יכיל "תסריט" לפיו יורצו כל הפקודות לפי הסדר > (mtm_checkout< test1.in >! tmpout) >&! tmperr > diff expout1 tmpout > diff experr1 tmperr מבוא לתכנות מערכות - 234122

  4. הרצת תסריט בעזרתsource • ניתן להריץ קובץ המכיל פקודות C-Shell (להלן תסריט - script) על ידי הפקודה source • הפקודות יבוצעו ב-Shell הנוכחי כאילו נכתבו בשורת הפקודה אחת אחרי השניה > source run_tests Running test 1 Running test 2 Running test 3 run_tests echo Running test 1 (mtm_checkout < test1.in >! tmpout) >&! tmperr diff expout1 tmpout diff experr1 tmperr echo Running test 2 (mtm_checkout < test2.in >! tmpout) >&! tmperr diff expout1 tmpout diff experr1 tmperr echo Running test 3 (mtm_checkout < test3.in >! tmpout) >&! tmperr diff expout1 tmpout diff experr1 tmperr מבוא לתכנות מערכות - 234122

  5. תסריטי אתחול • בהתחברות של משתמש למערכת מורץ התסריט .login אשר בתיקית הבית של המשתמש • בפתיחת C-Shell חדש מורץ התסריט .cshrc • הרצות תסריטי האתחול מתבצעות באמצעות source, ולכן הן משפיעות על מצב ה-Shell .cshrc .login set path = ($path .) set savehist=1000 alias llls-l alias cdex2 cd ~mtm/public/1011a/ex2 alias GCC gcc-std=c99 -Wall \ -pedantic-errors -Werror # welcome message echo ------ Welcome `whoami` !-------- echo You are in `pwd` directory of \ `hostname` echo OS is `uname -s` # echo disk usage is `du -sh | cut -f1` echo `who | wc -l` users are logged in echo Today is `date` מבוא לתכנות מערכות - 234122

  6. הרצת תסריט כקובץ הרצה • ניתן להריץ תסריט כפקודה: • בתחילת התסריט יש להוסיף את השורה #!/bin/tcsh -f • #! מסמן ל-Unix שהשורה הראשונה בקובץ מגדירה את התכנית לביצוע שאר הפקודות בקובץ • /bin/tcshהוא שם התכנית לביצוע הפקודות, במקרה שלנו C-Shell • -fמונע מה-Shell להריץ תסריטי אתחול • בנוסף יש להוסיף הרשאת ריצה לקובץ • כעת ניתן להריץ את התסריט כמו תכנית רגילה • בניגוד להרצה באמצעות פקודת source התסריט יבוצע בתהליך Shell חדש אשר יסתיים בסוף ריצת התסריט מבוא לתכנות מערכות - 234122

  7. הרצת תסריט כקובץ הרצה • נמיר את תסריט הרצת הבדיקות שלנו לקובץ הרצה: • בעיה חדשה: התסריטמתחיל להסתבך, הוספתבדיקות נוספות משכפלתקוד בתסריט ולא נוחה (ייתכנו אלפי בדיקות) • פתרון: נשתמש במבני בקרה (תנאים ולולאות) בדומה לשפת C > chmoda+xrun_tests > ./run_tests Running test 1 Running test 2 Running test 3 run_tests #!/bin/tcsh -f echo Running test 1 (mtm_checkout < test1.in >! tmpout) >&! tmperr diff expout1 tmpout diff experr1 tmperr echo Running test 2 (mtm_checkout < test2.in >! tmpout) >&! tmperr diff expout1 tmpout diff experr1 tmperr echo Running test 3 (mtm_checkout < test3.in >! tmpout) >&! tmperr diff expout1 tmpout diff experr1 tmperr מבוא לתכנות מערכות - 234122

  8. while • ניתן ליצור לולאות whileב-C-Shell: while (<expression>)<command1><command2>...end • הפקודות בגוף הלולאה יבוצעו כל עוד <expression> ממשיך להתקיים • לולאות while כמו שאר מבני הבקרה ניתנות לביצוע ישירותמהטרמינל > set i=1 > while ($i <= 3) while? echo $i while? @ i++ while? end 1 2 3 > ./run_tests Running test 1 Running test 2 Running test 3 run_tests #!/bin/tcsh -f set i=1 while ($i <= 3) echo Running test $i (mtm_checkout < test$i.in \ >! tmpout) >&! tmperr diff expout$itmpout diff experr$itmperr end מבוא לתכנות מערכות - 234122

  9. foreach • לולאת foreach משמשת למעבר על רשימה בצורה נוחה foreach <varname> (<list>) <command1> <command2> ...end • <varname> הוא שם המשתנה שיכיל בכל פעם איבר מהרשימה • <list> היא רשימה של מחרוזות run_tests #!/bin/tcsh -f foreach test (test*.in) echo Running $test (mtm_checkout < $test >! tmpout) >&! tmperr diff expout_$test tmpout diff experr_$test tmperr end > ./run_tests Running test1.in Running test2.in Running test3.in מבוא לתכנות מערכות - 234122

  10. if • ניתן להגדיר ב-C-Shell משפטי תנאי בשתי גרסאות • בשורה יחידה ללא else: if (<expression>) <command> • עבור בלוקים של פקודות (עם אפשרות ל-else): if (<expression>) then[commands] [else[more commands] ]endif מבוא לתכנות מערכות - 234122

  11. ביטויים אפשריים ב-if ו-while • השוואת מחרוזותעל ידי == ו-=! • השוואת ערכים מספריים על ידי =>, =<, >, < • אם אחד הפרמטרים לאופרטור אינו ערך מספרי תתקבל שגיאה • התנאי -f <filename>בודק האםקיים קובץ בשם <filename> • התנאי -d <filename>בודק האםקיימת תיקיה בשם <filename> • ניתן להשתמש בסוגריים עבור קדימויות • ניתן להשתמש בפעולות חשבוניות עלערכים מספריים כמו +, -, * ו-/ • ניתן להשתמש באופרטורים לוגייםלהרכבת תנאים ||, && ו-! > set str1=Hello > if ($str1 == Hello) echo yes yes > if (7 < 20) echo yes yes > if (0 == 00) echo yes > if (0 <= 00) echo yes yes >if (-f a.txt) echo file exists > cat > a.txt Hello world! > if (-f a.txt) echo file exists yes > mkdirmtm > if ( !(-f b.txt && -d mtm) ) echo yes yes מבוא לתכנות מערכות - 234122

  12. התאמת מחרוזות • האופרטור ~= מאפשר התאמת מחרוזת לתבנית • הארגומנט השמאלי הוא מחרוזת רגילה • הארגומנט הימני הוא תבנית אשר יכולה לכלול את הסימנים *, ? ו-[ ] כמו שתואר עבור תבניות של שמות קבצים • האופרטור ~! הוא השלילה של ~= > if (ends_with_z =~ *[zZ]) echo match match > if ("no point in string" !~ *.*) echo no point no point > if ("point - . - in string" !~ *.*) echo no point > set file = test4.in > if ($file =~ test*.in) echo test file test file מבוא לתכנות מערכות - 234122

  13. switch • ניתן ליצור מבנה switchב-C-Shell: switch (<string>) case <pattern1>: <cshell commands> [breaksw] ... case <pattern_n>: <cshell commands> [breaksw] [default: <cshell commands>]endsw • הכללים ב-switch מקבלים תבניותוההתאמה מתבצעת כמו עבור אופרטור ~= • אם כמה כללים מתאימים ייבחר הכלל הראשוןשמתאים switch($c) case "[a-z]": echo small letter breaksw case "[A-Z]": echo big letter breaksw case "[0-9]": echo digit breaksw case '$': echo dollar sign breaksw default: echo neither letter nor digit endsw מבוא לתכנות מערכות - 234122

  14. goto • ניתן להשתמש במשפטי goto כמו ב-C goto <label> ... <label>: ... • שימוש במשפטי goto הוא תכנות רע (ללא קשר לשפת התכנות) ולא נהוג להשתמש בהם • השימוש ב-goto יוצר קוד "ספגטי" קשה להבנה מבוא לתכנות מערכות - 234122

  15. העברת פרמטרים בשורת הפקודה • כמו ב-C ניתן לגשת לפרמטרים המועברים בשורת הפקודה לתסריט • המשתנה argvמכיל את רשימת הפרמטרים לתסריט • argv[1] הוא הפרמטר הראשון (ולא שם התסריט) • דרך נוחה יותר לגשת לפרמטר ה-nהיא על ידי $n • $* תוחלף ברשימת כל הפרמטריםלתסריט • $0 תוחלף בשם התסריט echo_script #!/bin/tcsh -f echo command: $0 set number = 1 foreachparam ( $* ) echo parameter $number : $param @ number++ end > echo_scriptaaabbb ccc command: echo_script parameter 1 : aaa parameter 2 : bbb parameter 3 : ccc איך ניתן לדעת את מספר הפרמטרים שהתקבלו? מבוא לתכנות מערכות - 234122

  16. קריאת קלט • ניתן לקרוא שורה מהקלט הסטנדרטי על ידי $< • הביטוי $<יוחלףעל ידי C-Shell בשורת קלט שתיקלט מהקלט הסטנדרטי • בד"כ נשתמש בסוגריים כדי לשמור את כל שורת הקלט > set input=$< Hello > echo $input Hello < set line=$< Hello world > echo $line Hello <set line=($<) Hello world > echo $line Hello world מבוא לתכנות מערכות - 234122

  17. עבודה עם קבצים • לא ניתן ב-C-Shellלכתוב ולקרוא מקבצים בצורה ישירה כמו ב-C • כדי לאפשר עבודה עם קבצים נשתמש בהפניות קלט/פלט ותסריטי עזר > cat > file.txt The dingo ate your baby > main_script The first line is: The dingo ate your baby main_script auxiliary_script #!/bin/tcsh -f cat file.txt | auxiliary_script #!/bin/tcsh -f set line=($<) echo "The first line is:" echo "$line" מבוא לתכנות מערכות - 234122

  18. חלוקה פונקציונלית של תסריטים • מאחר ולא ניתן להגדיר פונקציות ב-C-Shell נחלק את הקוד שלנו לתסריטים שונים בקבצים נפרדים • שימו לב שניתן להשתמש ב-C-Shell כדי לערבב תסריטים עם תכניות שנכתבו בשפות שונות בקלות - מכאן מגיע כוחן של שפות תסריטים - scripting languages • ניתן להעביר פרמטרים לתסריטי עזר • בעזרת פרמטרים בשרות הפקודה • בעזרת pipeline • בעזרת קבצים זמניים • ניתן לקבל ערכים חזרה מתסריטי עזר • בעזרת פלט מתסריט העזר מבוא לתכנות מערכות - 234122

  19. העברת והחזרת ערכים • החזרת ערכים מתסריטי העזר יכולה להתבצע בעזרת • שימוש ב-backticks set result = `helper_script` • העברה לתסריט אחר ב-pipeline helper_script | another_script • דרך קובץ זמני helper_script > temp • העברת פרמטרים לתסריטי עזר יכולה להתבצע בדרכים הבאות • בשורת הפקודה helper_script $arg1 $arg2 • בעזרת pipeline echo $arg1 $arg2 | helper_script • דרך קובץ זמני echo $arg1 $arg2 > temp helper_script < temp מבוא לתכנות מערכות - 234122

  20. דוגמה • נתון קובץ בשם football.txt המכיל נתונים על שערים שהובקעו במשחקי כדורגל • כל שורה בקובץ מציינת שם של שחקן, מספר השערים שהבקיע במשחק שנערך בתאריך מסוים, שם הקבוצה בה הוא שיחק ושם הקבוצה היריבה • ברצוננו לכתוב תסריט בשם player אשר יקבל כפרמטר שם של שחקןוידפיס את כל השורות עבורומהקובץ football.txt ואת סכוםמספר השערים שהבקיע football.txt AlonMiz. 2 23/10/93 Macabi-Haifa Macabi-Tel-Aviv IzakZoh. 1 12/11/93 Macabi-Tel-Aviv Hapoel-Beer-Sheva Ronen Ha. 3 27/12/93 Hapoel-Tel-Aviv Macabi-Tel-AvivReuven A. 2 12/11/93 Macabi-Haifa Hapoel-Tel-Aviv EyalBer. 1 20/11/93 Macabi-Haifa Macabi-Tel-Aviv IzakZoh. 1 12/11/93 Macabi-Tel-Aviv Hapoel-Haifa AlonMiz. 2 26/10/93 Macabi-Haifa Beitar-Jerusalem IzakZoh. 2 12/12/93 Macabi-Tel-Aviv Macabi-Hiafa AlonMiz. 2 23/12/93 Macabi-Haifa Macabi-Pet-Tikva Ronen Ha. 3 27/11/93 Hapoel-Tel-Aviv Macabi-Haifa > player "AlonMiz." AlonMiz. 2 23/10/93 Macabi-Haifa Macabi-Tel-Aviv AlonMiz. 2 26/10/93 Macabi-Haifa Beitar-Jerusalem AlonMiz. 2 23/12/93 Macabi-Haifa Macabi-Pet-Tikva Total number of goals: 6 מבוא לתכנות מערכות - 234122

  21. פתרון • לא נוכל לקרוא את הקובץ football.txtישירות מתוך player ולכן ניעזר בתסריט עזר • ניצור את התסריט calc_total אשר יקבלאת השורות הרלוונטיות לשחקן וידפיס אתהשורות וסכום השערים calc_total #!/bin/tcsh -f set line = ($<) set sum = 0 while ($#line != 0) @ sum = $sum + $line[3] echo $line set line = ($<) end echo "total number of goals: $sum" player התבנית הכללית של עיבוד קלט התבנית הכללית של עיבוד קלט #!/bin/tcsh -f grep "$1" football | calc_total התבנית הכללית של עיבוד קלט מבוא לתכנות מערכות - 234122

  22. דוגמה נוספת • כתבו תסריט לדירוג שחקנים בשם scores אשר יקבל רשימה של שמות שחקנים בשורת הפקודה וידפיס את דירוג השחקנים לפי מספר הגולים שהבקיעו • לכל שחקן יש להדפיס את דירוגו, שמו ומספר הגולים שהבקיע • שני שחקנים שהבקיעו מספר זהה של גולים יקבל דירוג זהה • יש להדפיס את השחקנים ממוינים בדר יורד לפי מספר הגולים שהבקיעו > scores "AlonMiz." "IzakZoh." "Ronen Ha." "Reuven A." 1 AlonMiz. 6 1 Ronen Ha. 6 2 IzakZoh. 4 3 Reuven A. 2 מבוא לתכנות מערכות - 234122

  23. פתרון scores calc_score add_ranks #!/bin/tcsh -f set line = ($<) set place = 1 @ goals = $line[3] while ($#line != 0) if ($goals != $line[3]) then @ place++ @ goals = $line[3] endif echo $place $line set line = ($<) end #!/bin/tcsh -f @ i = 1 while ( $i <= $#argv) grep "$argv[$i]" football.txt | calc_score >>! temp @ i++ end sort -nrk3 temp | add_ranks if (-f temp) rm-f temp #!/bin/tcsh -f set line = ($<) set sum = 0 set player_name = ($line[1-2]) while ($#line != 0) @ sum += $line[3] set line = ($<) end echo $player_name$sum מבוא לתכנות מערכות - 234122

  24. השוואה בין C-Shell ל-C • C-Shell היא שפת תסריטים - scripting language • שפות תסריטים נוספות: Perl, Tcl, Python, Ruby. • C היא שפת תכנות מערכת -system programming language • שפות מערכת נוספות: C++, Java, C#. מבוא לתכנות מערכות - 234122

  25. השוואה בין C-Shell ל-C • יתרונותשל C-Shellעל C: • עבודה נוחה עם מחרוזות ומשתנים • נוח "להדביק" תכניות קיימות • קוד קצרמשמעותית לחלק מהמשימות • אין קומפיילר - לא צריך להכריז על דברים • חסרונותשל C-Shell לעומת C: • אין קומפיילר - אין בדיקותמאפשר באגים מסוכנים • איטית(לעתם פי כמה מאות) • נבחר ב-C-Shell עבור מטלות פשוטות וקצרות שזמן הביצוע שלהן לא קריטי set deposits = ($*) set account_balance = 100 foreach d ($deposits) @ acount_balance=$account_balance + $d end echo $account_balance מבוא לתכנות מערכות - 234122

  26. C-Shell - סיכום • כדי לחסוך ביצוע חוזר וידני של פעולות ניתן ליצור תסריטים המכילים רצף פקודות שימושי ולהריצם בעזרת source או הפיכתם לקובץ הרצה • ב-C-Shell קיימים מבני הבקרה while, foreach, if ו-switch המאפשרים כתיבת קוד מתקדם בתסריטים • ניתן לגשת לפרמטרים לשרות הפקודה של תסריט בדומה לתכנית ב-C • כדי לקרוא מהקלט הסטנדרטי ב-C-Shell נשתמש ב-$< • כדי לקרוא מקובץ ב-C-Shell נשתמש בתסריטי עזר ו-pipeline • כתיבת תסריטים מסתמכת על הדבקת תסריטים ופקודות שונות • נשתמש ב-C-Shell עבור מטלות פשוטות שאינן דורשות חישובים רבים, עבור שאר המטלות נמשיך להשתמש ב-C מבוא לתכנות מערכות - 234122

  27. בקרת תהליכים ב-Unix הרצה בחזית וברקע מבוא לתכנות מערכות - 234122

  28. ריבוי תהליכים ב-Unix • Unix היא מערכת הפעלה התומכת בריבוי תהליכים (multi-tasking) • חובה עבור מערכת שנועדה לשירות מספר רב של משתמשים בו זמנית • תהליך הוא הרצה של תכנית כלשהי • ניתן להריץ תכנית יחידה במספר תהליכים במקביל • בניגוד למנשק גרפי בו השליטה במספר תהליכים אינטואיטיבית עבור עבודה בטרמינל יש להכיר מספר פקודות וקיצורים מבוא לתכנות מערכות - 234122

  29. הרצה בחזית וברקע • Shell יחיד יכול להריץ מספר תהליכים בו זמנית • כל התהליכים מדפיסים את הפלט שלהם לערוצי הפלט הסטנדרטיים • רק תהליך אחד יכול להשתמש בערוץ הקלט הסטנדרטי • תהליך אשר מקושר לערוץ הקלט הסטנדרטי רץ בחזית • כדי להריץ תהליך בחזית יש להפעילו כרגיל > command • כל עוד תהליך רץ בחזית אין גישה ל-prompt ולא ניתן להכניס פקודות חדשות • תהליכים שאינם מקושרים לקלט הסטנדרטי רצים ברקע • ניתן להריץ תהליך ברקע על ידי הוספת & לסוף הפקודה > command & • תהליך יכול להיות גם מושהה, במצב זה התהליך אינו רץ אך מצבו נשמר בזיכרון ונוכל להמשיך את הרצתו כשנרצה מבוא לתכנות מערכות - 234122

  30. בדיקת מצב תהליכים • הפקודה jobs מדפיסה את רשימת התהליכים המורצים תחת ה-Shell > jobs • לכל תהליך מוצג מספר מזהה, מצבו ושם הפקודה • סימן ה-+ מייצג את התהליך "הנוכחי" • תהליך זה יהווה את ברירת המחדל לפקודות טיפול בתהליכים • סימן ה-- מייצג את התהליך הבא בתור להיות + כאשר מספר תהליכים מוציאים פלט בו זמנית הטרמינל מתבלגן במהירות > ./loop 1 & [1] 3692 > Loop 1! ./loop 2 & [2] 3711 Loop 2! Loop 1! loop #!/bin/tcsh-f while ( 1 ) sleep 1 echo Loop $1! end המספר בסוגריים המרובעים הוא מספר התהליך תחת ה-Shell מבוא לתכנות מערכות - 234122

  31. שליחת אותות לתהליך בחזית • כדי לשנות את מצב הריצה של התהליך הרץ בחזית ניתן לשלוח אותות בעזרת קיצורים מהמקלדת • Ctrl+C: הורג (מפסיק) את התהליך אשר בחזית • Ctrl+Z: משהה את התהליך אשר בחזית • התהליך מפסיק לרוץ אך מצבו נשמר מבוא לתכנות מערכות - 234122

  32. פקודות לניהול תהליכים • ניתן להחזיר תהליך לריצה בחזית בעזרת fg > fg [process] • ניתן להחזיר תהליך לריצה ברקע בעזרת bg > bg [process] • ניתן להשהות תהליך על ידי stop > stop <process> • ניתן להרוג תהליך על ידי הפקודה kill > kill <process> • ניתן לציין מספר תהליך ע"י % • ניתן להריץ את התהליך ששמו מתחיל ב-<str> ע"י %<str> • אם קיימים שני תהליכים מתאימים הפקודה תיכשל • עבור fg ו-bg: אם לא צוין מספר תהליך יוחזר התהליך שמסומן ב-+ מבוא לתכנות מערכות - 234122

  33. בקרת תהליכים ב-Unix - סיכום Ctrl+Z ריצה בחזית מושהה הרצה רגילה fg Ctrl+C bg kill stop fg ריצה ברקע מופסק הרצה עם & kill מבוא לתכנות מערכות - 234122

More Related