Title: 《Unix环境编程》笔记:文件IO
Date: 2016-06-23 17:27:42
Category: 技术
Tags: 笔记, Linux
Slug: 《Unix环境编程》笔记:文件IO
Author: Lemon Tree

文件描述符

当进程需要打开或新建一个文件时,内核会将一个非负的整数返回给进程,这个用来标识文件的数就是文件描述符。
文件描述符0是进程的标准输入,1是标准输出,2是标准出错。
标准输入、标准输出、标准出错也被表示为STDIN_FILENO、STDOUT_FILENO、STDERR_FILENO。这些都定义在``中


部分函数[1]

open函数

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int oflag, .../*, mode_t mode*/);
  • pathname:打开或新建的文件名
  • oflag:以下常数定义在中。O_RDONLY、O_WRONLY、O_RDWR只能3选1,其他参数可以通过或运算一起构成oflag参数
    • O_RDONLY:只读
    • O_WRONLY:只写
    • O_RDWR:可读可写
    • O_APPEND:附加到文件尾
    • O_CREAT:若文件不存在则新建,需要指定第三个参数来说明文件的权限
    • O_EXCL:文件存在。如果同时指定了O_CREAT,而文件已经存在,则出错,否则新建文件
    • O_TRUNC:如果此文件存在,而且为只读或只写成功打开,则将其长度截短为0。
    • O_NOCTTY:如果pathname指的是终端设备,则不将此设备分配作为此进程的控制终端。
    • O_NONBLOCK:如果pathname指的是一个FIFO、一个块特殊文件或一个字符特殊文件,则此选择项为此文件的本次打开操作和后续的I/O操作设置非阻塞方式。

由open返回的文件描述符一定是最小的未用描述符数字。利用这个特性,可以在标准输入、标准输出和标准出错上打开文件。比如先关闭标准输出1,然后打开另一个文件,那该文件一定会在文件描述符1上打开。

creat函数

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int creat(const char *pathname, mode_t mode);

此函数等价于open(pathname, O_WRONLY | O_CREAT | O_TRUNC, mode);。creat函数以只写的方式打开文件。

close函数

#include <unistd.h>

int close(int filedes);
  • filedes:需要关闭的文件描述符

进程终止时,它所打开的所有文件都将有内核自动关闭,所以不需要手动去调用close函数关闭文件。关闭文件时也释放文件上的所有的锁。

lseek函数

#include <sys/types.h>
#include <unistd.h>

off_t lseek(int filedes, off_t offset, int whence);
  • offset:需要对文件进行的位移量,与whence的值相关。
  • whence:位移类型。
    • SEEK_SET:从文件开始处进行位移
    • SEEK_CUR:从当前位置进行位移,offset可正可负
    • SEEK_END:从文件尾进行位移,offset可正可负

当前文件位移量是一个非负整数,是文件开始到当前位置的字节数。当打开一个文件时,默认为0,除非指定O_APPEND。
可通过下面的方法确定一个打开文件的当前位移量,也可以用来确定文件是否可以设置位移量。如果文件描述符引用的是管道或FIFO,则lseek返回-1,并将errno设置为EPIPE。

off_t currpos;
currpos = lseek(fd, 0, SEEK_CUR);

如果文件位移量大于文件的长度,则在下一次写延长该文件,并在文件中形成空洞,没有写过的字节都被设为0。

read函数

#inlcude <unistd.h>

ssize_t read(int filedes, void *buff, size_t nbytes);
  • buff:从文件中读取的数据存放在buff中。
  • nbytes:需要读取的字节数

在度普通文件时,如果已经读到文件尾,则返回已读的字节数,在下次调用read的时候将返回0。

返回值:

  • 正数:读取的字节数
  • 0:文件尾
  • -1:出错

write函数

#include <unistd.h>

ssize_t write(int filedes, const void *buff, size_t nbytes);

写操作是从当前位移处开始的。如果指定了O_APPEND选项,则写到文件尾,位移量增加实际写的字节数。


文件共享

  • 进行write后,文件表中的当前文件位移量就是所写的字节数,如果超过了当前文件长度,则在v节点表中的当前文件长度被设置为当前文件位移量。
  • 如果用O_APPEDN标志打开了一个文件,则相关标志被写入文件表的文件状态标志,每次对文件执行写操作时,当前文件位移量首先被设置为i节点表中的文件长度,这样每次写的数据都被写入文件尾。
  • lseek函数只修改文件表中的当前文件位移量,没有进行任何I/O操作。
  • 若一个文件用lseek被定位到文件尾端,则文件表中的当前文件位移量被设置为i节点表中的当前文件长度**。

\- 完(废弃) -