Как найти причину сбоя установки futex?
Я пытаюсь синхронизировать 5 процессов, они должны быть созданы от одного отца.
Я попытался вставить 5 ожиданий, чтобы дождаться завершения дочернего процесса, но код никогда не достигает D4 и D5.
#include <unistd.h>
#include <semaphore.h>
#include <stdlib.h>
#include <sys/wait.h>
void func1(sem_t sem1, sem_t sem2);
void func2(sem_t sem1, sem_t sem2);
void func3(sem_t sem1, sem_t sem2);
void func4(sem_t sem1, sem_t sem2);
void func5(sem_t sem1, sem_t sem2);
int main() {
sem_t s1;
sem_t s2;
sem_init(&s1, 1, -1);
sem_init(&s2, 1, -1);
void (*arr[5])(sem_t, sem_t) = {func1, func2, func3, func4, func5};
int pid;
for (int i=0; i<5; i++) {
pid = fork();
if (pid == 0) {
arr[i](s1, s2);
break;
}
}
return 0;
}
void func1(sem_t sem1, sem_t sem2) {
system("echo D1");
sem_post(&sem1);
}
void func2(sem_t sem1, sem_t sem2) {
system("echo D2");
sem_post(&sem1);
}
void func3(sem_t sem1, sem_t sem2) {
system("echo D3");
sem_post(&sem2);
}
void func4(sem_t sem1, sem_t sem2) {
sem_wait(&sem1);
system("echo D4");
sem_post(&sem2);
}
void func5(sem_t sem1, sem_t sem2) {
sem_wait(&sem2);
system("echo D5");
}
Я ожидаю, что D4 будет показан после D1 и D2, а D5 будет показан последним (D3 не зависит от D1,D2,D4). Но мой код никогда не достигает D4, потому что средство futex возвращает неожиданную ошибку.
Выход:
The futex facility returned an unexpected error code.D1
D2
D3
2 ответа
Вы передаете семафоры по значению, что неверно, так как sem_t
Переменная в каждой функции является копией оригинала. (Вот почему такие функции, как sem_init()
, sem_post()
, а также sem_wait()
все принимают адреса семафора в качестве аргумента.)
Вам нужно передать семафоры по адресу, чтобы каждая функция работала с исходными семафорами:
void func1(sem_t *sem1, sem_t *sem2);
void func2(sem_t *sem1, sem_t *sem2);
void func3(sem_t *sem1, sem_t *sem2);
void func4(sem_t *sem1, sem_t *sem2);
void func5(sem_t *sem1, sem_t *sem2);
а также
void (*arr[5])(sem_t *, sem_t *) = {func1, func2, func3, func4, func5};
И вызвать функцию как:
arr[i](&s1, &s2);
Функции должны принять форму:
void func1(sem_t *sem1, sem_t *sem2) {
system("echo D1");
sem_post(sem1);
}
Обратите внимание, что адрес передан func1()
передается непосредственно sem_post()
,
Редактировать:
Как уже отмечали другие, вы неправильно инициализируете семафоры. Вы не можете инициализировать семафор с отрицательным значением.
Правильные общие семафоры
Как отмечено в комментариях, семфоры не находятся в памяти, разделяемой между несколькими процессами.
Один из способов поместить семфоры в разделяемую память - это использовать mmap()
:
#include <sys/mman.h>
int main() {
...
// map a 4k page of shared memory (assumes a sem_t is small
// enough to fit at least two)
void *sharedMem = mmap( 0, 4 * 1024, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0 );
// use the mmap()'d memory as shared semphores
sem_t *semArray = ( sem_t * ) sharedMem;
// initialize the semaphores
sem_init( &( semArray[ 0 ] ), 1, 0 );
sem_init( &( semArray[ 1 ] ), 1, 0 );
Код вызова становится
arr[i](&( semArray[ 0 ] ), &( semArray[ 1 ] ));
Таким образом, в этот код было внесено 2 небольших изменения.
- Сначала вам нужно правильно инициализировать семафоры.
sem_init(&s1, 1, 1);
вместоsem_init(&s1, 1, -1);
- Ваш родительский процесс должен дождаться завершения всех дочерних процессов, прежде чем сам завершится. Следовательно
wait(NULL);
в основном до окончания программы.
,
#include <unistd.h>
#include <semaphore.h>
#include <stdlib.h>
#include <sys/wait.h>
void func1(sem_t sem1, sem_t sem2);
void func2(sem_t sem1, sem_t sem2);
void func3(sem_t sem1, sem_t sem2);
void func4(sem_t sem1, sem_t sem2);
void func5(sem_t sem1, sem_t sem2);
int main() {
sem_t s1;
sem_t s2;
sem_init(&s1, 1, 1);
sem_init(&s2, 1, 1);
void (*arr[5])(sem_t, sem_t) = {func1, func2, func3, func4, func5};
pid_t child_pid, wpid;
int status;
for (int i=0; i<5; i++) {
child_pid = fork();
if (child_pid == 0) {
arr[i](s1, s2);
// break;
exit(0);
}
}
wait(NULL);
// while ((wpid = wait(&status)) > 0);
return 0;
}
void func1(sem_t sem1, sem_t sem2) {
system("echo D1");
sem_post(&sem1);
}
void func2(sem_t sem1, sem_t sem2) {
system("echo D2");
sem_post(&sem1);
}
void func3(sem_t sem1, sem_t sem2) {
system("echo D3");
sem_post(&sem2);
}
void func4(sem_t sem1, sem_t sem2) {
sem_wait(&sem1);
system("echo D4");
sem_post(&sem2);
}
void func5(sem_t sem1, sem_t sem2) {
sem_wait(&sem2);
system("echo D5");
}
Вы можете запустить и проверить здесь. онлайн код