기타 프로세스

지금까지 프로세스, 생성, 부모 및 자식 프로세스 등에 대해 논의했습니다. Orphan 프로세스, Zombie 프로세스 및 Daemon 프로세스와 같은 다른 관련 프로세스를 논의하지 않고는 논의가 불완전합니다.

고아 프로세스

이름에서 알 수 있듯이 고아는 부모가없는 프로세스를 의미합니다. 프로그램이나 응용 프로그램을 실행할 때 응용 프로그램의 부모 프로세스는 셸입니다. fork ()를 사용하여 프로세스를 생성 할 때 새로 생성 된 프로세스는 자식 프로세스이고 자식을 생성 한 프로세스가 부모 프로세스입니다. 차례로 이것의 부모 프로세스는 쉘입니다. 물론 모든 프로세스의 부모는 init 프로세스입니다 (Process ID → 1).

위는 일반적인 시나리오이지만 부모 프로세스가 자식 프로세스보다 먼저 종료되면 어떻게됩니까? 결과적으로 자식 프로세스는 이제 고아 프로세스가됩니다. 그러면 그 부모는 어떨까요? 새 부모는 모든 프로세스의 부모이며 초기화 프로세스 일뿐입니다 (프로세스 ID – 1).

다음 예제를 사용하여 이것을 시도하고 이해합시다.

/ * 파일 이름 : orphan_process.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;
}

컴파일 및 실행 단계

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

좀비 프로세스

간단히 말해서 부모와 자식 프로세스라는 두 개의 프로세스가 있다고 가정합니다. 하위 프로세스를 기다린 다음 프로세스 테이블에서 하위 프로세스 항목을 정리하는 것은 상위 프로세스의 책임입니다. 부모 프로세스가 자식 프로세스를 기다릴 준비가되어 있지 않고 그 동안 자식 프로세스가 작업을 완료하고 종료하면 어떻게됩니까? 이제 자식 프로세스는 좀비 프로세스가됩니다. 물론 좀비 프로세스는 부모 프로세스가 준비된 후 정리됩니다.

예제의 도움으로 이것을 이해합시다.

/ * 파일 이름 : 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;
}

컴파일 및 실행 단계

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

데몬 프로세스

간단히 말해서 연관된 쉘이나 터미널이없는 프로세스를 데몬 프로세스라고합니다. 왜 이것이 필요한가요? 사전 정의 된 간격으로 작업을 수행하고 특정 이벤트에 응답하기 위해 백그라운드에서 실행되는 프로세스입니다. 데몬 프로세스는 백그라운드 프로세스로 실행되므로 사용자 상호 작용이 없어야합니다.

내부 Linux 데몬 프로세스는 일반적으로 커널 데몬 (ksoftirqd, kblockd, kswapd 등), 인쇄 데몬 (cupsd, lpd 등), 파일 서비스 데몬 (smbd, nmbd 등)과 같은 문자 "d"로 끝납니다. , 관리 데이터베이스 데몬 (ypbind, ypserv 등), 전자 메일 데몬 (sendmail, popd, smtpd 등), 원격 로그인 및 명령 실행 데몬 (sshd, in.telnetd 등), 부팅 및 구성 데몬 (dhcpd) , udevd 등), init 프로세스 (init), cron 데몬, atd 데몬 등

이제 데몬 프로세스를 만드는 방법을 살펴 보겠습니다. 다음은 단계입니다-

Step 1− 자식 프로세스를 생성합니다. 이제 두 개의 프로세스가 있습니다. 부모 프로세스와 자식 프로세스

일반적으로 프로세스 계층 구조는 SHELL → PARENT PROCESS → CHILD PROCESS입니다.

Step 2− 종료하여 상위 프로세스를 종료합니다. 이제 자식 프로세스는 고아 프로세스가되고 init 프로세스에 의해 인계됩니다.

이제 계층은 INIT PROCESS → CHILD PROCESS입니다.

Step 3− 호출 프로세스가 프로세스 그룹 리더가 아닌 경우 setsid () 시스템 호출을 호출하면 새 세션이 생성됩니다. 이제 호출 프로세스가 새 세션의 그룹 리더가됩니다. 이 프로세스는이 새 프로세스 그룹과이 새 세션에서 유일한 프로세스입니다.

Step 4 − 프로세스 그룹 ID와 세션 ID를 호출 프로세스의 PID로 설정합니다.

Step 5 − 이제 터미널과 셸이 응용 프로그램에서 분리되었으므로 프로세스의 기본 파일 설명자 (표준 입력, 표준 출력 및 표준 오류)를 닫습니다.

/ * 파일 이름 : 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