阅读:1823回复:13
两个问题,每个10分
第一个问题,比较弱智,但是本人更弱智,居然没有看懂,特来请教:
在PASSTHRU的MPInitialize(...)函数中有一段关于NdisMSetAttributesEx的注释,即: Set the attributes now. The NDIS_ATTRIBUTE_DESERIALIZE is the key. This enables us to make up-calls to NDIS w/o having to call NdisIMSwitchToMiniport/NdisIMQueueCallBack This also forces us to protect our data using spinlocks where appropriate. Also in this case NDIS does not queue packets on out behalf. Since this is a very simple pass-thru miniport, we do not have a need to protect anything. However in a general case there will be a need to use per-adapter spin-locks for the packet queues at the very least. 谁能给我讲讲为什么它要设置NDIS_ATTRIBUTE_DESERIALIZE,这样做之后还需要调用NdisIMSwitchToMiniport/NdisIMQueueCallBack 吗?(鸟语水平太低,没有看明白) 第二个问题,如果在IMD中频繁的使用内存,对网络效率的影响有多大? |
|
最新喜欢:ljmmar... |
沙发#
发布于:2002-10-05 12:29
第一个问题,比较弱智,但是本人更弱智,居然没有看懂,特来请教: 仔细看了一下因该是: NDIS_ATTRIBUTE_DESERIALIZE enables us to make up-calls to NDIS without having to call NdisIMSwitchToMiniport or NdisIMQueueCallBack. 设置NDIS_ATTRIBUTE_DESERIALIZE,这样做之后 不需要 调用NdisIMSwitchToMiniport/NdisIMQueueCallBack 。 第二个问题好象太笼统了点,没有明确的答案吧。 IMD本身就对网络效率有一定的影响。 |
|
|
板凳#
发布于:2002-10-05 12:30
第一个问题:
基本上从nt4 sp3(也许是sp4,我脑子有点糊涂了,实在记不 清楚了)以后所有的miniport都应该设置为deserialize,这样 能够做到最大的异步。这样做了之后你不需要调用你后面说的 两个函数,但是ndis不负责你的driver的同步了。因为是你自己 负责同步,所以效率更高,对于多网卡或者多cpu的情况下, 效率更高。以前ndis(nt4+sp3以前)里面有一部分是不可重入 的,在一定程度上影响了效率(关于这部分内核重入的问题, 参看mark在nt magazine在98年发的一篇帖子,该帖子非常有名, 关于linux性能的。) 下面我说一个我自己的实战经验。因为前段时间我需要调试 异步加密,我为了尽量减少重入,我去掉了这个参数,结果 在长时间之内,总是要dump一次,后来我只好自己维护所有的 数据同步,加上这个参数。 如果你不设置这个参数,你需要用后面的那个函数进行同步, 但是好像那两个函数是过时函数:-(。 第2个问题: 通常如果你频繁分配内存,影响效率的程度大致在1/4左右。 更有效率和更好的方法是一次分配(通常在initiate或者 driverentry)一块大内存,例如2048*32,然后把每个块, 也就是2048的头指针插入一个队列中。每次使用的时候pop 一个指针出来用,用完之后push回去。这样你不会有无限制 的分配,当pop不出来的时候,你就知道多半有内存泄漏了, 因为这意味着ndis连续重入了32次,这几乎是不可能的。我在 慢速加密设备(usb 1.1)上,观察到的重入也只有大约4次。 这样还有一个好处,你在运行的时候,不会分配,释放,只有 pop,push,效率高很多。而且只要没有错误,你永远不会发生 无法分配内存的情况。此外,就算你的程序写错了,你也不会 因为内存泄漏而影响整个系统。因为你顶多泄漏32个。通常 你为每个网卡分配不同的内存,收发使用不同的链,那么 顶多就是网卡数*2*32*2048,你会发现这并非一块很大的内存。 如果不使用这种机制,发生了内存泄漏是非常可怕和难以调试 的。我曾经在代码中发生过这种错误。跑了很长时间之后,系统 不死机,但是tdi已经分配不出内存了。ping命令无法执行,其他 应用程序也执行的非常怪异。这个时候,ndis还能分配内存,我 的程序看起来也很正常,调试非常困难,而且这种错误非常难以 发现。 第一个问题,比较弱智,但是本人更弱智,居然没有看懂,特来请教: |
|
|
地板#
发布于:2002-10-05 12:49
看了两位大老的意见,觉得胡版主说得更透彻些,而且很有可能就是我犯的错误,所以就多给点了。
magicx说得也不无道理,所以也给点,嘻嘻。 谢谢二位! //bow |
|
地下室#
发布于:2002-10-05 15:26
嘿嘿。。。
又学到了很多! :D |
|
|
5楼#
发布于:2002-10-05 18:57
看了两位大老的意见,觉得胡版主说得更透彻些,而且很有可能就是我犯的错误,所以就多给点了。 刚刚看了胡版主给我回的帖子,思考了一下,觉得还是有些地方不能确诊。胡版主的回帖如下: -- 通常如果你频繁分配内存,影响效率的程度大致在1/4左右。更有效率和更好的方法是一次分配(通常在initiate或者driverentry)一块大内存,例如2048*32,然后把每个块,也就是2048的头指针插入一个队列中。每次使用的时候pop一个指针出来用,用完之后push回去。这样你不会有无限制的分配,当pop不出来的时候,你就知道多半有内存泄漏了,因为这意味着ndis连续重入了32次,这几乎是不可能的。我在慢速加密设备(usb 1.1)上,观察到的重入也只有大约4次。 这样还有一个好处,你在运行的时候,不会分配,释放,只有pop,push,效率高很多。而且只要没有错误,你永远不会发生无法分配内存的情况。此外,就算你的程序写错了,你也不会因为内存泄漏而影响整个系统。因为你顶多泄漏32个。通常你为每个网卡分配不同的内存,收发使用不同的链,那么顶多就是网卡数*2*32*2048,你会发现这并非一块很大的内存。 如果不使用这种机制,发生了内存泄漏是非常可怕和难以调试的。我曾经在代码中发生过这种错误。跑了很长时间之后,系统不死机,但是tdi已经分配不出内存了。ping命令无法执行,其他应用程序也执行的非常怪异。这个时候,ndis还能分配内存,我的程序看起来也很正常,调试非常困难,而且这种错误非常难以发现。 -- 首先,胡版主的方法我觉得很好,所以准备着手改造我的程序,具体方法如下: 1.在MPInitialize中申请两个收发内存垮 2.在收发过程中使用这些东东 3.在MPHalt中释放申请的内存块 不知道以上过程是否正确。即使以上过程正确,那我又该如何处理内存溢出呢?也就是说,当重入多次后,内存资源不足时,我该如何处理? 另外,我觉得我有必要详细描述一下我程序现在的症状。为了调试方便,我将程序设置成加密/解密和非加密/解密两种模式。在非加密/解密模式下,程序运行的很好,没有明显的效率下降(LAN内部FTP测试,速度可以达到1M)。 但是,当程序运行在加密/解密,FTP则无法连接。利用网络邻居搜索计算机的时间偏长。虽然可以打开对方完全共享的文件夹,进行数据拷贝。但是拷贝过程中,机器就象DOWN掉了一般。而且拷贝过程不会出现通常出现的那个显示进度的对话框。我不知道这是什么原因,以胡版主的经验看,这是什么问题? 我怀疑是我对数据进行加密之后,数据包比原来长了4个字节。但是我没有修改Packet中关于PacketSize的属性,所以导致了这样的后果。接收的过程则相反,向上传送的数据包要比接受的少4个字节(如果发送时所有数据都被发送)。 如果真的是这个东东影响了我的效率,那么该怎么解决?老师给我的时间不多了,请胡版主救救命!谢谢了! =============================================================== 上面是这个哥们给我发的mail。 回答如下: 你不可能重入32次,即使你的加密慢的象蜗牛在爬。 如果你poplist返回NULL,那么丢掉这个数据包好了。 如果你poplist真的返回NULL,那么一定是你的程序 除了问题,有什么地方用完了没有pushlist。 你的那个现象非常简单,就是不通。可能有几个包勉强 过去了,但是大包过不去。如果慢的不正常,就是丢包 或者错包。 因此你目前的问题绝对不是效率的问题,我还以为你 想极力榨干系统的能力,没有想到是这样。你不需要去 考虑分配内存的效率了,最慢的情况下,你用最苯 的分配内存的方法,只要不泄漏(即使泄漏,也能跑 10M数据没有问题),用任意算法或者加密卡,P4机器上如果 在以太网上小于100K BYTES那就完全是代码的问题。 (除非这块加密卡应该扔到海里去) ps:以后不要说救命的话了,只有你自己才能救自己的命, 这种话听了让人不太愉快,不象是个男人。 |
|
|
6楼#
发布于:2002-10-06 09:21
多谢胡版主教诲!
接着这个帖子,我想再问一个问题。在IMD中调用NidsMIndicateReceivedPackets(...)通知协议层接收Packet,但是在该函数中并没有要求给出PacketSize的信息,NDIS自己能做这个活吗?相应的,在NidsSend(...)中也没要求给出PacketSize,那么NDIS又是如何来弄的呢?如果包的长度改变了,和Packet有关的东东(在NDIS_PACKET或者其他什么东东里面)还有什么需要改的吗? |
|
7楼#
发布于:2002-10-06 22:56
多谢胡版主教诲! NDIS_PACKET数据结构中包含你说的那些信息。 例如包长度。 你需要仔细的看看NDIS_PACKET数据结构中的内容, 除了那些和数据包内容相关的东西之外,还有一些 例如oob数据之类的东西也需要仔细看看。 |
|
|
8楼#
发布于:2002-10-06 23:49
偶想起来了,在NDIS_PACKET_PRIVATE中有关于数据包长度的东东,结构如下:
这个是数月前我从什么地方找到的(现在记不清了,也找不到了,幸好自己的记事本上有),但是不知道是否也像NDIS一样,跟操作系统有关,另外不知道能否直接操作? 好像在原始版本的2000PASSTHRU中有过这样的语句:
根据这个,我猜想应该能够在自己申请的Packet中对这些数据进行操作,但是有些数据成员的具体说明我还没有找到,不知道胡版主能够把上面的那个结构中的成员变量给我讲讲(特别是该如何设置一个数据包的长度),谢谢了! |
|
9楼#
发布于:2002-10-07 01:02
[quote] 偶想起来了,在NDIS_PACKET_PRIVATE中有关于数据包长度的东东,结构如下:
这个是数月前我从什么地方找到的(现在记不清了,也找不到了,幸好自己的记事本上有),但是不知道是否也像NDIS一样,跟操作系统有关,另外不知道能否直接操作? 好像在原始版本的2000PASSTHRU中有过这样的语句:
根据这个,我猜想应该能够在自己申请的Packet中对这些数据进行操作,但是有些数据成员的具体说明我还没有找到,不知道胡版主能够把上面的那个结构中的成员变量给我讲讲(特别是该如何设置一个数据包的长度),谢谢了! [/quote] 关于设置数据包长度,前面的贴子里面甚至有source, 我不愿意说的太清楚,我这里只提示你,去看看如下函数: NdisQueryBuffer/safe(win9x不支持safe) NdisQueryPacket 以及去看看ndisbuffer的数据结构,ndis.h里面全都有。 通常不应该直接操作这些数据结构里面的变量,特别是那些 private。但是这里的private.tail/head,因为ndis好像没有 提供相关的宏,不过这两个成员变量9x的数据结构中也有, 所以还是平台无关的。不过通常来说,你并不需要直接操作 这两个成员变量。如果你看了我以前的贴子里面有直接操作 的,那是因为我以前没有太仔细的读数据结构,加上我那个时候 并不太关注兼容性之类的东西,幸好后来我发现对于9x也并不影响 其兼容性,所以一直没有改------谁会吃饱了没有事去修改 那些已经工作了很久并且很稳定的代码呢 :-)? |
|
|
10楼#
发布于:2002-10-07 02:47
胡版主,我想你是误会小弟我的意思了 :-) 我是想问问NDIS中是怎么处理Miniport驱动和Protocol驱动之间传输的数据包的?因为我发现并不是每一个发送/接收函数都给出了完整的数据包的信息(例如:NdisMIndicateReceivePacket).NDIS是通过解析NDIS_PACKET_PRIVATE结构来做的吗? 此外,你上面说的关于修改数据包长度的东东,我翻箱倒柜在坛子里找了半天也没见,到底在什么地方? |
|
11楼#
发布于:2002-10-07 02:49
补充一句,上面我说的NDIS好像应该表达为Wrapper,呵呵,我自己对概念也不是很清楚 :-)
|
|
12楼#
发布于:2002-10-07 03:06
[quote] 胡版主,我想你是误会小弟我的意思了 :-) 我是想问问NDIS中是怎么处理Miniport驱动和Protocol驱动之间传输的数据包的?因为我发现并不是每一个发送/接收函数都给出了完整的数据包的信息(例如:NdisMIndicateReceivePacket).NDIS是通过解析NDIS_PACKET_PRIVATE结构来做的吗? 此外,你上面说的关于修改数据包长度的东东,我翻箱倒柜在坛子里找了半天也没见,到底在什么地方? [/quote] 在w2k中,很多函数都成为了宏,ndis也不负责大多数同步工作了, 所以ndis其实做的事情已经比较少了。 ndis并不需要知道那些数据包的具体内容,不过ndis可能是需要 那些oob数据。 关于如何修改长度,你仔细看过那两个函数就知道了。 |
|
|
13楼#
发布于:2002-10-07 04:06
在w2k中,很多函数都成为了宏,ndis也不负责大多数同步工作了,所以ndis其实做的事情已经比较少了。ndis并不需要知道那些数据包的具体内容,不过ndis可能是需要那些oob数据。 那两个函数我早就看过多少遍了,自己真的没有什么感悟!可能是我对NDIS了解的还不够的缘故吧。 这里我还是再把我弄的玩意说说吧,请胡版主耐心看看! 我做的东东就是利用某种加密算法将数据包进行加密(算法由于某种原因不能公开),加密之后的东东要比原来多了4个字节,然后我没有对该数据包做任何操作就将其发送出去了。(不知道除了PASSTHRU里面原来带的东东之外,我还需要做些什么 :() 现在我怀疑影响网络正常工作的原因就是我在发送和接收的时候没有对有关PACKET的描述信息进行任何修改,不知道是不是这个原因,请指教! |
|