Linux File Operations-system calls and standard I/O Libraries

Source: Internet
Author: User
I. What is a file? Before describing file operations, we must first know what is a file. You may feel ridiculous when you see this problem, because for people who have used computers, files are the simplest concept. For example, a text is a file, A Work Document is a file. But in Linux, the concept of files is far more than that. In Linux, everything (or almost everything) is a file. Files include a lot of content. For example, common files are files, directories are files, devices are files, and pipelines are files. Operations on directories and devices can also be equivalent to operations on plain text files. This is also a very successful feature of Linux. Ii. System Call 1. file descriptor file descriptors are small values. You can use them to access open file devices. The number of file descriptors available depends on the system configuration. However, when a program starts to run, it usually has three open file descriptors, namely 0: Standard Input 1: Standard Output 2: standard errors the mathematics (0, 1, 2) is the file descriptor, because everything is a file in Linux, so the standard input (stdin), standard output (stdout) and stderr can also be treated as files. 2. system call common functions A. Open System Call OPEN function prototype: int open (const char * path, int oflags); int open (const char * path, int oflags, mode_t mode); path indicates the complete file name of the path, and oflags indicates the file access mode (that is, how to open the file, read-only, write-only, read-only, and writable ), mode is used to set the object access permissions. For specific optional parameters, you can view the manual page, which is not described here. Open creates an access path to a file or device. If the call succeeds, it returns a file descriptor that can be used by functions called by other systems such as read and write, the description of this file is unique and is not shared with any other running processes. If a failure occurs,-1 is returned and the global variable errno is set to indicate the cause of blindness. B. the prototype of the write function called by the Write System is size_t write (INT Fildes, const void * Buf, size_t nbytes ); write writes the first nbytes bytes of the buffer Buf to the file associated with the file descriptor Fildes, and returns the actual number of bytes written. If the return value is 0, no data is written. If the return value is-1, an error occurs in the call and the error code is saved in errno. Note: Fildes must be the created file descriptor returned in the open call, or a standard input, output, or standard error such as 0, 1, and 2. C. The prototype of the READ function called by the read system is size_t read (INT Fildes, void * Buf, size_t nbytes ); the read system calls to read the data in bytes of nbytes from the files related to the file descriptor and put them in the Buf of the Data zone to return the number of bytes read, -1 is returned if the request fails. D. The prototype of the function called by the close system is int close (INT Fildes). The function of close is to associate the file descriptor Fildes with the corresponding files. E. If there are so many examples, I will give a complete example, that is, copy one by one from a data file (which contains 1 m '0' characters) to another file. The file name is copy_system.c. The Code is as follows:
# Include <unistd. h> # include <sys/STAT. h> # include <fcntl. h> # include <stdlib. h> int main () {char c = '\ 0'; int in =-1, out =-1; // open the data file in = open ("data.txt", o_rdonly) in read-only mode; // create a file in write-only mode, if the file does not exist, create a new file // The file owner has the read and write permissions out = open ("copy_system.out.txt", o_wronly | o_creat, s_irusr | s_iwusr ); while (read (in, & C, 1) = 1) // read a byte of data write (Out, & C, 1 ); // write a byte of data // close the file descriptor close (in); close (out); Return 0 ;}

3. Anyone with C programming experience in the standard I/O library will know the stdio header file, which is the standard Io library of C language. In the standard Io library, the stream corresponds to the underlying file descriptor and is implemented as a pointer to the structure file. There are many Io library functions. In order to correspond to the previous content, Here we only talk about the functions that correspond to the previous four functions. For other functions, you can check the manual page. A. fopen library function prototype: file * fopen (const char * filename, const char * mode); similar to the underlying system calling open, if the call succeeds, a non-null pointer is returned. Return NULL if the request fails. B. fread library function prototype: size_t fread (void * PTR, size_t size, size_t nitems, file * stream); similar to the underlying calling of read, the function is to read nitems data with a length of size from stream to the buffer zone pointed to by PTR. The returned value is the number of records successfully read to the buffer zone. Note: stream is the object structure pointer returned by the fopen function. C. fwrite library function prototype: size_t fwrite (const void * PTR, size_t size, size_t nitems, file * stream); similar to the underlying calling write, the function is to read the nitems length from the buffer directed by PTR to size, and write them to the file corresponding to stream. D. The fclose library function prototype of the fclose library function is int fclose (File * stream). It is similar to the system call close, and its function is to close the specified file stream. In the same example, the following is another implementation version of the previous example. It implements the same functions as the previous example, but uses a standard I/O library instead of a system call, the code for file name copy_stdio.c is as follows:

# Include <stdio. h> # include <stdlib. h> int main () {int C = 0; file * pfin = NULL; file * pfout = NULL; // open the data file pfin = fopen ("data.txt ", "R"); // open the new file pfout = fopen ("copy_stdio.out.txt", "W"); While (fread (& C, sizeof (char), 1, pfin) // read data fwrite (& C, sizeof (char), 1, pfout ); // write data // close the file stream fclose (pfin); fclose (pfout); Return 0 ;}

Of course, you can also use other library functions to complete the work, such as replacing fread with fgetc and fwrite with fputc. 4. Relationship between file descriptors and file streams each file stream corresponds to an underlying file descriptor. You can mix the underlying input and output operations with high-level file stream operations, but generally do not do this, the consequences of data buffering are unpredictable. We can call the fileno function (prototype: int fileno (File * stream) to determine the underlying file descriptor used by the file stream, which returns the file descriptor pointing to the file stream. Instead, you can call the fdopen function (prototype: file * fdopen (INT Fildes,
Const char * mode) to create a new file stream on an opened file descriptor. The mode parameter is exactly the same as that of the fopen function, it must also conform to the access mode set when the file is initially opened. However, for programming in Linux, system calls are more often used, because system calls often provide more flexibility and more powerful functions, some operations must be called by the system. For example, you must use the system call when creating a file read/write lock. V. Compare the performance of system calls with standard I/O by comparing the code in this example. The executable files generated after compilation in the two examples are respectively copy_system.exeand copy_stdio.exe, use the time command in Linux to test the running time as follows: The test result shows that the system call efficiency is much lower than that of library functions. Why? Because system calling affects system performance. Compared with function calls, Linux must switch from running user code to executing kernel code before returning user code during system calls. Therefore, the overhead of system calls is greater than that of common function calls. However, there is also a way to reduce this overhead, that is, to minimize the number of system calls in the program, and to make every system call complete as much work as possible. Why is the efficiency of library functions to do the same thing so high? This is because the library function schedules the execution of underlying system calls only when the data meets the data block length (or buffer length) requirements, thus reducing the number of system calls, it also allows every system call to do as many things as possible, so the efficiency is relatively high. 6. A simple method to improve system calling. For example, we can use the code of every example (coy_system.c) to add or modify the code. For example, we can improve our efficiency by reading 1024 bytes at a time, after modification, save the file name as copy_system2.c. The Code is as follows:

# Include <unistd. h> # include <sys/STAT. h> # include <fcntl. h> # include <stdlib. h> int main () {char buff [1024]; int in =-1, out =-1; int nread = 0; In = open ("data.txt", o_rdonly ); out = open ("copy_system2.out.txt", o_wronly | o_creat, s_irusr | s_iwusr); // read and write 1024 bytes at a time while (nread = read (in, buff, sizeof (buff)> 0) write (Out, buff, nread); close (in); close (out); Return 0 ;}

The generated executable file is copy_system2.exe. You can use the time command to view the execution time. The comparison shows that its performance is improved by an order of magnitude, which is even more efficient than using database functions to copy characters one by one, at least on my machine.

Related Article

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.