在內核中,會維護兩個隊列:c++
accept函數會從全鏈接隊列裏取出一個鏈接,若是沒有則阻塞。這裏取出的是一個新的鏈接,叫已鏈接socket,不一樣於一開始建立的監聽socket。Socket在Linux中以文件的形式存在,有本身的文件描述符,讀寫就如同一個文件流。緩存
socket結構裏有一個發送隊列和一個接收隊列,裏面保存着緩存sk_buff,裏面能夠看到完整的包結構。socket
網卡接收到數據後寫入內存,並向CPU發起中斷,操做系統執行中斷程序喚醒對應socket等待隊列裏的進程。
如何同時監聽多個socket:函數
將進程放入全部須要監聽的socket的等待隊列裏,若是有一個socket接收到了數據就喚醒進程,而後遍歷socket列表查看是哪一個socket接收到了數據。spa
int epfd = epoll_create(...) epoll_ctl(epfd, ...) while(1){ int n = epoll_wait(...) for (接收到數據的socket){ //處理 } }
利用epoll_ctl將須要監視的socket添加到epoll_create建立的對象(eventpoll)中,而後利用epoll_wait進行阻塞,將進程放入eventpoll的等待隊列中。當有socket接收到數據,中斷程序將其被eventpoll的就緒列表所(rdllist)引用,而後喚醒進程,進程只須要遍歷就緒列表就能夠了。socket在eventpoll中利用紅黑樹存儲,而就緒列表利用雙向鏈表存儲。操作系統