为了更好地理解fork()系统调用,我在fork()和print语句之间随机播放,但卡在一个这样的代码中,代码是
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
printf("\n my process id %d \n",getpid());
pid_t pid1=fork();
printf("\nPID:=%d fork returned %d\n",getpid(),pid1);
pid_t pid2=fork();
printf("\nPID:=%d fork returned %d\n",getpid(),pid2);
pid_t pid3=fork();
printf("\nPID:=%d fork returned %d\n",getpid(),pid3);
return 0;
}
这是获得的输出 - :
我无法获得它所遵循的打印序列。我得到的只是首先执行PID 5079的过程,并且对于所有fork()系统调用,它将子PID返回到父级process.I我没有得到进一步的序列。
答案 0 :(得分:0)
fork()起初可能看起来有些混乱,但实际上非常简单。它的作用是将当前进程复制到另一个内存位置的新进程(复制所有内容,其数据,代码,当前指令......)。
所以我们开始使用pid = 5079的进程,当我们进行fork调用时,创建了一个pid = 5080的子进程,并且它具有与父进程相同的代码。
// Parent Process // // Child Process //
#include<stdio.h> #include<stdio.h>
#include<unistd.h> #include<unistd.h>
#include<stdlib.h> #include<stdlib.h>
int main() int main()
{ {
printf("\... printf("\...
pid_t pid1=fork(); pid_t pid1=fork();
printf("\nPI... //Next line// printf("\nPI... //Next line//
pid_t pid2=fork(); pid_t pid2=fork();
printf("\nPID:=... printf("\nPID:=...
pid_t pid3=fork(); pid_t pid3=fork();
printf("\nPID:=... printf("\nPID:=...
return 0; return 0;
} }
在继续执行代码之前,fork调用的返回值如下:在调用fork()的进程内,返回值是子进程的pid(父进程中的pid1变量= 5080) ,在子进程内,输出为0(子进程中的pid1变量= 0)。
所以fork之后的print语句将由父进程和子进程执行,具有不同的getpid()值和不同的pid1值,父进程有getpid()= 5079,pid1 = child进了pid = 5080(你可以在输出的第三行看到这个)。孩子将使用getpid()= 5080和pid1 = 0创建自己的print语句,你可以在输出的第8行看到这个,但是为什么第8行!!!
操作系统调度进程,即决定CPU将在哪个进程上工作以及进行多长时间。因此,操作系统似乎决定父进程(pid = 5079)应运行一段时间,并让子进程(pid = 5080)等待CPU执行其指令。
所以进程5079继续使用下一个fork,用pid = 5081创建一个新的子进程。然后它打印出我们在第三行中所期望的内容,然后它继续进行最后一个fork创建进程5082,打印出我们想要的内容期望在第四行,然后终止(进程5079终止,留下5080,5081,5082等待,并由操作系统采用,他们需要有一个父,但这对输出并不重要。)
现在5079终止,我们有3个进程在内存中等待CPU工作。操作系统必须决定运行哪个进程,并且似乎选择了最接近终止的进程,即进程5082,让我们看一下每个进程的剩余指令:
// process 5082 // // process 5081 // // process 5080 //
printf("\nP... printf("\nP... printf("\nP...
return 0; pid_t pid3=fork(); pid_t pid2=fork();
printf("\nP... printf("\nP...
return 0; pid_t pid3=fork();
printf("\nP...
return 0;
为什么这是剩下的代码?在一些其他进程中由fork创建的任何进程将在我们之前看到的fork语句之后开始执行。因此,处理5082打印的行5然后终止(其值为pid3 = 0,因为它是5079的子节点)。在终止5082之后,5081占用了CPU,它打印了第6行,然后创建了第50行的过程5085(为什么不按顺序排列5083?也许操作系统在执行代码时创建了一些过程)。
在打印线6之后过程5081终止。现在我们在内存中有5080和5085。您现在应该可以按照模式,选择5080运行,创建5086和5087然后终止。然后5085跑,接着5087,最后只有打印声明,然后终止,我们留下5086打印,最后一个分叉创建5088,然后在打印后终止5088。
操作系统是一个迷人的领域,超越系统调用的乐趣,如果你对此感兴趣我会推荐这本书,这是我在大学学习的: https://www.amazon.com/Operating-System-Concepts-Abraham-Silberschatz/dp/0470128720