Dup2 and Pipe

Source: Internet
Author: User
Tags stdin

DUP () and dup2 () functions

DUP and dup2 are also two very useful invocations, all of which are used to copy a file descriptor.
They are often used to redirect the stdin, stdout, and stderr of the process.
The prototypes of these two functions are as follows:
#include <unistd.h>
int dup (int oldfd);
int dup2 (int oldfd, int targetfd)

Using function dup, we can copy a descriptor. Passed to the function as an existing descriptor, it returns a new descriptor,
This new descriptor is a copy of the descriptor passed to it. This means that the two descriptors share the same data structure. For example
If we perform a lseek operation on a file descriptor, the position of the first file is the same as the second one.
The following is a code fragment that describes the method used by the DUP function:

int fd1, FD2;
...
FD2 = DUP (FD1);


Note that we can create a descriptor before calling fork, which is the same as the effect of calling DUP to create a descriptor,
The child process also receives a copy of the descriptor.

The DUP2 function is similar to the DUP function, but the DUP2 function allows the caller to specify a valid descriptor and the ID of the target descriptor. When the DUP2 function returns successfully,
The target descriptor (the second parameter of the DUP2 function) becomes a replica of the source descriptor (the first parameter of the DUP2 function), in other words,
Two file descriptors now point to the same file and are the file that the first parameter of the function points to. Here's a piece of code to illustrate:
int OLDFD;
OLDFD = open ("App_log", O_RDWR | o_create), 0644);
Dup2 (OLDFD, 1);
Close (OLDFD);

In this case, we open a new file called "App_log" and receive a file descriptor called FD1. We call the DUP2 function,
The argument is OLDFD and 1, which causes the file descriptor (that is, stdout) to be replaced with our newly opened file descriptor, because the standard output file ID is 1.
Anything written to StdOut will now be written to a file named "App_log".

Note that the DUP2 function immediately closes the OLDFD after it has been copied, but does not turn off the newly opened file descriptor because the file descriptor 1 now points to it.

Here's a more in-depth sample code. Recall the command-line pipeline in front of this article, where we use the standard output of the ls–1 command as the standard input
Connect to the Wc–l command. Next, we will use a C program to illustrate the implementation of this process. The code is shown in example code 3 below.
In example code 3, you first create a pipeline in line 9th and then divide the application into two processes: a subprocess (line 13–16)
and a parent process (line 20–23). Next, the STDOUT descriptor (line 13th) is first closed in the subprocess, and then the ls–1 command function is provided.
But it's not written to stdout (line 13th), it's written to the input of the pipe we built, which is done through the DUP function to redirect. On line 14th,
Use the Dup2 function to redirect the stdout to the pipe (pfds[1]). After that, immediately turn off the input end of the pipe. Then, using the EXECLP function to handle the process
The image is replaced with the process image of the command ls–1, and any output of it is sent to the input end of the pipe once the command is executed.

Now let's look at the receiving end of the pipe. As you can see from the code, the receiving end of the pipe is performed by the parent process. First close the stdin descriptor (line 20th),
Because we do not receive data input from standard device files such as the keyboard of a machine, we receive data from the output of other programs. Then, once again, use the DUP2 function (line 21st),
Let stdin become the output of the pipe by making the file descriptor 0 (that is, regular stdin) equal to Pfds[0]. Close the stdout end of the pipe (pfds[1]),
Because it's not used here. Finally, using the EXECLP function to replace the image of the parent process with the process image of the command wc-1, the command wc-1 the contents of the pipe as its input (line 23rd).

Example code 3: pipelining code that uses C to implement commands

1: #include <stdio.h>
2: #include <stdlib.h>
3: #include <unistd.h>
4:
5:int Main ()
6:.. {
7:int pfds[2];
8:
9:if (pipe (PFDs) = 0) ... {//Create a pipe
10:
11:if (fork () = 0) ... {//Child processes
12:
13:close (1); Close STDOUT Descriptor
14:dup2 (Pfds[1], 1); REDIRECT stdout to pipe (pfds[1])
15:close (Pfds[0]); Turn off the input end of the pipe
16:EXECLP ("ls", "ls", "-1", NULL); Replace the image of the handle process with the process image of the command ls–1
17:
:} else ... {//Parent process
19:
20:close (0); Close StdIn Descriptor
21:dup2 (Pfds[0], 0); Let stdin become the output of the pipe
22:close (Pfds[1]); Close the stdout end of the pipe (pfds[1])
23:EXECLP ("WC", "WC", "L", NULL); Replace the image of the parent process with the process image of the command wc-1
24:
25:}
26:
27:}
28:
29:return 0;
30:}


In this program, it is important to be particularly concerned that our child processes redirect its output to the pipeline's input, and then the parent process redirects its input to the output of the pipeline.
This is a very useful technique in real-world application development.

1. File descriptor in the kernel of the data structure
Before I say dup/dup2, I think it is necessary to understand the shape of the file descriptor in the kernel.
While a process is in existence, some files will be opened, which will return some file descriptors, from the shell
By default, 3 file descriptors exist (0, 1, 2), and 0 is associated with the standard input of the process.
1 is associated with the standard output of the process, 2 is associated with the standard error output of the process, and what is currently open in a process
File descriptors can be viewed through the/proc/process id/fd directory. The following diagram illustrates the problem clearly:

Process table Entries

————————————————
FD Flag File pointer
_____________________

FD 0:|________|____________|------------> file sheet

FD 1:|________|____________|

FD 2:|________|____________|

FD 3:|________|____________|

| .......         |

|_____________________|

Figure 1

The file table contains: File status flags, current file offsets, v node pointers, which are not discussed in this article
Focus, we just need to know that each open file descriptor (FD flag) has its own file table in the process table
Item that is pointed to by the file pointer.

2. dup/dup2 function
Both Apue and man documents describe the function of these two functions in a single sentence: Copying an existing file descriptor.
#include <unistd.h>
int dup (int oldfd);
int dup2 (int oldfd, int newfd);

To parse this process from the diagram, when the DUP function is called, the kernel creates a new file descriptor in the process, which is the minimum number of currently available file descriptors, pointing to the File table entry owned by OLDFD.
  Process table entries
 
  ————————————————
 
  FD flag file pointer
 
    ;    _____________________
 
 fd 0:|________|____________|                    ___
 
&NBSP;FD 1:|________|____________|----------------> |      |
 
 fd 2:|________|____________|                   | File Table |
 
 fd 3:|________|____________|----------------> |______|
 
       |     .......         |
 
      |_____________________|


Figure 2: Diagram after calling the DUP
As shown in Figure 2, if the value of the OLDFD is 1 and the current file descriptor has a minimum value of 3, the new descriptor 3 points to
The file table entry owned by descriptor 1.

The difference between dup2 and DUP is that you can specify the value of the new descriptor with the NEWFD parameter, and if NEWFD is already open,
Turn it off first. If NEWFD equals OLDFD, then Dup2 returns NEWFD without closing it. The DUP2 function returns a new
The file descriptor also shares the same file table entry as the parameter OLDFD.

Apue the problem in a different way:
In fact, call DUP (OLDFD);
Equivalence and

Fcntl (OLDFD, F_DUPFD, 0)
While calling Dup2 (OLDFD, NEWFD);
Equivalence and

Close (OLDFD);
Fcntl (OLDFD, F_DUPFD, NEWFD);

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.