views:

255

answers:

4

I have an assignment in which I need to declare a pipe in a header file. I really have no idea how to do this. It might be a really stupid question and I might be missing something obvious. If you could point me in the right direction I would greatly appreciate it.

Thanks for your time.

EDIT:

Sorry about the question being so vague. Maybe I need to reinforce my understanding of pipes.

I'm trying to create a pipe between two child processes. One child will write random characters into the pipe while the other child will read characters out of the pipe.

I guess I don't really understand what happens when I write something like:

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

Am I right in saying that the writing and reading file descriptors for the pipe are put into fd[0] and fd[1] respectively? If in one of the child processes I close fd[1], that child could be thought of as my writer, correct?

EDIT 2:

Okay, it looks as if I pretty much have everything figured out and done, except I am getting an error pertaining to the file descriptors.

My code looks like this: (This is only the code relating to the pipe)

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

After executing the code, I get an error for every iteration of read() and write() with the error "Bad file descriptor". I've tried searching online to solve this myself, but I do not think I know enough about this material in order to do so. Any direction would be greatly appreciated once again. Everybody that has contributed has done a wonderful job so far, thank you very much. Also, if it looks like I'm just having you do my homework for me, I'm putting forth an honest effort and this isn't the entirety of the assignment.

EDIT 3:

Is the write() system call writing to standard output? What if I only want the contents to be printed after the reader reads them out of the pipe? How do I write them into the pipe without it writing them to standard output?

EDIT 4: I've figured everything out now. Thanks for all of the help everybody. The only thing I'm still curious about is if I could somehow get the status of the parent process. I've collected the statuses from the child process using the wait() system call and was wondering how to retrieve the status of the parent process.

+1  A: 

Your question is almost impossibly vague, but I'm going to guess

extern int myPipe[2];

?

Tyler McHenry
that would be my *guess* as well
jschmier
How exactly do I use extern? If I say:extern int fd[2];in my header file, can I immediately access that array? Is this treated as a global variable? I need to have one source file for the writer and another for the reader, so in writer.c could I use the fd[0] without doing anything else? I'm new to C if you couldn't tell :) Thanks for your help.
Kyle Van Koevering
@Kyle - http://stackoverflow.com/questions/1433204/what-are-extern-variables-in-c
jschmier
A: 

If you intend to fork() to create the two processes then your "int fd[2]; pipe(fd);" will work as you described.

i.e. use fd[0] in one process and fd[1] in the other.

However, if you're not going to fork then you're probably going to have to create a pipe in the filesystem and communicate through this.

Use mkfifo to create your pipe and then open it for reading in one process and open it for writing in the other.

ScaryAardvark
Yes, I did intend to use fork() twice to create the two child processes. The processes are suppose to immediately call their respective functions (writer and reader) in their respective source files. Can I somehow use the fd[0] and fd[1] in those other source files? I'm new to C, thanks for all of your help.
Kyle Van Koevering
A: 

Why do you need to do it in a header file? You just call pipe() from your program. Then call fork(). As a result you have two processes accessing the same pipe.

shura
The assignment requires the pipe declaration to be in the header file.
Kyle Van Koevering
+3  A: 

Here's an example of a program that creates a pipe and then forks the process and calls a sender function in the parent and a receiver in the child. The pipe creation and file descriptors are in one source code file with an associated header file, as are the sender and receiver. The main file requests the pipe be created then does the fork() and calls the sender and receiver functions.

pipe.h - this contains the extern declaration for the pipe file descriptors as well as the declaration of the function that creates the pipe:-

#ifndef PIPE_H
#define PIPE_H

extern int pipe_fd[2];

void create_pipe(void);

#endif

pipe.c - contains the actual definition of the pipe_fd array:-

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

int pipe_fd[2];

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

sender.h - declares the prototype for the sender() function

#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 - mirror image of sender

#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 - ties it all together

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

Hopefully you can follow all this from the code but if not here's a little extra explanation.

The create_pipe() function in pipe.c creates a pipe and puts the two file descriptors into file_fd. The pipe.h file provides an extern declaration for the file descriptors so that they can be accessed by the sender and receiver files (better programming practice would be to provide "getter" functions for these file descriptors in pipe.h so that sender() and receiver() are not accessing global variables).

Sender and Receiver use the pipe_fd array to either write or read from the pipe after they close the file descriptor that they don't need. The main() function ties it all together by calling the pipe creation function and then doing the fork and calling sender or receiver depending on whether it is the parent or child respectively.

Running this as a complete program should get you the following output (although of course the PIDs you get will be different):-

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

Does all that make sense?

Andrew O'Reilly