AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 446131
Accepted
Goktug
Goktug
Asked: 2018-05-27 01:54:48 +0800 CST2018-05-27 01:54:48 +0800 CST 2018-05-27 01:54:48 +0800 CST

O arquivo usado pelo processo pai e filho

  • 772
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>


int main( int argc, char *argv[] ){


    FILE *fptr;
    pid_t pid;

    fptr = fopen("Shared File.txt", "a");
    pid = fork();

    if( pid > 0 ){ // parent process

        int counter = 0;

        while( counter < 10 ){
            fprintf(fptr, "a");
            ++counter;
        }
        wait(NULL);
    }
    else{

        int counter = 0;

        while( counter < 5 ){
            fprintf(fptr, "b");
            ++counter;
        }
    }

    return 0;
}

Quando eu executo este código, o arquivo produzido pelo código contém esta mensagem: bbbbbaaaaaaaaaa

Sempre que executo este código, recebo a mesma mensagem. Por que os processos não gravam no arquivo em ordem aleatória?

Por que o sistema operacional tenta terminar o processo filho primeiro?

Minha expectativa sobre a mensagem é assim: baabbaaaaabaaabaa Não há transição contínua entre os processos.

process shared-file
  • 4 4 respostas
  • 1592 Views

4 respostas

  • Voted
  1. Best Answer
    ilkkachu
    2018-05-27T02:08:19+08:002018-05-27T02:08:19+08:00

    O agendamento entre pai e filho já foi discutido (pelo menos) em Quando os processos filhos são executados e Como a chamada do sistema fork realmente funciona .

    Mas, neste caso, também há a questão do buffer dentro do stdio. Você está usando fprintf()para gravar em um arquivo normal. Por padrão, stdioarmazena a saída em arquivos regulares até que dados suficientes sejam gravados, para economizar na sobrecarga de chamada do sistema. No Linux x86, geralmente parece gravar em blocos de 4096 bytes, mas você não pode contar com isso, a menos que defina o buffer manualmente (veja setbuf()e amigos).

    Você pode ver isso com um comando como straceo que mostra as chamadas do sistema que um programa faz.

    Portanto, embora você não possa fazer nenhuma previsão sobre qual processo será executado primeiro, nesse caso, você pode prever que os as serão escritos consecutivamente e os bs também. Você só pode obter bbbbbaaaaaaaaaaou aaaaaaaaaabbbbb, e qual deles você obtém depende muito do acaso.

    • 6
  2. ctrl-alt-delor
    2018-05-27T14:02:10+08:002018-05-27T14:02:10+08:00

    Eu concordo principalmente com @ikkachu, exceto

    Qual deles você obtém bbbbbaaaaaaaaaaou aaaaaaaaaabbbbbé previsível. O sistema operacional espera que o filho termine, por causa de wait(NULL), então o pai sai. Como os buffers são liberados na saída, a criança começa a escrever primeiro.

    No entanto, não confie na previsibilidade dos buffers. Use descarga explícita quando necessário.

    • 2
  3. Johan Myréen
    2018-05-27T09:52:23+08:002018-05-27T09:52:23+08:00

    O usuário ilkkachu deu uma boa explicação de como o buffer afeta a saída. Minha resposta descreve o que aconteceria se você eliminasse o buffer, por exemplo, substituindo as fprintfchamadas por chamadas para write. Nesse caso, você obteria as e bs estritamente alternados. Isso porque a chamada a writecausa um reagendamento: escrever em blocos de um processo, dar a vez no outro processo, e assim por diante.

    Vamos imaginar o que aconteceria se a chamada para escrever não fosse bloqueada. Então teríamos que considerar escalas de tempo: você obteria execuções muito mais longas de as e bs do que apenas um ou dois por vez, porque os processadores modernos são capazes de executar bilhões de instruções por segundo, mas a frequência de agendamento é tipicamente algo entre 100 Hz e 1000 Hz. Um processo seria capaz de executar até dezenas de milhões de instruções antes de sofrer preempção e agendar a execução do outro processo. Mesmo levando em consideração a sobrecarga da chamada do sistema, isso daria ao processo tempo para imprimir strings muito longas de as ou s consecutivos b.

    • 1
  4. ErikF
    2018-05-27T17:46:44+08:002018-05-27T17:46:44+08:00

    ikkachu e Johan fizeram um ótimo trabalho explicando por que você observou o comportamento que você fez, então eu reescrevi ligeiramente seu programa para que cada processo libere o fluxo e durma por um segundo (para que cada thread tenha a chance de intercalar de maneira diferente a cada vez), para que você possa ver o efeito de intercalação com mais clareza.

    #include <stdio.h>
    #include <unistd.h>
    #include <sys/wait.h>
    
    int main(void) {
      FILE *fptr = stdout;
      pid_t pid;
      int counter = 0;
    
      pid = fork();
    
      if(pid > 0) { // parent process
        while(counter++ < 10) {
          fprintf(fptr, "aa");
          fflush(fptr);
          sleep(1);
        }
        wait(NULL);
        puts("");
      } else {
        while(counter++ < 5) {
          fprintf(fptr, "bbbb");
          fflush(fptr);
          sleep(1);
        }
      }
    }
    

    Se você executar isso várias vezes, obterá resultados diferentes de vez em quando:

    ~ $ ./thread
    aabbbbaabbbbaabbbbaabbbbaabbbbaaaaaaaaaa
    ~ $ ./thread
    aabbbbaabbbbaabbbbaabbbbaabbbbaaaaaaaaaa
    ~ $ ./thread
    aabbbbaabbbbaabbbbaabbbbbbbbaaaaaaaaaaaa
    ~ $ ./thread
    aabbbbaabbbbaabbbbaabbbbaabbbbaaaaaaaaaa
    
    • 1

relate perguntas

  • Como substituir os IDs de usuário e IDs de grupo por nomes em vez de números em "ps"?

  • Como obter os IDs dos grupos suplementares de um processo?

  • O que `/proc/irq/.../spurious` contém?

  • Um processo pai pode alterar o ambiente de seu filho?

  • Como 'ejetar' obtém processos para fechar identificadores de arquivo?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    ssh Não é possível negociar: "nenhuma cifra correspondente encontrada", está rejeitando o cbc

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    Como descarregar o módulo do kernel 'nvidia-drm'?

    • 13 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add retorna com: "Erro ao conectar ao agente: nenhum arquivo ou diretório" 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya Por que o Linux usa LF como caractere de nova linha? 2017-12-20 05:48:21 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve