C命名管道(fifo)。父进程陷入困境

时间:2010-05-29 15:07:52

标签: c fork pipe fifo

我想创建一个简单的程序,即fork,并且子进程写入命名管道,父进程从命名管道读取和显示。 问题是它进入了父进程,进行了第一次printf然后它变得奇怪,它没有做任何其他事情,没有进入第二个printf,它只是在控制台中输入的方式。

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
void main()
{
char t[100];
mkfifo("myfifo",777);
pid_t pid;
pid = fork();
if (pid==0)
{
    //execl("fifo2","fifo2",(char*)0);
    char r[100];
    printf("scrie2->");
    scanf("%s",r);

    int fp;
    fp = open("myfifo",O_WRONLY);
    write(fp,r,99);
    close(fp);
    printf("exit kid \n");
    exit(0);
} else
{
    wait(0);
    printf("entered parent \n"); // <- this it prints
    // whats below this line apparently its not being executed
    int fz; printf("1"); 
    fz = open("myfifo",O_RDONLY); printf("2");
    printf("fd: %d",fz);
    char p[100];
    int size;
    printf("------");
    //struct stat *info;
    //stat("myfifo",info); printf("%d",(*info).st_size);
    read(fz,p,99);
    close(fz);
    printf("%s",p);

    printf("exit"); exit(0);
}
}

2 个答案:

答案 0 :(得分:5)

您确实应该检查函数调用的返回值是否有错误,尤其是mkfifo()open()

您对wait()的来电将导致其当前位置出现问题。打开FIFO以便正常读取块,直到某个其他进程打开相同的FIFO进行写入,反之亦然 1 。父母正在等待孩子终止,孩子正在等待读者进程(即父母)连接到FIFO。

1 - 请参阅下面open()的说明,了解O_NONBLOCK使用FIFO

wait()来电转移到父流程退出之前,同时将调用中的模式更改为mkfifo()0666似乎可以解决您的一些直接问题。

完成后删除FIFO也是一种好习惯。

unlink("myfifo");

来自open() function documentation in IEEE Std 1003.1-2004

  

使用O_RDONLY或O_WRONLY设置打开FIFO时:

     
      
  • 如果设置了O_NONBLOCK,则只读的open()应无延迟返回。如果当前没有任何进程打开文件进行读取,则open()仅写入将返回错误。

  •   
  • 如果O_NONBLOCK被清除,则只读的open()将阻塞调用线程,直到线程打开文件进行写入。只写的open()将阻塞调用线程,直到线程打开文件进行读取。

  •   

以下示例是code in your original questionFIFO page of Beej's Guide to Unix IPC

的组合
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>

#define FIFO_NAME "myfifo"

int main(void)
{
    char buf[256];
    int num, fd;
    pid_t pid;

    if (mkfifo(FIFO_NAME, 0666) < 0)
        perror("mkfifo");

    pid = fork();
    if (pid == 0)
    {
        printf("child - waiting for readers...\n");
        if ((fd = open(FIFO_NAME, O_WRONLY)) < 0)
            perror("child - open");

        printf("child - got a reader -- type some stuff\n");
        while (fgets(buf, sizeof(buf), stdin), !feof(stdin))
        {
            if ((num = write(fd, buf, strlen(buf))) < 0)
                perror("child - write");
            else
                printf("child - wrote %d bytes\n", num);
        }

        close(fd);
        exit(0);
    }
    else
    {
        printf("parent - waiting for writers...\n");
        if ((fd = open(FIFO_NAME, O_RDONLY)) < 0)
            perror("parent - open");

        printf("parent - got a writer\n");
        do
        {
            if ((num = read(fd, buf, sizeof(buf))) < 0)
                perror("parent - read");
            else
            {
                buf[num] = '\0';
                printf("parent - read %d bytes: \"%s\"\n", num, buf);
            }
        } while (num > 0);

        close(fd);
        wait(0);
    }

    unlink(FIFO_NAME);
    return 0;
}

此示例已在Linux中测试过。按 Ctrl - D 终止程序。

答案 1 :(得分:3)

首先,尝试fprintf到stderr而不是printf(到stdout)

stderr没有缓冲。

然后你就可以知道实际打印的内容和不打印的内容。

或至少在等待任何事情之前添加fflush