在c语言中使用fork

Gol*_*olu 11 c fork systems-programming

现在我在理解fork()系统调用的工作方面遇到了问题.我写了一个代码如下:

#include<stdio.h>
int main()
{
    int a, b;
    b=fork();

    printf("\n the value of b = %d",b);
}
Run Code Online (Sandbox Code Playgroud)

此代码的输出如下:

现在我不明白为什么输出是这样的?

之后,我只是在我的代码中添加一行,输出完全不同.我的代码如下:

int main()
{
    int a, b;
    b=fork();
Run Code Online (Sandbox Code Playgroud)

当我运行代码输出跟随2389我的名字是manish

 the value of b = 0
Run Code Online (Sandbox Code Playgroud)

现在我对fork()通话的工作感到很困惑.

我的问题如下:

  1. 怎么样fork()
  2. 控制在fork()通话结束后的位置?
  3. 任何机构都可以解释为什么编写的代码输出有问题吗?
  4. 为什么b在不同位置发生的输出意味着在第一个代码中输出b = 2260就在输出之前,b = 0而值b = 2389不在...之前b = 0

请解释我在问题中编写的代码中的fork的工作,以便我可以正确地学习它.

lad*_*ini 39

首先要理解为什么使用fork这个词来命名这个函数可能会有所帮助.有没有听说过"在路上岔路口?" 在分支处,该过程必须分割路径.

首先,只有一个进程正常执行,直到您到达fork呼叫.调用fork时,会创建一个新进程,除了fork函数的返回值之外,它几乎与原始进程完全相同.新创建的进程称为子进程,因此生成它的进程称为父进程.

由于您希望为fork的每个分支执行不同的任务,因此您必须能够将子进程与父进程区分开来.这就是返回值的fork来源:fork将子进程id(pid)(新创建的进程)返回给父进程; 它给孩子返回0.另外,如果执行fork错误,返回值为-1.

在您的代码中,您不区分子进程和父进程,因此两个进程都会在fork调用后运行整个代码.

//what the child process looks like after fork is called
int main()
{
    int a, b;
    b=fork(); // <-- current line of execution: 0 is returned to b
    printf("\nmy name is manish\n");
    printf("\n my name is anil\n");
    printf("\n the value of b = %d",b);
}

// what the parent process looks like after fork is called
int main()
{
    int a, b;
    b=fork(); // <-- current line: child process id is returned
    printf("\nmy name is manish\n");
    printf("\n my name is anil\n");
    printf("\n the value of b = %d",b);
}
Run Code Online (Sandbox Code Playgroud)

如您所见,两个进程在fork之后具有相同的代码,因此重复输出.也许如果你想让父进程输出Manish和孩子输出Anil,那么你可以这样做:

int main()
{
    pid_t b; // note that the actual return type of fork is 
             // pid_t, though it's probably just an int typedef'd or macro'd

    b = fork();
    if (b == -1) perror("Fork failed");
    else if (b > 0) {
        printf("My name is Manish\n"); // parent process
    else
        printf("My name is Anil\n"); // child process

    printf("The value of b is %d\n", b);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

最后,必须进行的最后一个注释是,在您的代码中,输出似乎首先由一个进程完整执行,然后是另一个进程的完整执行.情况可能并非总是如此.例如,操作系统可能允许父进程执行'manish'输出,然后使该进程等待,并将cpu交给子进程,然后子进程执行'manish'.但是,子进程可以继续并执行'anil'和'b'输出,完成子进程的执行,从而将执行返回到父进程.现在父母通过输出'anil'和'b'本身来完成它的执行.运行此程序的最终输出可能如下所示:

my name is manish     // executed by parent
my name is anil       // child
the value of b = 0    // child
my name is anil       // parent
the value of b = 2244 // parent
manish.yadav@ws40-man-lin:~$ 

看看手册页fork.另请waitpid参阅父进程正确处理子进程,以便您不创建僵尸.

编辑:为了回答您在评论中提出的问题,我将回答您如何简单地连续运行每个流程.

int main() 
{
     pid_t pid;
     int i;

     for (i=0; i<NUM_PROCESSES; i++)
     {
         pid = fork();
         if (pid == -1) 
         {
             perror("Error forking");
             return -1;
         }
         else if (pid > 0)
         {
             // parent process
             waitpid(-1, NULL, 0); //might want to look at man page for this
                                   // it will wait until the child process is done 
         }
         else 
         {
             // do whatever each process needs to do;
             // then exit()
             doProcess(i);
             exit(0);
         }
     }
     // do anything else the parent process needs to do
     return 0;
}
Run Code Online (Sandbox Code Playgroud)

当然,这不是最好的代码,但它只是为了说明这一点.这里的主要思想是waitpid调用,这会导致父进程等待直到子进程处理它才fork终止.在子prcoess完成之后,父进程在waitpid调用之后继续,开始循环的另一次迭代for并分叉另一个(下一个)进程.这将继续,直到所有子进程按顺序执行,执行最终返回到父进程.

  • @Golu分叉的想法意味着进程可以同时运行.如果你想按顺序运行它们(可以这样做,而不是说它们不能),为什么首先要分叉?您是否通过按顺序运行流程来实现更大的目标? (2认同)

Chr*_*ick 5

  1. Fork会创建当前进程的副本.
  2. 原始副本和副本都从fork()被调用的点继续执行.
  3. 因为您的代码执行了两次,所以您的print语句也会被评估两次.在复制的进程中,值为b0.在原始进程中,值b是复制进程的进程ID.
  4. 一旦您的进程同时开始运行,它们将由您的操作系统独立调度,因此您无法保证它们何时实际运行.