ΔΠΛ371 - Πξνγξακκαηηζκόο Σπζηεκάησλ Γηάιεμε 11: Δίζνδνο/Έμνδνο Φακεινύ Δπηπέδνπ (Low-Level I/O) Κεθάιαην 3 (Stevens & Rago) Κεθάιαην 5 (Stevens & Rago γηα επαλάιευε) Δεκήηξεο Ζετλαιηπνχξ 11-1
Πεξηερφκελν Δηάιεμεο Δηαρείξηζε Λαζψλ κε ηελ <errno.h> Εηζαγσγή ζηα Αξρεία θαη Σπζηήκαηα Αξρείσλ ζην Unix (Σχπνη Αξρείσλ, Partitions, i-nodes, blocks) Μέζνδνη Δπεμεξγαζίαο Αξρείσλ: Standard I/O vs. Υακεινχ Επηπέδνπ Θ/Ο Φακεινύ Δπηπέδνπ Ι/Ο (System Calls I/O): Θεσξία θαη Πξαθηηθή. Παξαδείγκαηα Υξήζεο 11-2
Δηαρείξηζε Λαζψλ ζηελ C Πφς δηατεηρίδεζηε ηα ιάζε ζηελ C εάλ ασηά είλαη Run-time Errors? Με printf? debugging? Είλαη γεληθά απνδεθηφ φηη δελ κπνξνχκε λα γλσξίδνπκε ηελ αηηία φισλ ησλ ιαζψλ εάλ απηά δελ νθείινληαη ζηελ ινγηθή ηνπ πξνγξάκκαηνο καο. π.ρ., έλα ιάζνο ζην ζχζηεκα αξρείσλ, ν δίζθνο έρεη ραιάζεη, ην αξρείν ζην νπνίν πξνζπαζνχκε λα γξάςνπκε είλαη θιεηδσκέλν απφ άιιν ρξήζηε, θηι ) Νόκος ηοσ Murphy: If anything can go wrong, it will Σηόρνο: Εάλ ζπκβεί θάπνην ιάζνο λα δψζνπκε ζηνλ ρξήζηε έλα κήλπκα ιάζνπο ην νπνίν λα αληηθαηνπηξίδεη ηελ πξαγκαηηθή αηηία. 11-3
Δηαρείξηζε Λαζψλ #include <errno.h> Η βηβιηνζήθε <errno.h> : System Error Numbers (/usr/include/errno.h) Μεηά απφ θάζε θιήζε ζπλάξηεζεο, ε errno πεξηέρεη έλα αθέξαην (errno), ην νπνίν εθθξάδεη ηη ιάζνο έρεη πξνεγεζεί. Τπάξρνπλ πεξηζζόηεξα από 100 errno (αθέξαηνη, δεο man errno ) νη νπνίνη πξνζδηνξίδνπλ ηα δηάθνξα είδε ιαζψλ. To errno ηίζεηαη απφ ηηο ζπλαξηήζεηο πνπ θαινχκε (π.ρ., fopen). Εάλ κηα ζπλάξηεζε δελ ην ζέηεη ξεηά ηφηε ην errno δηαηεξεί ηελ πθηζηάκελε ηνπ ηηκή κέρξη λα ην ζέζεη θάπνηα εληνιή ζην πξφγξακκα καο (errno=0;) ηελ ζπλέρεηα εθηππψλνπκε απηά ιάζε κε ηελ ζπλάξηεζε: void perror(char *str) Εθηππψλεη ηελ ζπκβνινζεηξά str θαη ηελ πεξηγξαθή ηνπ errno Εάλ ζέιεηε λα εθηππψζεηε θάπνην κνξθνπνηεκέλν str, ρξεζηκνπνηήζεηε ηελ γλσζηή sprintf(), π.ρ., char string[50]; int file_number = 0; sprintf( string, "file.%d", file_number ); perror(string); 11-4
Δηαρείξηζε Λαζψλ #include <errno.h> Σα αθφινπζα πξνγξάκκαηα πξνζπαζνχλ λα αλνίμνπλ έλα αξρείν ζε write mode κε ηελ Standard I/O. Πξνθαλψο ππάξρνπλ πάξα πνιιά ελδερφκελα ιάζε: δηθαηψκαηα πξφζβαζεο, πξνβιήκαηα πξφζβαζεο, ην αξρείν δελ ππάξρεη, θηι. To αξηζηεξφ πξφγξακκα δελ δίλεη θάπνην θαηαηνπηζηηθφ κήλπκα ιάζνπο ελψ ην δεμηά (κε ηελ perror) επηζηξέθεη ηελ αθξηβή αηηία. #include <stdio.h> int main () { FILE * pfile; char *filename= /home/a.txt"; pfile = fopen (filename,"w"); if (pfile==null) { printf( Unable to open %s, filename); exit(1); return 0; #include <stdio.h> #include <errno.h> int main () { FILE * pfile; char *filename= /home/a.txt"; pfile = fopen (filename,"w"); if (pfile==null) { perror(filename); exit(1); return 0; ΔΠΛ 371 Πξνγξακκαηηζκόο Σπζηεκάησλ Σεκείσζε: Εάλ ην errno==0 ηφηε ε perror(filename) εθηππψλεη Νν Error ; Δάλ δελ κπνξεί λα δεκηνπξγεζεί ην αξρείν ηόηε εθηππώλεη (θσδηθό 13) : $./program /home/a.txt: Permission Denied 11-5
Δηαρείξηζε Λαζψλ #include <errno.h> Μεξηθέο, απφ ηηο πάξα πνιιέο, ζηαζεξέο πνπ βξίζθνληαη κέζα ζην αξρείν header errno.h. EPERM: Operation not permitted ENOENT (2): No such file or directory EINTR: Interrupted system call EIO: I/O Error EBUSY: Device or resource busy EEXIST: File exists EINVAL: Invalid argument EMFILE: Too many open files ENODEV: No such device EISDIR: Is a directory ENOTDIR: Isn t a directory.. 11-6
Δηαρείξηζε Λαζψλ Παξάδεηγκα Εθηέιεζεο /* File: errors_demo.c */ #include <stdio.h> /* For fopen, printf */ #include <errno.h> /* For errno variable */ main() { FILE *fp; char *p; int stat; # Δληνιή Α fp = fopen("non_existent_file", "r"); if (fp == NULL) { /* Check for error */ printf("errno = %d\n", errno); perror("fopen"); Σπλέρεηα Απνηέιεζκα Δθηέιεζεο errno = 2 fopen: No such file or directory errno = 12 malloc: Not enough space errno = 13 unlink: Permission denied Σπλέρεηα # Δληνιή Β p = (char *) malloc(400000000); // ~400MB if (p == NULL) { /* Check for error */ printf("errno = %d\n", errno); perror("malloc"); # Δληνιή Γ /***** BE CAREFUL: unlink tries to remove a file so do not run this under root*/ stat = unlink("/etc/motd"); if (stat == -1) { /* Check for error */ printf("errno = %d\n", errno); perror("unlink"); /etc/motd: greeting displayed whenever a user logs on to the system Απηό ηζρύεη κόλν ζηνλ aias@, ελώ ζηηο κεραλέο ΔΠΛ ηνπ 371 εξγαζηεξίνπ Πξνγξακκαηηζκόο δελ ππάξρεη Σπζηεκάησλ όξην ζηελ malloc 11-7
Σα φξηα ησλ πξνγξακκάησλ Έιεγρνο κε ηελ ulimit Αλ θαη δελ έρεη άκεζε ζρέζε κε ηελ ζπδήηεζε, ηα φξηα κηαο δηεξγαζίαο είλαη ελδηαθέξνλ θαη πνιχ ρξήζηκα. Η εληνιή ulimit (bash built-in) ζέηεη/δηαβάδεη ηα φξηα (limitations) ζηηο πεγέο ηνπ ζπζηήκαηνο πνπ είλαη δηαζέζηκεο ζε θάζε δηεξγαζία ηνπ ζπζηήκαηνο dzeina@aias> ulimit -a core file size (blocks, -c) 1048575 data seg size (kbytes, -d) 131072 file size (blocks, -f) 1048575 max memory size (kbytes, -m) 32768 open files (-n) 2000 pipe size (512 bytes, -p) 64 stack size (kbytes, -s) 32768 cpu time (seconds, -t) unlimited max user processes (-u) 128 virtual memory (kbytes, -v) unlimited dzeina@cs4030> ulimit -a core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited max nice (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 16239 max locked memory (kbytes, -l) 32 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 max rt priority (-r) 0 stack size (kbytes, -s) 10240 cpu time (seconds, -t) unlimited max user processes (-u) 16239 ΔΠΛ 371 Πξνγξακκαηηζκόο virtual memory Σπζηεκάησλ(kbytes, -v) unlimited 11-8
Εηζαγσγή ζηα Αξρεία θαη ηα πζηήκαηα Αξρείσλ Τώξα αο κειεηήζνπκε αλαιπηηθόηεξα ηα ζσζηήκαηα αρτείφλ (filesystem) θαη ηελ δηατείρηζε αρτείφλ ζην UNIX. Αληίζηοητες αξρέο ηζρύνπλ θαη ζε άιια ιεηηνπξγηθά ζπζηήκαηα, επνκέλωο MHN ζεωξήζεηε όηη απηά βξίζθνπλ εθαξκνγή κόλν ζην UNIX. 11-9
Ση είλαη έλα Αξρείν; Μηα αθνινπζία από bytes, ρσξίο θακηά δνκή φζν αθνξά ην ιεηηνπξγηθφ ζχζηεκα (δει., ην Λ δελ αληηιακβάλεηαη ηελ ζεκαζηνινγία απηψλ ησλ bytes). Οη βαζηθέο ιεηηνπξγίεο είλαη απηέο ηεο αλάγλσζεο read() δεδνκέλσλ θαη ηεο γξαθήο write() δεδνκέλσλ. File Structure: Η αλαγλψξηζε ηεο δνκήο ησλ δεδνκέλσλ ελαπφθεηηαη απνθιεηζηηθά ζηελ εθαξκνγή (π.ρ. ην Acrobat γλσξίδεη ηελ εζσηεξηθή δνκή ελφο PDF αιιά φρη ελφο DOC). 11-10
Ση είλαη έλα Αξρείν: Παξάδεηγκα GIF Αο δνχκε πσο είλαη θσδηθνπνηεκέλν έλα αξρείν εηθφλαο GIF (Graphics Interchange Format). Π.ρ., ην PDF.gif $od -c pdf.gif # dump contents of file as characters rest in octal Αξρή 20 8 = 16 10 0000000 G I F 8 9 a - \0 - \0 Δ \0 \0 377 377 377 0000020 377 377 \0 377 \0 377 377 \0 \0 \0 377 377 \0 377 \0 \0 0000040 \0 377 \0 \0 \0 377 1 \0 ή ή ή Ξ Ξ Ξ Ζ Ζ 0000060 Ζ 204 204 204 s s s R R R \b \b \b 0000120 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 0000100 377 377 377 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 0000140 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0! σ 004 0000160 001 \0 \0 021 \0, \0 \0 \0 \0 \0 \0 \0 005 0000200 377 ` $ 216 Ρ a 236 h 232 222 κ x $ p, Ο 2200 204 034? 252 ν f 215 ά 256 237 p H, ή 034 Magic number Σν ζρήκα δείρλεη φηη νη εηθφλεο (φπσο θαη ΌΛΑ ηα αξρεία) είλαη νπζηαζηηθά κηα ζεηξά απφ bytes απνζεθεπκέλα ζηνλ καγλεηηθφ δίζθν. 11-11
Σχπνη Αξρείν ζην Unix Everything in Unix is a File Regular Files: Αξρεία Δεδνκέλσλ (txt, pdf, jpg, ) $ ls -al ~/.profile -rwxr----- 1 dzeina faculty 281 Jan 19 12:46. profile Directory Files: Αξρεία ζπζηήκαηνο γηα ηελ δηαηήξεζε ηεο δνκήο ηνπ ζπζηήκαηνο αξρείσλ. $ ls -al ~ grep public_html drwxr-sr-x 8 dzeina faculty 4096 Feb 19 22:53 public_html Character-Special Files: Υξεζηκνπνηνχληαη γηα λα αλαπαξαζηήζνπλ Serial I/O ζπζθεπέο (terminals, printers θαη networks) $ ls -al `tty` crw--w---- 1 dzeina tty 136, 1 Feb 21 11:36 /dev/pts/1 Block Special Files : Υξεζηκνπνηνχληαη γηα λα αλαπαξαζηήζνπλ Μαγλεηηθνχο Δίζθνπο, Cdroms, flash drives ζηα νπνία ε αλάγλσζε/γξαθή δεδνκέλσλ γίλεηαη ζε Blocks (π.ρ. 512-8192 bytes) $ ls -al /dev/hdc # ην /dev/cdrom brw-rw---- 1 root disk 22, 0 Feb 21 10:09 /dev/hdc Symbolic link Files: Σo αξρείν είλαη έλαο ζχλδεζκνο πνπ δείρλεη ζε θάπνην άιιν αξρείν $ ln -s public_html/index.html index.lnk ; ls -al index.lnk lrwxrwxrwx 1 dzeina faculty 22 Feb 21 12:07 index.lnk -> public_html/index.html Νamed Pipes (FIFO): Υξεζηκνπνηείηαη γηα επηθνηλσλία κεηαμχ δηεξγαζηψλ Θα ηα δνχκε αξγφηεξα ζην κάζεκα. $ mkfifo pipef; ls -al ΔΠΛ grep 371 pipef Πξνγξακκαηηζκόο Σπζηεκάησλ prw-r--r-- 1 dzeina faculty 0 Feb 21 11:42 pipef 11-12
Πσο απνζεθεχνληαη ηα αξρεία? Σα αξρεία απνζεθεχνληαη πάλσ ζηηο ζπζθεπέο απνζήθεπζεο (Μαγλεηηθνχο Δίζθνπο, FLASH, Σαηλίεο, Cdrom, DVDs, etc). File-System (Σύζηεκα Αξρείσλ): Μέξνο ηνπ ππξήλα ην νπνην πινπνηεί έλα ζχλνιν απφ δνκέο δεδνκέλσλ θπξίαο θαη δεπηεξεύνπζαο κλήκεο γηα ηελ απνζήθεπζε, ηεξαξρηθή νξγάλσζε, αλάθηεζε θαη επεμεξγαζία δεδνκέλσλ. To file system ζε κεξηθά Λ. Windows NT,2000,XP,Vista,7: FAT, FAT32, NTFS, Windows Future Storage (WinFS: File Org. with DBs!) Linux Local Ext2, Ext3, Ext4, Linux Distributed: NFS, AFS, MacOS: Hierarchical FS+, Google s Non-kernel: MacFuse CDROMs: ISO9960, Φσηνγξαθηθέο & Κηλεηά κε Flash Memory : FAT 512 bytes : Master Boot Record (or Volume Boot Record) 11-13
Disk Partitions Ο δίζθνο ρσξίδεηαη ζε partitions Γηα λα βξνχκε ηα partitions ζην UNIX ρξεζηκνπνηνχκε ηελ εληνιή df $ df Filesystem 1K-blocks Used Available Use% Mounted on /dev/mapper/volgroup00-logvolroot 2031440 609380 1317204 32% / /dev/mapper/volgroup00-logvoltmp 1015704 94252 869024 10% /tmp /dev/mapper/volgroup00-logvolvar 2031440 391220 1535364 21% /var /dev/mapper/volgroup00-logvolusr 5078656 3409680 1406832 71% /usr /dev/mapper/volgroup00-logvolopt 2031440 1378252 548332 72% /opt /dev/mapper/volgroup00-logvolusrlocal 507748 36197 445337 8% /usr/local /dev/sda1 101086 23619 72248 25% /boot tmpfs 517108 0 517108 0% /dev/shm csfs7.cs.ucy.ac.cy:/home/students NFS-mounted (Network File System) drives! 164288512 129185280 35103232 79% /home/students csfs1.cs.ucy.ac.cy:/home/faculty 278673504 237194208 27323520 90% /home/faculty 11-14
Partitions Δηαθνξεηηθά partitions κπνξνχλ λα έρνπλ δηαθνξεηηθά ζπζηήκαηα αξρείσλ. Έλα partition ζην UNIX έρεη ηελ πην θάησ κνξθή: Super block (Filesystem Metadata) File system type, Size, Status Information about other metadata structures 11-15
i-nodes ηελ αξρή θάζε partition βξίζθεηαη κηα ιίζηα κε i-nodes, ηα νπνία αλαγλσξίδνπλ κνλαδηθά ηα αξρεία ηνπ ζπγθεθξηκέλνπ partition. Έλα i-node πεξηέρεη ηηο πιεξνθνξίεο (κηα ζπιινγή απφ δηεπζχλζεηο δίζθνπ) έηζη ψζηε λα γλσξίδεη ν ππξήλαο απφ πνχ λα αλαθηήζεη ηα data/directory blocks θάπνηνπ αξρείνπ Γηα λα βξείηε ην i-node number ελφο αξρείνπ δψζηε ηελ εληνιή "ls -i". Απφ έλα πξφγξακκα κπνξνχκε λα βξνχκε ην i-node κέζσ ηνπ system call stat() αξγφηεξα. 11-16
Data/Directory Blocks Έλα αξρείν (regular ή directory) απνηειείηαη απφ κηα ζεηξά "blocks" θαη νλνκάδεηαη "data block" θαη "directory block" αληίζηνηρα. Σν data-block απνζεθεχεη Μέξνο ησλ πξαγκαηηθψλ δεδνκέλσλ ελφο αξρείνπ. Σν directory-block απνζεθεχεη Θ-node number θαη filename γηα θάζε αξρείν ή ππνθαηάινγν. Data Block Directory Block 11-17
Παξάδεηγκα Εχξεζεο Αξρείνπ κε i-nodes Πσο βξίζθεη ην ιεηηνπξγηθό ζύζηεκα (ην ππνζύζηεκα αξρείσλ) ηα πεξηερόκελα ελόο αξρείνπ /usr/test.c? Ξεθηλά απφ ην directory block κε i- node 2 (πξψην δηαζέζηκν i-node ζην i-list, ην νπνίν αληηζηνηρεί ζην / folder) Απφ εθεί βξίζθεη φηη ην usr έρεη σο i-node to 200. ηελ ζπλέρεηα => 4 => 202 => 6 => Σέινο βξίζθεη φηη ηα data blocks κε i-nodes 204 θαη 206 πεξηέρνπλ ηα δεδνκέλα ηνπ αξρείνπ. Data Block (rest are Directory Blocks 11-18
Παξάδεηγκα Εχξεζεο Αξρείνπ κε i-nodes ην πξνεγνχκελν παξάδεηγκα ην αξρείν /usr/test.c κε i-node 6 πεξηείρε κνλάρα 2 blocks (κε i-node 204 θαη 206). Τη γίλεηαη εάλ έλα αξρείν έρεη πνιιά blocks; Τπάξρεη αξθεηόο ρώξνο γηα λα απνζεθεπηνχλ όια ηα i-nodes ησλ blocks πνπ ζπζρεηίδνληαη κε ην αξρείν; Σν Τπνζχζηεκα Αξρείσλ ρξεζηκνπνηεί έλα ηεξαξρηθό ζρήκα ην νπνίν απνηειείηαη απφ δέλδξα δεηθηψλ βάζνπο 0 (direct, απηφ ην νπνίν είδακε ήδε), 1 (single), 2 (double), θαη 3 (triple) 2KB block <24ΚΒ <1ΜΒ <512ΜΒ < max supported file size Ι-Ννde Structure (πεξηζζφηεξα γηα ηελ δνκή απηή ζηελ επφκελε δηάιεμε) 11-19
Μέζνδνη Επεμεξγαζίαο Αξρείσλ Σψξα ζα δνχκε κεζφδνπο επεμεξγαζίαο ηνπ πεξηερνκέλνπ ησλ αξρείσλ. Σν ρακεινχ επηπέδνπ I/O δηεθπεξαηψλεηαη εθηειψληαο system calls (θιήζεης ζσζηήκαηος). Ι/Ο System Call: θιήζεηο πξνο ηνλ ππξήλα ηνπ ιεηηνπξγηθνύ ζπζηήκαηνο ν νπνίνο καο επηζηξέθεη έλα File Descriptor (FD) (νξνινγία Unix) ή File Handle (νξνινγία Windows). Όιε ε επεμεξγαζία ζηελ ζπλέρεηα γίλεηαη κέζω ηνπ FD. Ι-Ννde Structure on Disk c b d a Ι-Ννde Structure in Memory 11-20
Δηεξγαζίεο θαη Αξρεία Μέζα ζηελ Γηεξγαζία File Descriptor Table: Έλα γηα θάζε δηεξγαζία. Κάζε εγγξαθή ηνπ, ή νπνία αλαγλσξίδεηαη απφ ην fd (0,1, ), πεξηέρεη έλα δείθηε ζην open files table. (ειέγμεηε ην /proc/$$/fd/) Μέζα ζηνλ Ππξήλα Οpen Files Table: Μηα εγγξαθή δεκηνπξγείηαη φπνηε εθηειέζνπκε open(). Η εγγξαθή πεξηέρεη i) δείθηε ζην inode table, ii) offset κέζα ζην αξρείν (ην επνκελν read εθηειεηηαη απφ ην offset); iii) status (π.ρ. read, write, append) κε ην νπνίν αλνίμακε ην αξρείν. Inode Table: Κάζε αξρείν εκθαλίδεηαη κφλν κηα θνξά ζε απηφ ηνλ πίλαθα. 13-21
Μέζνδνη Επεμεξγαζίαο Αξρείσλ Απφ ηα πξνγξάκκαηα εθαξκνγψλ κπνξνχκε λα αλαθηήζνπκε ηα δεδνκέλα ησλ αξρείσλ κε δπν ηξφπνπο: α) Standard I/O Library (Procedure) Calls fopen, fclose, fread, putc, readc, etc. απηά ηα νπνία ρξεζηκνπνηνχζαηε κέρξη ηψξα ζηα δηάθνξα καζήκαηα πξνγξακκαηηζκνχ κε ρξήζε δνκήο FILE Απηή ε κέζνδνο ζπληζηάηαη κφλν γηα ηα regular αξρεία (φρη άιινπο ηχπνπο) β) Κιήζεηο Σπζηήκαηνο (System Calls) (e.g., open, close, read, write, lseek) κέζσ File Handler (int) Σα νπνία κνηάδνπλ κε library calls (θιήζεηο ζπλαξηήζεσλ βηβιηνζήθεο), κε ηελ δηαθνξά φηη ηα system calls εθηεινχληαη κέζα ζην kernel space αληί ζην user space. Επνκέλσο θιήζε ζε έλα system call δελ ζεκαίλεη απιά φηη ζα θάλνπκε jump ζε κηα άιιε εληνιή νξηζκέλε αιινχ ζην πξφγξακκα αιιά φηη ζα γίλεη context switching (ελαιιαγή δηεξγαζηψλ), έηζη ψζηε λα εθηειέζεη ΔΠΛ ην 371 kernel Πξνγξακκαηηζκόο ηελ αίηεζε Σπζηεκάησλ ζαο. 11-22
Standard IO vs. Systems Calls Τα Standard I/O stdio.h (ANSI C99) είλαη κηα βηβιηνζήθε ζπλαξηήζεσλ γηα πξφζβαζε ζε αξρεία απφ πξνγξάκκαηα C (ρξεζηκνπνηείηαη πέξα απφ ην UNIX) Σα Standard I/O θάλνπλ θιήζε ζπλάξηεζεο ηεο ηδίαο ηεο δηεξγαζίαο ελψ ηα System Calls θαινχλ ιεηηνπξγίεο ηνπ ππξήλα. Σα Standard I/O calls πινπνηνύληαη θαη απηά κέζσ ησλ System Calls! Σα Standard I/O είλαη πην εύθνια H Standard I/O δεκηνπξγεί έλα Stream (FILE *) ελψ ηα System Calls έλα File Descriptor H Standard I/O θάλεη buffering (BUFSIZE ηελ stdio.h).. αιιά δίδνπλ ιηγόηεξε ειεπζεξία, ή νπνία ρξεηάδεηαη ζην Systems Programming System Call Standard I/O call open fopen Δπαλάιεςε Standard I/O Calls: Κεθάιαην 5 Stevens & Rago Man stdio close fclose read/write fread/fwrite // used for binary I/O chunks of bytes rather char or line getchar/putchar // read a character from STDIN getc/putc // >> >>..from file fgetc/fputc // identical to getc/putc gets/puts // read a string from STDIN fgets/fputs // >> > > > > > from file scanf/printf // read formatted input from STDIN fscanf/fprintf // >> > > > > > from file lseek fseek // move to a specific location in a file 11-23
Πιενλέθηεκα ησλ System Calls USER SPACE KERNEL SPACE Πιενλέθηεκα System Call: Πιήξεο Έιεγρνο! Τινπνίεζε Λεηηνπξγηψλ πνπ δελ πξνζθέξνληαη απφ ηα Standard I/O (locking, buffering, IPC) Έιεγρνο ηνπ Buffering: Σν νπνίν είλαη πνιχ ζεκαληηθφ ζε ζπζηήκαηα βάζεσλ δεδνκέλσλ νπνπ ζέινπκε λα ρεηξηζηνχκε ην buffering κέζα ζηελ ηδία ηελ εθαξκνγή θαη φρη ην standard I/O. Interprocess Communication: Όηαλ πξνγξακκαηίδεηαη επηθνηλσλία κεηαμχ δηεξγαζηψλ κε ρξήζε ζσιήλσλ θαη ππνδνρψλ (ζα καο απαζρνιήζνπλ αξγφηεξα ζην κάζεκα ) 11-24
Μεηνλεθηήκαηα ησλ System Calls Δίλαη Πνιύ Αθξηβά! : Ελψ έλα procedure call ζέιεη κφλν κεξηθέο εληνιέο κεραλήο ελψ έλα system call ζα θάλεη ηα εμήο: Η ππφ εθηέιεζε δηεξγαζία δηαθφπηεηαη θαη ην state ηεο θπιάγεηαη. Σν Kernel (Λ) παίξλεη ηνλ έιεγρν ηνπ CPU θαη εθηειεί ην system call. To Kernel (Λ) δηαθφπηεηαη θαη ην state ηεο θπιάγεηαη ελψ ηαπηφρξνλα δίδεη ηνλ έιεγρν πίζσ ζηελ δηεξγαζία. Όκσο, ε νξζνινγηζηηθή ρξήζε ησλ system calls νδεγεί ζε απμεκέλε Απόδνζε θάηη ην νπνίν είλαη πνιύ ζεκαληηθό. System Dependent: Δηαθνξεηηθέο Τινπνηήζεηο Λ. ππνζηεξίδνπλ δηαθνξεηηθέο ιεηηνπξγίεο. Οπφηαλ ηίζεηαη ζέκα κεηαθεξζηκόηεηαο (Portability) ηνπ πεγαίνπ θψδηθα κε ηα system calls. Γπζθνιόηεξνο Πξνγξακκαηηζκόο: Με ηελ standard I/O, ε βηβιηνζήθε νξγαλψλεη ηηο θιήζεηο πξνο ηνλ ππξήλα κε έηζη ηξφπν πνπ ηα δεδνκέλα ζα κεηαθέξνληαη ζε πιήξε blocks απφ ηνλ δίζθν ζηελ κλήκε, ελψ κε ηα System Calls πξέπεη λα ην ρεηξηζηνχκε κφλνη καο. 11-25
System Calls for I/O Τπάξρνπλ 5 βαζηθά system calls ηα νπνία παξέρεη ην Unix γηα file I/O (ειέγμεηε ην man s 2 open) int open(char *path, int flags [, int mode ] ); int close(int fd); int read(int fd, void *buf, int size); int write(int fd, void *buf, int size); off_t lseek(int fd, off_t offset, int whence); Γηα λα έρνπκε πξφζβαζε ζε απηέο ηηο ζπλαξηήζεηο κέζσ ησλ πξνγξακκάησλ εθαξκνγψλ ρξεηάδεηαη λα ζπκπεξηιάβνπκε ηηο αθφινπζεο βηβιηνζήθεο // file control options: #include <fcntl.h> // standard symbolic constants and types for unix #include <unistd.h> 11-26
1) System Calls: Open()/Close() Άλοηγκα Αρτείοσ γηα αλάγλφζε/γραθή δεδοκέλφλ # Returns: File Descriptor if OK, -1 on error int open(const char *path, int flags [, int mode ] ) # Returns: 0 if OK, -1 on error int close(int filedes); 'path : Απφιπην ε ζρεηηθφ κνλνπάηη πξνο ην αξρείν Σα flags θαη mode δειψλνπλ πσο ζέινπκε λα ρξεζηκνπνηήζνπκε ην αξρείν (επφκελε δηαθάλεηα) Εάλ ν ππξήλαο απνδερζεί ηελ αίηεζε καο, ηφηε δεκηνπξγείηαη ν κηθξφηεξνο δπλαηφ ``file descriptor (FD)'' (ην νπνίν είλαη κηα αθέξαηα ηηκή γηα αξρείν). Οπνηεζδήπνηε κειινληηθέο αλαθνξέο ζην αξρείν γίλνληαη κέζσ ηνπ FD. (ζα εμεγεζεί αλαιπηηθφηεξα ζηελ ζπλέρεηα) To Linux 2.4.22 ζέηεη έλα hard limit απφ 1,048,576 FDs αλά δηεξγαζία. Απηφ νξίδεηαη απφ ηελ ζηαζεξά OPEN_MAX ζηελ βηβιηνζήθε limits.h (φπσο ηελ εληνιή $ulimit n) Εάλ ε open επηζηξέςεη -1, ηφηε δελ ηθαλνπνηήζεθε ε αίηεζε θαη κπνξνχκε λα ειέγμνπκε ηελ ηηκή ηεο κεηαβιεηήο "errno" γηα λα βξνχκε γηαηί (κε ηελ perror()). Θπκεζείηε φηη ΔΠΛ φηαλ 371 αλνίγεη Πξνγξακκαηηζκόο έλα πξφγξακκα Σπζηεκάησλ ηφηε ηξεηο FDs είλαη ήδε αλνηθηνί (0:stdin, 1:stdout, 2:stderr). 11-27
1) System Calls: Open()/Close() Flags (ζηαζεξέο κέζα ζηε fcntl.h) : Τπνρξεσηηθέο θαη πξναηξεηηθέο επηινγέο. Υπνρξεσηηθέο: O_RDONLY (open for reading only),o_wronly (writing), O_RDWR (read/write) Πξναηξεηηθέο: O_APPEND (append to the end of file), O_TRUNC (if file exists in WR or RDWR then truncate its size to 0), O_CREAT (create if file does not exist we have to set MODE variables see below), Mode (ζηαζεξέο sys/stat.h) : Πξνζδηνξίδεη ηα δηθαηψκαηα εάλ δεκηνπξγνχκε αξρείν. Σν mode είλαη αθέξαηνο (ηδία ινγηθή κε Unix file permissions). Mode S_IRUSR: Read permission, owner εκείσζε: Tα Flags θαη ην Mode εθθξάδνληαη S_IWUSR: Write permission, owner κπνξνχλ λα δνζνχλ ζαλ δηάδεπμε ζπκβνιηθψλ S_IXUSR: Execute permission, owner νλνκάησλ, π.ρ., S_IRGRP: Read permission, group open("test.txt", O_WRONLY O_CREAT, S_IWGRP: Write permission, group S_IRUSR S_IWUSR S_IRGRP S_IROTH); S_IXGRP: Execute permission, group S_IROTH: Read permission, others Δμήγεζε: Τν ORing ζεηεη ηα bits : S_IWOTH: Write permission, others rwxrwxrwx = 110100100 S_IXOTH: Execute permission, ΔΠΛ 371 others Πξνγξακκαηηζκόο (δει. 100000000 Σπζηεκάησλ 010000000 ) 11-28
Open/close: Απιφ Παξάδεηγκα #include <fcntl.h> #include <stdio.h> // for printf int main(){ int fd1, fd2; if(( fd1 = open("foo.txt", O_RDONLY)) < 0){ perror("opening file"); exit(1); printf("the File Descriptor is : %d", fd1); if (close(fd1) < 0) { perror("closing file"); exit(1); 11-29
1) System Calls: Open()/Close() Μεραληζκφο Εθηέιεζεο Opening myfile (Inode:13) B) Entry 13 from that data structure is read from the disk and copied into the kernel s open files table. Σhat consists of data blocks 5 and 8. Inode 13 on Disk Inode 13 in RAM A) The file system reads the current directory, and finds that myfile is represented internally by entry 13 in the list of files maintained on the disk. Otherfile 18 C) User s access rights are checked (through Inode attributes) and the user s ΔΠΛ 371 Πξνγξακκαηηζκόο variable Σπζηεκάησλ fd is made to point to the allocated 11-30 entry in the open files table
2) System Call: Creat() Δεκηοσργία Αρτείοσ int creat(const char * filename, int mode); ή ελαιιαθηηθά open(filename, O_WRONLY O_CREAT O_TRUNC, mode); # Returns: File Descriptor for Ο_WRONLY if OK, -1 on error Ο Dennis Ritchie εξσηήζεθε θάπνηε πην είλαη ην κνλαδηθφ πξάγκα πνπ έρεη κεηαληψζεη γηα ηελ C. Απηφο απάληεζε leaving off the e on creat(). Μεηνλέθηεκα ηεο creat() είλαη φηη δελ κπνξνχκε λα δηαβάζνπκε απφ ην αξρείν πνπ δεκηνπξγήζακε. Γηα λα ην δηνξζψζνπκε θαη λα έρνπκε Δεκηνπξγία + Read/Write ρξεζηκνπνηήζηε ην αθφινπζν: open(filename, O_RDWR O_CREAT O_TRUNC, mode); 11-31
3) System Call: Read() Αλάγλσζε από θάπνην FD int read(int fd, void *buf, int size) Returns: αξηζκφ bytes πνπ δηαβάζηεθαλ, 0:EOF, -1:ERROR Δηαβάδεη size bytes απφ ηελ νληφηεηα (αξρείν, ζπζθεπή, άθξν ζσιήλα ή ππνδνρή) πνπ αληηζηνηρεί ζηνλ πεξηγξάθεη fd θαη ηα αληηγξαθεί ζην buf. Πεξηκέλεη (blocking wait) κέρξη ζπκπιεξσζεί ην buf ε κέρξη θηάζεη ην EOF. Πξνυπνζέηεη φηη ε εθαξκνγή ζαο έρεη δεζκεχζεη αξθεηφ ρψξν (malloc) ζην buf. Ση ζα ζπκβεί ζηελ αληίζεηε πεξίπησζε? εκεηψζηε φηη ην buf είλαη Posix-compliant (void *) παξά ηνλ παξαδνζηαθό νξηζκό char *buf) 11-32
3) System Call: Read() Μεραληζκφο Εθηέιεζεο B) the system gains access to the list of blocks that contain the file s data. A) The argument fd identifies the open file by pointing into the kernel s open files table. C) The file system therefore reads disk block number 5 into its buffer cache, then block number 8. D) the desired range of 100 bytes is copied into the user s memory at the 11-33 address indicated by buf.
4) System Call: Write() Αλάγλσζε από θάπνην FD int write(int fd, void *buf, int size) Returns: αξηζκφ bytes πνπ γξάθηεθαλ, -1:ERROR Γξάθεη size bytes απφ ην buf ζηελ νληφηεηα (αξρείν, ζπζθεπή, άθξν ζσιήλα ή ππνδνρή) πνπ αληηζηνηρεί ζηνλ πεξηγξάθεη fd. Δπηζηξέθεη ηνλ αξηζκφ απφ bytes πνπ γξαθηήθαλ. Απηφ κπνξεί λα είλαη ιηγφηεξν απφ ηελ αίηεζε (size) εάλ ππήξμε θάπνην πξφβιεκα κε ηνλ file descriptor Π.ρ., size=100 αιιά ε write θαηαθέξλεη λα γξάςεη κφλν 10. Εάλ επηζηξέςεη 0, ηφηε δελ γξάθηεθε ηίπνηα. Εάλ επηζηξέςεη -1, ηφηε ειέγμεηε ηνλ θσδηθφ ιάζνπο errno. 11-34
4) System Call: Write() Μεραληζκφο Εθηέιεζεο β) The kernel then flushes the newly written data to disk (assuming that block#8 has adequate space). Else a new block is allocated and the data is written there as well. α) Our program calls write(fd,buf, sizeof(buf)); and the data is copied to kernel space 11-35
Παξάδεηγκα 1: Τινπνίεζε ηνπ cat Να πινπνηήζεηε ζε C θαη κε ρξήζε θιήζεωλ ζπζηήκαηνο, έλα απιό πξόγξακκα ην νπνίν λα πξνζνκνηώλεη ηελ εληνιή cat (ρωξίο παξακέηξνπο) π.ρ../mycat < filename ls./mycat./mycat (επαλαιακβάλεη όηη γξάθνπκε) 11-36
Παξάδεηγκα 1: Τινπνίεζε ηνπ cat // Η βηβιηνζήθε stdio.h πεξηιακβάλεηαη κφλν γηα ηελ κεηαβιεηή BUFSIZE (αλ θάλακε θαη printf/scanf επίζεο), ε νπνία παίξλεη ηελ πην θαιή ηηκή (κε βάζε ην ππάξρσλ ζχζηεκα), παξά λα ηελ ζέηακε κφλνη καο. #include <unistd.h> // STDIN_FILENO, STDOUT_FILENO #include <stdio.h> // BUFSIZE #include <error.h> // perror int main(int argc, char * argv []) { char buf[bufsiz]; // BUFSIZE 8192 int n; while((n = read(stdin_fileno, buf, sizeof(buf))) > 0) if ( write(stdout_fileno, buf, n)!= n ) perror ("write error"); if (n < 0) perror("read error"); return 0; Εξψηεζε: Γηαηί δελ ρξεηαζηήθακε λα αλνίμνπκε ηνπο πεξηγξαθείο FD#0 θαη FD#1? 11-37
Παξάδεηγκα 2: Read/Write Demo Να πινπνηήζεηε ζε C θαη κε ρξήζε θιήζεωλ ζπζηήκαηνο, έλα απιό πξόγξακκα ην νπνίν i) δεκηοσργεί έλα, αξρείν, ii) γράθεη θάπνηα ζπκβνινζεηξά, iii) θιείλεη ην αξρείν, iv) αλοίγεη θαη γράθεη θάπνηα άιιε ζπκβνινζεηξά, v) θιείλεη ην αξρείν θαη ηέινο vi) δηαβάδεη ην αξρείν θαη ην εθησπώλεη ζηελ νζόλε. Κάζε βήκα λα ηππώλεη ηνλ αξηζκό ηωλ bytes. 11-38
Παξάδεηγκα 2: Read/Write Demo /* File: io_demo.c */ #include <stdio.h> /* For printf, BUFSIZE*/ #include <fcntl.h> /* For O_RDONLY, O_WRONLY,O_CREAT, O_APPEND */ #include <string.h> /* strlen */ main() { int fd, bytes; char buf[bufsiz]; char *filename = "temp.txt"; char *line1 = "First write. \n"; char *line2 = "Second write. \n"; // 0600 <==> S_IRUSR S_IWUSR <==> -,rw-,---,--- if ((fd = open(filename, O_WRONLY O_CREAT O_TRUNC, 0600)) == -1) { perror("open"); exit(1); Create file and enable us to write to the file // Πξνζνρή: Γξάθνπκε κόλν ην strlen(line1), αληί strlen(line1)+1 γηα λα // απνθύγνπκε ηα αλεπηζύκεηα \0 ( First write. \n\0 Second write. \n\0 ) bytes = write(fd, line1, strlen(line1)); /* Data out */ printf("%d bytes were written\n", bytes); Αλεπηζχκεην close(fd); 11-39
Παξάδεηγκα 2: Read/Write Demo if ((fd = open(filename, O_WRONLY O_APPEND)) == -1) { perror("open"); exit(1); bytes = write(fd, line2, strlen(line2)); /* Data out */ printf("%d bytes were written\n", bytes); close(fd); if ((fd = open(filename, O_RDONLY)) == -1) { perror("open"); exit(1); bytes = read(fd, buf, sizeof(buf)); /* Data in */ printf("%d bytes were read\n", bytes); close(fd); buf[bytes] = '\0'; printf("%s", buf); $./a.exe 14 bytes were written 15 bytes were written 29 bytes were read First write. Second write. 11-40
Παξάδεηγκα 3: Τινπνίεζε Concat Αξρείσλ Να πινπνηήζεηε ζε C θαη κε ρξήζε θιήζεωλ ζπζηήκαηνο, έλα απιό πξόγξακκα ην νπνίν λα πξνζνκνηώλεη ηελ ιεηηνπξγία ηεο πην θάηω εληνιήο θειύθνπο cat file1 >> file2 Τν πξόγξακκα ζαο εθηειείηαη κε ηνλ αθόινπζν ηξόπν. $concat file1 file2 11-41
Παξάδεηγκα 3: Τινπνίεζε Concat Αξρείσλ /* File: append_file.c */ #include <fcntl.h> /* For O_RDONLY. O_WRONLY, O_CREAT, O_APPEND */ #include <unistd.h> // STDERR_FILENO #include <string.h> // strlen main(int argc, char *argv[]) { int n, fromfd, tofd; char buf[1024]={; if (argc!= 3) { /* Check for proper usage */ sprintf(buf, "Usage: %s from-file to-file", argv[0]) ; write(stderr_fileno, buf, strlen(buf)); exit(1); 11-42
Παξάδεηγκα 3: Τινπνίεζε Concat Αξρείσλ if ((fromfd = open(argv[1], O_RDONLY)) < 0) { /* Open from-file */ perror("open"); exit(1); Append mode if ((tofd = open(argv[2], O_WRONLY O_CREAT O_APPEND, 0660)) < 0) { /* Open to-file */ perror("open"); exit(1); while ((n = read(fromfd, buf, sizeof(buf))) > 0) if (write(tofd, buf, n)!= n) { /* Copy data */ perror("copy error"); close(fromfd); /* Close from-file */ close(tofd); /* Close to-file */ $ cat file1 First write. $cat file 2 Second write. $concat file1 file2 $cat file2 First write. Second write. 11-43
5) System Call: lseek() Σπραία (Random) Μεηαθίλεζε κέζα ζην Αξρείν off_t lseek(int fd, off_t offset, int whence) Returns: new file offset if OK, -1 on error off_t δειψλεηαη κέζα ζην sys/types.h Offset (από πνύ): Οξίδεη ηελ ζέζε (position) Whence : Οξίδεη πσο ρξεζηκνπνηείηαη ην offset. SEEK_SET: relative to beginning of file SEEK_CUR: relative to the current position SEEK_END: relative to end of file Η ζπλάξηεζε lseek καο επηηξέπεη λα κεηαθηλεζνχκε κέζα ζην αξρείν κε ηπραίν ηξφπν. (Random Access). Κάζε αξρείν έρεη έλα «current file offset» ην νπνίν είλαη έλαο ζεηηθφο αθέξαηνο ν νπνίνο κεηξά ηνλ αξηζκφ απφ bytes απφ ηελ αξρή ηνπ αξρείνπ. Εάλ αλνίμεη ην αξρείν ην offset είλαη 0. Μεηά απφ αλάγλσζε m bytes, ην offset γίλεηαη m. To l seek πξνέξρεηαη απφ ην long seek δηφηη ην offset είλαη έλαο long integer. 11-44
5) System Call: lseek() Σπραία (Random) Μεηαθίλεζε κέζα ζην Αξρείν Σν lseek δειψλεη ην offset κέζα ζην kernel ρσξίο λα πξνθαιέζεη νπνηνλδήπνηε I/O. Tν Θ/Ο ζα γίλεη κφλν ζην επφκελν write. Εάλ εθηειέζνπκε ην πην θάησ εληνιή ηφηε ε επφκελε γξαθή (ή αλάγλσζε) ζα γίλεη 100 bytes δεμηφηεξα απφ ηελ παξφλ ζέζε: lseek(filedesc, 100, SET_CUR); Επνκέλσο έλα αξρείν κπνξεί λα έρεη «ηξχπεο» κε θελά. Απηέο νη ηξχπεο είλαη νπζηαζηηθά ζπλερφκελα 0 (NULLs) θαη θαηαιακβάλνπλ 1 byte αλά Null. Σν offset κπνξεί λα πάξεη ζεηηθέο θαη αξλεηηθέο ηηκέο, εάλ θαη εθφζνλ νη ζπζθεπέο ην ππνζηεξίδνπλ (π.ρ. ζε έλα αξρείν γίλεηαη άιια φρη ζε έλα socket). 11-45
Παξάδεηγκα 4: Τινπνίεζε Απινχ Database Να πινπνηήζεηε ζε C θαη κε ρξήζε θιήζεωλ ζπζηήκαηνο, κηα απιή δπαδηθή βάζε δεδνκέλωλ ή νπνία γξάθεη πέληε εγγξαθέο ηεο κνξθήο typedef struct person{ int id; char sex; char name[40]; attribute ((packed)) PERSON; Σν attribute ((packed)) ηνπ ζεκαίλεη φηη δελ ζέινπκε ν GCC compiler λα πξνζζέζεη padding ζηελ δνκή γηα λα ηελ θάλεη align ζηελ κλήκε. Εάλ δελ ην ρξεζηκνπνηήζνπκε πξέπεη λα θάλνπκε ηηο εγγξαθέο ησλ ζηνηρείσλ κηα-κηα ζπλερόκελα ζε έλα αξρείν user.db, ζηελ ζπλέρεηα αθήλεη 3 εγγξαθέο θελέο θαη κεηά γξάθεη αθόκε 5 εγγξαθέο. Τέινο δηαβάδεη από ην αξρείν όιεο ηηο εγγξαθέο θαη ηηο ηππώλεη ζηελ νζόλε. 11-46
Παξάδεηγκα 4: Τινπνίεζε Απινχ Database main(int argc, char *argv[]) { int n, fd, i; PERSON p; char *filename="users.db"; int offset; if ((fd = open(filename, O_RDWR O_CREAT, 0660)) < 0) { /* Open to-file */ perror("open db"); exit(1); // set the values in the p structure p.sex = 'm'; strcpy(p.name, "Costas"); // write 5 tuples to the file for (i=0; i<5; i++) { p.id = i; write(fd, (void *) &p, sizeof(p)); 11-47
Παξάδεηγκα 4: Τινπνίεζε Απινχ Database // seek the file descriptor three sizeof(p) positions to the right (from SEEK_CUR) lseek(fd, 3*sizeof(p), SEEK_CUR); // write another 5 tuples to the file for (i=0; i<5; i++) { p.id = i; write(fd, (void *) &p, sizeof(p)); // rewind the file descriptor to the beginning of the file lseek(fd, 0, SEEK_SET); // Now read and print the respective tuples while((n = read(fd, (void *) &p, sizeof(p))) > 0) { if ( sizeof(p)!= n ) perror ("read error"); printf("<%d,%c,%s>\n", p.id, p.sex, p.name); close(fd); 11-48
Παξάδεηγκα 4: Τινπνίεζε Απινχ $dbtest <0,m,Costas> <1,m,Costas> <2,m,Costas> <3,m,Costas> <4,m,Costas> <0,,> <0,,> <0,,> <0,m,Costas> <1,m,Costas> <2,m,Costas> <3,m,Costas> <4,m,Costas> Database Τν κέγεζνο ηνπ αξρείνπ είλαη 585 bytes (13 records * 45 bytes) 11-49