鍍金池/ 教程/ Linux/ 其他進(jìn)程
命名管道
消息隊列
進(jìn)程創(chuàng)建與終止
信號量
進(jìn)程組,會話和作業(yè)控制
共享內(nèi)存
進(jìn)程間通信簡介
子進(jìn)程監(jiān)視
其他進(jìn)程
覆蓋進(jìn)程映像
進(jìn)程信息
進(jìn)程映像
內(nèi)存映射
相關(guān)系統(tǒng)調(diào)用(System V)
進(jìn)程資源
System V & Posix
信號
進(jìn)程間通信教程
管道

其他進(jìn)程

到目前為止,我們已經(jīng)討論和學(xué)習(xí)了進(jìn)程,創(chuàng)建,父進(jìn)程和子進(jìn)程等。但是沒有討論其他相關(guān)進(jìn)程,如孤兒進(jìn)程,僵尸進(jìn)程和守護(hù)進(jìn)程,在本節(jié)中,我們來看看這些進(jìn)程。

孤兒進(jìn)程

如名字所示,孤兒進(jìn)程表示無父進(jìn)程。 當(dāng)我們運行程序或應(yīng)用程序時,應(yīng)用程序的父進(jìn)程是shell。 當(dāng)使用fork()創(chuàng)建一個進(jìn)程時,新創(chuàng)建的進(jìn)程是子進(jìn)程,創(chuàng)建是父進(jìn)程的子進(jìn)程。 反過來,這個父進(jìn)程就是shell。 當(dāng)然,所有進(jìn)程的父進(jìn)程是初始(init)進(jìn)程(進(jìn)程ID等于1)。

以上是一個常見的情況,但是,如果父進(jìn)程在子進(jìn)程之前退出,會發(fā)生什么情況。 結(jié)果是,子進(jìn)程現(xiàn)在成為孤兒進(jìn)程。 那么它的父進(jìn)程呢,它的新父進(jìn)程就是所有進(jìn)程的父進(jìn)程,這只不過是初始(init)進(jìn)程(進(jìn)程ID等于1)。

讓我們來看看下面的例子來理解孤兒進(jìn)程的含義。

文件: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;
}

編譯和執(zhí)行上面代碼,得到以下結(jié)果 -

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

僵尸進(jìn)程

簡而言之,假設(shè)有兩個進(jìn)程,即父進(jìn)程和子進(jìn)程。 父進(jìn)程負(fù)責(zé)等待子進(jìn)程,然后清理進(jìn)程表中的子進(jìn)程入口。 如果父進(jìn)程沒有準(zhǔn)備好等待子進(jìn)程,同時子進(jìn)程就完成工作并退出呢? 這種情況時,子進(jìn)程將成為僵尸進(jìn)程。 當(dāng)然,在父進(jìn)程準(zhǔn)備好之后,僵尸進(jìn)程就會被清除。

讓我們通過一個例子來理解這一點。

文件: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;
}

編譯和執(zhí)行上面代碼,得到以下結(jié)果 -

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

守護(hù)進(jìn)程

沒有任何關(guān)聯(lián)的shell或終端的進(jìn)程被稱為守護(hù)進(jìn)程。 為什么這是必要的? 這些是在后臺運行的進(jìn)程,以預(yù)定的時間間隔執(zhí)行操作,并響應(yīng)某些事件。 守護(hù)進(jìn)程不應(yīng)該有任何用戶交互,因為它作為后臺進(jìn)程運行。

內(nèi)核守護(hù)進(jìn)程通常以內(nèi)核守護(hù)進(jìn)程(ksoftirqd,kblockd,kswapd等),打印守護(hù)進(jìn)程(cupsd,lpd等),文件服務(wù)守護(hù)進(jìn)程(smbd,nmbd等)的字母“d” ,電子郵件守護(hù)進(jìn)程(sendmail,popd,smtpd等),遠(yuǎn)程登錄和命令執(zhí)行守護(hù)進(jìn)程(sshd,in.telnetd等),引導(dǎo)和配置守護(hù)進(jìn)程(dhcpd等),管理數(shù)據(jù)庫守護(hù)進(jìn)程(ypbind,ypserv等) ,udevd等),init進(jìn)程(init),cron守護(hù)進(jìn)程,atd守護(hù)進(jìn)程等。

現(xiàn)在讓我們看看如何創(chuàng)建一個守護(hù)進(jìn)程。 以下是步驟 -

第1步 - 創(chuàng)建一個子進(jìn)程。 現(xiàn)在我們有兩個進(jìn)程 - 父進(jìn)程和子進(jìn)程。通常流程是:SHELL -> 父進(jìn)程 -> 子進(jìn)程

第2步 - 通過退出終止父進(jìn)程。 子進(jìn)程現(xiàn)在成為孤兒進(jìn)程,由初始(init)進(jìn)程接管。
現(xiàn)在,這個流程層次是:初始(init)進(jìn)程 -> 子進(jìn)程。

第3步 - 如果調(diào)用進(jìn)程不是進(jìn)程組頭,則調(diào)用setsid()系統(tǒng)調(diào)用會創(chuàng)建一個新的會話。 現(xiàn)在調(diào)用進(jìn)程成為新會話的組頭。 這個進(jìn)程將是這個新的進(jìn)程組和這個新的進(jìn)程中唯一的進(jìn)程。

第4步 - 將進(jìn)程組ID和會話ID設(shè)置為調(diào)用進(jìn)程的PID。

第5步 - 關(guān)閉終端和外殼現(xiàn)在與應(yīng)用程序斷開連接的過程的默認(rèn)文件描述符(標(biāo)準(zhǔn)輸入,標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯誤)。

文件: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;
}

編譯和執(zhí)行上面示例代碼,得到以下結(jié)果 -

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