2

我有一个任务,我需要在头文件中声明一个管道。我真的不知道该怎么做。这可能是一个非常愚蠢的问题,我可能会遗漏一些明显的东西。如果你能指出我正确的方向,我将不胜感激。

谢谢你的时间。

编辑:

抱歉这个问题太含糊了。也许我需要加强我对管道的理解。

我正在尝试在两个子进程之间创建一个管道。一个孩子将随机字符写入管道,而另一个孩子将从管道中读取字符。

我想我真的不明白当我写这样的东西时会发生什么:

int fd[2];
pipe = pipe(fd);

我是否正确地说管道的写入和读取文件描述符分别放入fd[0]fd[1]?如果在我关闭的一个子进程中fd[1],那个孩子可以被认为是我的作家,对吗?

编辑2:

好的,看起来我几乎已经弄清楚并完成了所有事情,除了我收到与文件描述符有关的错误。

我的代码如下所示:(这只是与管道相关的代码)

项目2.h

extern int fd[2];

项目2.c

int fd[2];
pipe(fd);

作家.c

close(fd[0]);
result = write(fd[1], &writeBuffer, sizeof(writeBuffer));
if(result < 0){
    perror("Write");
}

读者.c

close(fd[1]);
result = read(fd[0], &readBuffer, sizeof(readBuffer))
if(result < 0){
    perror("Read");
}

执行代码后,每次 read() 和 write() 迭代都会出现错误,并显示错误“错误的文件描述符”。我已经尝试在网上搜索自己来解决这个问题,但我认为我对这个材料了解得不够多,无法做到这一点。任何方向将再次不胜感激。到目前为止,所有做出贡献的人都做得很好,非常感谢。另外,如果看起来我只是让你为我做作业,我正在付出诚实的努力,这不是任务的全部。

编辑 3:

write() 系统调用是否写入标准输出?如果我只想在阅读器从管道中读取内容后打印内容怎么办?如何将它们写入管道而不将它们写入标准输出?

编辑4: 我现在已经弄清楚了一切。感谢大家的帮助。我唯一仍然好奇的是我是否能以某种方式获得父进程的状态。我已经使用 wait() 系统调用从子进程中收集了状态,并且想知道如何检索父进程的状态。

4

4 回答 4

3

下面是一个程序示例,它创建一个管道,然后分叉该进程并在父进程中调用发送方函数,在子进程中调用接收方函数。管道创建和文件描述符与发送方和接收方一样,位于一个带有相关头文件的源代码文件中。该main文件请求创建管道,然后执行fork()并调用senderreceiver函数。

pipe.h - 这包含extern管道文件描述符的声明以及创建管道的函数的声明:-

#ifndef PIPE_H
#define PIPE_H

extern int pipe_fd[2];

void create_pipe(void);

#endif

pipe.c - 包含pipe_fd数组的实际定义:-

#include "pipe.h"
#include <unistd.c>

int pipe_fd[2];

void create_pipe(void)
   {
   pipe(pipe_fd);
   }

sender.h - 声明 sender() 函数的原型

#ifndef SENDER_H
#define SENDER_H

void sender(void);

#endif

发件人.c:-

#include "sender.h"
#include "pipe.h"
#include <unistd.h>
#include <stdio.h>

void sender(void)
   {
   char buf[]="Hello world";

   printf("Sender: PID = %d\n", getpid());
   close(pipe_fd[0]);
   write(pipe_fd[1], buf, sizeof(buf));
   }

接收器.h:-

#ifndef RECEIVER_H
#define RECEIVER_H

void receiver(void);

#endif

receiver.c - 发送者的镜像

#include <stdio.h>
#include <unistd.h>
#include "receiver.h"
#include "pipe.h"

void receiver(void)
   {
   int bytes;
   char buf[101];

   printf("Receiver: PID = %d\n", getpid());

   close(pipe_fd[1]);
   bytes = read(pipe_fd[0], buf, 100);
   buf[bytes]='\0';
   printf("Receiver got: %s\n", buf);
   }

main.c - 将它们联系在一起

#include "pipe.h"
#include "sender.h"
#include "receiver.h"
#include <sys/types.h>
#include <unistd.h>

void launch_sender_receiver(void)
   {
   pid_t forkpid;

   forkpid = fork();
   if (forkpid == 0)
      receiver(); /* child */
   else
      sender();
   }

int main(int argc, char* argv[])
   {
   create_pipe();
   launch_sender_receiver();
   return 0;
   }

希望您可以从代码中遵循所有这些,但如果不是,这里有一点额外的解释。

pipe.c 中的 create_pipe() 函数创建一个管道并将两个文件描述符放入file_fd. pipe.h 文件提供了文件描述符的extern声明,以便发送者和接收者文件可以访问它们(更好的编程实践是在 pipe.h 中为这些文件描述符提供“getter”函数,以便sender()receiver()访问全局变量)。

Sender 和 Receiverpipe_fd在关闭不需要的文件描述符后使用数组从管道写入或读取。该main()函数通过调用管道创建函数将它们联系在一起,然后根据它是父级还是子级进行分叉并调用发送方或接收方。

将它作为一个完整的程序运行应该会得到以下输出(当然,你得到的 PID 会有所不同):-

Receiver: PID = 3285
Sender: PID = 3284
Receiver got: Hello world

这一切有意义吗?

于 2010-03-17T00:41:28.853 回答
1

你的问题几乎不可能含糊,但我猜

extern int myPipe[2];

?

于 2010-03-16T21:42:49.133 回答
0

如果您打算 fork() 创建这两个进程,那么您的“int fd[2]; pipe(fd);” 将按照您的描述工作。

即在一个进程中使用 fd[0],在另一个进程中使用 fd[1]。

但是,如果您不打算分叉,那么您可能必须在文件系统中创建一个管道并通过它进行通信。

使用 mkfifo 创建您的管道,然后打开它以在一个进程中读取并打开它以在另一个进程中写入。

于 2010-03-16T21:52:52.823 回答
0

为什么需要在头文件中做呢?您只需从程序中调用 pipe() 即可。然后调用 fork()。结果,您有两个进程访问同一管道。

于 2010-03-16T21:52:55.903 回答