Почему синхронизация с семафором канала ведет себя так странно? - PullRequest
0 голосов
/ 31 января 2020

Я пытаюсь решить простой пример синхронизации процессов; в этом конкретном примере я хочу три процесса: один печатает «A», другой печатает «B» и последний печатает «C». Сначала я хочу напечатать «A», затем «B» или «C» и снова «A», «B» или «C». Чтобы быть более понятным, я хочу, чтобы выходной шаблон типа "ABACACABACABABACA ...."

Ниже приведен мой симплект-код, завершение не управляется, потому что это всего лишь пример, чтобы понять, как все работает.

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>




void semaphore_init (int* sw){
if (pipe(sw) == -1) {
printf ("Error\n");
exit (-1);
     }
}

void semaphore_wait (int* sw){
char buffer;
if (read(sw[0],&buffer,1) != 1) {
printf ("Error\n");
exit (-1);
     }
}


void semaphore_signal (int* sw){
if (write(sw[1],"X",1) != 1) {
printf ("Error\n");
exit (-1);
     }
}

int s1[2];
int s2[2];

void childA();
void childB();
void childC();

int main(){

pid_t pid;

semaphore_init(s1);
semaphore_init(s2);

semaphore_signal(s1);

pid=fork();
if(pid==0) childA();
else{
    pid=fork();
    if (pid==0) childB();
    else {
        pid=fork();
        if(pid==0) childC();
    }
}
wait(NULL);
return 0;
}

void childA(){

while(1){
    semaphore_wait(s1);
    printf("A-");
    semaphore_signal(s2);
   }
exit(0);
}

void childB(){

while(1){
    semaphore_wait(s2);
    printf("B-");
    semaphore_signal(s1);
   }
exit(0);
}

void childC(){

while(1){
    semaphore_wait(s2);
    printf("C-");
    semaphore_signal(s1);
   }
exit(0);
}

Я не понимаю, почему вывод этого кода выглядит примерно так:

1 Ответ

1 голос
/ 01 февраля 2020

Во многих реализациях, включая Linux, stdout является буферизованной строкой. Это означает, что любые символы printf сохраняются в буфере (памяти) до тех пор, пока не встретится новая строка или не заполнится буфер строк или не будет сброшен поток. В примере кода это приводит к тому, что каждый процесс записывает в свой локальный буфер каждый раз, когда он получает семафор. Таким образом, несмотря на то, что последовательность правильная, как вы предполагали, но поскольку есть три отдельных буфера, конечный результат будет не таким, как вы ожидаете. Каждый процесс в конечном итоге сбрасывает свой буфер в stdout, но каждый из этих буферов постоянно содержит одну и ту же букву.

Решение состоит в том, чтобы либо добавить новую строку в printf (как вы нашли), либо сделать явный fflush(stdout). Другой альтернативой является использование stderr, которое не буферизовано по умолчанию: например, fprintf(stderr, "A-");

...