流程
子进程被Linux内核调入CPU执行的过程
进程的生命周期包括从创建到退出的全部状态转化,它的生成周期里并不一定要经历所有的状态。
最初,父进程通过fork系统调用创建子进程,子进程被创建后,处于创建状态。Linux内核为子进程配置数据结构,如果内存空间足够,子进程在内核中就绪,否则在swap分区就绪。这时子进程处于就绪状态,等待Linux内核调度。
Linux内核会为子进程分配CPU时钟周期,在合适的时间将子进程调度上CPU运行,这时子进程处于内核状态,子进程开始运行。被分配的CPU时钟周期结束时,Linux内核再次调度子进程,将子进程调出CPU,子进程进入用户状态。
待子进程被分配的下一个CPU时钟周期到来时,Linux内核又将子进程调度到CPU运行,使子进程进入内核状态。如果有其他的进程获得更高优先级,子进程的时钟周期可能会被抢占,这时又会回到用户状态。
子进程进入睡眠状态
子进程在运行时,如果请求的资源得不到满足将进入睡眠状态,睡眠状态的子进程被从内存调换到swap分区。被请求的资源可能是一个文件,也可能是打印机等硬件设备。如果该资源被释放,子进程将被调入内存,继续以系统状态执行。
子进程结束
子进程可以通过exit系统调用结束,这时子进程将进入到僵死状态,生命周期结束。
例子
这里是一个通过fork()创建一个子进进程的例子,其中左边的红线表示父进程的流程,有表表示子进程的流程。
代码
#include <unistd.h> //fork()
#include <sys/types.h>
#include <stdio.h> //puts()
int main()
{
int status;
puts("start");
//创建子进程
pid_t pid = fork();
if(pid==-1){
perror("创建子进程失败");
return 1;
}
//判断是否是子进程
if(pid==0){
puts("I'm child");
puts("sleep 5s ...");
sleep(5);
puts("sleep end");
printf("子进程PID是%d\n", getpid());
printf("父进程PID是%d\n", getppid());
return 0;
}
else{
puts("I'm parent");
printf("子进程PID是%d\n", pid);
printf("父进程PID是%d\n", getpid());
}
wait(&status);
printf("%d\n", status);
puts("main end");
return 0;
}
运行结果
start
I'm parent
子进程PID是22875
父进程PID是22874
I'm child
sleep 5s ...
sleep end
子进程PID是22875
父进程PID是22874
0
main end
参考
- Linux环境C程序设计