Zoeken…


Invoering

Interprocescommunicatie (IPC) mechanismen laten verschillende onafhankelijke processen toe om met elkaar te communiceren. Standaard C biedt geen IPC-mechanismen. Daarom worden al dergelijke mechanismen gedefinieerd door het besturingssysteem van de host. POSIX definieert een uitgebreide reeks IPC-mechanismen; Windows definieert een andere set; en andere systemen definiëren hun eigen varianten.

semaforen

Semaphores worden gebruikt om bewerkingen tussen twee of meer processen te synchroniseren. POSIX definieert twee verschillende sets semafoorfuncties:

  1. 'System V IPC' - semctl() , semop() , semget() .
  2. 'POSIX Semaphores' - sem_close() , sem_destroy() , sem_getvalue() , sem_init() , sem_open() , sem_post() , sem_trywait() , sem_unlink() .

In deze sectie worden de System V IPC-semaforen beschreven, zo genoemd omdat ze zijn ontstaan met Unix System V.

Eerst moet u de vereiste kopteksten opnemen. Oude versies van POSIX vereist #include <sys/types.h> ; moderne POSIX en de meeste systemen vereisen dit niet.

#include <sys/sem.h>

Vervolgens moet u een sleutel definiëren in zowel de ouder als het kind.

#define KEY 0x1111 

Deze sleutel moet in beide programma's hetzelfde zijn, anders verwijzen ze niet naar dezelfde IPC-structuur. Er zijn manieren om een overeengekomen sleutel te genereren zonder de waarde ervan hard te coderen.

Vervolgens moet u, afhankelijk van uw compiler, deze stap wel of niet uitvoeren: een unie declareren voor semafoorbewerkingen.

union semun {
    int val;
    struct semid_ds *buf;
    unsigned short  *array;
};

Definieer vervolgens je try ( semwait ) en raise ( semsignal ) structuren. De namen P en V zijn afkomstig uit het Nederlands

struct sembuf p = { 0, -1, SEM_UNDO}; # semwait
struct sembuf v = { 0, +1, SEM_UNDO}; # semsignal

Begin nu met het verkrijgen van de id voor uw IPC-semafoor.

int id;
// 2nd argument is number of semaphores
// 3rd argument is the mode (IPC_CREAT creates the semaphore set if needed)
if ((id = semget(KEY, 1, 0666 | IPC_CREAT) < 0) {
    /* error handling code */
}

Initialiseer de semafoor in de ouder om een teller van 1 te hebben.

union semun u;
u.val = 1;
if (semctl(id, 0, SETVAL, u) < 0) { // SETVAL is a macro to specify that you're setting the value of the semaphore to that specified by the union u
    /* error handling code */
}

Nu kunt u de semafoor naar wens verlagen of verhogen. Aan het begin van uw kritieke sectie semop() u de teller met de semop() -functie:

if (semop(id, &p, 1) < 0) {
    /* error handling code */
}

Om de semafoor te verhogen, gebruikt u &v plaats van &p :

if (semop(id, &v, 1) < 0) {
    /* error handling code */
}

Merk op dat elke functie 0 retourneert bij succes en -1 bij mislukking. Het niet controleren van deze retourstatussen kan verwoestende problemen veroorzaken.


Voorbeeld 1.1: Racen met threads

Onderstaande programma zal een proces fork een kind en zowel ouder als kind poging om tekens op de terminal af te drukken zonder enige synchronisatie.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

int main()
{
    int pid;
    pid =  fork();
    srand(pid);
    if(pid < 0)
    {
        perror("fork"); exit(1);
    }
    else if(pid)
    {
        char *s = "abcdefgh";
        int l = strlen(s);
        for(int i = 0; i < l; ++i)
        {
            putchar(s[i]);
            fflush(stdout);
            sleep(rand() % 2);
            putchar(s[i]);
            fflush(stdout);
            sleep(rand() % 2);
        }
    }
    else
    {
        char *s = "ABCDEFGH";
        int l = strlen(s);
        for(int i = 0; i < l; ++i)
        {
            putchar(s[i]);
            fflush(stdout);
            sleep(rand() % 2);
            putchar(s[i]);
            fflush(stdout);
            sleep(rand() % 2);
        }
    }
}

Uitgang (1e run):

aAABaBCbCbDDcEEcddeFFGGHHeffgghh

(2e run):

aabbccAABddBCeeCffgDDghEEhFFGGHH

Het compileren en uitvoeren van dit programma zou je elke keer een andere output moeten geven.

Voorbeeld 1.2: Vermijd racen met semaphores

Wijzigingen in voorbeeld 1.1 om semaforen te gebruiken, hebben we:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

#define KEY 0x1111

union semun {
    int val;
    struct semid_ds *buf;
    unsigned short  *array;
};

struct sembuf p = { 0, -1, SEM_UNDO};
struct sembuf v = { 0, +1, SEM_UNDO};

int main()
{
    int id = semget(KEY, 1, 0666 | IPC_CREAT);
    if(id < 0)
    {
        perror("semget"); exit(11);
    }
    union semun u;
    u.val = 1;
    if(semctl(id, 0, SETVAL, u) < 0)
    {
        perror("semctl"); exit(12);
    }
    int pid;
    pid =  fork();
    srand(pid);
    if(pid < 0)
    {
        perror("fork"); exit(1);
    }
    else if(pid)
    {
        char *s = "abcdefgh";
        int l = strlen(s);
        for(int i = 0; i < l; ++i)
        {
            if(semop(id, &p, 1) < 0)
            {
                perror("semop p"); exit(13);
            }
            putchar(s[i]);
            fflush(stdout);
            sleep(rand() % 2);
            putchar(s[i]);
            fflush(stdout);
            if(semop(id, &v, 1) < 0)
            {
                perror("semop p"); exit(14);
            }

            sleep(rand() % 2);
        }
    }
    else
    {
        char *s = "ABCDEFGH";
        int l = strlen(s);
        for(int i = 0; i < l; ++i)
        {
            if(semop(id, &p, 1) < 0)
            {
                perror("semop p"); exit(15);
            }
            putchar(s[i]);
            fflush(stdout);
            sleep(rand() % 2);
            putchar(s[i]);
            fflush(stdout);
            if(semop(id, &v, 1) < 0)
            {
                perror("semop p"); exit(16);
            }

            sleep(rand() % 2);
        }
    }
}

Output:

aabbAABBCCccddeeDDffEEFFGGHHgghh

Door dit programma te compileren en uit te voeren, krijgt u elke keer dezelfde uitvoer.



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow