进程的管理 一、进程的基础 进程和程序的区别 每个进程有自己的pid、PCB 操作系统上运行的所有进程构成一颗树。 如何查看这颗树? pstree(1) 树根进程是init pid是 1 进程间的亲缘关系两种 父子关系 兄弟关系 使用top(1)命令观察进程的状态 使用ps(1)命令也可以查看进程。 二、进程的创建 父进程创建子进程 父进程如何去创建子进程? 父进程调用fork(2),创建新的子进程。 #include <unistd.h> pid_t fork(void); 功能:创建一个子进程 参数: void: 返回值: 在父进程中 -1 错误 errno被设置 成功 在父进程中 子进程的pid被返回 在子进程中 0 被返回 写时复制技术 举例说明 使用fork(2),创建新的子进程 代码参见 fork.c 三、进程的退出 1、注意return和exit(3)的区别 return只是从函数返回。结束函数的生命周期。 exit(3)结束进程的生命周期 exit(3) #include <stdlib.h> void exit(int status); 功能:使进程正常终止 参数: status:指定进程的退出状态码。 返回值: 返回这个值 status & 0377给父进程 举例说明 exit(3)的使用 代码参见 exit.c 目前,在bash下执行的程序,这个进程的父进程是bash。 2、可以使用atexit(3)或者on_exit(3)向进程注册函数,在进程退出的时候调用这写注册的函数。 从main函数中返回的时候,进程结束了吗? 进程没有结束。 atexit(3) #include <stdlib.h> int atexit(void (*function)(void)); 功能:向进程注册函数,在进程退出的时候被调用 参数: function:指定遗言函数 返回值: 0 成功 非0 失败 注意: 1、同一个函数注册一次就被调用一次,注册多次就被调用多次。 2、函数注册的顺序和调用的顺序相反 3、注册的遗言函数被子进程继承 void (*function)(void) 举例说明 使用atexit向进程注册遗言函数 代码参见 atexit.c on_exit(3) #include <stdlib.h> int on_exit(void (*function)(int , void *), void *arg); 功能:注册一个函数在进程终止的时候被调用 参数: function:指定了遗言函数的名字 arg:指定了function函数的第二个参数,function的第一个参数是exit(3) 的退出状态码。 返回值: 0 成功 非0 失败 void (*function)(int , void *) 举例说明 使用on_exit(3)注册遗言函数 代码参见 on_exit.c _exit(2) 父进程创建子进程,然后父进程马上退出,子进程还没有终止的情况下,子进程过继给init进程。这些子进程被称为孤儿进程。 演示孤儿进程的现象 代码参见alone.c 四、进程资源的回收 在进程终止的时候,会向父进程发送SIGCHLD信号,父进程收到这个信号以后,调用wait(2)家族的函数,去回收子进程的资源。 在父进程还没有回收子进程的资源的时候,这时候,子进程处于僵尸状态。这时候的子进程称为僵尸进程。 举例说明僵尸进程 代码参见zomble.c wait(2) #include <sys/types.h> #include <sys/wait.h> pid_t wait(int *status); 功能:等待进程状态的改变 参数: status:如果不为空,存储子进程的信息。 这个整数可以使用宏来检测。 WIFEXITED(status) 如果子进程正常终止,返回true。 WEXITSTATUS(status) 返回子进程的退出状态码。只有在上边的宏返回真的时候,被使用 WIFSIGNALED(status) 如果子进程被信号终止,那么返回true WTERMSIG(status) 只有在上边的宏为真的情况下使用。返回的是使子进程终止的信号编号。 返回值: -1 错误 返回终止的子进程的pid。 举例说明 使用wait(2)回收子进程的资源。 代码参见 wait.c 补充: 如何给进程发送信号,终止进程? kill -信号编号 pid 信号编号 2 3 9 pid_t waitpid(pid_t pid, int *status, int options); 功能:等待子进程状态的改变 参数: pid:指定了要等待的子进程的pid。 <-1: 等待任意子进程,子进程的组id等于pid的绝对值。 -1:等待任意子进程 0 :等待任意子进程,这写子进程的组id等于当前进程组id。 >0:pid指定了要等待的子进程pid。 status:如果不为空,存储子进程的信息。 options:可以改变是否等待子进程的终止。 WNOHANG:如果没有子进程退出,立即返回。 0 如果没有子进程退出,阻塞等待子进程退出。 返回值: 成功 返回子进程的pid 错误 -1 如果WNOHANG被指定 。0 代表等待的所有子进程都没有终止。 wait(&s)===waitpid(-1,&s,0) 进程组中有1个或更多个进程。一般情况下子进程和父进程属于同进程组。 总结: 一、进程的基础 pstree ps top 二、进程的创建 fork(2) 三、进程的退出 exit _exit atexit on_exit 孤儿进程 四、回收子进程的资源 wait waitpid 僵尸进程