分叉进程不是在C中调用函数

时间:2016-02-10 05:04:33

标签: c unix fork

C初学者。函数send_chars_to_reducers似乎没有在fork_mappers函数中创建的分叉进程内调用。

C代码

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

#define BUFFER_SIZE 1024
#define ALPHA_OFFSET 97
#define LETTERS 26

const int NUM_OF_MAPPERS = 4;
const int NUM_OF_REDUCERS = 26;

const int PIPE_READ_END = 0;
const int PIPE_WRITE_END = 1;
const int PIPE_BUFFER_SIZE = 1000;

int mapper_pipes[4][2];
int reducer_pipes[26][2];

void pipe_wrapper(int pipefd[]) {
    int ret = pipe(pipefd);
    if (ret == -1) {
        perror("Error. Failed when trying to create pipes.");
        exit(EXIT_FAILURE);
    }
}

void create_mapper_pipes(void) {
    int i;
    for (i = 0; i < NUM_OF_MAPPERS; i++) {
        pipe_wrapper(mapper_pipes[i]);
    }
}

void create_reducer_pipes(void) {
    int i; 
    for (i=0; i < NUM_OF_REDUCERS; i++) {
        pipe_wrapper(reducer_pipes[i]);
    }
}

// Prints an error msg and exits if one occurs. Else, returns the system call value.
int print_if_err(int syscall_val, const char* syscall_name) {
    if (syscall_val < 0) {
        perror(syscall_name);
        exit(errno);
    } else {
        //No syscall error we can return
        return syscall_val;
    }
}

void send_chars_to_reducers(void) {
    printf("hello from send_chars_to_reducers\n");
}

void fork_mappers(void) {


    /* Constants useful to all children */
    char ibuf[PIPE_BUFFER_SIZE]; // input pipe buffer
    int rlen = 0;

    int i;
    for (i=0; i<NUM_OF_MAPPERS; i++) {
        pid_t mapper_pid = print_if_err(fork(), "fork");
        close(mapper_pipes[i][PIPE_WRITE_END]);
        if (mapper_pid == 0) {
            rlen = print_if_err(read(mapper_pipes[i][PIPE_READ_END], ibuf, 1000), "read");
            while(rlen > 0) {    
                send_chars_to_reducers();
                printf("read line from forked_mappers, p%d: %s\n", i, ibuf);
                rlen = print_if_err(read(mapper_pipes[i][PIPE_READ_END], ibuf, 1000), "read");
            }
            _exit(0);
        }
    }
}

void fork_reducers(void) {
    printf("hello from fork_reducers\n"); 
    int i;
    for (i = 0; i < NUM_OF_REDUCERS; i++) {
        pid_t reducer_pid = print_if_err(fork(), "fork");
        if (reducer_pid == 0) {
            while (1 == 1) {

            }       
        }
    }
}

void send_lines_to_mappers(void) {
    int wlen = 0;
    char obuf[PIPE_BUFFER_SIZE];
    int ob_size;
    int count = 0;

    char buff[BUFFER_SIZE]; // a buffer for each line of the file
    FILE *input_file = fopen("input.txt", "r");
    // read the input file line by line
    while(fgets(buff, BUFFER_SIZE, input_file) > 0) {
        printf("read line from send_lin_to_mappers: %s\n", buff);
        ob_size = sizeof buff;
        switch(count) {
            case 0 :
                write(mapper_pipes[0][PIPE_WRITE_END], buff, ob_size);
                close(mapper_pipes[0][PIPE_WRITE_END]);
                break;
            case 1 : 
                write(mapper_pipes[1][PIPE_WRITE_END], buff, ob_size);
                close(mapper_pipes[1][PIPE_WRITE_END]);
                break;
            case 2 :
                write(mapper_pipes[2][PIPE_WRITE_END], buff, ob_size);
                close(mapper_pipes[2][PIPE_WRITE_END]);
                break;
            case 3 : 
                write(mapper_pipes[3][PIPE_WRITE_END], buff, ob_size);
                close(mapper_pipes[3][PIPE_WRITE_END]);
                break;
            default :
                printf("you did something wrong in send_lines_to_mappers loop");
        }
        count++;
    }
    fclose(input_file);
}

int main(void) {
    // Setup the mapper pipes
    create_mapper_pipes();
    create_reducer_pipes();
    fork_reducers();
    fork_mappers();
    send_lines_to_mappers();

    return 0;
}

输出

hello from fork_reducers
read line from send_lin_to_mappers: I like coding in C.

read line from send_lin_to_mappers: I like manually allocating memory, and opening the registers window in Visual Studio to see the values of the eax register and blitting graphics to the screen and all the stuff that Dr. Dobbs wrote about in the 90s.

read line from send_lin_to_mappers: My programming friends seem to believe that understanding this level of programming is good in a hand-wavy, theoretical sense, but when you consider all the web development, Java frameworks, and existing libraries most programmers today rely on, it's hard to really pin down a solid answer to the question "Why learn C?"

read line from send_lin_to_mappers: This is my attempt to answer that question, and I believe it comes down to the basic programming concept of abstraction.

1 个答案:

答案 0 :(得分:0)

问题是共享句柄的进程数。 每个减速器都打开管道 每个映射器都打开了管道,因此管道从未正确关闭(减速器处于繁忙的循环中。

    if (mapper_pid == 0) {
      int j;
      for( j = 0; j < NUM_OF_MAPPERS; j++ ){
        close( mapper_pipes[j][PIPE_WRITE_END]);
        if( j != i ){
           close(mapper_pipes[j][PIPE_READ_END]);
        }
    }

我注释掉了reducer fork,然后修复了mapper forks以关闭了孩子们除了我们想要读取的那个之外的所有管道句柄。

这开始使程序工作。 从pipe documentation开始,您应该关闭管道的未使用位。但是你已经预先打开了所有管道(可能更好地本地化它们),因此必须关闭子流程中所有未使用的句柄,以使操作系统正确整理资源