0

我试图使用管道将值从一个程序传递到另一个程序。

第一个程序创建一个管道,然后使用 fork 创建一个子进程,在子进程的一部分中,她使用 execlp 另一个程序执行。

我想在第一个程序与管道一起运行时将字符从第一个程序发送到另一个程序,但我不知道该怎么做,因为 fd[2] 仅在第一个程序中定义。

第一个程序的代码:

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

char getch();

int main()
{
    bool selected;
    int fd[2],pid;
    char choice;
    pipe(fd);
    pid=fork();
    if(pid==0)
    {
        execlp("./draw.out", "draw.out", NULL);
    }
    else
    {
        do
        {
            choice=getch();
            close(fd[0]);
            write(fd[1],&choice,1);
            close(fd[1]);
            kill(pid,SIGUSR2);
        }while(choice!='q');

    }

    return 1;
    //getchar();

}

第二个程序的代码:

#

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


typedef struct
{
    int x;
    int y;
}Point;

typedef struct
{
    Point dots[3];
}Tool;

void drawBoard(int array[][20]);
void initBoard(int array[][20]);
Tool retrieveTool();
bool changeLocation(int array[][20],Tool* tool);
void my_handler(int signum);

int main()
{
    bool nextTool=true;
    Tool temp=retrieveTool();
    int gameBoard[20][20];
    signal(SIGUSR2, my_handler);
    initBoard(gameBoard);
    changeLocation(gameBoard,&temp);
    drawBoard(gameBoard);
    while(true)
    {
        sleep(1);
        system("clear");
        if(!changeLocation(gameBoard,&temp))
            temp=retrieveTool();
        drawBoard(gameBoard);
    }
    return 1;
    //getchar();

}

void my_handler(int signum)
{
    char geth='a';
    if (signum == SIGUSR2)
    {


    close(fd[1]);
    read(fd[0],&geth,1);
    close(fd[0]);

    printf("Received SIGUSR2!%c\n",geth);
    }
}

正如您在第一个程序中看到的那样,我为管道定义了 fd[2] 变量,然后我将一个字符从用户发送到管道。我希望另一个程序上的信号处理程序“my_handler”将从同一个管道中读取,但这里没有定义 fd(在第二个程序中)。

我该怎么做?

4

1 回答 1

1

虽然管道变量 fd 仅在父级中,但实际的文件描述符是共享的。只要您的程序知道它们是什么(作为整数),就可以使用它们。所以有几个选择

  1. 在 exec 调用中将描述符编号传递给子程序(类似于

    sprintf(buf1,"%d", fd[0]);

    execlp("./draw.out", "draw.out", "-in", buf1, NULL);

    然后在draw中从argv读取描述符。

  2. 第二个相当常见的选项是使用 fd 0 输入和 fd 1 输出的约定。这仅在您的子程序不使用 stdin(或 std::cin)时才有效。否则,您可以选择另一个您确定可用的描述符(这比听起来更难)。为此,您需要在 fork 之后但在 exec 之前复制描述符。就像是

    dup2(fd[0],0);

    关闭(fd[0]);

    关闭(fd[1]);// 孩子不需要 fd[1]

    执行 (....)

在所有情况下,您都需要确保关闭所有未使用的描述符,包括旧副本。我建议尽快进行近距离通话(在分叉后每个块的开头)。否则,您的程序将不会在描述符上遇到 EOF。顺便说一句,您的程序都在循环或可以多次调用的处理程序中关闭描述符 - 两者都不太可能是正确的。您应该检查读取、写入和关闭的返回值以帮助调试。

于 2013-05-04T23:35:49.577 回答