操作系统IO相关知识

1. 操作系统涉及IO操作的宏观理解

说明:

  1. 用户程序读取io设备中的数据时(如磁盘,网卡),先由操作系统内核读取到内存(缓存页),用户程序读取到的是缓存页中的内容。
  2. 用户程序往io设备写数据时,修改的先是缓存页中的内容,需要定时把缓存页中的内容刷新flush到磁盘,不同的刷新策略在断电时数据丢失的多少不一样。
  3. 操作系统中有一个称为VFS(vistual file system虚拟文件系统)的树形结构,对应着Linux系统中的一个个文件。(Linux下一切皆文件)。
  4. fd和inode说明(每当进程用open()函数打开一个文件,内核便会返回该文件的文件操作符(一个非负的整形值),此后所有对该文件的操作,都会以返回的fd文件操作符为参数。 
  5. fd = open(pathname, flags, mode)
    // 返回了该文件的fd
    rlen = read(fd, buf, count)
    // IO操作均需要传入该文件的fd值
    wlen = write(fd, buf, count)
    status = close(fd)

  6. 每个文件系统会为存储于其上的所有文件(包括目录)维护一个i-node表,单个i-node包含以下信息:文件类型(file type),可以是常规文件、目录、套接字或FIFO,访问权限,文件锁列表(file locks),文件大小等
  7. 文件描述符可以理解为进程文件描述表这个表的索引,或者把文件描述表看做一个数组的话,文件描述符可以看做是数组的下标。当需要进行I/O操作的时候,会传入fd作为参数,先从进程文件描述符表查找该fd对应的那个条目,取出对应的那个已经打开的文件的句柄,根据文件句柄指向,去系统fd表中查找到该文件指向的inode,从而定位到该文件的真正位置,从而进行I/O操作。)
  8. 缓存页中的数据被称为脏数据(可能已经被应用程序修改)
  9. 当第二个进程操作同一个数据的时候,访问的是缓存页中的数据,不会从io中重新加载。
  10. 当访问的数据不同且数据不位于同一个缓存页的时候,将会从io中加载新的数据放入另一个缓存页
  11. 如何理解虚拟内存 - 知乎

2.linux操作文件系统常用命令

磁盘目录挂载

  1. df命令,查看目录挂载磁盘的情况,没有显示的目录默认挂在同/目录相同的磁盘
  2. df -h
  3. unmount命令,取消挂载
  4. mount命令  新增挂载

linux下常见文件类型

 linux文件类型的软连接和硬链接

相同点:一方修改,另一方同步修改

不同点:

硬链接是指向相同的inode号(相当于两个变量指向同一块内存区域),软连接指向不同的inode号

 创建硬链接时,内容引用数加1,创建软连接不加1.

创建硬链接

创建软连接(相当于一个快捷方式)

删除硬链接时,内容引用数减1,删除软连接时,指向的软连接爆红,表示不存在。

查看文件信息(inode号)

 创建能挂载指定目录的磁盘空间

1.创建一个空的指定大小的磁盘文件

2.将其转换为块文件

3.将其格式化为ext2格式文件

4.将其挂载到指定目录(当程序访问/mnt/ooxx的时候,就会到/dev/loop0中去寻找)

 where is 指令查找命令位置

whereis实用程序用于查找给定命令的二进制文件、源文件和手动文件

Linux中的Whereis命令,教你如何使用whereis命令及注意事项_Linux命令_云网牛站

 改变根目录的位置

前提条件是该目录下有/bin/bash文件在,且执行该命令后会执行bash命令

 查看当前进程的pid

$$是当前bash进程的pid 等同于 $BASHPID

显示当前进程加载了哪些文件

文件描述符中包含哪些东西?如何读取写入文件描述符

 

 

lsof -op $$(列出当前进程所打开的文件;)

重定向操作符的基本语法(每个命令都有标准012三个文件描述符)

 head 命令()展示文件前十行 

tail命令()展示文件后十行 

使用管道展示文件第8行

 父子进程通信问题 

父进程变量能否被子进程获取

 

程序从磁盘加载的过程:

从main方法开始,通过pc寄存器使用一条条指令创建类,创建变量执行。其中包含着通过mmu将虚拟内存指向物理内存地址

应用程序 --操作系统内核--磁盘交互方式

数据从磁盘加载到内存不再经过cpu,而是通过dma协处理器

首先明确:

内存被分为一个个4K大小的页,每个页的初始内容为空

应用程序想要读磁盘数据时,发起in80读中断,通过操作系统内核调用read函数,读取磁盘,并将读取结果放入内存中的缓存页中,被填充的缓存页被标记为dirty,发起中断将结果返回给应用程序。

应用程序想要往磁盘写数据时,发起in80写中断,通过操作系统内核调用write函数,修改内存中缓存页中的数据,但不一定立即将更改的缓存页数据刷新到磁盘,而是取决于应用程序或者操作系统的刷盘策略,这样做的好处是减少与磁盘的交互次数,提高程序的执行效率,缺点是因为没有立刻刷写数据到磁盘,可能造成断电时数据丢失。

刷写磁盘的时机:(刷盘后清除dirty标记)

1 满足指定的刷盘策略时机,这种情况下在空间足够的情况下刷盘后数据仍然在内存缓存页中,刷盘后数据清除dirty标记,直到数被再次修改。

2.因为缓存页空间不足引起的数据淘汰(lru算法,将最近最少使用的数据刷写到磁盘),这种情况下缓存页数据刷盘后淘汰,磁盘空间向前移动,在末尾继续写入缓存页

刷盘策略查看

sysctl -a |grep dirty

 修改默认的刷盘策略

示例:

 

strace命令(此处可以通过vi out.子进程号查看进程调用执行情况)

vi  out.2561

网络io模型演进

bio--->nio----->多路复用器(select--->poll------->epoll------->netty)

以上网络io模型解决了什么问题

客户端与服务端连接后,以何种方式处理连接的读写事件、不断压榨cpu的过程、

bio  同步阻塞模型,基于stream,基于多线程,浪费线程资源

nio  同步非阻塞模型,基于buffer和channel,通过设置configureblocking(false),可以实现单线程或者多线程,通过遍历所有的fd状态

epoll与selector

epoll的过程解释:

 

 1.服务器端创建serverSocket,发起3+1个调用(三个常规  socket bind listen,一个epoll特有  epoll_create{在内核中开辟一块空间}),对应关系看图2 

2.如果有客户端连接,就在这块内核空间中通过epoll_ctl方法将该fd放入一个红黑树的数据结构中。

3.如果客户端有数据需要读取,在数据被读入内核后,epoll进行延申处理,对比红黑树的fds,将有状态的fds复制到双向链表中(epoll特有)

4.当执行到select方法时,epoll,select和poll的对应系统调用是不同的,看上图

5.当有多个可读channel时,还有可能造成读阻塞,解决办法1:接收和处理分离,异步消息队列处理。如tomcat8    9

解决办法2:使用线程池多线程处理,如redis处理io时的io threads

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

塔◎

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值