Comment créer des sémaphores dans la mémoire partagée en C?

Ma tâche consiste à créer deux fichiers C différents, puis à utiliser les sémaphores pour la synchronisation des processus (j’exécute les deux fichiers C simultanément).

Ma principale préoccupation est la suivante: si je veux accéder aux sémaphores dans les deux processus (exécutables des fichiers C), je dois créer les sémaphores dans la mémoire partagée. Aussi, j’ai besoin de créer des sémaphores binarys.

Puisqu’il s’agit de mon premier programme, quelqu’un peut-il suggérer comment s’y prendre?

Je suis capable de créer et d’utiliser de la mémoire partagée, des sémaphores utilisés dans les threads. J’ai aussi regardé des conférences sur YouTube, mais je n’ai pas trouvé de solution adéquate.

Les sémaphores inter-processus sont une opération spécifique du système d’exploitation.

La plupart de ces solutions partagent le fait que vous créez le sémaphore en un processus via un chemin virtuel qui est appelé le nom du sémaphore. Si les permissions sont correctement définies, vous pouvez ouvrir le sémaphore dans un autre processus en utilisant le même chemin virtuel. Ces chemins virtuels ne sont généralement pas de vrais chemins de système de fichiers, même s’ils vous semblent familiers.

Sur les systèmes POSIX / System V, vous avez généralement deux options. Les différences entre les deux options sont très bien expliquées dans cette réponse .

Sémaphores Système V

Ce sont des sémaphores basés sur des chemins qui peuvent être obtenus avec semget() :

 #include  #include  #include  int sem; int sem_id = 1; key_t key; key = ftok("/virtualpathtosemaphore", 1); // create a new semaphore sem = semget(key, 1, IPC_CREAT); // use sem = semget(key, 1, 0); to attach to an existing semaphore // flags also contain access rights, to take care to set them appropriately // increment semaphore struct sembuf semopinc = { .sem_num = 0, .sem_op = 1, .sem_flg = 0 }; semop(sem, &semopinc, 1); /* decrement semaphore, may block */ struct sembuf semopdec = { .sem_num = 0, .sem_op = -1, .sem_flg = 0 }; semop(sem, &semopdec, 1); 

Notez qu’il est important de nettoyer les sémaphores, car les sémaphores System V restnt jusqu’à ce qu’ils soient explicitement non liés. Ce qui est plutôt un problème lorsqu’un processus se bloque sans nettoyer ses sémaphores (par exemple, FreeBSD est fourni avec un utilitaire ipcrm qui supprime les objects IPC System V suspendus).

Sémaphores POSIX

Celles-ci sont en réalité moins largement implémentées, alors vérifiez si votre kernel les prend en charge. La version nommée de ceux-ci est obtenue via sem_open() .

 #include  sem_t *sem; sem = sem_open("/nameofsemaphore", O_CREAT, permissions, 0); // use sem = sem_open("/nameofsemaphore", 0) to open an existing semaphore /* increment semaphore */ sem_post(sem); /* decrement semaphore */ sem_wait(sem); 

Les sémaphores POSIX sont détruits implicitement lorsque le dernier processus ayant un descripteur pour le sémaphore se termine. On dit qu’ils sont plus rapides que les sémaphores System V

les fenêtres

Windows a ses propres API de sémaphore: Les sémaphores sont créés par CreateSemaphore() .

Windows utilise la même astuce de nommage que POSIX mais avec des conventions d’espace de nom différentes.

 HANDLE hSem; hSem = CreateSemaphore(NULL, 0, LONG_MAX, _T("Local\\PathToMySemaphore"); // Use OpenSemaphore() to attach to an existing semaphore // increment semaphore: ReleaseSemaphore(hSem, 1, NULL); // decrement semaphore WaitForSingleObject(hSem, 0); 

N’oubliez pas d’append une vérification d’erreur lors de l’adaptation des exemples ci-dessus. Notez également que j’ai délibérément ignoré les permissions pour simplifier le code. N’oubliez pas d’append les drapeaux pertinents.

En plus de tout cela, vous pouvez également (comme cela se faisait généralement avant l’arrivée de vrais sémaphores) abuser du locking de fichier comme une forme de mutex binary.

Vous avez dit que vous utilisiez Ubuntu GNU / Linux, alors …

Utilisez des sémaphores nommés!

 #include  #include  #include  #include  #include  // On first process (the one that creates the semaphore) char semaphoreName[1 + 6 + 1]; semaphoreName[0] = '/'; semaphoreName[1 + snprintf(&semaphore[1], 6 + 1, "%d", getpid())] = '/0'; sem_t *sem = sem_open(semaphoreName, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 0); // On second process sem_t *sem = sem_open(semaphoreName, O_RDWR);