在unix中可用的文件I/O函数包含打开文件,读文件,写文件等。

Unix系统中的大多数文件I/O须要用到5个函数:open,read,write,lseek,close.

这里要说明的是read,write的文件I/O都是不带缓冲的,所谓的不带缓冲意思是它们都是走的内核中的一个系统调用。

对于内核而言,全部打开的文件都是通过文件描写叙述符进行引用,文件描写叙述符是一个非负整数。当打开一个现有文件或创建一个新文件时,内核向进程返回一个文件描写叙述符。当读或写一个文件时。使用open,create返回文件描写叙述符标识该文件。然后把返回的文件描写叙述符作为參数传递给read,write。

普通情况下unix系统的shell使用文件描写叙述符0作为进程的标准输入,1为标准输出,2为标准错误输出,不同的shell版本号可能有所不同,与unix内核无关。

文件描写叙述符的范围是0~open_max 早期的unix系统规定每个进程最多使用20个文件描写叙述符。

open函数

由open返回的文件描写叙述符是一个最小的未被使用的描写叙述符数值。这一点被有些程序是如今在标准输入,输出,报错上打开新文件。

比方。一个程序先关闭标准输出,然后再打开还有一个文件。事实上我们能够通过dup2函数来实现控制在制定的文件描写叙述符上打开文件。

Creat函数

Creat的一个不足之处是它以仅仅读方式打开所创建的文件。

在open的老版本号中,假设要创建一个暂时文件,并要先写该文件。然后又要读该文件,则必须先调用creat,close,然后调用open.只是如今的新版本号open已经攻克了这些不便利。

Close函数

当关闭一个文件时还会释放该进程加在该文件上的全部记录锁(有关记录锁有关内容,能够查看博客关于记录锁的文章)。

当一个进程终止时,内核会自己主动关闭它打开的全部文件。

非常多程序利用了这一功能而不显示的调用close关闭打开的文件。

Lseek函数

每个打开的文件都有一个与其相关联的“当前文件偏移量”它一般是一个非负整数,用以度量从文件開始处计算的字节数。通常,读,写操作都从当前文件偏移量处開始,并使偏移量添加所读写的自己数,当打开一个文件的最初时候文件的偏移量为0.

一般,文件的当前偏移量应当是一个非负整数,可是。某些设备也可能同意负的偏移量。但对于普通文件。则其偏移量必须是非负值。由于偏移量可能是负值,所以在比較lseek的返回值时不能检測是否小于0而是測试它是否等于-1.

Lseek仅将当前的文件偏移量记录在内核中,它并不引起不论什么I/O操作。然后,该偏移量用与下一个读或是写操作。

文件偏移量能够大于文件的当前长度,在这样的情况下,对该文件的下一次写将加长该文件并在文件里造成一个空洞,这一定是同意的。

位于文件里但没有写过的字节都被读为0.

文件里的空洞并不要求在磁盘上占用存储区。详细处理方式与文件系统的实现有关,当定位到超出文件尾端之后写时,对于新写的数据须要分配磁盘块。可是对于源文件尾端和新開始写位置之间的部分则不须要分配磁盘块。

Read函数

如read成功,则返回读到的字节数。

如已到达文件结尾,则返回0.

有多重情况可使实际读到的字节数少于要求读的字节数:

·读普通文件时。在读到要求字节数之前已经到达了文件尾端。比如,若在到达文件尾端之前还有30个字节,而要求读100个字节。则read返回30,下一次再调用read时,它将返回0

·  当从终端设备读时,通常一次最多读一行

·  当从网络读时。网络中的缓冲机构可能造成返回值小于所要求读的字节数。

·  当从管道或FIFO读时,如若管道包括的字节少于所须要的数量。那么read将仅仅返回实际可用的字节数

·  当从某些面向记录的设备(比如磁带)读时。一次最多返回一个记录。

·  当某一信号造成中断,而已经读了部分数据量时,读操作从文件的当前偏移量处開始,在成功返回之前,该偏移量将添加实际读到的字节数。

Write函数

对于普通文件。写操作从文件的当前偏移量处開始。假设在打开该文件时,制定了append选项,则在每次写操作之前,将文件偏移量设置在文件的当前结尾处。在一次成功写之后。该文件偏移量添加实际写的字节数

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYnVnYWxs/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

文件共享

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

内核使用三种数据结构表示打开的文件,它们之间的关系决定了在文件共享方面一个进程对还有一个进程可能产生的影响。

(1)每一个进程在进程表中都有一个记录项,记录项中包括有一张打开文件描写叙述符表,可将其视为一个矢量。每一个描写叙述符占用一项。与每一个文件描写叙述符相关联的是:

(a)文件描写叙述符标志

(b)指向一个文件表项的指针。

(2)内核为全部打开文件维持一张文件表。每一个文件表项包括:

(a)文件状态标志(读,写。加入,同步和非堵塞等)。

(b)当前文件偏移量

(c)指向该文件v节点表项的指针

(3)每一个打开文件(或设备)都有一个v节点,v节点包括了文件类型和对照文件进行各种操作的函数的指针。

对于大多数文件,v节点还包括了该文件的i节点(索引节点)。这些信息是在打开文件时从磁盘上读入内存的,所以全部关于文件的信息都是高速可供使用的。比如。i节点包括了文件的全部这。文件长度。文件所在的设备。指向文件实际数据块在磁盘上所在位置的指针(linux没有使用v节点。而是使用了通用i节点结构。

尽管两种实现有所不同。但在概念上,v节点与i节点是一样的。

两者都指向文件系统特有的i节点结构)。创建v节点结构的目的是对在一个计算机系统上的多文件系统类型提供支持。

假设两个独立进程各自打开了同一个文件。我们假定第一个进程在文件描写叙述符3上打开该文件。而还有一个进程则在文件描写叙述符4上打开该文件。打开该文件的每一个进程都得到一个文件表项,但对一个给定的文件仅仅有一个v节点表项。每一个进程都有自己的文件表项的一个理由是:这样的安排使每一个进程都有它自己的对该文件的当前偏移量。

给出了这些数据结构后。如今对前面所述的操作做进一步说明

1.在完毕每一个write后。在文件表项中的当前文件偏移量即添加所写的字节数。假设这使当前文件偏移量超过了当前文件长度,则在i节点表项中的当前文件长度被设置为当前文件偏移量(也就是该文件加长了)。

2.假设已append标志打开了一个文件。则对应标志也被设置到文件表项的文件状态标志中。每次对这样的具有填写标志的文件运行写操作时,在文件表中的当前文件偏移量首先被设置为i节点表项中的文件长度。

这使得每次写的数据都加入到文件的当前尾端处。

3.若一个文件用lseek定位到文件当前的尾端。则文件表项中的当前文件偏移量被设置为i节点表项中的当前文件长度。

4.lseek函数仅仅改动文件表项中的当前文件偏移量,没有进行不论什么I/O操作

可能有多个文件描写叙述符项指向同一个文件表项。我们就能看到这一点。在fork后也会发生相同的情况,次时父,子进程对于每个打开文件描写叙述符共享同一个文件表项。

注意,文件描写叙述符标志和文件状态标志在作用域方面的差别,前者仅仅用于一个进程的一个描写叙述符,而后者则适用于指向该给定文件表项的不论什么进程中的全部描写叙述符。

对于多个进程读同一个文件都能正确工作。

每一个进程都有它自己的文件表项。当中也有它自己的当前文件偏移量。可是,当多个进程同一时候写同一个文件时,则可能产生预期不到的结果。

我们会在单独的文章中,描写叙述多个个进程写的情况。

unix中文件I/O的更多相关文章

  1. UNIX中的文件类型

    Unix的文件类型信息包含在stat结构的st_mode成员中可以用宏确定文件类型: 普通文件(S_ISREG()):包含某种形式数据的常用文件类型 目录文件(S_ISDIR()):这种文件包含其他文 ...

  2. 今天在Mac机器上使用了Flex Builder编辑了一个源代码文件,保存后使用vim命令去打开时发现系统自动在每一行的结尾添加了^M符号,其实^M在Linux/Unix中是非常常见的,也就是我们在Win中见过的/r回车符号。由于编辑软件的编码问题,某些IDE的编辑器在编辑完文件之后会自动加上这个^M符号。看起来对我们的源代码没有任何影响,其实并不然,当我们把源代码文件Check In到svn之类

    今天在Mac机器上使用了Flex Builder编辑了一个源代码文件,保存后使用vim命令去打开时发现系统自动在每一行的结尾添加了^M符号,其实^M在Linux/Unix中是非常常见的,也就是我们在W ...

  3. 在linux/unix中查找大文件

    在linux/unix中查找大文件,如查找大于100M文件的位置路径,查找等于10M文件的位置路径等等,下面就介绍几个实现快速查找的命令: 1. 查找指定目录下所有大于100M的文件,命令为 find ...

  4. 如何理解“Unix 里一切都是文件”这句话-在 UNIX 中,一切都是字节流

    UNIX 操作系统的设计.用户界面.文化和演变都是建立在它的一套统一的想法和概念上.其中最重要的一点可能是“一切皆文件”,而这个概念被认为是 UNIX 的灵魂之一. 这一关键设计原则提供了一个统一的范 ...

  5. [译] 在 UNIX 中,一切皆文件

    原文地址:In UNIX Everything is a File 原文作者:ph7spot.com 译文出自:掘金翻译计划 本文永久链接:github.com/xitu/gold-m… 译者:pmw ...

  6. MATLAB中文件的读写和数据的导入导出

    http://blog.163.com/tawney_daylily/blog/static/13614643620111117853933/ 在编写一个程序时,经常需要从外部读入数据,或者将程序运行 ...

  7. 在linux下,去除^M,将windows格式文件(dos文件)改为unix格式文件

    在Windows系统下编辑的文件,换行符回车的格式为'\r\n',在linux系统下,回车的格式为'\n',在Windows下编辑的文本文件在上传至linux服务器时,回车'\r\n'就显示成^M+' ...

  8. 使用 ACE 库框架在 UNIX 中开发高性能并发应用

    使用 ACE 库框架在 UNIX 中开发高性能并发应用来源:developerWorks 中国 作者:Arpan Sen ACE 开放源码工具包可以帮助开发人员创建健壮的可移植多线程应用程序.本文讨论 ...

  9. java中文件的I/O操作

    java中文件的读写操作 (一) (1)java中文件的字节转成字符读操作 FileInputStream fStream = new FileInputStream("test.txt&q ...

随机推荐

  1. linux查看前几条命令记录

    1.按上下箭头键2.history|more分页显示3.vi /etc/profile找HISTSIZE=1000,说明你最多能存1000条历史记录.4.!!执行最近执行的命令5.history|he ...

  2. vue 表格数据编辑,点击取消或者完成按钮后,关闭编辑状态没有及时生效

    点击编辑按钮: 编辑状态下,表格可以编辑.但是点击“确认”或者“取消”按钮,列数据编辑状态已经修改,但是视图没有改变. 页面代码: 获取当前行的index,并直接修改当前行用于判断是否编辑状态的数据为 ...

  3. JS中Math函数基础

    Math 是数学函数,但又属于对象数据类型 typeof Math => ‘object’

  4. Nginx 项目部署和配置

    nginx 作为代理服务器,需要代理多个项目的话配置如下: server { listen       80; server_name  localhost; #charset koi8-r; #ac ...

  5. ASP.NET-未解决的问题

    001.((FormsIdentity)User.Identity).Ticket.UserData 用ASP.NET后台格式化成json数据后传回去的数据有&quot这样的符号 002.HT ...

  6. 关闭 sftp

    vi /etc/ssh/sshd_config 注释掉这行Subsystem  sftp    /usr/libexec/openssh/sftp-server /etc/rc.d/init.d/ss ...

  7. 使用ViewPager实现广告滑动效果

    效果图:               watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvSk1DNjAx/font/5a6L5L2T/fontsize/400/ ...

  8. 模拟实现Spring IoC功能

    为了加深理解Spring 今天自己写了一个模拟的Spring.... 步骤: 1.利用jdom解析bean.xml(pull,sax也能够,我这里用了jdom) 2.先解析全部的<bean/&g ...

  9. Zorka监控平台的Online reconfiguration基本效果展示

    在上一篇日志中,我简介了Zorka的Online reconfiguration的用法,可是没怎么介绍如何看到在线更改的效果,这里简单说说. 还是以之前的tomcat为例,我们在文件夹zorka\sc ...

  10. CxImage动态加载图片(判断图片文件类型)

    1.打开一张图可以通过创建一个新的CxImage对象来完成,通过构造函数来打开一张图CxImage::CxImage(const char * filename, DWORD imagetype)其中 ...