阻塞IO,
当前进程因不满足一些条件,而被挂起,即阻塞,cpu改去服务其它进程,
read一个普通文件,就马上执行,read一个鼠标,可是鼠标没有动,于是就阻塞了,
阻塞的好处,
利于os性能的发挥,cpu发挥高,虽然个体的费了点时间,但是总的效率得到了提高,
阻塞在多路IO的时候,缺陷就出来了,比如2路IO分别要读键盘和鼠标,阻塞在鼠标,可是鼠标没动,然后键盘输入也没用,
非阻塞IO,如果涉及多路IO,最好就不要用阻塞IO,
默认都是阻塞方式,
实现非阻塞,
1,打开文件O_NONBLOCK,
2,fcntl函数,
读取键盘,标准输入,stdin,0,默认就是打开的,
read( 0, buf, 2 );
读取鼠标,
int fd = -1;
fd = open( “/dev/input/mouse1”, O_RDONLY );
read( fd, buf, 5 );
同时读取键盘和鼠标,
由于读取2者,都是阻塞方式的,
而且程序中有固有的先后顺序,我们需要配合,比如先动鼠标,然后动键盘,
阻塞有它的好处,也有它的不便之处,
#include <stdio.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int main(void) { // 读取鼠标 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 鼠标 read.\n"); read(fd, buf, 50); printf("鼠标读出的内容是:[%s].\n", buf); // 读键盘 memset(buf, 0, sizeof(buf)); printf("before 键盘 read.\n"); read(0, buf, 5); printf("键盘读出的内容是:[%s].\n", buf); return 0; }
非阻塞IO,如果没有读到东西,就立即返回,
改变标准输入为非阻塞式的,
flag = fcntl( 0, F_GETFL );
flag |= O_NONBLOCK;
fcntl( 0, F_SETFL, flag );
非阻塞打开鼠标,
fd = open( “/dev/input/mouse1”, O_RDONLY | O_NONBLOCK );
然后出现了一种结果,
从鼠标和键盘所读出的内容都是空的,因为来不及输入,
接着,做了一种改变,
把读鼠标和键盘放到一个while(1)中,
经过这次修改,结果看起来舒服多了
#include <stdio.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int main(void) { // 读取鼠标 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; } // 把0号文件描述符(stdin)变成非阻塞式的 flag = fcntl(0, F_GETFL); // 先获取原来的flag flag |= O_NONBLOCK; // 添加非阻塞属性 fcntl(0, F_SETFL, flag); // 更新flag // 这3步之后,0就变成了非阻塞式的了 while (1) { // 读鼠标 memset(buf, 0, sizeof(buf)); //printf("before 鼠标 read.\n"); ret = read(fd, buf, 50); if (ret > 0) { printf("鼠标读出的内容是:[%s].\n", buf); } // 读键盘 memset(buf, 0, sizeof(buf)); //printf("before 键盘 read.\n"); ret = read(0, buf, 5); if (ret > 0) { printf("键盘读出的内容是:[%s].\n", buf); } } return 0; }
常见的阻塞:wait、pause、sleep等函数;read或write某些文件时常见的阻塞:wait、pause、sleep等函数,它们本身就是阻塞的,
read或write阻塞与否,看你操作的对象是谁,
#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) { // 读取鼠标 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; } // 当前有2个fd,一共是fd一个是0 // 处理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("超时了\n"); } else { // 等到了一路IO,然后去监测到底是哪个IO到了,处理之 if (FD_ISSET(0, &myset)) { // 这里处理键盘 memset(buf, 0, sizeof(buf)); read(0, buf, 5); printf("键盘读出的内容是:[%s].\n", buf); } if (FD_ISSET(fd, &myset)) { // 这里处理鼠标 memset(buf, 0, sizeof(buf)); read(fd, buf, 50); printf("鼠标读出的内容是:[%s].\n", buf); } } return 0; }
这个是poll的示例代码
#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) { // 读取鼠标 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; } // 初始化我们的pollfd myfds[0].fd = 0; // 键盘 myfds[0].events = POLLIN; // 等待读操作 myfds[1].fd = fd; // 鼠标 myfds[1].events = POLLIN; // 等待读操作 ret = poll(myfds, fd+1, 10000); if (ret < 0) { perror("poll: "); return -1; } else if (ret == 0) { printf("超时了\n"); } else { // 等到了一路IO,然后去监测到底是哪个IO到了,处理之 if (myfds[0].events == myfds[0].revents) { // 这里处理键盘 memset(buf, 0, sizeof(buf)); read(0, buf, 5); printf("键盘读出的内容是:[%s].\n", buf); } if (myfds[1].events == myfds[1].revents) { // 这里处理鼠标 memset(buf, 0, sizeof(buf)); read(fd, buf, 50); printf("鼠标读出的内容是:[%s].\n", buf); } } return 0; }