叉与管之间的双向通信

时间:2013-09-26 07:14:21

标签: c exec fork pipe

我正在尝试在主文件和帮助文件之间进行双向通信。 主文件分叉,子进行一些管道工作,然后运行一个exec。 我的问题是我可以从子exec向父exec发送信息,但不是相反。 下面是我的两个文件中的完整代码,因此您应该能够运行它。 任何帮助实现2路通信的工作都会非常有帮助。我现在已经连续工作了近8个小时。

当你运行它时,你会看到它打印出“哟0”。这是我测试它从主文件中获取一个整数,将它发送给帮助器,在它前面添加yo并将其发回。第一块代码是主文件,第二块是帮助器,第三块是运行它所需的映射文件。确保最后一行下面没有空行,第四行是运行它所需的代理文件。

运行是[./handler mapfile 20 agentfile。] int 20还没有做任何事情,但你需要在那里运行文件。 如果有人真正努力做到这一切并帮助我,我永远感激

主文件(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;

}

帮助文件(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);


}

地图文件

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

代理商档案

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

1 个答案:

答案 0 :(得分:1)

管道是跨进程的单一连接。在fork之前,打开管道并保留两个文件描述符,其中fd [0]可以读取,fd [1]可以写入。

因此,当您想要进行双向通信时,您需要创建两个管道,然后使用一个管道来读取子管理中的父管道,而使用另一个管道则相反。

更详细的解释以及一些示例代码可以是最基本的:http://linux.die.net/man/2/pipe