天天看点

Linux文件IO详解文件IO

文件IO

不带缓存的IO函数:

open

,

read

,

write

,

lseek

close

。每个函数对应内核的一个系统调用,这些函数不是C语言标准,但属于POSIX接口。

文件描述符

对Linux而言,所有的打开文件都由文件描述符引用。文件描述符是一个非负整数。当用

open

,

creat

打开文件时,返回文件描述符,对文件的读写操作通过文件描述符进行。

按照惯例,文件描述符0与进程的标准输入结合,文件描述符1与标准输出结合,文件描述符2与标准错误结合。在POSIX中,

1

2

用符号常数

STDIN_FILENO

STDOUT_FILENO

STDERR_FILENO

代替。这些常数定义在

<unistd.h>

中。

open

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

int open(const char* pathname, int o_flag, .../*, mode_t mode */);
           
  • pathname

    : 要打开或创建的文件的名字
  • o_flag

    : 打开文件标志(定义在

creat函数

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

int creat(const char *pathname, mode_t mode);   //成功时返回文件描述符,否则返回-1
           

早期的

open

函数只能打开已有的文件,需要用

creat

函数创建文件,而且

creat

创建文件的同时也以只写的方式打开了文件。相当于

open(pathname, O_WRONLY | O_CREAT | O_TRUNC, mode)

;

close

用close函数关闭一个打开文件。

#include <unistd.h>

int close(int filedes);
           

关闭一个文件时也释放该进程加在该文件的所有记录锁。当一个进程终止时,他的所有打开文件都由内核关闭。

lseek

每个打开文件都有一个与其关联的“当前文件位移量“。它是一个非负整数,用来度量从文件开始处计算的字节数。当打开一个文件时,位移量为0。lseek显式地定位一个打开文件的位移,该操作只改变了操作系统维护的值,不会有实际的IO操作。

以读写方式打开的文件使用一个偏移量,读或写都会改变改偏移量。如果使用了O_APPEND标志,每次写入后都会把偏移量移到末尾。

在打开文件表里每个表项有一个当前文件位移量成员。而文件描述符复制的结果是两个文件描述父共用一个位移量。

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

off_t lseek(int filedes, off_t offset, int whence); //成功时返回新的文件偏移,否则为-1。
           

filedes是要定位的文件的文件描述父,whence是基准位置,offset是以基准的偏移量。whence的取值:

- SEEK_SET: 文件开头。

- SEEK_CUR: 当前偏移量

- SEEK_END: 文件末尾加一的位置。

不是所有的文件都可以用lseek定位偏移,比如管道就不行。

read

#include <unistd.h>

ssize_t read(int filedes, void* buf, size_t n); //成功时返回读到的字节数(包括0),出错返回-1。
           

读数据时默认是阻塞的,如果open时指定O_NONBLOCK那么是非阻塞的。

有多种情况下,读取到的字节数小于指定的字节数:

- 读普通文件是,快到文件末尾。

- 从终端读取数据,默认时一次最多一行

- 从网络中读时,网络的部分数据没到达,只读取到达的数据。

读操作执行完之后,文件的偏移量后移实际读得的字节数。

write

#include <unistd.h>

ssize_t write(int filedes, const void* buf, size_t n); //成功时返回写入的字节数,出错为-1
           

写入后文件偏移后移写入字节数。如果打开时O_APPEND选项,则每次写入时都会自动将偏移移动到末尾再写入。

注:为了保证完整写入,需要检查返回值是否与n相等。

继续阅读