Linux: explicação detalhada da criação do processo

Criação de processo

Agora que conhecemos o conceito de um processo e como criá-lo, vamos explorar os detalhes da criação do processo em detalhes.

1. função do garfo

No Linux, a função fork pode criar um novo processo a partir de um processo existente, o novo processo é o processo filho e o processo original é o processo pai

#include <unistd.h> //头文件

pid_t = fork(void);
//返回值有三种情况
//pid_t = 0 表示子进程
//pid_t > 0 表示父进程
//pid_t < 0 表示创建失败

O processo chama a função fork. Quando o controle é transferido para o código fork no kernel, o que o kernel precisa fazer é:
1. Alocar um novo bloco de memória e estrutura de dados do kernel para o processo filho
2. Copiar parte da estrutura de dados conteúdo do processo pai para o processo filho
3. Adicionar o processo filho à lista de processos do sistema
4. Retornos de fork. Inicie o agendamento do planejador
A ideia principal de criar um processo filho chamando fork é criar um processo filho copiando o processo pai (copiando os dados no pcb do processo pai), o código é compartilhado, mas os dados são únicos.
Insira a descrição da imagem aqui

int main( void )
{
    
    
 pid_t pid;
 printf("Before: pid is %d\n", getpid());
 if ( (pid=fork()) == -1 )perror("fork()"),exit(1);
 printf("After:pid is %d, fork return %d\n", getpid(), pid);
 sleep(1);
 return 0;
}

Insira a descrição da imagem aquiExistem três linhas de saída, uma linha antes e duas linhas depois. O processo 3255 imprime primeiro a mensagem anterior e, em seguida, imprime depois. Outra mensagem depois de 3256 foi impressa. Observe que o processo 3256 não foi impresso antes, o motivo é mostrado na figura abaixoInsira a descrição da imagem aqui

Copy-on-write

Copy-on-write é uma tecnologia que pode atrasar ou mesmo evitar a cópia de dados.O kernel não copia todo o espaço de endereço do processo neste momento, mas permite que o processo pai e o processo filho compartilhem a mesma cópia. Copy-on-write, os dados serão copiados apenas no momento da escrita, de forma que cada processo tenha sua própria cópia, ou seja, a cópia dos recursos só é realizada quando precisa ser escrito. Resumindo: normalmente, o código é compartilhado entre o pai e o filho. Quando o pai e o filho não escrevem, os dados também são compartilhados. Quando uma das partes tenta escrever, cada cópia é feita por cópia na escrita .
Insira a descrição da imagem aqui

O motivo da falha na chamada

(1). Existem muitos processos no sistema
(2). O número de processos do usuário real excede o limite

2. função vfork

A função de vfork () é a mesma de fork (), a diferença é que vfork () não copia as entradas da tabela de páginas do processo pai. Quando um processo é criado desta forma, o processo filho é executado em seu espaço de endereço como um thread separado do processo pai, e o processo pai é bloqueado, o que significa que apenas quando o processo filho sai, o processo pai pode continuar a executar , e o processo filho não pode gravar no espaço de endereço. A vantagem de usar o vfork é que não há necessidade de copiar as entradas da tabela de páginas do processo pai. (Observação: com o advento da tecnologia copy-on-write, o vfork geralmente não é mais usado)

Encerramento do processo

É a saída do processo.Geralmente existem duas situações: saída normal e saída anormal.
Saída normal: O processo sai de onde corre para voltar ou sair, ou seja, sai onde o deixamos sair Saída
anormal: A tarefa não é completada e o programa sai por algum motivo na metade do caminho.

Três maneiras de sair normalmente

(1) função _exit
Call void exit (int status) em qualquer posição; você pode sair de um processo em qualquer posição no programa

#include <unistd.h>
void _exit(int status);
参数:status 定义了进程的终止状态,父进程通过wait来获取该值

Nota: Embora o status seja int, apenas os 8 bits inferiores podem ser usados ​​pelo processo pai. Então, quando _exit (-1), execute $? No terminal e descubra que o valor de retorno é 255
(2). Função de saída
Chame void _exit (int status) em qualquer posição; você pode sair de um processo em qualquer posição no programa

#include <unistd.h>
void exit(int status);

(3)
. Return sai de return na função principal; (return na função comum só pode sair da função, não do processo), return é uma forma mais comum de sair do processo. Executar return n é equivalente a executar exit (n), porque a função de tempo de execução de chamada de main tomará o valor de retorno de main como parâmetro de saída.

A diferença entre _exit e exit

Chame void exit (int status / void _exit (int status) em qualquer posição, você pode sair de um processo em qualquer lugar no programa, mas o primeiro irá atualizar o buffer ao sair do processo e gravar os dados no buffer para os dados, enquanto o último Ao sair do processo, os recursos são liberados diretamente sem atualizar o buffer; exit é uma função de biblioteca e _exit é uma interface de chamada do sistema

Acho que você gosta

Origin blog.csdn.net/qq_43825377/article/details/113817840
Recomendado
Clasificación