1.为什么我们要使用进程
伴随着科技的飞速发展,计算机行业近几十年来经历了巨大的变革进步,如今多核计算机早已经取代单核计算机成为主流,在多核计算机中为充分利用其内部的多个核以提升计算机的工作效率进程这一概念应运而生,通过多进程协同我们可以同时运行多个程序工作,充分利用了多个核心的算力提升了我们的工作效率。
2.Linux中的进程
Linux中自然拥有进程概念,在Linux中每个进程都有自己的存储空间该空间大致分为:代码段,数据段,栈段,堆段四个部分。Linux为了方便管理给每个进程分配了一个进程管理块(PCB)记录进程的基本信息与状态。在Linux中每个进程是由父进程产生所以同时其PCB的管理也由其父进程进行释放。
3.Linux中进程的相关函数(C语言)
在Linux的C语言程序中进程由父进程调用fork()函数产生,在这一过程中子进程运用写时拷贝的技术将父进程的代码复制一遍(这个说法可能不太严谨具体请参考写实拷贝的说法)然后父进程与子进程共用CPU运行(争夺使用权),并且子进程会和父进程一样沿着目前父进程所执行到的地方向下开始执行。
代码演示如下:
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
#include <stdlib.h>
int main()
{
pid_t child;
fprintf(stdout,"....这是开始\n");
child=fork();
if(child==-1)
{
perror("程序错误");
exit(1);
}
else if(child==0)
{
fprintf(stdout,"这是子进程:%d\n",child);
}
else
{
fprintf(stdout,"这是父进程:%d\n",child);
}
exit(0);
}
运行结果:
![](https://img-blog.csdnimg.cn/img_convert/df9d18ba337c26a4092ad5381809ae35.png)
4.僵尸进程与孤儿进程
在第二点中我们提到过子进程的PCB是由父进程进行释放的,那么问题来了,如果子进程先结束而父进程又没有释放其PCB又会发生什么呢?这就是僵尸进程,父进程释放其子进程的PCB是在其结束时释放的在其没有结束的时候是不会释放已结束子进程的PCB的所以“子进程先于父进程结束”就是僵尸进程的成因。此时PCB块空悬,造成了资源浪费同时占用进程序号(PID)。那么反过来父进程先于子进程结束呢?这就形成了孤儿进程,此时操作系统会给子进程分配一个父进程一般是init(pid为1)这一个分配过来的父进程非常靠谱保证能在子进程结束的时候释放其PCB。
僵尸进程代码演示:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
pid_t child;
fprintf(stdout,"...这是开始\n");
child=fork();
if(child==-1)
{
perror("出错了");
exit(1);
}
else if(child!=0)
{
while(1)
{
fprintf(stdout,"这是父进程\n");
sleep(1);
}
}
else
{
fprintf(stdout,"这是子进程\n");
}
exit(0);
}
运行演示:
![](https://img-blog.csdnimg.cn/img_convert/c1acbaa970bc386a97284076e730a814.png)
![](https://img-blog.csdnimg.cn/img_convert/441448ccf11ca9708596b7f26674d559.png)
孤儿进程代码演示:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
int main()
{
pid_t child;
fprintf(stdout,"...这是开始\n");
child=fork();
if(child==-1)
{
perror("出错了");
exit(1);
}
else if(child==0)
{
while(1)
{
fprintf(stdout,"这是子进程\n");
sleep(2);
}
}
else
{
fprintf(stdout,"这是父进程\n");
}
exit(0);
}
运行演示:
![](https://img-blog.csdnimg.cn/img_convert/8cdfc805cad6fd1bb8980695e9f018dc.png)
![](https://img-blog.csdnimg.cn/img_convert/34afa3a773dd59761a97e60a5246bd4b.png)
最简单的结束僵尸进程的方法就是结束其父进程(当然这种方法在很多情况下并不适用)。
5.wait系统调用
wait系统调用是父进程使用来等待子进程(默认只等待一个)退出的,其原型为:pid_t wait(int* stat_loc)。返回值为退出子进程的pid,stat_loc记录子进程main函数返回值。
代码演示:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/wait.h>
int main()
{
pid_t child1;
pid_t child2;
fprintf(stdout,"...这是开始\n");
child1=fork();
if(child1==-1)
{
perror("出错了");
exit(1);
}
else if(child1!=0)
{
child2=fork();
if(child2==-1)
{
perror("出错了");
exit(1);
}
else if(child2==0)
{
fprintf(stdout,"子进程pid为:%d\n",getpid());
exit(0);
}
else
{
int i;
int re=wait(&i);
fprintf(stdout,"wait返回为:%d 状态量i的值为:%d\n",re,i);
}
}
else
{
sleep(5);
fprintf(stdout,"子进程1的pid为:%d\n",getpid());
exit(0);
}
exit(0);
}
运行演示:
![](https://img-blog.csdnimg.cn/img_convert/8789e420b43b45635bd3a4002606c123.png)