【问题标题】:Linux fork,semaphore,pipe with CLinux fork,信号量,管道与 C
【发布时间】:2018-04-23 12:13:12
【问题描述】:

所以我想了解信号量是如何使用分叉的。我编写了一个 C 程序,它分叉一次并通过管道将整数从子 pid 传递到父 pid 4 次。因此,我已经能够通过分叉子项之间的管道成功地读/写。但是,当我尝试将多个写入循环到我的管道时遇到了问题。我正在尝试使用信号量来调节我的管道,以获得交替的写入、读取、写入、读取等功能。我的带有信号量的代码现在会生成 SEGFAULTS,或者在打印出我的标题后就挂起。我知道我可以用另一个管道来完成这项规定,但我专门这样做是为了更好地理解信号量。我一直在读一本操作系统的书,但它并没有真正点击;谁能通过我的代码示例向我解释这一点? (这不是作业)

/*****PROTOTYPES*****/
int SpawnBots();
void sender(int fd[2], sem_t *sem);
void receiver(int fd[2], sem_t *sem);

int exp(int base, int exponent);

int main(int argc, char *argv[]) {
    printf("WELCOME...\n");
    SpawnBots();

    return 0;
}


int SpawnBots() {
    sem_t *sem = sem_open("test_semaphore", O_CREAT | O_EXCL, 1, 1);
    sem_unlink("test_semaphore");
    int fd[2];              //0=input   1=output
    pid_t pid;

    //sem_init(sem, 1, 1);
    pipe(fd);
    pid = fork();

    if(pid==0) {
        //pid=0 is child
        sender(fd, sem);
    } else {
        //pid!=0 is parent
        receiver(fd, sem);
    }

    return 0;
}


void sender(int fd[2], sem_t *sem) {
    //child closes read pipe
    fflush(stdout);
    close(fd[0]);

    int val;
    char buffer[32];

    //writes 4 numbers to stdout
    for(int i=1; i<=4; i++) {
        sem_wait(sem);      //takes control; waits for read from receiver()

        val = exp((i+3), i);
        printf("\tChild %d: \t%d\n", i, val);       //prints out current data its writing
        sprintf(buffer, "%d", val);
        write(fd[1], buffer, strlen(buffer) + 1);   //writes to stdout

        sem_post(sem);      //hands back control
    }

    close(fd[1]);
    sem_close(sem);
    exit(0);
}


void receiver(int fd[2], sem_t *sem) {
    //child closes write pipe
    //fflush(stdout);
    close(fd[1]);

    int val;
    int i=1;
    int nbytes=1;
    char buffer[32];

    //reads in numbers until stdout is empty
    while(1) {
        sem_wait(sem);      //takes control; waits for write from sender()

        if((nbytes = read(fd[0], buffer, sizeof(buffer)+1)) > 0) {      //reads from stdout
            val = atoi(buffer);
            printf("\tParent %d: \t%d\n", i, val);      //prints out current data its reading
            i++;
        } else {
            break;
        }

        sem_post(sem);      //hands back control
    }

    sem_post(sem);
    close(fd[0]);
    sem_close(sem);
    exit(0);
}


int exp(int base, int exponent) {
    int output = 1;

    for(int i=1; i<=exponent; i++) {
        output = output * base;
    }

    return output;
}

【问题讨论】:

    标签: c linux pipe fork semaphore


    【解决方案1】:

    父进程和子进程都在该信号量上竞争sem_wait,其值为1。如果父级获胜,它会阻止read 调用。而孩子在sem_wait 中仍然被阻止。这是一个僵局。

    解决此死锁的一种方法是创建值为2 的信号量。

    另一种方法是从receiver 中删除sem_wait(sem) 和从sender 中删除sem_post(sem)。这是因为receiver 无论如何都会阻塞在read 中,直到sender 将某些内容写入管道。

    【讨论】:

    • 好吧,这是有道理的。我没有意识到 read 块。我了解僵局,但如何使用2 打开我的信号量,如sem_t *sem = sem_open("test_semaphore", O_CREAT | O_EXCL, 1, 2); 解决我的问题并生成交替的readwrite?我的理解是,Seamphore 就像在01 之间翻转的锁。当其1 时,您的代码将更改其值0,从而锁定其他进程,使其无法通过sem_wait(sem);
    • @Zhawn Mutex 是一个二进制信号量。而信号量可以有任意值。在维基百科中查找。
    猜你喜欢
    • 2015-08-19
    • 2016-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多