Σε αυτή την άσκηση θα χρειαστεί να φτιάξετε ένα απλό πρόγραμμα που θα υλοποιεί ένα linux C shell
ή αλλιώς command interpreter με όνομα "cs345sh" στο λειτουργικό σύστημα Linux.
Σε αυτήν την άσκηση θα εξοικιωθείτε με τη δημιουργία, τον έλεγχο, την εκτέλεση διεργασιών, τις κλήσεις συστήματος
(system calls) fork(), wait() και exec(), την επικοινωνία διεργασιών μέσω pipes και signals.
Το prompt του cs345sh shell θα είναι:
όπου αντί για <user> θα τυπώνει το όνομα του χρήστη που είναι logged-in στο σύστημα (δείτε την συνάρτηση βιβλιοθήκης
getlogin()) και αντί για <dir> θα τυπώνει το τρέχον directory
(δείτε την συνάρτηση βιβλιοθήκης getcwd()).
Με το cs345sh θα μπορεί ένας χρήστης:
να δίνει τις εντολές του και αυτές να εκτελούνται.
Συγκεκριμένα το shell θα διαβάζει εντολές από τον χρήστη και θα τις εκτελεί.
Αφού διαβάσει μια γραμμή εντολών, το cs345sh θα χρησιμοποιεί το system call fork(),
για να δημιουργήσει μια καινούρια διεργασία-παιδί η οποία θα εκτελεί την εντολή του χρήστη.
Η εκτέλεση της εντολής από τη διεργασία-παιδί θα γίνεται με τη χρήση ενός από τα system calls
της οικογένειας exec().
Η πατρική διεργασία θα περιμένει τη διεργασία-παιδί να τελειώσει την εκτέλεσή της (χρησιμοποιώντας το system call
wait()). Ύστερα, θα επιστρέφει στο prompt περιμένοντας τη νέα
εντολή του χρήστη, εκτός αν ο χρήστης έχει πληκτρολογήσει το "&" στο τέλος της εντολής όπου αυτό σημαίνει
ότι η διεργασία θα τρέχει ως daemon (background process), οπότε η πατρική διεργασία
δεν θα περιμένει αλλά θα επιστρέφει αμέσως στο prompt για νέα εντολή. Σε αυτήν την περίπτωση πριν επιστρέψει στο prompt
για να περιμένει νέα εντολή θα πρέπει πρώτα να τυπώνει το όνομα και το pid της διεργασίας που τρέχει στο παρασκήνιο.
να κατεθύνει την έξοδο μιας εντολής στην είσοδο μίας άλλης εντολής χρησιμοποιώντας pipes(Pipelines):
Η έξοδος μιας εντολής θα μπορεί να δίνεται σαν είσοδος σε μια άλλη εντολή που υπάρχει στην ίδια γραμμή
εντολών και διαχωρίζονται με το σύμβολο ''|'' μεταξύ τους. Παραδείγματα:
που βρίσκει όλες τις zombie διεργασίες.
που τυπώνει τα 10 μεγαλύτερα αρχεία στον τρέχοντα κατάλογο ταξινομημένα κατά μέγεθος.
Για την υλοποίηση αυτής της λειτουργίας θα σας φανεί χρήσιμο το system call pipe().
να κάνει έλεγχο διεργασιών:
και συγκεκριμένα:
Αναστολή εκτέλεσης διεργασίας: Ο χρήστης θα μπορεί να αναστείλει την εκτέλεση (suspend) της τρέχουσας διεργασίας αποστέλοντας ένα SIGTSTP signal
(πληκτρολογώντας Ctrl-Z) στην τρέχουσα διεργασία.
Ο χρήστης μπορεί να κάνει έλεγχο των τρεχουσών διεργασιών του shell με την εντολή "csd_jobs". Η εντολή αυτή θα εμφανίζει όλες τις διεργασίες τυπώνοντας
στην οθόνη: (i) τον αύξων αριθμό της διεργασίας με βάση την χρονική σειρά που έγινε suspend, (ii) την εντολή και (iii) το pid κάθε suspended διεργασίας
Σημείωση: Στο σημείο αυτό θα πρέπει το shell να κρατάει τις απαραίτητες πληροφορίες για όλες τις τρέχουσες διεργασίες σε μια δομή η οποία μπορεί
να είναι είτε δυναμική είτε στατική. Αυτό σημαίνει ότι θα εμφανίζονται κανονικά και τα background process που έχετε δημιουργήσει στο προηγούμενο βήμα
(με την χρήση του συμβόλου '&').
Συνέχιση εκτέλεσης διεργασίας: Ο χρήστης θα μπορεί να συνεχίσει την εκτέλεση (resume) μίας διεργασίας μέσω της αποστολής ένώς SIGCONT signal. Πιο συγκεκριμένα:
με την εντολή:
(όπου [job_id] είναι ο αύξων αριθμός της suspended διεργασίας με σύνταξη %1, %2 κλπ.) η διεργασία θα συνεχίζει την εκτέλεσή της στο background που
σημαίνει ότι το shell δεν θα περιμένει την περάτωσή της.
Ομοίως με την εντολή:
η διεργασία θα συνεχίζει την εκτέλεσή της στο foreground που σημαίνει ότι το shell θα περιμένει την περάτωση της.
Εκτός από τις εντολές του χρήστη, το cs345sh θα υποστηρίζει και τις παρακάτω δικές του εντολές :
cd:
Η εντολή αυτή θα δέχεται ένα όρισμα που δηλώνει τον κατάλογο (directory) ο οποίος θα πρέπει να γίνει το νέο τρέχoν directory (δείτε την κλήση συστήματος chdir()).
exit: Με την εντολή exit θα τερματίζεται η λειτουργία του cs345sh.
Reference - man pages
Ένα man page περιγράφει τον τρόπο λειτουργίας
ενός προγράμματος, ενός system call ή μιας library function. Η εμφάνιση ενός man page
γίνεται με τη χρήση της εντολής:
man(1)
Για να δείτε το man page (σε Linux) που αναφέρεται στη foo(N), κάνετε:
% man -S N foo
Ο συμβολισμός foo(N) αναφέρεται στο man page που περιγράφει τη foo στη κατηγορία (section)
'Ν'.
Λίστα με χρήσιμα man pages για την Aσκηση 1
Σας παραθέτουμε man pages με system calls που μπορεί να χρειαστείτε για την υλοποίηση της άσκησης.
Η παρακάτω λίστα δεν είναι δεσμευτική. Μπορείτε να χρησιμοποιήσετε και εναλλακτικούς τρόπους:
fork(2), exec(3), execv(3), wait(2), waitpid(2), signal(2), kill(1), pipe(2), sh(1), bash(1), chdir(2), getcwd(2), getlogin(2)
Παρατηρήσεις
Η άσκηση είναι ατομική. Τυχόν αντιγραφές μπορούν να ανιχνευθούν εύκολα
από κατάλληλο πρόγραμμα και θα μηδενιστούν. Συμπεριλάβετε το όνομα σας και
το λογαριασμό σας (account) σε όλα τα αρχεία.
Κατασκευάστε ένα αρχείο Makefile, έτσι ώστε
πληκτρολογώντας make all να γίνεται η μεταγλώττιση
(compilation) του προγράμματος και να παράγεται το εκτελέσιμο
αρχείο. Επίσης πληκτρολογώντας make clean να καθαρίζονται
όλα τα περιττά αρχεία, και να μένουν μόνο τα αρχεία που χρειάζονται
για τη μεταγλώττιση.
Επιπλέον, γράψτε και ένα αρχείο readme.txt το πολύ 30 γραμμών που να
περιέχει επεξηγήσεις για τον τρόπο υλοποίησης και παραδείγματα
για τη χρήση του cs345sh που υλοποιήσατε.
Τοποθετήστε σε ένα κατάλογο όλα τα
αρχεία που χρειάζονται για την άσκηση 1. Παραδώστε τα
παραπάνω αρχεία χρησιμοποιώντας το πρόγραμμα turnin (πληκτρολογήστε
turnin assignment_1@hy345 directory_name από τον κατάλογο
που περιέχει τον κατάλογο directory_name με τα αρχέια της άσκησης).
Σε πολλές περιπτώσεις τα ονόματα των συναρτήσεων βιβλιοθήκης είναι
ενδεικτικά. Μπορείτε να χρησιμοποιήσετε όποια σας βολεύουν.