3.6.1.非阻塞IO
3.6.1.1、阻塞与非阻塞
3.6.1.2、为什么有阻塞式
(1)常见的阻塞:wait、pause、sleep等函数;read或write某些文件时
(2)阻塞式的好处:有利于操作系统性能的发挥,
3.6.1.3、非阻塞
(1)为什么要实现非阻塞
(2)如何实现非阻塞IO访问:O_NONBLOCK和fcntl
3.6.2.阻塞式IO的困境
3.6.2.1、程序中读取键盘
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main(void)
{
char buf[100]; /* 定义一个buf */
memset(buf, 0, sizeof(buf));/* 清空 buf */
printf("before read \n");
//读取键盘
//键盘就是标准输入,stdin
read(0,buf,2); /* 从文件描述符 0 (0就是标准输入) 中 读取 2 个 字节,放到 buf 中 */
//read 这个函数默认是 阻塞的, 如果我们不按键盘的 话,程序一直阻塞在这里
printf("读出的内容是:[%s] \n", buf);
return 0;
}
运行结果:
3.6.2.2、程序中读取鼠标
1. 怎么找 鼠标的 设备文件 描述符
root@ubuntu:/home/aston# ls /dev/input/
by-id by-path event0 event1 event2 event3 mice mouse0 mouse1
cat /dev/input/mouse1 用cat 测试 mouse1
以上 是确定 mouse1 是鼠标的设备文件
代码:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(void)
{
char buf[100]; /* 定义一个buf */
int fd = -1;/* 定义设备文件描述符 */
fd = open("/dev/input/mouse1", O_RDONLY); /* open 打开mouse1 文件描述符, O_RDONLY 只读的文件打开 */
if (fd < 0) /* open 返回的 fd 小于 0,说明打开错误 */
{
perror("open:");
return -1;
}
memset(buf, 0, sizeof(buf));/* 清空 buf */
printf("before read \n");
//读取鼠标
read(fd,buf,5); /* 此时fd 就是 mouse1 ,从fd (mouse1)中 读取 5 个 字节,放到 buf 中 */
//read 这个函数默认是 阻塞的, 如果我们不按键盘的 话,程序一直阻塞在这里
printf("读出的内容是:[%s] \n", buf);
return 0;
}
运行结果:
3.6.2.3、程序中同时读取键盘和鼠标
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(void)
{
char buf[100]; /* 定义一个buf */
int fd = -1;/* 定义设备文件描述符 */
fd = open("/dev/input/mouse1", O_RDONLY); /* open 打开mouse1 文件描述符, O_RDONLY 只读的文件打开 */
if (fd < 0) /* open 返回的 fd 小于 0,说明打开错误 */
{
perror("open:");
return -1;
}
//读取鼠标
memset(buf, 0, sizeof(buf));/* 清空 buf */
printf("before 鼠标 read \n");
read(fd,buf,5); /* 此时fd 就是 mouse1 ,从fd (mouse1)中 读取 5 个 字节,放到 buf 中 */
//read 这个函数默认是 阻塞的, 如果我们不按键盘的 话,程序一直阻塞在这里
printf("鼠标读出的内容是:[%s] \n", buf);
//读取键盘
memset(buf, 0, sizeof(buf));/* 清空 buf */
printf("before 键盘 read \n");
read(0,buf,5); /* 从文件描述符 0 (0就是标准输入) 中 读取 2 个 字节,放到 buf 中 */
//read 这个函数默认是 阻塞的, 如果我们不按键盘的 话,程序一直阻塞在这里
printf("键盘读出的内容是:[%s] \n", buf);
return 0;
}
运行结果:
3.6.2.4、问题分析
当 程序中同时读取键盘和鼠标时,因为都是 阻塞 式 的, 只能按照 程序的顺序,先读取鼠标,在读取键盘, 我们实际使用时,并不是这样的,所有这是 阻塞式的 困境!!
3.6.3.并发式IO的解决方案: 鼠标 和 键盘 同时并发
3.6.3.1、非阻塞式IO
https://blog.csdn.net/liangzuzong/article/details/130536354
代码:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(void)
{
char buf[100]; /* 定义一个buf */
int flag = -1, fd = -1, ret = -1;
fd = open("/dev/input/mouse1", O_RDONLY | O_NONBLOCK); /* open 打开mouse1 文件描述符, O_RDONLY 只读的文件打开, O_NONBLOCK 非阻塞 属性 */
// 把 0 号文件描述符(标准输入stdio) ,变成非阻塞式
flag = fcntl(0, F_GETFL); /* 先获取 原来的 flag 。 F_GETFL 获取文件访问模式和文件状态标志*/
flag |= O_NONBLOCK; /* 添加 非阻塞 属性 */
fcntl(0, F_SETFL, flag); /* 更新 flag */
/* 以上这 3 步之后 ,标准输入0 ,就变成了 非阻塞式了 */
while(1)
{
//读取键盘
memset(buf, 0, sizeof(buf));/* 清空 buf */
ret = read(0,buf,5); /* 从文件描述符 0 (0就是标准输入) 中 读取 2 个 字节,放到 buf 中 */
//read 这个函数,标准输入 0 添加 O_NONBLOCK是 非 阻塞的,
if(ret > 0)
{
printf("键盘读出的内容是:[%s] \n", buf);
}
//读取鼠标
memset(buf, 0, sizeof(buf));/* 清空 buf */
ret = read(fd,buf,5); /* 此时fd 就是 mouse1 ,从fd (mouse1)中 读取 5 个 字节,放到 buf 中 */
//read 这个函数,fd(此时是鼠标) 添加 O_NONBLOCK是 非 阻塞的,
if(ret > 0)
{
printf("鼠标读出的内容是:[%s] \n", buf);
}
}
return 0;
}
运行结果: 缺点 性能不是最优!
3.6.3.2、多路复用IO
3.6.3.3、异步通知(异步IO)