关闭管道末端错误

时间:2016-11-13 16:37:39

标签: c linux pipe fork system-calls

我有一个程序,它会分叉一个孩子,并希望它与其父母沟通。但是,在关闭孩子的写端时,我似乎遇到了错误。

程序在孩子内部和if (close(pfd1[1]) == -1)

中停止

当孩子想要关闭写结束时,显然会失败。为什么呢?

/* Note: working under the assumption that the messages are of equal length */

int main(int argc, char * argv[])
{
    int pfd1[2];          
    char buf[BUF_SIZE];

    //checks pipefd1
    if (pipe(pfd1) == -1)
    {
        printf("Error opening pipe 1!\n");
        exit(1);
    }

    printf("Pipe opened with success. Forking ...\n");

    // child 1
    switch (fork())
    {
        case -1:
            printf("Error forking child 1!\n");
            exit(1);

        case 0:
            printf("\nChild 1 executing...\n");
            /* close writing end of first pipe */
            if (close(pfd1[1]) == -1)
            {
                printf("Error closing writing end of pipe 1.\n");
                _exit(1);
            }

            /* read from pipe 1 */
            if (read(pfd1[0], buf,  2000))
            {
                printf("Error reading to pipe 1.\n");
                _exit(1);
            }
            /* close reading end of first pipe */
            if (close(pfd1[1]) == -1)
            {
                printf("Error closing writing end of pipe 1.\n");
                _exit(1);
            }

            printf("Message received child ONE: %s", buf);
            printf("Exiting child 1...\n");
            _exit(0);

        default: //parent breaks just out
            break;
    }

    printf("inside parent\n");

    int child = 1;
    char *message = "Hey child1, this is your parent speaking";

    if(child == 1)
    {
        //close read end of pipe
        if(close(pfd1[0]) == -1)
        {
            printf("Error closing reading end of the pipe.\n");
            exit(EXIT_FAILURE);
        }

        printf("Parent closed read end of pipe1\n");

        //read end is closed, now write to child
        if(write(pfd1[1], message, strlen(message)))
        {
            printf("Error writing to the pipe.");
            _exit(EXIT_FAILURE);
        }

        printf("Writing to child1 succeeded\n");
    }

    if (wait(NULL) == -1)
    {
        printf("Error waiting.\n");
        exit(EXIT_FAILURE);
    }

    if (wait(NULL) == -1)
    {
        printf("Error waiting.\n");
        exit(EXIT_FAILURE);
    }

    printf("Parent finishing.\n");
    exit(EXIT_SUCCESS);
}

2 个答案:

答案 0 :(得分:3)

首先,在孩子的情况下,你试图两次关闭管道的书写端。我想第二次调用close(2)意味着关闭阅读结束,如上面的评论所述:

/* close reading end of first pipe */
if (close(pfd1[0]) == -1)
{
    printf("Error closing writing end of pipe 1.\n");
    _exit(1);
}

除此之外,请注意read(2)write(2)都返回实际读取或写入的字节数;在出现错误的情况下,返回值为-1,因此您的错误检查条件也应该修复,例如:

/* read from pipe 1 */
if (read(pfd1[0], buf,  2000) < 0) {
    printf("Error reading to pipe 1.\n");
    _exit(1);
}

//read end is closed, now write to child
if(write(pfd1[1], message, strlen(message)) < 0) {
    printf("Error writing to the pipe.");
    _exit(EXIT_FAILURE);
}

答案 1 :(得分:1)

根据钓鱼教学原则,诊断此类问题的一种好方法是检查错误是什么,并打印更多信息。这是我经常放入头文件并使用的技术:

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

/* This declaration and macro would really go into a header file: */
void fatal_error_helper( const char* msg, const char* sourcefile, int lineno, const char* syserr );

#define fatal_system_error(m) \
  fatal_error_helper( (m), __FILE__, __LINE__, strerror(errno) )

/* This function definition would really go into a .c file: */
void fatal_error_helper( const char* const msg,
                         const char* const sourcefile,
                         const int lineno,
                         const char * const syserr )
{
  fflush(stdout); /* Don't cross the streams! */
  fprintf( stderr,
           "%s at %s:%d: %s.  Program terminated.\n",
           msg, sourcefile, lineno, syserr
         );
  exit(EXIT_FAILURE);
}

/* Test driver: */
FILE* fails_to_open_file( const char* filename )
/* Returns a FILE* to an open file.  If the operation fails, prints an
 * error message and terminates the program.
 */
{
    /* Do this in general before calling the function whose error value
     * you check.  Otherwise, you might report the wrong error message 
     * from an earlier call and really confuse someone.
     */
    errno = 0;
    FILE* result = NULL;

    result = fopen(filename, ""); /* Fails. */
    if (!result)
       fatal_system_error("Failed to open file");
    return result;
}

int main(void)
{
  fails_to_open_file("nonexistent.file");
  return EXIT_SUCCESS;
}

这会显示错误消息,例如:Failed to open file at prog.c:26: Invalid argument. Program terminated.