Используют ли разветвленные дочерние процессы один и тот же семафор?
Допустим, я создаю семафор. Если я разветвляюсь на кучу дочерних процессов, все ли они будут использовать тот же семафор?
Кроме того, предположим, что я создаю структуру с семафорами внутри и разветвленной. Все ли дочерние процессы все еще используют один и тот же семафор? Если нет, хранение семафоров struct + в разделяемой памяти позволит дочерним процессам использовать те же семафоры?
Я действительно не понимаю, как мои дочерние процессы могут использовать одни и те же семафоры.
3 ответа
Допустим, я создаю семафор. Если я разветвляюсь на кучу дочерних процессов, все ли они будут использовать тот же семафор?
Если вы используете семафор SysV IPC (semctl
), тогда да. Если вы используете семафоры POSIX (sem_init
), тогда да, но только если вы передадите истинное значение аргумента pshared при создании и поместите его в общую память.
Кроме того, предположим, что я создаю структуру с семафорами внутри и разветвленной. Все ли дочерние процессы все еще используют один и тот же семафор? Если нет, хранение семафоров struct+ в разделяемой памяти позволит дочерним процессам использовать те же семафоры?
Что ты имеешь в виду под "семафорами внутри"? Ссылки на семафоры SysV IPC будут общими, потому что семафоры не принадлежат ни одному процессу. Если вы используете семафоры POSIX или создаете что-то из мьютексов и condvars pthreads, вам потребуется использовать разделяемую память и атрибут pshared (pthreads также имеет атрибут pshared для condvars и mutex)
Обратите внимание, что анонимные карты создаются с помощью MAP_SHARED
Отметить как (анонимную) разделяемую память для этих целей, поэтому нет необходимости фактически создавать именованный сегмент совместно используемой памяти. Обычная память кучи не будет разделяться после разветвления.
Допустим, я создаю семафор. Если я разветвляюсь на кучу дочерних процессов, все ли они будут использовать тот же семафор?
Зависит от того, как вы создали семафор, чтобы сделать это с помощью семафора IPC, см. Semaphore.c: Иллюстрация передачи простого семафора для примера.
Кроме того, предположим, что я создаю структуру с семафорами внутри и разветвленной. Все ли дочерние процессы все еще используют один и тот же семафор? Если нет, хранение семафоров struct + в разделяемой памяти позволит дочерним процессам использовать те же семафоры?
Для этого ваш семафор должен храниться в области, совместно используемой родительским и дочерним процессами, например, совместно используемой памяти, а не просто создаваться в стеке или в куче, потому что он будет скопирован, когда процесс разветвится.
Я действительно не понимаю, как мои дочерние процессы могут использовать одни и те же семафоры.
Семафор может быть разделен между потоками или процессами. Межпроцессное совместное использование реализовано на уровне операционной системы. Два или более разных процесса могут совместно использовать один и тот же семафор, даже если эти процессы не были созданы путем разветвления одного родительского процесса.
Посмотрите этот пример для совместного использования безымянного семафора 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
,
Попробуй это
child и parent будут увеличивать переменную общего доступа в качестве альтернативы
#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>
struct test {
sem_t mutex1;
sem_t mutex2;
int temp;
}test1;
int main(int argc, char **argv)
{
int fd, i,count=0,nloop=10,zero=0,*ptr;
struct test *testptr;
//open a file and map it into memory
sem_t mutex;
fd = open("log.txt",O_RDWR|O_CREAT,S_IRWXU);
write(fd,&zero,sizeof(int));
ptr = mmap(NULL, sizeof(struct test),PROT_READ |PROT_WRITE,MAP_SHARED,fd,0);
close(fd);
memcpy(ptr, &test1, sizeof(test1));
testptr = (struct test *)ptr;
// testptr = (struct test *)&test1;
/* create, initialize semaphore */
if( sem_init(&(testptr->mutex1),1,1) < 0)
{
perror("semaphore initilization");
exit(0);
}
/* create, initialize semaphore */
if( sem_init(&(testptr->mutex2),1,0) < 0)
{
perror("semaphore initilization");
exit(0);
}
if (fork() == 0) { /* child process*/
for (i = 0; i < nloop; i++) {
sem_wait(&(testptr->mutex2));
printf("child: %d\n", testptr->temp++);
sem_post(&(testptr->mutex1));
}
exit(0);
/* back to parent process */
for (i = 0; i < nloop; i++) {
sem_wait(&testptr->mutex1);
printf("parent: %d\n", testptr->temp++);
sem_post(&(testptr->mutex2));
}
exit(0);
}