【问题标题】:bad output from pipe with multiple processes具有多个进程的管道输出错误
【发布时间】:2013-04-04 22:55:58
【问题描述】:

在下面的代码中,我有两个管道,一个是 fd[] 处理将范围变量传送到子进程的句柄。另一个管道 rw[] 负责打印方法的结果。 fd 工作正常,但 rw 打印垃圾。 range 和 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。

【问题讨论】:

    标签: c pipe


    【解决方案1】:

    我不确定这是否能解决所有问题,但您肯定有逻辑问题。在您的计算例程中,您可以将零个或多个 long 写入输出。在您的打印(父)例程中,您期望只有一个值通过。因此,如果没有发送任何内容,您的读取将失败。如果发送了多个值,则只读取第一个值。第一个解决方法是检查您的读取返回值并对其进行循环。

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

    【讨论】:

    • 感谢您的提示,但还没有,但我将一个 char * 传递到管道中并将其从 rw 中取出。我在 isNarccissistic() 方法中处理 narc_num 或 n 的方式有问题吗?
    • 您希望在完成读取后等待调用(不确定这会产生多大的不同)
    • 另一项 - 在第一次写入后立即关闭 rw[1]。因此,您剩余的写入失败。此外,您将在同一个地方多次关闭 rw[0]。
    • 非常感谢,是多次关闭把一切搞砸了。我需要加强对管道的理解。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多