文件共享

UNIX系统支持在不同进程中共享打开的文件,首先先用一幅apue的图来介绍一下内核用于I/O文件的数据结构:

如图所见,一个进程都会有一个记录项,记录项中包含有一张打开文件描述符表,每个描述符占用一项。

描述符包括:(a)文件描述符标志(fd标志),(b)指向一个文件表项的指针(文件指针)。

而文件表包括:(a)文件状态标志,(b)当前文件偏移量,(c)v节点指针

v节点包括:文件类型和对此文件进行各种操作的函数的指针,大部分v节点还包括年i节点(索引节点,第四章详细介绍)

如果两个进程各自打开同一个文件的话,文件表是的分开的,但v节点是共享的:

文件表分开是因为:使每个进程都有它自己的对该文件的当前文件偏移量。

这样,当多个进程写同一个文件时,就有可能出问题。Let me tell you why.

早期的UNIX没有O_APPEND追尾选项,所以写到文件的结尾是这样做的:

if (lseek(fd, 0L, 2) < 0) /* 定位到文件的末端 */

err_sys("lseek error");

if (write(fd, buf, 100) != 100) /* 追尾写100字节 */

err_sys("write error");

这样对单个进程来说是没有问题的。但是对于多个进程对同一个文件同时使用这种方法就会出错了。

比如A和B进程同时打开一个文件,假定A调用了lseek,它将进程A的该文件当前偏移量设置为1500字节(文件末尾处),然后内核切换B进程运行,B也是调用lseek也将该文件的当前偏移量设置为1500字节(文件末尾处,记住,每个进程并不是共享同一个当前文件偏移量的),然后B调用了write函数,将当前偏移量曾至1600字节。因为该文件的长度已经增加了,所以内核对v节点中的当前文件长度更新为1600。然后内核切回A进程,当A调用write时,就从当前文件偏移量(1500字节)处将数据写到文件中去,这样也就代换了进程B
刚写到该文件中的数据。

问题出在逻辑操作“先定位到文件尾端处,然后写“上,它使用了两个分开的函数调用。解决的方法就是使这两个操作变成一个操作(这也就叫做原子操作)。任何一个需要多个函数的操作都不可能是原子操作,因为在两个函数调用之间,内核都有可能临时挂起该进程(如上面所加假定的)。

UNIX提供了一种方法使这种操作成为原子操作,该方法就是在打开文件时设置O_APPEND标志。这就使内核每次对这种文件进行写之前,都将进程的当前文件偏移量设置到该文件的尾端处,于是每次写之前就不用再调用lseek。

一般而言,原子操作(atomic operation)指的时由多步组成的操作。如果该原子操作执行,则要么时执行完所有步骤,要么一步也不执行,不可能只执行所有步骤的一个子集。(只要理解原子是不可分的就行了)

第三章笔记待续。

《APUE》第三章笔记(3)的更多相关文章

  1. 《APUE》第三章笔记(2)

    read函数 调用read函数从打开的文件中读数据. #include <unistd.h> ssize_t read(int filedes, void *buf, size_t nby ...

  2. 《APUE》第三章笔记(1)

    以下内容是我看<APUE>第二版第三章的笔记,有错还希望指出来,谢谢. unbuffered I/O,跟buffered I/O相对,buffered I/O就是 ISO C标准下的标准输 ...

  3. 【转】《APUE》第三章笔记(4)及习题3-2

    原文网址:http://www.cnblogs.com/fusae-blog/p/4256794.html APUE第三章的最后面给出的函数,现在还用不着,所以,先留个名字,待到时候用着了再补上好了. ...

  4. 《APUE》第三章笔记(4)及习题3-2

    APUE第三章的最后面给出的函数,现在还用不着,所以,先留个名字,待到时候用着了再补上好了. dup和dup2函数:用来复制文件描述符的 sync函数,fsync函数和fdatasync函数:大致的功 ...

  5. HBase in Action前三章笔记

    近期接触HBase,看了HBase In Action的英文版.開始认为还行,做了些笔记.可是兴许看下去,越来越感觉到实战这本书比較偏使用上的细节,对于HBase的具体设计涉及得很少.把前三章的一些笔 ...

  6. 《HALCON数字图像处理》第三章笔记

    目录 第三章 HALCON图像处理基础 HALCON控制语句 HALCON算子 HALCON图像处理入门 HALCON图像读取 HALCON图像显示 图形窗口 图像显示 显示文字 HALCON图像转换 ...

  7. [ APUE ] 第三章 文件系统

    1. 文件描述符 打开或创建一个文件时,内核向进程返回一个文件描述符,当读.写一个文件时,用open()或creat()返回的文件描述符标识该文件,将其作为参数传递给write.read. stdin ...

  8. unix环境高级编程第三章笔记

    文件描述符 1.文件描述符的概念 对于内核而言,所有打开的文件都会用一个文件描述符来引用,打开或和创建一个新文件的时候,内核会给进程返回一个文件描述符,而当使用read write时,可以使用这个文件 ...

  9. Vue2.5开发去哪儿网App 第三章笔记 上

    1.  vue 生命周期函数 每个 Vue 实例在被创建之前都要经过一系列的初始化过程.例如,实例需要配置数据观测(data observer).编译模版.挂载实例到 DOM ,然后在数据变化时更新 ...

随机推荐

  1. RH442之Tuned优化方案

    系统优化 介绍: Tuned是监控并收集系统组件使用资源的守护进程,可根据收集信息动态调整系统,可调整CPU和网络资源的使用来提高活跃设备性能与不活跃设备电能消耗.通过tuned-adm中提供优化案例 ...

  2. IOS - view之间切换

    //进入下一页 - (IBAction)Go:(id)sender { TwoViewController *twoVC = [[TwoViewController alloc] init];//这里 ...

  3. IOS开发UIImage中stretchableImageWithLeftCapWidth方法的解释

    - (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCap ...

  4. Spring Bean Scope 有状态的Bean 无状态的Bean

    http://blog.csdn.net/anyoneking/article/details/5182164 在Spring的Bean配置中,存在这样两种情况: <bean id=" ...

  5. CAS认证(2):认证过程

    国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...

  6. chrome扩展——Postman

    今天须要測试一个http的接口,曾经都是使用java的httpClient工具jar,自己编写代码去调试,但这样的方式比較死板,每次都要执行一段代码...于是就像有没有类似的在线工具能够使用? 调查了 ...

  7. QT下自定义QQ聊天窗口tab控件

    1.用继承pushbutton派生类来实现tab按钮,里面加一个QPushbutton关闭按钮:(自定义类:CCustomTabButton) 2.多个tab按钮用QHboxLayout做容器: 3. ...

  8. BZOJ 2049: [Sdoi2008]Cave 洞穴勘測 LCT

    入门级LCT: 仅仅有 Cut Link 2049: [Sdoi2008]Cave 洞穴勘測 Time Limit: 10 Sec  Memory Limit: 259 MB Submit: 3073 ...

  9. 将默认的Netbeans中文版设置为英文界面

    问题:从官网下载的Netbeans不论是中文版还是英文版默认的操作界面都是中文,并且字体十分恶心. 原因:Netbeans 根据本地的操作系统自动设置界面语言,并且没有提供更改的功能. 目标效果:把N ...

  10. Android Studio 完美修改应用包名

    我们平时新建项目有些朋友可能当时就是随意写的一个包名,然后在项目过程中, 又感觉这个包名不太好,所以就要对包名进行修改,根据我们正常的修改方式,是这样的. 在种情况是只能修改最外层的那个名称, 如果我 ...