1. Non blocking IO and blocking IO
(1) Difference between non blocking IO and blocking IO:
Non blocking IO is that the user directly obtains a result without waiting after sending an IO request. It is usually used with O_NONBLOCK works with fcntl.
Blocking IO is that when the user thread sends an IO request, the kernel will check whether the resource is ready. If it is not ready, it will wait for the data to be ready, and the user thread will be in a blocking state. The user thread will hand over the CPU. The common blocking functions include wait, pause, sleep and so on. When reading or writing some files.
(2) Advantages of non blocking IO: for the kernel, most of the internal default IO modes are set to blocking. This advantage is to give full play to the performance of the operating system, make the CPU work when needed, greatly improve the CPU utilization, reduce the time of standing still, and improve the efficiency of the overall system
Blocking IO:
Set the read function to read the contents entered by the mouse and keyboard. First block access to the mouse, and then block access to the keyboard. At this time, shake the mouse to get the contents of the mouse, and then enter the keyboard to get the contents of the keyboard. However, if you input the keyboard first, the process will always block the mouse input until you shake the mouse, which brings the trouble that the input must be in order.
#include <stdio.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int main(void) { // Read mouse int fd = -1; char buf[200]; fd = open("/dev/input/mouse1", O_RDONLY); if (fd < 0) { perror("open:"); return -1; } memset(buf, 0, sizeof(buf)); printf("before mouse read.\n"); read(fd, buf, 50); printf("The contents read by the mouse are:[%s].\n", buf); // Read keyboard memset(buf, 0, sizeof(buf)); printf("before keyboard read.\n"); read(0, buf, 5); printf("The contents read by the keyboard are:[%s].\n", buf); return 0; }
Note: for the standard input device of the keyboard, the corresponding file descriptor is 0; The mouse is not a standard device, but it can be viewed by ls /dev/input. After confirming the currently used device, open("/dev/input/mouse1", O_RDONLY); Open the corresponding device file and use the following method to find the mouse device.
Non blocking IO:
The simplest solution is to change the two IO positions to non blocking mode, which is similar to a polling mode. The corresponding IO operations are performed by looping reading the mouse and keyboard.
#include <stdio.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int main(void) { // Read mouse int fd = -1; int flag = -1; char buf[200]; int ret = -1; fd = open("/dev/input/mouse1", O_RDONLY | O_NONBLOCK); if (fd < 0) { perror("open:"); return -1; } // Make file descriptor No. 0 (stdin) non blocking flag = fcntl(0, F_GETFL); // Get the original flag first flag |= O_NONBLOCK; // Add non blocking attribute fcntl(0, F_SETFL, flag); // Update flag // After these three steps, 0 becomes non blocking while (1) { // Read mouse memset(buf, 0, sizeof(buf)); ret = read(fd, buf, 50); if (ret > 0) { printf("The contents read by the mouse are:[%s].\n", buf); } // Read keyboard memset(buf, 0, sizeof(buf)); ret = read(0, buf, 5); if (ret > 0) { printf("The contents read by the keyboard are:[%s].\n", buf); } } return 0; }
Analysis of experimental phenomena: whether you move the mouse or the keyboard first, you can print information, but the CPU is always consumed here, and other processes can not get CPU scheduling, which reduces the CPU utilization.
2.IO multiplexing
O multiplexing usually needs the help of select or poll function, which is expressed in the form of external blocking, internal non blocking, automatic polling and multi blocking IO
External blocking means that the select/poll function is blocked externally, which is the most common blocking method. Both IOS are encapsulated in select/poll. Internal non blocking automatic polling means that within the package, the mouse and keyboard inputs are always in the mode of automatic polling, and who meets the conditions will output. Multi channel blocking IO means that the package of mouse and keyboard is still blocking io.
select function:
#include <stdio.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/select.h> #include <sys/time.h> int main(void) { // Read mouse int fd = -1, ret = -1; char buf[200]; fd_set myset; struct timeval tm; fd = open("/dev/input/mouse1", O_RDONLY); if (fd < 0) { perror("open:"); return -1; } // Currently, there are two FDS, one of which is 0 // Process myset FD_ZERO(&myset); FD_SET(fd, &myset); FD_SET(0, &myset); tm.tv_sec = 10; tm.tv_usec = 0; ret = select(fd+1, &myset, NULL, NULL, &tm); if (ret < 0) { perror("select: "); return -1; } else if (ret == 0) { printf("Timeout\n"); } else { // Wait until all the IOS arrive, and then monitor which IO arrives and deal with it if (FD_ISSET(0, &myset)) { // The keyboard is handled here memset(buf, 0, sizeof(buf)); read(0, buf, 5); printf("The contents read by the keyboard are:[%s].\n", buf); } if (FD_ISSET(fd, &myset)) { // Here we deal with the mouse memset(buf, 0, sizeof(buf)); read(fd, buf, 50); printf("The contents read by the mouse are:[%s].\n", buf); } } return 0; }
poll function:
#include <stdio.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <poll.h> int main(void) { // Read mouse int fd = -1, ret = -1; char buf[200]; struct pollfd myfds[2] = {0}; fd = open("/dev/input/mouse1", O_RDONLY); if (fd < 0) { perror("open:"); return -1; } // Initialize our pollfd myfds[0].fd = 0; // keyboard myfds[0].events = POLLIN; // Wait for read operation myfds[1].fd = fd; // mouse myfds[1].events = POLLIN; // Wait for read operation ret = poll(myfds, fd+1, 10000); if (ret < 0) { perror("poll: "); return -1; } else if (ret == 0) { printf("Timeout\n"); } else { // Wait until all the IOS arrive, and then monitor which IO arrives and deal with it if (myfds[0].events == myfds[0].revents) { // The keyboard is handled here memset(buf, 0, sizeof(buf)); read(0, buf, 5); printf("The contents read by the keyboard are:[%s].\n", buf); } if (myfds[1].events == myfds[1].revents) { // Here we deal with the mouse memset(buf, 0, sizeof(buf)); read(fd, buf, 50); printf("The contents read by the mouse are:[%s].\n", buf); } } return 0; }
3. Asynchronous IO
(1) What is asynchronous IO: asynchronous IO can be understood as a set of interrupt response system implemented by the operating system with software
(2) Working mode: we register an asynchronous IO event in the current process (use signal to register a SIGIO signal processing function), and then the current process can handle its own affairs normally. When an asynchronous event occurs, the current process will receive a SIGIO signal and execute the bound processing function to process the asynchronous event
(3) Functions involved:
fcntl(F_GETFL,F_SETFL,O_ASYNC,F_SETOWN)
signal or sigaction (SIGIO)
#include <stdio.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <signal.h> int mousefd = -1; // Bind to SIGIO signal and handle asynchronous notification events within the function void func(int sig) { char buf[200] = {0}; if (sig != SIGIO) return; read(mousefd, buf, 50); printf("The contents read by the mouse are:[%s].\n", buf); } int main(void) { // Read mouse char buf[200]; int flag = -1; mousefd = open("/dev/input/mouse1", O_RDONLY); if (mousefd < 0) { perror("open:"); return -1; } // Set the file descriptor of the mouse to accept asynchronous IO flag = fcntl(mousefd, F_GETFL); flag |= O_ASYNC; fcntl(mousefd, F_SETFL, flag); // Set the receiving process of asynchronous IO events as the current process fcntl(mousefd, F_SETOWN, getpid()); // Register the SIGIO signal capture function of the current process signal(SIGIO, func); // Read keyboard while (1) { memset(buf, 0, sizeof(buf)); read(0, buf, 5); printf("The contents read by the keyboard are:[%s].\n", buf); } return 0; }