# IPC System V Το IPC System V δίνει σε δύο μη σχετιζόμενες διεργασίες έναν κοινόχρηστο πόρο που κατέχει ο πυρήνας: ένα **σύνολο σηματοφόρων** για συντονισμό, ή ένα **τμήμα κοινόχρηστης μνήμης** για τη μεταβίβαση bytes χωρίς αντιγραφή μέσα από σωλήνα. Κάθε πόρος προσδιορίζεται από ένα ακέραιο κλειδί και επιζεί μέχρι μια διεργασία να τον αφαιρέσει ρητά. Τα αρθρώματα ευκολίας `IPC::SysV`, `IPC::Semaphore` και `IPC::SharedMem` δεν είναι διαθέσιμα στην PetaPerl, οπότε οι συνταγές εδώ χρησιμοποιούν τη χαμηλού επιπέδου οικογένεια ενσωματωμένων συναρτήσεων [`semget`](../../p5/core/perlfunc/semget.md) / [`shmget`](../../p5/core/perlfunc/shmget.md) με τις τιμές των σημαιών γραμμένες ως απλούς αριθμούς. Αυτές οι ενσωματωμένες συναρτήσεις είναι το επίπεδο που περιτυλίγουν τα αρθρώματα· η απευθείας χρήση τους κοστίζει μόνο μερικές ονομασμένες σταθερές που παρέχετε μόνοι σας. ## Οι σταθερές σημαιών που χρειάζεστε Μια χούφτα μικροί ακέραιοι ελέγχουν το πώς συμπεριφέρονται αυτές οι κλήσεις. Είναι οι τυπικές τιμές του Linux: ```perl use constant { IPC_PRIVATE => 0, # "give me a fresh, private key" IPC_CREAT => 0o1000, # create the resource if absent IPC_EXCL => 0o2000, # fail if it already exists IPC_RMID => 0, # control command: remove the resource }; ``` Τα χαμηλά εννέα bits της λέξης σημαιών είναι συνηθισμένα bits δικαιωμάτων, τα ίδια `0600` / `0644` που θα περνούσατε στην [`chmod`](../../p5/core/perlfunc/chmod.md). Το `IPC_CREAT | 0600` σημαίνει «δημιούργησέ το, ανάγνωση/εγγραφή για τον ιδιοκτήτη». ## Μια παράδοση μέσω κοινόχρηστης μνήμης Η κοινόχρηστη μνήμη είναι το ταχύτερο κανάλι: μια διεργασία γράφει bytes σε ένα τμήμα, μια άλλη τα διαβάζει κατευθείαν, χωρίς αντιγραφή από τον πυρήνα ενδιάμεσα. Αυτό το πρόγραμμα δημιουργεί ένα τμήμα, γράφει ένα ωφέλιμο φορτίο, κάνει fork, και το παιδί διαβάζει πίσω τα ίδια bytes: ```perl use constant { IPC_PRIVATE => 0, IPC_CREAT => 0o1000, IPC_RMID => 0, }; my $size = 1024; my $id = shmget(IPC_PRIVATE, $size, IPC_CREAT | 0600); defined $id or die "shmget: $!"; my $payload = "shared-payload"; shmwrite($id, $payload, 0, length $payload) or die "shmwrite: $!"; my $kid = fork() // die "fork: $!"; if ($kid == 0) { # Child reads the same segment the parent wrote. shmread($id, my $buf, 0, length $payload) or die "shmread: $!"; print "child read: $buf\n"; # child read: shared-payload exit 0; } waitpid($kid, 0); # The segment outlives the processes - remove it explicitly. shmctl($id, IPC_RMID, 0) or warn "shmctl: $!"; ``` Δύο σημεία αποφασίζουν αν αυτός ο κώδικας διαρρέει: - **Οι `shmread` / `shmwrite` παίρνουν ρητό μήκος.** Δεν σταματούν σε ένα NUL ή σε έναν χαρακτήρα νέας γραμμής· τους λέτε ακριβώς πόσα bytes να μετακινήσουν, ξεκινώντας από μια μετατόπιση. Περάστε `length $payload` ώστε ο αναγνώστης και ο εγγραφέας να συμφωνούν ως προς το μέγεθος. - **Το `IPC_RMID` δεν είναι αυτόματο.** Ένα κοινόχρηστο τμήμα παραμένει στον πυρήνα αφού κάθε διεργασία που είχε προσαρτηθεί σε αυτό έχει τερματίσει. Μπορείτε να δείτε ορφανά τμήματα με `ipcs -m` στο κέλυφος. Πάντα να συνδυάζετε ένα [`shmget`](../../p5/core/perlfunc/shmget.md) με ένα αντίστοιχο [`shmctl`](../../p5/core/perlfunc/shmctl.md) `IPC_RMID`. ## Ένας σηματοφόρος για συντονισμό Ένα σύνολο σηματοφόρων είναι ένας μικρός πίνακας μετρητών που φυλά ο πυρήνας. Η κλασική χρήση είναι ένα κλείδωμα: μια διεργασία μειώνει τον μετρητή για να εισέλθει σε ένα κρίσιμο τμήμα και τον αυξάνει για να εξέλθει. Αυτή η συνταγή δημιουργεί ένα σύνολο ενός στοιχείου, το αρχικοποιεί, και το αφαιρεί: ```perl use constant { IPC_PRIVATE => 0, IPC_CREAT => 0o1000, IPC_RMID => 0, SETVAL => 16, # semctl command: set one value GETVAL => 12, # semctl command: read one value }; # A set with one semaphore. my $sem = semget(IPC_PRIVATE, 1, IPC_CREAT | 0600); defined $sem or die "semget: $!"; # Initialise semaphore 0 to the value 1 (one token available). semctl($sem, 0, SETVAL, 1) or die "semctl SETVAL: $!"; my $value = semctl($sem, 0, GETVAL, 0); print "semaphore value: $value\n"; # semaphore value: 1 # Remove the set when finished. semctl($sem, 0, IPC_RMID, 0) or warn "semctl IPC_RMID: $!"; ``` Οι ίδιες οι λειτουργίες αναμονής/σηματοδότησης περνούν μέσα από την [`semop`](../../p5/core/perlfunc/semop.md), η οποία παίρνει μια πακεταρισμένη συμβολοσειρά τριάδων `(sem_num, sem_op, sem_flg)` χτισμένη με [`pack`](../../p5/core/perlfunc/pack.md). Η μείωση κατά ένα περιμένει μέχρι ένα διακριτικό να είναι ελεύθερο· η αύξηση κατά ένα το απελευθερώνει. Όπως με την κοινόχρηστη μνήμη, ένα σύνολο σηματοφόρων που κατέχει ο πυρήνας πρέπει να αφαιρεθεί με `IPC_RMID` αλλιώς παραμένει - ορατό υπό το `ipcs -s`. ## Διασταυρούμενοι σύνδεσμοι αναφοράς - [`shmget`](../../p5/core/perlfunc/shmget.md) - δημιουργεί ή ανοίγει ένα κοινόχρηστο τμήμα - [`shmread`](../../p5/core/perlfunc/shmread.md) / [`shmwrite`](../../p5/core/perlfunc/shmwrite.md) - μετακινούν bytes προς τα μέσα και προς τα έξω - [`shmctl`](../../p5/core/perlfunc/shmctl.md) - έλεγχος, συμπεριλαμβανομένου του `IPC_RMID` - [`semget`](../../p5/core/perlfunc/semget.md) - δημιουργεί ή ανοίγει ένα σύνολο σηματοφόρων - [`semop`](../../p5/core/perlfunc/semop.md) - οι λειτουργίες αναμονής/σηματοδότησης - [`semctl`](../../p5/core/perlfunc/semctl.md) - ορισμός, ανάγνωση και αφαίρεση - [`pack`](../../p5/core/perlfunc/pack.md) - χτίζει τη συμβολοσειρά λειτουργίας της `semop` ## Επόμενο Η κοινόχρηστη μνήμη και οι σηματοφόροι είναι τα βαρέα κανάλια. Για τα ελαφρύτερα, προσανατολισμένα σε ροή, δείτε [Υποδιεργασίες και συνεργαζόμενες διεργασίες](subprocesses.md) και [Υποδοχές TCP](sockets-tcp.md).