简体   繁体   中英

2 way communication between with fork and pipe

I'm trying to get 2 way communication between a main file and a helper file. The main file forks, and the child does some pipe work and then runs an exec. My problem is that I can send information from the child exec to the parent exec, but not the other way around. Below Is my entire code from the two files, so you should be able to run it. Any help in getting the 2 way communication working will be extremely helpful. i'm been at this for almost 8 hours straight now.

When you run it, you'll see it print out "yo 0". This was me testing that it takes an integer from the main file, sends it to the helper, adds yo in front of it and sends it back. The first slab of code is the main file, second is the helper, third is the map file needed to run it. make sure there isn't a blank line underneath the last line, and the fourth is the agent file needed to run it.

the running is [./handler mapfile 20 agentfile.] the int 20 doesn't do anything yet, but you need it in there to run the file. If anyone actually goes to the effort to do all this and help me, i am eternally grateful

main file (handler.c)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/wait.h>


enum ErrorCode {
        SHOW_USAGE = 1, BAD_STEPS, OPEN_MAP_ERROR, CORRUPT_MAP,
        OPEN_AGENT_ERROR, CORRUPT_AGENTS, AGENT_ERROR,
        AGENT_WALLED, AGENT_COLLIDED, TOO_MANY_STEPS, INVALID_AGENT_RESPONSE,
        AGENT_CLOSED, AGENT_DIED, SIGINT_REC
};

typedef struct {
        int valid;
        int row, col;
} Point;

typedef struct {
        Point point;
        int number;
        char name;
        char param[20];
        char type[20];
} Agent;

typedef struct {
        int rows, cols;
        char **grid;
} Map;

Map map;
Map agentMap;
int listSize = 0;

void error(enum ErrorCode e) {
        switch(e) {
        case SHOW_USAGE:
                fprintf(stderr, "Usage: handler mapfile maxsteps agentfile\n");
                break;
        case BAD_STEPS:
                fprintf(stderr, "Invalid maxsteps.\n");
                break;
        case OPEN_MAP_ERROR:
                fprintf(stderr, "Unable to open map file.\n");
                break;
        case CORRUPT_MAP:
                fprintf(stderr, "Corrupt map.\n");
                break;
        case OPEN_AGENT_ERROR:
                fprintf(stderr, "Unable to open agent file.\n");
                break;
        case CORRUPT_AGENTS:
                fprintf(stderr, "Corrupt agents.\n");
                break;
        case AGENT_ERROR:
                fprintf(stderr, "Error running agent.\n");
                break;
        case AGENT_WALLED:
                fprintf(stderr, "Agent walled.\n"); // needs fixing, check spec sheet
                break;
        case AGENT_COLLIDED:
                fprintf(stderr, "Agent collided.\n"); // same as AGENT_WALLED
                break;
        case TOO_MANY_STEPS:
                fprintf(stderr, "Too many steps.\n");
                break;
        case INVALID_AGENT_RESPONSE:
                fprintf(stderr, "Agent sent invalid response.\n"); // fixiing
                break;
        case AGENT_CLOSED:
                fprintf(stderr, "Agent exited with status.\n"); // fixiing
                break;
        case AGENT_DIED:
                fprintf(stderr, "Agent exited due to signal.\n"); // fixing
                break;
        case SIGINT_REC:
                fprintf(stderr, "Exiting due to INT signal.\n");
                break;
        }
        exit(e);
}


void print_map(Map map)
{
        int r;
        for (r = 0; r < map.rows; ++r) {
                printf("%s", map.grid[r]);
        }
        puts("");
}

void print_agents(Agent *agents, int size)
{
        int i;
        for (i = 0; i < size; i++) {
                Agent temp = agents[i];
                printf("%d %d %c %d %s %s %i\n", temp.point.row, temp.point.col, temp.name, temp.number, temp.type, temp.param, i);
        }
        puts("");
}


void readMap(char *file)
{
        int r;
        FILE *fd = fopen(file, "r");
        char buffer[20];
        char d;

        if (!fd) {
                error(OPEN_MAP_ERROR);
        }

        if (fgets(buffer, 20, fd) == NULL) {
                error(CORRUPT_MAP);
        }

        if (sscanf(buffer, "%d %d%1[^\n]\n", &map.rows, &map.cols, &d) != 2 ||
            map.rows < 1 || map.rows > 999 || map.cols < 1 || map.cols > 999) {
                error(CORRUPT_MAP);
        }

        map.grid = malloc(map.rows * sizeof(char *));
        for (r = 0; r < map.rows; ++r) {
                map.grid[r] = calloc(map.cols + 2, sizeof(char));
                if (fgets(map.grid[r], map.cols + 2, fd) == NULL ||
                                        map.grid[r][map.cols] != '\n') {
                        error(CORRUPT_MAP);
                }
        }

        fclose(fd);

}

void checkAgent(char *file)
{
        FILE *fd = fopen(file, "r");
        if (!fd) {
                error(AGENT_ERROR);
        }
        fclose(fd);
}

int growList (Agent **agentList, int curSize, int increaseNum)
{
        const int newSize = curSize + increaseNum;
        Agent *temp = (Agent*) realloc(*agentList, (newSize * sizeof(Agent)));

        if (temp == NULL) {
                exit(20);
        }
        else {
                *agentList = temp;
                return newSize;
        }
}


Agent* readAgentFile(char *file, Agent *agentList)
{
        int readCount = 0;
        FILE *fp = fopen(file, "r");
        char buffer[80];

        listSize = 0;
        if (!fp) {
                error(OPEN_AGENT_ERROR);
        }

        if (fgets(buffer, 80, fp) == NULL) {
                error(CORRUPT_AGENTS);
        }

        rewind(fp);
        while (fgets(buffer, 80, fp) != NULL) {
                if (buffer[0] != '#') {
                        Agent agent;
                        sscanf( buffer, "%d %d %c %s %s" ,&agent.point.row, &agent.point.col, &agent.name, agent.type, agent.param);
                        checkAgent(agent.type);
                        agent.number = readCount+1;
                        listSize = growList(&agentList, listSize, 1);
                        agentList[readCount] = agent;
                        readCount++;
                }
        }
        if (readCount == 0) {
                error(CORRUPT_AGENTS);
        }

        fclose(fp);
        return agentList;
}

void createAgentMap()
{
        int i,j;
        agentMap = map;
        for (i=0; i < map.rows; i++) {
                for (j=0; j < map.cols; j++) {
                        char c = map.grid[i][j];
                        if (c == '.') {
                                agentMap.grid[i][j] = ' ';
                        }
                }
        }
}

int main(int argc, char **argv)
{
        int steps;
        int pid;
        int returnStatus;
        int i;
        int out_pipe[2];
        int in_pipe[2];
        char ch[20];

        Agent firstAgent;
        Agent *agentList =(Agent *) calloc(1, sizeof(Agent));

        if (argc != 4) {
                error(SHOW_USAGE);
        }

        sscanf(argv[2], "%d", &steps);
        if ((steps < 1)) {
                error(BAD_STEPS);
        }

        readMap(argv[1]);
        agentList = readAgentFile(argv[3], agentList);
        firstAgent = agentList[0];
        createAgentMap();

        for (i=0; i < listSize; i++) {

                if (pipe(out_pipe) < 0) {
                        perror("Pipe Error");
                }
                if (pipe(in_pipe) < 0) {
                        perror("Child pipe error");
                }

                Agent temp;
                temp = agentList[i];

                switch ( pid = fork() )
                {
                        case -1:
                                perror("Can't fork.\n");
                                exit(20);
                        case 0:
                                /* Child */
                                /*close(1);
                                dup(in_pipe[1]);
                                close(0);
                                dup(out_pipe[0]);
                                close(in_pipe[0]);
                                close(out_pipe[1]);*/

                                dup2(out_pipe[0], 0);
                                dup2(in_pipe[1], 1);

                                execlp(temp.type, temp.type, temp.param, (char *)0);
                                perror("No exec");
                        default:
                                //close(1);
                                //dup(handlerChild[1]);
                                //fprintf(stdout, "%d", listSize);

                                write(out_pipe[1], "%d", listSize);

                                close(in_pipe[1]);
                                close(0);
                                dup(in_pipe[0]);

                                if (fgets(ch, 20, stdin) == NULL) {
                                        break;
                                }
                                printf("%s\n", ch);
                }

        }

        while (steps > 0) {


                steps -= 1;

        }

        return 0;

}

helper file (simple.c)

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

typedef struct {
        int valid;
        int row, col;
} Point;

typedef struct {
        int numAgents;
        char agentNames[80];
        int agentNumber;
} Info;

typedef struct {
        int rows, cols;
        char **grid;
} Map;

Map agent_map;

int main(int argc, char **argv)
{
        int steps = 10;
        int simple_pipe[2];
        int dir;
        char inputDir;
        char input_stream[20];
        int in = dup(0);
        Info info;

        if (argc == 2) {
                sscanf(argv[1], "%c1", &inputDir);
                switch (inputDir) {
                        case 'N': dir = 0; break;
                        case 'E': dir = 1; break;
                        case 'S': dir = 2; break;
                        case 'W': dir = 3; break;
                        default : fprintf(stdout, "Invalid params.\n"); exit(2);
                }

        }
        else {
                fprintf(stdout, "Incorrect number of params.\n");
                exit(1);
        }

        close(0);
        dup(simple_pipe[0]);
        fgets(input_stream, 20, stdin);

        sscanf(input_stream, "%d", &info.numAgents);
        //printf("%d", info.numAgents);
        //printf("this is the input: %s\n", input_stream);      // This is successfully printing to stdout in the pipe
        fprintf(stderr, "yo %d \n", info.numAgents);
        while (steps > 0) {


        steps -= 1;
        }
        exit(0);


}

map file

6 6
##..##
#....#
#.##.#
#....#
##....
######

agent file

1 1 A ./simple E
2 2 B ./simple N
5 2 C ./simple S

A pipe is a unidrectional connection across processes. Before you fork, you open the pipe and it will reserve two file descriptors, where fd[0] can be read from and fd[1] can be written to.

So when you want to have a two way commumincation you need to create two pipes, and then use one for reading in the parent writing in the child and the second pipe the other way around.

A more detailed explanation along with some sample code can be foun dhere: http://linux.die.net/man/2/pipe

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