IO相关

I/O操做主要指 文件I/O操做:打开 (open)、读 (read)、写 (write)、跳转 (lseek:由于文件的当前位置记录在文件表项上,每次获取文件后建议从新设置为:上次的位置)、关闭 (close)数据库

特色:

  • I/O的操做对象:本地文件、网络IPC套接字、unix域套接字.
  • 不一样I/O:都是在这个基础上经过缓存改变read/write的次数来改变CPU占用时间。

方法

方法名 操做对象 特色 成功 出错
文件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

名词解释

  • 文件描述符:对于内核而言,全部打开(open/create)的文件都经过文件描述符引用,是一个非负整数。
符号 对象 常量
0 STDIN_FILENO
1 STDOUT_FILENO
2 错误 STDERR_FILENO

1、文件I/O

open和openat

#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的时候才使用
  • oflag
符号 说明
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操做等待,直到全部对文件同一部分挂起的操做都完成

creat

#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)缓存

close

#include <unistd.h>
int close(int fd)
            --- 成功:返回0;出错:返回-1
  • 关闭一个文件时,会释放该进程加载该文件上的全部记录锁。
  • 进程终止时,内核自动关闭全部打开的文件。

lseek (移动)

#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);

read

#include <unistd.h>
ssize_t read(int fd,void *buf, size_t nbytes);
            --- 成功:读到的字节数,若已到文件尾,返回0;出错:返回-1

# POSIX修改:

    int read(int fd,char *buf,unsigned nbytes);
  • 参数
    • fd:文件描述符
    • buf:从内核缓存读取到程序空间的缓存
    • nbytes:一次读取字节数
  • 特色
    • 成功返回以前,该偏移量增长实际读到的字节数。
    • 倒数第二次不满 nbytes,则返回读取到的个数;最后一次返回0(文件尾部)
    • 终端设备读时,一般一次最多读一行
    • 网络读,网络中的缓冲机制可能形成返回值小于所要读的字节数
    • 管道或FIFO读,广岛包涵的字节少于所需的数量,那么read只返回实际可用的字节数
    • 记录设备(如磁盘),一次返回一个记录
    • 当已信号形成终端,而已经读了部分数据量时。

write

#include <unistd.h>
ssize_t write(int fd,const void *buf ,size_t nbytes);
            --- 成功:返回已写的字节数;出错:返回-1
  • 参数:和read相同
  • 特色:
    • 出错常见缘由:磁盘写满、文件长度设置了限制
    • 普通文件,写从当前偏移量处开始。
      • 1.成功后,偏移量移动到写入后的位置。
      • 2.若是打开文件时,指定了O_APPEND选项,则在每次写操做以前,将文件偏移量设置在文件的当前结尾处,在一次成功后,文件偏移量增长时间写的字节。

dup和dup2

#include <unistd.h>
int dup(int fd);
int dup2(int fd,int fd2);
        ----成功:返回新的描述符;出错:返回 -1
  • 特色
    • 清楚文件项的 FD_CLOEXEC 状态
    • dup(fd) : 返回新的文件描述符,fd不关闭。=fcntl(fd,F_DUPFD,0)
    • dup2(fd,fd2) : 返回新的描述fd2,旧的fd1关闭。若fd=fd2,则不关闭。=fcntl(fd1,F_DUPFD,fd2)

sync,fsync,fdatasync

#include <unistd.h>
int fsyn(int fd);
int fdatasync(int fd);
        --- 成功:返回0;出错;返回-1
void sync(void);
  • 特色:
    • sync:将修改过的块缓冲区排入写队列,而后就返回,不等待实际的些盘操做。
    • fsync: 等待写磁盘操做完成才返回 (内核将写队列中的块缓冲区刷新到磁盘,并修改文件属性(长度)等信息) ,适用于数据库。
    • fdatasync: 等待内核将块缓冲区数据刷新进磁盘,不等待文件属性(长度)修改完成。

fcntl (修改文件属性)

修改文件属性: 文件表信息中的文件状态标志:只读,只写,非阻塞...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*/
}
  • 参数:
    • cmd
参数 做用 返回 第三位
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

      • 锁类型(l_type):F_RDLCK(共享读锁)F_WRLCK(独占性写锁)F_UNLCK(解锁一个区域)
      • 要加锁或解锁区域的起始偏移量:l_startl_whence
      • 区域的字节长度:l_len
      • 进程的ID(l_pid)持有的锁能阻塞当前进程,仅F_GETLK返回
    • 记录锁(进程间)注意项:当第一个进程正在读或修改文件的某个部分时,使用记录数能够阻止其它***进程***修改同一文件区。ide

      • l_len=0:表示锁的方位能够扩张到最可能偏移量。
      • 整个文件加锁:l_start=0和l_whence=SEEK_SET指向文件的起始位置。指定l_len=0。
      • 读锁共享:多个进程在给定的字节上能够共享读锁,即有读锁还能再加。
      • 读锁替换:同一进程在已有一把读锁的同一文件区间加读锁,锁将被替换。
      • 写锁独占:在一个文件的同一字节区间只能有一把写锁,不能有其它读锁或写锁。
      • 分裂和合并:对一把锁的中间字段解锁,则分裂成2变锁。中间字段被加一样的锁,则合并为一把锁。

2、标准I/O

标准I/O处理了不少细节,如缓冲区分配、优化的块长度执行I/O等。这使得用户没必要担忧如何选择正确的块长度。函数

  • 名称解释
    • 宽字节:ASCII字符集:一个字符用一个字节表示。国际字符集:一个字符可用多个字节表示。标准I/O文件流可用于单字节或多字节(宽)字符集
    • 流的定向:
      • 1.当在为定向的流上使用一个多字节I/O函数,将设置流向为宽定向
      • 2.当在为定向的流上使用单字节I/O函数,将该流的定向设置为字节流向
      • 3.freopen函数清除一个流的定向
      • 4.fwide用于设置流的定向
    • 缓冲:
      • 目的:减小Read和write的调用次数
      • 全缓冲:(磁盘)在填满标准I/O缓冲区后才进行实际I/O操做。1.磁盘上的文件一般都是由标准I/O实施全缓冲,在一个流执行第一次I/O操做时,相关标准I/O函数一般调用malloc获取缓冲区。
      • 行缓冲:(终端输入输出),遇到换行符时,标准I/O库执行I/O操做。
      • 不带缓冲:标准I/O不对字符进行缓冲存储。
  • 特色(与文件I/O比较):
    • 标准I/O 移植性好,不少UNIX以外的系统都实现了这些标准
    • fopen打开一个指向FILE对象的指针。该指针对象一般是一个结构:实际I/O的文件描述符、指向用于该流缓冲区的指针(进程空间缓冲区,和read/write的内核空间缓冲有区别)、当前在缓冲区中的字符数、出错标志etc

fwide 设置流的定向

#include <stdio.h>
#include <wchar.h>
int fwide(FILE *fp,int mode);
    
        --- 返回值:若流是宽定向,返回正值;如流是字节定向,返回负值;若流是为定向,返回0
  • 参数
mode 说明
负数 试图使指定的流是字节流定向
正数 试图使指定的流是宽定向
0 不试图试图设置流的定向,饭返回标识该流定向的值
  • 特色

setbuf/setvbuf 设置缓冲类型

#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
  • 参数及特色
  • setbuf

|buf|缓冲区及长度|缓冲类型| |:--|:--|:--| |非空|长度为BUFSIZ的用户缓冲区buf|全缓冲或行缓冲| |NULL|无缓冲|不带缓冲|

  • setvbuf
buf buf 缓冲区及长度 缓冲类型
_IOFBUF 非空 长度为BUFSIZ的用户缓冲区buf 全缓冲
_IOFBUF NULL 合适长度的系统缓冲区buf 全缓冲
_IOLBUF 非空 长度为BUFSIZ的用户缓冲区buf 行缓冲
_IOLBUF NULL 合适长度的系统缓冲区buf 行缓冲
_IONBUF 忽略 无缓冲 不带缓冲

fflush 刷新数据

#include <stdio.h>

int fflush(FILE *fp)
        ---成功:返回;出错,返回EOF
  • 特色:
    • 是该流全部未写的数据都被传送至内核
    • 若是fp=null,则将致使全部的输出流被冲洗
fopen、freopen、fdopen
#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),用于建立管道和网络通讯通道函数返回的描述符

fclose

#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"

临时文件

  • ISO C 标准I/O :同时使用下面函数
#include <stdio.h>
char *tmpnam(char *ptr);        "指向惟一路径名的指针"
FILE *tmpfile(void);        "成功:返回文件指针;出错:返回NULL"
  • Single UNIX Specification
#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);

3、高级I/O

非阻塞I/O、记录锁、I/O多路转接(select 和poll 函数)、异步I/O、readv和writev函数、存储映射I/O(mmmp)

名词解释

  • 低速系统:

      1. 某些文件类型(如:管道、终端设备、网络设备)的数据不存在,读操做可能会是调用者永远阻塞。
      1. 数据不能被相同的文件类型当即接受(如:管道中无空间、网络流控制),写操做可能会被调用者永久阻塞。
      1. 某中条件发生以前打开某些文件类型可能会发生阻塞。
      • 1.打开一个终端设备,须要线等待与之链接的调制解调器应答.
      • 2.以写模式打开FIFO,那么在没有其它进程已用读打开该FIFO时也要等待)
      1. 对已加上强制性***记录锁***的文件进行读写;
      1. 某些ioctl操做;
      1. 某些进程间通讯函数。
      1. 读写磁盘文件会暂时阻塞调用者,但并不能将与磁盘I/O有关的系统调用视为低速。
  • 非阻塞:若是发起open、read、write这样的I/O操做,不能完成,则调用当即出错(errno=NAGAIN)返回,表示该操做如继续执行将阻塞。

    • open函数,直接设置为O_NONBLOCK标志。
    • 已经打开的文件描述符,调用fcntl将文件状态标志设置为O_NONBLOCK
  • 记录锁():当第一个进程正在读或修改文件的某个部分时,使用记录数能够阻止其它进程修改同一文件区。

#include<fcntl.h>
int fcntl(int fd,int cmd,.../*struct flock *flockprt*/);

    ---'成功:依赖下面CMD命令;出错:返回-1'

select 和 pselect

#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'
  • 参数
    • fd_set:文件描述符集合
    • maxfdpl:三个集合中最大文件描述符号值+1.
    • tvptr:当文件描述符没准备好
参数 说明
tvptrNULL 永久等待,直到有一个关心的描述符准备好
tvptr->tv_set0 && tvptr->tv_usec 0 不等待,直接返回
tvptr->tv_set !=0 && tvptr->tv_usec !=0 等待指定的秒数和微秒数。
  • 特色
    • 告诉内核 :

      • 关心的描述符及每一个文件描述符关心的条件(每一个描述符每次只能关心一种条件,readfds、writefds、excepfds中文件描述符不能重复)
      • 等待时间
    • 内核返回:

      • 准备好(不会阻塞,就是全部数据都加载到了内核内存中)的描述符总数量
      • 准备好(不会阻塞,就是全部数据都加载到了内核内存中)的文件描述符
    • 准备好

      • read、write操做不阻塞。内核已经把读数据整理完毕,把写数据完成传输。
#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'
  • 特色:
    • timespec : 纳秒
    • sigmask : 信号屏蔽只字,以原子操做的方式安装信号屏蔽字。

poll

#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标志
标志名 输入至events? 从revents获得结果? 说明
POOLIN . . 能够不阻塞地读高优先数据意外的数据(等效于POLLRDNORM
POLLRDNORM . . 能够不阻塞地读普通数据
POLLRDBAND . . 能够不阻塞地读优先数据
POLLPRI . . 能够不阻塞地高优先数据
POLLOUT . . 能够不阻塞地普通数据
POLLWRNORM . . 与POLLOUT相同
POLLWRBAND . . 能够不阻塞地写高优先数据
POLLERR . 已出错
POLLHUP . 已挂断
POLLNVAL . 描述符没有引用一个打开文件
* timeout
参数 说明
timeout-1 永远等待
timeout0 不等待,直接返回
timeout > 0 等待指定的秒数和微秒数。

异步 I/O

  • 步骤

      1. 打开文件
      1. 设置aio的缓冲区、信号及信号处理
      1. 启用for循环处理
      1. 根据append、read、write来作处理。
      1. read:
      • aio_error 验证是否出错
      • aio_return 将字节数据读取到aio中
      • 处理
      • 设置写的缓冲大小、字节数
      • 调用aio_write
      1. write的操做与read相似
#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_notify
参数 说明
SIGEV_NONE 请求完成后,不通知进程
SIGEV_SIGNAL 请求完成,返回sigev_signo指定信号。sigev_value会做为siginfo结构中的si_value,并将signinfo放入信号列表,等待处理程序处理
SIGEV_THREAD 请求完成,由sigev_notify_function指定的函数处理。sigev_value做为它的惟一参数。除非,sigev_notify_attributes字段被设定为pathread属性结构的地址,且该结构指定了另一个县城的属性,不然该函数将在分离状态下的一个单独的线程中执行。
  • 特色:
      1. 异步请求被放入等待处理的队列中,等待系统的AIO控制块处理.

aio_fsync :强制全部等待中的异步操做不等待而写入持久化的存储中

#include <aio.h>

int aio_fsync(int op,struct aiocb *aiocb);

        --'成功:返回0;出错:-1'
  • 参数:
    • op:
参数 说明
O_DSYNC 和fdatasync同样:等待数据写入持久存储就返回
O_SYNC fsycn同样:等待数据和文件状态都完成

aio_error 和 aio_return

#include <aio.h>

int aio_error(const struct aiocb *aiocb);
  • 特色:

    • 用改函数测试异步I/O是否成功
  • 返回:

参数 说明
0 异步操做成功完成。须要调用aio_return 函数获取操做返回值
-1 aio_error的调用失败
EINPROGRESS 异步读、写或同步操做仍在等待
其它状况 其它任何返回值是相关的异步操做失败返回的错误码
#include <aio.h>

int aio_return(const struct aiocb *aiocb);

    -- '成功:read、write、fsync的的结果;出错:-1,设置errno'
  • 特色
    • 异步操做完成前,不要调用。不然os会释放掉包涵I/O操做返回值的记录

aio_suspend : 阻塞进程,直到I/O操做完成

#include <aio.h>

int aio_suspend(const struct aiocb *const list[] , int nent, const struct timespec *timeout);
    
    -- '成功:0;出错:-1,设置errno'
  • 参数:

    • list:AIO控制块数组的指针,空指针被跳过。
    • nent:数组中的条目
  • 返回:

条件 返回
被信号中断 返回-1,将errno设置为EINTR
没有完成任何I/O操做,超过timeout的时间 返回-1,errno=EAGAIN
I/O完成 返回 0

aio_cancel

#include <aio.h>

int aio_cancel(inf fd, struct aiocb *aiocb);
  • 特色

    • I/O操做取消成功,对应的AIO控制块调用aio_error函数将会返回errno=ECANCELED。
  • 返回:

说明
AIO_ALLDONE 全部操做在尝试取消以前已完成
AIO_CANCELED 全部要求的操做已取消
AIO_NOTCANCELED 至少有一个要求的操做没有被取消
-1 调用失败

lio_listio 提交一系列I/O请求

#include <aio.h>

int lio_listio(int mode,struct aiocb *restrict const list[restrict], int nent , struct sigevent *restrict sigev);
    
    -- '成功:0;出错:-1'
  • 参数:

    • argv:异步通知信息
    • mode:I/O是不是真的异步
      • mode=LIO_WAIT:sigev参数被忽略。I/O操做完成后返回。
      • mode=LIO_NOWAIT:放入I/O请求队列后,当即返回。
        • argv = NULL, 完成时,每一个AIO模块自己启动各自异步通知
        • argv = 其它异步通知信息,I/O完成后自动发送。
  • 特色:

readv 和 wrtiev

#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;     '缓冲大小'
}
  • 参数:

    • iov:缓冲区数组
    • iovcnt: 数组个数
  • 特色:

    • 一次函数中读、写多个非连续缓冲区的数据到内核的缓冲区。
    • writev好理解,数组顺序来写。
    • readv则按照数组顺序,将一个数组一个数组填满。
    • 配合真实的read/write。当须要复制数据增长,能极大的减小数据复制。

输入图片说明

存储映射I/O

#include <sys/mman.h>

void  *mmap(void *addr, size_t len, int port,int flag,int fd, off_t off );
        -- '成功:返回映射区的起始地址;出错:MAP_FAILED'
  • 参数:

    • addr:映射存储区的起始位置
    • fd:要被映射文件的描述符。
    • port:映射存储区的保护要求
参数 说明
PROT_READ 映射区可读
PROT_WRITE 映射区可写
PROT_EXEC 映射区可执行
PROT_NONE 映射区不可访问
  • flag:
参数 说明
MAP_FIXED 返回值必须等于addr
MAP_SHARED 本进程对映射区所进行的存储操做的配置
MAP_PRIVATE 对映射区的存储操做致使建立映射文件的一个私有副本
  • 特色:

    • 将一个磁盘文件映射到存储空间的一个缓冲区
相关文章
相关标签/搜索