1

我需要编写具有这样结构的程序:

父母制作先进先出,然后fork()

  • 孩子 1 从标准输入读取消息并将其写入命名管道 (FIFO)
  • 然后在父进程中我需要创建管道(未命名)和另一个fork()
  • 子编号 2 从 FIFO 中读取,计算消息长度并通过管道(未命名)将编号发送给父级。

我用一个叉子创建了一个简单的程序,孩子可以与父母交流:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

#define FIFO "/tmp/my_fifo"

int main()
{
pid_t fork_result;
int pipe_fd;
int res;
char writer[3];
char reader[3];

res = mkfifo(FIFO,0777);
if (res == 0)
{
    printf("FIFO created!\n");

    fork_result = fork();
    if (fork_result == -1)
    {
        fprintf(stderr, "fork error");
        exit(EXIT_FAILURE);
    }       
    if (fork_result == 0)
    {
        printf("CHILD 1\n");
        pipe_fd = open(FIFO, O_WRONLY | O_NONBLOCK);
        scanf("%s", writer);
        res = write(pipe_fd,writer,3);
        if (res == -1)
        {
            fprintf(stderr,"error writing fifo\n");
            exit(EXIT_FAILURE);
        } 
        (void)close(pipe_fd);
        exit(EXIT_SUCCESS);
    }
    else
    {
        printf("PARENT\n");
        pipe_fd = open(FIFO, O_RDONLY);
        res = read(pipe_fd, reader, 3);
        printf("reader: 0: %c\n",reader[0]);
        printf("reader: 1: %c\n",reader[1]);
        printf("reader: 2: %c\n",reader[2]);
        (void)close(res);
    }         
}
else
{
    printf("deleting fifo... run program again!\n");
    unlink(FIFO);
}
exit(EXIT_SUCCESS);
}

它运行良好。所以我创建了具有上述架构的代码:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

#define FIFO "/tmp/my_fifo"

int main()
{
pid_t fork_result;
pid_t fork_result2;
int pipe_fd;
int res;
char writer[3];
char reader[3];

res = mkfifo(FIFO,0777);
if (res == 0)
{
    printf("FIFO created!\n");
    fork_result = fork();

    if (fork_result == -1)
    {
        fprintf(stderr, "fork error");
        exit(EXIT_FAILURE);
    }     

    if (fork_result == 0)
    {
        printf("CHILD 1\n");
        pipe_fd = open(FIFO, O_WRONLY | O_NONBLOCK);
        scanf("%s", writer);
        res = write(pipe_fd,writer,3);
        if (res == -1)
        {
            fprintf(stderr,"error writing to fifo\n");
            exit(EXIT_FAILURE);
        } 
        (void)close(pipe_fd);
    exit(EXIT_SUCCESS);
    }
    else
    {
        printf("PARENt 1\n");
        //don't forget pipe!

        fork_result = fork();
        pipe_fd = open(FIFO, O_RDONLY);
        if (fork_result == 0)
        {
           printf("CHILD 2\n");
           res = read(pipe_fd, reader, 3);
           printf("Odczytano: 0: %c\n",reader[0]);
           printf("Odczytano: 1: %c\n",reader[1]);
           printf("Odczytano: 2: %c\n",reader[2]);
           (void)close(res);
        } 
    }         
}
else
{
    printf("deleting fifo\n");
    unlink(FIFO);
}
exit(EXIT_SUCCESS);
} 

运行顺序是这样的:

PARENT 1
CHILD 1
CHILD 2

因此,在父 1 中,我打开 FIFO 进行读取,在子 1 中,我正在写入 FIFO,而子 2 应该读取它。我的意思是在代码中,因为当我运行它时,我什至无法向 FIFO 写入任何内容。scanf("%s", writer);在第一个程序中工作的块中。

我使用open()正确吗?我需要在getpid()某个地方使用吗?为什么当我尝试写入 fifo 时它会阻塞。

4

2 回答 2

1

The problem is that CHILD1 is opening the fifo with O_NONBLOCK, which will fail (with EWOULDBLOCK or EAGAIN) if no other process has the fifo open for reading. Now in the first program, the parent continues running after the fork and opens the fifo for reading before the child gets going and opens the write end, so it works. But in the second case, the parent does an extra fork first, which slows it down just enough that CHILD1 gets to its open command before PARENT or CHILD2 has opened the fifo for reading, so the CHILD1 open fails.

Get rid of the O_NONBLOCK and it works just fine (though you do open the fifo for reading in both PARENT and CHILD2, which is probably not what you want).

如果你想从键盘上阅读,你还有另一个问题。如果您从 shell 运行此命令,PARENT 将立即退出(或多或少),因此 shell 将返回从键盘读取命令,这意味着 CHILD1 和 shell 将争夺输入。另一方面,如果你做你最初描述的事情并让 PARENT 等待从 CHILD2 的管道读取,它应该做你想做的事情。

于 2013-02-01T18:03:27.197 回答
0

Isn't it because you use twice the same variable fork_result? As you created another variable fork_result2, which you don't use, it is probably unintended.

I don't know if this will solve your problem, but at least using fork_result2 at the second fork would make it easier to understand...

于 2013-02-01T18:03:07.730 回答