具有多个进程的管道输出错误

时间:2013-04-04 22:55:59

标签: c pipe

在下面的代码中,我有两个管道,一个,fd []句柄将一个范围变量传递给子进程。另一个管道rw []负责打印方法的结果。 fd工作正常,但是rw打印垃圾。范围和narc_num都很长,我已成功通过rw管道打印了一个字符串和一个字符。有任何想法吗?感谢。

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

/**
 * process propigating version of narcisstic base-10 number generator
**/

/**
 * A Narcissistic number is a number where all of its digits, when raised to the power n where n is the number of digits in its number, equla the number itseld.
 * examples:
 * 2^1 = 2
**/
 void isNarcissisticNumber(int rw[], long min, long max){
//    printf("min %ld max %ld\n", min, max);
    long n;
    for(n = min; n <= max; n++){
    long num = n;
        int digits = floor(log10(num)) + 1;
        int digit_arr[digits];
        long narc_num = 0;
        int index = 0;
        do{
            digit_arr[index++] = num%10;
            num /= 10;
        }while(num > 0);
        index = 0;
        for(index; index < digits; index++){
            narc_num += pow(digit_arr[index], digits);
        }
        if(narc_num == n){
        printf("%ld\n", n);
        // parent: writing only, so close read-descriptor.
        close(rw[0]);
        write(rw[1], &n, sizeof(long));
                // close the write descriptor
                close(rw[1]);
    }
    }
}

int main(int argc,           // Number of strings in array argv
          char *argv[]){      // Array of command-line argument strings)
    //check that there is only one passed in parameter in addition to the program name at argv[0]  
    if(argc != 2){
        printf("Args found: %d. 1 arg required\n", argc);
        return;
    }
    //check that argv passed in is an int
    if(!atoi(argv[1])){
        printf("argument shoud be the # of processes to proc.\n");
        return;
    }
    int num_processes = atoi(argv[1]);
    //counter for narcissistic numbers
    long offset = 10000;
    long range= -offset; 
    //file pipe
    int fd[2];
    //printing pipe
    int rw[2];
    int n = 0;
    long output;
    while(n < num_processes){ // -1 offset to line up array index with num_processes arg   
    pipe(rw);
    pipe(fd);
        pid_t process = fork();
    pid_t child_process;
        int status;
    if(process == 0){ //chid process --> execute program
        child_process = process;
                /* Duplicate the input side of pipe to stdin */
        // chid: reading only, so close the write-descriptor
            close(fd[1]);
        read(fd[0], &range, sizeof(range));
        close(fd[0]);
        isNarcissisticNumber(rw, range, range+offset-1);
    }else if(process != 0){
        // parent: writing only, so close read-descriptor.
            close(fd[0]);
        range += offset;
        write(fd[1], &range, sizeof(range));
        // close the write descriptor
            close(fd[1]);

        // for the current child process to complete its routine befire checking for output
        wait(&child_process);       
        //read from the printing pipe
        close(rw[1]);
        while(read(rw[0], &output, sizeof(long))){
            printf("printer %ld\n", output);
        }
        close(rw[0]);
    }else{ //failed to fork
            printf("process failed to fork!\n");
            return -1;
        }
    n++;
    }
}

编辑#1:虽然这使得父项仅在子项完成后进行检查,但它不会修复管道的输出,即使printf另有说明,它现在只是0。

1 个答案:

答案 0 :(得分:1)

我不确定这会解决所有问题,但你肯定有一个逻辑问题。在计算例程中,您可以向输出写入零个或多个长整数。在您的打印(父)例程中,您只需要一个值。因此,如果没有发送任何内容,您的阅读将失败。如果发送了多个值,则只读取第一个值。第一个修复方法是检查读取的返回值并在其上循环。

另请注意 - 在您的子进程上等待()可能也是一个好主意。