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 對映射區的存儲操做致使建立映射文件的一個私有副本
  • 特色:

    • 將一個磁盤文件映射到存儲空間的一個緩衝區
相關文章
相關標籤/搜索