在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. [luogu] P4823 [TJOI2013]拯救小矮人(贪心)

    P4823 [TJOI2013]拯救小矮人 题目描述 一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决定搭一个人梯.即:一个小矮人站在另一小矮人的 肩膀上,知道最顶端的小矮人伸直胳膊可以 ...

  2. Mysql学习总结(34)——Mysql 彻底解决中文乱码的问题

    mysql 中常常出现对中文支持不友好的情况 常见的错误 "Illegal mix of collations for operation" 下面我们规整一下 mysql 数据库中 ...

  3. Mysql学习总结(33)——阿里云centos配置MySQL主从复制

    1.安装jdk1.8 首先确定没有安装过jdk 2.yum –y list java*查询系统自带的jdk安装包情况. 3.安装jdk1.8 4. 验证安装结果. 安装mysql 1. rpm -Uv ...

  4. ZOJ 3640

    很简单的概率题了 设dp[x]为能力值 为x时出去的期望 天数 #include <iostream> #include <cstdio> #include <cmath ...

  5. Android.mk添加本地程序和库的经常使用模版

    Android.mk添加本地程序和库的经常使用模版 Android中添加本地程序或者库.这些程序和库与其所在路径没有关系.仅仅与它们的配置文件Android.mk有关.Android.mk文件里可以主 ...

  6. leetcode第一刷_Reverse Linked List II

    翻转链表绝对是终点项目,应该掌握的,这道题要求的是翻转一个区间内的节点.做法事实上非常相似,仅仅只是要注意判定開始是头的特殊情况,这样head要更新的,还有就是要把翻转之后的尾部下一个节点保存好,要么 ...

  7. the process android.process.acore has stopped或the process com.phone。。。。

    模拟器一启动 The process android.process.acore has stopped unexpectedly 今天不知道怎么回事,模拟器一启动就狂报错, 模拟器已经重新安装过了, ...

  8. RSA in .net and dotnet core

    dotnet RSAParameters Struct https://docs.microsoft.com/zh-cn/dotnet/api/system.security.cryptography ...

  9. thinkphp项目上传到github,为什么缺少很多文件

    thinkphp项目上传到github,为什么缺少很多文件 问题: 把tp5项目push到码云(类似github)上,为什么没有thinkphp这个核心库? 然后我看了下码云和github上,官方的t ...

  10. hdoj--1260--Tickets(简单dp)

    Tickets Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Su ...