20楼#
发布于:2004-04-21 18:06
我用cache没有提高performance,用timer的方式效率一定很低的,微软的办法是重写一个port driver.
你们那里有没有写port driver的高手? |
|
21楼#
发布于:2004-04-25 23:28
请问你的例子是什么系统
port driver 在win98下才会用吧 |
|
22楼#
发布于:2004-04-26 14:05
我这里也没有port driver的例子,我自己也在找,现在只在www.storagecraft.com这里发现有人写了这个,准备让公司去买一套过来看看。
|
|
23楼#
发布于:2004-04-26 16:46
NT4 Source里边有SCSIPORT.SYS的源代码,可以拿来参考一下。
|
|
24楼#
发布于:2004-04-27 09:15
o,真的么?太好了,能告诉我哪里有下么
|
|
25楼#
发布于:2004-04-27 11:11
o,真的么?太好了,能告诉我哪里有下么 可以使用BT下载啊,NT4 Sourcr泄露出来都那么久了,你竟然不知道?难道是闭关练功去了? |
|
|
26楼#
发布于:2004-04-27 14:00
我知道nt的code出来了,但是没想到这块也会有,一直都在忙,还没空看这些东西呢,主要还是怕看不懂,呵呵
|
|
27楼#
发布于:2004-04-28 11:56
你是加个预取线程吧,我用这个方法的时候,预取线程和StartIo 总是不能并行运行,总是StartIo把cache搞完后才轮到预取线程运行。不知道你是怎么调优先级的。我的用cdspeed测试只有5M/s,Daemon可以到100M/s,真是变态。
加cache可能会有改善。我们就是这样提速的,差不多在10倍左右。用Nero测试下来,Burst Rate在60M左右。 |
|
28楼#
发布于:2004-04-29 09:13
我只有3MB/s,差劲啊,有没有details关于预取?
|
|
29楼#
发布于:2004-04-30 16:06
预取这个东西就靠自己发挥了,呵呵,先把数据读到内存,下次就可以在startio拷贝数据,完成请求了。
|
|
30楼#
发布于:2005-01-25 15:04
我只有3MB/s,差劲啊,有没有details关于预取? 加一个LRU ,FIFO,OPT的队列就可以提高突发速率。可以达到daemon-tools 那样BT的300-400M/S的速度的。 不过提高数据传输确实恼火,用scsitimer 老是快不了。 |
|
|
31楼#
发布于:2005-01-26 17:49
daemon-tools alcohol的数据传输速率好象也不高呀。也就100X左右(17M/S)。是不是还是拜这个scsitimer 所害?
听说有人采用backdoor scsiport driver 可以达到71M/S, 采用哪个VSPORT 可以达到84M/s ,不知道是否是真的? 下边这种方法老大们用过吗? Subject: Re: Anton..Can you help? From: "Anton Kolomyeytsev" <xxx@cooldev.com> Date: Thu, 23 Jan 2003 09:29:39 -0500 Hi, you do not need to send SRBs to some unknown miniport, you need to send SRBs to yourself. From the worker thread you create to call all the code that need to be executed at PASSIVE_LEVEL and in system thread context you just call your own miniport to complete the previous request (SRB) you're handing in the worker thread now. First you need to locate DEVICE_OBJECT that belongs to you (to your miniport). PDEVICE_OBJECT g__PDEVICE_OBJECT__Miniport in global data region. In DriverEntry( ... ) you need to run: PDEVICE_OBJECT l__PDEVICE_OBJECT__Scan = ( ( PDRIVER_OBJECT )( p__PVOID__DriverObject )->DeviceObject ); while ( l__PDEVICE_OBJECT ) { ULONG l__ULONG__DeviceType = l__PDEVICE_OBJECT__Scan->DeviceType; if ( l__ULONG__DeviceType == FILE_DEVICE_CONTROLLER ) { g__PDEVICE_OBJECT__Miniport = l__PDEVICE_OBJECT__Scan; // Keep the pointer!!! break; } l__PDEVICE_OBJECT__Scan = l__PDEVICE_OBJECT__Scan->NextDevice; } Now you have DEVICE_OBJECT of your miniport in global variable. The way shown above is not "safe" but it works for me. If you do not like this way you can always try to enumerate all the SCSI miniports and find your own instance somewhere in the delayed initialization or later by call to ZwCreateFile( ..., "\\Device\\Scsi%u", ... ). Now in the worker thread that just executed code to do something with SRB you need to run this code (p__PSCSI_REQUEST_BLOCK__Srb is the SRB you're executing): KEVENT l__KEVENT; IO_STATUS_BLOCK l__IO_STATUS_BLOCK; PIRP l__PIRP; NTSTATUS l__NTSTATUS; SCSI_REQUEST_BLOCK l__SCSI_REQUEST_BLOCK; PIO_STACK_LOCATION l__PIO_STACK_LOCATION; PVOID l__PVOID__SrbBuffer = ( PVOID )( p__PSCSI_REQUEST_BLOCK__Srb ); // Keep pointer to SRB here LARGE_INTEGER l__LARGE_INTEGER__StartingOffset; KeInitializeEvent( &l__KEVENT, NotificationEvent, FALSE ); l__LARGE_INTEGER.QuadPart = 1; // SCSIPORT.SYS does this, do not know for what l__PIRP = IoBuildSynchronousFsdRequest( IRP_MJ_SCSI, g__PDEVICE_OBJECT__Miniport, // Global device object &l__PVOID__SrbBuffer, sizeof( l__PVOID__SrbBuffer ), &l__LARGE_INTEGER__StartingOffset, &l__KEVENT, &l__IO_STATUS_BLOCK ); RtlZeroMemory( &l__SCSI_REQUEST_BLOCK, sizeof( l__SCSI_REQUEST_BLOCK ) ); l__SCSI_REQUEST_BLOCK.TargetId = l__UCHAR__TargetId; // Your target ID goes here, and all SCSI address should be correct ... l__SCSI_REQUEST_BLOCK.Function = 2; l__SCSI_REQUEST_BLOCK.Length = sizeof( SCSI_REQUEST_BLOCK ); l__SCSI_REQUEST_BLOCK.SrbFlags = ( SRB_FLAGS_DATA_IN | SRB_FLAGS_NO_QUEUE_FREEZE | SRB_FLAGS_BYPASS_FROZEN_QUEUE ); // DO NOT FORGET TO PUT THIS FLAG OR YOU MAY RUN A DEADLOCK!! l__SCSI_REQUEST_BLOCK.DataBuffer = l__PVOID__SrbBuffer; l__SCSI_REQUEST_BLOCK.DataTransferLength = sizeof( l__PVOID__Buffer ); l__PIO_STACK_LOCATION = IoGetNextIrpStackLocation( l__PIRP ); l__PIO_STACK_LOCATION->MajorFunction = IRP_MJ_SCSI; l__PIO_STACK_LOCATION->MinorFunction = 1; l__PIO_STACK_LOCATION->Parameters.Scsi.Srb = &l__SCSI_REQUEST_BLOCK; l__NTSTATUS = IoCallDriver( g__PDEVICE_OBJECT__Miniport, // Global device object l__PIRP ); if( l__NTSTATUS == STATUS_PENDING ) { KeWaitForSingleObject( &l__KEVENT, Executive, KernelMode, FALSE, NULL ); l__NTSTATUS = l__IO_STATUS_BLOCK.Status; } Analyze l__NTSTATUS that keep operation completion here. So the idea is simple. From the thread that runs independently you can queue SRB that holds the pointer to the SRB you want to complete to your own miniport (if asking SCSIPORT to process the flag with no queue freeze). In the context of the SCSI miniport (HwStartIo) you analyze SRB and complete both SRBs on the same time, first that is pointer in .Buffer of the "parent" SRB and next this SRB itself ("parent"). That's all... I'm very sorry but I'm not going to spend more time on this topic - I've did this already last year and I have other things to do and do not know anything new about this stuff. In your particular case I'll recommend to write WDM driver that will be shared between 2000/XP/.NET and 98/Me and have storage part separated into port drivers (different of course ) for both platforms. Very good sample of doing this is USBLS120 from Microsoft (this sample not part of DDK but can be found on the net). Good luck! Regards, Anton Kolomyeytsev |
|
|
32楼#
发布于:2005-01-27 13:37
为什么我用上面的方法,老是停在KeWaitForSingleObject上了??并且没有进我的HwStartIo
我的是xp |
|
上一页
下一页