Condição de corrida não funciona no Arch Linux

Condição de corrida não funciona no Arch Linux

O programa C a seguir deve ilustrar a condição de corrida entre processos filho e pai:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main()
{
     fork();
     printf("\n 1234567890 \n");
     return 0;
}

Quando meus amigos executam (emUbuntu), eles obtêm a saída esperada, que é confusa 1234567890s

Um exemplo :12312345645678907890

Mas quando tento o mesmo programa no meuArco Linux, nunca fornece tal saída. É sempre um após o outro.

 1234567890 

 1234567890 

eu gosto dissoarco linuxé de alguma forma evitar a condição de corrida, mas eu gostaria dedesabilitarquaisquer desses recursos e gostaria de obter resultados como os do meu amigo.

Responder1

A printfchamada executaria uma ou mais write(2)chamadas de sistema e a ordem em que elas seriam processadas seria a ordem real da saída. Um ou mais, porque depende do buffer dentro da biblioteca C. Com a saída com buffer de linha (indo para o terminal), você provavelmente receberá duas writechamadas, uma para a nova linha inicial e outra para o restante.

write(1, "\n", 1);
write(1, " 1234567890 \n", 13);

É possível agendar outro processo entre as chamadas, fornecendo primeiro as duas linhas vazias, depois as linhas com os dígitos, mas como não há muito processamento em andamento, é improvável em um sistema descarregado.

Observe que como ambos os processos imprimem exatamente a mesma coisa, não importa qual deles seja executado primeiro, desde que um não interrompa o outro.

Se a saída for para um arquivo ou canal, o padrão é que ela seja totalmente armazenada em buffer, então você provavelmente receberá apenas uma writechamada (por processo) e nenhuma chance de saída mista.

Seu exemplo de dígitos misturados seria possível se os dígitos fossem gerados um por um, com chamadas de sistema individuais. É difícil entender por que uma implementação de biblioteca sensata faria isso ao imprimir uma string estática cujo comprimento é conhecido. Com mais gravações em loop, a saída misturada seria mais provável:

Algo assim:

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

int main(int argc, char *argv[])
{
     int i;
     setbuf(stdout, NULL);  /* explicitly unbuffered */
     int x = fork(); 
     for (i = 0 ; i < 500 ; i++) {
          printf("%d", !!x);
     }
     if (x) {
          wait(NULL);  
          printf("\n");  
     }  
     return 0;  
}

Me dá uma saída como abaixo. Na maioria das vezes, nem sempre. Cabe ao sistema decidir como agendar os processos. A imprevisibilidade é a razão pela qual geralmente tentamos evitar condições de corrida.

111111111111111111111111111111111111111111111111111111111111111111111111111
111111111111111111111111111111111111111111111111111111111111111111111111111
111100000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000010000001001100
110000000011001100110011000000010011001100110000000100110011001100000001001
100110011000000010011001100110000000100110011001100000001001100110011000000
...

Responder2

Minha suspeita é que a fork()chamada do sistema está atrasando o processo pai ou filho por tempo suficiente para permitir que o outro processo termine a chamada printf()e faça com que a string apareça na saída antes mesmo de chegar à sua própria printf().

A saída de um grande número de strings em um loop provavelmente mostrará a saída misturada que você descreve, se os processos pai e filho tiverem tempo para executar os loops simultaneamente.

"Consertar" isso provavelmente envolveria reescrever a fork()chamada do sistema ou os componentes do kernel envolvidos nela.

informação relacionada