ΠΕΡΙΕΧΟΜΕΝΑ
Η. PROCESS CONTROL FUNCTIONS
Τα
πρωτότυπά της βρίσκονται στα <process.h> και <stdlib.h>:
void abort( )
Προκαλεί
άμεσο τερματισμό ενός προγράμματος.
Π.χ.: #include <process.h>
main(
)
{
for(;;)
if(getch( ) == ‘A’) abort( );
}
Το
πρόγραμμα ορίζει έναν ατέρμονα βρόγχο ο οποίος τερματίζεται αν πατηθεί Α.
Το
πρωτότυπό της βρίσκεται στο <stdlib.h>:
int atexit (func)
void (*func) ( )
Η
συνάρτηση atexit( )
καθορίζει τη συνάρτηση func, να είναι
η συνάρτηση, που θα καλείται σε περίπτωση ομαλού τερματισμού του προγράμματος.
Η atexit( ) επιστρέφει 0, αν η συνάρτηση είναι Terminating Function και 1 σε
άλλη περίπτωση. Μπορούν να κληθούν ως 32 συναρτήσεις. Αυτές καλούνται ανάποδα
απ’ ότι δηλώθηκαν, δηλ. First in,
Last out.
Π.χ.: main( ) {
void
done( );
if
(atexit (done) ) printf (“Error”);
}
void
done ( ) {
printf
(“Hello There”);
}
3.
Η οικογένεια συναρτήσεων exec…
Τά
πρωτότυπά τους βρίσκονται στο <process.h>:
int execl (char *fname, char *arg0, … , char *argN, NULL)
int execle (char *fname, char *arg0, … , char *argN, NULL, char *envp[ ])
int execlp (char *fname, char *arg0, … , char *argN, NULL)
int execpe (char *fname, char *arg0, … , char *argN, NULL, char *envp[ ])
int execp (char *fname, char *arg[ ])
int execpe (char
*fname, char *arg[ ], char *envp[ ])
int execv (char *fname, char *arg[ ])
int execve (char *fname, char *arg[ ], char *envp[ ])
Οι
συναρτήσεις αυτές χρησιμοποιούνται για να εκτελέσουν άλλα προγράμματα. Το
πρόγραμμα αυτό λέγεται child
process file και δείχνεται από τον pointer fname. Οι
παράμετροι στην child process δείχνονται είτε από το arg0…argN, είτε από
τον πίνακα arg[ ]. Ένα environment string πρέπει να δείχνεται από το envp (τα arguments
δείχνονται από το argv στην child process).
Αν
δεν υπάρχει προέκταση ή τελεία στο fname, γίνεται
πρώτα ανίχνευση για αρχείο με αυτό το όνομα. Αν αυτό αποτύχει, προστίθεται η
προέκταση .EXE και η
ανίχνευση επαναλαμβάνεται ξανά. Αν το extension ορίζεται,
η ανίχνευση γίνεται για το συγκεκριμένο string. Τέλος, αν υπάρχει τελεία και όχι extension, η ανίχνευση γίνεται για το αρχείο, που βρίσκεται στα
αριστερά του ονόματος.
Ο
ακριβής τρόπος δράσης της exec…
εξαρτάται από την έκδοση της συνάρτησης που χρησιμοποιούμε. Η exec… διαθέτει διαφορετικές καταλήξεις, οι οποίες ορίζουν
τη λειτουργία της. Μία κατάληξη μπορεί να περιέχει ανάλογα ένα ή δύο
χαρακτήρες.
Συναρτήσεις
που περιέχουν ένα p στην
κατάληξη, ελέγχουν για την child
process και στα directory που ορίζονται από το DOS PATH. Αν δεν υπάρχει το p, τότε ο έλεγχος γίνεται μόνο στο current και στο root
directory.
Αν
υπάρχει ένα 1, τότε οι παράμετροι στην child process θα
περάσουν ξεχωριστά μία – μία. Αυτό το χρησιμοποιούμε όταν ξέρουμε πόσες
παράμετροι θα περαστούν. Σημειώνουμε ότι η τελευταία παράμετρος πρέπει να είναι
NULL.
Αν
υπάρχει e, δείχνει
ότι ένα ή περισσότερα environmental
strings θα
περαστούν στην child process. Η παράμετρος envp[ ] είναι ένας πίνακας από string pointers. Κάθε string που δείχνεται από τα στοιχεία του πίνακα πρέπει να
έχει τη φόρμα: environment variable = value.
Ο
τελευταίος pointer στον
πίνακα πρέπει να είναι NULL. Αν ο
πρώτος pointer είναι NULL, τότε το child
κληρονομεί το ίδιο περιβάλλον σαν τον parent.
Είναι
σημαντικό ότι τα ανοιχτά αρχεία στη διάρκεια του exec… μένουν ανοιχτά και στο child.
Αν
η exec έχει επιτυχή εκτέλεση δεν
επιστρέφει τιμή. Σε περίπτωση αποτυχίας επιστρέφει –1 και θέτει το errno σε μία από τις παρακάτω τιμές:
Macro
EZBIG EACCES EMFILE ENOENT ENOEXEC ENOMEM |
Έννοια
Too Many Arguments Access To Child Process File Denied Too Many Files File Not Found Exec Format Error Not Enough Free Memory |
Π.χ.: #include <stdio.h>
#include
<process.h>
main(
)
{
execl
( “Test.Exe”, “Test.Exe”, “hello”, “10”, NULL);
}
main(int
argc, char *argv[ ] )
{
printf(“this
program is executed with this command line:”);
printf
( “arguments: “);
printf
(argv[1]);
printf(“%d”,
atoi(argv[2]));
}
4. Η οικογένεια συναρτήσεων spawn…
Το
πρωτότυπό της βρίσκεται στο <process.h>:
int spawnl (int
mode, char *fname, char *arg0, … , char *argN, NULL)
int spawnle (int
mode, char *fname, char *arg0,… , char *argN, NULL, char *envp[ ])
int spawnlp (int
mode, char *fname, char *arg0, … , char *argN, NULL)
int spawnlpe (int mode, char *fname, char *arg0,… , char *argN, NULL, char *envp[ ])
int spawnp (int mode, char *fname, char *arg[ ])
int spawnpe (int mode, char *fname, char *arg[ ], char *envp[ ])
int spawnv (int mode, char *fname, char arg[ ])
int spawnve (int mode, char *fname, char *arg[ ], char
*envp[ ])
Αυτό το group συναρτήσεων χρησιμοποιείται για να εκτελέσει άλλα
προγράμματα. Η διαφορά αυτών των συναρτήσεων από τις exec συναρτήσεις, είναι ότι οι spawn… δεν αντικαθιστούν το parent program στη μνήμη
(αντίθετα με τις exec… , που το
αντικαθιστούν πλήρως). Το όνομα του προγράμματος είναι το fname. Αν υπάρχουν παράμετροι αυτές δείχνονται από τα arg0…argN ή τον
πίνακα arg[ ]. Αν χρειαστεί να
περαστεί ένα environment
string, αυτό δείχνεται από την envp (οι παράμετροι θα δείχνονται από την argv στην child
process).
Η
παράμετρος mode
διευκρινίζει πως θα εκτελεστεί το child
process program. Μπορεί να έχει μία από τις
παρακάτω τιμές (ορισμένες στο header
file process.h):
Macro
P_WAIT P_NOWAIT P_OVERLAY |
Execution Mode
Suspends parent process until the child has finished executing Executes both the parent and the child concurrently – not implemented – in TURBO C Replaces the parent process
in memory |
Όπως
βλέπουμε, η P_NOWAIT είναι προς το παρόν μη διαθέσιμη, έτσι συνήθως
χρησιμοποιούμε την P_WAIT σαν value
mode. Πάντως αν θέλουμε να
αντικαταστήσουμε το parent
πρόγραμμα, είναι καλύτερο να χρησιμοποιήσουμε την exec… . Αν χρησιμοποιηθεί η επιλογή P_WAIT μετά το
τέλος του child, η ροή
του ελέγχου επιστρέφει στο parent και
μάλιστα στην επόμενη γραμμή μετά την κλήση του spawn.
Αν
δεν υπάρχει προέκταση ή τελεία στο string, που
δείχνει το fname, γίνεται
πρώτα ανίχνευση για αρχείο με αυτό το όνομα. Αν αυτό αποτύχει, προστίθεται η
προέκταση .EXE και η
ανίχνευση γίνεται για το συγκεκριμένο string. Τέλος,
αν υπάρχει τελεία και όχι extension, η
ανίχνευση γίνεται για το αρχείο, που βρίσκεται στα αριστερά του ονόματος.
Ο
ακριβής τρόπος αντίδρασης της spawn… εξαρτάται
από την έκδοση της εντολής που χρησιμοποιούμε. Η spawn διαθέτει διαφορετικές καταλήξεις, οι οποίες ορίζουν τη
λειτουργία της. Μία κατάληξη μπορεί να περιέχει ανάλογα ένα ή δύο χαρακτήρες.
Συναρτήσεις
που περιέχουν ένα p στην
κατάληξη, ελέγχουν για την child
process και στα directory, που ορίζονται από το DOS PATH. Αν δεν υπάρχει το p, ο έλεγχος γίνεται μόνο στο current και στο root
directory.
Αν
υπάρχει ένα 1, τότε οι παράμετροι στην child process θα
περάσουν ξεχωριστά μία – μία. Αυτό το χρησιμοποιούμε όταν ξέρουμε πόσες
παράμετροι θα περαστούν. Σημειώνουμε ότι η τελευταία παράμετρος πρέπει να είναι
NULL (το NULL ορίζεται στο <stdio.h>).
Αν
υπάρχει ν στην κατάληξη, τότε οι παράμετροι θα περαστούν σε πίνακα. Αυτό το
χρησιμοποιούμε όταν δεν ξέρουμε πόσες ακριβώς παράμετροι θα περαστούν.
Αν
υπάρχει e, στην
κατάληξη, ορίζει ότι ένα ή περισσότερα environmental strings θα
περαστούν στην child process. Η παράμετρος envp[ ] είναι ένας πίνακας από string pointers. Κάθε string στον πίνακα πρέπει να έχει
τη μορφή: environment variable = value.
Ο
τελευταίος pointer στον
πίνακα πρέπει να είναι NULL. Αν το
πρώτο στοιχείο του πίνακα είναι NULL, τότε το child κληρονομεί το ίδιο περιβάλλον σαν τον parent.
Υπενθυμίζεται
ότι όσα αρχεία ανοίξουν στο parent, μένουν
ανοιχτά και στο child.
Αν
η spawn έχει επιτυχή εκτέλεση δεν
επιστρέφει τιμή. Σε περίπτωση αποτυχίας επιστρέφει –1 και θέτει το errno σε μία από τις παρακάτω τιμές:
Macro
EZBIG EACCES EMFILE ENOENT ENOEXEC ENOMEM |
Έννοια
Too Many Arguments Access To Child Process File Denied Too Many File File Not Found Exec Format Error Not Enough Free Memory |
Μία spawned διαδικασία μπορεί να κάνει spawn και σε άλλες διαδικασίες. Το όριο των nested spawn ορίζεται από την ελεύθερη RAM και το μέγεθος των προγραμμάτων.
Π.χ.: #include <stdio.h> / * Parent Process * /
#include
<process.h>
main(
)
{
printf
( “In Parent \n”);
spawnl
(P_WAIT, “Test.Exe”, “Test.Exe”, “hello”, “10”, NULL);
printf
(“\n Back in Parent”);
}
#include
<stdio.h> / * First
Child * /
#include
<process.h>
main
(int argc, char *argv[ ] )
{
printf
(“First Child Process executed with this command line: “);
printf
(“Arguments: “);
printf
(argv [1]);
printf
(“%d”, atoi (argv[2])); spawnl(P_WAIT, “Test2.Exe”, NULL);
printf
(“\n Back if First Child Process”);
}
main(
)
{
printf(“In
Second Child Process”);
}
Το παράδειγμα αυτό περιλαμβάνει ένα parent program, το οποίο καλεί ένα child. Το child τυπώνει τις παραμέτρους κλήσεις του και καλεί ένα δεύτερο child. Μετά το τέλος του δεύτερου childe επιστρέφει στο πρώτο child και έπειτα στο parent.