欧美性猛交xxxx免费看_牛牛在线视频国产免费_天堂草原电视剧在线观看免费_国产粉嫩高清在线观看_国产欧美日本亚洲精品一5区

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

網(wǎng)絡(luò)IO套路分享

Linux愛(ài)好者 ? 來(lái)源:Linux愛(ài)好者 ? 作者:Linux愛(ài)好者 ? 2020-10-13 14:52 ? 次閱讀

轉(zhuǎn)自:我是程序員小賤-L的存在

1 阻塞與非阻塞--開(kāi)胃菜

阻塞

我們知道在調(diào)用某個(gè)函數(shù)的時(shí)候無(wú)非就是兩種情況,要么馬上返回,然后根據(jù)返回值進(jìn)行接下來(lái)的業(yè)務(wù)處理。當(dāng)在使用阻塞IO的時(shí)候,應(yīng)用程序會(huì)被無(wú)情的掛起,等待內(nèi)核完成操作,因?yàn)榇藭r(shí)的內(nèi)核可能將CPU時(shí)間切換到了其他需要的進(jìn)程中,在我們的應(yīng)用程序看來(lái)感覺(jué)被卡主(阻塞)了。

阻塞IO

傳統(tǒng)阻塞IO模型

傳統(tǒng)阻塞IO模型

特點(diǎn):

通過(guò)阻塞式IO獲取輸入的數(shù)據(jù)

其中每個(gè)連接都采用獨(dú)立的線程完成數(shù)據(jù)輸入,業(yè)務(wù)處理以及數(shù)據(jù)返回的操作

這種方案有什么問(wèn)題?

首先當(dāng)并發(fā)較大的時(shí)候,需要?jiǎng)?chuàng)建大量的線程來(lái)處理連接,需要占用大量的系統(tǒng)資源。

連接建立完成以后,如果當(dāng)前線程沒(méi)有數(shù)據(jù)可讀,將會(huì)阻塞在read操作上造成線程資源的浪費(fèi)

鑒于上面的兩個(gè)問(wèn)題,通常是解決方案是啥呢?

第一種是采用IO復(fù)用的模型,所謂IO復(fù)用模型即多個(gè)連接共享一個(gè)阻塞對(duì)象,應(yīng)用程序只會(huì)在一個(gè)阻塞對(duì)象上等待。當(dāng)某個(gè)連接有新的數(shù)據(jù)處理,操作系統(tǒng)直接通知應(yīng)用程序,線程從阻塞狀態(tài)返回并開(kāi)始業(yè)務(wù)處理

第二種方案即采用線程池復(fù)用的方式。將連接完成后的業(yè)務(wù)處理任務(wù)分配給線程,一個(gè)線程處理多個(gè)連接的業(yè)務(wù)。IO復(fù)用結(jié)合線程池的方案即Reactor模式。

Reactor

從上圖我們可以發(fā)現(xiàn),通過(guò)一個(gè)或者多個(gè)請(qǐng)求傳遞給服務(wù)器,通過(guò)統(tǒng)一的事件管理機(jī)制進(jìn)行請(qǐng)求分發(fā),這種模式即事件驅(qū)動(dòng)處理模式。

通常一個(gè)服務(wù)端處理網(wǎng)絡(luò)請(qǐng)求的過(guò)程是啥樣的?

服務(wù)端處理請(qǐng)求的常規(guī)過(guò)程

服務(wù)端將這些請(qǐng)求分別同步分派給多個(gè)處理線程,即IO多路復(fù)用統(tǒng)一監(jiān)聽(tīng)事件,收到事件再進(jìn)行分發(fā)。那么圖中重要的兩個(gè)關(guān)鍵字是啥意思?

Reactor

在一個(gè)單獨(dú)的線程運(yùn)行,主要負(fù)責(zé)監(jiān)聽(tīng)和分發(fā)事件。就仿佛我們手機(jī)設(shè)置的轉(zhuǎn)接,將來(lái)自前任的電話轉(zhuǎn)接給適當(dāng)?shù)穆?lián)系人

Handlers

主要負(fù)責(zé)處理執(zhí)行IO實(shí)際的事情。

根據(jù)Reactor的數(shù)量和處理的資源大小通常又分為單Reactor線程,單Reactor多線程,主從Reactor多線程。這部分將在文章后面進(jìn)行詳細(xì)闡述,先和大家一起復(fù)習(xí)幾個(gè)基本概念

非阻塞

當(dāng)使用非阻塞函數(shù)的時(shí)候,和阻塞IO類(lèi)比,內(nèi)核會(huì)立即返回,返回后獲得足夠的CPU時(shí)間繼續(xù)做其他的事情。

非阻塞

這樣說(shuō)可能有點(diǎn)不太好理解,試試一個(gè)例子來(lái)

小藍(lán)經(jīng)常去樓下的小賣(mài)部買(mǎi)煙,因?yàn)槟切〗憬愦_實(shí)好看,即使不買(mǎi)去看看也飽了那種。有一天去買(mǎi)煙,讓我等下,他去倉(cāng)庫(kù)看看,就一直在那里等著小姐姐回復(fù),就仿佛阻塞在了小姐姐的店。

那么阻塞IO是個(gè)啥樣子嘞?

小姐姐,今天有黃鶴樓煙沒(méi),小姐姐看看了柜臺(tái),沒(méi)有,到處找也沒(méi)有了,然后告訴我這周沒(méi)有了,下周應(yīng)該會(huì)有貨,好嘛,我寂寞的小手顫抖了,其實(shí)我就是想去小姐姐家買(mǎi)東西,于是下周我又去問(wèn)小姐姐,小姐姐果然有心,就知道我回去她家店買(mǎi),直接給我留了兩包黃鶴樓,就這樣反反復(fù)復(fù),和小姐姐的感情越來(lái)越好,這樣就是阻塞IO的輪詢(xún),我沒(méi)有被阻塞而是不斷地咨詢(xún)小姐姐(輪詢(xún))。

抽煙的人,經(jīng)常一句話就是“這一根抽了就不抽了”,怎么能忍住一周?看來(lái)輪詢(xún)效率太低,直接給小姐姐打電話:“小姐姐,煙到了麻煩通知一聲,我來(lái)你家拿”,這就是IO多路復(fù)用。

感情嘛,最激烈的時(shí)期不外乎是最開(kāi)始的那么兩個(gè)月,不,渣男,怎么可能就兩個(gè)月,感情真是越來(lái)越好,然后我就給小姐姐說(shuō):“小姐姐,我給你個(gè)地址,還有微信,到時(shí)候到貨了麻煩給我寄過(guò)來(lái)”,這尼瑪,不僅加了微信,還給我送到了家,這就是異步IO,至于后續(xù)的故事是怎么樣的想知道?

好勒,就是寫(xiě)IO模型,配上線程/進(jìn)程所向披靡(網(wǎng)絡(luò)編程的核心)

非阻塞IO之讀(繼續(xù)查閱資料)

咱們知道套接字有個(gè)緩沖區(qū),如果緩沖區(qū)沒(méi)有數(shù)據(jù)可讀,那么在非阻塞的情況下調(diào)用read就會(huì)立即返回,返回自然會(huì)有個(gè)狀態(tài),不然我們一臉懵逼,無(wú)法進(jìn)行下一步。返回可能是EWOULDBLOCK或者EAGAIN出錯(cuò)信息。

非阻塞IO之寫(xiě)

剛才我們說(shuō)了,有個(gè)叫做緩沖區(qū)的概念,當(dāng)然也有發(fā)送緩沖區(qū),如果發(fā)送緩沖區(qū)滿了,不能容納更多的字節(jié),這個(gè)時(shí)候操作系統(tǒng)內(nèi)核就會(huì)盡全力從應(yīng)用程序拷貝數(shù)據(jù)到發(fā)送緩沖區(qū)并立即從write調(diào)用返回。在拷貝的過(guò)程中,可能全部拷貝了,也可能一字節(jié)也沒(méi)拷貝,所以使用返回值來(lái)告訴應(yīng)用程序到底有多少數(shù)據(jù)拷貝到了發(fā)送發(fā)送緩沖區(qū),方便再次調(diào)用write,輸出未完成的字節(jié)。

總結(jié)下兩種方式:

阻塞IO是:拷貝-知道所有數(shù)據(jù)拷貝到發(fā)送緩沖區(qū)。

非阻塞IO是拷貝-返回-再拷貝-再返回。ok,read和write的騷操作如下圖

讀寫(xiě)阻塞不同點(diǎn)

說(shuō)了這么多,當(dāng)面試官問(wèn)你的時(shí)候,能不能對(duì)答如流嘞,總結(jié)如下:

read總是在接受緩存區(qū)有數(shù)據(jù)的時(shí)候直接返回,而不是等到應(yīng)用程序哥頂?shù)臄?shù)據(jù)充滿才返回。如果此時(shí)緩沖區(qū)是空的,那么阻塞模式會(huì)等待,非阻塞則會(huì)返回-1并有EWOULDBLOCK或EAGAIN錯(cuò)誤

和read不太一樣的是,在阻塞模式下,write只有在發(fā)送緩沖區(qū)足矣容納應(yīng)用程序的輸出字節(jié)時(shí)才會(huì)返回。在非阻塞的模式下,能寫(xiě)入多少則寫(xiě)入多少,并返回實(shí)際寫(xiě)入的字節(jié)數(shù)

當(dāng)使用fgets等待標(biāo)準(zhǔn)輸入的時(shí)候,如果此時(shí)套接字有數(shù)據(jù)但不能讀出。IO多路復(fù)用意味著可以將標(biāo)準(zhǔn)輸入、套接字等都當(dāng)做IO的一路,任何一路IO有事件發(fā)生,都將通知相應(yīng)的應(yīng)用程序去處理相應(yīng)的IO事件,在我們看來(lái)就反復(fù)同時(shí)可以處理多個(gè)事情。這就是IO復(fù)用。

IO復(fù)用

2 select

當(dāng)使用select函數(shù)的時(shí)候,先通知內(nèi)核掛起進(jìn)程,一旦一個(gè)或者多個(gè)IO事情發(fā)生,控制權(quán)將返回給應(yīng)用程序,然后由應(yīng)用程序進(jìn)行IO處理。

那么IO事件都包含哪些

標(biāo)準(zhǔn)輸入文件描述符可以讀

已連接套接字準(zhǔn)備好可以寫(xiě)

如果一個(gè)IO事件等待超過(guò)10秒,發(fā)生超時(shí)

select使用方法

intselect(intmaxfdp,fd_set*readset,fd_set*writeset,fd_set*exceptset,structtimeval*timeout);

maxfdp 表示待測(cè)試描述符基數(shù),它的值為待測(cè)試最大描述符加1.假設(shè)當(dāng)前的select的測(cè)試描述符集合為{0,1,3},那么這個(gè)時(shí)候maxfd為4,

隨后為三個(gè)描述符集合,分別為讀集合readset,寫(xiě)集合writeset和異常集合exceptset。它們會(huì)通知內(nèi)核,當(dāng)有可讀可寫(xiě)發(fā)生的時(shí)候記得通知它們

如何設(shè)置這些描述符

intFD_ZERO(intfd,fd_set*fdset);//一個(gè)fd_set類(lèi)型變量的所有位都設(shè)為0 intFD_CLR(intfd,fd_set*fdset);//清除某個(gè)位時(shí)可以使用 intFD_SET(intfd,fd_set*fd_set);//設(shè)置變量的某個(gè)位置位 intFD_ISSET(intfd,fd_set*fdset);//測(cè)試某個(gè)位是否被置位

最后一個(gè)參數(shù)是時(shí)間

structtimeval { longtv_sec;/*秒*/ longtv_usec;/*微秒*/ };

設(shè)置為NULL,select會(huì)一直等待下去

設(shè)置非零值,等待固定時(shí)間后返回

將tv_sec和tv_usec均設(shè)置為0,表示不等待,檢測(cè)完畢就返回

程序案例

#include #include #include #include #include #include conststaticintMAXLINE=1024; conststaticintSERV_PORT=10001; intmain() { inti,maxi,maxfd,listenfd,connfd,sockfd; /*nready描述字的數(shù)量*/ intnready,client[FD_SETSIZE]; intn; /*創(chuàng)建描述字集合,由于select函數(shù)會(huì)把未有事件發(fā)生的描述字清零,所以我們?cè)O(shè)置兩個(gè)集合*/ fd_setrset,allset; charbuf[MAXLINE]; socklen_tclilen; structsockaddr_incliaddr,servaddr; /*創(chuàng)建socket*/ listenfd=socket(AF_INET,SOCK_STREAM,0); /*定義sockaddr_in*/ memset(&servaddr,0,sizeof(servaddr)); servaddr.sin_family=AF_INET; servaddr.sin_port=htons(SERV_PORT); servaddr.sin_addr.s_addr=htonl(INADDR_ANY); bind(listenfd,(structsockaddr*)&servaddr,sizeof(servaddr)); listen(listenfd,100); /*listenfd是第一個(gè)描述字*/ /*最大的描述字,用于select函數(shù)的第一個(gè)參數(shù)*/ maxfd=listenfd; /*client的數(shù)量,用于輪詢(xún)*/ maxi=-1; /*init*/ for(i=0;imaxfd)maxfd=connfd; if(i>maxi)maxi=i; if(nready<=1)?continue; ????????????else?nready?--; ????????} ????????for(i=0?;?i<=maxi?;?i++) ????????{ ????????????if?(client[i]<0)?continue; ????????????sockfd?=?client[i]; ????????????if(FD_ISSET(sockfd,&rset)) ????????????{ ????????????????n?=?read(sockfd?,?buf?,?MAXLINE); ????????????????if?(n==0) ????????????????{ ????????????????????/*當(dāng)對(duì)方關(guān)閉的時(shí)候,server關(guān)閉描述字,并將set的sockfd清空*/ ????????????????????close(sockfd); ????????????????????FD_CLR(sockfd,&allset); ????????????????????client[i]?=?-1; ????????????????} ????????????????else ????????????????{ ????????????????????buf[n]=''; ????????????????????printf("Socket?%d?said?:?%s ",sockfd,buf); ????????????????????write(sockfd,buf,n);?//Write?back?to?client ????????????????} ????????????????nready?--; ????????????????if(nready<=0)?break; ????????????} ????????} ????} ????return?0; }

但是他有個(gè)比較明顯的特點(diǎn)就是所支持文件描述符有限,默認(rèn)為1024個(gè),隨機(jī)出現(xiàn)poll

3 poll

鑒于select所支持的描述符有限,隨后提出poll解決這個(gè)問(wèn)題

還是先看聲明

intpoll(structpollfd*fds,nfds_tnfds,inttimeout);

再看pollfd結(jié)構(gòu)

structpollfd{ intfd;/*文件描述符*/ shortevents;/*描述符待檢測(cè)的事件*/ shortrevents;/*returnedevents*/ };

注意下這個(gè)結(jié)構(gòu)體,分別包含了文件描述符和描述符對(duì)應(yīng)的事件,這事件和文件描述符緊密相結(jié)合,其中事件使用二進(jìn)制掩碼表示,如POLLIN代表讀事件,POLLOUT代表寫(xiě)事件。

#definePOLLIN0x0001/*anyreadabledataavailable*/ #definePOLLPRI0x0002/*OOB/Urgentreadabledata*/ #definePOLLOUT0x0004/*filedescriptoriswriteable*/

從結(jié)構(gòu)中可以看見(jiàn)還有個(gè)參數(shù)是revents,從字面意思可知事件備份。對(duì)的,相當(dāng)于將poll每次檢測(cè)的結(jié)果保留在revents,這樣就不需要每次都重置描述符和事件。那到底有哪些事件

可讀事件---系統(tǒng)內(nèi)核會(huì)通知應(yīng)用程序數(shù)據(jù)可讀

#definePOLLIN0x0001/*anyreadabledataavailable*/ #definePOLLPRI0x0002/*OOB/Urgentreadabledata*/ #definePOLLRDNORM0x0040/*non-OOB/URGdataavailable*/ #definePOLLRDBAND0x0080/*OOB/Urgentreadabledata*/

可寫(xiě)事件---系統(tǒng)內(nèi)核會(huì)通知套接字緩沖區(qū)已經(jīng)可以安排,隨后使用write函數(shù)不會(huì)被堵塞

#definePOLLOUT0x0004/*filedescriptoriswriteable*/ #definePOLLWRNORMPOLLOUT/*nowritetypedifferentiation*/ #definePOLLWRBAND0x0100/*OOB/Urgentdatacanbewritten*/

了解函數(shù)返回值

小于0----表示事件發(fā)生前永遠(yuǎn)等待

-1---發(fā)生錯(cuò)誤

0--在指定的而時(shí)間沒(méi)有任何事件發(fā)生

poll和select不同之處在于,在select中,文件描述符個(gè)數(shù)隨著fd_set的實(shí)現(xiàn)而固定,而在poll函數(shù)中,我們可以通過(guò)控制pollfd數(shù)組的大小來(lái)改變描述符的個(gè)數(shù)

案例

#include #include #include #include #include #include #defineINFTIM-1 #definePOLLRDNORM0x040/*Normaldatamayberead.*/ #definePOLLRDBAND0x080/*Prioritydatamayberead.*/ #definePOLLWRNORM0x100/*Writingnowwillnotblock.*/ #definePOLLWRBAND0x200/*Prioritydatamaybewritten.*/ #defineMAXLINE1024 #defineOPEN_MAX16//一些系統(tǒng)會(huì)定義這些宏 #defineSERV_PORT10001 intmain() { inti,maxi,listenfd,connfd,sockfd; intnready; intn; charbuf[MAXLINE]; socklen_tclilen; structpollfdclient[OPEN_MAX]; structsockaddr_incliaddr,servaddr; listenfd=socket(AF_INET,SOCK_STREAM,0); memset(&servaddr,0,sizeof(servaddr)); servaddr.sin_family=AF_INET; servaddr.sin_port=htons(SERV_PORT); servaddr.sin_addr.s_addr=htonl(INADDR_ANY); bind(listenfd,(structsockaddr*)&servaddr,sizeof(servaddr)); listen(listenfd,10); client[0].fd=listenfd; client[0].events=POLLRDNORM; for(i=1;imaxi)maxi=i; nready--; if(nready<=0)?continue; ????????} ????????for(i=1;i<=maxi;i++) ????????{ ????????????if(client[i].fd<0)?continue; ????????????sockfd?=?client[i].fd; ????????????if(client[i].revents?&?(POLLRDNORM|POLLERR)) ????????????{ ????????????????n?=?read(client[i].fd,buf,MAXLINE); ????????????????if(n<=0) ????????????????{ ????????????????????close(client[i].fd); ????????????????????client[i].fd?=?-1; ????????????????} ????????????????else ????????????????{ ????????????????????buf[n]=''; ????????????????????printf("Socket?%d?said?:?%s ",sockfd,buf); ????????????????????write(sockfd,buf,n);?//Write?back?to?client ????????????????} ????????????????nready--; ????????????????if(nready<=0)?break;?//no?more?readable?descriptors ????????????} ????????} ????} ????return?0; }

5 epoll

epoll 通過(guò)監(jiān)控注冊(cè)的多個(gè)描述字,來(lái)進(jìn)行 I/O 事件的分發(fā)處理。不同于 poll 的是,epoll 不僅提供了默認(rèn)的 level-triggered(條件觸發(fā))機(jī)制,還提供了性能更為強(qiáng)勁的edge triggered(邊緣觸發(fā))機(jī)制

在The Linux Programming Interface有張圖展示三種IO復(fù)用技術(shù)在面對(duì)不同文件描述符時(shí)的差異

The Linux Programming Interface

從上圖咱們知道即使10000個(gè)描述符的時(shí)候,常規(guī)的select和poll性能下降明顯,而epoll變化不大

那么epoll是什么操作這么6?

epoll通過(guò)監(jiān)控注冊(cè)多個(gè)描述字進(jìn)行IO事件的分發(fā)。不同poll的是,epoll不僅提供默認(rèn)的level-trigger機(jī)制還提供了邊緣觸發(fā)機(jī)制,這里可以先思考下兩者有什么區(qū)別

編程三步驟

intepoll_create(intsize);

就是通過(guò)它來(lái)創(chuàng)造實(shí)例,這個(gè)返回的值將用于后續(xù)的技能解鎖,如果不需要了這個(gè)實(shí)例,則需要使用close方法來(lái)釋放示例,不要占著坑不拉屎,這樣很不道德。

那這個(gè)size是干撒子的嘞?它告訴內(nèi)核期望監(jiān)控多少個(gè)描述符,然后使用這部分的信息來(lái)初始化內(nèi)核底層的數(shù)據(jù)結(jié)構(gòu),不過(guò)時(shí)代在變化,在現(xiàn)在高版本的實(shí)現(xiàn)中,不在需要這個(gè)參數(shù),自動(dòng)動(dòng)態(tài)化了,高級(jí)了吧。

intepoll_ctl(intepfd,intop,intfd,structepoll_event*event);

創(chuàng)建了實(shí)例,并有了返回值來(lái)標(biāo)識(shí)這個(gè)示例,是時(shí)候添加事件了,此時(shí)就是使用epoll_ctl。第一個(gè)參數(shù)epfd即是上面的返回值。第二個(gè)參數(shù)表示是準(zhǔn)備刪除事件還是監(jiān)控事件,哪都有哪些選項(xiàng)呢

三個(gè)事件

第三個(gè)參數(shù)為注冊(cè)事件的文件描述符比如一個(gè)監(jiān)聽(tīng)字

第四個(gè)參數(shù)表示注冊(cè)的事件類(lèi)型,可以在這個(gè)結(jié)構(gòu)體中自定義數(shù)據(jù)。

intepoll_wait(intepfd,structepoll_event*events,intmaxevents,inttimeout); //返回值:成功返回的是一個(gè)大于0的數(shù),表示事件的個(gè)數(shù);返回0表示的是超時(shí)時(shí)間到;若出錯(cuò)返回-1

epoll_wait函數(shù)和之前的select等類(lèi)似,等待內(nèi)核IO事件的分發(fā)。第一個(gè)參數(shù)為create返回值句柄。第二個(gè)參數(shù)回給用戶(hù)空間需要處理的 I/O 事件。第三個(gè)參數(shù)為一個(gè)大于0的整數(shù),表示epoll_wait可以返回的最大事件值。第四個(gè)參數(shù)是epoll_wait阻塞時(shí)的超時(shí)值,如果設(shè)置為-1表示不超時(shí),如果設(shè)置為0則立即返回。

6 epoll的底層實(shí)現(xiàn)

這部分內(nèi)容,我在之前的文章中提過(guò)且給大家分享過(guò)一篇源碼筆記,大家需要的話也可以微信找我拿。

當(dāng)我們使用epoll_fd增加一個(gè)fd的時(shí)候,內(nèi)核會(huì)為我們創(chuàng)建一個(gè)epitem實(shí)例,講這個(gè)實(shí)例作為紅黑樹(shù)的節(jié)點(diǎn),此時(shí)你就可以BB一些紅黑樹(shù)的性質(zhì),當(dāng)然你如果遇到讓你手撕紅黑樹(shù)的大哥,在最后的提問(wèn)環(huán)節(jié)就讓他寫(xiě)寫(xiě)吧

隨后查找的每一個(gè)fd是否有事件發(fā)生就是通過(guò)紅黑樹(shù)的epitem來(lái)操作

epoll維護(hù)一個(gè)鏈表來(lái)記錄就緒事件,內(nèi)核會(huì)當(dāng)每個(gè)文件有事件發(fā)生的時(shí)候?qū)⒆约旱怯浀竭@個(gè)就緒列表,然后通過(guò)內(nèi)核自身的文件file-eventpoll之間的回調(diào)和喚醒機(jī)制,減少對(duì)內(nèi)核描述字的遍歷,大俗事件通知和檢測(cè)的效率

7 C10K問(wèn)題

這里的C代表并發(fā),10K=10000。雖然現(xiàn)在通過(guò)現(xiàn)成的框架libevent/Netty可以輕松完成這個(gè)目標(biāo),但是在二十多年前,突破這個(gè)并發(fā)量還是非常困難的。那么要同時(shí)支撐這么多用戶(hù),需要從哪些方面考慮呢

文件句柄

我們知道每個(gè)連接代表一個(gè)文件描述符,如果不夠用,新的鏈接將會(huì)被丟棄并產(chǎn)生錯(cuò)誤

連接數(shù)過(guò)多

在Linux中默認(rèn)為1024,但是如果你是root,你可以通過(guò)/etc/sysctl.cong來(lái)修改,使得支持1w個(gè)描述符

文件句柄

系統(tǒng)內(nèi)存

每個(gè)連接不是只占用鏈接套接字那么簡(jiǎn)單,每個(gè)鏈接都需要占用發(fā)送緩沖區(qū)和接收緩沖區(qū),不信我們看看

系統(tǒng)內(nèi)存

上面三個(gè)值分別代表的是最小分配值、默認(rèn)分配至和最大分配至,這樣如果1w個(gè)連接需要消耗

發(fā)送接收緩沖區(qū)

此時(shí)假設(shè)一個(gè)連接需要128K緩沖區(qū),那么 1w 個(gè)連接大約需要 1.2G 應(yīng)用層緩沖,所以支持w的連接不是內(nèi)存的問(wèn)題。

網(wǎng)絡(luò)帶寬

假設(shè)當(dāng)前10個(gè)連接,其中每個(gè)鏈接傳輸大約1KB的數(shù)據(jù),那么帶寬需要10 * 10000 * 1KB/s * 8=80MBPS。在現(xiàn)在看來(lái)也是很一般了

那么如何解決C10K問(wèn)題?

一方面需要考慮到IO,也就是上面說(shuō)的阻塞IO和非阻塞IO

如何分配進(jìn)程,線程的資源服務(wù)上w的連接

阻塞IO與進(jìn)程

這個(gè)好理解,來(lái)個(gè)連接我就分配個(gè)進(jìn)程(fork)去處理,這個(gè)進(jìn)程處理此鏈接的所有IO,不管是阻塞還是非阻塞IO,多個(gè)連接也不會(huì)產(chǎn)生影響,畢竟進(jìn)程之間有著各自的進(jìn)程空間

進(jìn)程是程序執(zhí)行的最小單位,一個(gè)進(jìn)程有著完整的地址空間,程序計(jì)數(shù)器,想要?jiǎng)?chuàng)建一個(gè)進(jìn)程,使用fork即可,fork后會(huì)在父子進(jìn)程中各返回一次,如果返回值為0則是子進(jìn)程,隨后父子進(jìn)程處理各自的邏輯

fork

創(chuàng)建完進(jìn)程執(zhí)行了任務(wù),當(dāng)要離開(kāi)的時(shí)候需要清理干凈資源,如果退出了還將進(jìn)程的相關(guān)信息留下,不回收就會(huì)變?yōu)榻┦M(jìn)程。這些僵尸進(jìn)程不是沒(méi)人管了,會(huì)交給一個(gè)叫做init的進(jìn)程,如果僵尸進(jìn)程太多,勢(shì)必會(huì)占用太多的內(nèi)存空間甚至耗盡我們的系統(tǒng)資源。

那如果想主動(dòng)的回收這些資源,怎么辦呢?

處理子進(jìn)程退出一般是注冊(cè)一個(gè)信號(hào)處理函數(shù),然后捕捉信號(hào)SIGCHILD信號(hào),在信號(hào)處理函數(shù)中調(diào)用waitpid函數(shù)完成資源的回收即可。

假設(shè)此時(shí)服務(wù)端開(kāi)始監(jiān)聽(tīng),兩個(gè)客戶(hù)端AB分別連接服務(wù)端,客戶(hù)端A發(fā)起請(qǐng)求后,連接成立返回新的套接字叫做連接套接字,此時(shí)父進(jìn)程派生子進(jìn)程,在子進(jìn)程中使用連接套接字和客戶(hù)端通信,所以這個(gè)時(shí)候子進(jìn)程不關(guān)心監(jiān)聽(tīng)套接字。父進(jìn)程則相反,服務(wù)交給子進(jìn)程后,不再關(guān)心連接套接字,而是關(guān)心監(jiān)聽(tīng)套接字,如下圖所示

客戶(hù)端A發(fā)起連接

缺點(diǎn):效率不高,擴(kuò)展性較差且資源占用率高

此時(shí)客戶(hù)端B發(fā)來(lái)新的請(qǐng)求,accept返回新的已連接套接字,父進(jìn)程又派生子進(jìn)程

客戶(hù)端B發(fā)起請(qǐng)求

部分實(shí)現(xiàn)

while(1) { if((conn=accept(listenfd,(structsockaddr*)&peeraddr,&peerlen))

缺點(diǎn):效率不高,擴(kuò)展性較差且資源占用率高,注意事項(xiàng)

對(duì)套接字的關(guān)閉

子進(jìn)程的回收

阻塞IO+線程

剛才不是說(shuō)進(jìn)程占用資源多么,那么就是用線程唄。單進(jìn)程中可以有多個(gè)線程,每個(gè)線程都有自己的上下文,包括唯一標(biāo)識(shí)的線程ID 程序計(jì)數(shù)器等,同一個(gè)進(jìn)程的多個(gè)線程共享整個(gè)虛擬地址空間,其中包含了代碼、數(shù)據(jù)、堆。

為什么線程的上下文的開(kāi)銷(xiāo)比進(jìn)程少呢

我們的代碼是交給CPU執(zhí)行的,程序計(jì)數(shù)器會(huì)告訴CPU代碼執(zhí)行到哪兒了,寄存器呢會(huì)存儲(chǔ)當(dāng)前計(jì)算的中間值,內(nèi)存存放當(dāng)前使用的變量,當(dāng)切換到另外的計(jì)算場(chǎng)景的時(shí)候,需要重新載入新的值,這個(gè)時(shí)候就出現(xiàn)了上下文的切換

現(xiàn)在每個(gè)連接由一個(gè)線程處理

do{ acceptconnections pthread_createforconnecedconnectionfd thread_run(fd) }while(true)

主線程負(fù)責(zé)監(jiān)聽(tīng)連接請(qǐng)求

while(1) { //服務(wù)一直在運(yùn)行,直到被某個(gè)操作或命令終止該進(jìn)程 intrecvbytes; socklen_tlength=sizeof(cliaddr); //accept()函數(shù)讓服務(wù)器接收客戶(hù)的連接請(qǐng)求 intclientfd=accept(servfd,(structsockaddr*)&cliaddr,&length); if(clientfd

每個(gè)客戶(hù)連接的線程函數(shù)

void*recv_msg_from_client(void*arg) { //分離線程,使主線程不必等待此線程 pthread_detach(pthread_self()); intclientfd=*(int*)arg; intrecvBytes=0; char*recvBuf=newchar[BUFFER_SIZE]; memset(recvBuf,0,BUFFER_SIZE); while(1) { if((recvBytes=recv(clientfd,recvBuf,BUFFER_SIZE,0))<=?0)? ????????{ ????????????perror("recv出錯(cuò)! "); ????????????return?NULL; ????????} ????????recvBuf[recvBytes]=''; ????????printf("recvBuf:%s ",?recvBuf); ????} ????close(clientfd); ????return?NULL; }

可是頻繁的創(chuàng)建線程也還是比較耗資源,這樣子是不是可以使用線程池提前創(chuàng)建一波線程,多個(gè)連接復(fù)用它即可

線程池

上面程序雖然可以較好地處理連接,但是如果并發(fā)較多,就會(huì)引起線程的頻繁切換和銷(xiāo)毀,怎們優(yōu)化?

我們?cè)诜?wù)端啟動(dòng)的時(shí)候,預(yù)先分配固定大小的多個(gè)線程,當(dāng)新連接建立的時(shí)候,從連接隊(duì)列中取出這個(gè)連接描述字進(jìn)程處理

主線程與工作線程

細(xì)心地同學(xué)可能發(fā)現(xiàn),既要從隊(duì)列取數(shù)據(jù),也會(huì)從隊(duì)列寫(xiě)數(shù)據(jù),會(huì)不會(huì)有混亂。是的,所以通常還會(huì)使用mutex和條件變量進(jìn)行加持。

但是不是每個(gè)鏈接都是需要時(shí)刻服務(wù),每次創(chuàng)建線程還是比較消耗資源,那就提前創(chuàng)建一批線程,所謂線程池,復(fù)用線程池來(lái)獲取某種效率的提升

線程池

非阻塞 I/O + readiness notification + 單線程

我們的程序可以通過(guò)輪詢(xún)的方式對(duì)套接字進(jìn)行挨個(gè)訪問(wèn),從而找出進(jìn)行IO處理的套接字。

在這里插入圖片描述

描述符少還行,如果太多,每次的循環(huán)將消耗大量的CPU時(shí)間,而且可能循環(huán)完了都沒(méi)發(fā)現(xiàn)一個(gè)套接字可以讀寫(xiě)。既然這樣,我們直接交給操作系統(tǒng),讓它告訴我們哪些套接字可以讀寫(xiě)。程序就變?yōu)檫@樣

poll

我們每次dispatch就相當(dāng)于對(duì)所有的套接字進(jìn)行排查,這樣顯然效率不是很高。如果dispatch之后只提供有IO事件或者IO變化的套接字就好了,這就是epoll的設(shè)計(jì)

epoll

非阻塞 I/O + readiness notification + 多線程

上述幾種方案都是在一個(gè)線程分發(fā),顯然沒(méi)有利用當(dāng)今的多核技術(shù),我們完全可以讓每個(gè)核作為一個(gè)IO分發(fā)器進(jìn)行事件的分發(fā),這其實(shí)就是reactor模式,也是后續(xù)將談到的事件驅(qū)動(dòng)。

單Reactor多線程

8 事件驅(qū)動(dòng)

事件驅(qū)動(dòng)也叫做反應(yīng)堆模型或者Event loop模型,重要的是兩點(diǎn)

通過(guò)poll、epoll等IO分發(fā)技術(shù)實(shí)現(xiàn)一個(gè)無(wú)限循環(huán)的事件分發(fā)線程

將所有的IO事件抽象為事件,每個(gè)事件設(shè)置回調(diào)函數(shù)

在處理大部分網(wǎng)絡(luò)程序的時(shí)候,無(wú)外乎處理一下幾個(gè)事兒

從套接字讀取數(shù)據(jù)

對(duì)收到的數(shù)據(jù)進(jìn)行解析

根據(jù)解析的內(nèi)容進(jìn)行計(jì)算處理

處理后的結(jié)果按照約定的格式編碼

通過(guò)套接字發(fā)送出去

那么之前我們說(shuō)了使用fork子進(jìn)程的方式實(shí)現(xiàn)通信,隨著客戶(hù)端的增多,處理效率不高,因?yàn)閒ork的開(kāi)銷(xiāo)太大

fork

為什么說(shuō)事件驅(qū)動(dòng)是一種高性能,高并發(fā)的模式?

既然這么牛皮,當(dāng)然有它的特點(diǎn)。舉個(gè)例子,來(lái)成都一個(gè)月,印象特別深刻卻是到處都是咖啡館,點(diǎn)一杯咖啡坐著一邊喝一邊看妹子,服務(wù)員小姐姐也不會(huì)找我,只有當(dāng)我去續(xù)杯的時(shí)候,再找小姐姐勾搭(觸發(fā)事件了),小姐姐滿足了我的需求,我就接著邊喝咖啡邊看其他小姐姐,這就是事件驅(qū)動(dòng)??磦€(gè)圖

事件驅(qū)動(dòng)

為了模式整體的效率,不能因?yàn)樘幚順I(yè)務(wù)邏輯導(dǎo)致IO事件處理的效率下降,所以我們決定將注入XML文件的解析,數(shù)據(jù)庫(kù)的查找等工作放在其他線程中,所謂將這些工作和反應(yīng)堆線程解耦。讓這個(gè)反應(yīng)堆只處理IO相關(guān)任務(wù),業(yè)務(wù)邏輯這些操作分成小任務(wù)放在線程池中讓其他空閑的線程處理。處理完后再交給反應(yīng)堆,然后發(fā)送出去

拆分業(yè)務(wù)邏輯

主從Reactor

ok,咱們已經(jīng)知道使用Reactor反應(yīng)堆的方式同時(shí)分發(fā)Acceptor上的連接建立事件,但是我們還是沒(méi)有完全實(shí)現(xiàn)解耦,這個(gè)Reactor線程既要分發(fā)連接建立,還要分發(fā)已經(jīng)建立連接的IO,如果太多的客戶(hù)請(qǐng)求是不是會(huì)處理不過(guò)來(lái),那么能不能讓其分離嘞

主從Reactor

我們看看主從reactor的方式,思路很清晰,主reactor主負(fù)責(zé)分發(fā)Acceptor連接建立,然后已經(jīng)聯(lián)機(jī)的IO事件交給sub-reactor,這個(gè)sub-reactor的數(shù)量可以根據(jù)CPU的核數(shù)來(lái)定。

假設(shè)咱們是一個(gè)四核的CPU,設(shè)置sub-reactor為4.這個(gè)時(shí)候4個(gè)反應(yīng)堆同時(shí)干活,是不是增強(qiáng)了IO分發(fā)處理的效率,因?yàn)槎嗪瞬僮?,也大大的減少并發(fā)處理的鎖開(kāi)銷(xiāo)。

多Reactor

epoll

上面說(shuō)了poll的reactor反應(yīng)堆模式,和poll相比,epoll可謂更加高效的事件機(jī)制。

如何切換到epoll呢

在lib/event_loop.c中的event_loop_init_with_name中,可以發(fā)現(xiàn)通過(guò)宏EPOLL_ENABEL來(lái)決定使用哪一個(gè)

EPOLL_ENABEL

然后我們?cè)诟夸浿胁榭碈MakeLists.txt文件,如果系統(tǒng)中有epoll_create就會(huì)自動(dòng)開(kāi)啟EPOLL_ENALE,如果沒(méi)有則采用默認(rèn)的poll作為事件分發(fā)機(jī)制。

EPOLL_ENALE

這還沒(méi)完,我們需要讓編譯器知道這個(gè)宏,所以需要讓CMake往config.h文件寫(xiě)入這個(gè)宏的最終值。

配置config.h

那么,為啥epoll的性能就比poll更好呢

首先poll和select,在使用之前需要一個(gè)感興趣的事件集合,系統(tǒng)內(nèi)核通過(guò)它構(gòu)建相應(yīng)的數(shù)據(jù)結(jié)構(gòu)并注冊(cè),epoll卻不是,它會(huì)維護(hù)一個(gè)全局的事件集合,通過(guò)epoll的句柄操作這個(gè)集合,操作系統(tǒng)內(nèi)核不需要每次重新掃描整個(gè)集合

使用poll或者select的時(shí)候,應(yīng)用程序需要掃描整個(gè)感興趣的事件集合并找出活動(dòng)的事件,如果請(qǐng)求量過(guò)大,掃描一次花費(fèi)的時(shí)間就太長(zhǎng)。而epoll不是,epoll直接返回活動(dòng)的事件,減少大量的掃描時(shí)間。

那么邊緣觸發(fā)與條件觸發(fā)到底是啥意思

如果某個(gè)套接字有1000個(gè)字節(jié)需要讀,兩個(gè)方案都會(huì)產(chǎn)生read ready notification,如果應(yīng)用程序只讀了500字節(jié),就會(huì)陷入等待,對(duì)于條件觸發(fā)就不一樣,它會(huì)因?yàn)檫€有500字節(jié)而不斷地產(chǎn)生read ready notification

異步IO

用程序告知內(nèi)核啟動(dòng)某個(gè)操作,并讓內(nèi)核在整個(gè)操作(包括將數(shù)據(jù)從內(nèi)核拷貝到應(yīng)用程序的緩沖區(qū))完成后通知應(yīng)用程序。那么和信號(hào)驅(qū)動(dòng)有啥不一樣?

異步IO

信號(hào)驅(qū)動(dòng)IO試內(nèi)核通知應(yīng)用程序什么時(shí)候啟動(dòng)一個(gè)IO操作。而異步IO模型是由內(nèi)核通知應(yīng)用程序啥時(shí)候完成。

異步IO的主要優(yōu)點(diǎn)是充分的利用DMA特性。缺點(diǎn)是,如果要完成真正的異步IO,對(duì)于操作系統(tǒng)的壓力較大,需要做大量的工作。

現(xiàn)在我們已經(jīng)知道了阻塞IO 非阻塞IO,以及通過(guò)select epoll poll等IO多路復(fù)用并結(jié)合線程池的方案實(shí)現(xiàn)高性能的網(wǎng)絡(luò)框架。但是還有個(gè)與之相對(duì)應(yīng)叫做proactor的網(wǎng)絡(luò)驅(qū)動(dòng)模式,兩者有什么區(qū)別?

在windows中這一套完整的支持套接字的異步編程接口叫做IOCP,和Reactor模式一樣之處在于,也存在一個(gè)無(wú)限循環(huán)的event loop線程的,但是不同于Reactor模式,這個(gè)線程不負(fù)責(zé)處理IO調(diào)用,只是負(fù)責(zé)在對(duì)應(yīng)的read,write操作完成的情況下,分發(fā)完成事件道不同的處理函數(shù)。簡(jiǎn)單的一句話總結(jié)即Reactor模式基于待完成的IO事件,而Proactor模式基于已完成的IO事件。

責(zé)任編輯:xj

原文標(biāo)題:「網(wǎng)絡(luò)IO套路」當(dāng)時(shí)就靠它追到女友

文章出處:【微信公眾號(hào):Linux愛(ài)好者】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 網(wǎng)絡(luò)
    +關(guān)注

    關(guān)注

    14

    文章

    7600

    瀏覽量

    89303
  • 編程
    +關(guān)注

    關(guān)注

    88

    文章

    3640

    瀏覽量

    94032
  • 異步
    +關(guān)注

    關(guān)注

    0

    文章

    62

    瀏覽量

    18110
  • 阻塞
    +關(guān)注

    關(guān)注

    0

    文章

    24

    瀏覽量

    8144

原文標(biāo)題:「網(wǎng)絡(luò)IO套路」當(dāng)時(shí)就靠它追到女友

文章出處:【微信號(hào):LinuxHub,微信公眾號(hào):Linux愛(ài)好者】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    借助IO-Link收發(fā)器簡(jiǎn)化微控制器設(shè)計(jì)

    IO-Link是24 V、3線工業(yè)通信標(biāo)準(zhǔn),支持工業(yè)從站和IO-Link主站之間的點(diǎn)對(duì)點(diǎn)通信,進(jìn)而與更高級(jí)別的過(guò)程控制網(wǎng)絡(luò)進(jìn)行通信。
    的頭像 發(fā)表于 01-03 11:02 ?1213次閱讀
    借助<b class='flag-5'>IO</b>-Link收發(fā)器簡(jiǎn)化微控制器設(shè)計(jì)

    一體式遠(yuǎn)程IO的Profinet通信協(xié)議模組-三格電子

    ,采用實(shí)時(shí)(RT)通訊功能,符合:GB/T 25105-2014《工業(yè)通信網(wǎng)絡(luò)現(xiàn)場(chǎng)總線規(guī)范類(lèi)型 10: PROFINET IO 規(guī)范》,IEC 61158-5-10:2007,IDT。 產(chǎn)品外觀 產(chǎn)品選型 設(shè)備參數(shù) 審核編
    的頭像 發(fā)表于 12-26 14:12 ?173次閱讀
    一體式遠(yuǎn)程<b class='flag-5'>IO</b>的Profinet通信協(xié)議模組-三格電子

    λ-IO:存儲(chǔ)計(jì)算下的IO棧設(shè)計(jì)

    動(dòng)機(jī)和背景? ? 存儲(chǔ)計(jì)算存儲(chǔ)資源的充分利用。IO棧是管理存儲(chǔ)器的的基本組件,包括設(shè)備驅(qū)動(dòng)、塊接口層、文件系統(tǒng),目前一些用戶(hù)空間IO庫(kù)(如SPDK)有效降低了延遲,但是io棧仍然不可或缺。這是因?yàn)?
    的頭像 發(fā)表于 12-02 10:35 ?276次閱讀
    λ-<b class='flag-5'>IO</b>:存儲(chǔ)計(jì)算下的<b class='flag-5'>IO</b>棧設(shè)計(jì)

    一文解讀Linux 5種IO模型

    Linux里有五種IO模型:阻塞IO、非阻塞IO、多路復(fù)用IO、信號(hào)驅(qū)動(dòng)式IO和異步IO,我發(fā)現(xiàn)
    的頭像 發(fā)表于 11-09 11:12 ?436次閱讀
    一文解讀Linux 5種<b class='flag-5'>IO</b>模型

    本地IO與遠(yuǎn)程IO:揭秘工業(yè)自動(dòng)化中的兩大關(guān)鍵角色

    在工業(yè)自動(dòng)化領(lǐng)域,IO(Input/Output,輸入/輸出)模塊扮演著至關(guān)重要的角色。它們作為連接控制系統(tǒng)與現(xiàn)場(chǎng)設(shè)備的橋梁,負(fù)責(zé)數(shù)據(jù)的采集與指令的執(zhí)行。然而,隨著技術(shù)的不斷進(jìn)步,IO模塊也分為本地IO和遠(yuǎn)程
    的頭像 發(fā)表于 10-08 18:06 ?581次閱讀

    MCU IO口的作用和特點(diǎn)

    MCU(微控制器)的IO口(Input/Output Port,輸入輸出端口)是單片機(jī)與外界進(jìn)行信息交互的關(guān)鍵接口。這些IO口在微控制器的功能實(shí)現(xiàn)中扮演著至關(guān)重要的角色,它們不僅負(fù)責(zé)數(shù)據(jù)的輸入和輸出,還承載著電平轉(zhuǎn)換、中斷處理、功能復(fù)用等多種功能。以下是對(duì)MCU
    的頭像 發(fā)表于 09-30 11:52 ?1232次閱讀

    FPGA-5G通信算法的基本套路

    5G通信的風(fēng)口雖然經(jīng)過(guò)近3年的洗禮,熱度稍減,但不可否認(rèn)的是,全球5G網(wǎng)絡(luò)的部署正在持續(xù)快速推進(jìn),而我國(guó)更是部署了占據(jù)全球70% 左右的5G基站。 隨著工業(yè)互聯(lián)網(wǎng)的推進(jìn),“5G+工業(yè)互聯(lián)網(wǎng)”的企業(yè)
    發(fā)表于 08-15 17:34

    IO與PLC的差異及應(yīng)用

    為您介紹io模塊與PLC的差異及其各自的應(yīng)用場(chǎng)景
    的頭像 發(fā)表于 07-18 15:54 ?1678次閱讀
    <b class='flag-5'>IO</b>與PLC的差異及應(yīng)用

    初識(shí)IO-Link及IO-Link設(shè)備軟件協(xié)議棧

    亞信IO-Link設(shè)備軟件協(xié)議棧是基于亞信電子AXM-IOLS IO-Link設(shè)備評(píng)估板設(shè)計(jì)的,搭載意法半導(dǎo)體 STM32F469AI微控制器,并在STM32CubeIDE開(kāi)發(fā)環(huán)境中進(jìn)行開(kāi)發(fā)。此
    的頭像 發(fā)表于 07-08 13:55 ?3021次閱讀
    初識(shí)<b class='flag-5'>IO</b>-Link及<b class='flag-5'>IO</b>-Link設(shè)備軟件協(xié)議棧

    什么是遠(yuǎn)程IO模塊?它有哪些分類(lèi)?

    在工業(yè)自動(dòng)化和遠(yuǎn)程監(jiān)控的領(lǐng)域中,遠(yuǎn)程IO模塊(Remote Input/Output Module)扮演著至關(guān)重要的角色。它不僅擴(kuò)展了設(shè)備的輸入和輸出能力,還通過(guò)網(wǎng)絡(luò)或其他通信方式實(shí)現(xiàn)了遠(yuǎn)程數(shù)據(jù)采集
    的頭像 發(fā)表于 06-15 15:59 ?2096次閱讀

    遠(yuǎn)程IO與分布式IO的區(qū)別

    在工業(yè)自動(dòng)化和控制系統(tǒng)設(shè)計(jì)中,遠(yuǎn)程IO(Input/Output)和分布式IO是兩個(gè)重要的概念。它們各自具有獨(dú)特的特點(diǎn)和優(yōu)勢(shì),適用于不同的應(yīng)用場(chǎng)景。本文將詳細(xì)探討遠(yuǎn)程IO與分布式IO
    的頭像 發(fā)表于 06-15 15:57 ?2879次閱讀

    智嵌物聯(lián)網(wǎng)絡(luò)IO控制器接入智嵌云控演示

    智嵌物聯(lián)的網(wǎng)絡(luò)IO控制器(云版本)支持接入智嵌云,實(shí)現(xiàn)設(shè)備的遠(yuǎn)程控制與檢測(cè)。本文檔以智嵌的4路網(wǎng)絡(luò)IO控制器為例,介紹設(shè)備接入智嵌云的方法,以及實(shí)現(xiàn)網(wǎng)頁(yè)控制及手機(jī)APP控制的方法。
    的頭像 發(fā)表于 05-30 09:26 ?597次閱讀
    智嵌物聯(lián)<b class='flag-5'>網(wǎng)絡(luò)</b><b class='flag-5'>IO</b>控制器接入智嵌云控演示

    使用IO-Link技術(shù)能帶來(lái)哪些優(yōu)勢(shì)?細(xì)數(shù)IO-Link八大優(yōu)勢(shì)

    IO-Link是國(guó)際標(biāo)準(zhǔn)化的跨供應(yīng)商IO技術(shù),能夠?qū)崿F(xiàn)從控制系統(tǒng)到傳感器/執(zhí)行器級(jí)別的雙向通信。
    的頭像 發(fā)表于 03-08 13:40 ?1079次閱讀

    如何去提高EtherCAT IO的性能呢?

    進(jìn)行EtherCAT IO性能優(yōu)化涉及多個(gè)方面,包括硬件選擇、網(wǎng)絡(luò)配置、軟件優(yōu)化和應(yīng)用程序設(shè)計(jì)。
    的頭像 發(fā)表于 03-07 09:28 ?610次閱讀

    簡(jiǎn)單說(shuō)一下阻塞IO、非阻塞IO、IO復(fù)用的區(qū)別?

    對(duì)于計(jì)算機(jī)而言,任何涉及到計(jì)算機(jī)核心(CPU和內(nèi)存)與其他設(shè)備間的數(shù)據(jù)轉(zhuǎn)移的過(guò)程就是IO
    的頭像 發(fā)表于 03-04 15:14 ?1443次閱讀
    簡(jiǎn)單說(shuō)一下阻塞<b class='flag-5'>IO</b>、非阻塞<b class='flag-5'>IO</b>、<b class='flag-5'>IO</b>復(fù)用的區(qū)別?