C standard I/O library functions and unbuffered I/O functions

Source: Internet
Author: User
Tags readable touch command truncated



First, C standard I/O library functions, unbuffered I/O functions


1. How the C standard I/O library function is called by the system



fopen (3)



Calling open (2) Opens the file, returns a file descriptor (a number of type int), assigns a document structure, contains the file's descriptor, I/O buffer, and the current read and write location information, returns the address of the document structure.



FGETC (3)



The file's descriptor, I/O buffer, and the current read/write location are found by the passed-in files * parameter, judging whether the next character can be read from the I/O buffer, or if it can be returned directly, otherwise call read (2) to nginx the file description, let the kernel read the file's data to the I/O buffer, The next character is then returned. (open files for C standard I/O are represented by the file * pointer, and for the kernel, open files are indicated by file descriptors, file descriptors are obtained from the open system call, and file descriptors are required when using the read, write, close system calls.) )



FPUTC (3)



Determines whether the file's I/O buffer has space to hold a character, if any, is stored directly in the I/O buffer and returns, if the I/O buffer is full, call write (2), let the kernel write the contents of the I/O buffer back to the file.



Fclose (3)



If there is still data in the I/O buffer that is not written back to the file, call write (2) back to the file and then call Close (2) to close the file, releasing the files struct and I/O buffers.






The system functions such as open, read, write, and close are called unbuffered I/O (unbuffered I/O) functions, and the user program can either call the C standard I/O library function while reading and writing the file, or call the underlying unbuffered I/O function directly. What is the respective usage scenario?


    • With unbuffered I/O functions to enter the kernel every time, write a system call than the function of a user control is much slower, so in the user program to open I/O buffer is still necessary, C standard I/O library function is more convenient.
    • Using the C standard I/O library function It is always important to note that I/O buffers and actual files may be inconsistent , calling Fflush (3) when necessary.
    • The Unix tradition is that everything is a file,i/o function not only can read and write files but also can read and write devices. It is generally not desirable to have buffering when reading and writing devices . For example, the network settings read and write is expected to be real-time reading.


  C standard library functions are part of the C standard, and unbuffered I/O functions are part of the UNIX standard . You can only use unbuffered I/O functions on the Unxi platform, not on Windows.






2. File descriptors



Each process has a task_struct struct in the Linux kernel to maintain process-related information called process descriptor, which in the operating system theory is called the Process Control block (PCB, Process Control Block). In Task_struct, there is a pointer to the files_struct struct, called a file descriptor table, each of which contains a pointer to an open file, as shown in:






The user program cannot directly access the file descriptor list in the kernel, but only the index of the file descriptor (that is, 0, 1, 2, 3), which is called the file descriptor and is saved with the INT type variable. When the call to open opens a file or creates a new file, the kernel assigns a file descriptor and returns it to the user program , which points to the new open file in the file descriptor edge item. When the file is read and written, the user program passes the file descriptor to read or write, the kernel finds the corresponding table entry based on the file descriptor, and then finds the corresponding file through the pointer in the table key.



Three files are automatically opened when the program starts: standard input, standard output, and standard error output. The C standard is represented by the file * pointer stdin, stdout, and stderr respectively. The descriptors for these three files are 0, 1, 2, respectively, and are stored in the corresponding file structure. The following macro definitions are in the header file Unistd.h to represent these three file descriptors:





 
 
#define STDIN_FILENO  0
#define STDOUT_FILENO 1
#define STDERR_FILENO 2





Second, Open/close


1. Open

The Open function opens or creates a file.





 
 
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);


In the man page, the Open function has two forms, one with 2 parameters, one with 3 parameters, in C code the declaration of the Open function is this:





int Open (constcharint flags, ...);


The last variable parameter can be 0 or 1, which is determined by the flag bit in the flags parameter.



The pathname parameter is the name of the file to open or create, either a relative path or an absolute path. The flags parameter has a series of constant values to choose from, and you can select multiple constants to join with a bitwise OR operator , so the definitions of these constants begin with O_, which indicates or.



Required option: one must be specified in the following three constants, and only one is allowed.


    • O_rdonly read-only Open
    • O_wronly only Write Open
    • O_rdwr Readable writable file


The following options can be set at the same time as 0 or more, and the required options are either bitwise or up as the flags parameter, there are many options, and the following are some of the optional options:


    • O_append indicates append. If the file already has content, the data written by this open file is appended to the end of the file without overwriting the original content.
    • O_creat create this file if it does not exist. When using this option, you need to provide a third parameter, mode, which represents the access rights for the file
    • O_EXCL if O_creat is specified at the same time and the file already exists, an error is returned.
    • O_trunc if the file already exists and is opened in write-only or read-only writable mode, its length is truncated to 0 bytes.
    • O_nonblock for device files, O_nonblock Open can do non-blocking I/O (nonblock I/O).


The open function is slightly different from the fopen function of the C standard I/O library:


    • When a file is fopen in a writable manner, it is created automatically if the file does not exist, and open requires O_creat to create the file, or the file does not exist and is returned with an error.
    • When a file is fopen in W or w+ mode, if the file already exists, it is truncated to 0 bytes, and the open file must explicitly specify O_TRUNC to truncate the file, otherwise it will be overwritten directly on the original data.


The third parameter, mode, specifies file permissions, which can be expressed in octal numbers, such as 0644 for-rw-r--r--, or as a bitwise or as a macro defined by a s_irusr, S_IWUSR, and so on. Note: File permissions are determined by the open mode parameter and the Umask mask of the current process.



The umask mask of the shell process can be viewed with the umask command:





$ umask 0022


When you create a file with the Touch command, the Create permission is 0666, and the touch process inherits the Umask mask of the shell process, so the final file permission is 0666&~022 = 0644.



2. Close



The close function closes an open file:





#include <unistd.h>
int close (int fd);
Return value: 0 if successful, -1 if error, and set errno


The parameter fd is the file descriptor to be closed. When a process finishes, the kernel calls close for all file descriptors that have not yet been closed for the process, so even if the user program does not call close, the kernel will automatically close all files it opens at the time of termination.



The file descriptor returned by open must be the smallest descriptor that the process has not yet used. Because the file descriptor 0, 1, 2 is opened automatically when the program starts, the first call to open opens the file usually returns the descriptor 3, and the call to open returns 4. You can use this to open a new file on standard input, standard output, or standard error output to implement redirection functionality. For example, first call close to close the file descriptor 1, and then call Open opens a regular file, you must return the file descriptor 1, when the standard output is no longer a terminal, but a regular file, and then call printf will not print to the screen, but write to this file.






Third, Read/write



1. Read



The read function reads data from an open device or file





#include <unistd.h>
ssize_t read (int fd, void * buf, size_t count);
Return value: The number of bytes read is returned successfully. If an error occurs, -1 is returned and errno is set. If the end of the file is reached before the read is called, the read returns 0 this time.


The parameter count is the number of bytes requested to be read, the data read is saved in the buffer buf, and the current read and write location of the file is moved backwards. This read-write location may be different from the read and write location when using the C standard library. A return value type of ssize_t represents a signed size_t, which returns either a positive number of bytes (positive), 0 (to the end of the file), or a negative 1 (error). When read returns, the return value indicates how many bytes in the buf were just read. in some cases, the number of bytes actually read (the return value) is less than the number of bytes requested to read Count, for example:


    • When reading a regular file, the end of the file is reached before the count byte is read.
    • Read from the terminal device, usually in the unit of behavior, read to the newline character returned.
    • Read data from the network, depending on the transport layer protocol and the kernel cache mechanism, the return value may be less than the requested number of bytes.


2. Write



The Write function writes data to an open device or file.





#include <unistd.h>ssize_t write (intconstvoid *buf, size_t count) The number of bytes written successfully returned, error 1 and set errno


When writing a regular file, the return value of write is usually equal to the number of bytes requested, while writing to the terminal device or network is not necessarily true.




3. Blocking



  reading regular files is not blocked , no matter how many bytes read, read is bound to return within a limited time. Reading from the terminal device or network is not necessarily, if the data entered from the terminals do not have newline characters, call read read terminal equipment will be blocked, if the network does not receive packets, call read from the network will block the reading, as to how long it will be blocked is uncertain. If there is no data, it will always be blocked there. The same as write operations.



When a process calls a blocked system function, the process is put to sleep, and the kernel dispatches another process to run until the event that the process waits for occurs (such as a packet is received on the network, or the sleep time specified by the call is reached) it is possible for it to continue running. The running state is relative to the sleep state. In the Linux kernel, the running process is divided into two scenarios:


    • is being dispatched for execution. The CPU is in the context of the process, the program counter (EIP) holds the instruction address of the process, the General register holds the intermediate result of the process operation, the process is executing the instructions, is reading and writing the process's address space.
    • Ready state. The process does not need to wait for any events to occur and can be executed at any time, but the CPU is still executing another process, so the process waits for the kernel to be dispatched in a ready queue.


If you specify the O_NONBLOCK flag when you open a device, the Read/write does not block.






Fourth. Lseek



Lseek is similar to the fseek function of the standard I/O library, where the current read/write position (or offset) can be moved.





#include <sys/types.h><unistd.h>off_t lseek (intint whence);


The meaning of the parameter offset and whence is exactly the same as the fseek function. There are three types of whience settings, Seek_set,seek_cur,seek_end, like Fseek, where the offset allows for more than the end of the file, in which case the next write to the file will extend the file, The empty part of the middle is read in 0.



If Lseek executes successfully, the new offset is returned, so the current offset of an open file can be determined by the following methods:





0, seek_cur);


The device is generally not set to offset. If the device does not support Lseek then Lseek returns-1, and the errno is set to Espipe. Note that the fseek and Lseek have subtle differences in the return value, and Fseek returns 1 on successful return 0 failure. To return the current offset, call Ftell, and return-1 if Lseek succeeds when the current offset fails.






Fifth, Fcntl



Stdin_fileno has been opened automatically when the program starts, so we have to change the way Std_fileno is opened (such as setting O_nonblock) must be reopened with the open function. Another way is to use the FCNTL function to change the properties of an open file, you can reset the read, write, append, non-blocking flag, and do not have to re-open the file.











#include <unistd.h>
#include <fcntl.h>

int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, long arg);
int fcntl(int fd, int cmd, struct flock *lock);


This function, like open, is also implemented with variable parameters, and the type and number of variable parameters depend on the preceding cmd parameter.



The following program changes the properties of the Stdin_fileno using the two FCNTL commands F_GETFL and F_SETFL:





#include <unistd.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <stdlib.h> #define MSG_TRY "try again\n" int main(void)
{ char buf[10]; int n; int flags;
    flags = fcntl(STDIN_FILENO, F_GETFL);
    flags |= O_NONBLOCK; if (fcntl(STDIN_FILENO, F_SETFL, flags) == -1)
    {
        perror("fcntl");
        exit(1);
    }
    tryagain:
        n = read(STDIN_FILENO, buf, 10); if (n < 0) { if (errno == EAGAIN) {
                sleep(1);
                write(STDOUT_FILENO, MSG_TRY,
                strlen(MSG_TRY)); goto tryagain;
            }
        perror("read stdin");
        exit(1);
    }
    write(STDOUT_FILENO, buf, n); return 0;
} 




Sixth. IOCTL


The IOCTL is used to control and configure commands to the device , 

and some commands also need to read and write some data, but the data cannot be read and written by Read/write, known as out-of-band data. In other words, read/write read and write data is In-band data, is the main body of the I/O operation, and the IOCTL command is to transmit control information, wherein the data is auxiliary data, such as the serial port to send and receive data through the read/write operation, and the serial port baud rate, check bit, The stop bit is set by the IOCTL, the result of a/D conversion is read, and the accuracy and operating frequency of the A/D conversion is set by the IOCTL.





#include <sys/ioctl.h>int ioctl (intint request, ...);


D is a file descriptor for a device. Request is the command of the IOCTL, and the mutable parameter depends on the request, usually a pointer to a variable or struct body. Returns 1 if an error occurs, and returns the other value if successful, and the return value is dependent on request. The following program uses the Tiocgwinsz command to obtain the window size of the end device.





#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/ioctl.h> int main(void)
{ struct winsize size; if (isatty(STDOUT_FILENO) == 0)
        exit(1); if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &size)<0) {
        perror("ioctl TIOCGWINSZ error");
        exit(1);
    }
    printf("%d rows, %d columns\n", size.ws_row, size.ws_col); return 0;
}





Seventh, Mmap


Mmap can map a portion of a disk file directly to memory, so that the location of the file directly has a corresponding memory address, read and write to the file can be done directly with pointers without the need for read/write function.











#include <sys/mman.h>
void *mmap(void *addr, size_t len, int prot, int flag, int filedes, off_t off);
int munmp(void *addr, size_t len);


The function of each parameter is illustrated as follows:






If the addr parameter is null, the kernel will itself select the appropriate address in the memory address space to establish the mapping. If addr is not NULL, a hint should be given to the kernel to start mapping from what address, and the kernel will choose an appropriate address above addr to start mapping. Once the mapping is established, the true map header address can be obtained by the return value. The Len parameter is the length of the portion of the file that needs to be mapped. The off parameter is the mapping from where the file begins, and must be an integer multiple of the page size (typically 4K on a 32-bit system structure). Filedes is a descriptor that represents the file.



The prot parameter has four values:


    • Prot_exec represents this segment of the map executable, such as mapping shared libraries
    • The Prot_read represents this section of the map that is readable
    • Prot_write indicates that this section of the map can be written
    • Prot_none indicates that this section of the map is inaccessible


There are a number of values for the flag parameter, two of which are:


    • Map_shared the mapping of multiple processes to the same file is shared, one process modifies the mapped memory, and another process sees this change.
    • Map_private the mapping of multiple processes to the same file is not shared, one process modifies the mapped memory, and the other process does not see this change, nor does it actually write to the file.


Returns the first address of the map if Mmap succeeds, and returns a constant map_failed if an error occurs. When the process terminates, the mapped memory of the process is automatically dismissed, or munmap can be called. Munmap successfully returned 0, error returned-1.



The bottom of the mmap function is also a function call, which is often used when executing programs to map the shared library to the address space of the change process.



C standard I/O library functions and unbuffered I/O functions


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.