12、函數sync、fsync和fdatasync數據庫
延遲寫:傳統的Unix系統在內核中設有緩衝區或頁高速緩衝,大多數磁盤I/O都經過緩衝區進行,當咱們向文件寫入數據時,內核一般先將數據複製到緩衝區,而後排入隊列,晚些時候再寫入磁盤。Unix系統提供了sync、fsync和fdatasync三個函數。安全
#include <unistd.h> int fsync(inf fd); int fdatasync(int fd); //若成功,返回0;若出錯,返回-1 void sync(void);
sync只是將全部修改過的塊緩衝區排入寫隊列,而後就返回,它並不等待實際磁盤操做結束。一般稱爲update的喜歡守護進程週期性地調用sync函數,這就保證了按期沖洗(flush)內核的塊緩衝區。app
fsync函數只對內核文件描述符fd指定的一個文件起做用,而且等待寫磁盤操做結束後才返回,其主要應用場景是數據庫內應用。異步
fdatasync函數相似fsync,但他至響應文件的數據部分。而除數據外,fsync還會更新文件的屬性。async
十3、函數fcntl函數
#include <fcntl.h> int fcntl(int fd, int cmd, .../*int arg*/); //若成功,則依賴於cmd;若出錯,則返回-1
fcntl函數能夠改變已經打開文件的屬性,有如下5個功能:ui
1.複製一個已有的描述符(cmd = F_DUPFD 或 F_DUPED_CLOEXEC)spa
2.獲取、設置文件描述符標誌(cmd = F_GETFD 或 F_SETFD)code
3.獲取、設置文件狀態標誌(cmd = F_GETFL 或 F_SETFL)blog
4.獲取、設置異步I/O全部權(cmd = F_GETOWN 或 F_SETOWN)
5.獲取、設置記錄鎖(cmd = F_GETLK、F_SETLK 或 F_SETLKM)
F_DUPFD : 複製文件描述符fd,新文件描述符做爲函數返回值,它是還沒有打開的各描述符中大於或等於第三個參數值返回。新描述符和fd共享一張文件表項,可是新文件描述符由他本身的一套文件文件描述符標誌。其FD_CLOEXEC文件描述符標誌被清除。
F_DUPED_CLOEXEC: 複製文件描述符,設置與新描述符關聯的FD_CLOEXEC文件描述符標誌的值。
F_GETFD : 對應於fd的文件描述符標誌做爲函數值做爲返回。當前只定義了一個文件描述符標誌FD_CLOEXEC
F_SETFD : 對於fd設置文件描述符標誌。新標誌值按第三個參數設置。
F_GETFL : 對應fd的文件狀態標誌做爲函數值返回,其返回值和open的標誌位一致。
F_SETFL : 將文件狀態標誌設置爲第三個參數的值:能夠更改的幾個標誌是:O_APPEND、O_NONBLOCK、O_SYNC、O_DSYNC、O_RSYNC、O_FSYNC和O_ASYNC
F_FETOWN : 獲取當前接受SIGIO和SIGURG信號的進程或進程組ID
F_SETOWN :設置SIGIO和SIGURG信號的進程ID或進程組ID。正的arg指定一個進程ID,負的arg指定一個進程組ID。
#include "apue.h" #include <fcntl.h> int main(int argc, char *argv[]) { int val; if(argc != 2) { err_quit("usage : a.out <descripor#>"); } if((val = fcntl(atoi(argv[1]), F_GETFL, 0)) < 0) { err_sys("fcntl error for fd %d\n", atoi(argv[1])); } switch(val & O_ACCMODE) { case O_RDONLY: printf("read only"); break; case O_WRONLY: printf("write only"); break; case O_RDWR: printf("read write"); break; default: err_dump("unknow access mode"); } if(val & O_APPEND) { printf(", append"); } if(val & O_NONBLOCK) { printf(", nonblocking"); } if(val & O_SYNC) { printf(", synchronous writes"); } // #if !defined_ ( _POSIX_C_SOURCE) && defined_(O_FSYNC) && (O_FSYNC != O_SYNC) if(val & O_FSYNC) { printf(", synchronous writes"); } // #endif putchar('\n'); exit(0); }
3-5:對於指定的描述符打印文件標誌
在修改文件描述符標誌或文件狀態標誌時必須謹慎,先要得到如今的標誌值,而後定期望值修改他,而後設置新標誌值。不能只是執行F_SETFD或F_SETFL命令,這樣會關閉之前設置的標誌位:
void set_fl(int fd, int flags) { int val; if((val = fcntl(fd, F_GETFL, 0)) < 0) { err_sys("fcntl F_GETFL error"); } val |= flags; if(fcntl(fd, F_SETFL, val) < 0) { err_sys("fcntl F_SETFL error"); } }
3-6:對一個文件描述符開啓一個或多個文件狀態標誌
在Unix系統中,一般write只是將數據排入隊列,而實際的寫磁盤操做則可能在之後的某個時刻進行。而數據庫系統則須要使用O_SYNC,這樣一來,他從write返回時就知道數據已確實寫到了磁盤上,以避免在系統異常時產生數據丟失。數據的安全性獲得了保證,其代價是設置O_SYNC會顯著增長系統時間和時鐘時間。
十4、函數ioctl和/def/fd
iotl函數一直是I/O操做的雜物箱。不能用本章其餘函數表示的I/O操做一般都能用ioctl標識。終端I/O是使用ioctl最多的地方。
較新的系統都提供名爲/dev/fd的目錄,其目錄項是名爲0、一、2等的文件。打開文件/dev/fd/n等效於複製描述符n。