【问题标题】:How do I declare a pipe in a header file? (In C)如何在头文件中声明管道? (在 C 中)
【发布时间】:2010-03-16 21:37:54
【问题描述】:

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

感谢您的宝贵时间。

编辑:

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

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

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

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

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

编辑 2:

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

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

proj2.h

extern int fd[2];

proj2.c

int fd[2];
pipe(fd);

writer.c

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

reader.c

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

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

编辑 3:

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

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

【问题讨论】:

  • 您需要更清楚、更详细地解释您的问题。
  • @Kyle:你认为应该在标题中声明什么:文件描述符或系统调用?你了解extern 对变量的使用吗(在前一种情况下是必要的)?你为什么相信?你知道上下文函数中声明和定义的区别吗(后一种情况需要)?
  • @Kyle for Edit 3: write() 调用将文件描述符作为其第一个参数,该参数指示输出写入的位置。文件描述符 1 是标准输出,因此 write(1, "hello") 将写入标准输出。但是,如果您在 pipe() 返回的数组中提供第二个文件描述符,您将写入管道而不写入标准输出。看一下我在下面发布的代码作为示例。鉴于您提出的问题,我认为您会从阅读 UNIX 系统编程书籍中受益(我推荐 Robbins & Robbins 的书)。
  • 安德鲁,非常感谢您的意见,非常有用。我一定会看看那本 UNIX 系统编程书。

标签: c header pipe declare


【解决方案1】:

这是一个程序示例,该程序创建一个管道,然后分叉该进程并在父进程中调用发送方函数,在子进程中调用接收方函数。管道创建和文件描述符与发送者和接收者一样,都在一个带有相关头文件的源代码文件中。 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

sender.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));
   }

receiver.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”函数,以便 @ 987654336@ 和 receiver() 没有访问全局变量)。

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

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

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

这一切有意义吗?

【讨论】:

    【解决方案2】:

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

    extern int myPipe[2];
    

    ?

    【讨论】:

    • 这也是我的猜测
    • 究竟如何使用extern?如果我说: extern int fd[2];在我的头文件中,我可以立即访问该数组吗?这是否被视为全局变量?我需要为作者提供一个源文件,为读者提供另一个源文件,所以在 writer.c 中我可以使用 fd[0] 而不做任何其他事情吗?如果您不知道,我是 C 新手 :) 感谢您的帮助。
    【解决方案3】:

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

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

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

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

    【讨论】:

    • 是的,我确实打算使用 fork() 两次来创建两个子进程。假设这些进程会立即在它们各自的源文件中调用它们各自的函数(写入器和读取器)。我可以在其他源文件中以某种方式使用 fd[0] 和 fd[1] 吗?我是 C 新手,感谢您的所有帮助。
    【解决方案4】:

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

    【讨论】:

    • 赋值要求管道声明在头文件中。
    猜你喜欢
    • 2011-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-23
    • 2015-02-13
    • 2014-04-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多