263 lines
11 KiB
HTML
263 lines
11 KiB
HTML
|
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
|
||
|
<!--Converted with LaTeX2HTML 96.1-c (Feb 29, 1996) by Nikos Drakos (nikos@cbl.leeds.ac.uk), CBLU, University of Leeds -->
|
||
|
<HTML>
|
||
|
<HEAD>
|
||
|
<TITLE>6.2.2 Creating Pipes in C</TITLE>
|
||
|
<META NAME="description" CONTENT="6.2.2 Creating Pipes in C">
|
||
|
<META NAME="keywords" CONTENT="lpg">
|
||
|
<META NAME="resource-type" CONTENT="document">
|
||
|
<META NAME="distribution" CONTENT="global">
|
||
|
<LINK REL=STYLESHEET HREF="lpg.css">
|
||
|
</HEAD>
|
||
|
<BODY LANG="EN">
|
||
|
<A NAME="tex2html468" HREF="node12.html"><IMG WIDTH=37 HEIGHT=24 ALIGN=BOTTOM ALT="next" SRC="next_motif.gif"></A> <A NAME="tex2html466" HREF="node9.html"><IMG WIDTH=26 HEIGHT=24 ALIGN=BOTTOM ALT="up" SRC="up_motif.gif"></A> <A NAME="tex2html460" HREF="node10.html"><IMG WIDTH=63 HEIGHT=24 ALIGN=BOTTOM ALT="previous" SRC="previous_motif.gif"></A> <A NAME="tex2html470" HREF="node1.html"><IMG WIDTH=65 HEIGHT=24 ALIGN=BOTTOM ALT="contents" SRC="contents_motif.gif"></A> <BR>
|
||
|
<B> Next:</B> <A NAME="tex2html469" HREF="node12.html">6.2.3 Pipes the Easy </A>
|
||
|
<B>Up:</B> <A NAME="tex2html467" HREF="node9.html">6.2 Half-duplex UNIX Pipes</A>
|
||
|
<B> Previous:</B> <A NAME="tex2html461" HREF="node10.html">6.2.1 Basic Concepts</A>
|
||
|
<BR> <P>
|
||
|
<H2><A NAME="SECTION00722000000000000000">6.2.2 Creating Pipes in C</A></H2>
|
||
|
<P>
|
||
|
Creating ``pipelines'' with the C programming language can be a bit more involved
|
||
|
than our simple shell example. To create a simple pipe with C, we make use of
|
||
|
the pipe() system call. It takes a single argument, which is an array of two
|
||
|
integers, and if successful, the array will contain two new file descriptors
|
||
|
to be used for the pipeline. After creating a pipe, the process typically
|
||
|
spawns a new process (remember the child inherits open file descriptors).
|
||
|
<P>
|
||
|
<P>
|
||
|
<HR><PRE> SYSTEM CALL: pipe();
|
||
|
|
||
|
PROTOTYPE: int pipe( int fd[2] );
|
||
|
RETURNS: 0 on success
|
||
|
-1 on error: errno = EMFILE (no free descriptors)
|
||
|
EMFILE (system file table is full)
|
||
|
EFAULT (fd array is not valid)
|
||
|
|
||
|
NOTES: fd[0] is set up for reading, fd[1] is set up for writing</PRE>
|
||
|
<HR>The first integer in the array (element 0) is set up and opened for reading,
|
||
|
while the second integer (element 1) is set up and opened for writing.
|
||
|
Visually speaking, the output of fd1 becomes the input for fd0. Once
|
||
|
again, all data traveling through the pipe moves through the kernel.
|
||
|
<P>
|
||
|
<PRE> #include <stdio.h>
|
||
|
#include <unistd.h>
|
||
|
#include <sys/types.h>
|
||
|
|
||
|
main()
|
||
|
{
|
||
|
int fd[2];
|
||
|
|
||
|
pipe(fd);
|
||
|
.
|
||
|
.
|
||
|
}</PRE>
|
||
|
<P>
|
||
|
Remember that an array name in C <EM>decays</EM> into a pointer to its first
|
||
|
member. Above, <TT>fd</TT> is equivalent to <TT>&fd[0]</TT>. Once we have established the
|
||
|
pipeline, we then fork our new child process:
|
||
|
<P>
|
||
|
<PRE> #include <stdio.h>
|
||
|
#include <unistd.h>
|
||
|
#include <sys/types.h>
|
||
|
|
||
|
main()
|
||
|
{
|
||
|
int fd[2];
|
||
|
pid_t childpid;
|
||
|
|
||
|
pipe(fd);
|
||
|
|
||
|
if((childpid = fork()) == -1)
|
||
|
{
|
||
|
perror("fork");
|
||
|
exit(1);
|
||
|
}
|
||
|
.
|
||
|
.
|
||
|
}</PRE>
|
||
|
<P>
|
||
|
If the parent wants to receive data from the child, it should close fd1,
|
||
|
and the child should close fd0. If the parent wants to send data to the
|
||
|
child, it should close fd0, and the child should close fd1. Since
|
||
|
descriptors are shared between the parent and child, we should always be sure
|
||
|
to close the end of pipe we aren't concerned with. On a technical note, the
|
||
|
EOF will never be returned if the unnecessary ends of the pipe are not
|
||
|
explicitly closed.
|
||
|
<P>
|
||
|
<PRE> #include <stdio.h>
|
||
|
#include <unistd.h>
|
||
|
#include <sys/types.h>
|
||
|
|
||
|
main()
|
||
|
{
|
||
|
int fd[2];
|
||
|
pid_t childpid;
|
||
|
|
||
|
pipe(fd);
|
||
|
|
||
|
if((childpid = fork()) == -1)
|
||
|
{
|
||
|
perror("fork");
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
if(childpid == 0)
|
||
|
{
|
||
|
/* Child process closes up input side of pipe */
|
||
|
close(fd[0]);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* Parent process closes up output side of pipe */
|
||
|
close(fd[1]);
|
||
|
}
|
||
|
.
|
||
|
.
|
||
|
}</PRE>
|
||
|
<P>
|
||
|
As mentioned previously, once the pipeline has been established, the file
|
||
|
descriptors may be treated like descriptors to normal files.
|
||
|
<P>
|
||
|
<PRE>/*****************************************************************************
|
||
|
Excerpt from "Linux Programmer's Guide - Chapter 6"
|
||
|
(C)opyright 1994-1995, Scott Burkett
|
||
|
*****************************************************************************
|
||
|
MODULE: pipe.c
|
||
|
*****************************************************************************/
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <unistd.h>
|
||
|
#include <sys/types.h>
|
||
|
|
||
|
int main(void)
|
||
|
{
|
||
|
int fd[2], nbytes;
|
||
|
pid_t childpid;
|
||
|
char string[] = "Hello, world!\n";
|
||
|
char readbuffer[80];
|
||
|
|
||
|
pipe(fd);
|
||
|
|
||
|
if((childpid = fork()) == -1)
|
||
|
{
|
||
|
perror("fork");
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
if(childpid == 0)
|
||
|
{
|
||
|
/* Child process closes up input side of pipe */
|
||
|
close(fd[0]);
|
||
|
|
||
|
/* Send "string" through the output side of pipe */
|
||
|
write(fd[1], string, (strlen(string)+1));
|
||
|
exit(0);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* Parent process closes up output side of pipe */
|
||
|
close(fd[1]);
|
||
|
|
||
|
/* Read in a string from the pipe */
|
||
|
nbytes = read(fd[0], readbuffer, sizeof(readbuffer));
|
||
|
printf("Received string: %s", readbuffer);
|
||
|
}
|
||
|
|
||
|
return(0);
|
||
|
}</PRE>
|
||
|
<P>
|
||
|
Often, the descriptors in the child are duplicated onto standard input
|
||
|
or output. The child can then exec() another program, which inherits the
|
||
|
standard streams. Let's look at the dup() system call:
|
||
|
<P>
|
||
|
<P>
|
||
|
<HR><PRE> SYSTEM CALL: dup();
|
||
|
|
||
|
PROTOTYPE: int dup( int oldfd );
|
||
|
RETURNS: new descriptor on success
|
||
|
-1 on error: errno = EBADF (oldfd is not a valid descriptor)
|
||
|
EBADF (newfd is out of range)
|
||
|
EMFILE (too many descriptors for the process)
|
||
|
|
||
|
NOTES: the old descriptor is not closed! Both may be used interchangeably</PRE>
|
||
|
<HR>Although the old descriptor and the newly created descriptor can be used
|
||
|
interchangeably, we will typically close one of the standard streams first.
|
||
|
The dup() system call uses the lowest-numbered, unused descriptor for the
|
||
|
new one.
|
||
|
<P>
|
||
|
Consider:
|
||
|
<P>
|
||
|
<PRE> .
|
||
|
.
|
||
|
childpid = fork();
|
||
|
|
||
|
if(childpid == 0)
|
||
|
{
|
||
|
/* Close up standard input of the child */
|
||
|
close(0);
|
||
|
|
||
|
/* Duplicate the input side of pipe to stdin */
|
||
|
dup(fd[0]);
|
||
|
execlp("sort", "sort", NULL);
|
||
|
.
|
||
|
}</PRE>
|
||
|
<P>
|
||
|
Since file descriptor 0 (stdin) was closed, the call to dup() duplicated the
|
||
|
input descriptor of the pipe (fd0) onto its standard input. We then make
|
||
|
a call to execlp(), to overlay the child's text segment (code) with that of
|
||
|
the sort program. Since newly exec'd programs inherit standard streams from
|
||
|
their spawners, it actually inherits the input side of the pipe as its
|
||
|
standard input! Now, anything that the original parent process sends to the
|
||
|
pipe, goes into the sort facility.
|
||
|
<P>
|
||
|
There is another system call, dup2(), which can be used as well. This
|
||
|
particular call originated with Version 7 of UNIX, and was carried on through
|
||
|
the BSD releases and is now required by the POSIX standard.
|
||
|
<P>
|
||
|
<P>
|
||
|
<HR><PRE> SYSTEM CALL: dup2();
|
||
|
|
||
|
PROTOTYPE: int dup2( int oldfd, int newfd );
|
||
|
RETURNS: new descriptor on success
|
||
|
-1 on error: errno = EBADF (oldfd is not a valid descriptor)
|
||
|
EBADF (newfd is out of range)
|
||
|
EMFILE (too many descriptors for the process)
|
||
|
|
||
|
NOTES: the old descriptor is closed with dup2()!</PRE>
|
||
|
<HR>With this particular call, we have the close operation, and the actual
|
||
|
descriptor duplication, wrapped up in one system call. In addition, it
|
||
|
is guaranteed to be atomic, which essentially means that it will never
|
||
|
be interrupted by an arriving signal. The entire operation will transpire
|
||
|
before returning control to the kernel for signal dispatching. With the
|
||
|
original dup() system call, programmers had to perform a close() operation
|
||
|
before calling it. That resulted in two system calls, with a small degree
|
||
|
of vulnerability in the brief amount of time which elapsed between them.
|
||
|
If a signal arrived during that brief instance, the descriptor duplication
|
||
|
would fail. Of course, dup2() solves this problem for us.
|
||
|
<P>
|
||
|
Consider:
|
||
|
<P>
|
||
|
<PRE> .
|
||
|
.
|
||
|
childpid = fork();
|
||
|
|
||
|
if(childpid == 0)
|
||
|
{
|
||
|
/* Close stdin, duplicate the input side of pipe to stdin */
|
||
|
dup2(0, fd[0]);
|
||
|
execlp("sort", "sort", NULL);
|
||
|
.
|
||
|
.
|
||
|
}</PRE>
|
||
|
<P>
|
||
|
<HR><A NAME="tex2html468" HREF="node12.html"><IMG WIDTH=37 HEIGHT=24 ALIGN=BOTTOM ALT="next" SRC="next_motif.gif"></A> <A NAME="tex2html466" HREF="node9.html"><IMG WIDTH=26 HEIGHT=24 ALIGN=BOTTOM ALT="up" SRC="up_motif.gif"></A> <A NAME="tex2html460" HREF="node10.html"><IMG WIDTH=63 HEIGHT=24 ALIGN=BOTTOM ALT="previous" SRC="previous_motif.gif"></A> <A NAME="tex2html470" HREF="node1.html"><IMG WIDTH=65 HEIGHT=24 ALIGN=BOTTOM ALT="contents" SRC="contents_motif.gif"></A> <BR>
|
||
|
<B> Next:</B> <A NAME="tex2html469" HREF="node12.html">6.2.3 Pipes the Easy </A>
|
||
|
<B>Up:</B> <A NAME="tex2html467" HREF="node9.html">6.2 Half-duplex UNIX Pipes</A>
|
||
|
<B> Previous:</B> <A NAME="tex2html461" HREF="node10.html">6.2.1 Basic Concepts</A>
|
||
|
<P><ADDRESS>
|
||
|
<I>Converted on: <BR>
|
||
|
Fri Mar 29 14:43:04 EST 1996</I>
|
||
|
</ADDRESS>
|
||
|
</BODY>
|
||
|
</HTML>
|