簡體   English   中英

Linux fork,信號燈,帶C的管道

[英]Linux fork,semaphore,pipe with C

因此,我試圖了解叉子的信號燈。 我編寫了一個C程序,該程序分叉一次並通過管道從子pid到父pid傳遞一個整數4次。 因此,我已經能夠使用分叉的孩子之間的管道成功讀取/寫入。 但是,當我嘗試循環多次寫入管道時,我遇到了問題。 我試圖用信號量來調節我的管道,以便獲得交替的寫入,讀取,寫入,讀取等。我的帶有信號量的代碼現在生成SEGFAULTS或只是在打印出我的標頭之后掛起。 我知道我可以用另一個管道來完成此規則,但是我專門這樣做是為了更好地理解信號量。 我一直在讀一本OS書籍,但並不是真正的點擊。 誰能通過我的代碼示例向我解釋這一點? (這不是家庭作業)

/*****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;
}

父進程和子進程sem_wait針對該值為1信號量爭用sem_wait 如果父母獲勝,則會阻止其進行read通話。 而孩子在sem_wait仍然處於阻塞sem_wait 這是一個僵局。

解決此死鎖的一種方法是創建值為2的信號量。

另一種方法是從receiver刪除sem_wait(sem) ,從sender刪除sem_post(sem) 這是因為receiver sender無論如何都會阻止read ,直到sender將某些內容寫入管道為止。

暫無
暫無

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

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