【问题标题】:Need help in IPC through Pipes通过 Pipes 在 IPC 方面需要帮助
【发布时间】:2012-04-04 07:36:11
【问题描述】:

我在实验室工作。 父进程将创建两个子进程 A 和 B。 儿子 A 将通过管道向儿子 B 发送一些字符串。儿子 B 将反转从儿子 A 得到的字符串的字符串大小写,并将反转的字符串发回给儿子 A。收到反转的字符串后,儿子 A 将其打印到屏幕上.

这是代码。

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

void process_A(int input_pipe[], int output_pipe[])
{
    int c;    
    char ch; 
    int rc;  


    close(input_pipe[1]); 
    close(output_pipe[0]); 

    while ((c = getchar()) > 0) {
        ch = (char)c;
        rc = write(output_pipe[1], &ch, 1);
    if (rc == -1) { 
        perror("A_TO_B: write");
        close(input_pipe[0]);
        close(output_pipe[1]);
        exit(1);
        }

    rc = read(input_pipe[0], &ch, 1);
    c = (int)ch;
    if (rc <= 0) { 
        perror("A_TO_B: read");
        close(input_pipe[0]);
        close(output_pipe[1]);
        exit(1);
        }
    putchar(c);
    }
    close(input_pipe[0]);
    close(output_pipe[1]);
    exit(0);
}

void process_B(int input_pipe[], int output_pipe[])
{
    int c;   
    char ch; 
    int rc;   
    close(input_pipe[1]); 
    close(output_pipe[0]); 
    while (read(input_pipe[0], &ch, 1) > 0) {
        c = (int)ch;
        if (isascii(c) && isupper(c))
            c = tolower(c);
          else if (isascii(c) && islower(c))
            c = toupper(c);
        ch = (char)c;
        rc = write(output_pipe[1], &ch, 1);
        if (rc == -1) {
            perror("B_TO_A: write");
            close(input_pipe[0]);
            close(output_pipe[1]);
            exit(1);
        }
    }

    close(input_pipe[0]);
    close(output_pipe[1]);
    exit(0);
}


int main(int argc, char* argv[])
{
    /* 2 arrays to contain file descriptors, for two pipes. */
    int A_TO_B[2];
    int B_TO_A[2];
    int pid;       
    int rc,i,State;       

    /* first, create one pipe. */
    rc = pipe(A_TO_B);
    if (rc == -1) {
    perror("main: pipe A_TO_B");
    exit(1);
    }
    /* create another pipe. */
    rc = pipe(B_TO_A);
    if (rc == -1) {
    perror("main: pipe B_TO_A");
    exit(1);
    }

    for(i=0;i<2;i++)
    {
        if((pid=fork()) <0){perror("fork failed\n");};
        if((i==0) && (pid ==0))
        {
            process_A(A_TO_B, B_TO_A); 
        }
        else if((i==1)&&(pid==0))
        {
            process_B(B_TO_A, A_TO_B); 
        }
        else if(pid>0)
        {
           wait( &State );          
        }   
    }

    return 0;   
}

问题是当我运行程序时,儿子 B 会被阻止。 我需要你们帮助。 提前致谢。

【问题讨论】:

    标签: unix operating-system ipc multiprocessing inter-process-communicat


    【解决方案1】:

    好的,图表:

    initially: parent process: has
      B_TO_A[0] and [1] open,
      has A_TO_B[0] and [1] open
    fork (makes copy)
    parent:                                child (pid==0):
    B_TO_A both open, A_TO_B both open     call process_A: close unwanted pipe ends, loop
    
    call wait(), wait for one child        loop reads stdin, writes one pipe, reads other pipe
    
    if we ever get here:
    
    fork (makes copy)
    parent:                                child (pid==0):
    B_TO_A both open, A_TO_B both open     call process_B: close unwanted pipe ends, loop
    
    parent: both ends of both pipes open
    call wait(), wait for one child        loop reads one pipe, writes other pipe
    

    首先,您通常不会到达“如果我们到达这里”,因为运行 process_A() 的子进程在循环中运行,直到标准输入上的 EOF(如果首先发生)或管道读/写调用之一失败(例如,由于 input_pipe[0] 上的 EOF)。由于父级仍在 wait() 调用中等待,并且两个管道的两端都打开,因此管道上没有 EOF(管道上的 EOF 在您读取所有写入者写入的所有数据之后发生,并且所有 dup s的写端已经关闭)。所以到达那里的唯一方法是在标准输入上点击 EOF,这样while 循环就不会运行。

    其次,如果您确实有时间再次分叉并执行process_B(),那么该孩子也将永远等待,因为它正在读取的管道的一个写入端仍然是打开的......在父级中!父级不会关闭它,因为父级将永远在wait 中等待。

    一般来说,这里需要做的是:

    • 创建两个管道(就像现在一样)
    • fork 一次,然后在子进程中运行 process_A()
    • 再次分叉(在父级中),并在(新)子级中运行process_B()
    • 关闭两个管道的两端(在父级中)
    • 现在等待两个孩子,两个孩子都开始了

    如果你不能启动第二个孩子,你必须做一些事情(比如kill()第一个孩子),错误处理会有点混乱。所以你需要知道你已经走了多远。你仍然可以循环到 fork 两次,但你不能在循环内 wait ,并且只有两次循环循环,每个循环都执行不同的步骤,你不妨在没有循环的情况下把它全部写出来。

    【讨论】:

    • 它帮助了我 100%。谢谢你。
    猜你喜欢
    • 1970-01-01
    • 2011-01-27
    • 2014-02-06
    • 2017-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多