1 open函数
#include <fcntl.h>
int open(const char *pathname, int oflag, /*mode_t mode*/ );
成功则返回文件描述符,失败则返回-1
第三个参数写成/*mode_t mode */ 表示这个参数仅在创建新文件时使用
Pathname表示要打开或者创建文件的名字
Oflag可用来说明此函数的多个选项。用下面一个或多个常量进行“或”运算构成
O_RDONLY 只读打开 0
O_WRONLY 只写打开 1
O_RDWR 读写打开 2
上面三个常量必须且只能指定一个。下面的常量是可选的
O_APPEND 每次写时都追加到文件的尾端
O_CREAT 若此文件不存在则创建它,使用此项时需要第三个参数mode
O_EXCL 可以测试文件是否存在,若不存在则创建,这使得测试和创建成为原子操作
O_TRUNC 如果此文件存在,而且为只写或读写成功打开,则将其长度截短为0
O_NOCITY 如果pathname指的是终端设备,则不将该设备分配为控制终端
O_NONBLOCK 如果pathname指的是一个FIFO,一个块特殊文件或一个字符特殊文件,则将本次打开及后续操作设置为非阻塞模式
O_DSYNC 使每次write等待物理I/O操作完成
O_RSYNC 使read操作等待,直至写操作完成
O_SYNC 使每次write等待物理I/O操作完成,包括由write操作引起的文件属性更新所需的I/O
使用方法:
if ( ( fd = open( "file.hole" ,O_RDWR) ) < 0)
err_sys( "open error" ) ;
2 create函数
#include <fcntl.h>
int creat(const char *pathname, mode_t mode);
它等效于
open (pathname, O_WRONLY | O_CREAT | O_TRUNC, mode);
成功则返回为只写打开的文件描述符,失败则返回-1
3 close函数
#include <unistd.h>
int close(int filedes);
Returns: 0 if OK, 1 on error
4 lseek函数
#include <unistd.h>
off_t lseek(int filedes, off_t offset, int whence);
若成功返回新的偏移量,失败返回-1
Whence=SEEK_SET:距文件开始处的offset字节
Whence=SEEK_CUR:当前值加offset,offset可正可负
Whence=SEEK_END:文件长度加offset,offset可正可负
可以用以下方式确定打开文件的当前偏移量
off_t currpos = lseek(fd, 0, SEEK_CUR);
由于不成功时返回-1,所以一定要和-1比较。因为某些设备也允许负的偏移量
#include "apue.h"
Int main(void)
{
if (lseek(STDIN_FILENO, 0, SEEK_CUR) == -1)
printf("cannot seek\n");
else
printf("seek OK\n");
exit(0);
}
5 read函数
#include <unistd.h>
ssize_t read(int filedes, void *buf, size_t nbytes);
Returns: number of bytes read, 0 if end of file, -1 on error
3.8 write函数
#include <unistd.h>
ssize_t write(int filedes, const void *buf, size_t nbytes);
Returns: number of bytes written if OK, -1 on error
6 原子操作(pread和pwrite函数)
#include <unistd.h>
ssize_t pread(int filedes, void *buf, size_t nbytes, off_t offset);
Returns: number of bytes read, 0 if end of file, 1 on error
ssize_t pwrite(int filedes, const void *buf, size_t nbytes, off_t offset);
Returns: number of bytes written if OK, 1 on error
调用pread相当于调用lseek和read,但是pread又和这种顺序有重要区别:
一.调用pread时,无法中断其定位和读操作
二.不更新文件指针
调用pwrite相当于调用lseek和write
7 dup和dup2函数(用来复制一个现存的文件描述符)
#include <unistd.h>
int dup(int filedes);
int dup2(int filedes, int filedes2);
Both return: new file descriptor if OK, -1 on error
Dup()返回的新描述符一定是最小数值,而dup2()可以通过filedes2来指定新的描述符
复制一个描述符的另一种方法是fcntl函数
dup2(filedes, filedes2);等效于dup(filedes);
fcntl(filedes, F_DUPFD, filedes2);等效于dup2(filedes, filedes2);
当然了,dup2并不完全等同于close和fcntl. 原因有两点
1.dup2是原子操作,而close和fcntl则包括两个函数调用。有可能在close和fcntl之间插入执行信号捕捉函数,它可能修改文件描述符
2.dup2和fcntl有某些不同的errno
8 延迟写
当数据写入文件时,先将数据复制到缓冲区中。如果缓冲区没写满,则等待缓冲区写满或者需要存放其他磁盘块数据时,再排入输出队列,待其到达队首时,才进行实际的I/O操作。
延迟写减少了磁盘读写,却降低了文件内容的更新速度次数,使得欲写到文件中的数据在一段时间内没写到磁盘上,如果系统发生故障,可能造成文件丢失
#include <unistd.h>
int fsync(int filedes);
int fdatasync(int filedes);
Returns: 0 if OK, 1 on error
void sync(void);
sync是对所有文件起作用,将所有修改过的块缓冲,排入写队列,但是不等待写完成即返回;fsync只对文件描述符filedes指定的单一文件起作用,并且等待写磁盘操作结束;fdatasync类似于fsync,但它只影响文件的数据部分,fsync还会同步更新文件的属性
9 fcntl函数(可以改变已打开文件的性质)
#include <fcntl.h>
int fcntl(int filedes, int cmd, ... /* int arg */ );
Returns: depends on cmd if OK , -1 on error
Fcntl函数有5种功能:
Duplicate an existing descriptor (cmd = F_DUPFD)
Get/set file descriptor flags (cmd = F_GETFD or F_SETFD)
Get/set file status flags (cmd = F_GETFL or F_SETFL)
Get/set asynchronous I/O ownership (cmd = F_GETOWN or F_SETOWN) 异步I/O所有权
Get/set record locks (cmd = F_GETLK, F_SETLK, or F_SETLKW)