42
הההההה ההההה ההההה3 ההה ההה ההההה הההההה ההה ההההההה

מערכות הפעלה

  • Upload
    anahid

  • View
    68

  • Download
    5

Embed Size (px)

DESCRIPTION

מערכות הפעלה. תרגול 3 קלט פלט בסיסי תקשורת בין תהליכים. אדמיניסטרציה. אתר הקורס: http://www.cs.biu.ac.il/~shpiget/OS / הגשות: תרגיל ראשון - תאריך הגשה 14.03.2005 שאלות – ראו FAQ באתר הקורס האם הערך החוזר בתרגיל1 הוא בהכרח Short ? לאן יש להגיש? - PowerPoint PPT Presentation

Citation preview

Page 1: מערכות הפעלה

מערכות הפעלה

3תרגול קלט פלט בסיסי

תקשורת בין תהליכים

Page 2: מערכות הפעלה

תירגול 3 - מערכות הפעלה 2

אדמיניסטרציה:אתר הקורס

http://www.cs.biu.ac.il/~shpiget/OS/:הגשות

14.03.2005תרגיל ראשון - תאריך הגשה שאלות – ראוFAQבאתר הקורס

הוא בהכרח 1האם הערך החוזר בתרגיל Short??לאן יש להגיש

-כל סטודנט מגיש באופן עצמאי ע"י שימוש בSubmitexתוכנות שיש להגיש בנפרד לשני תרגילים!2 מכיל 1תרגיל שימו לב לשמות הספריות להגשהEx1_Fork Ex1_Shell שם הקבצים להגשה הםexec1.c עבור Fork-ו ,exec2.c עבור Shell

Page 3: מערכות הפעלה

תירגול 3 - מערכות הפעלה 3

נושאים שיכוסו

קלט/פלט של תהליכיםתקשורת וסנכרון בין תהליכים

מבואpipesהכוונת קלט ופלטFIFOs – Named Pipes

Page 4: מערכות הפעלה

תירגול 3 - מערכות הפעלה 4

Linux (1)קלט/פלט של תהליכים ב-

ק/פ של תהליך מול התקן נעשה תוך שימוש במערך שלdescriptors

לכל תהליך ישנה טבלה, ששמה Process Descriptor Table - PDT-אשר מנוהל ע"י ה OS.

כל כניסה בטבלה מצביעה על אובייקט ניהולfile) object מטעם (descriptorהתהליך עבור ההתקן המקושר ל-

-קוד תהליך ניגש להתקן דרך הdescriptor.אובייקט הניהול מתופעל ע"י גרעין מערכת ההפעלה בלבד

מחוון הקובץ" הוא חלק מאובייקט הניהול ומצביע למקום ספציפי בקובץ"הפתוח, כלומר הנתונים הבאים לקריאה / כתיבה מההתקן

-התקן המופעל באמצעות הdescriptor ,יכול להיות קובץ, התקן חומרה ערוץ תקשורת או כל דבר שניתן לכתוב ו/או לקרוא נתונים אליו וממנו

-ממשק ההתקשרות עם ההתקן דרך הdescriptor הינו אחיד, ללא תלות בסוג ההתקן

Page 5: מערכות הפעלה

תירגול 3 - מערכות הפעלה 5

Linux (2)קלט/פלט של תהליכים ב--ערכי הdescriptors הבאים מקושרים להתקנים הבאים כברירת

מחדל:0) stdinמקושר לקלט הסטנדרטי, בדרך-כלל המקלדת - (

פעולות הקלט המוכרות, כדוגמתscanf() ודומותיה, הן למעשה פעולות של קריאה stdinמהתקן הקלט הסטנדרטי דרך

1) stdoutמקושר לפלט הסטנדרטי, בדרך-כלל תצוגת טקסט במסוף - ( פעולות הפלט המוכרות, כדוגמתprintf() ודומותיה, הן למעשה פעולות של כתיבה

stdoutלהתקן הפלט הסטנדרטי דרך

2) stderr מקושר לפלט השגיאות הסטנדרטי, בדרך-כלל גם הוא תצוגת - (טקסט במסוף

-ניתן לשנות את קישור הdescriptors להתקנים באופן דינמי, כפי שנראה בהמשך

Page 6: מערכות הפעלה

תירגול 3 - מערכות הפעלה 6

Linux (3)קלט/פלט של תהליכים ב--תחילת עבודה עם התקן היא ע"י קישור ההתקן לdescriptor

()openבפעולת -הdescriptorפתוח", כלומר מקושר להתקן" -הdescriptors 0,1,2פתוחים מתחילת ביצוע התהליך

-בסיום העבודה עם ההתקן מנותק הdescriptor מההתקן ()closeבפעולת

-הdescriptorסגור", כלומר לא מקושר להתקן" -כל הdescriptors הפתוחים של תהליך נסגרים באופן

אוטומטי ע"י מערכת ההפעלה בסיום התהליך עם זאת, מומלץ לבצע סגירה מסודרת בקוד בכל סיום שימוש

descriptorב- אין צורך לסגורdescriptors / פתוחים המקושרים לערוצי הקלט / פלט

שגיאות הסטנדרטיים (אלא אם רוצים לחבר אותם להתקנים אחרים)

Page 7: מערכות הפעלה

תירגול 3 - מערכות הפעלה 7

)1קריאות מערכת בסיסיות (

()openפתיחת התקן לגישה – #include <sys/types.h>#include <sys/stat.h>#include <fcntl.h> //Last Arg. is Opt. for O_CREAT

onlyint open(const char *path, int flags [,mode_t mode]);

:ההתקן המבוקש (דרך פעולה path נפתח לגישה לפי (mode ולפי הרשאות המוגדרות ב-flagsהתכונות המוגדרות ב-

:במקרה של הצלחה – ה-ערך מוחזר descriptor המקושר הנמוך ביותר שהיה descriptorלהתקן שנפתח (ערך זה הוא ה-

)1סגור לפני פתיחת ההתקן), במקרה של כישלון – (-

Page 8: מערכות הפעלה

תירגול 3 - מערכות הפעלה 8

)2קריאות מערכת בסיסיות (

flags תכונות לאפיון פתיחת הקובץ. חייב להכיל אחת מהאפשרויות – הבאות:

O_RDONLYהקובץ נפתח לקריאה בלבד – O_WRONLYהקובץ נפתח לכתיבה בלבד – O_RDWRהקובץ נפתח לקריאה ולכתיבה –

ORכמו כן, ניתן לצרף תכונות אופציונליות שימושיות נוספות באמצעות (|) עם הדגל המתאים, למשל:

O_CREATצור את הקובץ אם אינו קיים – O_APPENDשרשר מידע בסוף קובץ קיים –

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

הבא. :ערך מוחזר

-במקרה של הצלחה – הdescriptor המקושר להתקן שנפתח. ערך זה הנמוך ביותר שהיה סגור לפני פתיחת ההתקןdescriptorהוא ה-

– 1(-במקרה של כישלון(

Page 9: מערכות הפעלה

תירגול 3 - מערכות הפעלה 9

mode_t קביעת הרשאות הקבצים ע"י קוד תיעשה לפי המפתח

הבא:

:0400כך שלמעשה הרשאות קריאה בלבד יהיו :0200הרשאות כתיבה בלבד כך שעבורR+W 0600 עבור עצמי ניתן את ההרשאה

UserGroupOthers

RWXRWXRWX

421421222120

Page 10: מערכות הפעלה

תירגול 3 - מערכות הפעלה 10

)3קריאות מערכת בסיסיות ( – סגירת גישה להתקןclose()

#include <unistd.h>int close(int fd);

-פעולה: סגירת הdescriptor fd לאחר הסגירה לא . שצוייןfdניתן לגשת להתקן דרך ה-

:פרמטריםfd-ה – descriptorהמיועד לסגירה

– 1(-. כישלון – 0ערך מוחזר: הצלחה(

Page 11: מערכות הפעלה

תירגול 3 - מערכות הפעלה 11

)4קריאות מערכת בסיסיות (

– קריאת נתונים מהתקןread()#include <unistd.h>ssize_t read(int fd, void *buf, size_t count);

פעולה: מנסה לקרוא עדcount בתים מתוך ההתקן המקושר buf לתוך החוצץ fdל--ייתכן שייקראו פחות מcountבתים

-למשל, אם נותרו פחות מ countבתים בקובץ ממנו קוראים ייתכן אף שלא ייקראו בתים כלל

) למשל, אם בקריאה מקובץ, מחוון הקובץ הגיע לסוף הקובץEOF( מחוון הקובץ מקודם בכמות הבתים שנקראו בפועל מההתקן, כך

שבפעולת הגישה הבאה לקובץ (קריאה, כתיבה וכד') ניגש לנתונים הנתונים שנקראו בפעולה הנוכחיתשאחרי

פעולת הקריאה תחסום את התהליך הקורא (תוריד אותו להמתנה) עדשיהיו נתונים זמינים לקריאה בהתקן

למשל: בקובץ, תהליך ימתין עד שהנתונים ייקראו מהדיסק

Page 12: מערכות הפעלה

תירגול 3 - מערכות הפעלה 12

)5קריאות מערכת בסיסיות (

:פרמטריםfd-ה – descriptorהמקושר להתקן ממנו מבקשים לקרוא bufמצביע לחוצץ בו יאוחסנו הנתונים שייקראו מההתקן – countמספר הבתים המבוקש –

:ערך מוחזר בהצלחה – מספר הבתים שנקרא מההתקן לתוךbuf אם .

read() נקראה עם count = 0 ללא קריאה0, יוחזר אם משתמשים בפעולה זו עלpipeעשויה להיווצר חסימה – 1(-בכישלון(

Page 13: מערכות הפעלה

תירגול 3 - מערכות הפעלה 13

)6קריאות מערכת בסיסיות (

– כתיבת נתונים להתקןwrite()#include <unistd.h>ssize_t write(int fd, const void *buf, size_t count);

פעולה: מנסה לכתוב עדcount בתים מתוך buf fdלהתקן המקושר ל-

ל-0בתלות בהתקן, ייתכן שייכתבו בין countבתים למשל, אם יש מספיק מקום פנוי

-בדומה לread() מחוון הקובץ מקודם בכמות הבתים ,שנכתבו בפועל, והגישה הבאה לקובץ תהיה לנתונים

שאחרי אלו שנכתבו גם פעולתwrite() יכולה לחסום את התהליך בפעולה על

התקנים מסוימים – למשל, עד שייתפנה מקום לכתיבה

Page 14: מערכות הפעלה

תירגול 3 - מערכות הפעלה 14

)7קריאות מערכת בסיסיות (

:פרמטריםfd-ה – descriptorהמקושר להתקן אליו מבקשים לכתוב bufמצביע לחוצץ בו מאוחסנים הנתונים שייכתבו להתקן – countמספר הבתים המבוקש לכתיבה –

:ערך מוחזר בהצלחה – מספר הבתים שנכתב להתקן מתוךbuf אם .

write() נקראה עם count = 0 ללא כתיבה0, יוחזר אם משתמשים בפעולה זו עלpipeעשויה להיווצר חסימה – 1(-בכישלון(

Page 15: מערכות הפעלה

תירגול 3 - מערכות הפעלה 15

)8קריאות מערכת בסיסיות (-הערות לread: ()

-ייתכן שייקראו פחות מcount-בתים (למשל, אם נותרו פחות מ count בתים בקובץ ממנו קוראים), וייתכן אף שלא ייקראו בתים כלל (למשל, אם בקריאה

))EOFמקובץ, מחוון הקובץ הגיע לסוף הקובץ ( מחוון הקובץ מקודם בכמות הבתים שנקראו בפועל מההתקן, כך שבפעולת

הנתונים שאחריהגישה הבאה לקובץ (קריאה, כתיבה וכד') ניגש לנתונים שנקראו בפעולה הנוכחית

פעולת הקריאה תחסום את התהליך הקורא (תוריד אותו להמתנה) עד שיהיונתונים זמינים לקריאה בהתקן

-הערות לwrite: () ל-0כתלות בהתקן, ייתכן שייכתבו בין count מספיק אין בתים (למשל, אם

מקום פנוי)-בדומה לread מחוון הקובץ מקודם בכמות הבתים שנכתבו בפועל, והגישה ,()

הבאה לקובץ תהיה לנתונים שאחרי אלו שנכתבו גם פעולתwrite – יכולה לחסום את התהליך בפעולה על התקנים מסוימים ()

למשל, עד שיתפנה מקום לכתיבה

Page 16: מערכות הפעלה

תירגול 3 - מערכות הפעלה 16

)1קלט ופלט – סגנון עבודה (

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

לדוגמה: אם רוצים לקרואk תוים לתוך החוצץ buf:נבצע את הקוד הבא ,total=0;

while (k > 0) {r = read(fd, buf [total], k);if (r < 0) {

/* handle error */}else{total+=rk –= r;}

}) ניתן בקלות להתאים את דוגמת הקוד שלעיל לטפל במצבים נוספיםEOF ,

סוף מחרוזת וכו') כדי לעבוד בצורה מסודרת מומלץ להגדיר פונקציות קריאה וכתיבה המכילות

קוד כנ"ל ולהשתמש בהן

Page 17: מערכות הפעלה

תירגול 3 - מערכות הפעלה 17

)2קלט ופלט – סגנון עבודה (

-ניתן לעבוד עם קבצים והתקנים גם דרך הAPI , המוכר משיעורי מבוא לתכנות:libcשל ספריית

fopen(), fclose(), fread(), fwrite(), [f]printf(), [f]scanf()'וכו ,

עם זאת, כדאי מאוד להימנע מלערבב קריאות בעבודה libcמערכת יחד עם קריאות לפונקציות

על אותו התקן :הסיבהlibc מנהלת מנגנוני בקרה משלה הכוללים

לקריאות המערכת הבסיסיות, מעלחוצצים וכו' ו"עקיפת" מנגנונים אלו יכולה לגרום לשיבוש הנתונים

Page 18: מערכות הפעלה

תירגול 3 - מערכות הפעלה 18

)1שיתוף ק/פ בין חוטים ותהליכים (

:טבלת ה-חוטים descriptors ,גלובלית לתהליך לכל החוטים שבומשותפתכלומר

מתארי התהליכים של כל החוטים מצביעים על אותוPDT:פעולת תהליכים fork() של טבלת עותק נוסף יוצרת

אצל תהליך הבןdescriptorsה-תהליך הבן יכול לגשת לאותם התקנים אליהם ניגש האב-הdescriptors כלומר מצביעים שותפים ששוכפלו הינם ,

לאותו אובייקט ניהול, ובפרט, חולקים את אותו מחוון קובץ בתים מה-10לדוגמה: אם האב קורא descriptor ואחריו הבן קורא

של האב. 10 הבתים שאחרי ה-3 בתים, אז הבן יקרא את 3הכתיבה מושפעת באופן דומה

Page 19: מערכות הפעלה

תירגול 3 - מערכות הפעלה 19

)2שיתוף ק/פ בין חוטים ותהליכים (

-תהליכים (וחוטים) המשתמשים בdescriptors שותפים או משותפים צריכים לתאם את פעולות

הגישה להתקן על-מנת שלא לשבש זה את פעולת זה הבעיה נפוצה במיוחד ב"שושלות משפחתיות" של

תהליכים: אבות ובנים, אחים, נכדים וכו' פעולתexecve() את טבלת אינן משנות ודומותיה

של התהליך, למרות שהתהליך descriptorsה-מאותחל מחדש

קבצים והתקנים פתוחים אינם נסגריםשימושי ביותר להכוונת קלט ופלט של תוכניות אחרות

Page 20: מערכות הפעלה

תירגול 3 - מערכות הפעלה 20

Linux (1)תקשורת בין תהליכים ב-

,בדומה למערכות הפעלה מודרניות אחרותLinux מציעה מגוון מנגנונים לתקשורת וסנכרון בין תהליכים

IPC = Inter-Process Communication לכאורה, ניתן היה להסתפק בתקשורת בין תהליכים דרך קבצים

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

-המנגנונים שLinux:מציעה למטרת תקשורת בין תהליכים כוללים pipes-ו FIFOs (named pipes): ערוצי תקשורת בין תהליכים באותה מכונה

ותהליכים pipeבסגנון יצרן-צרכן: תהליכים מסוימים מייצרים נתונים לתוך ה-אחרים צורכים את הנתונים

signals: איתותים - הודעות אסינכרוניות הנשלחות בין תהליכים באותה מכונה (וגם ממערכת ההפעלה לתהליכים) על-מנת להודיע לתהליך המקבל

על אירוע מסוים

Page 21: מערכות הפעלה

תירגול 3 - מערכות הפעלה 21

Linux (2)תקשורת בין תהליכים ב-System V IPC שם כולל לקבוצה של מנגנוני תקשורת שהופיעו :

ואומצו במהרה AT&T של חברת UNIXלראשונה בגרסאות . במסגרת קבוצה Linux הקיימים כולל UNIXעל-ידי מרבית סוגי ה-

זו נכללים:סמפורים) תורי הודעותmessage queues( "מנגנון המאפשר להגדיר "תיבות דואר –

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

יצירת איזור זיכרון מיוחד המשותף למרחבי הזיכרון של זיכרון משותף – מספר תהליכים. זו צורת התקשורת היעילה ביותר והמקובלת ביותר עבור

IPCיישומים הדורשים כמות גדולה של

Page 22: מערכות הפעלה

תירגול 3 - מערכות הפעלה 22

Linux (3)תקשורת בין תהליכים ב-sockets מנגנון סטנדרטי המאפשר יצירת ערוץ תקשורת :

) בין תהליכים היכולים להמצא גם duplexדו-כיווני (במכונות שונות. מנגנון זה מסתיר את התפעול הפיזי של

התקשורת בין המחשבים (רשת, כבלים וכו'). עלsockets ניתן ללמוד בהרחבה במסגרת הקורס "תקשורת

באינטרנט" וכן דרך מגוון אתרים, כדוגמת:

http://www.ecst.csuchico.edu/~beej/guide/net

-במהלך תרגול זה אנו נסקור את מנגנוני הpipes IPC כדוגמאות למנגנוני signalsוה-

Page 23: מערכות הפעלה

תירגול 3 - מערכות הפעלה 23

pipes-ב Linux (1)pipes (צינורות) הם ערוצי תקשורת חד-כיווניים המאפשרים

FIFO (First-In-First-Out)העברת נתונים לפי סדר הנתונים נקראים בסדר בו הם נכתבים

pipesמשמשים גם לסנכרון תהליכים, כפי שנראה בהמשך המימוש שלpipes-ב Linux הוא כאובייקטים של מערכת

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

-הגישה לpipe היא באמצעות שני descriptors אחד לקריאה :ואחד לכתיבה

Page 24: מערכות הפעלה

תירגול 3 - מערכות הפעלה 24

pipes-ב Linux (2)

היצירה שלpipe היא באמצעות קריאת המערכת pipe()-וה ,pipe הנוצר הינו פרטי לתהליך, כלומר אינו

נגיש לתהליכים אחרים במערכת לפיכך, הדרך היחידה לשתףpipe בין תהליכים שונים

היא באמצעות קשרי משפחה תהליך אב יוצרpipe ואחריו יוצר תהליך בן באמצעות fork()

שלו, descriptors באמצעות ה-pipe– לאב ולבן יש גישה ל-המצויים בשניהם

-לאחר סיום השימוש בpipe מצד כל התהליכים pipe) מפונים משאבי ה-descriptors(סגירת כל ה-

באופן אוטומטי

Page 25: מערכות הפעלה

תירגול 3 - מערכות הפעלה 25

pipes-ב Linux (3)

-למי מהתהליכים הבאים יש גישה לpipe שיוצר ?Aתהליך

-לכל התהליכים פרט לB

fork()ProcessA pipe() fork()

fork() fork()ProcessB

ProcessC

ProcessD

ProcessE

Page 26: מערכות הפעלה

תירגול 3 - מערכות הפעלה 26

()pipeקריאת המערכת :תחביר

#include <unistd.h>int pipe(int filedes[2]);

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

:פרמטריםfiledes-מערך בן שני תאים. ב – filedes[0] יאוחסן

filedes[1] שנוצר וב-pipe מה-לקריאה descriptorה-לכתיבה descriptorיאוחסן ה-

:בכישלון)1(- בהצלחה ו- 0ערך מוחזר

Page 27: מערכות הפעלה

תירגול 3 - מערכות הפעלה 27

pipe (1)קריאה וכתיבה ל-

פעולות קריאה וכתיבה מתבצעות באמצעותread()-ו write() pipe של ה-descriptorsעל ה-

ניתן להסתכל עלpipe כמו על תור FIFO עם מצביע קריאה יחיד (להוצאת נתונים) ומצביע כתיבה יחיד (להכנסת נתונים)

-כל קריאה (מכל תהליך שהוא) מהpipe .מקדמת את מצביע הקריאה באופן דומה, כל כתיבה מקדמת את מצביע הכתיבה

בדרך-כלל, תהליך מבצע רק אחת מהפעולות (קריאה או השני שאינו בשימושdescriptorכתיבה) ולכן נהוג לסגור את ה-

-הdescriptors ולכן שותפים של הקריאה בכל התהליכים הם , של הכתיבהdescriptorsיש לתאם בין הקוראים. כנ"ל לגבי ה-

Page 28: מערכות הפעלה

תירגול 3 - מערכות הפעלה 28

pipe (2)קריאה וכתיבה ל-

read-מ pipe:תחזיר -את כמות הנתונים המבוקשת אם היא נמצאת בpipe-פחות מהכמות המבוקשת אם זו הכמות הזמינה בpipeבזמן הקריאה 0) EOF-כאשר כל ה (write descriptors-נסגרו וה pipeריק את התהליך אם יש כותבים (תחסום write descriptors-ל (pipe-וה pipe

ריק. כאשר תתבצע כתיבה, יוחזרו הנתונים שנכתבו עד לכמות המבוקשתwrite-ל pipe:תבצע

-כתיבה של כל הכמות המבוקשת אם יש מספיק מקום פנוי בpipe) אם יש קוראיםread descriptors-ואין מספיק מקום פנוי ב (pipe ,

את התהליך עד שניתן יהיה לכתוב את כל הכמות תחסוםהכתיבה הדרושה

-הpipe-4 מוגבל בגודלו (כK-ולכן כתיבה ל (pipe שאין בו מספיק מקום פתוחים) תיכשלread descriptorsפנוי ושאין עבורו קוראים (

Page 29: מערכות הפעלה

תירגול 3 - מערכות הפעלה 29

pipeתכנית דוגמה –

#include <stdio.h<#include <unistd.h<

int main ()} int my_pipe[2];

int status; char father_buff[6];

int index = 0;

status = pipe(my_pipe); if (status == -1) }

printf("Unable to open pipe\n"); exit(-1);

{

status = fork(); if (status == -1) }

printf("Unable to fork\n"); exit(-1);

{

if (status == 0) { /* son process */ close(my_pipe[0]); write(my_pipe[1], "Hello", 6 * sizeof(char)); exit(0); } else { /* father process */ close(my_pipe[1]); wait(&status); /* wait until son process

finishes */ read(my_pipe[0], father_buff, 6); printf("Got from pipe: %s\n", father_buff); exit(0); }}

Page 30: מערכות הפעלה

תירגול 3 - מערכות הפעלה 30

)1הכוונת קלט ופלט (-אחד השימושים הנפוצים ביותר בdescriptors-בכלל וב pipes

Input/Outputבפרט הינו הכוונת הקלט והפלט של תכניות (Redirection(

ניתוב המידע המיועד להתקן פלט לתוך התקן אחר (למשל קובץ) אוהחלפת מקור המידע מהתקן קלט אחד באחר

-תוכנות הshell-ב Linux (ובמערכות הפעלה רבות אחרות) תומכות בהכוונת קלט ופלט באופן מובנה בפקודות שלהן

לדוגמה: התכניתls מדפיסה את רשימת הקבצים בספרייה הנוכחית הבאה:shell דרך פקודת ה-ls. ניתן להריץ את stdoutלתוך

$ ls-הפקודה הבאה תגרום לshell להכניס את הפלט של ls לקובץ myfile

$ ls > myfile

Page 31: מערכות הפעלה

תירגול 3 - מערכות הפעלה 31

)2הכוונת קלט ופלט (

-מה למעשה ביצע הshell(.. בערך) ?בתגובה לפקודה הקודמת status = fork();if (status == 0) {

close(1);fd = open(“myfile”, O_WRONLY…);execve(“/bin/ls”, …);

{באופן דומה ניתן לכוון את הקלט של תכנית להגיע מקובץ

לדוגמה: התכניתmore-קוראת נתונים מ stdin ומדפיסה אותם עם הפסקה בין עמוד לעמוד. הפקודה הבאה תגרום לה להדפיס את הקובץ

myfilemore < myfile

Page 32: מערכות הפעלה

תירגול 3 - מערכות הפעלה 32

)3הכוונת קלט ופלט ( קריאת המערכתdup()שימושית במיוחד לפעולות הכוונת קלט ופלט -

#include <unistd.h>int dup(int oldfd);

-פעולה: מעתיקה את הdescriptor oldfd-ל descriptor (סגור) אחר פנוי בטבלה.

-הdescriptor-החדש הינו ה descriptorהסגור בעל הערך הנמוך ביותר בטבלה ,לאחר פעולה מוצלחתoldfd-וה descriptor שותפים החדש הם

:פרמטריםoldfd-ה – descriptorהמיועד להעתקה – חייב להיות פתוח לפני ההעתקה

:ערך מוחזר-בהצלחה, מוחזר הערך של הdescriptorהחדש 1(-בכישלון מוחזר(

:קריאה דומהint dup2(oldfd, newfd) סוגרת את – newfd אם צריך newfd ומחזירה את newfd ל-oldfdומעתיקה את

Page 33: מערכות הפעלה

תירגול 3 - מערכות הפעלה 33

)4הכוונת קלט ופלט (

כאשר רוצים לכוון את הקלט או הפלט לבוא מתוך או להשלח בין התהליכים בתור התקן pipeאל תהליך אחר, משתמשים ב-

המחליף את התקן הקלט או הפלט לדוגמה: אם נרצה שהפלט שלls:יודפס בעמודים עם הפסקות

$ ls | more-מה יבצע הshell(..בערך) ?בתגובה לפקודה הנ"ל

pipe(MyFd);status = fork();if (status == 0) { /* first child */ close(1); //Def. Out dup(MyFd[1]); close(MyFd[0]); close(MyFd[1]); execve(“/bin/ls”,…);}

status = fork();if (status == 0) { /* second child */ close(0); //Def. In dup(MyFd[0]); close(MyFd[0]); close(MyFd[1]); execve(“/bin/more”,..);}close(MyFd[0]); close(MyFd[1]);

Page 34: מערכות הפעלה

תירגול 3 - מערכות הפעלה 34

pipe(pipe4_6.c)דוגמא נוספת ל-#include <stdio.h>#include <unistd.h>int main(int argc, char *argv[]){

int i = 0, status, fd[2];

if (argc < 3) { // To be used for CMD | CMD “a.out who sort”fprintf(stderr, "usage: %s <command> <command>\n", argv[0]);exit(1);

}if (pipe(fd) < 0) // create pipe{

perror("pipe call");exit(2);

}//… next slide

Page 35: מערכות הפעלה

תירגול 3 - מערכות הפעלה 35

pipeswitch (fork())דוגמא המשך - {

case -1: // errorperror("fork call");exit(1);

case 0: // child - the writing processdup2(fd[1], 1); // make stdout go to pipeclose(fd[0]);close(fd[1]);execlp(argv[1], argv[1], NULL);exit(3);

default: // parent - the reading processdup2(fd[0], 0); // make stdin come from pipeclose(fd[0]);close(fd[1]);execlp(argv[2], argv[2], NULL);exit(3);

}return (0); }

שימו לב: SIGPIPE כלומרpipeאם אחד התהליכים נכשל אזי האחר יקבל התראת סיגנל על כישלון ב-

Page 36: מערכות הפעלה

תירגול 3 - מערכות הפעלה 36

FIFOs-ב Linux (1)

FIFO הוא למעשה pipe בעל "שם" גלובלי שדרכו יכולים כל "ציבורי"pipeהתהליכים במכונה לגשת אליו –

נקרא גםnamed pipe

השימוש העיקרי תקשורת מבלי שיהיה ביניהם קשרי משפחהלמשל, כאשר תהליכי לקוח צריכים לתקשר עם תהליך שרת"אכן יש להסכים מראש על שם ה"מקשר

FIFO נוצר באמצעות קריאת המערכת mkfifo()-שם הFIFO,הוא כשם קובץ במערכת הקבצים

למרות שאיננו קובץ כלל" למשל/home/yossi/myfifo"-הFIFOמופיע במערכת הקבצים בשם שנבחר

Page 37: מערכות הפעלה

תירגול 3 - מערכות הפעלה 37

FIFOs-ב Linux (2) פתיחתFIFO לשימוש נעשית ע"י open()

-ניתן לבצע הן קריאה והן כתיבה לFIFO דרך אותו descriptor ערוץ) תקשורת דו-כיווני)

-תהליך שפותח את הFIFO לקריאה בלבד נחסם עד שתהליך לכתיבה, וההפךFIFOנוסף יפתח את ה-

-פתיחת הFIFO) לכתיבה וקריאה O_RDWR ,איננה חוסמת. עם זאת (יש לוודא שלכל קריאה יש כותב (אחרת תהליך יחיד ייחסם - קיפאון)

,כאובייקטים ציבוריים רביםFIFO אינו מפונה אוטומטית לאחר שהמשתמש האחרון בו סוגר את הקובץ, ולכן יש לפנותו

בצורה מפורשת באמצעות פקודות או קריאות מערכת )rmלמחיקת קבצים (למשל, פקודת

Page 38: מערכות הפעלה

תירגול 3 - מערכות הפעלה 38

FIFOs-ב Linux (3)

קריאת המערכתmkfifo()#include <sys/types.h>#include <sys/stat.h>int mkfifo(const char *pathname, mode_t mode);

פעולה: יוצרתFIFO המופיע במערכת הקבצים במסלול pathname והרשאות הגישה שלו הן mode

:פרמטריםpathname-שם ה – FIFOוגם המסלול לקובץ במערכת הקבצים mode-הרשאות הגישה ל – FIFO שנוצר. בדומה לכפי שהוסבר בשקף

.0600. ניתן להכניס ערך openההרחבה על :בכישלון)1(- בהצלחה, 0ערך מוחזר

Page 39: מערכות הפעלה

תירגול 3 - מערכות הפעלה 39

(Filename : half_duplex.h))1דוגמת ריצה (#define HALF_DUPLEX "/tmp/halfduplex“#define MAX_BUF_SIZE> 255

(hd_server.c)#include <stdio.h>#include <errno.h>#include <ctype.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <halfduplex.h> /* For name of the named-pipe */

int main(int argc, char *argv[]){ int fd, ret_val, count, numread; char buf[MAX_BUF_SIZE];

/* Create the named - pipe */ ret_val = mkfifo(HALF_DUPLEX, 0600);

// See Next slide

Page 40: מערכות הפעלה

תירגול 3 - מערכות הפעלה 40

} if ((ret_val == -1) && (errno != EEXIST)) )2דוגמת ריצה ( perror("Error creating the named pipe"); exit (1); }

/* Open the named pipe for reading */ fd = open(HALF_DUPLEX, O_RDONLY);

/* Read from the Named pipe */ numread = read(fd, buf, MAX_BUF_SIZE);

buf[numread] = '0';

printf("Half Duplex Server : Read From the pipe : %sn", buf);

/* Convert to the string to upper case */ count = 0; while (count < numread) { buf[count++] = toupper(buf[count]); } printf("Half Duplex Server : Converted String : %sn", buf);}

Page 41: מערכות הפעלה

תירגול 3 - מערכות הפעלה 41

(hd_client.c))3דוגמת ריצה (/* like prev prog #include <stdio.h> #include <errno.h> #include <ctype.h>#include

<unistd.h> #include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>*/#include <halfduplex.h> /* For name of the named-pipe */

int main(int argc, char *argv[]){ int fd; /* Check if an argument was specified. */ if (argc != 2) { printf("Usage : %s <string to be sent to the server>n", argv[0]); exit (1); }

/* Open the Named pipe for writing */ fd = open(HALF_DUPLEX, O_WRONLY);

/* Write to the pipe */ write(fd, argv[1], strlen(argv[1]));}

Page 42: מערכות הפעלה

תירגול 3 - מערכות הפעלה 42

שימוש בקוד הדוגמא-למעשה אנו רואים כאן "שרת" שפותח את הNamed-Pipe ולקוח שיעשה בו

ע"י תוכנת ה"שרת"FIFOשימוש, ראשית ניצור את ה-% hd_server &

-בנק' זו ייחסם השרת בקריאה משום שאין כותב לNamed-Pipe% hd_client hello

– "כעת יפתח ה"משתמשclient ויסיים את פעולתוFIFO ל-helloאת צד הכתיבה ויזין את המילה

:השרת, יקרא וידפיס את השורות הבאותHalf Duplex Server : Read From the pipe : helloHalf Duplex Server : Converted String : HELLO

?מה שכחנו"- למחוק את הקובץ מ/tmp/halfduplex"

?מה אם נרצה תקשורת דו-סטרית נצטרך לפתוחNamed-pipe !נוסף