一,文件描述符、套接字和管道
对于内核而言,所有打开的打开的文件都通过文件描述符引用。文件描述符是一个非负整数。内核为每个进程维护一个结构体struct task_struct,可称为进程控制块(PCB: Process Control Block)或进程描述符,含有一个称为打开文件描述符表的子结构体。普通的文件、套接字和管道都被放入其中,这说明这三者都被抽象为文件,共同占用进程占用的打开文件描述符。
其中UNIX系统shell使用:
文件描述符0与进程的标准输入相关联;
文件描述符1与标准输出相关联;
文件描述符2与标准出错输出相关联。
二,文件I/O函数
1,open 函数可以打开或创建一个文件。
#include <fcntl.h>
int open(const char *pathname, int oflag, ... /* mode_t mode */ );
返回值:成功则返回文件描述符,出错则返回-1。
参数:
pathname:是要打开或创建文件的名字。
oflag:说明此函数的多个选项。可将它的选项进行“或”运算构成oflag。
O_RDONLY 只读打开。
O_WRONLY 只写打开。
O_RDWR 读、写打开。
这三个选项只能制定且必须一个。下列常量可选:
O_APPEND 每次都从文件尾端写。
O_CREAT 若文件不存在,则创建它。使用次选项必须带第三个参数。
O_EXECL 如果指定了O_EXECL,而文件存在,则会出错。可以用它测试一个文件是否存在,如果不存在,则创建它。
O_TRUNC 如果此文件存在,而且为只写或只读打开,则将其长度截短为0。
2,create函数创建一个文件
#include <fcntl.h>
int create(const char *pathname, mode_t mode);
返回值:成功则返回打开的文件描述符,出错则返回-1。
由于它只能以只写的方式打开所创建的文件,所以等效于:
open(pathname, 0_WRONLY | O_CREAT | O_TRUNC, mode);
3,close函数关闭一个打开的文件
#include <unistd.h>
int close(int filedes)
返回值:成功则返回打开的文件描述符,出错则返回-1。
如果一个进程没有调用close显示关闭,当进程终止时,内核会自动关闭它所有打开的文件。
4,lseek函数 为一个打开的文件设置偏移量
每个打开的文件都有一个与其关联的“当前文件偏移量”,它是一个非负整数,用以度量从文件开始处计算的字节数。默认情况下,打开一个文件,该偏移量被设置为0,除非制定了O_APPEND选项。
#include <unistd.h>
off_t lseek(int filedes, off_t offset, int whence)
返回值:成功则返回新的文件的偏移量,出错则返回-1。
参数:设置的偏移量offset与whence有关。
whence | 文件的偏移量设置为 | offset值 |
SEEK_SET | 文件开始处offset个字节 | 必须为正数 |
SEEK_CUR | 文件偏移量当前值加offset | 可正可负 |
SEEK_END | 文件长度加offset | 可正可负 |
如何确定当前打开文件的偏移量:
int curpose;
curpose = lseek(filedes, 0, SEEK_CUR);
也可以用来判断所涉及的文件是否可以设置偏移量。因为文件描述符引用的是一个管道、FIFO或网络套接字,则lseek返回-1,并将error设置为ESPIPE。
注意:lseek(file, 163840, SEEK_SET);如果文件偏移量大于文件的当前长度,对该文件的下一次写将加长该文件,并在文件中构成一个空洞,这些空洞不在磁盘上占用存储区,位于文件中但没有写过的字节都被读为0(即空洞都被读为0)。
5,read函数 从打开的文件读数据
#include <unistd.h>
ssize_t read(int filedes, void *buf, size_t nbytes);
返回值:
- 若成功返回读到的字节数;
- 若已到文件结尾返回0;
- 若出错返回-1。
实际读到的字节数有可能少于要求读的字节数 nbytes:
- 读取普通文件时,在读到要求字节数时已到达文件末尾。例如,若在到达文件末尾之前还有30个字节,而要求读100个字节,则read返回30,下一次再调用read时,它将返回0(文件尾端)。
- 当从终端设备读时,通常一次最多读一行。
- 当从网络读时,网络中的缓冲机构可能造成返回值小于所要求读的字节数。
- 当从管道或FIFO读时,如管道包含的字节少于所需的数量,那么read将只返回实际可用的字节数。
- 当某一信号造成中断,而已经读了部分数据量时。
6,write函数 向打开的文件写入数据
#include <unistd.h>
ssize_t write(int filedes, const void *buf, size_t nbytes);
返回值:
- 若成功返回已写入的字节数;
- 如出错返回-1。
返回值通常与参数nbytes的值相同,否则表示出错(比如缓冲区已满)。