不得不說為這非同步epoll模型還真是傷了神。。。主要問題就是在libaio的核心通知上,因為這東西實在太低階了,用起來還比較麻煩。我為了不再多開執行緒,實現和iocp基本相同的原理,在proc內部又用了次epoll,使其核心通知和使用者通知都能在乙個執行緒中得到相同處理。並且用map對映eventfd與收發型別的關係,使其能夠在收到event的時候,通過eventfd能直接判斷出接下來的操作。還有就是由於libaio需要將fd設定為o_direct,所以無論收發都得用自己的緩衝區,不然會導致效率大大降低。這份**有興趣自己研究,具體的不多說了,寫出來還沒測試,不知道應用於實際專案中效果如何,大牛可以自己測下
yum install libaio-devel
-lpthread -std=c++11
#include #include#include#include#include#include #include#include#include#include#include #include#include#include#include#include#define recv_events 1024
#define send_events 1024
#define proc_events 1024
#define buf_send_len 1024
#define buf_recv_len 1024
#define recv_len 128
#define send_len 128
using namespace std;
typedef unsigned long long ull;
struct client
;void* createserv(void* args);
void* proc(void* args);
using namespace std;
const int _thread_count = 8;
int _epfd;
int socksrv;
int id = 0;
epoll_event _events[recv_events] = ;
epoll_event ev[_thread_count];
mutex m;
deque_deque;
map_sockmap;
list_removelist;
mutex lock4cv2;
condition_variable cv2;
int _thread_unfinish;
int _eventfd4send[_thread_count];
int _eventfd4recv[_thread_count];
int _proc_epfd[_thread_count];
map_eventfd_type_map;
enum
;int main()
pthread_create(&tid, 0, createserv, 0);
for (int i = 0; i < _thread_count; i++)
cin.get();
cin.get();
return 0;
}bool _isfinish()
void release(int fd)
} close(fd);
}static void recv_callback(io_context_t ctx, struct iocb *iocb, long res, long res2)
void* proc(void* args)
epoll_event* e = _deque.front();
_deque.pop_front();
m.unlock();
if (e->data.fd == -1)
if (e->data.fd == socksrv)
else if (e->events == epollin)
else
}io_submit(ioctx, i, io_submit_arr);
//此處一定要加鎖。當wait還未準備好,但_isfinish剛剛檢測完時_thread_unfinish -= 1;cv2.notify_all();這兩句恰巧在之後執行,那就gg了,兩邊進入互相等待的狀態
lock4cv2.lock();
_thread_unfinish -= 1;
cv2.notify_all();
lock4cv2.unlock();
}else
io_submit(ioctx4write, i, io_submit_arr2);
}num -= r;}}
}threadevents[i].events = 0;
} }}void* createserv(void* args)
_epfd = epoll_create(recv_events);
ev[0].data.fd = socksrv;
ev[0].events = epollin | epollet;
epoll_ctl(_epfd, epoll_ctl_add, socksrv, &ev[0]);
//accept loop
while (true)
while (true)
fcntl(s, f_setfl, o_nonblock | o_direct);
client* c = new client;
posix_memalign((void**)&c->recvbuf, getpagesize(), buf_recv_len);
posix_memalign((void**)&c->sendbuf, getpagesize(), buf_send_len);
c->id = id;
c->fd = s;
id += 1;
_sockmap.insert(pair(s, c));
ev[0].data.fd = s;
ev[0].events = epollin | epollet;
epoll_ctl(_epfd, epoll_ctl_add, s, &ev[0]);
} _thread_unfinish = _thread_count;
for (int i = 0; il(lock4cv2);
cv2.wait(l, _isfinish);
for (auto iter = _removelist.begin(); iter != _removelist.end(); ++iter)
_removelist.clear();
}}
高效通訊模型之 非同步通訊模型
非同步模型 非同步和同步 同步,就是在發出乙個功能呼叫時,在沒有得到結果前,呼叫不返回 非同步,當乙個非同步過程呼叫發出後,呼叫者不能立即得到呼叫結果,而是通過狀態,通知和 來通知呼叫者。通過檢查狀態來判斷非同步呼叫結果,效率會很低,因為需要週期性檢查狀態 函式和通知差不多 同步呼叫與阻塞呼叫 對於...
C SOCKET通訊模型(一)select
為了 簡潔,socket上那些函式的返回錯誤值我就不再捕獲了,windows平台 server.cpp define fd setsize 2048 normal.cpp 定義控制台應用程式的入口點。include stdafx.h include include include include i...
C SOCKET通訊模型(四)IOCP
相比ioevent,iocp沒有事件監聽,而是採用執行緒池管理 其實就是對使用者建立的執行緒的乙個分配管理機制,本身並不會建立多餘額外的執行緒 佇列的形式,這個系統佇列也就是所謂的完成埠,用於核心與應用層的互動。iocp沒有監聽事件數量的限制,沒有事件列表為空需要等待的問題,雖然ioevent沒有i...