terrychen
驱动小牛
驱动小牛
  • 注册日期2002-04-15
  • 最后登录2014-03-13
  • 粉丝0
  • 关注0
  • 积分174分
  • 威望68点
  • 贡献值0点
  • 好评度15点
  • 原创分0分
  • 专家分0分
阅读:4242回复:32

scsi miniport的问题

楼主#
更多 发布于:2003-12-25 14:15
我在写一个虚拟scsi设备的driver,使用ScsiPortNotification来返回srb到portdriver.但是因为是虚拟设备,所以没有真正的中断,目前是用ScsiPortNotification(RequestTimerCall,)来返回数据,但是好像这个timer最小间隔是10 milliseconds。这样很影响效率,请问一下大家有没有什么办法,可以直接ScsiPortNotification返回给port driver,或者什么方法可以提高效率?

最新喜欢:

aventineaventi...
cool-net
驱动小牛
驱动小牛
  • 注册日期2003-03-18
  • 最后登录2010-01-05
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2003-12-25 15:35
效率要求很高吗?
我就是使用TimerCall的,不觉得有什么问题呀.

>> 但是好像这个timer最小间隔是10 milliseconds
10 milliseconds是指系统调度Timer的时间精度,但是TimerCall是以microseconds为单位的,意思是最差情况下你可能要等上10ms,但正常情况下应该不用等那么久,平均就5ms吧.

如果不涉及读硬盘的操作,正常的SRB可以直接Complete,这个效率应该很高,涉及读盘的时候,读盘加线程切换也要花点时间吧,这样算下来其实你并没有在TimerCall那里损失太多的时间.

事实是,我使用1000 microseconds进行TimerCall,从虚拟设备上往硬盘上拷东西跟在硬盘的不同分区之间拷东西,基本感觉不到什么速度差异.
有错误才会有进步,所以我的人生目标是: 错误不断,毁人不倦!
terrychen
驱动小牛
驱动小牛
  • 注册日期2002-04-15
  • 最后登录2014-03-13
  • 粉丝0
  • 关注0
  • 积分174分
  • 威望68点
  • 贡献值0点
  • 好评度15点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2003-12-25 16:05
〉〉10 milliseconds是指系统调度Timer的时间精度,但是TimerCall是以microseconds为单位的,意思是最差情况下你可能要等上10ms,但正常情况下应该不用等那么久,平均就5ms吧.
这点我同意,通常timercall返回的时间是不到10ms,但是在我的设备里就是这个timercall影响了我的效率,现在我的设备用iometer测试下来是大概4MB左右,里面很多时间是被这个消耗的,你说正常的SRB可以直接Complete,这个我曾经试过,但是好像不起作用,portdriver好像没收到一样,几秒钟以后就一个resetbus了,不知道你直接complete怎么做的?
cool-net
驱动小牛
驱动小牛
  • 注册日期2003-03-18
  • 最后登录2010-01-05
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2003-12-25 16:23
不太明白你的意思,你是说对于 *每一个SRB* 你都要进行一次TimerCall吗?

对于那些可以立即完成的操作(比如EjectMedia或ModeSense或TestUnitReady之类的)也使用TimerCall?

我使用TimerCall的地方仅限于那些在DISPATCH_LEVEL上不能完成的或必须在指定的线程上下文环境中完成的操作(如打开文件,读文件,写文件之类的), 其它的SRB一律是处理完之后马上就:

ScsiPortNotification(RequestComplete, Extension, Srb);
然后
ScsiPortNotification(NextRequest, Extension, NULL);
有错误才会有进步,所以我的人生目标是: 错误不断,毁人不倦!
seaquester
驱动大牛
驱动大牛
  • 注册日期2002-05-22
  • 最后登录2016-06-16
  • 粉丝0
  • 关注0
  • 积分500分
  • 威望115点
  • 贡献值0点
  • 好评度107点
  • 原创分0分
  • 专家分52分
地下室#
发布于:2003-12-25 16:25
〉〉10 milliseconds是指系统调度Timer的时间精度,但是TimerCall是以microseconds为单位的,意思是最差情况下你可能要等上10ms,但正常情况下应该不用等那么久,平均就5ms吧.
这点我同意,通常timercall返回的时间是不到10ms,但是在我的设备里就是这个timercall影响了我的效率,现在我的设备用iometer测试下来是大概4MB左右,里面很多时间是被这个消耗的,你说正常的SRB可以直接Complete,这个我曾经试过,但是好像不起作用,portdriver好像没收到一样,几秒钟以后就一个resetbus了,不知道你直接complete怎么做的?
 


Complete一个SRB可以用:
ScsiPortNotification(  NotificationType = RequestComplete )
注意设置状态SrbStatus 和ScsiStatus。

再调用:
ScsiPortNotification(  NotificationType = NextRequest )
接受下一个请求。

八风舞遥翩,九野弄清音。 鸣高常向月,善舞不迎人。
terrychen
驱动小牛
驱动小牛
  • 注册日期2002-04-15
  • 最后登录2014-03-13
  • 粉丝0
  • 关注0
  • 积分174分
  • 威望68点
  • 贡献值0点
  • 好评度15点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2003-12-25 16:47
>>不太明白你的意思,你是说对于 *每一个SRB* 你都要进行一次TimerCall吗?

当然不是每一个srb用一次timercall,我是把所有的srb放到一个list上面,然后一次timercall以后把所有执行完了的srb都return回去。

>>Complete一个SRB可以用:
>>ScsiPortNotification( NotificationType = RequestComplete )
>>注意设置状态SrbStatus 和ScsiStatus。

>>再调用:
>>ScsiPortNotification( NotificationType = NextRequest )
>>接受下一个请求。

我只用了ScsiPortNotification( NotificationType = RequestComplete ),没有调用nextrequest.会怎么样呢?
cool-net
驱动小牛
驱动小牛
  • 注册日期2003-03-18
  • 最后登录2010-01-05
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2003-12-25 16:55
>> 当然不是每一个srb用一次timercall,我是把所有的srb放到
>> 一个list上面,然后一次timercall以后把所有执行完了的srb
>> 都return回去
这样不好,应该是能Complete的直接Complete,不能Complete的才放在List里在TimerCall里Complete.
注意,不管你有没有Complete,在返回SRB给SCSIPort之前,你都应该调用NextRequest.

>> 我只用了ScsiPortNotification( NotificationType =
>> RequestComplete ),没有调用nextrequest.会怎么样呢?
SCSIPort会超时,然后送一个RESET_BUS下来,呵呵.:):):):)
有错误才会有进步,所以我的人生目标是: 错误不断,毁人不倦!
terrychen
驱动小牛
驱动小牛
  • 注册日期2002-04-15
  • 最后登录2014-03-13
  • 粉丝0
  • 关注0
  • 积分174分
  • 威望68点
  • 贡献值0点
  • 好评度15点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2003-12-25 17:01
ScsiPortNotification( RequestComplete,HwDeviceExtension,Srb );

ScsiPortNotification(NextRequest, HwDeviceExtension, NULL);
都用上了,不好使啊。依然timeout
seaquester
驱动大牛
驱动大牛
  • 注册日期2002-05-22
  • 最后登录2016-06-16
  • 粉丝0
  • 关注0
  • 积分500分
  • 威望115点
  • 贡献值0点
  • 好评度107点
  • 原创分0分
  • 专家分52分
8楼#
发布于:2003-12-25 17:42
ScsiPortNotification( RequestComplete,HwDeviceExtension,Srb );

ScsiPortNotification(NextRequest, HwDeviceExtension, NULL);
都用上了,不好使啊。依然timeout


注意设置状态SrbStatus 和ScsiStatus。


八风舞遥翩,九野弄清音。 鸣高常向月,善舞不迎人。
cool-net
驱动小牛
驱动小牛
  • 注册日期2003-03-18
  • 最后登录2010-01-05
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2003-12-25 18:39
ScsiPortNotification( RequestComplete,HwDeviceExtension,Srb );

ScsiPortNotification(NextRequest, HwDeviceExtension, NULL);
都用上了,不好使啊。依然timeout

不知道你的处理过程是什么样的,我吧我的过程给你看看,这个肯定能工作:

定义两个队列:
QUEUE RequestQueue;
QUEUE CompleteQueue;

BOOLEAN __stdcall ScsiMiniPortStartIo(PVOID Ext, PSCSI_REQUEST_BLOCK Srb)
{
 if(能处理)
 {
  // 处理,并设置:
  //   Srb->SrbStatus
  //   Srb->SenseInfoBuffer
  //   Srb->SenseInfoBufferLength
  //   Srb->ScsiStatus;
  // Srb->SrbStatus一定不要设置成SRB_STATUS_PENDING;
 }
 else
 {
  Srb->SrbStatus = SRB_STATUS_PENDING;
  RequestQueue.Enqueue(Srb); // 放队列里等线程处理
 }

 if(Srb->SrbStatus == SRB_STATUS_PENDING)
 {
  //启动Timer
  ScsiPortNotification(RequestTimerCall, Ext,ScsiTimer,1000);
 }
 else
 {
  //完成它
  ScsiPortNotification(RequestComplete, Ext, Srb);
 }

 //千万别忘了这个
 ScsiPortNotification(NextRequest, Ext, NULL);

 return TRUE;
}

系统线程里:
Thread()
{
 while(true)
 {
  Srb = RequestQueue.Dequeue();

  //处理Srb并设置:
  //   Srb->SrbStatus
  //   Srb->SenseInfoBuffer
  //   Srb->SenseInfoBufferLength
  //   Srb->ScsiStatus;
  // Srb->SrbStatus一定不要设置成SRB_STATUS_PENDING;

  CompleteQueue.Enqueue(Srb); //放到完成队列里等Timer处理
 }
}

Timer里:
void __stdcall ScsiTimer(PVOID Ext)
{
 // 完成所有CompleteQueue里的Srb
 while((Srb = CompleteQueue.Dequeue()) != NULL)
 {
  //完成它
  ScsiPortNotification(RequestComplete, Ext, Srb);
 }

 //如果还有没处理的Srb,一定要记得再起Timer
 if(!RequestQueue.IsEmpty())
 {
  ScsiPortNotification(RequestTimerCall, Ext,ScsiTimer,1000);
 }
}

以上只是一个粗略的流程,里面有许多地方需要同步保护,你自己加。另外,你并不一定非得起一个系统线程,使用QueueWorkItem之类的也能达到同样的效果,想必这对你不是什么问题。
有错误才会有进步,所以我的人生目标是: 错误不断,毁人不倦!
terrychen
驱动小牛
驱动小牛
  • 注册日期2002-04-15
  • 最后登录2014-03-13
  • 粉丝0
  • 关注0
  • 积分174分
  • 威望68点
  • 贡献值0点
  • 好评度15点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2003-12-29 15:24
你和我程序的唯一的区别就是,你在startio里面起的requestimercall,而我是用一个timer反复的call,这样改变不了效率啊。不知道你的device的performance怎么样,能帮忙看一看么?

[编辑 -  12/29/03 by  terrychen]
cool-net
驱动小牛
驱动小牛
  • 注册日期2003-03-18
  • 最后登录2010-01-05
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2003-12-29 16:47
 if(Srb->SrbStatus == SRB_STATUS_PENDING)
 {
  //启动Timer
  ScsiPortNotification(RequestTimerCall, Ext,ScsiTimer,1000);
 }
 else
 {
  //完成它
  ScsiPortNotification(RequestComplete, Ext, Srb);
 }
我只是PENDING的时候RequestTimerCall(换句话说,象TestUnitReady或ModeSense之类的SRB通通不用TimerCall),而听前几篇帖子你的意思是你把所有的SRB都给Mark成Pending,然后\"全部\"在TimerCall里Complete,是这样吗?如果是,那当然有效率问题.

我以前写的那个是一个Virtual Optical Disk(也就是个可移动硬盘),在两个虚拟设备之间拷文件(也就是说所有的数据都要从我的驱动程序里过),也没发现有什么太大的效率问题(大约达到80%-90%的硬盘速度),不知道你的驱动跟真正的硬盘比起来效率损失有多大?
有错误才会有进步,所以我的人生目标是: 错误不断,毁人不倦!
terrychen
驱动小牛
驱动小牛
  • 注册日期2002-04-15
  • 最后登录2014-03-13
  • 粉丝0
  • 关注0
  • 积分174分
  • 威望68点
  • 贡献值0点
  • 好评度15点
  • 原创分0分
  • 专家分0分
12楼#
发布于:2003-12-29 17:23
实际上TestUnitReady和mode_sense在这里很小一部分,大概占1%都不到,主要是write和read问题了,效率主要就是timercall实际上消耗了太多时间。而且system好像发srb也不是很频繁。现在我实现的这个速度也不是很慢,copy东西什么的,感觉还可以,但是microsoft有个tools,测出来是我10倍,所以很郁闷
rayyang2000
管理员
管理员
  • 注册日期2001-03-23
  • 最后登录2012-09-13
  • 粉丝3
  • 关注0
  • 积分1036分
  • 威望925点
  • 贡献值3点
  • 好评度823点
  • 原创分0分
  • 专家分0分
13楼#
发布于:2003-12-30 20:07
加cache可能会有改善。我们就是这样提速的,差不多在10倍左右。用Nero测试下来,Burst Rate在60M左右。
天天coding-debugging中----超稀饭memory dump file ======================================================== [b]Windows Device Driver Development and Consulting Service[/b] [color=blue][url]http://www.ybwork.com[/url][/color] ========================================================
terrychen
驱动小牛
驱动小牛
  • 注册日期2002-04-15
  • 最后登录2014-03-13
  • 粉丝0
  • 关注0
  • 积分174分
  • 威望68点
  • 贡献值0点
  • 好评度15点
  • 原创分0分
  • 专家分0分
14楼#
发布于:2003-12-31 08:59
加cache,能不能说具体一点呢?我PORT_CONFIGURATION_INFORMATION里面的cachedata也true了,没有什么反映啊,版主说说吧
cool-net
驱动小牛
驱动小牛
  • 注册日期2003-03-18
  • 最后登录2010-01-05
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
15楼#
发布于:2003-12-31 19:42
如果你是用文件虚拟设备的话,加cache不是很必要,应为文件系统本来就有cache(注意WRITE_THROUGH只控制写,而INTERMEDIATE_BUFFER不能控制FileSystem的cache)。

你可以把MaximumTransferLength加大点儿试试。
有错误才会有进步,所以我的人生目标是: 错误不断,毁人不倦!
terrychen
驱动小牛
驱动小牛
  • 注册日期2002-04-15
  • 最后登录2014-03-13
  • 粉丝0
  • 关注0
  • 积分174分
  • 威望68点
  • 贡献值0点
  • 好评度15点
  • 原创分0分
  • 专家分0分
16楼#
发布于:2003-12-31 21:23
这个我已经改了,改成了128k,但是一般系统不会一次i/o请求超过64k的,所以没什么用,估计miniport没戏了,得用别的port driver了
kangzh
驱动小牛
驱动小牛
  • 注册日期2004-03-09
  • 最后登录2012-08-06
  • 粉丝0
  • 关注0
  • 积分4分
  • 威望22点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
17楼#
发布于:2004-04-02 17:21
问问各位大牛:俺在Read10中调用如下SubRequest,之后在一个线程中接受事件来处理该Srb,之后将处理的Srb放到定时器的TimerCall中
完成提交,但在重新启动时好像死机一样,好像是Scsi miniport加载时一直处于等待状态,大家说一下我的这种做法可以吗?正确该怎么做呢

BOOLEAN CVThreadDevice::SubmitRequest(PSCSI_REQUEST_BLOCK Srb)
{
Srb->SrbStatus = SRB_STATUS_PENDING;

if( KeGetCurrentIrql()>DISPATCH_LEVEL )
{
VPrint(("Current IRQL: %x\n",KeGetCurrentIrql() ));
//
// KeSetEvent can only be running at DISPATCH_LEVEL and less
//
LoadStatus(Srb,recNOT_READY);
//
// use RequestReturn of base class here!
//
CVDevice::RequestReturn(Srb);
return TRUE;
}

((PSRB_EXTENSION)Srb->SrbExtension)->Srb = Srb;

ExInterlockedInsertTailList(
&RequestHead,
&((PSRB_EXTENSION)Srb->SrbExtension)->ListEntry,
&ListLock
);
//
// Signal the worker for processing
//
KeSetEvent(
&ThreadEvent,
IO_NO_INCREMENT,
FALSE );

return TRUE;
}
kangzh
驱动小牛
驱动小牛
  • 注册日期2004-03-09
  • 最后登录2012-08-06
  • 粉丝0
  • 关注0
  • 积分4分
  • 威望22点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
18楼#
发布于:2004-04-16 11:57
seaquester 大虾,救救小弟阿
把这段代码放到链表中,同时在线程中处理,就出现超时,但如果先把srb放到list中,并马上取出执行,就没有任何问题,请问这是怎么回事.

Srb->SrbStatus = SRB_STATUS_SUCCESS;
Srb->ScsiStatus = SCSISTAT_GOOD;
DbgPrint(\"this=%x,m_ScsiHBA=%x\\n\",this,m_ScsiHBA);
(this->*m_CmdTable[Srb->Cdb[0]])(Srb);
ScsiPortNotification(NextRequest,
(PVOID)m_ScsiHBA,
Srb );
ScsiPortNotification(RequestComplete,
(PVOID)m_ScsiHBA,
Srb );

kangzh
驱动小牛
驱动小牛
  • 注册日期2004-03-09
  • 最后登录2012-08-06
  • 粉丝0
  • 关注0
  • 积分4分
  • 威望22点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
19楼#
发布于:2004-04-21 17:49
terrychen:
你的scsi效率提高了吗?有没有比较好的方法亚
上一页
游客

返回顶部