到目前为止,我们已经讨论了进程,进程的创建,父进程和子进程等。如果不讨论其他相关进程(如孤立进程,僵尸进程和守护进程),则将是不完整的。
当我们运行程序或应用程序时,该应用程序的父进程是shell,当我们使用fork()创建进程时,新创建的进程是子进程,而创建子进程的进程是父进程。反过来,其父进程是shell。当然,所有进程的父进程都是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或终端的进程称为守护进程,为什么需要这个?这些是在后台运行的进程,它们以预定义的时间间隔执行操作并响应某些事件,守护程序进程不应与任何用户交互,因为它作为后台进程运行。
现在让我们看看如何创建守护进程。以下是步骤-
步骤1 - 创建一个子进程,现在我们有两个进程–父进程和子进程
通常,进程层次结构为:SHELL→PARENT PROCESS→CHILD PROCESS
步骤2 - 通过退出终止父进程,现在子进程成为孤立进程,并由init进程接管。
现在,层次结构是INIT PROCESS→CHILD PROCESS
步骤3 - 如果调用进程不是进程组负责人,则调用setsid()系统调用将创建一个新会话。
步骤4 - 将进程组ID和会话ID设置为调用进程的PID。
步骤5 - 由于终端和Shell现在已与应用程序断开连接,请关闭进程的默认文件描述符(标准输入,标准输出和标准错误)。
来源:LearnFk无涯教程网
/*文件名: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
祝学习愉快!(内容编辑有误?请选中要编辑内容 -> 右键 -> 修改 -> 提交!)