Допустим, я создаю семафор. Если я разветвляюсь кучу дочерних процессов,
они все еще будут использовать тот же семафор?
Зависит от того, как вы создали семафор, чтобы сделать это с семафором IPC, см. semaphore.c: Иллюстрация простого семафора, передающего для примера.
Также предположим, что я создаю структуру с семафорами внутри и разветвлен. Делать
все дочерние процессы все еще используют тот же семафор? Если нет, то будет
хранение семафоров struct + в разделяемой памяти позволяет ребенку
процессы используют одни и те же семафоры?
Для этого ваш семафор должен храниться в области, совместно используемой родительским и дочерним процессами, например, совместно используемой памяти, а не просто создаваться в стеке или в куче, потому что он будет скопирован, когда процесс разветвится. 1013 *
Я действительно не понимаю, как мои разветвленные дочерние процессы могут использовать
те же семафоры.
Семафор можно разделить между потоками или процессами. Межпроцессное совместное использование реализовано на уровне операционной системы. Два или более разных процесса могут совместно использовать один и тот же семафор, даже если эти процессы не были созданы путем разветвления одного родительского процесса.
См. Этот пример для совместного использования безымянного семафора UNIX между родительским процессом и его дочерним (для компиляции с gcc вам понадобится флаг -pthread
):
#include <semaphore.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
int main(void)
{
/* place semaphore in shared memory */
sem_t *sema = mmap(NULL, sizeof(*sema),
PROT_READ |PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,
-1, 0);
if (sema == MAP_FAILED) {
perror("mmap");
exit(EXIT_FAILURE);
}
/* create/initialize semaphore */
if ( sem_init(sema, 1, 0) < 0) {
perror("sem_init");
exit(EXIT_FAILURE);
}
int nloop=10;
int pid = fork();
if (pid < 0) {
perror("fork");
exit(EXIT_FAILURE);
}
if (pid == 0) {
/* child process*/
for (int i = 0; i < nloop; i++) {
printf("child unlocks semaphore: %d\n", i);
if (sem_post(sema) < 0) {
perror("sem_post");
}
sleep(1);
}
if (munmap(sema, sizeof(sema)) < 0) {
perror("munmap");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
if (pid > 0) {
/* back to parent process */
for (int i = 0; i < nloop; i++) {
printf("parent starts waiting: %d\n", i);
if (sem_wait(sema) < 0) {
perror("sem_wait");
}
printf("parent finished waiting: %d\n", i);
}
if (sem_destroy(sema) < 0) {
perror("sem_destroy failed");
exit(EXIT_FAILURE);
}
if (munmap(sema, sizeof(sema)) < 0) {
perror("munmap failed");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
}
Вывод будет:
parent starts waiting: 0
child unlocks semaphore: 0
parent finished waiting: 0
parent starts waiting: 1
child unlocks semaphore: 1
parent finished waiting: 1
...
Возможно, вы также захотите прочитать Семафоры в Linux , но имейте в виду, что пример семафоров UNIX для данной вилки не работает, поскольку автор забыл использовать флаг MAP_ANONYMOUS
в mmap
.