APUE(3)---文件I/O (2)

七.函数write

#include <unistd.h>
size_t write(int fd, const void *buf, size_t nbytes);
//若成功,返回已写字节数;若出错,返回-1

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

八、I/O的效率

  大多数文件系统为改善性能都采用某种预读(read ahead)技术。当检测到正进行顺序读取时,系统就试图读入比应用所要求的更多数据,并假想应用很快就会读这些数据。

九、文件共享

  UNIX系统支持在不同进程间共享打开文件。内核使用3种数据结构表示打开文件,他们之间的关系决定了在文件共享方面一个进程对另一个进程可能产生的影响:

1.每个进程在进程表中都有一个记录项,记录项中包含一张打开文件描述符表,可将其视为一个矢量,每个描述符占用一项。与每个文件描述符相关联的是:a.文件描述符标志(close_on_exec);b。只想一个文件表项的指针

2.内核为所有打开文件维持一张文件表。每个文件表项包含:a.文件状态标志(读、写、添写、同步和非阻塞等);b.当前文件偏移量;c.指向文件v节点表象的指针

3.每个打开文件和设备都有一个v节点结构。v节点包含了文件类型和对此文件进行各种操作函数的指针。对于大多数文件,v节点还包含了该文件的i节点,i节点包含了文件的所有者、文件长度、指向文件实际数据块在磁盘上所在位置的指针,这些信息是在打开文件时从磁盘上读入内存的并且随时可用的。

  当两个进程同时打开一个文件时,两个进程都获得一个各自的文件表项是因为这可以使每个进程都有它自己的对该文件的当前偏移量,但对一个特定的文件只有一个v节点表项。下面进一步说明:

1.在完成每一个write后,在文件表项中的当前文件偏移量即增加所写入的字节数。如果这导致当前文件偏移量超出了当前文件长度,则将i节点表项中的当前设置成为当前文件偏移量

2.如果用O_APPEND标志打开一个文件,则相应标志也被设置到文件表项的文件状态标志中。每次对这种具有追加写标志的文件执行操作时,文件表项中的当前文件偏移量首先会被i节点表项中的文件长度。这就使得每次写入的数据都追加到文件的当前尾端处。

3.若一个文件用lseek定位到文件当前的尾端,则将文件表项中的当前文件偏移量设置为i节点表项中的当前文件长度(lseek是一次性的,O_APPEND是重复的)

4.lseek函数至修改文件表项中的当前文件偏移量,不进行任何I/O操作。

  可能有多个文件描述符项指向同一个文件表项(dup函数),fork函数后,此时父进程、子进程各自的每一个打开文件描述符共享同一个文件表项。文件描述符标志只用于一个进程的一个描述符,文件状态标志则应用于指向该给定文件表项的任何进程中的所有描述符。

十、原子操作

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

1、追加到一个文件

  早期的UNIX本没有提供O_APPEND,追加操作只能通过lseek和write两个操作来完成,但是在这两个操作不是原子的,在多个进程同时操作一个文件时,可能发生A进程lseek到文件尾,B进程在文件尾写入了某些数据,这时A进程再写入,就可能覆盖B的数据。UNIX现在提供了O_APPEND操作来解决这个问题,在其内部的lseek和write是原子的,这样就能保证写入一定是结尾处。

2.函数pread和pwrite

  与追加不同的是,这是两个读写的加强版

3.创建一个文件

  对open函数现有O_CREAT和O_EXCL,当不存在要创建的文件时,创建文件,并成功返回;若文件已经存在,则返回,这是一个原子操作。如果没有这样一个原子操作,那莪们就只能先尝试去open,open失败再去create,但是在这两个操作间隙可能有其他操作创建了相应的文件,从而导致产生错误。

十一、函数dup和dup2

#include <unistd.h>
int dup(int fd);
int dup2(int fd, int fd2);
//若成功,则返回新的文件描述符,若失败,则返回-1

  dup每次返回的新文件描述符一定是当前可用文件描述符中的最小值。对于dup2,可以用fd2指定新描述符的值。如果fd2已经打开,则将其关闭。如fd等于fd2,则dup2返回fd2,而不关闭它。够则fd2的FD_CLOEXEC文件描述符标志就被清除,这样fd2在进程调用exec时是打开状态。并且dup和dup2返回的新文件描述符是共享一个文件表项,这就意味着他们共享:文件状态标志、文件偏移量等信息。dup2也是一个原子操作,相当于一个close加fcntl,二者有细微差别。

时间: 2024-07-29 22:36:09

APUE(3)---文件I/O (2)的相关文章

unix环境高级编程(第三版)中apue.h文件的配置问题

最近刚开始学习unix环境高级编程(第三版),其中有个作者自己写的apue.h文件,在这归总下相应的配置方法,希望对有需要的朋友们有所帮助 首先http://www.apuebook.com/code3e.html 上去下载相应的压缩包,注意自己书的版本. 下载完成之后,鉴于大多数朋友学习linux都是基于虚拟机的,所以顺便附上虚拟机与本地主机传输文件的方式 首先下载SSH Secure Shell 这个工具,然后直接点击quick connect, 弹出如下界面,输入虚拟机的ip地址,和登录用

【APUE】文件I/O

文件描述符 对于内核而言,所有打开的文件都通过文件描述符引用.文件描述符是一个非负整数. 按照惯例,UNIX系统shell使用文件描述符0与进程的标准输入相关联,文件描述符1与标准输出相关联,文件描述符2与标准错误输出相关联. open函数:打开或创建一个文件 #include <fcntl.h> int open(const char *pathname,int oflag,...); pathname是要打开或创建文件的名字,oflag参数用来说明此函数的多个选项 create函数:创建文

(一)一起学 APUE 之 文件 IO

. . . . . 最近在学习 APUE,所以顺便将每日所学记录下来,一方面为了巩固学习的知识,另一方面也为同样在学习APUE的童鞋们提供一份参考. 本系列博文均根据学习<UNIX环境高级编程>一书总结而来,如有错误请多多指教. APUE主要讨论了三部分内容:文件IO.并发.进程间通信. 文件IO: 标准IO:优点是可移植性高,缺点是性能比系统 IO 差,且功能没有系统 IO 丰富. 系统IO:因为是内核直接提供的系统调用函数,所以性能比标准 IO 高,但是可移植性比标准 IO 差. 并发:

c程序添加apue头文件

#include "apue.h" (c程序添加的头文件) 1. 超级用户权限登入 #cd /usr/include 2. 将apue.h和error.c两个文件copy到该目录下.(apue.h位于 your_apue_path/inlcude ; error.c位于your_apue_path/lib ) 以我的路径为例: #cp /root/apue.2e/inlcude/apue.h . #cp /root/apue.2e/lib/error.c . (实现apue.h中的出错

(三) 一起学 APUE 之 文件和目录

. . . . . 前面两篇博文讲了文件 IO 的基本操作,但是它们操作的都是文件本身所存储的有效数据.而文件系统保存文件的时候不仅仅要存储文件内的数据,还要存储许多亚数据,即文件属性和其它特征数据.这篇博文 LZ 就带领大家讨论文件系统亚数据的操作. 1.stat(2) 1 stat, fstat, lstat - get file status 2 3 #include <sys/types.h> 4 #include <sys/stat.h> 5 #include <u

[13]APUE:(文件)记录锁

[a] 概念 建议锁:在遵循相同记录锁规则的进程间生效,通常用于保证某个程序自身多个进程间的数据一致性 强制锁:意在保证所有进程间的数据一致性,但不一定有效:如不能应对先 unlink 后建立同名副本的行为 [b] fcntl #include <fcntl.h> int fcntl(int fd, int cmd, struct flock *flockp) //出错返回 -1  struct flock { short l_type; //锁类型:F_RDLCK / F_WRLCK / F

(二) 一起学 APUE 之 文件 IO

. . . . . 昨天我们讨论了标准 IO,今天主要说说系统 IO. 1.文件描述符 在 SYSIO 中贯穿了一个整形数,它就是文件描述符.对内核而言,所有打开的文件都是通过文件描述符引用的.它的作用与 STDIO 中的 FILE 结构体类似,但是它们的工作原理是完全不同的.它实际上是一个由内核保存的数组下标,所以不会是负数,下面我会用一张图来表示它的作用. 图1 SYSIO 文件描述符 图是在 Ubuntu 下好不容易找到了一个画图软件画的,质量不怎么样,小伙伴们先凑合着看吧. 我解释下图上

[03]APUE:文件 I/O

[a] open #include <fcntl.h> int open(const char *path, int oflag, ... ,mode_t mode) 成功返回文件描术符, 失败返回 -1 oflag: O_RDONLY / O_WRONLY / O_RDWR / O_EXEC / O_APPEND / O_CLOEXEC / O_CREAT / O_EXCL / O_NONBLOCK / O_NOFOLLOW / O_SYNC / O_TRUNC / O_DSYNC ...

APUE:文件和目录

文件权限有: S_IRWXU = S_IRUSR | S_IWUSR | S_IXUSR S_IRWXG = S_IRGRP | S_IWGRP | S_IXGRP S_IRWXO = S_IROTH | S_IWOTH | S_IXOTH 文件类型有: S_ISREG() // 普通文件 S_ISDIR() // 目录 S_ISCHR() // 字符特殊文件(设备) S_ISBLK() // 块特殊文件(设备) S_ISFIFO() // 管道或 FIFO S_ISLNK() // 符号链接

APUE:文件I/O

标准流描述符: /* Standard file descriptors. */ #define STDIN_FILENO 0 /* Standard input. */ #define STDOUT_FILENO 1 /* Standard output. */ #define STDERR_FILENO 2 /* Standard error output. */ 打开.创建.关闭文件: #define O_ACCMODE 0003 /* O_ACCMODE = O_RDONLY | O_W