Read/write blocking and non-blocking reading of Serial Port Data

Source: Internet
Author: User

readThe function reads data from open devices or files.

# Include <unistd. h> ssize_t read (int fd, void * Buf, size_t count); Return Value: number of bytes read successfully. If an error occurs,-1 is returned and errno is set, if the end of the file has been reached before the read operation is called, 0 is returned for this read operation.

ParameterscountThe number of bytes requested to read. The read data is stored in the buffer zone.buf. 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 examplefgetcRead one byte,fgetcIt is possible to pre-read 1024 bytes from the kernel to the I/O buffer, and then return the first byte. At this time, the read/write position recorded by the file in the kernel is 1024, whileFILEThe read/write position of the record in the struct is 1. Note that the return value type isssize_t, Indicating signedsize_tIn this way, both the number of positive bytes and 0 (indicating that the object is reached) can be returned, and the negative value-1 (indicating an error) can be returned ).readDescription of the return value when the function returnsbufThe first few bytes are just read. In some cases, the actual number of bytes read (returned value) is smaller than the number of bytes read by the request.countFor example:

  • When reading a regular filecountBytes have reached the end of the file. For example, if there are 30 bytes at the end of the file and 100 bytes are requested to be readreadReturns 30. next timeread0 is returned.

  • 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.

writeThe function writes data to an opened device or file.

# Include <unistd. h> ssize_t write (int fd, const void * Buf, size_t count); return value: the number of written bytes is returned successfully, error-1 is returned, and errno is set

When writing a regular file,writeThe return value is usually equal to the number of bytes written by the request.countBut write to the terminal device or network is not necessarily.

Reading regular files is not blocked, no matter how many bytes are read,readWill be returned within a limited period of time. Reading from the terminal device or network is not necessarily. If the data entered from the terminal does not have a line break, callreadThe read terminal device is blocked. If no data packet is received on the network, callreadReads from the network will be blocked. 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, wait until the waiting event of the process occurs (for example, packets are received on the network, orsleepThe specified sleep time is reached. 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, and the program counter (eipThe command address of the process is saved, and the intermediate result of the process operation is saved in the General Register. The command of the process is being executed, and the address space of the process is being read and written.

  • 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 $ dbash: D: Command not found

First executiona.outThe result is normal, and the second execution process is a bit special. Now let's analyze it:

  1. Shell Process Creationa.outProcess,a.outThe process starts to run, while the shell process waits for sleep.a.outThe process exits.

  2. a.outCallreadWait until the terminal device enters a line break.readReturn,readRead-Only takes 10 characters, and the remaining characters are still stored in the input buffer of the kernel terminal device.

  3. a.outThe 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.

IfopenA device is specifiedO_NONBLOCKFlag,read/writeIt will not be blocked. ToreadFor example, if the device is not readable,-1 is returned.errnoIsEWOULDBLOCK(OrEAGAINThese two macros have the same defined values), indicating that they should be blocked here (wowould
Block, virtual tone), in fact, it does not block but directly returns an error, the caller should try to read 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 arrival) processing data; non-blocking read (device 2); If (device 2 has data arrival) process data ;...}

IfRead (device 1)Is blocked, so as long as device 1 does not have data to arrive, it will always be blocked on device 1readIn 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 using non-blocking I/OwhileIn the loop, the query is continuously performed (this is called the tight loop), but the query is delayed for a while 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 arrival) processing data; non-blocking read (device 2); If (device 2 has data arrival) 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. To learn laterselect(2)The function can monitor multiple devices at the same time in a blocking manner, and can set the timeout time for blocking wait to solve 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 to run, the files automatically opened on file descriptors 0, 1, and 2 are terminals, but noO_NONBLOCKFlag. So, just like 28.2 "blocking read terminals", standard read input is blocked. We can re-open the Device File/dev/tty(Indicates the current terminal ).O_NONBLOCKFlag.

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));elsewrite(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.