Λειτουργικά Συστήματα (ΗΥ-345)
Χειμερινό Εξάμηνο 2011
Ασκηση 3η



Παράδοση: 2/12/2011

Υλοποίηση System Calls στο ΜΙΝΙΧ

Σκοπός αυτής της άσκησης είναι εξοικείωση με τις έννοιες και την υλοποίηση των system calls σε ένα λειτουργικό σύστημα. Για το σκοπό αυτό σας ζητείται να φτιάξετε δύο νέα δικά σας system call στο λειτουργικό σύστημα Minix.


Περιγραφή

(1) Θα υλοποιήσετε ένα system call το οποίο θα εμφανίζει όλες τις εγγραφές του process table (mprog) του Memory Management System του Minix. Θα εμφανίζονται μόνο τα slots τα οποία δεν είναι άδεια. Υπάρχουν αρκετά παραδείγματα μέσα στον κώδικα του MINIX που να διατρέχουν τον process table. Για κάθε διεργασία του process table θα πρέπει να εμφανίζονται το pid, το process number και το όνομα της διεργασίας. Το system call αυτό θα το ονομάσετε printproc() .

θα γράψετε ένα απλό πρόγραμμα που θα χρησιμοποιεί αυτό το νέο system call. Παρακάτω σας δίνεται ένα παράδειγμα για το πως μπορεί να είναι το output της κλήσης αυτού του system call:
PID    P_NR    P_NAME
 0     -10      TTY
 0     -9       DP8390
 0     -8       SYN_AL
 0     -7       IDLE
      ......
 29     4       sh
 18     5       update
 30     6       getty
 30     7       getty
 30     8       getty
 33     9       project5


(2) Κάθε διεργασία έχει ένα memory map entry για τα τρία διαφορετικά segments μνήμης που έχει (text, data και stack). To entry (mp_seg) αυτό είναι αποθηκευμένο στον process table (mprog) του Memory Management System και περιέχει τρεις τιμές για κάθε segment: την εικονική διεύθυνση, τη φυσική διεύθυνση και το μέγεθος. Οπότε συνολικά έχουμε 9 τιμές για κάθε διεργασία.

Σας ζητείτε να υλοποιήσετε το system call getmpseg(pid, i) το οποίο ανάλογα με τη τιμή i που δέχεται ως δεύτερο όρισμα θα επιστρέφει μία από τις 9 τιμές του memory map entry για την διεργασία με το pid που δέχεται ως πρώτο όρισμα. Οπότε το system call πρώτα θα διατρέχει τον process table του Memory Management System του Minix για να βρεί την διεργασία με το pid που δίνετε σαν όρισμα, και έπειτα ανάλογα με το δεύτερο όρισμα i θα επιστρέφει την αντίστοιχη τιμή του memory map entry ως εξής:

i = 0 εικονική διεύθυνση text segment
i = 1 φυσική διεύθυνση text segment
i = 2 μέγεθος text segment
i = 3 εικονική διεύθυνση data segment
i = 4 φυσική διεύθυνση data segment
i = 5 μέγεθος data segment
i = 6 εικονική διεύθυνση stack segment
i = 7 φυσική διεύθυνση stack segment
i = 8 μέγεθος stack segment

Για οποιαδήποτε άλλη τιμή του i η getmpseg θα επιστρέφει -1. Αν το pid που δώθηκε σαν όρισμα δεν υπάρχει στον process table, τότε η getmpseg θα επιστρέφει επίσης -1.

Τέλος θα γράψετε ένα απλό πρόγραμμα που θα χρησιμοποιεί και αυτό το δεύτερο νέο system call. Το πρόγραμμα θα δέχετε σαν προαιρετικό όρισμα ένα pid κάποιας διεργασίας και θα τυπώνει όλα τα memory segments για αυτή τη διεργασία. Για να βρείτε ένα έγκυρο pid κάποιας διεργασίας που τρέχει στο σύστημα μπορείτε να χρησιμοποίησετε το προηγούμενο πρόγραμμα που φτιάξατε με το system call printproc. Άν το πρόγραμμα δεν δεχτεί όρισμα από command line κάποιο pid, τότε θα τυπώνει όλα τα memory segments για την τρέχουσα διεργασία που καλέι το system call getmpseg. Για να βρείτε το pid της τρέχουσας διεργασίας μπορείτε να χρησιμοποιήσετε το system call getpid() του Minix, το οποίο επιστρέφει το pid της διεργασίας που το καλέι.
Για παράδειγμα, το πρόγραμμα σας μπορεί να μοιάζει κάπως έτσι:
int map[9];
for (i=0; i<9; i++) 
   map[i] = getmpseg(getpid(), i); 
printf(“Text %d %d %d\n”, map[0], map[1], map[2]);
printf(“Data %d %d %d\n”, map[3], map[4], map[5]);
printf(“Stack %d %d %d\n”, map[6], map[7], map[8]);
Και η έξοδος του προγράμματος κάπως έτσι:
Text 0 104 63
Data 0 167 20
Stack 60 227 2

Emulators

Για να τρέξετε το minix πάνω από τα linux μηχανήματα θα χρησιμοποιήσετε τον emulator QEMU ή τον emulator bochs. Αυτοί οι emulators είναι εγκατεστημένοι στα linux μηχανήματα που υπάρχουν στα εργαστήρια του τμήματος. Ή μπορείτε να τους εγκαταστήσετε σε δικό σας μηχάνημα. Για να τρέξετε το λειτουργικό σύστημα Μinix με τo QEMU ή το bochs θα πρέπει πρώτα να αντιγράψετε το κατάλληλο αρχέιο με το image του Minix απο την περιοχή του μαθήματος σε ένα δικό σας directory και στη συνέχεια να το φορτώσετε με τον emulator. Έπειτα θα τροποποιήσετε τα κατάλληλα αρχεία στον source κώδικα του minix, ώστε να υλοποιήσετε τα καινούργια system calls, και θα αρχίσετε ξανά το minix με τις δικές σας αλλαγές ώστε να βεβαιωθείτε οτι δουλεύουν. Για αυτό τον λόγο απαιτείται στην άσκηση να φτιάξετε και κάποια δικά σας test προγράμματα που χρησιμοποιούν τα καινούργια system calls. Τέλος, θα παραδώσετε το αρχείο minix.img που είναι το image του δικού σας "τροποποιημένου" minix που θα μπορούμε να φορτόσουμε στον emulator. Περισσότερες και πιο αναλυτικές οδηγίες για το πώς θα τρέχετε το minix χρησιμοποιώντας το QEMU, και πως κάνετε αλλαγές σε αυτό, μπορείτε να βρείτε εδώ . Οι αντίστοιχες οδηγίες για τον emulation bochs είναι εδώ .

README

Στο README που θα παραδώσετε θα πρέπει να περιγράψετε συνοπτικά τον τρόπο υλοποίησης των system calls. Περιγράψτε την ακολουθία των κλήσεων, τις συναρτήσεις βιβλιοθηκών και τα διάφορα τμήματα του λειτουργικού που εμπλέκονται κατά την εκτέλεση των system calls (τα βήματα που ακολουθούνται από την στιγμή που το σύστημα λαμβάνει το system call, πως το διαχειρίζεται εσωτερικά και πως επιστρέφει την απάντηση στον χρήστη).

Hints

  1. Στην άσκηση αυτή θα σας βοηθήσει πολύ η εντολή του UNIX grep. Επίσης, αν χρησιμοποιείτε τον vim editor, θα σας φανεί πολύ χρήσιμο και το πρόγραμμα ctags. Χρησιμοποιήστε την εντολή man από το shell για να μάθετε πως ακριβώς λειτουργεί κάθε εντολή.
  2. Για δική σας ευκολία (για να ξέρετε σε ποιό σημείο έχετε αλλάξει κώδικα μέσα στα αρχεία του Μinix), χρησιμοποιείστε σχόλια πριν και μετά τις αλλαγές σας και/ή εντολές του τύπου :
    #ifdef ... ή #if ...
    ... νέος κώδικας ...
    #else
    ... παλιός κώδικας ...
    #endif
  3. Για το πρώτο system call μπορείτε να ξεκινήσετε μελετώντας τον τρόπο λειτουργίας των system calls getpid και getppid. Μερικά από τα αρχεία στα οποία ίσως χρειαστεί να επέμβετε ή ακόμα και να δημιουργήσετε οι ίδιοι είναι τα παρακάτω:
    /src/lib/sunsyscall/Makefile
    /src/lib/sunsyscall/printproc.s
    /src/lib/sunsyscall/getmpseg.s
    /src/lib/posix/Makefile
    /src/lib/posix/_printproc.c
    /src/lib/posix/_getmpseg.c
    /include/minix/callnr.h
    /src/mm/table.c
    /src/mm/getset.c
    /include/minix/syslib.h
    /src/lib/syslib/Makefile
    /src/lib/syslib/sys_printproc.c
    /src/lib/syslib/sys_getmpseg.c
    /include/minix/com.h
    /src/kernel/proc.h
    /usr/src/kernel/system.c

Παρατηρήσεις

  1. Η άσκηση είναι ατομική. Τυχόν αντιγραφές μπορούν να ανιχνευθούν εύκολα από κατάλληλο πρόγραμμα και θα μηδενιστούν. Συμπεριλάβετε το όνομα σας, τον αριθμό μητρώου σας, και το username σας σε όλα τα αρχεία.
  2. Γράψτε ένα αρχείο README, το πολύ 30 γραμμών, με επεξηγήσεις για τον τρόπο υλοποίησης των system calls.
  3. Κατασκευάστε ένα αρχείο Makefile, έτσι ώστε πληκτρολογώντας make all να γίνεται η μεταγλώττιση (compilation) των προγραμμάτων που χρησιμοποιούν τα system calls και να παράγονται τα εκτελέσιμα αρχεία. Επίσης πληκτρολογώντας make clean να καθαρίζονται όλα τα περιττά αρχεία, και να μένουν μόνο τα αρχεία που χρειάζονται για τη μεταγλώττιση.
  4. Κατασκευάστε ένα κατάλογο που θα περιέχει τo README και το αρχείο minix.img, το οποίο είναι το image του minix που φορτώνεται από τον emulator. Παραδώστε τα παραπάνω αρχεία χρησιμοποιώντας το πρόγραμμα submit (πληκτρολογήστε submit assignment_3@hy345 directory_name από τον κατάλογο που περιέχει τον κατάλογο directory_name με τα αρχέια της άσκησης).
  5. Σε πολλές περιπτώσεις τα ονόματα των αρχείων είναι ενδεικτικά. Μπορείτε να χρησιμοποιήσετε όποια σας βολεύουν.