Http://blog.sina.com.cn/s/blog_67b74aea01018ycx.html
The Linux (Unix) process is intricately related to files, and this tutorial attempts to elaborate on this issue. include: 1, Linux multi/single process and multi/single file on the use of file streams and descriptors and some issues needing attention. 2, fork,vfork flow buffer and so on the impact of file operations.
1
. Linux
file system architecture First, add a bit of basic knowledge about Linux file systems. As shown in the following: Figure 1 disks, partitions, and file systems It should be understood that the structure shown is a logical representation of how files are stored in a hard disk, regardless of the process. For some of these terms, see the explanations below. I node: Contains almost all of the files/directories-For information placed on the hard disk that need to be saved for a long time. For example: File owner, file type, I node number (stored in directory block), primary and secondary device number, connection count, access/modification time, io block length, file bytes and so on. The stat function (#include) can be used to obtain information about the I node.
2
. Simple process and file relationship Here, we understand the relationship between single-process multi-file and multi-process single-file, which is quite easy to do without considering fork (parent-child process), except that the assignment statement brings us some minor problems.
2.1
, a process opens multiple files at the same time:
Figure 21 The kernel data structure when a process opens 2 different files at the same timeof These, v-node we have almost already introduced, because it is not only contains I node, its own content is not much, focus on the file table it. for the file table, be aware that it is not from the hard disk of things, it can be said that he is part of the process (probably by the operating system kernel is responsible for maintenance, I am not verified (it is really the kernel responsible for maintenance, see apue-> Section3.12), because it is process or kernel, it is irrelevant to the problem we are discussing. The documentation table includes: file Status flag: Contains Read, write, add write, synchronous and non-blocking various files open/current status. Current file offset: Record file pointer position v Node/I node: A file type and a pointer to a function that makes various operations on this file, which are read into memory by the disk when the file is opened. The File table contents can be modified using the FCNTL function (#include).
2.2
, multiple unrelated processes open a file at the same time: Figure 32 The kernel data structure when a process opens the same file at the same time at this point, 2 files each use a different file table, which indicates that different process file status flag, file offset, etc. are independent. But they share the same v-node table. It is easy to understand the nature of this structure.
3.
Copying of file descriptors or streams for a file descriptor or a stream copy, in many cases we will take an assignment statement, below to understand the difference between an assignment and a DUP, the DUP function copies the file descriptor after the kernel data structure: (Conversion of file streams and file descriptors See here ) Figure 4 Executes the DUP function (#include) after copying the file descriptor, the kernel data structure. at this point, 2 FD file flags use the same file table at the same time.
3.1
,
DUP
differences with assignment statements for file descriptors
to understand the difference between a DUP and an assignment statement for a file descriptor, see the following procedure. Program Description: Open a file descriptor, respectively, for the DUP and assignment statements to copy, copy, print the original and copied file descriptor ID, see if it has the same value, then close the file, test whether the shutdown is successful. Examples of programs: #include #include#include#include int sys_err (char *str) { puts (str); exit ( 0);} int main (void) { int p,q; if (P=open ("C_FID.C", o_rdonly) = = =-1) sys_err ("Open error"); q = DUP (p); Puts ("DUP:"); printf ("File p,q fd is:%d%d\n", Q, p); printf ("Close file p OK?:%d\n", Close (p)); printf ("Close file Q OK?:%d\n", close (q)); if ((P=open ("C_FID.C" , o_rdonly)) = =-1) Sys_err ("Open error"); q = p; puts ("=:"); printf ("File p,q fd is:%d%d\n", Q, p); printf ("Close file p Ok?:%d\n ", Close (p)); printf (" Close file Q OK?:%d\n ", close (q)); return 0;} Program run Result: Dup:file p,q fd is:4 3 //file p,q use a differentFile descriptor "Close" p OK?: 0close file q OK?: 0//Files closed successfully =:file p,q FD is:3 3//Simple copy close file P OK?: 0close file Q OK?: -1//off Failed because this descriptor has been closed As a result, the DUP is a new file descriptor ID and pointer, but they share the file table, the effect 4, then close a file descriptor, the other one is still available, the file table will not be released. Instead of assigning a statement, it simply records the original file pointer in another variable, the same as the file descriptor of the 2 variables, and does not produce a new item in the Process table item.
3.2
, the assignment statement copies the standard stream. Example: #include # include int sys_err (char *str) {puts (str); Exit (0);} int main (void) {FILE *p,*q; if ((P=fopen ("C_fid.c", "r")) = = NULL) sys_err ("Open error"); Q = p; printf ("FILE p,q fd is:%d%d\n", Fileno (Q), Fileno (p)); printf ("Close file p OK?:%d\n", fclose (p)); printf ("Close file Q OK?:%d\n", fclose (q)); return 0;} Program execution results: File p,q FD is:3 3//2 streams share the same file descriptor close filename p OK?: 0*** glibc detected ***//2 The shutdown caused an error, causing the program to crash. ... ....
4
, the
introduction of fork
after the process and file relationship and the impact of stream buffering on file operations
4.1 fork Figure 5 Sharing of open files between parent and child processes after using fork After using fork, the child process inherits the file table opened by the parent process, at which point the parent-child process uses the same file table (visible, guessing that the file table is maintained by the kernel because it is correct because the file table is not copied), which means that 2 processes will share the file state, file offset, and so on. If you use close to close a file descriptor in a process, the descriptor is still valid in the other process and the corresponding file table is not freed. It is important to note that when you use C standard IO for file read and write, the first end process will also count the data in the buffer to the length of the file offset, you can use the Setbuf,setvbuf (#include) setting for the corresponding file buffer type and length. Examples of programs: #include #include#include#include#include int main (void) { int pid; FILE *p; char buff[20]={0}; int test=-2; if (P=fopen ("/ Media/lin_space/soft/netbeans-6.5-ml-cpp-linux.sh "," r ")) = = NULL) {//file greater than 4096 bytes puts ("open error."); Exit (0); } if ((Pid=fork ()) < 0) { puts ("fork error"); exit (0); } Else if (pid = = 0) { Sleep (2); test = Ftell (P);//returns the current offset printf ("\nchild-ftell is:%d\n", test); if ((buff[0] = FGETC (p))! = EOF) printf ("Child-fgetc is:%c\n", buff[0]); else puts ("child- Fgetc error\n "); test = Ftell (p); printf ("Child-ftell is:%d\n", test); } else { test = Ftell (p); printf ("\nparent-ftell is:%d\n", test); if ((buff[0] = fgetc (p))! = EOF) & nbsp; printf ("Parent-fgetc is:%c\n", buff[0]); else puts (" Parent-fgetc error\n "); test = Ftell (p); printf ("Parent-ftell is:%d\n", test); } printf ("Parent and Child-close file OK?:%d\n", fclose (p)); return 0;} Program execution Result: Parent-ftell is:0parent-fgetc is: #parent-ftell is:1parent and Child-close file OK?: 0[email p rotected]:/media/lin_space/summa/apue/unit8$ //Parent Process End Child-ftell is:4096 The //child process file offset is 4096 because the file buffer type is full buffered and the buffer size is 4096child-fgetc Is:achild-ftell is:4097parent and Child-clos E file OK?: 0 //file closed successfully
4.2 vfork for Vfork, although the child process runs in the space of the parent process, the child process has its own process table entry (containing the process PID,FD flag, the file pointer, and so on), so that after one of the processes is finished, another process's file descriptor is still valid. The child process gets a copy of the parent process file descriptor. but vfork for standard streams, the situation is different, after a process has ended (if not using _exit () to end the process), the process may end up flushing the stream buffer and closing the stream, depending on the implementation the difference between fork and vfork see here
[Go] linux System file stream, file descriptor and process relationship between the detailed