1. open the file kernel data structure
1. A process opens two files
File status flag: read, write, append, sync, non-blocking, etc.
2. A process opens the same file twice
3. Two processes open the same file
Example program:
C ++ code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
|
/*************************************** ********************************** > File name: file_0000.c > Author: Simba > Mail: dameng34@163.com > Created time: sat 23 Feb 2013 02:34:02 pm CST **************************************** ********************************/ # Include <sys/types. h> # Include <sys/STAT. h> # Include <unistd. h> # Include <fcntl. h> # Include <stdio. h> # Include <stdlib. h> # Include <errno. h> # Include <string. h># Define err_exit (m )\ Do {\ Perror (m );\ Exit (exit_failure );\ } While (0) Int main (INT argc, char * argv []) { Int fd1, fd2; Char buf1 [1024] = {0 }; Char buf2 [1024] = {0 }; /* Process Control Block PCB * Struct task { *... * Struct files_struct * files; *} * The same process opens the same file twice. The pointer corresponding to one FD index in a file descriptor table owned by a process points to one * File table (including File status (non-blocking of read/write append synchronization), current file offset, * Number of file references (when two FD points to the same file table, the reference count is 2. See DUP for redirection ), * File operation pointers, V node pointers, etc.) are not shared, * V node table (including V node information (struct Stat) And I node information) Sharing */ /* The two processes open the same file */ Fd1 = open ("test.txt", o_rdonly ); If (fd1 =-1) Err_exit ("Open error "); Read (fd1, buf1, 5 ); Printf ("buf1 = % s \ n", buf1 ); Fd2 = open ("test.txt", o_rdwr ); If (fd2 =-1) Err_exit ("Open error "); Read (fd2, buf2, 5 ); Printf ("buf2 = % s \ n", buf2 ); Write (fd2, "AAAAA", 5 ); Memset (buf1, 0, sizeof (buf1 )); Read (fd1, buf1, 5 ); Printf ("buf1 = % s \ n", buf1 ); Close (fd1 ); Close (fd2 ); Return 0; } |
Assume that the content of the test.txt file is abcdehello.
The test is as follows:
Simba @ Ubuntu :~ /Documents/code/linux_programming/apue/file_io $./file_share
Buf1 = ABCDE
Buf2 = ABCDE
Buf1 = aaaaa
The content of the test.txt file is changed to abcdeaaaaa.
Analysis: The analysis shows that a process opens the same file twice, and the file table is not shared, that is, each has its own file offset and file opening flag, therefore, the FD of two read operations is read from the beginning, but the V-node table is shared and written in fd2 (the read and write operations on the same file table share the offset) changed the hard disk data block pointed to by inode, and read fd1 again to get the changed value.
II. I/O redirection
After DUP (3) is executed, the system selects an idle file descriptor (4). In this way, two file descriptors point to the same file table, so the reference count is 2. To redirect data using functions such as dup, close the input and output file descriptor and execute DUP (FD). In this way, the input and output file descriptor also points to the file pointed to by FD, in this way, redirection is implemented. In addition, dup2 and fcntl functions can also be implemented. In fact, without using these functions, you can directly close (0/1/2) before opening. Run the following cat command to copy a file:
C ++ code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
|
/*************************************** ********************************** > File name: Process _. c > Author: Simba > Mail: dameng34@163.com > Created time: sat 23 Feb 2013 02:34:02 pm CST **************************************** ********************************/ # Include <sys/types. h> # Include <sys/STAT. h> # Include <unistd. h> # Include <fcntl. h> # Include <stdio. h> # Include <stdlib. h> # Include <errno. h> # Include <string. h> # Include <signal. h> # Define err_exit (m )\ Do {\ Perror (m );\ Exit (exit_failure );\ } While (0)Int main (INT argc, char * argv []) { Close (0 ); Open ("makefile", o_rdonly ); Close (1 ); Open ("test.txt", o_wronly | o_creat | o_trunc, 0664 ); Execlp ("cat", "cat", null ); Return 0; } |
Now, the standard input is the file makefile, and the standard output is the file makefile2. If you replace the current process with Cat, cat reads the standard input and then outputs it to the standard output, which completes the copy function.
The DUP/fcntl function example program is as follows:
C ++ code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
|
/*************************************** ********************************** > File name: file_dup.c > Author: Simba > Mail: dameng34@163.com > Created time: sat 23 Feb 2013 02:34:02 pm CST **************************************** ********************************/ # Include <sys/types. h> # Include <sys/STAT. h> # Include <unistd. h> # Include <fcntl. h> # Include <stdio. h> # Include <stdlib. h> # Include <errno. h> # Include <string. h># Define err_exit (m )\ Do {\ Perror (m );\ Exit (exit_failure );\ } While (0) /* DUP dup2 fcntl */ Int main (INT argc, char * argv []) { Int FD; FD = open ("test2.txt", o_wronly ); If (FD =-1) Err_exit ("Open error "); /* Close (1 ); DUP (FD ); */ // Dup2 (FD, 1 );
Close (1 ); If (fcntl (FD, f_dupfd, 0) <0) // search for available FD from 0 Err_exit ("fcntl error "); Printf ("Hello \ n"); // export to test2.txt Return 0; } |
Reference: apue