Primeiro, o programa pode fazer seu próprio buffer de saída. Às vezes, isso é chamado de “armazenamento em buffer stdio ” após o nome do componente da biblioteca que executa essa tarefa em C: as funções como putc
, fputs
, fprintf
, etc., declarado em stdio.h
. Em caso afirmativo, produzirá saída em rajadas, normalmente de alguns kilobytes (quando a saída é um terminal, o padrão é liberar o buffer em cada caractere de nova linha).
Em algum momento, o programador ou a função de biblioteca subjacente chama write
explicitamente. Isso solicita que o kernel grave os dados especificados no pipe. O kernel pode decidir gravar todos ou parte dos dados. Como o arquivo é um pipe, o kernel copiará os dados na área de buffer do pipe. Se o buffer de tubulação estiver cheio, a chamada de sistema write
bloqueia até que haja espaço: seu programa (ou mais precisamente, o encadeamento que chamou write
, caso haja vários encadeamentos no nível do kernel) não retomará a execução até a chamada para write
retorna.
(É possível, mas improvável nesta situação, que o programa tenha definido o descritor de arquivos do canal como não- blocking Se este for o caso, se o kernel determinar que não pode copiar nenhum dado, ele retornará o controle para o programa, a chamada do sistema write
retornará 0. Um programa que faz tal bloqueio não chamadas do sistema normalmente chamam select
ou poll
ou epoll
em um loop para bloquear até que um dos descritores de arquivo com os quais ele está se comunicando esteja pronto para entrada ou saída.)
O fato de o programa estar bloqueado durante uma chamada de sistema não está relacionado à escolha do algoritmo de escalonamento. Em sua essência, qualquer programador distingue entre os tópicos prontos , que podem ser fornecidos Tempo de CPU e aguardando threads, o que não é possível. A essência de um planejador é escolher um encadeamento pronto e deixá-lo rodar até que o encadeamento faça uma chamada de sistema (o que coloca o encadeamento em estado de espera) ou ocorra algum evento assíncrono (na prática, um processador interrupt ). Durante o processamento de uma chamada de sistema, pode ser que um encadeamento que estava até então bloqueado esteja pronto, por exemplo, porque esse encadeamento estava em uma chamada write
e o kernel agora pôde entregar os dados dessa chamada. Algumas coisas podem bloquear um thread pronto, por exemplo, um sinal para pausar ( SIGSTOP
) . O agendador mantém algum tipo de lista pronta para decidir qual thread agendar a seguir: uma lista de threads que estão prontos (geralmente é muito mais complicado do que uma simples lista em um agendador do mundo real).