文件I/O(2)

文件共享

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

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

与每一个文件描写叙述符相关联的是:

a)      文件描写叙述符标志

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

2)  内核为全部打开文件维持一张文件表。

每一个文件表项包括:

a)      文件状态标志(读、写、读写、添些、同步和堵塞等)

b)      当前文件偏移量

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

3)  每一个打开文件(或设备)都有一个v节点(v-node)结构。

v节点包括了文件类型和对照文件进行各种操作的函数的指针。对于大多数文件,v节点还包括了该文件的i节点。

i节点包括文件全部者、文件长度、文件所在的设备、指向文件实际数据块在磁盘上所在位置的指针等。

图1:打开文件的内核数据结构

假设两个进程各自打开了同一个文件,则如图2所看到的。

假定第一个进程在文件描写叙述符3打开上该文件。而还有一个进程在文件描写叙述符4上打开该文件。每一个进程都得得到一个文件表项,但对一个给定的文件仅仅有一个v节点表项。每一个进程都有自己的文件表项的一个理由是:使每一个进程都有自己对该问价的当前偏移量。

如今对前一节文件I/O(1)的几个操作进一步说明:

1.  完毕write之后,文件里当前偏移量即所添加的字节数。假设当前偏移量大于文件长度。则将i节点中当前文件长度设为当前文件偏移量。

2.  用O_APPEND打开一个文件,对应标志会被设置到文件状态标识中。每次写时,当前偏移量会被设置为i节点中的文件长度

3.  lseek定位到文件尾端时。则文件当前偏移量会被设置为当前文件长度。

可能有多个文件描写叙述符指向同一文件表项。调用dup和fork时都能看到这一点。

多个进程读同一文件能正确工作。但多个进程写同一文件时,可能产生预期不到的后果。能够利用原子操纵避免这样的情况。

原子操作

一般而言,原子操作指的是由多部组成的操作。假设该院自地运行,要么运行完所以步骤,要么一步也不运行。

1.      加入至一个文件

考虑一个进程。它要讲数据加入到一个文件尾端。

早期UNIX不支持open,所以能够例如以下实现:

if(lseek(fd, 0L, 2)<0)

err_sys(“lseekerror”);

if(write(fd, buf, 100) != 100)

err_sys(“writeerror”);

对于单个进程,这段程序能正常工作。

但多个进程就不一定。结社进程A和B都对同一文件进行加入操作。每一个进程都打开该文件。此时数据结构之间关系如图2中所看到的。

假定A调用lseek,将A的当前偏移量设置为1500。进程B执行lseek也将其当前偏移量设为1500。

然后B调用write,将当前偏移量增至1600。

然后内核又进行进程切换使进程A恢复执行,当A调用write时,从其当前偏移量1500处将数据写入。将替换B刚写入到该文件里的数据。

问题出在逻辑操作“定位到文件尾端处,然后写“使用了两个分开的函数调用。解决的方法是使这两个操作成为一个原子操作。O_APPEND标识,使内核每次对文件进行写之前。都将进程当前偏移量设置到该文件的尾端处。

2.pread和pwrite函数

原子性地定位搜索和运行I/0。

#include <unistd.h>

ssize_t pread(int fd, void *buf, size_tcount, off_t offset);

ssize_t pwrite(int fd, const void *buf,size_t count, off_t offset);

ssize_t pread(int fd, void *buf, size_tcount, off_t offset);

ssize_t pwrite(int fd, const void *buf,size_t count, off_t offset);

dup和dup2函数

#include <unistd.h>

int dup(int oldfd);

int dup2(int oldfd, int newfd);

上面两个函数都可用来复制一个现存的文件描写叙述符。

由dup返回的新文件描写叙述符一定是当前可用文件描写叙述符中的最小数值。用dup2则能够用newfd參数指定新描写叙述符的数值。假设newfd已经打开,则先将其关闭。假设newfd等于oldfd,则dup2返回newfd而不关闭它。

图3.3显示了这样的情况。

假定我们的进程运行了:

newfd = dup(1);

当此函数运行时,如果下一个可用的描写叙述符是3。由于这两个描写叙述符指向同一个文件表项。所以他们共享文件标志以及同一文件偏移量。

sync、fsync和fdatasync

#include <unistd.h>

void sync(void);

int fsync(int fd);

int fdatasync(int fd);

当将数据写入文件时。内核通常将数据拷贝到一个缓冲区。直到缓冲区写满。再将缓冲区排路输出队列。然后等待其到达队首,才进行实际的I/O操作。这样的输出防暑被称为延迟写。延迟写降低了磁盘的读写次数。但却降低了文件内容的跟新速度。当系统发生问题时,延迟写可能造成文件跟新内容的丢失。

为了保证磁盘上实际文件系统与缓冲区快速缓存中内容一致性。UNIX系统提供了sync、fsync和fdatasync 三个函数。

fcntl函数

#include <unistd.h>

#include <fcntl.h>

int fcntl(int fd, int cmd, ... /* arg */ );

能够改变已经打开文件的性质。

复制一个现有的描写叙述符(cmd=F_DUPFD)

获得或设置文件描写叙述符(cmd=F_GETFD|F_SETFD)

获得或设置文件状态标志(cmd=F_GETFL|F_SETFL)

获得或设置异步I/O全部权(cmd=F_GETOWN|F_SETOWN)

获得或设置记录锁(cmd=F_GETLK|F_SETLK、F_SETLKW)

能够用fcntl函数设置文件状态,经常使用设置套接字描写叙述符为非堵塞O_NONBLOCK

ioctl函数

#include <sys/ioctl.h>

int ioctl(int d, int request, ...);

提供了一个用于控制设备及其描写叙述符行为和配置底层服务的接口。

/dev/fd

打开文件/dev/fd/n等效于复制描写叙述符n。

文件I/O(2)的更多相关文章

  1. Mapreduce的文件和hbase共同输入

    Mapreduce的文件和hbase共同输入 package duogemap;   import java.io.IOException;   import org.apache.hadoop.co ...

  2. mapreduce多文件输出的两方法

    mapreduce多文件输出的两方法   package duogemap;   import java.io.IOException;   import org.apache.hadoop.conf ...

  3. 01.SQLServer性能优化之----强大的文件组----分盘存储

    汇总篇:http://www.cnblogs.com/dunitian/p/4822808.html#tsql 文章内容皆自己的理解,如有不足之处欢迎指正~谢谢 前天有学弟问逆天:“逆天,有没有一种方 ...

  4. SQL Server 大数据搬迁之文件组备份还原实战

    一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 解决方案(Solution) 搬迁步骤(Procedure) 搬迁脚本(SQL Codes) ...

  5. SQLSERVER将一个文件组的数据移动到另一个文件组

    SQLSERVER将一个文件组的数据移动到另一个文件组 有经验的大侠可以直接忽视这篇文章~ 这个问题有经验的人都知道怎麽做,因为我们公司的数据量不大没有这个需求,也不知道怎麽做实验 今天求助了QQ群里 ...

  6. SQL Server中的高可用性(2)----文件与文件组

        在谈到SQL Server的高可用性之前,我们首先要谈一谈单实例的高可用性.在单实例的高可用性中,不可忽略的就是文件和文件组的高可用性.SQL Server允许在某些文件损坏或离线的情况下,允 ...

  7. C# ini文件操作【源码下载】

    介绍C#如何对ini文件进行读写操作,C#可以通过调用[kernel32.dll]文件中的 WritePrivateProfileString()和GetPrivateProfileString()函 ...

  8. 【小程序分享篇 一 】开发了个JAVA小程序, 用于清除内存卡或者U盘里的垃圾文件非常有用

    有一种场景, 手机内存卡空间被用光了,但又不知道哪个文件占用了太大,一个个文件夹去找又太麻烦,所以我开发了个小程序把手机所有文件(包括路径下所有层次子文件夹下的文件)进行一个排序,这样你就可以找出哪个 ...

  9. 【原】Android热更新开源项目Tinker源码解析系列之二:资源文件热更新

    上一篇文章介绍了Dex文件的热更新流程,本文将会分析Tinker中对资源文件的热更新流程. 同Dex,资源文件的热更新同样包括三个部分:资源补丁生成,资源补丁合成及资源补丁加载. 本系列将从以下三个方 ...

  10. GreenDao 数据库:使用Raw文件夹下的数据库文件以及数据库升级

    一.使用Raw文件夹下的数据库文件 在使用GreenDao框架时,数据库和数据表都是根据生成的框架代码来自动创建的,从生成的DaoMaster中的OpenHelper类可以看出: public sta ...

随机推荐

  1. BZOJ4373: 算术天才⑨与等差数列(线段树 hash?)

    题意 题目链接 Sol 正经做法不会,听lxl讲了一种很神奇的方法 我们考虑如果满足条件,那么需要具备什么条件 设mx为询问区间最大值,mn为询问区间最小值 mx - mn = (r - l) * k ...

  2. css 中可以继承的属性

    CSS中可以和不可以继承的属性一.无继承性的属性 1.display:规定元素应该生成的框的类型 2.文本属性: vertical-align:垂直文本对齐 text-decoration:规定添加到 ...

  3. JSP内置对象——out对象/request对象

    在这个科技高速发展的时代,迫使我们的脚步一刻都不能停下. 在这个for循环语句当中,我们可以直接使用jsp内置对象中的out对象来给浏览器打印输出,那么这个out对象就是一个内置对象, 在这里,我们使 ...

  4. 自己来实现一套IOC注解框架

    我们自己来实现一套IOC注解框架吧,采用的方式反射加注解和Xutils类似,但我们尽量不写那么麻烦,也不打算采用动态代理,我们扩展一个检测网络的注解,比如没网的时候我们不去执行方法而是给予没有网络的提 ...

  5. 使用 Azure PowerShell 模块创建和管理 Windows VM

    Azure 虚拟机提供完全可配置的灵活计算环境. 本教程介绍 Azure 虚拟机的基本部署项目,例如选择 VM 大小.选择 VM 映像和部署 VM. 你将学习如何执行以下操作: 创建并连接到 VM 选 ...

  6. sql 经典面试题及答案(选课表)

    SQL数据库面试题以及答案 Student(Sno,Sname,Sage,Ssex) 学生表       Sno:学号:Sname:学生姓名:Sage:学生年龄:Ssex:学生性别Course(Cno ...

  7. SQL2005中的事务与锁定(九)-(1)- 转载

    ------------------------------------------------------------------------ -- Author : HappyFlyStone - ...

  8. 《SQL Server 2008从入门到精通》--20180716

    1.锁 当多个用户同时对同一个数据进行修改时会产生并发问题,使用事务就可以解决这个问题.但是为了防止其他用户修改另一个还没完成的事务中的数据,就需要在事务中用到锁. SQL Server 2008提供 ...

  9. fedora 中从命令行中直接打开资源管理器

    windows 中 使用 start . 可以实现 macos 中 使用 open . 可以实现 linux 中 可以使用 nautilus . 可以实现 了解nautilus 详细的使用说明,可以 ...

  10. Spark 基本概念 & 安装

    1. Spark 基本概念 1.0 官网 传送门 1.1 简介 Spark 是用于大规模数据处理的快如闪电的统一分析引擎. 1.2 速度 Spark 可以获得更高的性能,针对 batch 计算和流计算 ...