Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
POSIX信号量在C中,但仍有竞争条件?_C_Linux_Posix - Fatal编程技术网

POSIX信号量在C中,但仍有竞争条件?

POSIX信号量在C中,但仍有竞争条件?,c,linux,posix,C,Linux,Posix,我试图理解信号量,但我无法理解。我想我的代码中仍然有种族条件 这个概念非常简单,使用命令行参数-a、-b、-c或-d启动这个程序4次。开始顺序应该不重要,但是使用下面的代码(见下文)就可以了,我不太清楚为什么 最后,打印输出应12345678 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h>

我试图理解信号量,但我无法理解。我想我的代码中仍然有种族条件

这个概念非常简单,使用命令行参数-a、-b、-c或-d启动这个程序4次。开始顺序应该不重要,但是使用下面的代码(见下文)就可以了,我不太清楚为什么

最后,打印输出应
12345678

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/fcntl.h>

sem_t *semdes = SEM_FAILED;
char *sem_name = "test";

int main(int argc, char *const *argv)
{
    int opt, res;
    semdes = sem_open(sem_name, O_CREAT | O_EXCL, 0600, 4);
    printf("sem_open() returned %p\n", semdes);
    if (semdes == SEM_FAILED)
    {
        semdes = sem_open(sem_name, 0);
    }
    if ((opt = getopt(argc, argv, "abcd:")) != -1)
    {
        switch (opt)
        {
        case 'a':
            //printNumbers(1, 5);
            sem_wait(semdes);
            res = sem_wait(semdes);
            if (res != 0)
            {
                perror("ERROR: sem_wait() failed");
            }
            printf("sem_wait() returned %d\n", res);
            printf("%d\n", 1);
            sleep(1);
            sem_post(semdes);
            sem_wait(semdes);
            res = sem_wait(semdes);
            if (res != 0)
            {
                perror("ERROR: sem_wait() failed");
            }
            printf("sem_wait() returned %d\n", res);
            printf("%d\n", 5);
            sleep(1);
            sem_post(semdes);

            break;
        case 'b':
            sem_wait(semdes);
            res = sem_wait(semdes);
            if (res != 0)
            {
                perror("ERROR: sem_wait() failed");
            }
            printf("sem_wait() returned %d\n", res);
            printf("%d\n", 2);
            sleep(1);
            sem_post(semdes);
            //printNumbers(2, 6);
            break;
        case 'c':
            sem_wait(semdes);
            res = sem_wait(semdes);
            if (res != 0)
            {
                perror("ERROR: sem_wait() failed");
            }
            printf("sem_wait() returned %d\n", res);
            printf("%d\n", 3);
            sleep(1);
            sem_post(semdes);
            //printNumbers(3, 7);
            break;
        case 'd':
            sem_wait(semdes);
            res = sem_wait(semdes);
            if (res != 0)
            {
                perror("ERROR: sem_wait() failed");
            }
            printf("sem_wait() returned %d\n", res);
            printf("%d\n", 4);
            sleep(1);
            sem_post(semdes);
            //printNumbers(4, 8);
            break;
        default:
            fprintf(stderr, "ERROR: unknown option '%c'\n", opt);
            exit(1);
            break;
        }
    }
    else
    {
        exit(1);
    }

    return 0;
}

多亏了基督教使用多个信号量的思想,我解决了这个问题

最终代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/fcntl.h>

sem_t *semA = SEM_FAILED;
sem_t *semB = SEM_FAILED;
sem_t *semC = SEM_FAILED;
sem_t *semD = SEM_FAILED;
sem_t *sem1 = SEM_FAILED;
sem_t *sem2 = SEM_FAILED;
char *nameA = "testa";
char *nameB = "testb";
char *nameC = "testc";
char *nameD = "testd";

int printNumbers(char *name1, char *name2, int no)
{
    //open own semaphore first
    sem1 = sem_open(name1, O_CREAT, 0600, 0);
    int res = sem_wait(sem1);
    if (res != 0)
    {
        perror("PROG: ERROR: sem_wait() failed");
    }
    //printf("sem_wait() of %s returned %d\n", name1, res);
    printf("%d\n", no);
    sem_close(sem1);
    sleep(5);
    //open next semaphore
    sem2 = sem_open(name2, O_CREAT, 0600, 1);
    sem_post(sem2);
    sem_close(sem2);
    return res;
}

void cleanUp()
{
    char name[6] = "testa";
    int res = 0;
    for (size_t i = 0; i < 4; i++)
    {
        res = sem_unlink(name);
        if (res != 0)
        {
            perror("ERROR: sem_unlink() failed");
        }
        printf("sem_unlink() returned %d\n", res);
        name[4] = name[4]+1;
    }
}

int main(int argc, char *const *argv)
{
    int opt, res;

    if ((opt = getopt(argc, argv, "abcd")) != -1)
    {
        switch (opt)
        {
        case 'a':
            // Guarantees 1 is always first since no semaphore
            printf("\n%d\n", 1);
            sleep(5);
            semB = sem_open(nameB, O_CREAT, 0600, 1);
            sem_post(semB);
            sleep(5);
            sem_close(semB);
            printNumbers(nameA, nameB, 5);
            break;
        case 'b':
            printNumbers(nameB, nameC, 2);
            printNumbers(nameB, nameC, 6);
            break;
        case 'c':
            printNumbers(nameC, nameD, 3);
            printNumbers(nameC, nameD, 7);
            break;
        case 'd':
            printNumbers(nameD, nameA, 4);
            printNumbers(nameD, nameA, 8);
            cleanUp();
            break;
        default:
            fprintf(stderr, "ERROR: unknown option '%c'\n", opt);
            exit(1);
            break;
        }
    }
    else
    {
        exit(1);
    }
    return 0;
}

打印输出是什么?@SteveFriedl我现在添加了输出-(同时删除
你在
“abcd:
)我相信如果一个信号灯有多个侍者,那么不可能预测哪个(单个)侍者会被唤醒,所以这些几乎可以以任何顺序出现,只要1在5之前,2在6之前,等等。@Pascalerino使用不同的信号量。当进程A完成时,它释放进程B正在睡眠的信号量,这反过来又释放进程C正在睡眠的信号量,以此类推。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/fcntl.h>

sem_t *semA = SEM_FAILED;
sem_t *semB = SEM_FAILED;
sem_t *semC = SEM_FAILED;
sem_t *semD = SEM_FAILED;
sem_t *sem1 = SEM_FAILED;
sem_t *sem2 = SEM_FAILED;
char *nameA = "testa";
char *nameB = "testb";
char *nameC = "testc";
char *nameD = "testd";

int printNumbers(char *name1, char *name2, int no)
{
    //open own semaphore first
    sem1 = sem_open(name1, O_CREAT, 0600, 0);
    int res = sem_wait(sem1);
    if (res != 0)
    {
        perror("PROG: ERROR: sem_wait() failed");
    }
    //printf("sem_wait() of %s returned %d\n", name1, res);
    printf("%d\n", no);
    sem_close(sem1);
    sleep(5);
    //open next semaphore
    sem2 = sem_open(name2, O_CREAT, 0600, 1);
    sem_post(sem2);
    sem_close(sem2);
    return res;
}

void cleanUp()
{
    char name[6] = "testa";
    int res = 0;
    for (size_t i = 0; i < 4; i++)
    {
        res = sem_unlink(name);
        if (res != 0)
        {
            perror("ERROR: sem_unlink() failed");
        }
        printf("sem_unlink() returned %d\n", res);
        name[4] = name[4]+1;
    }
}

int main(int argc, char *const *argv)
{
    int opt, res;

    if ((opt = getopt(argc, argv, "abcd")) != -1)
    {
        switch (opt)
        {
        case 'a':
            // Guarantees 1 is always first since no semaphore
            printf("\n%d\n", 1);
            sleep(5);
            semB = sem_open(nameB, O_CREAT, 0600, 1);
            sem_post(semB);
            sleep(5);
            sem_close(semB);
            printNumbers(nameA, nameB, 5);
            break;
        case 'b':
            printNumbers(nameB, nameC, 2);
            printNumbers(nameB, nameC, 6);
            break;
        case 'c':
            printNumbers(nameC, nameD, 3);
            printNumbers(nameC, nameD, 7);
            break;
        case 'd':
            printNumbers(nameD, nameA, 4);
            printNumbers(nameD, nameA, 8);
            cleanUp();
            break;
        default:
            fprintf(stderr, "ERROR: unknown option '%c'\n", opt);
            exit(1);
            break;
        }
    }
    else
    {
        exit(1);
    }
    return 0;
}
1
2
3
4
5
6
7
8
sem_unlink() returned 0
sem_unlink() returned 0
sem_unlink() returned 0
sem_unlink() returned 0