其他進程
到目前爲止,我們已經討論和學習了進程,創建,父進程和子進程等。但是沒有討論其他相關進程,如孤兒進程,殭屍進程和守護進程,在本節中,我們來看看這些進程。
孤兒進程
如名字所示,孤兒進程表示無父進程。 當我們運行程序或應用程序時,應用程序的父進程是shell。 當使用fork()
創建一個進程時,新創建的進程是子進程,創建是父進程的子進程。 反過來,這個父進程就是shell
。 當然,所有進程的父進程是初始(init
)進程(進程ID等於1)。
以上是一個常見的情況,但是,如果父進程在子進程之前退出,會發生什麼情況。 結果是,子進程現在成爲孤兒進程。 那麼它的父進程呢,它的新父進程就是所有進程的父進程,這只不過是初始(init
)進程(進程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
守護進程
沒有任何關聯的shell或終端的進程被稱爲守護進程。 爲什麼這是必要的? 這些是在後臺運行的進程,以預定的時間間隔執行操作,並響應某些事件。 守護進程不應該有任何用戶交互,因爲它作爲後臺進程運行。
內核守護進程通常以內核守護進程(ksoftirqd,kblockd,kswapd等),打印守護進程(cupsd,lpd等),文件服務守護進程(smbd,nmbd等)的字母「d」 ,電子郵件守護進程(sendmail,popd,smtpd等),遠程登錄和命令執行守護進程(sshd,in.telnetd等),引導和配置守護進程(dhcpd等),管理數據庫守護進程(ypbind,ypserv等) ,udevd等),init進程(init),cron守護進程,atd守護進程等。
現在讓我們看看如何創建一個守護進程。 以下是步驟 -
第1步 - 創建一個子進程。 現在我們有兩個進程 - 父進程和子進程。通常流程是:SHELL -> 父進程 -> 子進程
第2步 - 通過退出終止父進程。 子進程現在成爲孤兒進程,由初始(init
)進程接管。
現在,這個流程層次是:初始(init
)進程 -> 子進程。
第3步 - 如果調用進程不是進程組頭,則調用setsid()
系統調用會創建一個新的會話。 現在調用進程成爲新會話的組頭。 這個進程將是這個新的進程組和這個新的進程中唯一的進程。
第4步 - 將進程組ID和會話ID設置爲調用進程的PID。
第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