The File descriptors is an integer table memory-managed object that can be read and written by the process.
A process can get the file descriptors by opening the files directory or device by creating a pipeline
or copy an already existing descriptors,
The file descriptor abstracts the file pipeline device to the same thing as a byte stream. The file descriptor is mapped as an index to the
The process table. Each process has a file descriptor for the privatization control, starting with 0. Process Read File descriptor 0
Writes the file descriptor to a 1 write error message to the file identifier of 2.
while (FD = open ("console", O_RDWR)) >= 0) {
8508 if (FD >= 3) {
8509 Close (FD);
8510 break;
8511}
8512}
The above code shows that the shell always has three scenarios for the console to guarantee file descriptors
(0 standard input 1 standard output, 2 standard error stream) all open simultaneously.
The Read function reads bytes from the file
The Write function writes bytes to the file
Read (FD, BUF, n) reads n bytes from a file identified by the FD to the BUF buffer
Returns the number of bytes read. The read function continues to read bytes from the file, and when read to the end of the file returns 0 identity file
Read end.
Write (fd, BUF, n) reads n bytes from the buffer to the file in the FD identity, returns the number of bytes written n,
Less than n, there will be errors.
The following code reads byte writes from the standard input stream to the standard output stream
Char buf[512];
int n;
for (;;) {
n = Read (0, buf, sizeof buf)//0 indicates that the input stream reads sizeof buf bytes from the fd=0 file into a buffer
if (n = = 0)//n =0 Read byte failed
Break
if (n < 0) {//error occurred
fprintf (2, "read error\n");
Exit ();
}
if (write (1, buf, n)! = N) {//BUF buffer data is read in the first n bytes into the 1 standard output stream
fprintf (2, "Write error\n");//write to file fails if the return value written is equal to n
Exit ();
}
}
Here's a simplified version of the code a shell runs for the
Command Cat <input.txt:
Char *argv[2];
Argv[0] = "Cat";
ARGV[1] = 0;
if (fork () = = 0) {
Close (0);
Open ("Input.txt", o_rdonly);
EXEC ("Cat", argv);
}
The sub-process close (0) withdraws the FD with the file 0, so that the open function guarantees that the FD returned by "Input.txt" is the minimum of 0.
The EXEC function now lets the cat function read from Input.txt fd=0 identifies the standard input stream, which is the byte read from the file
Stream into memory.
The redirect code is as follows:
struct Redircmd {
8376 int type;
8377 struct cmd *cmd;
8378 Char *file;
8379 Char *efile;
8380 int mode;
8381 int fd;
8382};
The following code is in the Runcmd function
8430 Case REDIR:
8431 rcmd = (struct redircmd*) cmd;
8432 Close (RCMD->FD);//Close the current file descriptor
8433 if (open (Rcmd->file, Rcmd->mode) < 0) {//Open new file descriptor open failed return number less than 0
8434 printf (2, "open%s failed\n", rcmd->file);
8435 exit ();
8436}
8437 Runcmd (rcmd->cmd);//Continue calling this function to start re-judging
8438 break;
The main loop key code for the Shell execution Script command is as follows
if (fork1 () = = 0)
8525 Runcmd (Parsecmd (BUF));//the use of runcmd instead of directly calling the EXEC function to execute
8526 wait (); In order to cope with the occurrence of various situations.
8527}
8528 exit ();
8529
The file offset can be shared in a parent-child process as in the following code
if (fork () = = 0) {
Write (1, "Hello", 6);
Exit ();
} else {
Wait ();
Write (1, "world\n", 6);
}
The child process writes a "Hello" 6-byte string to the standard output stream, exiting
When the parent process starts running, it goes directly to the wait state until after the child process exits after the Hello has finished writing.
It begins to write the world to the standard output stream. Finally print out for Hello World
Indicates the offset of a file descriptor that is common to a parent-child process.
Similar commands have (echo hello; echo World) >output.txt.
The DUP function copies a FD and returns the new FD, and the original FD common one file offset.
For example, the following code will also output Hello world!
FD = DUP (1);
Write (1, "Hello", 6);
Write (FD, "world\n", 6);
File descriptors between processes, or file descriptors created through the DUP function, are common to a file offset.
Or it can be described as representing a specific file stream. In both cases, calling the Open function opens the same file
The two FD returned will not be common for one file offset.
Dup allows shells
To implement commands like This:ls existing-file non-existing-file > Tmp1
2>&1. The 2>&1 tells the Shell to give, the command a file descriptor 2 that
is a duplicate of descriptor 1.
Both the name of the existing file and the error message for the
Non-existing file would show up in the file TMP1. The xv6 Shell doesn ' t support
I/O redirection for the error file descriptor, and now you know how to implement it.
The 2>&1 command indicates that the file descriptor 2 is the return value of the file descriptor 1 called DUP (1). This will put Existing-file Non-existing-file
Write to the same file in temp. The error stream does not support redirection now it can be implemented through the DUP.
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
Analysis of Linux input and output stream and file descriptor