Outros Processos
Até agora, discutimos sobre os processos, sua criação, processos pai e filho, etc. A discussão será incompleta sem discutir outros processos relacionados, como o processo Órfão, o processo Zumbi e o processo Daemon.
Processo Órfão
Conforme indicado pelo nome, órfão implica processo sem pais. Quando executamos um programa ou aplicativo, o processo pai do aplicativo é o shell. Quando criamos um processo usando fork (), o processo recém-criado é o processo filho e o processo que criou o filho é o processo pai. Por sua vez, o processo pai disso é shell. Obviamente, o pai de todos os processos é o processo init (ID do processo → 1).
O cenário acima é um cenário normal, no entanto, o que acontece se o processo pai sair antes do processo filho. O resultado é que o processo filho agora se torna o processo órfão. Então, o que acontece com seu pai, seu novo pai é o pai de todos os processos, que nada mais é do que o processo init (ID do processo - 1).
Vamos tentar entender isso usando o exemplo a seguir.
/ * Nome do arquivo: órfão_processo.c * /
#include<stdio.h>
#include<stdlib.h>
int main() {
int pid;
system("ps -f");
pid = fork();
if (pid == 0) {
printf("Child: pid is %d and ppid is %d\n",getpid(),getppid());
sleep(5);
printf("Child: pid is %d and ppid is %d\n",getpid(),getppid());
system("ps -f");
} else {
printf("Parent: pid is %d and ppid is %d\n",getpid(),getppid());
sleep(2);
exit(0);
}
return 0;
}
Etapas de compilação e execução
UID PID PPID C STIME TTY TIME CMD
4581875 180558 0 0 09:19 ? 00:00:00 sh -c cd /home/cg/root/4581875;
timeout 10s main
4581875 180564 180558 0 09:19 ? 00:00:00 timeout 10s main
4581875 180565 180564 0 09:19 ? 00:00:00 main
4581875 180566 180565 0 09:19 ? 00:00:00 ps -f
Parent: pid is 180565 and ppid is 180564
UID PID PPID C STIME TTY TIME CMD
4581875 180567 0 0 09:19 ? 00:00:00 main
4581875 180820 180567 0 09:19 ? 00:00:00 ps -f
Child: pid is 180567 and ppid is 180565
Child: pid is 180567 and ppid is 0
Processo Zumbi
Em termos simples, suponha que você tenha dois processos, a saber, o processo pai e o filho. É responsabilidade do processo pai esperar pelo processo filho e, em seguida, limpar a entrada do processo filho da tabela de processos. E se o processo pai não estiver pronto para aguardar o processo filho e, nesse ínterim, o processo filho concluir seu trabalho e sair? Agora, o processo filho se tornaria o processo zumbi. Claro, o processo zumbi é limpo depois que o processo pai fica pronto.
Vamos entender isso com a ajuda de um exemplo.
/ * Nome do arquivo: zombie_process.c * /
#include<stdio.h>
#include<stdlib.h>
int main() {
int pid;
pid = fork();
if (pid == 0) {
system("ps -f");
printf("Child: pid is %d and ppid is %d\n",getpid(),getppid());
exit(0);
} else {
printf("Parent: pid is %d and ppid is %d\n",getpid(),getppid());
sleep(10);
system("ps aux|grep Z");
}
return 0;
}
Etapas de compilação e execução
UID PID PPID C STIME TTY TIME CMD
4581875 184946 0 0 09:20 ? 00:00:00 sh -c cd /home/cg/root/4581875;
timeout 10s main
4581875 184952 184946 0 09:20 ? 00:00:00 timeout 10s main
4581875 184953 184952 0 09:20 ? 00:00:00 main
4581875 184954 184953 0 09:20 ? 00:00:00 main
4581875 184955 184954 0 09:20 ? 00:00:00 ps -f
Child: pid is 184954 and ppid is 184953
Processo Daemon
Em termos simples, o processo que não tem nenhum shell ou terminal associado é conhecido como processo daemon. Por que isso é necessário? Esses são os processos executados em segundo plano para realizar ações em intervalos predefinidos e também responder a determinados eventos. O processo daemon não deve ter nenhuma interação com o usuário, pois é executado como um processo em segundo plano.
Os processos daemon internos do Linux geralmente terminam com a letra “d”, como Kernel Daemons (ksoftirqd, kblockd, kswapd, etc.), Impressão Daemons (cupsd, lpd, etc.), File Service Daemons (smbd, nmbd, etc.) , Daemons de banco de dados administrativo (ypbind, ypserv, etc.), Daemons de correio eletrônico (sendmail, popd, smtpd, etc.), Login remoto e Daemons de execução de comando (sshd, in.telnetd, etc.), Daemons de inicialização e configuração (dhcpd , udevd, etc.), processo init (init), cron daemon, atd daemon, etc.
Agora vamos ver como criar um processo daemon. A seguir estão as etapas -
Step 1- Crie um processo filho. Agora temos dois processos - o processo pai e o processo filho
Normalmente, a hierarquia do processo é SHELL → PROCESSO PAI → PROCESSO DA CRIANÇA
Step 2- Encerre o processo pai saindo. O processo filho agora se torna o processo órfão e é assumido pelo processo init.
Agora, a hierarquia é PROCESSO INIT → PROCESSO INFANTIL
Step 3- Chamar a chamada de sistema setsid () cria uma nova sessão, se o processo de chamada não for um líder de grupo de processo. Agora, o processo de chamada se torna o líder do grupo da nova sessão. Este processo será o único processo neste novo grupo de processos e nesta nova sessão.
Step 4 - Defina o ID do grupo de processo e o ID da sessão como PID do processo de chamada.
Step 5 - Feche os descritores de arquivo padrão (entrada padrão, saída padrão e erro padrão) do processo, pois o terminal e o shell agora estão desconectados do aplicativo.
/ * Nome do arquivo: daemon_test.c * /
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdlib.h>
#include<string.h>
int main(int argc, char *argv[]) {
pid_t pid;
int counter;
int fd;
int max_iterations;
char buffer[100];
if (argc < 2)
max_iterations = 5;
else {
max_iterations = atoi(argv[1]);
if ( (max_iterations <= 0) || (max_iterations > 20) )
max_iterations = 10;
}
pid = fork();
// Unable to create child process
if (pid < 0) {
perror("fork error\n");
exit(1);
}
// Child process
if (pid == 0) {
fd = open("/tmp/DAEMON.txt", O_WRONLY|O_CREAT|O_TRUNC, 0644);
if (fd == -1) {
perror("daemon txt file open error\n");
return 1;
}
printf("Child: pid is %d and ppid is %d\n", getpid(), getppid());
printf("\nChild process before becoming session leader\n");
sprintf(buffer, "ps -ef|grep %s", argv[0]);
system(buffer);
setsid();
printf("\nChild process after becoming session leader\n");
sprintf(buffer, "ps -ef|grep %s", argv[0]);
system(buffer);
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
} else {
printf("Parent: pid is %d and ppid is %d\n", getpid(), getppid());
printf("Parent: Exiting\n");
exit(0);
}
// Executing max_iteration times
for (counter = 0; counter < max_iterations; counter++) {
sprintf(buffer, "Daemon process: pid is %d and ppid is %d\n", getpid(), getppid());
write(fd, buffer, strlen(buffer));
sleep(2);
}
strcpy(buffer, "Done\n");
write(fd, buffer, strlen(buffer));
// Can't print this as file descriptors are already closed
printf("DoneDone\n");
close(fd);
return 0;
}
Parent: pid is 193524 and ppid is 193523
Parent: Exiting
4581875 193525 0 0 09:23 ? 00:00:00 main
4581875 193526 193525 0 09:23 ? 00:00:00 sh -c ps -ef|grep main
4581875 193528 193526 0 09:23 ? 00:00:00 grep main
4581875 193525 0 0 09:23 ? 00:00:00 main
4581875 193529 193525 0 09:23 ? 00:00:00 sh -c ps -ef|grep main
4581875 193531 193529 0 09:23 ? 00:00:00 grep main