1 文件描述符
所有打开的文件都通过文件描述符引用,文件描述符是一个非负整数,本质是一个数组下标。
当打开或创建一个文件的时候,内核向进程返回一个文件描述符。
open,creat返回文件描述符来标识该文件,将其作为参数传递给write和read。
UNIX系统shell使用文件描述符0与进程的标准输入相关联,1和标准输出相关联,2和标准错误输出相关联。:
2 open函数
打开一个文件
pathname是打开或创建文件的名字。
oflag说明次函数的多个选项:
O_RDONLY 只读打开 0
O_WRONLY 只写打开 1
O_RDWR 读、写打开 2
以上这三个参数必须且只能定义一个,下列常量是可选的
O_APPEND 每次写入时追加到文件尾部
O_CREAT 如果文件不存在,则创建。使用第三个参数来限制创建文件的权限。
O_EXCL 如果指定了O_CREAT,则如果存在该文件,则会出错。
O_TRUNC 如果只读或只写打开的文件存在,将其长度截短为0
O_NOCTTY 如果pathname指定的是终端设备,则不将该设备分配作为此进程的控制终端。
O_NONBLOCK 如果pathname指定的是一个FIFO,一个块特殊文件或一个字符特殊文件,则此选项为文本的本次打开操作和后续的I/O操作设置非阻塞模式。
以下参数是Single UNIX Specification
O_DSYNC 使每次write操作等待物理I/O完成,如果写操作不影响读取刚写入的数据,则不等待文件属性被更新
O_RSYNC 使以文件描述符为参数的read等待,直到任何对文件同一部分进行的未决写操作都完成。
O_SYNC 使每次write操作等待物理I/O完成。
3 creat函数
创建一个文件
词函数等同于
open(pathname, O_RDONLY | O_TRUNC | O_CREAT, mode);
这个函数的缺点是返回一个以只写打开的文件描述符,建议使用open函数来创建文件:
open(pathname, O_RDWR | O_CREAT | O_TRUNC, mode);
4 close函数
关闭一个打开的文件
关闭一个文件的同时关闭在该进程中为文件加上的所有记录锁。
*编程原则:谁打开谁关闭,谁申请谁释放
5 lseek函数
每打开一个文件的时候,都有一个与其相关的“当前文件偏移量”,用以度量从文件开始处计算的文件字节数。
按照系统默认情况,当文件打开时,除非指定O_APPEND选项,文件偏移量从0开始。
可以调用lseek来显示的为打开文件设置其偏移量。
以下是whence属性
SEEK_SET 将文件偏移量设置为距从文件开始处offset个字节
SEEK_CUR 将文件偏移量设置为从当前处到offset个字节,offset可以为正/负
SEEK_END 将文件偏移量设置为文件长度加offset
可以用下面的方式打开文件的偏移量
6 read函数
从打开的文件读取数据
ssize_t 带符号的整数
size_t 不带符号的整数
以下情况读到的字节数少于要求的字节数
1.在读到要求字节数之前已经读到文件结尾
2.当从终端设备文件读时
3.从网络读时
4.从管道或者FIFO读时
5.从某些面向记录的设备读时(磁带)
6.信号影响
读操作从文件的当前偏移量开始,读取完毕该偏移量加上读取的实际字节数
7 write函数
向打开的文件中写入数据
对于普通文件,write函数从文件的偏移量开始写,如果指定了O_APPEND选项,就从文件的结尾处开始写,在一次成功的写操作之后,该文件的偏移量加上实际写入的字节数
8 文件共享
内核使用三种数据结构来表示打开的文件,它们之间的关系决定了在文件共享方面一个进程对另一个进程可能产生的影响。
1.每个进程在进程表中都有一个记录项,记录项中包含一张打开文件描述符表,可将其视为一个矢量,每一个文件描述符占用一项,与每个文件描述符相关联的是:
a.文件描述符标志
b.指向一个文件表项的指针
2.内核为每个打开文件维持一个文件表,每个文件表含:
a.文件状态标志
b.当前文件偏移量
c.指向该文件v节点表项的指针
3.每打开一个文件都有一个v节点结构。包含了文件类型和对此文件进行各种操作的函数的指针。
如果有两个独立的进程各自打开了同一个文件,打开文件的每一个进程都将得到一个文件表项,但是对于一个给定的文件只有一个v节点表项。
这种安排使得每个进程都有它自己的对该文件的当前偏移量。
但是对于多个进程对同一文件进行写操作的时候就会产生不可预期的错误,所以要介绍原子操作。
9 原子操作
为了避免多进程操作同一文件会产生覆盖的影响,有如下函数,该函数首先操作lseek,然后在进行读写操作
10 dup和dup2
复制一个现存的文件描述符
#include <unistd.h>
int dup(int filedes);
int dup(int filedes, int filedes2);
//若正确,返回新的文件描述符,错误返回-1
由dup返回的文件描述符一定是当前可用的最小的文件描述读
dup2函数则用filedes2来指定新文件描述符,如果filedes2已经存在,则先将其关闭。若filedes2等于filedes则返回filedes2,而不关闭
11 sync, fsync, fdatasync函数
保证了磁盘上实际文件系统与缓冲区高速缓存中内容的一致性
sync将所有修改过的块缓冲区排入写队列,然后就返回,不等待实际写磁盘操作结束。
通常系统的守护进程update会定期调用sync,命令sync也是调用sync函数
fsync对文件描述符filedes指定的单一文件起作用,并且等待实际写磁盘操作结束。同时也会同步更新文件的属性。
fdtatsync和fsync类似,不过它值针对与数据部分。
12 fcntl函数
可以改变以打开文件的属性
fcntl的五种功能cmd
1.F_DUPFD 复制一个现有的文件描述符,与dup,dup2函数类似,返回一个文件描述符
2.F_GETFD或F_SETFD 获得/设置文件描述符标记,返回文件描述符标记
3.F_GETFL或F_SETFL 获得/设置文件状态标志,返回文件状态标志
O_RDONLY 只读打开
O_WRONLY 只写打开
O_RDWR 读写打开
O_APPEND 追加
O_NONBLOCK 非阻塞模式
O_SYNC 等待写完成(数据和属性)
O_DSYNC 等待写完成(数据)
O_RSYNC 同步读写
O_FSYNC 等待写完成
O_ASYNC 异步I/O
前三个访问标志是互斥的,因此首先必须使用屏蔽字O_ACCMODE取得访问模式位,在比较
4.F_GETOWN或F_SETOWN 获得/设置异步I/O所有权,返回一个正的进程ID或一个负的进程组ID
5.F_GETLF、F_SETLK或F_SETLKW 获得/设置记录锁
13 ioctl函数
I/O操作的杂物箱
在此原型中,我们表示的只是ioctl函数本身所要求的头文件。通常还需要另外的设备专用头文件<termios.h>
14 /dev/fd
在较新的系统都提供名为/dev/fd的目录。打开/dev/fd/n等效于复制描述符n
阅读(241) | 评论(4) | 转发(0) |
<script type=text/javascript charset=utf-8 src="http://static.bshare.cn/b/buttonLite.js#style=-1&uuid=&pophcol=3&lang=zh"></script> <script type=text/javascript charset=utf-8 src="http://static.bshare.cn/b/bshareC0.js"></script>
所有打开的文件都通过文件描述符引用,文件描述符是一个非负整数,本质是一个数组下标。
当打开或创建一个文件的时候,内核向进程返回一个文件描述符。
open,creat返回文件描述符来标识该文件,将其作为参数传递给write和read。
UNIX系统shell使用文件描述符0与进程的标准输入相关联,1和标准输出相关联,2和标准错误输出相关联。:
2 open函数
打开一个文件
- #include <fcntl.h>
- int open(const char * pathname, int oflag, ...);
- //若成功返回文件描述符,不成功返回-1
oflag说明次函数的多个选项:
O_RDONLY 只读打开 0
O_WRONLY 只写打开 1
O_RDWR 读、写打开 2
以上这三个参数必须且只能定义一个,下列常量是可选的
O_APPEND 每次写入时追加到文件尾部
O_CREAT 如果文件不存在,则创建。使用第三个参数来限制创建文件的权限。
O_EXCL 如果指定了O_CREAT,则如果存在该文件,则会出错。
O_TRUNC 如果只读或只写打开的文件存在,将其长度截短为0
O_NOCTTY 如果pathname指定的是终端设备,则不将该设备分配作为此进程的控制终端。
O_NONBLOCK 如果pathname指定的是一个FIFO,一个块特殊文件或一个字符特殊文件,则此选项为文本的本次打开操作和后续的I/O操作设置非阻塞模式。
以下参数是Single UNIX Specification
O_DSYNC 使每次write操作等待物理I/O完成,如果写操作不影响读取刚写入的数据,则不等待文件属性被更新
O_RSYNC 使以文件描述符为参数的read等待,直到任何对文件同一部分进行的未决写操作都完成。
O_SYNC 使每次write操作等待物理I/O完成。
3 creat函数
创建一个文件
- #include <fnctl.h>
- int creat(const char * pathname, mode_t mode);
- //若成功则返回一个以只写打开的文件描述符,失败返回-1
open(pathname, O_RDONLY | O_TRUNC | O_CREAT, mode);
这个函数的缺点是返回一个以只写打开的文件描述符,建议使用open函数来创建文件:
open(pathname, O_RDWR | O_CREAT | O_TRUNC, mode);
4 close函数
关闭一个打开的文件
- #include <unistd.h>
- int close(int filedes);
- //若成功返回0,错误返回-1
*编程原则:谁打开谁关闭,谁申请谁释放
5 lseek函数
每打开一个文件的时候,都有一个与其相关的“当前文件偏移量”,用以度量从文件开始处计算的文件字节数。
按照系统默认情况,当文件打开时,除非指定O_APPEND选项,文件偏移量从0开始。
可以调用lseek来显示的为打开文件设置其偏移量。
- #include <unistd.h>
- off_t lseek(int filedes, off_t offset, int whence);
- //若成功返回文件的偏移量,失败返回-1
SEEK_SET 将文件偏移量设置为距从文件开始处offset个字节
SEEK_CUR 将文件偏移量设置为从当前处到offset个字节,offset可以为正/负
SEEK_END 将文件偏移量设置为文件长度加offset
可以用下面的方式打开文件的偏移量
- off_t currpos;
- currpos = lseek(fd, 0, SEEK_CUR);
从打开的文件读取数据
- #include <unistd.h>
- ssize_t read(int filedes, void * buf, size_t nbytes);
- //若成功返回读到的字节数,若以到达文件结尾返回0,若出错返回-1
size_t 不带符号的整数
以下情况读到的字节数少于要求的字节数
1.在读到要求字节数之前已经读到文件结尾
2.当从终端设备文件读时
3.从网络读时
4.从管道或者FIFO读时
5.从某些面向记录的设备读时(磁带)
6.信号影响
读操作从文件的当前偏移量开始,读取完毕该偏移量加上读取的实际字节数
7 write函数
向打开的文件中写入数据
- #include <unistd.h>
- ssize_t write(int filedes, const void * buf, size_t nbytes);
- //若成功返回写入的字节数,若失败返回-1
8 文件共享
内核使用三种数据结构来表示打开的文件,它们之间的关系决定了在文件共享方面一个进程对另一个进程可能产生的影响。
1.每个进程在进程表中都有一个记录项,记录项中包含一张打开文件描述符表,可将其视为一个矢量,每一个文件描述符占用一项,与每个文件描述符相关联的是:
a.文件描述符标志
b.指向一个文件表项的指针
2.内核为每个打开文件维持一个文件表,每个文件表含:
a.文件状态标志
b.当前文件偏移量
c.指向该文件v节点表项的指针
3.每打开一个文件都有一个v节点结构。包含了文件类型和对此文件进行各种操作的函数的指针。
如果有两个独立的进程各自打开了同一个文件,打开文件的每一个进程都将得到一个文件表项,但是对于一个给定的文件只有一个v节点表项。
这种安排使得每个进程都有它自己的对该文件的当前偏移量。
但是对于多个进程对同一文件进行写操作的时候就会产生不可预期的错误,所以要介绍原子操作。
9 原子操作
为了避免多进程操作同一文件会产生覆盖的影响,有如下函数,该函数首先操作lseek,然后在进行读写操作
- #include <unistd.h>
- ssize_t pread(int filedes, void * buf, size_t nbytes, off_t offset);
- ssize_t pwrite(int filedes, const void * buf, size_t nbytes, off_t offset);
- //其返回值和read,write类似
复制一个现存的文件描述符
#include <unistd.h>
int dup(int filedes);
int dup(int filedes, int filedes2);
//若正确,返回新的文件描述符,错误返回-1
由dup返回的文件描述符一定是当前可用的最小的文件描述读
dup2函数则用filedes2来指定新文件描述符,如果filedes2已经存在,则先将其关闭。若filedes2等于filedes则返回filedes2,而不关闭
11 sync, fsync, fdatasync函数
保证了磁盘上实际文件系统与缓冲区高速缓存中内容的一致性
- #include <unistd.h>
- int fsync(int filedes);
- int fdatasync(int filedes);
- //若成功返回0,失败返回-1
- void sync(void);
通常系统的守护进程update会定期调用sync,命令sync也是调用sync函数
fsync对文件描述符filedes指定的单一文件起作用,并且等待实际写磁盘操作结束。同时也会同步更新文件的属性。
fdtatsync和fsync类似,不过它值针对与数据部分。
12 fcntl函数
可以改变以打开文件的属性
- #include <fcntl.h>
- int fcntl(int filedes, int cmd, ...);
- //若成功则返回值依赖于cmd,失败返回-1
1.F_DUPFD 复制一个现有的文件描述符,与dup,dup2函数类似,返回一个文件描述符
2.F_GETFD或F_SETFD 获得/设置文件描述符标记,返回文件描述符标记
3.F_GETFL或F_SETFL 获得/设置文件状态标志,返回文件状态标志
O_RDONLY 只读打开
O_WRONLY 只写打开
O_RDWR 读写打开
O_APPEND 追加
O_NONBLOCK 非阻塞模式
O_SYNC 等待写完成(数据和属性)
O_DSYNC 等待写完成(数据)
O_RSYNC 同步读写
O_FSYNC 等待写完成
O_ASYNC 异步I/O
前三个访问标志是互斥的,因此首先必须使用屏蔽字O_ACCMODE取得访问模式位,在比较
4.F_GETOWN或F_SETOWN 获得/设置异步I/O所有权,返回一个正的进程ID或一个负的进程组ID
5.F_GETLF、F_SETLK或F_SETLKW 获得/设置记录锁
13 ioctl函数
I/O操作的杂物箱
- #include <unistd.h> // System V
- #include <sys/ioctl.h> // BSD and linux
- #include <stropts.h> // XSI STREAMS
- int ioctl(int filedes, int request, ...);
- //若出错返回-1,成功返回其他值
在此原型中,我们表示的只是ioctl函数本身所要求的头文件。通常还需要另外的设备专用头文件<termios.h>
14 /dev/fd
在较新的系统都提供名为/dev/fd的目录。打开/dev/fd/n等效于复制描述符n