简体   繁体   中英

Define same pipe to 2 different programs

im trying to pass values from one program to another using pipe.

The first program create a pipe and then a son process with fork and in the part of the son process she execute with execlp another program.

I want to send chars from the first program to the other while they are running with the pipe, but i don't know how to do that because the fd[2] is defined only in the first program.

The code of the first program:

#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();

}

The code of the second program:

#

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);
    }
}

As you can see in the first program i define fd[2] variable to the pipe, and i send a char from the user to the pipe. I want that the signal handler "my_handler" on the other program will read from the same pipe, but fd is not defined here(in the second program).

How should i do that?

While the pipe variable fd is only in the parent, the actual file descriptors are shared. They can be used provided your program knows what they are (as integers). So there are a couple of options

  1. Pass the descriptor number in to the child program in the exec call (so something like

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

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

    And then read the descriptor from argv in draw.

  2. A second, fairly common, option is to use the convention that fd 0 is input and fd 1 is output. This only works if your child program does not otherwise use stdin (or std::cin). Otherwise you can just choose another descriptor that you are sure will be available (this is harder than it sounds). For this to work, you need to copy the descriptor after the fork but before the exec. Something like

    dup2(fd[0],0);

    close(fd[0]);

    close(fd[1]); // The child doesn't need fd[1]

    execlp(....)

In all cases you need to make sure that any unused descriptors, including old copies, get closed. I'd advise doing the close calls as soon as possible (at the start of each block after the fork). Otherwise you programs will not encounter EOF on the descriptor. BTW, your programs are both closing the descriptors either in a loop or in a handler that could be called multiple times - neither is likely to be correct. You should check return values from read, write and close to help debug things.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM