redis.conf翻譯與配置(六)【redis6.0.6】
3390
2025-04-01
libaio是linux版本的aio庫,aio指的是異步io。這里記錄下libaio的使用,主要過程為:libaio的初始化,io請求的下發和回收,libaio銷毀。
libaio的接口
libaio的初始化
int io_setup(int maxevents, io_context_t *ctxp); // maxevents表示能處理的最大事件數,同時初始化結構io_context_t,調用之前ctxp的內容必須初始化為0
提交IO讀寫請求
long io_submit (io_context_t ctx_id, long nr, struct iocb **iocbpp); // 提交任務前,必須先填充iocb結構體。可以使用io_prep_pwrite和io_prep_pread接口生成iocb的結構體,這其中涉及到fd,需要先open對應的文件,并設置為O_DIRECT標志。另外,buff需要先對齊。 struct io_iocb_common { PADDEDptr(void *buf, __pad1); // 緩存空間 PADDEDul(nbytes, __pad2); // 字節數 long long offset; // 偏移 long long __pad3; unsigned flags; unsigned resfd; }; /* result code is the amount read or -'ve errno */ struct iocb { PADDEDptr(void *data, __pad1); /* Return in the io completion event */ 用戶回調函數,可以通過io_set_callback設置 PADDED(unsigned key, __pad2); /* For use in identifying io requests */ short aio_lio_opcode; short aio_reqprio; int aio_fildes; union { struct io_iocb_common c; struct io_iocb_vector v; struct io_iocb_poll poll; struct io_iocb_sockaddr saddr; } u; }; void io_prep_pread(struct iocb *iocb, int fd, void *buf, size_t count, long long offset) { memset(iocb, 0, sizeof(*iocb)); iocb->aio_fildes = fd; iocb->aio_lio_opcode = IO_CMD_PREAD; iocb->aio_reqprio = 0; iocb->u.c.buf = buf; iocb->u.c.nbytes = count; iocb->u.c.offset = offset; } void io_prep_pwrite(struct iocb *iocb, int fd, void *buf, size_t count, long long offset) { memset(iocb, 0, sizeof(*iocb)); iocb->aio_fildes = fd; iocb->aio_lio_opcode = IO_CMD_PWRITE; iocb->aio_reqprio = 0; iocb->u.c.buf = buf; // 緩存空間 iocb->u.c.nbytes = count; // 字節數 iocb->u.c.offset = offset; // 偏移 } // 這里需要注意:buf必須是按照扇區對齊的(512的倍數),可以使用posix_memalign進行對齊。
(1)為什么是O_DIRECT標志
O_DIRECT標志指采用DIRECT I/O,相對于此,有個Buffered I/O。后者需要將用戶空間的數據拷貝到內核緩存區,然后再拷貝到磁盤,這操作造成了CPU資源和內存資源的浪費。而DIRECT I/O,不需要通過內核緩存數據,直接將用戶空間數據拷貝到磁盤。所以選擇O_DIRECT標志,利于減少內存拷貝和CPU利用率。但是這樣做的話,需要用戶保證內存對齊,否則數據是無法正常寫入的,可以使用posix_memalign進行內存對齊。讀寫緩沖區的地址、內容的大小、文件偏移必須是扇區的倍數(通常是512字節)。
(2)posix_memalign的使用
#include
如果調用posix_memalign()成功時,會返回size字節的動態內存,并且這塊內存的地址是alignment的倍數。參數alignment必須是2的冪,還是void指針的大小的倍數。返回的內存塊的地址放在了memptr里面,函數返回值是0。
如果調用失敗時,沒有內存會被分配,memptr的值沒有被定義,返回如下錯誤碼之一:
EINVAL:參數不是2的冪,或者不是void指針的倍數。
ENOMEM:沒有足夠的內存去滿足函數的請求。
要注意的是,對于這個函數,errno不會被設置,只能通過返回值得到。
由posix_memalign()獲得的內存通過free( )釋放。
IO請求返回
讀寫io請求下發后,使用io_getevents函數等待io結束信號。
int io_getevents(io_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct timespec *timeout); // 返回events數組,events為數組首地址; // nr為數組長度,即最大返回的event數; // min_nr為最少返回的event數; // timieout表示超時時間,填寫NULL表示無等待超時 // io_event的結構體內容: struct io_event {undefined PADDEDptr(void *data, __pad1); PADDEDptr(struct iocb *obj, __pad2); PADDEDul(res, __pad3); PADDEDul(res2, __pad4); }; // res為實際完成的字節數 // res2位讀寫成功的狀態,0表示成功 // obj為io_submit中下發的內容
IO取消或者銷毀
int io_destroy(io_context_t ctx); // 跟io_setup對應 int io_cancel(io_context_t ctx, struct iocb *iocb, struct io_event *evt); // 取消之前通過io_submit傳入的iocb
實例
單獨使用aio
#include
aio和epoll結合
需要使用到io_set_eventfd,將evenfd寫到iocb中,io_set_eventfd的定義如下:
void io_set_eventfd(struct iocb *iocb, int eventfd) { iocb->u.c.flags |= (1 << 0) /* IOCB_FLAG_RESFD */; iocb->u.c.resfd = eventfd; }
具體步驟:
(1)創建eventfd
efd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
(2)將eventfd設置到iocb中
io_set_eventfd(iocb, efd);
(3)提交aio請求
io_submit(ctx, NUM_EVENTS, iocb);
(4)創建epollfd,并將eventfd加到epoll中
epfd = epoll_create(1); epoll_ctl(epfd, EPOLL_CTL_ADD, efd, &epevent); epoll_wait(epfd, &epevent, 1, -1);
(5)當eventfd可讀時,從eventfd讀出完成IO請求的數量,并用io_getevents獲取這些IO
read(efd, &finished_aio, sizeof(finished_aio); r = io_getevents(ctx, 1, NUM_EVENTS, events, &tms);
具體實例:
// aio.cpp #include
參考:
https://blog.csdn.net/enlaihe/article/details/112320114?spm=1001.2014.3001.5506
https://blog.csdn.net/cjsycyl/article/details/9332241 (epoll和aio結合)
https://zhuanlan.zhihu.com/p/145394613?from_voters_page=true (講得挺清楚)
https://blog.csdn.net/brucexu1978/article/details/7085924
Linux
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。