Linux read () function

Source: Internet
Author: User

Read () function
The READ function reads data from open devices or files.
#include <unistd.h>    
ssize_t read(int fd, void *buf, size_t count);  
Returned value: the number of bytes read successfully. If an error occurs,-1 is returned and errno is set. If the value reaches the end of the file before the read is called, 0 is returned for this read operation.
The Count parameter is the number of bytes requested to read. The read data is stored in the buffer Buf and the current read/write position of the file is moved back. Note that the read/write location may be different from the read/write location when the C standard I/O library is used. This read/write location is recorded in the kernel, when the C standard I/O library is used, the read/write location is in the user space I/O buffer. For example, if fgetc is used to read a byte, fgetc may pre-read 1024 bytes from the kernel to the I/O buffer, and then return the first byte, in this case, the Read and Write locations recorded by the file in the kernel are 1024, while those recorded in the file structure are 1. Note that the return value type is ssize_t, indicating the signed size_t. This can return both the number of positive bytes, 0 (indicating that the object is reached), and negative value-1 (indicating an error ). When the READ function returns, the returned value indicates the number of bytes in the Buf that have just been read. In some cases, the actual number of bytes read (returned value) is smaller than the number of bytes read by the request. For example, when reading a regular file, the number of bytes read has reached the end of the file. For example, if there are 30 bytes left at the end of the file and 100 bytes are requested to be read, 30 is returned for read and 0 is returned for the next read.

Read from the terminal device, usually in the unit of action. If you read a line break, the system returns the result.

Read from the network. Based on different transport layer protocols and kernel caching mechanisms, the returned value may be smaller than the number of bytes requested. The socket programming section will explain in detail later.

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

#include <unistd.h>   
ssize_t write(int fd, const void *buf, size_t count);  
Returned value: the number of bytes written. If an error occurs,-1 is returned. When errno is set to write a regular file, the return value of write is usually equal to the number of bytes written by the request. Count, writing to a terminal device or network is not necessarily the case.

Reading regular files will not be blocked. No matter how many bytes are read, read will be returned within a limited period of time. Reading from a terminal device or network is not necessarily the case. If the data entered from the terminal does not have a line break, the device that calls the read terminal will be blocked. If no data packet is received on the network, calling read will block reading from the network. It is not clear how long it will be blocked. If no data has been reached, it will be blocked. Similarly, writing regular files will not be blocked, but writing to the terminal device or network is not necessarily.

Now let's clarify the concept of block. When a process calls a blocked system function, the process is put into sleep state. At this time, the kernel Schedules other processes to run, it is not possible to continue running until the waiting event occurs (for example, the packet is received on the network or the sleep time specified by sleep is called. The running state is opposite to the sleeping state. In the Linux kernel, processes in the running state are divided into two situations:

Being scheduled. The CPU is in the context of the process. The instruction address of the process is saved in the program counter (EIP), and the intermediate result of the process is saved in the General Register, executing the command of the process and reading and writing the address space of the process.

Ready. This process can be executed at any time without waiting for any event, but the CPU is still executing another process, so the process is waiting for scheduling by the kernel in a ready queue. There may be multiple ready processes in the system at the same time. Who should execute the scheduling? The scheduling algorithm of the kernel is based on priority and time slice, and the priority and time slice of each process are dynamically adjusted according to the running status of each process, so that every process can get a fair execution opportunity, at the same time, the user experience should be taken into account, and the response of processes that interact with users should not be too slow.

The following applet reads data from the terminal and then writes it back to the terminal.

Example 28.2. Blocking the read Terminal

#include <unistd.h>  
#include <stdlib.h>    
int main(void)  {
   char buf[10];
   int n;
   n = read(STDIN_FILENO, buf, 10);
   if (n < 0) {
    perror("read STDIN_FILENO");
    exit(1);
   }
   write(STDOUT_FILENO, buf, n);
   return 0;  }

The execution result is as follows:

$./A. Out Hello (Press ENTER) hello
$./A. Out Hello World (Press ENTER) hello
worl$ d  bash: d: command not found

The result of the first execution of A. Out is normal, and the second execution process is a bit special. Now let's analyze it:

The shell process creates a. Out process, and the. Out process starts to run, while the shell process waits for the. Out Process to exit.

A. out calls read, sleep and wait until the terminal device enters a line break to return from read, read only takes 10 characters, the remaining characters are still stored in the kernel terminal device input buffer.

A. Out
The process prints and exits. At this time, the shell process resumes operation. The shell continues to read the user-input commands from the terminal, so it reads the remaining characters D and line breaks in the input buffer zone of the terminal device, it is interpreted and executed as a command, and the result shows that the command cannot be executed, without D.

If the o_nonblock flag is specified when a device is opened, read/write will not be blocked. Take read as an example. If the device does not read data for the moment,-1 is returned, and errno is set to ewouldblock (or eagain, the two macros have the same value ), it indicates that it should have been blocked here (wocould block, virtual tone). In fact, it does not block but directly returns an error. The caller should try to read it again (again ). This kind of behavior is called poll. The caller only queries it, instead of blocking it, so that the caller can monitor multiple devices at the same time:

While (1 ){
Non-blocking read (device 1 );
If (device 1 has data arriving)
Process data;
Non-blocking read (device 2 );
If (device 2 has data arriving)
Process data;
...
}

If
Read (device 1)
Is blocked, so as long as device 1 does not have data to arrive, it will always be blocked on device 1
Read
In call, even if device 2 has data arriving, it cannot be processed. Using non-blocking I/O can prevent device 2 from being processed in a timely manner.

Non-blocking I/O has a drawback. If no data has been reached for all devices, the caller needs to perform repeated queries for useless work. If the congestion exists, the operating system can schedule other processes for execution, it won't be useless. When non-blocking I/O is used, it is usually not continuously queried in a while loop (this is called tight loop), but every delay is waiting for a while to query, in order to avoid too much useless work, other processes can be scheduled for execution when the wait is delayed.

while(1) {
Non-blocking read (device 1 );
If (device 1 has data arriving) processing data;
Non-blocking read (device 2 );
If (device 2 has data arriving) processing data;
   ...   sleep(n);
  }

The problem is that device 1 may not be able to process data in a timely manner when it arrives. It takes up to n seconds to process the data, and repeated queries are still useless. The Select (2) function to be learned in the future can monitor multiple devices at the same time in a blocking manner and set the timeout time for blocking wait, thus solving this problem satisfactorily.

The following is an example of non-blocking I/O. Currently, we have learned that only terminals can cause blocking, so we use terminals for this experiment. When the program starts execution, the files automatically opened on the 0, 1, and 2 file descriptors are terminals, but there is no o_nonblock flag. So just like
28.2 "blocking reading terminal", reading standard input is blocked. You can re-open the device file/dev/tty (indicating the current terminal) and specify
O_nonblock flag.

Example 28.3. Non-blocking read Terminal

#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 fd, n;
   fd = open("/dev/tty", O_RDONLY|O_NONBLOCK);
   if(fd<0) {
    perror("open /dev/tty");
    exit(1);
   }
  tryagain:
   n = read(fd, buf, 10);
   if (n < 0) {
    if (errno == EAGAIN) {
     sleep(1);
     write(STDOUT_FILENO, MSG_TRY, strlen(MSG_TRY));
     goto tryagain;
    }
     perror("read /dev/tty");
    exit(1);
   }
   write(STDOUT_FILENO, buf, n);
   close(fd);
   return 0;
  }

The following is an example of non-blocking I/O timeout. It not only ensures the logic of timeout and exit, but also ensures that the processing delay is small when data arrives.

Example 28.4. Non-blocking read terminal and wait timeout

#include <unistd.h> 
#include <fcntl.h>  
#include <errno.h> 
#include <string.h> 
#include <stdlib.h>   
#define MSG_TRY "try again\n"  
#define MSG_TIMEOUT "timeout\n"    
int main(void)  {
   char buf[10];
   int fd, n, i;
   fd = open("/dev/tty", O_RDONLY|O_NONBLOCK);
   if(fd<0) {
    perror("open /dev/tty");
    exit(1);
   } 
  for(i=0; i<5; i++) {
    n = read(fd, buf, 10);
    if(n>=0)     break;
    if(errno!=EAGAIN) {
     perror("read /dev/tty");
     exit(1); 
   } 
   sleep(1);
    write(STDOUT_FILENO, MSG_TRY, strlen(MSG_TRY));
   } 
  if(i==5)
     write(STDOUT_FILENO, MSG_TIMEOUT, strlen(MSG_TIMEOUT));
  else 
    write(STDOUT_FILENO, buf, n);
   close(fd);
   return 0;
  }

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.