第三章:Unix/Linux进程管理
知识点总结:
本章讨论了 Unix/Linux中的进程管理;阐述了多任务处理原则;介绍了进程概念;并以一个编程示例来说明多任务处理、上下文切换和进程处理的各种原则和方法
多任务处理系统支持动态进程创建、进程终止,以及通过休眠与唤醒实现进程同步、进程关系,以及以二叉树的形式实现进程家族树,从而允许父进程等待子进程终止;提供了一个具体示例来阐释进程管理函数在操作系统内核中是如何工作的;然后,解释了 Unix/Linux中各进程的来源,包括系统启动期间的初始进程、INIT进程、守护进程、登录进程以及可供用户执行命令的sh进程;
对进程的执行模式进行了讲解,以及如何通过中断、异常和系统调用从用户模式转换到内核模式;再接着,描述了用于进程管理的Unix/Linux系统调用,包括 fork, wait、exec和exit ;
阐明了父进程与子进程之间的关系,包括进程终止和父进程等待操作之间关系的详细描述;解释了如何通过IN1T进程处理孤儿进程,包括当前Linux中的subreaper进程,并通过示例演示了 subreaper进程;接着,详细介绍了如何通过exec更改进程执行映像,包括exeeve系统调用、命令行参数和环境变量;
解释了 I/O重定向和管道的 原则及方法,并通过示例展示了管道编程的方法;
进程管理中的系统调用:
fork():fork系统调用用于创建一个新进程,称为子进程,它与进行fork()调用的进程(父进程)并发运行。创建新的子进程后,两个进程都将执行fork()系统调用之后的下一条指令。子进程使用相同的PC(程序计数器),相同的CPU寄存器,相同的打开文件,这些文件在父进程中使用。
举例:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
// 在此指令后生成两个运行相同程序的进程
fork();
fork();
fork();
printf("Hello world!\n");
return 0;
}
实践内容:教材实例编程:C3.2.c:
代码:
#include <stdio.h>
#include <unistd.h> //fork函数头文件
int main()
{
int pid=fork(); // fork a child
if (pid)
{
printf("PARENT %d CHILD=%d\n", getpid(), pid);
printf("PARENT %d EXIT\n", getpid());
} // PARENT
//sleep(1);
else
{
printf("child %d start my parent«%d\n", getpid(), getppid());
// sleep(2); // sleep 2 seconds -> let parent die first
printf("child %d exit my parent=%d\n", getpid(), getppid());
}
}
在sleep()注释的情况下:
在sleep()删除注释的情况下:
实践内容:教材实例编程C3.3.c:
代码:
/************** C3.3.CS wait() and exit() ***************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
int pid, status;
pid = fork();
if (pid)
{
printf("PARENT %d WAITS FOR CHILD %d TO DIE\n", getpid(),pid);
pid = wait(&status)> // wait for ZOMBIE child process
printf("DEAD CHILD=%d, status=0x%04x\n", pid, status);
} // PARENT:
else
{
printf("child %d dies by exit(VALUE)\n", getpid());
exit(100);
}
}
实践截图:
实践内容:教材实例编程C3.4.c:
代码:
//************** C3.4.C: Subreaper Process*****//
#include <stdio.h>
#include <unistd.h>
#include <wait.h>
#include <sys/prctl.h>
int main()
{
int pid,r,status;
printf("mark process %d as a subreaper\n",getpid());
r = prctl(PR_SET_CHILD_SUBREAPER);
pid = fork();
if(pid)
{
printf("subreaper %d child = %d\n", getpid(), pid);
while (1)
{
pid = wait(&status);
if (pid > 0)
{
printf("subreaper %d waited a ZOMBIE=%d\n",getpid(), pid);
}
else
break;
}
}
else
{
printf("child %d parent = %d\n", getpid(), getppid());
pid = fork();
if (pid)
{
printf("child=%d start: grandchild=%d\n", getpid(),pid);
printf("child=%d EXIT: grandchild=%d\n",getpid(),pid);
}
else
{
printf("grandchild=%d start:myparent=%d\n",getpid(),getppid());
printf("grandcild=%d EXIT:myparent=%d\n", getpid(),getppid());
}
}
}
实践截图: