簡體   English   中英

LINUX IPC:使用PIPE將不同的值傳遞給CHILD進程,除了第一次,在C中不起作用

[英]LINUX IPC: Passing different values to CHILD process using PIPE not working, except for first time, in C

我有一組taskid分為幾組,每組由唯一的groupid標識。

  1. 對於每個group ,我需要生成一個子進程( 每個進程都充當服務器-意味着它們從其他進程獲取消息並在處理后返回結果 )。

  2. 每個孩子都有權為其與其關聯的GROUP專門服務。 因此,我想在生成后立即將唯一的groupId傳遞給每個子進程,以便它僅執行與其groupId相關聯的任務。

  3. 在CHILD產生時,PARENT僅向CHILD寫入了groupId ,也只有一次。 CHILD不應該將任何內容寫回PARENT。 (單向通信- PARENT - write/CHILD -read

經過一些研究,我編寫了如下的偽代碼。 (這是一個可編譯的代碼)。

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

int process(int n);

#define NGROUPID 5
#define INIT_GROUPID 1000

int parent_to_child[2];
int main()
{
    pid_t pid;
    pid_t pid_array[NGROUPID];  //Child pid array.
    int groupId[NGROUPID];
    int groupID = 0,i;

    srand((unsigned int) time(NULL));  //random seed
    groupId[0] = INIT_GROUPID;

    printf("[0.1] ");
    //set groupIds 
    for(i=1; i < (NGROUPID - 1); i++)
    {
        int j = i -1;
        groupId[i]= groupId[j] + 2;
        printf("%d~%d\t",j,groupId[j]);

    }
    printf("%d~%d\n",i-1,groupId[i-1]);

    fflush(stdout); //Flushing stdout before pipe call
    pipe(parent_to_child);

    // For each groupId, spawn child process 
    for (i = 0; i < (NGROUPID - 1); i++ )
    {

        pid = fork();
        if(pid < 0)
        {
            perror("fork failed\n");
            exit(1);
        }
        if(pid == 0)
        {
            process(i); //Child Process.
            break;  //Is it necessory to break? Will it create Children of children?
        }
        if(pid > 0)
        {
            close(parent_to_child[0]); //parent is not reading from child
            printf("[1.1] writing to child: %d parent %d i %d groupId %d\n",pid,getpid(),i,groupId[i]);
            write(parent_to_child[1], &groupId[i], sizeof(int)); //Passing groupId to Child.
            pid_array[i] = pid;  //To shutdown cleanly.
        }
    }
    if(pid > 0)
    {

        for (i = 0; i < (NGROUPID - 1); i++ )
        {
            printf("[1.2] waiting for pid: %d\n",pid_array[i]);
            waitpid(pid_array[i], NULL, 0);
            printf("[1.3] Finished pid: %d\n",pid_array[i]);
        }

    }

    printf("[0.2] Did we Finished total %d PID %d\n", NGROUPID, getpid());
    if(pid > 0)
        printf("[1.4] There are no zombies\n");

    return 0;

}

//This is a pseudo code. Actual code will consists of receiving messages
// from other processes (using message queue) and return the results after processing.
// This act like a SERVER process, which will not quit in usual scenario. 
int process(int n)
{
    int groupID = 0;
    close(parent_to_child[1]); //we are not going to return to Parent.
    read(parent_to_child[0], &groupID, sizeof(int)); //Read from Parent
    unsigned int sec = (rand() % 10) + 1;
    printf("[2.1] Processing %d th Process pid: %d groupId %d sleep %d sec\n",n, getpid(), groupID, sec);
    sleep(sec);
    printf("[2.2] Returning from sleep %d Process pid: %d groupId %d sleep %d sec\n",n, getpid(), groupID, sec);
}

該程序的輸出如下:

    [0.1] 0~1000    1~1002  2~1004  3~1006
    [1.1] writing to child: 15068 parent 15067 i 0 groupId 1000
    [2.1] Processing 0 th Process pid: 15068 groupId 1000 sleep 3 sec
    [1.1] writing to child: 15069 parent 15067 i 1 groupId 1002
    [2.1] Processing 1 th Process pid: 15069 groupId 0 sleep 3 sec
    [1.1] writing to child: 15070 parent 15067 i 2 groupId 1004
    [2.1] Processing 2 th Process pid: 15070 groupId 0 sleep 3 sec
    [1.1] writing to child: 15071 parent 15067 i 3 groupId 1006
    [1.2] waiting for pid: 15068
    [2.1] Processing 3 th Process pid: 15071 groupId 0 sleep 3 sec

    // This Gap is not a part of output. It indicates the sleep worked from here.

    [2.2] Returning from sleep 0 Process pid: 15068 groupId 1000 sleep 3 sec
    [0.2] Did we Finished total 5 PID 15068
    [2.2] Returning from sleep 1 Process pid: 15069 groupId 0 sleep 3 sec
    [0.2] Did we Finished total 5 PID 15069
    [1.3] Finished pid: 15068
    [1.2] waiting for pid: 15069
    [1.3] Finished pid: 15069
    [1.2] waiting for pid: 15070
    [2.2] Returning from sleep 2 Process pid: 15070 groupId 0 sleep 3 sec
    [0.2] Did we Finished total 5 PID 15070
    [1.3] Finished pid: 15070
    [1.2] waiting for pid: 15071
    [2.2] Returning from sleep 3 Process pid: 15071 groupId 0 sleep 3 sec
    [0.2] Did we Finished total 5 PID 15071

輸出中的編號系統如下。

    [0.*] - Indicate that Print from General part of code (neither parent or child)
    [1.*] - Indicate that Print from PARENT process. (pid > 0)
    [2.*] - Indicate that Print from CHILD process.  (pid == 0)

此代碼幾乎沒有問題。

1.隨機數我依靠隨機數來為兒童產生不均勻的睡眠時間,這模仿了實際情況。 即使我在main函數中放置了srand(time(NULL))函數,但process() function中的rand()始終生成相同的輸出(在上面的輸出中為3 seconds )。 是因為CPU太快了嗎? 如果是,是否有更好的種子可用?

2.閱讀PIPE
除非第一次,從CHILD進程讀取的groupId始終為零。 如下面的輸出所示。

[2.1] Processing 2 th Process pid: 15070 groupId 0 sleep 3 sec

您可以清楚地看到,在由父代進行writegroupId被正確拾取。 (如下所示):

[1.1] writing to child: 15070 parent 15067 i 2 groupId 1004

我如何改進此代碼以實現結果。 還是這種邏輯有任何缺陷(我問這個問題是因為我是IPC的初學者,沒有太多的經驗)。 我是否需要為groupId數組實現一個critical section

提前致謝。

隨機數。 您在分叉之前先叫srand ,所以所有子代都繼承相同的種子,因此他們對rand的調用將產生相同的數字。 您可以在循環內增加種子,並使每個子代自己調用srand

通訊。 parent_to_child[0]在生成第一個孩子后關閉parent_to_child[0] ,因此以后的孩子將繼承封閉的管道,並且無法通過它接收groupID信息。 僅當所有分叉完成時,父級才應關閉該管道。

暫無
暫無

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

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