文件描述符用于标识所有类型的已打开文件,包括管道、FIFO、socket、终端、设备和普通文件,
针对每一个进程,文件描述符都自成一套
标准文件描述符
文件描述符
|
用途
|
POSIX名称
|
stdio流
|
0
|
标准输入
|
STDIN_FILENO
|
stdin
|
1
|
标准输出
|
STDOUT_FILENO
|
stdout
|
2
|
标准错误
|
STDERR_FILENO
|
stderr
|
打开一个文件
-
#include <sys/stat.h>
-
#include <fcntl.h>
-
int open(const char *pathname, int flags, .../*mode_t mode*/);
-
/*Returns file descriptor on success, or -1 on error*/
1. 如果pahname是一个符号链接,会对其进行解引用
2. flag为位掩码,用户指定文件的访问模式
访问模式
|
描述
|
O_RDONLY
|
以只读方式打开文件
|
O_WRONLY
|
以只写方式打开文件
|
O_RDWR
|
以读写方式打开文件
|
这里需要注意的是,早期的UNIX实现中使用数字0、1、2,而非上表中的常量名称。大多数现代UNIX实现将这些常量定义为上述相应的数字,由此 O_RDWR != O_RDONLY| O_WRONLY。这三种方式只能使用一种,不能同时使用,初次之外,还可以与如下访问模式相或
状态标志
|
描述
|
O_APPEND
|
总在文件尾部追加数据
|
O_ASYNC
|
信号驱动I/O,党对于open()返回的fd可以实施I/O操作的时候,系统产生一个信号通知进程,仅对特定类型的文件有效,例如终端、fifos以及socket
|
O_CLOEXEC
|
避免fork()之后exec(),但没来得及fcntl()设置close-on-exec标志
|
O_CREAT
|
如果文件不存在,创建一个新的空文件。如果有此标志,必须提供mode参数
|
O_DIRECT
|
无系统缓冲的文件I/O操作
|
O_DIRECTORY
|
如果pathname并非目录,则返回错误
|
O_DSYNC
|
根据同步I/O数据完整性的完成要求来执行文件写操作
|
O_EXCL
|
此标志与O_CREAT标志结合使用表明:如果文件已经存在,则不会打开文件
|
O_LARGEFILE
|
支持以大文件方式打开文件
|
O_NOATIME
|
在读文件时,不更新文件的最近访问时间,要使用该标志,要么调用进程的有效用户id必须与文件的拥有者相匹配,要么进程需要拥有特权(CAP_FOWNER),否则,调用失败。
|
O_NOCTTY
|
如果打开的文件属于终端设备,该标志防止其成为控制终端
|
O_NOFOLLOW
|
在该标志被设置的时候,不解析符号链接
|
O_NONBLOCK
|
以非阻塞I/O打开文件
|
O_SYNC
|
以同步方式打开文件
|
O_TRUNC
|
如果文件已经存在且为普通文件,那么将清空文件内容,将其长度置0
|
位掩码参数mode制定了文件的访问权限,如果open()未指定O_CREAT标志,则可以省略mode参数。mode参数可以指定为数字(通常是8进制),更为可取的做法是对0个或多个下标中所列的位掩码常量进行逻辑或操作
常量
|
其他值
|
权限位
|
S_ISUID
|
04000
|
set-user-id
|
S_ISGID
|
02000
|
set-group-id
|
S_ISVTX
|
01000
|
sticky
|
S_IRUSR
|
00400
|
user-read
|
S_IWUSR
|
00200
|
user-write
|
S_IXUSR
|
00100
|
user-exec
|
S_IRGRP
|
00040
|
group-read
|
S_IWGRP
|
00020
|
group-write
|
S_IXGRP
|
00010
|
group-exec
|
S_IROTH
|
00004
|
other-read
|
S_IWOTH
|
00002
|
other-write
|
S_IXOTH
|
00001
|
other-exec
|
S_IRWXU
|
07000
|
|
S_IRWXG
|
00700
|
|
S_IRWXO
|
00007
|
|
读取文件内容
-
#include <unistd.h>
-
ssize_t read(int fd, void *buffer, size_t count);
-
/*returns number of bytes read, 0 on EOF, or -1 on error*/
count指定最多能读取的字节数,buffer参数提供用来存放输入数据的内存缓冲区地址
如果调用成功,返回实际读取的字节数,如果遇到文件结束EOF,则返回0,如果出现错误则返回-1.在中断读取字符,一遇到换行符(\n),read()调用就会结束
写入文件
-
#include <unistd.h>
-
ssize_t write(int fd, void *buffer, size_t count);
-
/*returns number of bytes written, or -1 on error*/
如果调用成功,返回实际写入文件的字节数。可能会比count小(磁盘已满等资源限制)
关闭文件
-
#include <unistd.h>
-
int close(int fd);
-
/*returns 0 on success, or -1 on error*/
关闭一个打开的fd,并将其释放毁调用进程,供该进程继续使用。当一个进程终止时,将自动关闭其已打开的所有文件描述符
改变文件偏移量
对于每一个打开的文件,
系统内核会记录其文件偏移量。文件偏移量是执行下一条read()或write()操作的文件起始的位置,会以相对于文件头部起始点的文件当前位置来表示
-
#include <unistd.h>
-
off_t lseek(int fd, off_t offset, int whence);
-
/*returns new file offset if successful, or -1 on error*/
-
/*不允许将其应用于管道、FIFO、socket或者终端*/
offset制定了一个以字节为单位的数值(有符号),whence表明应该参照哪个基点来解释offset参数{SEEK_SET, SEEK_CUR, SEEK_END},当为SEEK_SET的时候,offset必须非负
文件空洞:
如果程序的文件偏移量已经跨越了文件结尾,然后再执行I/O操作,read()会返回0,表示文件结尾;write()则可以在文件结尾后的任意位置写入数据。从文件结尾处到新写入数据间的这段空间被称为文件空洞。从编程角度看,文件空洞中是存在字节的,读取空洞将返回以0(空字节)填充的缓冲区。
然而
文件空洞不占用任何磁盘空间。直到后续某个点,在文件空洞中写入了数据,文件系统才会为之分配磁盘块。文件空洞的主要优势在于,与为实际需要的空字节分配磁盘块相比,稀疏填充的文件会占用较少的磁盘空间。coredump文件是包含空洞文件的常见例子
不支持文件空洞的文件系统会显式的将空字节写入文件。
空洞的存在意味着一个文件名义上的大小可能要比其占用的磁盘存储总量要大。向文件空洞中写入字节,内核需要为其分配存储单元,即使文件大小不变,系统可用磁盘空间将减小。
通用I/O模型以外的操作
-
#include <sys/ioctl.h>
-
int ioctl(int fd, int request, .../* argp */);
-
/*value returned on success depends on request, or -1 on error*/
reques参数制定了将在fd上执行的控制操作,具体设备的头文定义了可传递给request参数的常量,第三个参数可以是任意数据类型。
ioctl()会有移植性问题
阅读(6006) | 评论(0) | 转发(0) |