簡體   English   中英

如何找到導致futex設施失敗的原因?

[英]How to find what causes the futex facility to fail?

我正在嘗試同步 5 個進程,它們必須由同一個父親創建。

我嘗試插入 5 個 waitpid 以等待子進程結束,但代碼從未到達 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

您通過value傳遞信號量,這是不正確的,因為每個函數中的sem_t變量是原始變量的副本 (這就是為什么sem_init()sem_post()sem_wait()sem_wait()都將信號量的地址作為參數的原因。)

您需要通過address傳遞信號量,因此每個函數都對原始信號量進行操作:

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 個小的更改。

  1. 首先,您需要正確初始化信號量。 sem_init(&s1, 1, 1); 而不是sem_init(&s1, 1, -1);
  2. 您的父進程需要等待所有子進程退出,然后才能退出。 因此wait(NULL); 在程序結束之前的 main 中。

.

#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");
}

您可以在此處運行並檢查。 在線代碼

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM