system函数
我们已经实现了通过fork函数创建一个子进程然后通过execve函数来实现子进程代码的加载从而让子进程运行另一个程序。
system函数是对于fork函数和execve函数的封装,调用时会自动创建子进程空间,并且把新程序的代码加载到子进程中运行起来。
system函数
函数原型:
#include <stdio.h>
int system(const char * command);
功能:创建子进程并且加载新程序到子进程空运行起来。
参数:新程序的路径名和文件名
代码演示:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
system("ls");
return 0;
}
运行结果为:
上面进程赋值的新进程的代码就是ls命令。
我们可以看到ls在bin这个目录下面。
这个路径在环境变量当中。所以上面代码不需要外加路径。
那么我们也可以加载我们自己的程序,这个时候就需要加上路径名:
我们在当前文件写入一个main.c文件
main.c
#include <stdio.h>
int main()
{
printf("this is new process\n");
return 0;
}
生成可执行文件main
然后通过system函数加载main函数:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
system("./main");
return 0;
}
运行结果为:
回收进程资源
进程运行终止之后,不管进程是正常终止还是异常终止,必须回收进程所占用的资源。
为什么要回收进程资源?
1:程序代码在内存中动态运行起来之后才有了进程,既然进程结束了,就需要将代码占用的内存空间释放出了。
2:OS为了管理进程,为每一个进程在内从中开辟了一个task_struct 结构体变量,进程结束了,这个结构体所占用的内存空间也需要被释放。
3:进程在运行的过程中也会占用其他资源,我们都要进行释放。
由父进程来回收进程空间,父进程运行结束时,会释放子进程资源。
僵尸进程和孤儿进程
子进程终止,但是父进程还在运行,父进程没有回收子进程资源之前,子进程就是僵尸进程。
孤儿进程:
子进程还在运行,但是父进程终止了,子进程就是孤儿进程
为了能够回收孤儿进程终止后的资源,孤儿进程会被托管到PID为1的init进程,当被托管的子进程终止时,init会立即主动回收孤儿进程的进程资源,回收资源很快,所以孤儿进程没有变成僵尸进程。
代码演示:僵尸进程
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
pid_t ret = 0;
ret = fork();
if(ret>0)
{
while(1);
}
else if(ret == 0)
{
}
return 0;
}
运行结果为:
我们把与所有终端相关的的进程进行显示:
我们可以看到最前面有不同大写的字母:
R代表正在运行
S代表处于休眠状态
Z代表僵尸进程,进程运行完等待被回收资源。
我们可以看到父进程PID为10731的进程前面时R,R代表正在运行。
子进程PID为11648的进程前面时Z表示的是僵尸进程。
代码演示:孤儿进程
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
pid_t ret = 0;
ret = fork();
if(ret>0)
{
}
else if(ret == 0)
{
while(1);
}
return 0;
}
运行结果为:
我们可以看到在执行之后退出了,这个时候父进程结束了,就把终端控制权返回给shell程序,这个时候子进程一直在执行。我们进行查看:
此时a.out是子进程并且正在运行,就是孤儿进程。