版权声明:醋姑娘 https://blog.csdn.net/weixin_37023469/article/details/82996092
前言
这学期在学操作系统,目前感觉还是挺有意思的。
操作系统老师:“鼓励你们大开脑洞多试试,会有各种奇异的结果,但是最后居然都能解释出来。”
本文是根据课上讲解+自行实践写的。
测试环境:Ubuntu
正文
关于fork()的3种返回值
- 这里提到的fork和下面程序中使用的fork()是一个C语言库函数,不是系统调用级别的fork();它根据不同的情况会返回3种类型的值。(而系统调用级别的fork只返回一种值:那就是创建出来的子进程的pid。)
- 在父进程中,返回创建的子进程的pid
- 在子进程中,返回0
- 出错,返回负值
下面程序的if分支是对这个知识点的运用。
#include <stdio.h>
#include <unistd.h>
int main(){
pid_t pid;
pid = fork(); //创建子进程
if(pid==0){
printf("child process\n");
}
else if (pid>0){
printf("parent process\n");
}
else{
//error 这里不作处理
}
}
输出结果是:
parent process
child process
(不同操作系统中可能顺序不一样?因为父进程和子进程可以并发,执行顺序由操作系统调度策略决定?——不是特别确定)
关于缓冲区
- 上课的时候老师提到了一个例子,让我们回去自己试试
#include <stdio.h>
#include <unistd.h>
int main(){
pid_t pid;
//第一种
printf("start...");
//第二种
//printf("start...\n");
pid = fork();
if(pid==0){
printf("child process\n");
}
else if (pid>0){
printf("parent process\n");
}
else{
//error 这里不作处理
}
}
可以看到我们在fork()调用前写了一局printf,两种情况唯一的区别就是多了个’\n’。
- 输出结果:
- 第一种:
start…parent process
start…child process - 第二种:
start…
parent process
child process
- 第一种:
看到这个结果我就觉得可能是’\n’能刷新/清除缓冲区之类的原因吧。然后问了下老师。
- 我:pcb中是否存在类似输出缓冲区的信息,而换行可以刷新/清空缓冲区?所以执行fork()时,"start…"还在缓冲区没有真正地被输出在显示器上,就被复制到子进程的pcb中的缓冲区去了。
- 老师:如果不强制清除缓冲区,想当于子进程不仅copy了父进程的内存、PCB,还copy了缓冲区的内容。\n 或者flush都是强制清除缓冲区,所以加\n就是清除之后再执行下一条指令。如果不加\n,提交到缓冲区就接着执行下一条指令了。
关于wait()的机制
- 经过测试,Ubuntu下:当父进程调用wait()函数时,是从调用的那一刻起,CPU就不再执行父进程了,父进程进入waiting(阻塞)状态,等待合作进程(子进程)的消息,直到子进程完全结束,父进程才会变成ready(就绪)状态。
- 因为只在Ubuntu和Mac os上测试了下,在别的系统中还有一种可能(虽然并未找到这样的系统,因为根本没有去试):CPU还是会执行父进程,只是每次执行的时候都因为fork()、wait()返回值之类的原因在一直停留在wait(),无法执行下面的语句,造成从表面上看好像没有执行的假象。