深入了解IO

什么是IO

IO是输入input输出output的首字母缩写形式,直观意思是计算机输入输出,它描述的是计算机的数据流动的过程,因此IO第一大特征是有数据的流动;

另外,对于一次IO,它究竟是输入还是输出,是针对不同的主体而言的,不同的主体有不同的描述。例如,甲乙两人交谈,甲将大脑中的想法通过声带震动,继而通过声波传入乙的耳朵,乙通过耳膜的震动再由神经将信号解析到大脑,这个数据流动的过程对甲而言是输出,对乙而言是输入。

从直观层面理解IO的话:
IO就是计算机与外部设备之间的一次 数据流动过程,IO的本体是一个有使用意义的可运行的电脑,有了主机后还要有外设,外设为显示器,键盘,鼠标等。(即输入设备,输出设备)(这段话可以理解为,IO其实就是输入输出设备与主机之间的数据流动)

从计算机构架角度理解IO:

任何涉及到计算机核心(cpu和内存)与其他设备之间的数据转移过程就是IO。

从编程角度理解IO:

IO的主体是其应用过程的运行态,即进程。

IO过程分为IO调用和IO执行。IO调用是由进程发起,IO执行是操作系统的工作。

IO调用是应用程序对操作系统IO功能的一次触发,目的是将进程的内部数据迁移到外部(即输出),或者将外部的数据迁移到进程的内部(即输入)。

IO调用中输入的一次过程:

1.进程向操作系统请求外部数据

2.操作sys将外部数据加载到内核缓冲区。

3.操作sys将数据从内核缓冲区拷贝到进程缓冲区

4.进程读取数据后继续后面的工作。

IO执行是操作sys的工作

if进程发起了读取数据的IO调用,操作sys需要将外部数据拷贝到进程缓冲区,在有数据拷贝到进程缓冲区前,进程缓冲区处于不可读状态,我们称之为操作IO未就绪,而是可以做其他的事情,这是,我们称其为非阻塞IO,对于非阻塞IO,在编程时要轮询就绪状态。

流的概念:

在C中引入了流(stream)的概念。它将数据的输入输出看作是数据的流入和流出,这样不管是磁盘文件或者是物理设备(打印机、显示器、键盘等),都可看作一种流的源和目的,视他们为同一种东西,而不管其具体的物理结构,即对他们的操作,就是数据的流入和流出。

这种把数据的输入输出操作对象,抽象化为一种流,而不管它的具体结构的方法很有利于编程,而涉及流的输出操作函数可用于各种对象,与其具体的实体无关,即具有通用性。

标准IO和文件IO的区别

1.标准IO的定义:在c库中定义的一组用于输入输出的函数接口。

文件IO的定义:在系统中定义的一组用于输入输出的函数接口。

2.标准IO存在缓冲区,可以减少系统调用。

文件IO没有缓冲区,每次都要系统调用。

3. 标准IO具有一定的可移植性,是因为它是一个标准函数包和stdio.h头文件中的定义,也就是说当它拿 到 别的系统时,稍微改一下编译文件,便可以在新的系统上运行。文件IO的文件操作符在其他sys.(系统的缩写,个人习惯)中可能并不能得到认可,所以,文件IO就没有一定的可移植性。

4. 标准IO围绕流进行操作,流用FILE * 描述。默认打开三个流:stdin(标准输入)、stdout(标准输 出)、stderr(标准错误)。 文件IO围绕文件描述符进行操作,默认打开三个文件描述符:0(标准输 入)、1(标准输入)、2(标准错误)。

FILE实际上包含了为管理流所需要的所有信息:

1.实际I/O的文件描述符(例:FILE *fp,其中fp就是实际文件描述符,fp指的标准输出,标准输入,标准错误(0,1,2))

2.指向流缓存的指针(标准I/O缓存,由malloc分配,又称为用户态进程空间的缓存,区别于内核所设的缓存),

3.缓存长度,当前在缓存中的字节数,出错标志等。

标准I/O对每个I/O流自动进行缓存管理,它提供了三种类型的缓存:

1.全缓存:

当填满标准I/O缓存后才执行I/O操作。磁盘上的文件通常是全缓存的。

2.行缓存:

当输入输出遇到新行符或缓存满时,才由标准I/O库执行实际I/O操作。stdin、stdout通常是行缓存的。

3.无缓存:

相当于read、write了。stderr通常是无缓存的,因为它必须尽快输出。

int fflush(FILE *stream),其中stream是要冲洗的流,可以实时将缓存区里面的东西刷新出来。

注释1: 在linux的缓存IO机制中,操作系统会将IO的数据缓存在文件系统的页缓存(page cache)中,也就是说,数据会先被拷贝到操作系统内核的缓存区中,然后才会从操作系统内核的缓存区拷贝到应用程序的地址空间。标准I/O库在关闭流的时候自动释放缓存。

另外,也可以使用函数fflush()将流所有未写的数据送入(刷新)到内核(内核缓冲区),fsync()将所有内核缓冲区的数据写到文件(磁盘)

注释2:标准IO是从内核缓存区将数据拷贝到用户缓存区,再从用户缓存区将数据写入文件或者设备。而所谓的提高了系统的调用意思是系统不用一次又一次的将数据放入内核缓存区,从而减轻了系统的工作量。

文件IO是将数据直接从内核缓存区写入到文件或者是设备。所以,他需要一次又一次的从内核空间进行数据的输入输出,系统调用的次数会很多,增加了系统的工作量。

另外,对于linux整体构架的理解也有益于对IO过程的理解

系统调用:

linux内核中设置了一组用于实现各种系统功能的子程序,称为系统调用。随Linux核心还提供了一些C语言函数库,这些库对系统调用进行了一些包装和扩展,因为这些库函数与系统调用的关系非常紧密,所以习惯上把这些函数也称为系统调用。系统调用将Linux整个体系分为用户态和内核态(或者说内核空间和用户空间)

内核态

其实从本质上说就是我们所说的内核,它是一种特殊的软件程序,特殊在哪儿呢?控制计算机的硬件资源,例如协调CPU资源,分配内存资源,并且提供稳定的环境供应用程序运行。

用户态(应用程序)

就是提供应用程序运行的空间,为了使应用程序访问到内核管理的资源例如CPU,内存,I/O。内核必须提供一组通用的访问接口,这些接口就叫系统调用。

库函数

库函数就是屏蔽这些复杂的底层实现细节,减轻程序员的负担,从而更加关注上层的逻辑实现。它对系统调用进行封装,提供简单的基本接口给用户,这样增强了程序的灵活性。

当然对于简单的接口,也可以直接使用系统调用访问资源,例如:open(),write(),read()等等。

库函数根据不同的标准也有不同的版本,例如:glibc库,posix库

shell

它是一种特殊的应用程序,俗称命令行。为了方便用户和系统交互,一般一个shell对应一个终端,呈现给用户交互窗口。当然shell也是编程的,它有标准的shell语法,符合其语法的文本叫shell脚本。很多人都会用shell脚本实现一些常用的功能,可以提高工作效率。

linux 进程的运行状态

当应用程序进行系统调用的时候,进程运行状态会发生变化,进程会从运行态变为内核态,当调用完成后,则从内核态变为运行态。

内核态:进程运行在内核空间

运行态:进程运行在用户空间

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值