五个文件io函数,open,read,write,lseek,close;
不带缓冲的io是指每个read,write函数都调用内核中的一个系统调用。它在多进程间共享资源,原子操作就变得很重要。
文件描述符:
对于内核而言,所有打开的文件都是通过文件描述符引用。他是一个费负整数,当打开或者创建一个文件,内核向进程返回一个文件描述符。
当读或者写一个文件时,使用open或creat返回的文件描述符标识该文件,将其作为参数传给read或write。
0----标准输入 STDIN_FILENO
1-----标准输出 STDOUT_FILENO
2-----标准错误输出 STDERR_FILENO (定义在unistd.h中)
文件描述符限制在0-OPEN_MAX间
open函数
#include<fcntl.h>
int open(const char *pathname, int flag, /* mod_t mode */)
成功返回文件描述符,失败返回-1
flag有以下几种,可以用或运算构成flag参数
O_RDONLY 只读 0
O_WRONLY 只写 1
O_RDWR 读写 2
这三个常量中必须指定一个且只能指定一个,则下列常量是可选的。
O_APPEND 每次写追加到末尾
O_CREAT 若此文件不存在则创建它,使用此选项时需要指定第三个参数设置文件的访问权限
当bufsize为1024时io效率最好,可由试验得到。
文件共享
unix支持在不同的进程间共享打开的文件。
内核使用三种数据结构表示打开的文件。
1。每个进程在进程表中都有一个记录项。
2。内核为打开的所有文件维护一张文件表。
3。每个打开文件或设备都有一个v节点结构。
原子性操作
pread,pwrite
dup和dup2函数
用来复制一个现存的文件描述符
dup(filedes);等效于 fcntl(filedes, F_DUPFD, 0);
而调用dup2(filedes, filedes2)等效于close(filedes2); fcntl(filedes, FDUPFD, filedes2);
后一种情况并不完全等于close加上fcntl操作,因为dup2是原子操作
sync,fsync,fdatasync函数
传统unix实现在内核中并没有高速缓冲去,高速缓存,或页面高速缓存,大多数io都是通过缓冲进行。
#include<unistd.h>
int fsync(int filedes);
int fdatasync(int filedes);
成功返回0, 错误返回-1
void sync(void);
sync 只将所有修改过的块缓冲区排入写入队列,然后就返回,并不等待实际写磁盘操作结束。
通常称为update的系统守护程序会周期性的调用sync函数。这就定期的冲洗内核的块缓冲区。
fsync函数只对由文件描述符filedes指定的单一文件起作用,并且等待写磁盘操作结束。可用于数据库类的程序,可以保证修改过的块立即写入到磁盘上。
fdatasync类似于fsync,但它只影响文件的数据部分。而数据外,fsync还会更新文件的属性。
fcntl函数
改变已经打开文件的性质。
#include <fcntl.h>
int fcntl(int filedes, int cmd, .../* int arg */);
返回值:若成功则依赖于cmd,出错返回-1
fcntl函数有五种功能:
1。复制一个现有的描述符 cmd=F_DUPFD
2。获得/设置文件描述符标记 cmd=F_GETFD/F_SETFD
3。获得设置文件状态标志 cmd=F_GETFL/F_SETFL
4。获得设置异步io所有权 cmd=F_GETOWN/F_SETOWN
5。获得/设置记录锁 cmd=F_GETLK, F_SETLK或者F_SETLKW
ioctl函数
ioctl函数是io操作的杂物箱,不能用本章中的其他函数表示的io函数都能用ioctl表示。
终端io是ioctl的最大 使用方面
#include <unistd.h>
#include <sys/ioctl.h>
#include <stropts.h>
int ioctl(int filedes, int request, ...);
出错返回-1,成功返回其他值。
/dev/fd
较新的系统度提供了/dev/fd目录,其目录项是名为0,1,2等文件,打开/dev/fd/n等效于复制描述符n,(假定描述符n是打开的);