【轉】linux非同步io機制
Linux的I/O機制經歷了一下幾個階段的演進:
1. 同步阻塞I/O: 使用者程式進行I/O操作,一直阻塞到I/O操作完成為止。
2. 同步非阻塞I/O: 使用者程式可以通過設定檔案描述符的屬性O_NONBLOCK,I/O操作可以立即返回,但是並不保證I/O操作成功。
3. 非同步事件阻塞I/O: 使用者程式可以對I/O事件進行阻塞,但是I/O操作並不阻塞。通過select/poll/epoll等函式呼叫來達到此目的。
4. 非同步時間非阻塞I/O: 也叫做非同步I/O(AIO),使用者程式可以通過向核心發出I/O請求命令,不用等帶I/O事件真正發生,可以繼續做
另外的事情,等I/O操作完成,核心會通過函式回撥或者訊號機制通知使用者程式。這樣很大程度提高了系統吞吐量。
下面就AIO做詳細介紹:
要使用aio的功能,需要include標頭檔案aio.h,在編譯連線的時候需要加入POSIX實時擴充套件庫rt.下面就aio庫的使用做介紹。
1. AIO整個過程所使用的資料存放在一個結構體中,struct aiocb,aio control block.看看標頭檔案中的定義:
/* Asynchronous I/O control block. */
struct aiocb
{
int aio_fildes; /* File desriptor. */ 需要在哪個檔案描述符上進行I/O
int aio_lio_opcode; /* Operation to be performed. */ 這個是針對批量I/O的情況有效,讀寫操作型別
int aio_reqprio; /* Request priority offset. */ 請求優先順序(If _POSIX_PRIORITIZED_IO is defined, and this file supports it, then the
asynchronous operation is submitted at a priority equal to that of the
calling process minus aiocbp->aio_reqprio.)
volatile void *aio_buf; /* Location of buffer. */ 具體內容,資料快取
size_t aio_nbytes; /* Length of transfer. */ 資料快取的長度
struct sigevent aio_sigevent; /* Signal number and value. */ 用於非同步I/O完成後的通知。
內部實現使用的資料成員。
/* Internal members. */
struct aiocb *__next_prio;
int __abs_prio;
int __policy;
int __error_code;
__ssize_t __return_value;
#ifndef __USE_FILE_OFFSET64
__off_t aio_offset; /* File offset. */
char __pad[sizeof (__off64_t) - sizeof (__off_t)];
#else
__off64_t aio_offset; /* File offset. */ 檔案讀寫偏移
#endif
char __unused[32];
};
2. int aio_read(struct aiocb *aiocbp);
非同步讀操作,向核心發出讀的命令,傳入的引數是一個aiocb的結構,比如
struct aiocb myaiocb;
memset(&aiocb , 0x00 , sizeof(myaiocb));
myaiocb.aio_fildes = fd;
myaiocb.aio_buf = new char[1024];
myaiocb.aio_nbytes = 1024;
if (aio_read(&myaiocb) != 0)
{
printf("aio_read error:%s\n" , strerror(errno));
return false;
}
3. int aio_write(struct aiocb *aiocbp);
非同步寫操作,向核心發出寫的命令,傳入的引數仍然是一個aiocb的結構,當檔案描述符的O_APPEND
標誌位設定後,非同步寫操作總是將資料新增到檔案末尾。如果沒有設定,則新增到aio_offset指定的
地方,比如:
struct aiocb myaiocb;
memset(&aiocb , 0x00 , sizeof(myaiocb));
myaiocb.aio_fildes = fd;
myaiocb.aio_buf = new char[1024];
myaiocb.aio_nbytes = 1024;
myaiocb.aio_offset = 0;
if (aio_write(&myaiocb) != 0)
{
printf("aio_read error:%s\n" , strerror(errno));
return false;
}
4. int aio_error(const struct aiocb *aiocbp);
如果該函式返回0,表示aiocbp指定的非同步I/O操作請求完成。
如果該函式返回EINPROGRESS,表示aiocbp指定的非同步I/O操作請求正在處理中。
如果該函式返回ECANCELED,表示aiocbp指定的非同步I/O操作請求已經取消。
如果該函式返回-1,表示發生錯誤,檢查errno。
5. ssize_t aio_return(struct aiocb *aiocbp);
這個函式的返回值相當於同步I/O中,read/write的返回值。只有在aio_error呼叫後
才能被呼叫。
6. int aio_cancel(int fd, struct aiocb *aiocbp);
取消在檔案描述符fd上的aiocbp所指定的非同步I/O請求。
如果該函式返回AIO_CANCELED,表示操作成功。
如果該函式返回AIO_NOTCANCELED,表示取消操作不成功,使用aio_error檢查一下狀態。
如果返回-1,表示發生錯誤,檢查errno.
7. int lio_listio(int mode, struct aiocb *restrict const list[restrict],
int nent, struct sigevent *restrict sig);
使用該函式,在很大程度上可以提高系統的效能,因為再一次I/O過程中,OS需要進行
使用者態和核心態的切換,如果我們將更多的I/O操作都放在一次使用者太和核心太的切換中,
減少切換次數,換句話說在核心儘量做更多的事情。這樣可以提高系統的效能。
使用者程式提供一個struct aiocb的陣列,每個元素表示一次AIO的請求操作。需要設定struct aiocb
中的aio_lio_opcode資料成員的值,有LIO_READ,LIO_WRITE和LIO_NOP。
nent表示陣列中元素的個數。最後一個引數是對AIO操作完成後的通知機制的設定。
8. 設定AIO的通知機制,有兩種通知機制:訊號和回撥
(1).訊號機制
首先我們應該捕獲SIGIO訊號,對其作處理:
struct sigaction sig_act;
sigempty(&sig_act.sa_mask);
sig_act.sa_flags = SA_SIGINFO;
sig_act.sa_sigaction = aio_handler;
struct aiocb myaiocb;
bzero( (char *)&myaiocb, sizeof(struct aiocb) );
myaiocb.aio_fildes = fd;
myaiocb.aio_buf = malloc(BUF_SIZE+1);
myaiocb.aio_nbytes = BUF_SIZE;
myaiocb.aio_offset = next_offset;
myaiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
myaiocb.aio_sigevent.sigev_signo = SIGIO;
myaiocb.aio_sigevent.sigev_value.sival_ptr = &myaiocb;
ret = sigaction( SIGIO, &sig_act, NULL );
訊號處理函式的實現:
void aio_handler( int signo, siginfo_t *info, void *context )
{
struct aiocb *req;
if (info->si_signo == SIGIO) {
req = (struct aiocb *)info->si_value.sival_ptr;
if (aio_error( req ) == 0) {
ret = aio_return( req );
}
}
return;
}
(2). 回撥機制
需要設定:
myaiocb.aio_sigevent.sigev_notify = SIGEV_THREAD
my_aiocb.aio_sigevent.notify_function = aio_handler;
回撥函式的原型:
typedef void (* FUNC_CALLBACK)(sigval_t sigval);
AIO機制為伺服器端高併發應用程式提供了一種效能優化的手段。加大了系統吞吐量。
本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/eroswang/archive/2009/04/20/4095163.aspx
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/16179598/viewspace-627277/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- java同步非阻塞IOJava
- Java 非阻塞 IO 和非同步 IOJava非同步
- Linux核心的同步機制(2)(轉)Linux
- Linux核心的同步機制(1)(轉)Linux
- IO模式和IO多路複用(阻塞IO、非阻塞IO、同步IO、非同步IO等概念)模式非同步
- Linux 核心同步機制Linux
- IO - 同步 非同步 阻塞 非阻塞的區別非同步
- Spark IO機制Spark
- 網路IO之阻塞、非阻塞、同步、非同步總結非同步
- linux核心級同步機制--futexLinux
- 談談對不同I/O模型的理解 (阻塞/非阻塞IO,同步/非同步IO)模型非同步
- IO通訊模型(二)同步非阻塞模式NIO(NonBlocking IO)模型模式BloC
- 【轉載】Linux上Oracle啟用非同步IOLinuxOracle非同步
- Linux核心同步機制之(五):Read Write spin lock【轉】Linux
- 深入理解nodejs的非同步IO與事件模組機制NodeJS非同步事件
- Oracle在Linux下使用非同步IO(aio)配置(轉)OracleLinux非同步AI
- 轉:SYBASE在Linux下使用非同步IO(aio)配置Linux非同步AI
- 如何解讀 Java IO、NIO 中的同步阻塞與同步非阻塞?Java
- [轉]阻塞/非阻塞與同步/非同步非同步
- 【進階之路】併發程式設計(三)-非阻塞同步機制程式設計
- Linux的安全機制(轉)Linux
- 11、協程和io教程01 -- 併發 並行 同步 非同步 阻塞 非阻塞 以及 IO多路複用並行非同步
- linux 同步IO: sync、fsync與fdatasyncLinux
- 阻塞IO與非阻塞IO
- 【死磕NIO】— 阻塞IO,非阻塞IO,IO複用,訊號驅動IO,非同步IO,這你真的分的清楚嗎?非同步
- Javascript非同步機制JavaScript非同步
- 核心同步機制 RCU
- 同步機制比較
- 深入剖析setState同步非同步機制非同步
- Linux上Oracle啟用非同步IOLinuxOracle非同步
- IO多路複用機制詳解
- Java網路程式設計和NIO詳解5:Java 非阻塞 IO 和非同步 IOJava程式設計非同步
- 如何給女朋友解釋什麼是IO中的阻塞、非阻塞、同步、非同步?非同步
- 非同步IO,同步IO,Direct IO,FILESYSTEMIO_OPTIONS, DISK_ASYNCH_IO [final]非同步
- 《JAVA併發程式設計實戰》原子變數和非阻塞同步機制Java程式設計變數
- JS執行機制--同步與非同步JS非同步
- 執行緒同步機制執行緒
- Flutter 非同步機制:microtaskFlutter非同步