I/O操做主要指
文件I/O操做
:打开 (open)、读 (read)、写 (write)、跳转 (lseek:由于文件的当前位置记录在文件表项上,每次获取文件后建议从新设置为:上次的位置)、关闭 (close)。数据库
方法名 | 操做对象 | 特色 | 成功 | 出错 |
---|---|---|---|---|
文件I/O | 操做文件系统,读写磁盘数据 | |||
open | 路径/fd | 获取新的文件操做符 | 文件描述符 | -1 |
creat | 路径 | 建立新的文件描述符 | 0 | -1 |
read | fd | 从内核读取数据将数据读到进程中 | 已读取的字节数;若已到文件尾->0;偏移量向后移动读取的字节大小 | -1 |
write | fd | 将程序中的数据放到内核块缓存中,程序没有缓冲。当buf值大于磁盘块长度时(传入的数据大小比内核I/O通道大),总体的操做时间变化不大 | 已写的字节数;偏移量向后移动写入的字节大小 | -1 |
lseek | fd | 设置文件项中的偏移量 | 新的文件偏移量 | -1 |
close | fd | 关闭文件 | 0 | -1 |
dup | fd | 获取新的文件描述符,指向相同的文件表项 | 新的描述符 | -1 |
sync | fd | write调用后调用,将块缓冲区排入写队列,而后返回。不关心是否成功 | ||
fdatasync | fd | write调用后调用,等待内核将块缓冲刷新到磁盘,直接返回 | 0 | -1 |
fsync | fd | write调用后调用,等待内核将块缓冲刷新到磁盘,并修改完文件状态和偏移量,而后返回 | 0 | -1 |
fcntl | fd | 获取、设置新的文件描述符、文件表中的文件状态 | -1 | |
标准I/O | 自带缓冲区(进程里面)的文件I/O | |||
fwide | 获取或设置流的定向 | 宽字节:正值;字节:负值;设置返回0 | ||
fflush | 刷新数据 | 0 | -1 | |
fopen、freopen、fdopen | 打开文件流 | 文件指针 | NULL | |
fclose | 关闭文件流 | 0 | EOF | |
fgetc | 字节读 | 下一个字符 | 文件尾部或出错:EOF | |
fputc | 字节写文件流 | C | EOF | |
fgets | 行读 | 返回buf | 文件尾部或出错:NULL | |
fputs | 行写 | 非负 | EOF | |
fread | 块写 | 读的对象数 | EOF | |
fwrite | 快写 | 写的对象数 | EOF | |
ftell、fseek、rewind、ftello、fseeko、fgetpos、fsetpos | 快写 | 写的对象数 | EOF | |
tmpnam和tmpfile | ISOC标准的临时文件 | |||
mkdtemp和mkstemp | SUS标准的临时文件 | |||
fmemopen | 内存流 | 流指针 | NULL | |
open_memstream | 内存流 | 流指针 | NULL | |
open_wmenstream | 内存流 | 流指针 | NULL | |
高级I/O | 同步非阻塞I/O | 这几个接口再也不是严格意义上的阻塞,而是只阻塞自定的时间,等返回事件时, | ||
select/pselect | 注册fd感兴趣的事件,注册三个描述符集合(readfds、writefds、exceptfds) | 准备好的描述符数目(及描述符处理的数据都加载到内核内存中,不会在等待内存作读写操做) ;超时,返回0 | -1 | |
poll | 注册fd感兴趣的事件,经过 pollfd 的结构体数组注册 | 缺点:1.支持文件描述符过小(默认1024);2.并不知道哪一个fd准备好了,必须挨着去轮训对比fd | 准备好的描述符数目(及描述符处理的数据都加载到内核内存中,不会在等待内存作读写操做) ;超时,返回0 | -1 |
FD_ISSET | 检测是否fd的事件 | 0 | -1 | |
FD_CLR | 删除fd到fdset中 | 0 | -1 | |
FD_SET | 设置fd到fdset中 | 0 | -1 | |
FD_ZERO | 清楚fdset中的fd | 0 | -1 | |
高级I/O | 异步I/O:此操做是经过aio_return获取值,read/write只做为事件注册 | |||
aio_read | 异步读,将读取事件注册给内核。内核从缓冲中读取数据到目标addr | 0 | -1 | |
aio_write | 异步写,将写取事件注册给内核。内核从目标addr写入到缓冲中 | 0 | -1 | |
aio_fsync | 强制全部等待中的异步操做不等待而写入持久化的存储中 | 0 | -1 | |
aio_error | 测试异步I/O是否成功 | 0 | -1 | |
aio_return | 返回操做结果。异步操做完成前,不要调用。不然os会释放掉包涵I/O操做返回值的记录 | read、write、fsync的的结果 | -1 | |
aio_suspend | 阻塞进程,直到I/O操做完成 | 0 | -1 | |
lio_listio | 提交一系列I/O请求 | 0 | -1 | |
readv | 从内涵中读取数据到多个非连续缓冲区 | 读的字节数 | -1 | |
writev | 将多个非连续缓冲区数据写到内核缓冲区 | 读的字节数 | -1 | |
mmap | 将一个磁盘文件映射到存储空间的一个缓冲区 | 返回映射区的起始地址 | MAP_FAILED |
符号 | 对象 | 常量 |
---|---|---|
0 | 读 | STDIN_FILENO |
1 | 写 | STDOUT_FILENO |
2 | 错误 | STDERR_FILENO |
#include <fcntl.h> int open(const char *path,int oflag,.../*mode_t mode*/) int openat(int fd ,const char *path,int oflag,.../*mode_t mode*/) -- 返回:成功,返回文件操做符;若出错,返回-1
符号 | 功能 |
---|---|
path | 打开或建立的名字 |
oflag | 选项 |
... | 可变,当oflag=O_CREATE的时候才使用 |
符号 | 说明 |
---|---|
O_RDONLY | 只读打开 |
O_WRONLY | 只写打开 |
O_EXEC | 只执行打开 |
O_SEARCH | 只搜索打开(应用于目录) |
O_APPEND | 每次追加到文件的尾端 |
O_CLOEXEC | 设置文件项的文件状态为FD_CLOEXEC常量,在执行exec调用的新程序中关闭,且为原子操做。 |
O_CREAT | 若此文件不存在则建立它,须要传入open的第3个参数mode(访问权限位) |
O_DIRECTORY | 若是path引用的不是目录,则出错 |
O_EXCL | 1.测试一个文件是否存在,若是不存在则建立此文件(原子操做)。2.若是同时指定O_CREATE,而文件已存在,则出错。 |
O_NOCTTY | 若是path引用的是终端设备,则不将该设备分配做为次进程的控制终端 |
O_NOFOLOOW | 若是path引用的是一个符号连接 |
O_SYNC | (同步写)每次write等待物理I/O操做完成,包括由write引发的文件属性更新所需的I/O |
O_TRUNC | 若是此文件存在,并且为写或读-写成功打开,则将其长度截断为0 |
O_DSYNC | 每次write要等待物理I/O操做完成,可是若是该写操做并不影响读写刚写入的数据,则不需等待文件属性被更新 |
O_RSYNC | (同步读)read操做等待,直到全部对文件同一部分挂起的操做都完成 |
#include <fcntl.h> int creat(const char *path,mode_t mode); --- 成功:返回为写打开的文件描述符;出错,返回-1 等价于: open(path,O_WRONLY|O_CREATE|O_TRUNC,mode); 修改后使用: open(path,O_RDWR|O_CREATE|O_TRUNC,mode)
create不足:以写的方式打开建立的文件,在操做前须要close下,而后在用open.create--->write--->read--->close-->open数组
修改:处理方法:open(path,O_RDWR|O_CREATE|O_TRUNC,mode)缓存
#include <unistd.h> int close(int fd) --- 成功:返回0;出错:返回-1
#include<unistd.h> off_t lseek(int fd, off_t offset, int whence); --- 成功:返回新的文件偏移量;出错:返回-1
每一个打开文件都有一个与其关联的"当前文件偏移量"(current file offset)。它一般是一个非负整数。一般,read、write都是从当前文件的偏移量开始,并使偏移量增长所读写的字节数。网络
系统默认,打开一个五年级,除非指定O_APPEND选项,不然该偏移量被设置为*app
whence参数异步
参数 | 做用 |
---|---|
SEEK_SET | 文件开始处offset个字节 |
SEEK_CUR | 文件偏移量设置为当前值加offset,offset可为正或负 |
SEEK_END | 文件偏移量设置为文件长度加offset,offset可为正或负 |
# 若是指向管道、FIFO或网络套接字,则返回-1 off_t curpos; currpos = lseek(fd,0,SEEK_CUR);
#include <unistd.h> ssize_t read(int fd,void *buf, size_t nbytes); --- 成功:读到的字节数,若已到文件尾,返回0;出错:返回-1 # POSIX修改: int read(int fd,char *buf,unsigned nbytes);
#include <unistd.h> ssize_t write(int fd,const void *buf ,size_t nbytes); --- 成功:返回已写的字节数;出错:返回-1
#include <unistd.h> int dup(int fd); int dup2(int fd,int fd2); ----成功:返回新的描述符;出错:返回 -1
#include <unistd.h> int fsyn(int fd); int fdatasync(int fd); --- 成功:返回0;出错;返回-1 void sync(void);
修改文件属性: 文件表信息中的文件状态标志:只读,只写,非阻塞...socket
#include <fcntl.h> int fcntl(int fd, int cmd, .../*struct flock *flockptr */) ---成功:根据cmd返回;出错:返回-1 1. struct flock { short l_type; /*F_RDLCK,F_WRLCK,F_UNLCK*/ short l_whence; /*SEEK_SET,SEEK_CUR,SEEK_END*/ off_t l_start; /*F_RDLCK,F_WRLCK,F_UNLCK*/ off_t l_len; /*F_RDLCK,F_WRLCK,F_UNLCK*/ pid_t l_pid; /*F_RDLCK,F_WRLCK,F_UNLCK*/ }
参数 | 做用 | 返回 | 第三位 |
---|---|---|---|
F_DUPFD | 复制一个已有的描述符,与老的文件描述符共享同一文件项。清除FD_CLOEXEC的标志 | 成功:返回新的文件描述符;出错:-1 | 0 |
F_DUPFD_CLOEXEC | 复制一个已有的描述符,不清除FD_CLOEXEC的标志 | 成功:返回新的文件描述符;出错:-1 | 0 |
F_GETFD | 获取文件描述符标志(文件描述符信息) | 成功:返回新的文件描述符;出错:-1 | 0 |
F_SETFD | 设置文件描述符标志(文件描述符信息) | 成功:根据第三个参数返回新的描述符;出错:-1 | 0 |
F_GETFL | 获取文件状态标志(文件表信息) | 成功:文件状态;出错:-1 | 0 |
F_SETFL | 获取文件状态标志(文件表信息) | 成功:1;出错:-1 | 0 |
F_GETOWN | 获取异步I/O的全部权 | 成功:获取当前接受到的SIGIO和SIGURG信号的进程ID或进程组ID;出错:-1 | 0 |
F_SETOWN | 设置异步I/O的全部权 | 成功:1;出错:-1 | 0 |
F_GETLK | 获取记录锁,判断描述的锁是否被另一把锁排斥(阻塞) | 成功:有:重写flock,返回现有锁;否:flock不变;出错:-1 | flock |
F_SETLK | 设置取记录锁,非阻塞版 | 成功:1;出错:errno=EACCESS或EAGAIN;出错:-1 | flock |
F_SETLKW | 设置取记录锁,是F_SETLK的阻塞(wait)版本。若是设置不成功则休眠,当锁能够用或者休眠由信号中断、则该进程被唤醒 | 成功:1;出错:-1 | flock |
flock结构:async
记录锁(进程间)注意项:当第一个进程正在读或修改文件的某个部分时,使用记录数能够阻止其它***进程***修改同一文件区。ide
标准I/O处理了不少细节,如缓冲区分配、优化的块长度执行I/O等。这使得用户没必要担忧如何选择正确的块长度。函数
#include <stdio.h> #include <wchar.h> int fwide(FILE *fp,int mode); --- 返回值:若流是宽定向,返回正值;如流是字节定向,返回负值;若流是为定向,返回0
mode | 说明 |
---|---|
负数 | 试图使指定的流是字节流定向 |
正数 | 试图使指定的流是宽定向 |
0 | 不试图试图设置流的定向,饭返回标识该流定向的值 |
#include <stdio.h> void setbuf(File *restrict fp,char *restrict buf); int setvbuf(File *restrict fp,char *restrict buf,int mode,size_t size); ---成功:返回;出错,返回EOF
|buf|缓冲区及长度|缓冲类型| |:--|:--|:--| |非空|长度为BUFSIZ的用户缓冲区buf|全缓冲或行缓冲| |NULL|无缓冲|不带缓冲|
buf | buf | 缓冲区及长度 | 缓冲类型 |
---|---|---|---|
_IOFBUF | 非空 | 长度为BUFSIZ的用户缓冲区buf | 全缓冲 |
_IOFBUF | NULL | 合适长度的系统缓冲区buf | 全缓冲 |
_IOLBUF | 非空 | 长度为BUFSIZ的用户缓冲区buf | 行缓冲 |
_IOLBUF | NULL | 合适长度的系统缓冲区buf | 行缓冲 |
_IONBUF | 忽略 | 无缓冲 | 不带缓冲 |
#include <stdio.h> int fflush(FILE *fp) ---成功:返回;出错,返回EOF
#include <stdio.h> FILE *fopen(const char *restrict pathname,const char *restrict type); FILE *freopen(const char *restrict pathname,const char *restrict type ,FILE *restrict fp); FILE *fdopen(int fd, const char *type); --- 成功:返回文件指针;出错:返回NULL
type | 说明 | oopen标志 |
---|---|---|
r或rb | 为读而打开 | O_RDONLY |
w或wb | 把文件截断至0长,或为写而建立 | O_WRONLY/O_CREAT/O_TRUNC |
a或ab | 追加:为在文件尾写而打开,或为写而建立 | O_WRONLY/O_CREAT/O_APPEND |
r+或r+b或rb+ | 为读和写 | O_RDWR |
w+或w+b或wb+ | 把文件截断至0长,或为读和写而建立 | O_RDWR/O_CREAT/O_TRUNC |
a+或a+b或ab+ | 为在文件尾读和写而打开或建立 | O_RDWR/O_CREAT/O_APPEND |
函数 | 说明 |
---|---|
fopen | 打开路径为pathname的一个指定文件 |
freopen | 用于标准输入输出或标准错误。 |
fdopen | 是一个标准I/O流与一个文件描述符结合(open、dup、dup二、fcntl、pipe、socket、socketpair、accept),用于建立管道和网络通讯通道函数返回的描述符 |
#include <stdio.h> int fclose(FILE *fp) ---成功:0;出错:EOF
#include <stdio.h> int getc(FILE *fp); int fgetc(FILE *fp); int getchar(voide); -- 成功:返回下一个字符;若刀刀文件尾端或出错:返回EOF
#include<stdio.h> int putc(int c,FILE *fp); int fputc(int c,FILE *fp); int putchar(int c); -- 成功:返回C;出错:返回EOF
#include <stdio.h> char *fgets(char *restrict buf,int n,FILE *restrict fp); char *gets(char *buf);"不能指定缓存大小,不推荐使用" ---成功:返回buf;到文件尾部或出错:返回NULL
#include <stdio.h> int fputs(const char *restrict str,FILE *restrict fp); int puts(const char *str);"不推荐使用" --成功:返回非负;出错:返回EOF
#include <stdio.h> size_t fread(void *restrict ptr,size_t size,size_t boby,File *restrict fp); size_t fwrite(const void *restrict ptr,size_t bobj,FILE *restrict fp); --返回读或写的对象数
#include <stdio.h> long ftell(FILE *fp); "成功:返回当前文件位置;失败:返回-1L" int fseek(FILE *fp,long offset ,int whence); "成功:返回0;失败:返回-1" void rewind(FILE *fp); off_t ftello(FILE *fp); "成功:返回当前文件位置;出错:返回-1" int fseeko(FILE *fp,off_t offset, int whence); "成功:返回0;出错:返回-1" int fgetpos(FILE *restrict fp,fpos_t *restrict pos); int fsetpos(FILE *FP, const fpost_t *pos); --"成功:返回0;出错:返回非0"
#include <stdio.h> char *tmpnam(char *ptr); "指向惟一路径名的指针" FILE *tmpfile(void); "成功:返回文件指针;出错:返回NULL"
#include <stdlib.h> char *mkdtemp(char *template); 成功:返回指向"目录"名的指针;出错:返回NULL int mkstemp(char *template); 成功:返回"文件"描述符;出错:返回NULL
#include <stdio.h> 1."成功:返回流指针;出错:返回NULL" FILE *fmemopen(void *restrict buf,size_t size,const *restrict type); 2.字节:成功:返回流指针;出错:返回NULL FILE *open_memstream(char **bufp,size_t *sizep); 3.宽字节:成功:返回流指针;出错:返回NULL FILE *open_wmenstream(wchar_t **bufp,size_t *sizep);
非阻塞I/O、记录锁、I/O多路转接(select 和poll 函数)、异步I/O、readv和writev函数、存储映射I/O(mmmp)
低速系统:
非阻塞:若是发起open、read、write这样的I/O操做,不能完成,则调用当即出错(errno=NAGAIN)返回,表示该操做如继续执行将阻塞。
记录锁():当第一个进程正在读或修改文件的某个部分时,使用记录数能够阻止其它进程修改同一文件区。
#include<fcntl.h> int fcntl(int fd,int cmd,.../*struct flock *flockprt*/); ---'成功:依赖下面CMD命令;出错:返回-1'
#include <sys/select.h> int select(int maxfdpl,fd_set *restrict readfds,fd_set *restrict writefds, fd_set *restrict execeptfds,struct timeval * restrict tvprt ); --'成功:1.准备就行的描述符数目;超时,返回0;出错:-1'
参数 | 说明 |
---|---|
tvptrNULL | 永久等待,直到有一个关心的描述符准备好 |
tvptr->tv_set0 && tvptr->tv_usec 0 | 不等待,直接返回 |
tvptr->tv_set !=0 && tvptr->tv_usec !=0 | 等待指定的秒数和微秒数。 |
告诉内核 :
内核返回:
准备好:
#include <sys/select.h> 1.检测fd是否已经准备好 int FD_ISSET(int fd,fd_set *fdset); --'若fd在描述符集合中,返回非0值;不然,返回0' 2.设置、删除、清除 void FD_CLR(int fd, fd_set *fdset); void FD_SET(int fd, fd_set *fdset); void FD_ZERO(fd_set *fdset);
#include <sys/select.h> int pselect(int maxfdp1,fd_set *restrict readfds, fd_set *restrict writefds,fd_set *restrct execptfds, const struct timespec *restrict tsptr, const sigset_t *restrict sigmask); --'成功:1.准备就行的描述符数目;超时,返回0;出错:-1'
#include <poll.h> int poll(struct pollfd fdarray[], nfds_t nfds,int timeout); -- '返回值:准备就绪的描述符数目;若超时,返回 0;若出错,返回-1' 1. pollfd struct pollfd { int fd; short events; 'fd感兴趣的事件' short revents; 'fd发生了什么' }
参数:
标志名 | 输入至events? | 从revents获得结果? | 说明 |
---|---|---|---|
POOLIN | . | . | 能够不阻塞地读高优先数据意外的数据(等效于POLLRDNORM |
POLLRDNORM | . | . | 能够不阻塞地读普通数据 |
POLLRDBAND | . | . | 能够不阻塞地读优先数据 |
POLLPRI | . | . | 能够不阻塞地读高优先数据 |
POLLOUT | . | . | 能够不阻塞地写普通数据 |
POLLWRNORM | . | . | 与POLLOUT相同 |
POLLWRBAND | . | . | 能够不阻塞地写高优先数据 |
POLLERR | . | 已出错 | |
POLLHUP | . | 已挂断 | |
POLLNVAL | . | 描述符没有引用一个打开文件 |
* timeout
参数 | 说明 |
---|---|
timeout-1 | 永远等待 |
timeout0 | 不等待,直接返回 |
timeout > 0 | 等待指定的秒数和微秒数。 |
步骤
#include <aio.h> int aio_read(struct aiocb *aiocb); int aio_write(struct aiocb *aiocb); --'成功:返回0;出错:-1' 1. aiocb struct aiocb { int aio_fildes; '文件描述符' off_t aio_offset; '偏移量' volatitle void *aio_buf; '缓冲区开始地址' size_t aio_nbytes; '读/写的字节数' int aio_reqprio; '异步I/O请求提示顺序' struct sigvent aio_sigevent; 'I/O完成后,通知应用程序处理' int aio_lio_opcode; '用于基于列表的异步I/O' } 2. sigevent struct sigevent { int sigev_notify; '通知类型' int sigev_signo; '通知数量' union sigval sigev_value; '处理方法入数' void (*sigev_notify_function) (union sigval); '处理方法' pthread_attr_t *sigev_notify_attributes; '通知参数' }
参数 | 说明 |
---|---|
SIGEV_NONE | 请求完成后,不通知进程 |
SIGEV_SIGNAL | 请求完成,返回sigev_signo指定信号。sigev_value会做为siginfo结构中的si_value,并将signinfo放入信号列表,等待处理程序处理 |
SIGEV_THREAD | 请求完成,由sigev_notify_function指定的函数处理。sigev_value做为它的惟一参数。除非,sigev_notify_attributes字段被设定为pathread属性结构的地址,且该结构指定了另一个县城的属性,不然该函数将在分离状态下的一个单独的线程中执行。 |
#include <aio.h> int aio_fsync(int op,struct aiocb *aiocb); --'成功:返回0;出错:-1'
参数 | 说明 |
---|---|
O_DSYNC | 和fdatasync同样:等待数据写入持久存储就返回 |
O_SYNC | fsycn同样:等待数据和文件状态都完成 |
#include <aio.h> int aio_error(const struct aiocb *aiocb);
特色:
返回:
参数 | 说明 |
---|---|
0 | 异步操做成功完成。须要调用aio_return 函数获取操做返回值 |
-1 | aio_error的调用失败 |
EINPROGRESS | 异步读、写或同步操做仍在等待 |
其它状况 | 其它任何返回值是相关的异步操做失败返回的错误码 |
#include <aio.h> int aio_return(const struct aiocb *aiocb); -- '成功:read、write、fsync的的结果;出错:-1,设置errno'
#include <aio.h> int aio_suspend(const struct aiocb *const list[] , int nent, const struct timespec *timeout); -- '成功:0;出错:-1,设置errno'
参数:
返回:
条件 | 返回 |
---|---|
被信号中断 | 返回-1,将errno设置为EINTR |
没有完成任何I/O操做,超过timeout的时间 | 返回-1,errno=EAGAIN |
I/O完成 | 返回 0 |
#include <aio.h> int aio_cancel(inf fd, struct aiocb *aiocb);
特色
返回:
值 | 说明 |
---|---|
AIO_ALLDONE | 全部操做在尝试取消以前已完成 |
AIO_CANCELED | 全部要求的操做已取消 |
AIO_NOTCANCELED | 至少有一个要求的操做没有被取消 |
-1 | 调用失败 |
#include <aio.h> int lio_listio(int mode,struct aiocb *restrict const list[restrict], int nent , struct sigevent *restrict sigev); -- '成功:0;出错:-1'
参数:
特色:
#include <sys/uio.h> ssize_t readv(int fd,const struct iovec *iov , int iovcnt); ssize_t writev(int fd,const struct iovec *iov, int iovcnt); --'已读或已写的字节数;出错:-1' 1. strct iovec { void *iov_base; '开始地址' size_t iov_len; '缓冲大小' }
参数:
特色:
#include <sys/mman.h> void *mmap(void *addr, size_t len, int port,int flag,int fd, off_t off ); -- '成功:返回映射区的起始地址;出错:MAP_FAILED'
参数:
参数 | 说明 |
---|---|
PROT_READ | 映射区可读 |
PROT_WRITE | 映射区可写 |
PROT_EXEC | 映射区可执行 |
PROT_NONE | 映射区不可访问 |
参数 | 说明 |
---|---|
MAP_FIXED | 返回值必须等于addr |
MAP_SHARED | 本进程对映射区所进行的存储操做的配置 |
MAP_PRIVATE | 对映射区的存储操做致使建立映射文件的一个私有副本 |
特色: