如何找到导致 futex 设施失败的原因?
How to find what causes the futex facility to fail?
我正在尝试同步 5 个进程,它们必须由同一个父进程创建。
我尝试插入5个waitpids来等待子进程结束,但是代码始终没有到达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 工具 returns 一个意外错误。
输出:
The futex facility returned an unexpected error code.D1
D2
D3
因此,需要对该代码进行 2 处小改动。
- 首先你需要正确初始化信号量。
sem_init(&s1, 1, 1);
而不是 sem_init(&s1, 1, -1);
- 您的父进程需要等待所有子进程退出,然后才能自行退出。因此,在程序结束之前,main 中的
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");
}
您可以 运行 并在此处查看。 oneline code
您通过 value 传递信号量,这是不正确的,因为每个函数中的 sem_t
变量是 copy 原来的。 (这就是为什么 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 ] ));
我正在尝试同步 5 个进程,它们必须由同一个父进程创建。
我尝试插入5个waitpids来等待子进程结束,但是代码始终没有到达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 工具 returns 一个意外错误。
输出:
The futex facility returned an unexpected error code.D1
D2
D3
因此,需要对该代码进行 2 处小改动。
- 首先你需要正确初始化信号量。
sem_init(&s1, 1, 1);
而不是sem_init(&s1, 1, -1);
- 您的父进程需要等待所有子进程退出,然后才能自行退出。因此,在程序结束之前,main 中的
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");
}
您可以 运行 并在此处查看。 oneline code
您通过 value 传递信号量,这是不正确的,因为每个函数中的 sem_t
变量是 copy 原来的。 (这就是为什么 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 ] ));