系统编程之进程的创建.僵尸与孤儿进程
一.进程
进程是正在执行的程序实例。执行程序时,内核会将程序代码载入虚拟内存,为程序变量分配空间,在内核中建立相应的数据结构,以记录与进程有关的各种信息(比如,进程ID、用户ID、组ID以及终止状态等)
在内核看来,进程是一个个实体,内核必须在它们之间共享各种计算机资源。对于像内存这样的受限资源来说,内核一开始会为进程分配一定数量的资源,并 在进程的生命周期内,统筹该进程和整个系统对资源的需求,对这一分配进行调整。程序终止时,内核会释放所有此类资源,供其他进程重新使用。其他资源(如 CPU、网络带宽等)等属于可再生资源,但必须在所有进程间平等共享。
我们可以通过ps -aux来打印当前的所有进程,其中状态具体表示为:S表示睡眠,R表示可运行,D表示等待,T表示停止,Z表示死进程或僵尸进程,PID表示进程号,PPID表示父进程号。接下来打印当前程序的进程号和父进程号:
1 #include <stdio.h> 2 #include <sys/types.h> 3 #include <unistd.h> 4 5 //typedef unigned int pid_t 6 int main(void) 7 { 8 pid_t self_pid = getpid(); 9 pid_t parent_pid = getppid(); 10 11 printf("self_pid = %d\n", self_pid); 12 printf("parent_pid = %d\n", parent_pid);//bash 13 14 return 0; 15 } ~ ~ ~
二:创建新进程:
创建一个新的进程可以分为三种方法:systeme(),exel()族,fork();
1,system()
system()函数调用“/bin/sh -c command”执行特定的命令,阻塞当前进程直到command命令执行完毕
以下是通过system来打印当前的路径:
1 #include <stdio.h> 2 #include <sys/types.h> 3 #include <unistd.h> 4 #include <stdlib.h> 5 6 //typedef unigned int pid_t 7 int main(void) 8 { 9 printf("execute this command\n"); 10 system("pwd"); 11 printf("Over\n"); 12 13 14 return 0; 15 } ~ ~ ~ ~
运行结果:
2.exel族(execl、execlp、execle、execv、execvp)
execl系列函数是替换类创建进程,即在创建进程的同时,把以前的进程干掉,其具体的原型为:
原型:
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ..., char * const envp[]);
int execv(const char *path, char *const argv[]);
以下是 execl创建进程:
1 #include <stdio.h> 2 #include <sys/types.h> 3 #include <unistd.h> 4 #include <stdlib.h> 5 6 //typedef unigned int pid_t 7 int main(void) 8 { 9 printf("execute this command\n"); 10 execlp("ls","ls","-l", (char *)0); 11 printf("Over\n"); 12 13 14 return 0; 15 }
运行结果:
可以发现,以前应该打印的over那句,没有打印,这就是因为被他的子进程干掉了。
3.fork孤儿进程
在fork函数之前,需要了解两个概念:第一个是孤儿进程:就是一个进程的父进程比子进程先要退出,
以下是一个孤儿进程的实例:
1 #include <stdio.h> 2 #include <sys/types.h> 3 #include <unistd.h> 4 #include <stdlib.h> 5 6 //fork---->孤儿进程,僵尸进程, 7 8 int main(void) 9 { 10 pid_t pd = 0; 11 int status = 0; 12 13 pd = fork(); 14 15 if(0 > pd) 16 { 17 perror("fork"); 18 exit(EXIT_FAILURE);//--->return 19 } 20 21 if(0 == pd) 22 { 23 printf("this is child process:%d\n", getpid()); 24 printf("my parent process id:%d\n", getppid()); 25 //sleep(5); 26 exit(9); 27 } 28 //子进程程序 29 else if(0 < pd) 30 //pd > 0 31 { 32 // wait(&status);//回收子进程资源 33 //printf("status is %d\n", status>>8); 34 printf("this is parent process:%d\n", getpid()); 35 printf("my parent process id:%d\n", getppid()); 36 //sleep(1); 37 } 38 //父进程程序 39 40 41 return 7; 42 }
运行结果:
可以看到首先打印的是父进程,在打印的是子进程,子进程的父进程号为 1,1是init进程,也是所有进程的祖先进程。
当一个进程成了孤儿进程之后,都会有init进程来回收所有的资源,所以说,孤儿进程的资源不会存在浪费。
4.fork僵尸进程
当一个进程结束,而父进程却没有调用wait函数来回收进程的资源。这个进程叫做僵尸进程.
以下是一个僵尸进程的实例,让父进程睡秒之后再退出!
1 #include <stdio.h> 2 #include <sys/types.h> 3 #include <unistd.h> 4 #include <stdlib.h> 5 6 //fork---->孤儿进程,僵尸进程, 7 8 int main(void) 9 { 10 pid_t pd = 0; 11 int status = 0; 12 13 pd = fork(); 14 15 if(0 > pd) 16 { 17 perror("fork"); 18 exit(EXIT_FAILURE);//--->return 19 } 20 21 if(0 == pd) 22 { 23 printf("this is child process:%d\n", getpid()); 24 printf("my parent process id:%d\n", getppid()); 25 //sleep(5); 26 exit(9); 27 } 28 //子进程程序 29 else if(0 < pd) 30 //pd > 0 31 { 32 //wait(&status);//回收子进程资源 33 //printf("status is %d\n", status>>8); 34 printf("this is parent process:%d\n", getpid()); 35 printf("my parent process id:%d\n", getppid()); 36 sleep(5); 37 } 38 //父进程程序 39 40 41 return 7; 42 } ~
运行结果:
在父进程睡的这5S中可以看到26977的状态为僵尸态。
为了避免这种僵尸状态的出现,造成资源的浪费,需要对子进程的进行“收尸”
一般父进程需要调用wait函数来等待子进程退出之后再退出。
接下来是一个正常退出的进程:
1 #include <stdio.h> 2 #include <sys/types.h> 3 #include <unistd.h> 4 #include <stdlib.h> 5 6 //fork---->孤儿进程,僵尸进程, 7 8 int main(void) 9 { 10 pid_t pd = 0; 11 int status = 0; 12 13 pd = fork(); 14 15 if(0 > pd) 16 { 17 perror("fork"); 18 exit(EXIT_FAILURE);//--->return 19 } 20 21 if(0 == pd) 22 { 23 printf("this is child process:%d\n", getpid()); 24 printf("my parent process id:%d\n", getppid()); 25 sleep(5); 26 exit(9); 27 } 28 //子进程程序 29 else if(0 < pd) 30 //pd > 0 31 { 32 wait(&status);//回收子进程资源 33 printf("status is %d\n", status>>8); 34 printf("this is parent process:%d\n", getpid()); 35 printf("my parent process id:%d\n", getppid()); 36 } 37 //父进程程序 38 39 40 return 7; 41 } ~ ~
运行结果:
可以看到父进程在5S之后等待子进程退出之后在退出!回收子进程的资源!
。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。