www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁(yè) > > 充電吧
[導(dǎo)讀]RTL8139 網(wǎng)卡性能提升分析3162412793@qq.com技術(shù)交流QQ群:691976956?一、數(shù)據(jù)接收優(yōu)化數(shù)據(jù)接收優(yōu)化,主要是從如下幾個(gè)點(diǎn)出發(fā)進(jìn)行驅(qū)動(dòng)軟件的修改:接收中斷實(shí)現(xiàn)上下部方式,中

RTL8139 網(wǎng)卡性能提升分析

3162412793@qq.com

技術(shù)交流QQ群:691976956

?

一、數(shù)據(jù)接收優(yōu)化

數(shù)據(jù)接收優(yōu)化,主要是從如下幾個(gè)點(diǎn)出發(fā)進(jìn)行驅(qū)動(dòng)軟件的修改:

接收中斷實(shí)現(xiàn)上下部方式,中斷中通過(guò)發(fā)送同步信號(hào)量,收包由一個(gè)阻塞的任務(wù)來(lái)獲取到該信號(hào)量后開始進(jìn)行接收的動(dòng)作。

原始方式:

當(dāng)有網(wǎng)絡(luò)數(shù)據(jù)包接收完畢后,CPU會(huì)進(jìn)中斷服務(wù)程序,中斷服務(wù)中,通過(guò)一個(gè)系統(tǒng)API函數(shù)來(lái)掛接收包任務(wù),那就是netJobAdd,該函數(shù)原形如下:

?? STATUS netJobAdd

???? (

???? FUNCPTR routine, /*在工作程序隊(duì)列中要加的例行程序*/

???? int param1, /*這個(gè)例行程序的第一個(gè)參數(shù)*/

???? int param2, /*這個(gè)例行程序的第二個(gè)參數(shù)*/

???? int param3, /*這個(gè)例行程序的第三個(gè)參數(shù)*/

???? int param4, /*這個(gè)例行程序的第四個(gè)參數(shù)*/

???? int param5,/*這個(gè)例行程序的第五個(gè)參數(shù)*/

???? )

而默認(rèn)情況下,netJobAdd 接口將 routine 函數(shù)和相應(yīng)的參數(shù)傳遞到 tNet0 任務(wù)重被執(zhí)行,而該任務(wù)的優(yōu)先級(jí)是 50(VxWorks6.6版本是50, 不記得VxWorks5.5.1是多少了,也許是45),該優(yōu)先級(jí)固定死了,沒有提升的空間。

改進(jìn)方式:

經(jīng)過(guò)上述的分析后,可以在中斷服務(wù)程序中釋放一個(gè)同步信號(hào)量,通知接收數(shù)據(jù)包的任務(wù)來(lái)收包,而該收包任務(wù)的優(yōu)先級(jí)可以自定義調(diào)整,也就是具體實(shí)現(xiàn)中斷上下部的方式。

?

LOCAL void rtl81x9Int

??? (

??? RTL81X9END_DEVICE? *pDrvCtrl

??? )

{

?

#if? 0

??? if (stat & RTL_IPT_RX_OK)

??? {

??? ????if (netJobAdd ((FUNCPTR)rtl81x9HandleRecvInt,(int) pDrvCtrl,0, 0, 0, 0) != OK)

??? ??????? DRV_LOG(DRV_DEBUG_INT, "xl: netJobAdd (rtl81x9HandleRecvInt) failedn",

0, 0, 0, 0, 0, 0);

??? ??? DRV_LOG(DRV_DEBUG_RX, "RTL_IPT_RX_OKn", 0, 0, 0, 0, 0, 0);*/

}

#endif

?

if (stat & RTL_IPT_RX_OK)

{

if(pDrvCtrl->unit == 0)

{

/*釋放信號(hào)量,開始接收數(shù)據(jù)*/

semGive(rtlNetTaskSemId0);

}

}

}

?????

收包任務(wù)的實(shí)現(xiàn)

?????

/*數(shù)據(jù)接收任務(wù)0*/

void rtlRecvTask0(RTL81X9END_DEVICE *?? pDrvCtrl)

{

??? FOREVER

??? {

??????? /* wait for somebody to wakeus up */

??? ???semTake (rtlNetTaskSemId0, WAIT_FOREVER);

??? ???rtl81x9HandleRecvInt(pDrvCtrl);

??? }

}

?

在start 函數(shù)中,啟動(dòng)一個(gè)接受數(shù)據(jù)包的任務(wù),如下代碼所示。

?

VxWorks系統(tǒng)下的緩沖區(qū)管理機(jī)制的研究

網(wǎng)絡(luò)協(xié)議存儲(chǔ)池使用mBlk結(jié)構(gòu)、clBlk結(jié)構(gòu)、簇緩沖區(qū)和netBufLib提供的函數(shù)進(jìn)行組織和管理。mBlk和clBlk結(jié)構(gòu)為簇緩沖區(qū)(cluster)中數(shù)據(jù)的緩沖共享和緩沖鏈接提供必要的信息。netBufLib例程使用mBlk和clBlk來(lái)管理cluster和引用cluster中的數(shù)據(jù),這些結(jié)構(gòu)體中的信息用于管理cluster中的數(shù)據(jù)并且允許他們通過(guò)引用的形式來(lái)實(shí)現(xiàn)數(shù)據(jù)共享,從而達(dá)到數(shù)據(jù)“零拷貝”的目的。

?

結(jié)構(gòu)體mBlk和clBlk及其數(shù)據(jù)結(jié)構(gòu)

mBlk是訪問存儲(chǔ)在內(nèi)存池中數(shù)據(jù)的最基本對(duì)象,由于mBlk僅僅只是通過(guò)clBlk來(lái)引用數(shù)據(jù),這使得網(wǎng)絡(luò)層在交換數(shù)據(jù)時(shí)就可以避免數(shù)據(jù)復(fù)制。只需把一個(gè)mBlk連到相應(yīng)mBlk鏈上就可以存儲(chǔ)和交換任意多的數(shù)據(jù)。一個(gè)mBlk結(jié)構(gòu)體包括兩個(gè)成員變量mNext和mNextPkt,由它們來(lái)組成縱橫兩個(gè)鏈表:mNext來(lái)組成橫的鏈表,這個(gè)鏈表中的所有結(jié)點(diǎn)構(gòu)成一個(gè)包(packet);mNextPkt來(lái)組成縱的鏈表,這個(gè)鏈表中的每個(gè)結(jié)點(diǎn)就是一個(gè)包(packet),所有的結(jié)點(diǎn)鏈在一起構(gòu)成一個(gè)包隊(duì)列,如圖1所示。

?


結(jié)構(gòu)體mBlk和clBlk的數(shù)據(jù)結(jié)構(gòu)如下所示:

struct mBlk

{

M_BLK_HDR??? mBlkHdr;????????????? /* header */

M_PKT_HDR??? mBlkPktHdr;???????? /* pkthdr */

CL_BLK *???????? pClBlk;????? /* pointer to cluster blk */

} M_BLK;

?

struct clBlk

{

???? CL_BLK_LIST? clNode;/* union of next clBlk */

????UINT?????? clSize;/* cluster size*/

????int??? clRefCnt;/*countof thecluster */

????struct netPool *? pNetPool;? /* pointer to the netPool */

} CL_BLK;

?

/* header at beginning of each mBlk */

struct mHdr

{

????struct mBlk *???? mNext;/* nextbuffer in chain */

? ???struct mBlk * mNextPkt;/* next chain inqueue/record */

???? char *mData;??????????????? /* location of data */

?int?mLen;/* amount of data in this mBlk */

?UCHAR?? mType;/* type of data in this mBlk */

?UCHAR?? mFlags;?????????????? /* flags; see below */

} M_BLK_HDR;

?

/* record/packet header in first mBlk of chain; valid if M_PKTHDR set */

struct?????? ???pktHdr

{

struct ifnet *???????? rcvif;/* rcvinterface */

int????? len;???????????? /* total packet length */

} M_PKT_HDR;

?

網(wǎng)絡(luò)協(xié)議存儲(chǔ)池的初始化

VxWorks在網(wǎng)絡(luò)初始化時(shí)給網(wǎng)絡(luò)協(xié)議分配存儲(chǔ)池并調(diào)用netPoolInit()函數(shù)對(duì)其初

始化,由于一個(gè)網(wǎng)絡(luò)協(xié)議通常需要不同大小的簇,因此它的存儲(chǔ)池也必須包含很多

簇池(每一個(gè)簇池對(duì)應(yīng)一個(gè)大小的簇)。如圖2所示。另外,每個(gè)簇的大小必須為2

的方冪,最大可為64KB(65536),存儲(chǔ)池的常用簇的大小為64,128,256,512,

1024比特,簇的大小是否有效取決于CL_DESC表中的相關(guān)內(nèi)容,CL_DESC表是由

netPoolInit()函數(shù)調(diào)用設(shè)定的。

?

網(wǎng)絡(luò)協(xié)議存儲(chǔ)池初始化后的結(jié)構(gòu)

?

使用netBufLib進(jìn)行內(nèi)存池管理

?

netBufLib提供了mBlks與clBlks結(jié)構(gòu),其中mBlks指向clBlks,而clBlks指向

實(shí)際存貯數(shù)據(jù)的Cluster。不同層次之間交互數(shù)據(jù)可以直接通過(guò)傳遞mBlks鏈來(lái)進(jìn)

行,而不用進(jìn)行多余的數(shù)據(jù)拷貝。其中clBlks的作用是,記錄有多少個(gè)mBlks對(duì)其

進(jìn)行了引用,當(dāng)引用為零時(shí)才可以釋放。不同的mBlks可以指向相同的clBlks,以

共享數(shù)據(jù)。

?

對(duì)于發(fā)送或接收的包可以由多個(gè)分開的內(nèi)存塊組成,也可以由一塊大的內(nèi)存塊組成。

因此對(duì)于一個(gè)包來(lái)說(shuō),它有一個(gè)mBlks鏈,鏈接著這個(gè)包的所有clusters。一個(gè)包

也應(yīng)該可以由一個(gè)大cluster組成,要是這樣的話,一個(gè)包就只要有一個(gè)mBlks就

行了。mBlks除鏈接著本身的所有的mBlks外,mBlks頭還鏈接著下一個(gè)包的mBlks

鏈的頭。

?

Clusters大小:

對(duì)于Clusters的大小,可以有不同型號(hào)。用于protocol的內(nèi)存池,可以有不同大

小的Clusters型號(hào),但型號(hào)大小仍有限定(見參考資料)。用于driver的內(nèi)存池,

只有一種大小的Cluster。其大小與MTU(max transport unit)類似。

?

建立內(nèi)存池內(nèi)驟:

調(diào)用netPoolInit(),初始化緩沖池參數(shù)。預(yù)留mBlk,clBlk,cluster結(jié)構(gòu)空間等。

步應(yīng)在初始化時(shí)進(jìn)行。

?

在Clusters中保存數(shù)據(jù):

1、在初始化時(shí),調(diào)用netClusterGet()來(lái)預(yù)留Clusters空間。

2、當(dāng)組裝好數(shù)據(jù)或接收到數(shù)據(jù)則裝進(jìn)Clusters中的一個(gè)。

3、調(diào)用netClBlkGet()來(lái)預(yù)留clBlk結(jié)構(gòu)。

4、調(diào)用netClBlkJoin()連接clBlk到包含數(shù)據(jù)的Cluster。

5、調(diào)用netMblkGet()預(yù)留mBlk結(jié)構(gòu)。

6、調(diào)用netMblkClJoin()連接mBlk結(jié)構(gòu)到clBlk。

?

釋放mBlks,clBlks,Clusters:

釋放mBlks鏈:netMblkClChainFree().這將釋放鏈中所有的mBlks。同時(shí)減少clBlks

中mBlks對(duì)其的引用,若減少至零,則clBlks及Clusters被釋放。釋放單獨(dú)

mBlk,clBlk,Cluster: netMblkClFree();

?

protocol與driver間傳數(shù)據(jù):

driver調(diào)用MUX的muxReceive();MUX調(diào)用protocol的stackRcvRtn()函數(shù);當(dāng)

muxReceive()正確返回后,driver確定數(shù)據(jù)己發(fā)送,接下來(lái)的buffer釋放,由協(xié)

議棧上層來(lái)完成。(The upper layers of the stack are responsible for freeing

the memory back to the driver’s memory pool.)

?

三、網(wǎng)絡(luò)收包分析

網(wǎng)卡收包有一系列需要注意的地方。

3.1 數(shù)據(jù)包的格式定義

數(shù)據(jù)包的格式如下。

??? /* cur_rx:

?????????? 31?????????? 16 15???????????? 0

??????????------------------------------------------------------????

??? 0:???? |????WORD1??? |???? WORD2????|? -----

??????????------------------------------------------------------???????

???????????? ???????????????????????????????????????_/

??? +4:??? ------------------------------------------------------

?????????? |??????????? DWORD3??????????? |

??????????------------------------------------------------------

?????????? WORD1:? Receive Status Flag;

?????????? WORD2:? Receive Package Length;

?????????? DWORD3: Receive PackageData Start Address.

???? */

??

?? 數(shù)據(jù)包開頭的4字節(jié)是接收的狀態(tài)標(biāo)志和數(shù)據(jù)長(zhǎng)度信息,后面才是數(shù)據(jù)的開始地址,

也就是說(shuō),拷貝數(shù)據(jù)的地址從當(dāng)前的指針位置 cur_rx + 4 開始,尾部是4字節(jié)的幀校驗(yàn)序列 FCS (Frame Check Sequence), FCS 采用32位CRC循環(huán)冗余校驗(yàn)對(duì)從"目標(biāo)MAC地址"字段到"數(shù)據(jù)"字段的數(shù)據(jù)校驗(yàn),一般該數(shù)據(jù)沒有使用。

?

數(shù)據(jù)拷貝

當(dāng)前一幀數(shù)據(jù)的長(zhǎng)度信息是存放在位置指針的頭四個(gè)字節(jié)中的,具體如上所述。

獲取到的長(zhǎng)度包含了4字節(jié)的狀態(tài)信息,然后是數(shù)據(jù),然后是4字節(jié)的 FCS。

拷貝數(shù)據(jù)動(dòng)作:

如果沒有跨尾,則直接拷貝即可。

??? memcpy (pNewCluster, readPtr + 4,len);???

??? 計(jì)算下一次DMA數(shù)據(jù)存放的地址;

??? cur_rx = (cur_rx + len + 4 + 3)& ~3;

如果有跨尾,則分兩次拷貝

wrapSize = (int) ((readPtr + len) - (pDrvCtrl->ptrRxBufSpace +RTL_RXBUFLEN));

/* Copy in first section of message as stored */

/* at the end of the ring buffer?????????? ? */

memcpy (pNewCluster, readPtr + 4, len-wrapSize-4);

/* Copy in end of message as stored */

/* at the start of the ring buffer?*/

memcpy (pNewCluster +len - wrapSize - 4, pDrvCtrl->ptrRxBufSpace,wrapSize);

/* there have some error compiler's bug in this line*/

/* If I just copy the correct bytes the last two bytes will*/

/* have some trouble, so I copy extra bytes to fix the CPU or*/

/* OS's bug vic??????????????????? */

?

計(jì)算下一次DMA數(shù)據(jù)存放的地址;

??? cur_rx = (wrapSize + 4 + 3) &~3;

3.2 數(shù)據(jù)接收由硬件DMA從FIFO到主內(nèi)存后,提交給 pMblk 的內(nèi)存鏈之Cluster,

最理想的是實(shí)現(xiàn)“零拷貝”。

?

?

?

原始方式:

網(wǎng)卡MAC接收到數(shù)據(jù)后,先進(jìn)入到內(nèi)部的64K+16字節(jié)的FIFO,然后由 DMA直接將 FIFO中的數(shù)據(jù)通過(guò)PCI Master 的方式來(lái)傳遞到主存,主存為一個(gè)環(huán)形的內(nèi)存緩沖區(qū),如上述圖所示。當(dāng)有完整的數(shù)據(jù)包過(guò)來(lái)后,通過(guò)中斷通知CPU,進(jìn)入到中斷服務(wù)程序處理接收邏輯。

首先讀取接收狀態(tài),如果發(fā)現(xiàn)是發(fā)送中斷,則直接調(diào)用發(fā)送中斷服務(wù)程序,如果是接收中斷,且沒有發(fā)現(xiàn)接收錯(cuò)誤,則發(fā)送同步信號(hào)量,收包任務(wù)被激活,進(jìn)入到收包程序。

?

收包程序?qū)⒆x命令寄存器,獲取到 bit 0 的數(shù)值,如果該數(shù)值一直為0,則表示緩沖區(qū)中還有數(shù)據(jù)沒有取完,通過(guò)一個(gè)循環(huán)操作解析數(shù)據(jù)包,拷貝到 Cluster, 連接到clBlk, 最后連接到 mBlk, 然后提交到協(xié)議棧,直到取完為止,中間有一系列的容錯(cuò)處理,還有注意內(nèi)存拷貝的指針計(jì)算等操作,都在里面。

?

改進(jìn)方式:

上述的原始的方式,存在一個(gè)很明顯的問題,那就是進(jìn)行了數(shù)據(jù)的拷貝。分配給DMA

的環(huán)行緩沖區(qū)地址是獨(dú)立的,數(shù)據(jù)首先會(huì)到這里,而我們最終提交給協(xié)議棧的內(nèi)存空間卻是另一個(gè)內(nèi)存塊,該內(nèi)存塊也是由用戶自己分配的,那么就需要進(jìn)行從第一個(gè)內(nèi)存地址空間到另一個(gè)內(nèi)存地址空間的搬移,這樣大大地浪費(fèi)了操作系統(tǒng)的時(shí)間,效率自然就降低了。

鑒于此,可以考慮一點(diǎn),能否在由DMA環(huán)行緩沖區(qū)拷貝數(shù)據(jù)到Cluster 改為直接使用DMA的環(huán)行緩沖區(qū)作為內(nèi)存管理 Cluster 的新地址,說(shuō)的比較多,估計(jì)也聽的有點(diǎn)不太明白,看下面的對(duì)比圖。

?

原始的操作方式

?

?

現(xiàn)在的操作方式

?

這樣直觀看了后,發(fā)現(xiàn)效率肯定有明顯的差別,前者需要內(nèi)存拷貝,后者不需要內(nèi)存拷貝。

具體的,在實(shí)現(xiàn)后者的設(shè)計(jì)思想上,有一些技巧需要考慮的。因?yàn)橛布O(shè)計(jì)特點(diǎn),當(dāng)DMA環(huán)行緩沖區(qū)到尾后,如果條件允許,數(shù)據(jù)將會(huì)自動(dòng)從DMA緩沖區(qū)頭開始存放數(shù)據(jù),目前設(shè)置的DMA緩沖區(qū)大小為 64K+16(16字節(jié)用于軟件自動(dòng)調(diào)節(jié)下次存放的指針位置,確保是對(duì)齊的地址)。

這樣的話,如果按照提交指針的方式,則會(huì)有點(diǎn)問題,為什么呢?因?yàn)椋∏僧?dāng)數(shù)據(jù)包跨緩沖區(qū)尾和區(qū)頭的時(shí)候,這樣提交指針就會(huì)出現(xiàn)數(shù)據(jù)錯(cuò)誤。具體原因分析如下:

雖然分配了一段地址給DMA環(huán)行緩沖區(qū),看起來(lái)是一個(gè)環(huán),但實(shí)際上,地址不是連接在一起的,而是一塊內(nèi)存,只是通過(guò)配置了寄存器后告訴硬件DMA,到內(nèi)存的尾了,就自動(dòng)從頭開始存放而已。

?

?

如果接收到的數(shù)據(jù)包沒有跨尾,則可以直接提交當(dāng)前的入口指針即可,否則,如果出現(xiàn)了跨尾,則還是按照上述的操作會(huì)出現(xiàn)問題,看下圖。

?

?

如果出現(xiàn)跨尾,則直接提交 Data Pointer 后將使用了后面虛線的內(nèi)容,而不會(huì)使用前面的數(shù)據(jù)塊,暫時(shí)無(wú)法實(shí)現(xiàn)自動(dòng)回頭的功能。

有兩種方式解決該問題,一種就是,在網(wǎng)卡驅(qū)動(dòng) start函數(shù)中,動(dòng)態(tài)分配一個(gè)1518+8

字節(jié)的內(nèi)存塊,然后將上述出現(xiàn)了分離的數(shù)據(jù)拷貝到該內(nèi)存塊,然后將該內(nèi)存首地

址join到 clBlk 即可;另一種就是,在分配DMA環(huán)行緩沖區(qū)的時(shí)候,在原來(lái)的64K+16字節(jié)的基礎(chǔ)上,多分配1518+8字節(jié)的空間,如上述的虛線框所示,這樣的話,只需要將上述的最頭上的蘭色框的數(shù)據(jù)拷貝到DMA End地址之后,然后可以直接提交 Data Pointer ?join到 clBlk 即可。

??????

但是在實(shí)際中,按照后者操作的方式,出現(xiàn)了一些問題,需要解決。

?

問題點(diǎn)如下:

?

按照后者的方式操作后,PING 沒有問題,小量發(fā)送數(shù)據(jù)包也沒有問題,當(dāng)使用發(fā)包工具大量發(fā)包的時(shí)候,只要在串口控制臺(tái)上按下任何的命令,都會(huì)出現(xiàn)如下的錯(cuò)誤信息:

?

data access

Exception current instruction address: 0x001ebce4

Machine Status Register: 0x00003032

Data Access Register: 0x5fff0017

Condition Register: 0x42048042

Data storage interrupt Register: 0x40000000

Task: 0x273b470 "tRtlRxTask0"

0x273b470 (tRtlRxTask0): task 0x273b470 has had a failure and has beenstopped.

0x273b470 (tRtlRxTask0): fatal kernel task-level exception!

?

通過(guò)DEBUG方式,依次查找出現(xiàn)問題的原因。

上述錯(cuò)誤信息指令地址在0x001ebce4,一般而言,如果修改代碼,重新編譯,該地址將會(huì)變化。

?

在命令行下查看了該地址信息,如下:

?

-> lkAddr 0x001ebce4

?

0x001eb290 netMblkChainDup??????????text???

0x001ec398 muxTxRestart?????????????text???

0x001ec48c muxReceive???????????????text???

0x001ec6a0 muxSend??????????????????text???

0x001ec6d8 _muxTkSendNpt????????????text???

0x001ec7c0 _muxTkSendEnd????????????text???

0x001eca98 muxTkSend????? ???????????text???

0x001ecac8 muxTkReceive?????????????text???

0x001ecd04 ipcom_sem_wait???????????text???

0x001ecd28 ipcom_mutex_lock?????????text???

0x001ecd4c ipcom_sem_interrupt_flush text???

0x001ecd6c ipcom_sem_flush??????????text???

value = 0 = 0x0

?

問題點(diǎn)應(yīng)該可以鎖定在 netMblkChainDup 這個(gè)函數(shù)中。

?

可以使用 tt 命令跟蹤下。

跟蹤發(fā)現(xiàn),在 netMblkChainDup 函數(shù)里面出現(xiàn)了異常。

?

-> tt tRtlRxTask

?

0x000962f8 vxTaskEntry? +0x48 :rtlRecvTask0 (0x270d9e8)

0x00030324 rtlRecvTask0 +0x28 : semTake ()

0x0016d9d4 semTake????? +0x138:semBTake ()

value = 0 = 0x0

?

正常情況下,如上述所示。

?

如果出現(xiàn)了上述的數(shù)據(jù)非法訪問錯(cuò)誤,則網(wǎng)絡(luò)收包任務(wù)將被迫停止。通過(guò) tt 命令后就可以發(fā)現(xiàn),通過(guò)一系列的函數(shù)調(diào)用后,最后的執(zhí)行函數(shù)為netMblkChainDup,估計(jì)在該函數(shù)中,釋放了一些內(nèi)存,然后繼續(xù)使用導(dǎo)致。

?

但是有一點(diǎn)不太明白的是,如在 shell下不執(zhí)行任何的操作,網(wǎng)絡(luò)可以承受不停的沖擊,沒有什么問題,如果一旦操作后,系統(tǒng)就掛死了。

?

反匯編,找到該指令的地址所在:

可以使用 objdumpppc –D vxWorks>img.s

?

-> objdumpppc –D vxWorks >img.s

?

?

找到目標(biāo)地址:

?

?

如何實(shí)現(xiàn)DMA緩沖區(qū)和 pMblk 的緩沖區(qū)管理鏈中的 Cluster的內(nèi)存共享,以達(dá)到“零拷貝”。

該部分的內(nèi)存共享,如上述分析,可能存在一些問題。實(shí)際測(cè)試的結(jié)果是,網(wǎng)絡(luò)在該情況下可以正常的收發(fā)包,但是,內(nèi)存可能出現(xiàn)了問題,或者操作系統(tǒng)的任務(wù)棧遭受了破壞,shell 下無(wú)法輸入命令,只要一輸入,系統(tǒng)就掛死了。同上3),原因還沒有找到。

?

借助以前開發(fā)VxWorks系統(tǒng)下的 1394驅(qū)動(dòng)經(jīng)驗(yàn),能否借助于消息隊(duì)列來(lái)提升性能?

借助于 Linux 系統(tǒng)下面的接收機(jī)制

初始化使能中斷后,第一次無(wú)論是發(fā)送完成或接收中斷,進(jìn)去后,關(guān)閉所有中斷,然后讀取中斷狀態(tài)寄存器,判斷是何種類型的中斷,如果是發(fā)送完成中斷,則在退出中斷之前,僅僅打開發(fā)送中斷,如果是接收中斷,則在退出中斷之前,不使能接收中斷,等接收數(shù)據(jù)包任務(wù)完成后再使能該中斷。

總結(jié)為一句話,發(fā)送中斷按照原始的處理方式,而接收中斷第一次進(jìn)中斷后,屏蔽該中斷類型,中斷服務(wù)程序釋放一個(gè)同步信號(hào)量,激活收包任務(wù),采用輪詢的方式直到將數(shù)據(jù)包接收完畢后再打開接收中斷。

?

二、數(shù)據(jù)發(fā)送優(yōu)化

在閱讀發(fā)送函數(shù)時(shí),發(fā)現(xiàn)協(xié)議棧(以下簡(jiǎn)稱上層),將pMblk 指針傳遞給發(fā)送函數(shù),然后再查詢是否有可用的發(fā)送描述符后,對(duì)上層的數(shù)據(jù)包進(jìn)行拷貝到發(fā)送描述符對(duì)應(yīng)的緩沖區(qū),設(shè)置發(fā)送,等待完成。

這里對(duì)速度影響比較大的點(diǎn)就是,執(zhí)行了數(shù)據(jù)的拷貝動(dòng)作,參考如下代碼:

LOCAL STATUS rtl81x9Send

??? (

??? RTL81X9END_DEVICE?????????? *pDrvCtrl,?????????? /* device ptr */

??? M_BLK_ID???????????????????? pMblk?????????????? /* data to send */

)

{

??? ???????????/* Replace this code !! */

??????? #if 0

??????????????? len = netMblkToBufCopy(pMblk, pBuf, NULL);

???????????????netMblkClChainFree(pMblk);

??????? #endif

??????????????? len =pMblk->mBlkHdr.mLen;

???????????????

??? ??????????? ???/*pMblk->mBlkPktHdr.len = len;*/

???????????????

??????????????? len = max (len, ETHERSMALL);

??????????????? tx_val = len + (0x38<< 16);

?

/* pass pointer to the TX desc register */

??????????????? pBuf =pMblk->mBlkHdr.mData;

??????????????? …

??????????????? /* Flush the writepipe */

??????? ????????CACHE_PIPE_FLUSH ();

??????? ????????netMblkClChainFree(pMblk); /* Add byalex */

}

上述代碼中,紅色字體部分是原始的代碼,需要進(jìn)行拷貝,這樣會(huì)影響到發(fā)送性能,修改為藍(lán)色字體部分,基本上實(shí)現(xiàn)了“零拷貝”,經(jīng)過(guò) EtherPeek 發(fā)包軟件測(cè)試,沒有問題。

?


本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動(dòng)電源

在工業(yè)自動(dòng)化蓬勃發(fā)展的當(dāng)下,工業(yè)電機(jī)作為核心動(dòng)力設(shè)備,其驅(qū)動(dòng)電源的性能直接關(guān)系到整個(gè)系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動(dòng)勢(shì)抑制與過(guò)流保護(hù)是驅(qū)動(dòng)電源設(shè)計(jì)中至關(guān)重要的兩個(gè)環(huán)節(jié),集成化方案的設(shè)計(jì)成為提升電機(jī)驅(qū)動(dòng)性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機(jī) 驅(qū)動(dòng)電源

LED 驅(qū)動(dòng)電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個(gè)照明設(shè)備的使用壽命。然而,在實(shí)際應(yīng)用中,LED 驅(qū)動(dòng)電源易損壞的問題卻十分常見,不僅增加了維護(hù)成本,還影響了用戶體驗(yàn)。要解決這一問題,需從設(shè)計(jì)、生...

關(guān)鍵字: 驅(qū)動(dòng)電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動(dòng)電源的公式,電感內(nèi)電流波動(dòng)大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計(jì) 驅(qū)動(dòng)電源

電動(dòng)汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動(dòng)汽車的核心技術(shù)之一是電機(jī)驅(qū)動(dòng)控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機(jī)驅(qū)動(dòng)系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動(dòng)汽車的動(dòng)力性能和...

關(guān)鍵字: 電動(dòng)汽車 新能源 驅(qū)動(dòng)電源

在現(xiàn)代城市建設(shè)中,街道及停車場(chǎng)照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進(jìn)步,高亮度白光發(fā)光二極管(LED)因其獨(dú)特的優(yōu)勢(shì)逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動(dòng)電源 LED

LED通用照明設(shè)計(jì)工程師會(huì)遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動(dòng)電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動(dòng)電源的電磁干擾(EMI)問題成為了一個(gè)不可忽視的挑戰(zhàn)。電磁干擾不僅會(huì)影響LED燈具的正常工作,還可能對(duì)周圍電子設(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來(lái)解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動(dòng)電源

開關(guān)電源具有效率高的特性,而且開關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機(jī)重量也有所下降,所以,現(xiàn)在的LED驅(qū)動(dòng)電源

關(guān)鍵字: LED 驅(qū)動(dòng)電源 開關(guān)電源

LED驅(qū)動(dòng)電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動(dòng)LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動(dòng)電源
關(guān)閉