简介

Unix系统大多数文件i/o只需要:open、read、write、lseek、close这几个函数。但是某些时候我们也需要fcntl、ioctl、sync等函数配合使用。这些函数都是不带缓冲区的I/0(unbuffered I/O),

术语不带缓冲的指的是每个read和write都是内核中的一个系统调用。这些函数都是POSIX和single UNIX Specification的组成部分。

这样说可能有点迷糊,举个例子说明

不带缓存的I/O:       read,write,open......
标准(带缓存的)I/O: fgets,fread,fwrite.....

这里使用两个对应的函数进行比较:

ssize_t write(int filedes, const void *buff, size_t nbytes)
size_t fwrite(const void *ptr, size_t size, size_t nobj, FILE *fp)

上面的buff和ptr都是指应用程序自己使用的buffer,实际上当需要对文件进行写操作时,都会先写到内核所设的缓冲存储器。如果该缓存未满,则并不将其排入输出队列,直到缓存写满

或者内核再次需要重新使用此缓存时才将其排入磁盘I/O输入队列,再进行实际的I/O操作,也就是此时才把数据真正写到磁盘,这种技术叫延迟写。

1、如果我们直接用非缓存I/O对内核的缓冲区进行读写,会产生许多管理不善而造成的麻烦(如一次性写入过多,或多次系统调用导致的效率低下)。

2、标准(带缓存的)I/O为我们解决了这些问题,它处理很多细节,如缓冲区分配,以优化长度执行I/O等,更便于我们使用。

文件描述符

一切皆是文件”是 Unix/Linux 的基本哲学之一。不仅普通的文件,目录、字符设备、块设备、 套接字等在 Unix/Linux 中都是以文件被对待;它们虽然类型不同,但是对其提供的却是同一套操作界面。

 

对内核而言,所有打开的文件都是通过文件描述符引用的,文件描述符是一个非负的整数,当打开一个现有文件或创建一个新文件,内核向进程返回一个文件描述符。按照惯例,unix系统shell把文件描述符0与进程的标准的输入关联,

文件描述符1与标准的输出关联,文件描述符2与标准错误关联。幻数0,1,2虽然已被标准化,我们在使用的时候应该用STDIN_FILENO、STDOUT_FILENO、STDERR_FILENO符号代替以提高可读性

文件共享(摘抄UNIX环境编程)

unix系统支持在不同进程间共享打开的文件。

内核使用三种数据结果表示打开的文件。

(1)每个进程在进程表中都有一个记录项,记录项中包含有一张打开文件的描述符表,可将其视为一个矢量,每个描述符占用一项。

每个文件描述符相关连的是:

  • 文件描述符标志
  • 指向一个文件表项的指针。

(2)内核为所有打开文件维持一张文件表。每个文件表项包含:

  • 文件状态标志(包含读写,填写,同步,非阻塞等)
  • 当前文件偏移量
  • 指向该文件v节点表项的指针。

(3)每个打开的文件都有一个v节点结构。v节点包含了文件类型和对此文件进行各种操作的函数的指针。对于大多数文件,v节点还包括了该文件的i节点。这些信息是再打开文件时从磁盘上读入内存的。这些文件都是从磁盘读入内存的,所以可以快速使用这些参数。

note:Linux没有使用v节点,而是使用了通用的i节点。

此图为打开文件的内核数据结构,该进程有两个不同的打开文件,一个文件打开为标准输入,另一个打开为标准输出。

如果两个独立进程各自打开同一个文件,则有如图所示

我们假设第一个进程在文件描述符3打开该文件,而另一个进程在文件描述符4上打开该文件。打开该文件的每个进程都得到一个文件表项。但对一个给定的文件只有一个v节点表项。每个进程都有自己的一个文件表项,理由是每个进程都要有对一个文件的偏移量。

下面描述上图的产生事件:

  • 在完成每个write后,在文件表项中的当前文件偏移量增加所写的字节数,如果这是当前文件偏移量超过了当前的文件长度,则在i节点表项忠的当前文件长度被设置为当前文件偏移量。
  • 如果用O_APPEND标志打开一个文件,则相应标志也被设置到文件表现的文件状态标志中。每次对这种具有填写标志的文件执行写操作时候,在文件表项中的当前文件偏移量标志中,首先被设置为i节点表项忠的文件长度,这就似的每次写的数据都添加到文件的当前尾端。
  • 若一个文件用lseek函数丁文到文件的当前的尾端。则文件表项中的当前文件偏移量被设置为i节点表项中的当前文件长度。
  • lseek函数只修改文件表系那个忠的当前文件偏移量。没有进行任何io操作

可能有多个文件描述符指向同一个文件表项

fork 后也会发生同样的情况,此时父子进程对于每个打开文件描述符共享同一个文件表项。

note:文件描述符标志和恩见状态标志在作用域方面的区别。潜质只用与一个进程的一个进程描述符。而后者则使用语指向改给定文件表项的任何进程中的所有描述符。

当我们看到多个进程进行对一个文件同时操作的时候,这时候就产生了冲突,如何避免呢,那么就是下一节原子操作~

2017/4/5(2天一博客连载Unix环境编程)加油

Unix文件 I/O(不带缓冲区的)上的更多相关文章

  1. unix文件操作函数

    1. fopen函数 #include <stdio.h> FILE *fopen(const char *path, const char *mode) 返回:文件顺利打开后,指向该流的 ...

  2. 标准c库函数与Linux下系统函数库 区别 (即带不带缓冲区的学习)

    我们都知道,C语言在UNIX/Linux系统下有一套系统调用(系统函数),比如文件操作open().close().write().read()等,而标准C语言的库函数中也有一套对文件的操作函数fop ...

  3. Day17_105_IO_BufferWriter带缓冲区的字符输出流

    BufferWriter带缓冲区的字符输出流 * OutputStreamWriter(); 转换流,可以将文件字节输出流转换为文件字符输出流 * 代码: import java.io.*; publ ...

  4. Linux C 文件与目录4 将缓冲区数据写入磁盘

    将缓冲区数据写入磁盘 所谓缓冲区,是Linux系统对文件的一种处理方式.在对文件进行写操作时,并没有立即把数据写入到磁盘,而是把数据写入到缓冲区.如果需要把数据立即写入到磁盘,可以使用sync函数.用 ...

  5. Unix文件操作

    一.概述 Unix文件操作常用函数包括open.close.creat.lseek.dup.dup2.fcntl等, 其中open.creat. fcntl函数需要包含头文件<fcntl.h&g ...

  6. PHP+ajaxForm异步带进度条上传文件实例

    在使用ajaxForm方法之前,首先需要安装form.js的插件,网上有: 一.首先说用法,ajaxForm可以接收0或1个参数,该参数可以是一个变量.一个对象或回调函数,这个对象主要有以下参数: v ...

  7. JAVA之旅(二十五)——文件复制,字符流的缓冲区,BufferedWriter,BufferedReader,通过缓冲区复制文件,readLine工作原理,自定义readLine

    JAVA之旅(二十五)--文件复制,字符流的缓冲区,BufferedWriter,BufferedReader,通过缓冲区复制文件,readLine工作原理,自定义readLine 我们继续IO上个篇 ...

  8. 利用arcserver 自带tomcat实现上传shapefile、cad等文件,然后用soe解析。

    一.功能实现分析 1.soe中传入指定路径目录和文件名就能读取shp.cad并解析,然后返回JSON格式数据给flex端生成图形.(soe读取的是本地绝对路径) 2.所以首先要上传文件到soe发布所在 ...

  9. PSR-1之PHP代码文件必须以不带BOM的UTF-8编码

    BOM——Byte Order Mark,就是字节序标记 在UCS 编码中有一个叫做”ZERO WIDTH NO-BREAK SPACE“的字符,它的编码是FEFF.而FFFE在UCS中是不存在的字符 ...

随机推荐

  1. 20150817---成长日记1---DelayQueue&&Delayed&&Other

    今天第一次接触DelayQueue,源于项目中的话单解析入库的拆分线程中引入,首先简单了解一下DelayQueue: DelayQueue是一个无界阻塞队列,只有在延迟期满时才能从中提取元素.该队列的 ...

  2. BZOJ 3402: [Usaco2009 Open]Hide and Seek 捉迷藏(最短路)

    这个= =一看就是最短路了= = PS:最近有点懒 = = 刚才看到一道平衡树的裸题还嫌懒不去写= =算了等刷完这堆水题再去理= = CODE: #include<cstdio>#incl ...

  3. WPF - 监听判断键盘组合键的按下

    对于键盘事件PreviewKeyDown.PreviewKeyUp.KeyDown.KeyUp,在其中检查当次事件是哪个按键触发的很简单,只需要判断KeyEventArgs类型的事件参数e的Key属性 ...

  4. ucGUI的学习小结

    前言 做一个小项目时需要实现GUI及相关操作(响应按键).用的SoC的优点是功耗低,但是受限于硬件能力,之前的SDK里并没有对GUI有很好的支持.后面对GUI的界面外观还有一定的要求,就在网上搜了一下 ...

  5. error LNK2001: unresolved external symbol __beginthreadex

    解决方法: project->settings->C++>category->code generation->Use runtime library选Debug Mul ...

  6. 【Harmony】概述

      原文来自本人的微信公众号文章  系统工程实验室     引言 基于模型的系统工程(简称MBSE,英文全称Model based System Engineering )的实践至少需要三个维度的支撑 ...

  7. Java程序员入门:Java程序员面试失败的5大原因

    1 说得太少 尤其是那些开放式的问题,如"请介绍下你自己"或"请讲一下你曾经解决过的复杂问题".面试官会通过你对这些技术和非技术问题的回答来评估你的激情.他们也 ...

  8. jquery 日期获取

    来自:http://blog.csdn.NET/liujun198773/article/details/7554628  感谢 $(function(){ var mydate = new Date ...

  9. Struts2框架(8)---Struts2的输入校验

    Struts2的输入校验 在我们项目实际开发中在数据校验时,分为两种,一种是前端校验,一种是服务器校验: 客户端校验:主要是通过jsp写js脚本,它的优点很明显,就是输入错误的话提醒比较及时,能够减轻 ...

  10. 【js数据结构】栈解决括号不匹配问题

    栈可以用来判断一个算术表达式中的括号是否匹配. 思路:读取算术表达式,遇到左括号'{'.'['.'('压入栈,栈的特点是后入先出,所以当遇到右括号'}'.']'.')'的时候,取出栈顶元素,是否满足读 ...