NIO知识点

一、NIO简介

1)Java BIO : 同步并阻塞(传统阻塞型),服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销。
在这里插入图片描述
2)Java NIO : 同步非阻塞,服务器实现模式为一个线程处理多个请求(连接),即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求就进行处理。
在这里插入图片描述

二、操作系统的几个概念

1、内核态和用户态

内核态:cpu可以访问内存的所有数据,包括外围设备,例如硬盘,网卡,CUP也可以将自己从一个程序切换到另一个程序。

用户态:只能受限的访问内存,且不允许访问外围设备,占用CPU的能力被剥夺。

为什么要有用户态和内核态?

因为需要限制不同的程序之间的访问能力, 防止他们获取别的程序的内存数据, 或者获取外围设备的数据, 并发送到网络, CPU划分出两个权限等级 – 用户态和内核态。

什么时候会发生内核态和用户态的切换?

【用户态在需要申请外部资源的时候会切换至内核态】。比如执行系统调用、发生中断、异常等,内核态执行完成会回退至用户态。

2、系统中断

在这里插入图片描述

中断的分类:

【中断源】是指能够引起中断的原因。一台【处理器】可能有很多中断源,但按其性质和处理方法,大致可分为如下五类:

  1. 机器故障中断,比如掉电。
  2. 程序性中断。现行程序本身的异常事件引起的,可分为以下三种:一是程序性错误,非法操作和除数为零等;二是产生特殊的运算结果,例如定点溢出;三是程序出现某些预先确定要跟踪的事件,跟踪操作主要用于程序调试。有些机器把程序性中断称为“异常”,不称为中断。
  3. IO-【输出设备】中断,IO中断。
  4. 外中断。来自控制台【中断开关】、计时器、时钟或其他设备,这类中断的处理较简单,实时性强。
  5. 调用管理程序。用户程序利用专用指令“调用管理程序”发【中断请求】,是用户程序和操作系统之间的联系桥梁。

系统中断有什么好处:

1、分时操作,解决CPU的快速处理和慢速IO设备的问题。

2、实时处理,word中可以一边打字一边做拼写检查。

3、故障处理,会优先处理故障。

3.DMA

DMA(Direct Memory Access,直接存储器访问) ,它允许不同速度的硬件装置来沟通,而不需要依赖于[ CPU ](https://baike.baidu.com/item/ CPU /120556)的大量中断负载。否则,CPU 需要从来源把每一片段的资料复制到暂存器,然后把它们再次写回到新的地方。在这个时间中,CPU 对于其他的工作来说就无法使用。

​ 当CPU需要访问外设(磁盘、网卡、usb)的数据时,将任务丢给DMA,有DMA负责利用总线将数据先拷贝到内存,DMA传输前,CPU要把总线控制权交给DMA控制器,而在结束DMA传输后,DMA控制器应立即把总线控制权再交回给CPU。传输结束后,发出中断信号,通知CPU。
在这里插入图片描述

简而言之就是解决不同设备运行速度带来的问题,CPU运行速度快等待其他设备就会浪费CPU资源。

4、数据结构位图bitmap:

有一个场景:需要你统计你的同事的一个月的打卡记录。

你要怎么做,创建三十几个变量,0代表没打卡,1代表已打卡?

事实上我们使用一个int能表示:

11111111 10101111 11111111 11111110

​ 一个int四个字节,就是三十二位,从第0位开始算第一天的打卡记录,那么有三十二位足够了,因为一个月最多也就31天。

​ 我们能很简单的看出他第10天和12天没有打卡。

三、NIO相关的系统调用

首先,每个客户端连接在Linux系统下,都有一个文件描述符fd与之对应,文件描述符有一个编号,不同的编号表示不同的连接。

文件描述符

比如我们执行系统调用,常见文件,打开文件等。

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
int creat(const char *pathname, mode_t mode);

flags:

O_RDONLY          以只读方式打开文件
O_WRONLY         以只写方式打开文件
O_RDWR              以读和写的方式打开文件
上面三个只能选择一个,下面的可以合理的任意组合:
O_CREAT             打开文件,如果文件不存在则建立文件
O_APPEND           强制write()从文件尾开始

mode:参数可选:

#define S_IRWXU 00700     文件所有者可读可写可执行
#define S_IRUSR 00400     文件所有者可读
#define S_IWUSR 00200     文件所有者可写
#define S_IXUSR 00100     文件所有者可执行
#define S_IRWXG 00070     文件用户组可写可读可执行
#define S_IRGRP 00040     文件用户组可读
#define S_IWGRP 00020     文件用户组可写
#define S_IXGRP 00010     文件用户组可执行
#define S_IRWXO 00007     其他用户可写可读可执行
#define S_IROTH 00004     其他用户可读
#define S_IWOTH 00002     其他用户可写

我们发现这两个系统调用(函数)有一个int类型的返回值,这个返回值就是文件描述符。

如同:

File file = new File("C://a.txt");

中的file。

1、select系统调用

select系统调用有一个重要参数,为fd文件描述符集合,即你要监听哪些文件描述符(哪些连接),这个文件描述符集合rset用一个bitmap位图表示,位图大小为1024,即最多只能监听1024个客户端连接。

​ 当发起系统调用时,会将rset拷贝到内核态,然后内核态监听有没有数据可以处理,监听的所有文件描述符都没有数据的话会一直阻塞,直到有数据时,将有数据的fd索引置一,然后返回给用户态

Select缺点:

  • 位图大小默认1024,有上限。
  • 每次都需要创建一个文件描述符位图并拷贝到内核态。
int select(int nfds, fd_set *readfds, fd_set *writefds,
                  fd_set *exceptfds, struct timeval *timeout);

  1. nfds:要检测的文件描述符数量,最大文件描述符加1。(避免遍历范围外的bitmap)
  2. readfds:指定了被读监控的文件描述符集ÿ
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值