簡體   English   中英

如何使用 pipe 或任何其他方法將數據從多個子進程發送到父數組?

[英]How to send data from multiple child process to a parent array using pipe or any other method?

我正在嘗試通過fork()創建多個進程,並對子進程進行一些數學運算,例如數組元素的總和,然后將值返回給父進程,父進程會將每個值保存在parentArray中,如代碼中所述。 現在我的問題是如何在這個階段執行此操作,我只收到第一個進程的一個值,rest 的值為零。 是否有另一種傳遞值的方法,或者可以通過 pipe 來完成? 請幫我

#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <sys/wait.h>

void showReturnStatus(pid_t childpid,int status){
    if (WIFEXITED(status) && !WEXITSTATUS(status))
        printf("Child %ld terminated normally\n", (long)childpid);
    else if (WIFEXITED(status))
        printf("Child %ld terminated with return status %d\n",(long)childpid, WEXITSTATUS(status));
    else if (WIFSIGNALED(status))
        printf("Child %ld terminated due to uncaught signal %d\n",(long)childpid, WTERMSIG(status));
    else if (WIFSTOPPED(status))
        printf("Child %ld stopped due to signal %d\n",(long)childpid, WSTOPSIG(status));
}

int main(int argc, char *argv[])
{
    srand(time(0));
    int arraySize=9,noProcess=3,array[arraySize],status=0;
    pid_t pid;
    int parentSum=0;
    int parentArray[3],fd[2];     //fd file descriptor

    if(pipe(fd)==-1)
        return 0;

    for(int i=0 ;i<arraySize;i++)
        array[i]=(rand()%100)+1;
    
    for(int i=0;i<arraySize;i++){
        printf("\n %d : %d  ",i,array[i]);
    }
    printf("\nParent PID[%d] \n",getpid());
    
    for(int childP=0;childP<noProcess;childP++){
        int child=fork();
        int childSum;
        if(child==0){
            close(fd[0]);
            childSum=0.0;
            for(int i=childP*3;i<(childP+1)*3;i++)
                childSum+=array[i];
            printf("\nChild Process No [%d] PID [%d] Return Sum : %d \n",childP,getpid(),childSum);
            write(fd[1],&childSum,sizeof(childSum));
            close(fd[1]);
            exit(0); 
        }
        pid=wait(&status);
        showReturnStatus(pid,status);
        close(fd[1]);
        read(fd[0],parentArray,sizeof(parentArray));
        close(fd[0]);

    }
    for (int i=0;i<3;i++)
    {
        printf("\nValue Array : %d\n",parentArray[i]);
    }
    

    printf("\nParent Process with PID [%d] calculate Sum : %d\n",getppid());
    return 0;
}

這是您的代碼的修訂版本,其中包含多項更改。

  • 它允許子進程同時運行。

  • 它關注各種錯誤情況。

  • 它每行打印 10 個數據條目。

  • 它檢查數組大小是進程數的 integer 倍數。

  • 它不會在父節點中過早關閉 pipe。

  • 它將錯誤報告給標准錯誤,並以失敗狀態退出。

  • 它在 output 消息的末尾打印換行符; 它不需要在消息的開頭打印換行符。

  • 我更喜歡避免noProcess ,因為它暗示“沒有進程”; 我將其重命名為numProcess

  • 該代碼使用numProcessarraySize來控制所有相關的循環等。

  • 它在父進程中計算並打印總和,以便可以快速檢查來自子進程的值。 這也表明,出於本練習的目的,使用流程是一種人工制品。

  • 它打印每行具有多個條目的數組。

  • 我調整了計算以生成數字 1..99,以便格式%2d統一工作。

  • 我使用這些選項進行編譯(源代碼pipe79.c ,程序pipe79 ):

     gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes pipe79.c -o pipe79
  • argc > 0的測試只是為了確保使用了argc ——如果不是,代碼由於未使用的變量而無法編譯。

  • 我介紹了變量numPerProcessstartstop ,因為這些值至少使用了兩次。

  • 除了制作 static 之外,我不需要觸摸showReturnStatus() ,由於我使用的編譯選項,這也是必要的。 function 不在此源文件之外使用,因此 IMO 無論如何它應該是static 如果它在其他地方使用,它將在 header 中聲明,該 header 將包含在它的定義位置和使用位置。

  • 可能還有其他可以指出的詳細更改,但我忘記了我進行了更改。

代碼:

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>

static void showReturnStatus(pid_t childpid, int status)
{
    if (WIFEXITED(status) && !WEXITSTATUS(status))
        printf("Child %ld terminated normally\n", (long)childpid);
    else if (WIFEXITED(status))
        printf("Child %ld terminated with return status %d\n", (long)childpid, WEXITSTATUS(status));
    else if (WIFSIGNALED(status))
        printf("Child %ld terminated due to uncaught signal %d\n", (long)childpid, WTERMSIG(status));
    else if (WIFSTOPPED(status))
        printf("Child %ld stopped due to signal %d\n", (long)childpid, WSTOPSIG(status));
}

int main(int argc, char *argv[])
{
    srand(time(0));
    int arraySize = 72;
    int numProcess = 6;
    int array[arraySize];
    int fd[2];
    const char *arg0 = (argc == 0) ? "pipe79" : argv[0];    /* Use argc */

    assert(arraySize % numProcess == 0);
    int numPerProcess = arraySize / numProcess;

    if (pipe(fd) == -1)
    {
        fprintf(stderr, "%s: failed to create a pipe\n", arg0);
        exit(EXIT_FAILURE);
    }

    int sum = 0;
    for (int i = 0; i < arraySize; i++)
    {
        array[i] = (rand() % 99) + 1;
        sum += array[i];
    }

    int width = 0;
    const char *pad = "";
    for (int i = 0; i < arraySize; i++)
    {
        width += printf("%s%2d: %2d", pad, i, array[i]);
        pad = ", ";
        if (width > 72)
        {
            putchar('\n');
            width = 0;
            pad = "";
        }
    }
    if (width > 0)
        putchar('\n');
    printf("Sum calculated by parent: %d\n", sum);
    printf("Parent PID[%d]\n", getpid());

    for (int childP = 0; childP < numProcess; childP++)
    {
        int child = fork();
        if (child < 0)
        {
            fprintf(stderr, "%s: failed to fork child %d\n", arg0, childP + 1);
            exit(EXIT_FAILURE);
        }
        if (child == 0)
        {
            close(fd[0]);
            int childSum = 0;
            int start = childP * numPerProcess;
            int stop = start + numPerProcess;
            printf("Child PID %d: processing rows %d..%d\n", getpid(), start, stop - 1);
            for (int i = start; i < stop; i++)
                childSum += array[i];
            printf("Child Process No [%d] PID [%d] Return Sum : %d\n", childP, getpid(), childSum);
            if (write(fd[1], &childSum, sizeof(childSum)) != sizeof(childSum))
            {
                fprintf(stderr, "Child Process No [%d] PID [%d] failed to write to the pipe\n",
                        childP, getpid());
                exit(EXIT_FAILURE);
            }
            close(fd[1]);
            exit(0);
        }
    }

    close(fd[1]);

    sum = 0;
    pid_t pid;
    int status = 0;
    while ((pid = wait(&status)) != -1)
    {
        int number;
        showReturnStatus(pid, status);
        if (read(fd[0], &number, sizeof(number)) != sizeof(number))
        {
            fprintf(stderr, "%s: parent process got a short read on the pipe\n", arg0);
            exit(EXIT_FAILURE);
        }
        printf("sum from pipe: %d\n", number);
        sum += number;
    }

    printf("Parent Process with PID [%d] accumulated sum : %d\n", getpid(), sum);
    return 0;
}

樣品 output:

 0: 68,  1: 13,  2: 74,  3: 37,  4: 88,  5:  4,  6: 73,  7: 94,  8:  2,  9: 71
10: 20, 11: 19, 12: 93, 13: 96, 14: 13, 15: 96, 16: 98, 17: 12, 18: 94, 19: 10
20: 27, 21: 38, 22: 48, 23: 14, 24: 18, 25: 50, 26: 61, 27: 15, 28: 88, 29: 41
30:  2, 31: 99, 32: 42, 33:  8, 34: 55, 35: 32, 36: 29, 37: 53, 38: 78, 39: 15
40: 69, 41: 19, 42: 85, 43: 78, 44:  3, 45: 59, 46: 96, 47: 37, 48: 35, 49: 95
50: 59, 51: 12, 52: 63, 53: 34, 54: 31, 55: 17, 56: 88, 57: 63, 58: 74, 59: 15
60: 10, 61: 38, 62: 24, 63: 27, 64: 70, 65: 64, 66: 40, 67: 43, 68: 87, 69: 82
70: 35, 71: 11
Sum calculated by parent: 3451
Parent PID[58056]
Child PID 58057: processing rows 0..11
Child Process No [0] PID [58057] Return Sum : 563
Child PID 58058: processing rows 12..23
Child Process No [1] PID [58058] Return Sum : 639
Child PID 58059: processing rows 24..35
Child Process No [2] PID [58059] Return Sum : 511
Child PID 58060: processing rows 36..47
Child Process No [3] PID [58060] Return Sum : 621
Child PID 58061: processing rows 48..59
Child Process No [4] PID [58061] Return Sum : 586
Child 58059 terminated normally
sum from pipe: 563
Child 58060 terminated normally
sum from pipe: 639
Child 58058 terminated normally
sum from pipe: 511
Child 58057 terminated normally
sum from pipe: 621
Child 58061 terminated normally
sum from pipe: 586
Child PID 58062: processing rows 60..71
Child Process No [5] PID [58062] Return Sum : 531
Child 58062 terminated normally
sum from pipe: 531
Parent Process with PID [58056] accumulated sum : 3451

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM