Các quy trình khác

Cho đến nay, chúng ta đã thảo luận về các quy trình, quá trình tạo ra nó, quy trình mẹ và con, v.v. Cuộc thảo luận sẽ không đầy đủ nếu không thảo luận về các quy trình liên quan khác, chẳng hạn như quy trình Orphan, quy trình Zombie và quy trình Daemon.

Quá trình mồ côi

Như được chỉ ra trong tên, mồ côi ngụ ý quá trình không cha mẹ. Khi chúng tôi chạy một chương trình hoặc ứng dụng, quy trình cha của ứng dụng là shell. Khi chúng ta tạo một tiến trình bằng fork (), tiến trình mới được tạo là tiến trình con và tiến trình tạo ra con là tiến trình mẹ. Đổi lại, tiến trình cha của quá trình này là shell. Tất nhiên, cha của tất cả các quy trình là quy trình init (ID quy trình → 1).

Trên đây là một kịch bản thông thường, tuy nhiên, điều gì sẽ xảy ra nếu process cha thoát ra trước process con. Kết quả là, tiến trình con bây giờ trở thành tiến trình mồ côi. Vậy còn cha mẹ của nó thì sao, cha mẹ mới của nó là cha của tất cả các tiến trình, không là gì khác ngoài tiến trình init (Process ID - 1).

Hãy để chúng tôi thử và hiểu điều này bằng cách sử dụng ví dụ sau.

/ * Tên tệp: 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;
}

Các bước biên dịch và thực hiện

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

Quá trình xác sống

Nói một cách dễ hiểu, giả sử rằng bạn có hai quy trình, đó là quy trình cha và quy trình con. Quy trình cha có trách nhiệm đợi quy trình con và sau đó xóa mục nhập quy trình con khỏi bảng quy trình. Điều gì sẽ xảy ra nếu process cha không sẵn sàng chờ process con, và trong khi đó process con hoàn thành công việc và thoát ra? Bây giờ, tiến trình con sẽ trở thành tiến trình thây ma. Tất nhiên, tiến trình zombie được dọn dẹp sau khi tiến trình mẹ sẵn sàng.

Hãy để chúng tôi hiểu điều này với sự trợ giúp của một ví dụ.

/ * Tên tệp: 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;
}

Các bước biên dịch và thực hiện

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

Quy trình Daemon

Nói một cách dễ hiểu, tiến trình không có bất kỳ trình bao hoặc thiết bị đầu cuối liên quan nào được gọi là quy trình daemon. Tại sao điều này là cần thiết? Đây là các quy trình chạy trong nền để thực hiện các hành động theo các khoảng thời gian được xác định trước và cũng phản hồi các sự kiện nhất định. Quá trình daemon không được có bất kỳ tương tác nào của người dùng, vì nó chạy như một quá trình nền.

Các quy trình nền Linux nội bộ thường kết thúc bằng ký tự “d” như Kernel Daemons (ksoftirqd, kblockd, kswapd, v.v.), Daemons in (cupd, lpd, v.v.), Daemons dịch vụ tệp (smbd, nmbd, v.v.) , Daemon cơ sở dữ liệu quản trị (ypbind, ypserv, v.v.), Daemon thư điện tử (sendmail, popd, smtpd, v.v.), Daemons đăng nhập từ xa và thực thi lệnh (sshd, in.telnetd, v.v.), Daemon khởi động và cấu hình (dhcpd , udevd, v.v.), init process (init), cron daemon, atd daemon, v.v.

Bây giờ chúng ta hãy xem cách tạo một quy trình daemon. Sau đây là các bước -

Step 1- Tạo quy trình con. Bây giờ chúng ta có hai quy trình - quy trình mẹ và quy trình con

Thông thường, thứ bậc quy trình là VỎ → QUY TRÌNH PHỤ HUYNH → QUY TRÌNH CON

Step 2- Chấm dứt tiến trình cha bằng cách thoát. Tiến trình con bây giờ trở thành tiến trình mồ côi và được tiếp quản bởi tiến trình init.

Bây giờ, hệ thống phân cấp là QUY TRÌNH INIT → QUÁ TRÌNH TRẺ EM

Step 3- Việc gọi lệnh gọi hệ thống setsid () tạo ra một phiên mới, nếu quá trình gọi không phải là nhóm trưởng quá trình. Bây giờ quá trình gọi trở thành nhóm trưởng của phiên mới. Quy trình này sẽ là quy trình duy nhất trong nhóm quy trình mới này và trong phiên mới này.

Step 4 - Đặt ID nhóm quy trình và ID phiên thành PID của quy trình gọi.

Step 5 - Đóng các bộ mô tả tệp mặc định (đầu vào tiêu chuẩn, đầu ra tiêu chuẩn và lỗi tiêu chuẩn) của quá trình vì thiết bị đầu cuối và trình bao giờ đã bị ngắt kết nối khỏi ứng dụng.

/ * Tên tệp: 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