【问题标题】:How to pass values between processes after using the fork() call?使用 fork() 调用后如何在进程之间传递值?
【发布时间】:2020-10-04 03:03:32
【问题描述】:

我需要创建一个程序,该程序将启动 4 个进程之间的竞赛,以从用户输入中获取一个数字。用户将输入 4 个数字(1 到 4),收到第一个数字 (1) 的进程将成为获胜者,首先,随后的进程将获得第二、第三和第四名,具体取决于他们从用户。

程序将首先使用fork()系统调用创建4个进程,每个创建的进程由一个1到4的数字标识,这个数字表示它的创建顺序。例如,创建的第一个子进程的 ID = 1。

毕竟,进程被创建,进程将开始向用户请求一个数字。每个进程都会打印它从用户那里得到的号码,并打印它的 ID 号。父进程不参与比赛,等待所有子进程完成后退出。

我认为我已经完成了基本结构,但我不确定如何在进程之间传递值,或者是否正在完成合法的竞争条件。我也无法运行最后 3 个进程。

这是我的输出:

My output

这是预期的输出:

Expected Output

这是我目前所拥有的:


#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>

    int p1, p2, num; 

int procNUM = 1, runNum = 1 ;

void game(int p1,int p2);

int main() {
    
     printf("Enter numbers for processes to race for >>>\n");

    p1 = fork();

    p2 = fork();
    
if (p1 > 0 && p2 > 0) { 
       //parent 
       
      
            printf(" I am a process with pid %d and I am process number %d in the race.\n",getpid(), procNUM);
            procNUM++;
           // fflush(stdout);
           // scanf("%d", &num);
           // printf("%d", &num);
           // printf(I am a processs with);
       
    } 
    
    else if (p1 == 0 && p2 > 0) 
    { 
    //child 1 
    
     printf(" I am a process with pid %d and I am process number %d in the race.\n",getpid(), procNUM);
     procNUM++;
    // fflush(stdout);
     
    } 
    
    else if (p1 > 0 && p2 == 0) 
    { 
    //child 2 
   
    printf(" I am a process with pid %d and I am process number %d in the race.\n",getpid(), procNUM);
    procNUM++;
    //fflush(stdout);
    
    
    } 
    
    else { 
       //child 3
       
    printf(" I am a process with pid %d and I am process number %d in the race.\n",getpid(), procNUM);
    procNUM++;
   // fflush(stdout);
   
       
        
    } 


    game(p1, p2);

 return 0;   
}


void game(int p1,int p2){
    if (p1 > 0 && p2 > 0) { 
       //parent 
            scanf("%d", &num);
            printf(" I am a process with pid %d and I am process number %d in the race and I am in %d place.\n",getpid(), procNUM, runNum);
            //fflush(stdout);
            runNum++;
       
    } 
    
    else if (p1 == 0 && p2 > 0) 
    { 
    //child 1 
    
            scanf("%d", &num);
            printf(" I am a process with pid %d and I am process number %d in the race and I am in %d place.\n",getpid(), procNUM, runNum);
            //fflush(stdout);
       runNum++;
    
    
    } 
    
    else if (p1 > 0 && p2 == 0) 
    { 
    //child 2 
   
            scanf("%d", &num);
            printf(" I am a process with pid %d and I am process number %d in the race and I am in %d place.\n",getpid(), procNUM, runNum);
           // fflush(stdout);
       runNum++;
    
    } 
    
    else { 
       //child 3
       
            scanf("%d", &num);
            printf(" I am a process with pid %d and I am process number %d in the race and I am in %d place.\n",getpid(), procNUM, runNum);
            //fflush(stdout);
       runNum++;
        
    } 
    
    
    
}





【问题讨论】:

    标签: c linux pipe fork race-condition


    【解决方案1】:

    fork'ing 之后,您的 procNUM 变量“分支”并且与父进程的 procNUM 没有任何共同之处,因此递增它不会告诉父进程任何信息(写入时复制)。

    要将值传递给子进程,请使用 argv[] 数组 - 它是 execvp 函数的参数。

    我建议采用标准方式:在主程序中启动多个线程,每个线程启动一个子进程。子进程(game.c)代码很简单:

    #include <stdio.h>
    int main(int argc, char** argv)
    {
        int num;
        scanf("%d", &num);
        return num;
    }
    

    父程序涉及更多。

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    // #include <threads.h>
    // #include <stdatomic.h>
    #include <pthread.h>
    
    // Compile the program above to  'game' using "gcc -o game game.c"
    #define N (4)
    const char* game_file = "./game";
    
    // Declare PID array, ret_code and threads
    int pids[N];
    int ret_code[N];
    pthread_t thread[N];
    // C11: thrd_t thread[N];
    
    // Each thread increments this atomic int when the child process finishes
    /* C11: atomic_int */ int proc_finish_count;
    

    线程程序是

    int game_proc(void *arg) {
        int i = *((int*)arg);
        pids[i] = fork();
        if (pids[i] > 0) {
            while(1) {
                int st;
                int res = waitpid(pids[i], &st, WNOHANG);
                if (res == pids[i]) {
                    proc_finish_count++;
                    // In C11 use atomics :
                    // atomic_fetch_add_explicit(&proc_finish_count, 1, memory_order_relaxed);
                    printf(" I am a process with pid %d and I am process number %d in the race and I am in %d place.\n", pids[i], i, proc_finish_count);
                    break;
                } else
                if (res < -1) {
                    // error while waiting
                    return 1;
                }
            }
        } else { 
            // Here you can pass parameters to `game` - insert the list of strings before NULL
            execlp(game_file, game_file, NULL);
            printf("Error running process\n");
        } 
    
        return 0;
    }
    

    主函数只是启动并等待线程

    int main(){
        int i;
        proc_finish_count = 0;
        for (i = 0 ; i < N ; i++) {
            ret_code[i] = i; // index of the process
            pthread_create(&thread[i], NULL, &game_proc, &ret_code[i]);
            // C11: thrd_create(&thread[i], &game_proc, &ret_code[i]);
        }
    
        for (i = 0 ; i < N ; i++)
            pthread_join(&thread[i], NULL);
            // C11: thrd_join(thread[i], NULL);
    
        return 0;
    }
    

    由于您的孩子处理“竞争”标准输入,我建议将“xterm”或其他终端仿真器作为子进程启动 - 这样输入可以真正“竞争”。

    【讨论】:

    • 在编译这个时,我收到一个错误,提示找不到 threads.h。这是命令 gcc -o parent Dee_parent.c。知道可能出了什么问题吗?
    • 我使用的是 C11 标准,如果您有旧的编译器,请将 thrd_create 更改为 pthread_create 并将 thrd_join 更改为 pthread_join。此外,thrd_t 现在是 pthread_t 并且 pthread_create 的参数应该有另一个 NULL(参见手册页)。
    • 由于您使用的是 GCC,只需尝试“gcc -std=c11 -o parent parent.c”命令(显式启用 C11 支持)
    • 我认为,不需要修改。我一开始不想使用 C11,但是带有特定于操作系统的原子和 libpthread 的代码似乎更冗长。
    • 我尝试使用 C18 运行它,它给了我相同的线程。h 未找到错误。它需要 pthread,h 文件,这需要您将所有常规线程函数更改为 pthread 函数。我不知道如何让它与 pthread 一起工作。
    猜你喜欢
    • 1970-01-01
    • 2011-12-13
    • 1970-01-01
    • 1970-01-01
    • 2021-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多