fork()syatem call

时间:2017-03-05 14:52:13

标签: operating-system fork computer-science system-calls

为了更好地理解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;
}

这是获得的输出 - :

output

我无法获得它所遵循的打印序列。我得到的只是首先执行PID 5079的过程,并且对于所有fork()系统调用,它将子PID返回到父级process.I我没有得到进一步的序列。

1 个答案:

答案 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