本文介绍了C命名管道(fifo).父进程卡住的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想编写一个简单的程序,即fork,然后孩子将其写入命名管道,而父级将从命名管道中读取和显示.问题是它进入父级,执行第一个printf,然后变得很奇怪,它没有做其他任何事情,没有到达第二个printf,这只是在控制台中进行输入的方式.

I want to make a simple program, that fork, and the child writes into the named pipe and the parent reads and displays from the named pipe.The problem is that it enters the parent, does the first printf and then it gets weird, it doesn't do anything else, does not get to the second printf, it just ways for input in the console.

#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);
}
}

推荐答案

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

You really should be checking the return value on function calls for errors, especially mkfifo() and open().

您对wait()的调用将在其当前位置引起问题.打开FIFO以正常读取块,直到其他进程打开相同的FIFO进行写入为止,反之亦然.父级正在等待子级终止,而子级正在等待读取器进程(即父级)连接到FIFO.

Your call to wait() is going to cause problems in its current location. Opening a FIFO for reading normally blocks until some other process opens the same FIFO for writing, and vice versa. The parent is waiting for the child to terminate and the child is waiting for a reader process, i.e., the parent, to connect to the FIFO.

wait()调用移至父进程退出之前,并将调用方式从mkfifo()更改为0666似乎可以解决您的一些直接问题.

Moving the wait() call to just before the parent process exits along with changing the mode in the call to mkfifo() to 0666 seems to resolve some of your immediate problems.

优良的做法是在完成FIFO后将其删除.

It is also good practice to remove the FIFO when you are finished with it.

unlink("myfifo");


摘自IEEE Std 1003.1-2004中 open()函数文档:


From the open() function documentation in IEEE Std 1003.1-2004:

  • 如果设置了O_NONBLOCK,则只读的open()将立即返回.如果当前没有进程打开要读取的文件,则仅用于写入的open()将返回错误.

  • If O_NONBLOCK is set, an open() for reading-only shall return without delay. An open() for writing-only shall return an error if no process currently has the file open for reading.

如果清除了O_NONBLOCK,则只读的open()将阻塞调用线程,直到线程打开要写入的文件为止.仅写操作的open()将阻塞调用线程,直到线程打开文件进行读取为止.

If O_NONBLOCK is clear, an open() for reading-only shall block the calling thread until a thread opens the file for writing. An open() for writing-only shall block the calling thread until a thread opens the file for reading.


以下示例是原始问题中代码的组合《 Beij Unix IPC指南》的FIFO页:

#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上进行了测试.按-终止程序.

This example was tested in Linux. Press - to terminate the program.

这篇关于C命名管道(fifo).父进程卡住的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-23 07:26