NOTE: Performance Communication driver with single process
Description idea about perfom communication driver.
Dispatching 3 routines:
Dispatcher IRP_MJ_CREATE
Как косвенный признак начало работы с драйвером для передачи данных. В этом месте можно размести логику запросов на получения данных к нежестоящему драйверу. Основная задача, сформированть Н запросов и отослать нижестоящему драйверу. При завершении запроса положить в список завершенных, если не было запросов от IRP_MJ_READ, если они были то взять первый запрос и скопировать в него тело и установить запрос как завершенный
Dispatcher IRP_MJ_READ
Проверить список завершенных запросов, если не пуст, скопировать тело и установить что запрос завершен, в противном случае, отложить запрос(Mark) не устонавливая Complete.
Сложен в реализации.
Dispatcher IRP_MJ_WRITE
Формируем запрос на отправку данных, копируем из пришедшего запроса "тело". Устанавливаем пришедший запрос как завершонный. А новый запрос отправляем.
Побочный эфект может: Если отправка не удалась, то участник который отослал не узнает об этом. Так что нужно будет ему сообщить либым другим способом.
//-----------------------------------------------------------
typedef struct _PatternReadRequest
{
LIST_ENTRY List;
PIRP pIrp;
PVOID pBuffer;
struct _DEV_EXT * pDevExt;
} PatternReadRequest,
* PPatternReadRequest;
//-----------------------------------------------------------
NTSTATUS
IzVPipeDispatchCreate(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
)
/*++
** Dispatch IRP_MJ_CREATE
** Call next driver
** If succes pass read N requests to next driver
--*/
{
NTSTATUS Status;
//Can check Pnp State, write log, PAGED_CODE() and etc.
IoSkipCurrentIrpStackLocation( pIrp );
Status = IoCallDriver(pDevExt->UnderlyingPDO, pIrp);
PassReadRequests( pDevExt );
return( Status );
}
//-----------------------------------------------------------
void
PassReadRequests(
PDEV_EXT pDevExt
)
/*++
** Building MAX_COUNT_RECV_REQUEST read request and pass down
** Adding to list pending read requests
--*/
{
PPatternReadRequest pPatternRequest;
//Validate the once pass read requests
for ( i = 0; i < MAX_COUNT_RECV_REQUEST; ++i ) {
pPatternRequest = BuildPatternRequest( pDevExt );
IoSetCompletionRoutine(
pPatternRequest->pIrp,
ReadComplete,
pPatternRequest,
TRUE,
TRUE,
TRUE
);
//Adding to wait list
KeAcquireSpinLock( &pDevExt->lockRecv, &oldIrql);
InsertTailList( &pDevExt->ReadRequestWait, &pPatternRequest->List );
KeReleaseSpinLock( &pDevExt->lockRecv, oldIrql );
//delay request
Status = IoCallDriver(
pDevExt->NextLowerDriver,
pPatternRequest->pIrp
);
//Validate Status with PENDING
}
}
//-----------------------------------------------------------
PPatternReadRequest
IzVPipeBuildPatternRequest(
PDEV_EXT pDevExt
)
/*++
** Build patter internal read request
--*/
{
LARGE_INTEGER Offset;
PPatternReadRequest patternRequest;
patternRequest = ExAllocatePoolWithTag(
NonPagedPool,
sizeof( PatternReadRequest ),
0
);
if ( patternRequest == NULL ) {
goto exit_error;
}
patternRequest->pBuffer = ExAllocatePoolWithTag(
NonPagedPool,
pDevExt->MaxReceivePacketSize,
0
);
if ( patternRequest->pBuffer == NULL ) {
ExFreePool(patternRequest);
goto exit_error;
}
Offset.QuadPart = 0;
patternRequest->pIrp = IoBuildAsynchronousFsdRequest(
IRP_MJ_READ,
pDevExt->NextLowerDriver,
patternRequest->pBuffer,
pDevExt->MaxReceivePacketSize,
&Offset,
NULL
);
//Validate patternRequest->pIrp
patternRequest->pDevExt = pDevExt;
return (patternRequest);
exit_error:
//this is fail situation
return (NULL) ;
}
//-----------------------------------------------------------
NTSTATUS
DispatchRead(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
)
/*++
** Dispatch IRP_MJ_READ
**
*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG DataLength;
KIRQL oldIrql;
PPatternReadRequest pPatternRequest;
PVOID pIrpBuffer;
ULONG i;
PDEV_EXT pDevExt = ( PDEV_EXT )pDeviceObject->DeviceExtension;
PIO_STACK_LOCATION pIrpStack;
pIrpStack = IoGetCurrentIrpStackLocation( pIrp );
DataLength = pIrpStack->Parameters.Read.Length;
//Validate DataLength
pIrpBuffer = MmGetSystemAddressForMdlSafe(
pIrp->MdlAddress,
NormalPagePriority
);
if ( pIrpBuffer == NULL ) {
Status = STATUS_INVALID_PARAMETER;
pIrp->IoStatus.Status = Status;
IoCompleteRequest(
pIrp,
IO_NO_INCREMENT
);
return ( Status );
}
KeAcquireSpinLock(
&pDevExt->lockRecv,
&oldIrql
);
if ( IsListEmpty ( &pDevExt->ReadRequestComplete ) ) {
pPatternRequest = (PPatternReadRequest)
ExAllocatePoolWithTag(
NonPagedPool,
sizeof( PatternReadRequest ),
0
);
if ( pPatternRequest == NULL ) {
Status = STATUS_INSUFFICIENT_RESOURCES;
pIrp->IoStatus.Status = Status;
IoCompleteRequest(
pIrp,
IO_NO_INCREMENT
);
return ( Status );
}
pPatternRequest->pIrp = pIrp;
// insert to list pending request
InsertTailList(
&pDevExt->ReadRequestPending,
&pPatternRequest->List
);
IoMarkIrpPending( pPatternRequest->pIrp );
KeReleaseSpinLock(
&pDevExt->lockRecv,
oldIrql
);
return ( STATUS_PENDING );
}
else {
pPatternRequest = (PPatternReadRequest)
RemoveHeadList( &pDevExt->ReadRequestComplete );
KeReleaseSpinLock(
&pDevExt->lockRecv,
oldIrql
);
if ( pPatternRequest ) {
RtlCopyMemory(
pIrpBuffer,
pPatternRequest->pBuffer,
pPatternRequest->pIrp->IoStatus.Information
);
pIrp->IoStatus.Status = pPatternRequest->pIrp->IoStatus.Status;
pIrp->IoStatus.Information = pPatternRequest->pIrp->IoStatus.Information;
IoCompleteRequest(
pIrp,
IO_NO_INCREMENT
);
pPatternRequest = IzVPipeReusePatternRequest(pDevExt, pPatternRequest);
//check pPatternRequest
pPatternRequest->pDevExt = pDevExt;
IoSetCompletionRoutine(
pPatternRequest->pIrp,
IzVPipeReadComplete,
pPatternRequest,
TRUE,
TRUE,
TRUE
);
KeAcquireSpinLock( &pDevExt->lockRecv,
&oldIrql );
InsertTailList( &pDevExt->ReadRequestWait, &pPatternRequest->List );
KeReleaseSpinLock( &pDevExt->lockRecv, oldIrql );
Status = IoCallDriver(
pDevExt->NextLowerDriver,
pPatternRequest->pIrp
);
//Validate Status with STATUS_PENDING
return ( STATUS_SUCCESS );
}
}
return ( STATUS_PENDING );
}
//-----------------------------------------------------------
PPatternReadRequest
IzVPipeReusePatternRequest(
PDEV_EXT pDevExt,
PPatternReadRequest patternRequest
)
/*++
** Free old IRP and memory and build new Async read request
--*/
{
PMDL mdl;
PMDL nextMdl;
LARGE_INTEGER Offset;
Description idea about perfom communication driver.
Dispatching 3 routines:
- IRP_MJ_CREATE
- IRP_MJ_READ
- IRP_MJ_WRITE
Dispatcher IRP_MJ_CREATE
Как косвенный признак начало работы с драйвером для передачи данных. В этом месте можно размести логику запросов на получения данных к нежестоящему драйверу. Основная задача, сформированть Н запросов и отослать нижестоящему драйверу. При завершении запроса положить в список завершенных, если не было запросов от IRP_MJ_READ, если они были то взять первый запрос и скопировать в него тело и установить запрос как завершенный
Dispatcher IRP_MJ_READ
Проверить список завершенных запросов, если не пуст, скопировать тело и установить что запрос завершен, в противном случае, отложить запрос(Mark) не устонавливая Complete.
Сложен в реализации.
Dispatcher IRP_MJ_WRITE
Формируем запрос на отправку данных, копируем из пришедшего запроса "тело". Устанавливаем пришедший запрос как завершонный. А новый запрос отправляем.
Побочный эфект может: Если отправка не удалась, то участник который отослал не узнает об этом. Так что нужно будет ему сообщить либым другим способом.
//-----------------------------------------------------------
typedef struct _PatternReadRequest
{
LIST_ENTRY List;
PIRP pIrp;
PVOID pBuffer;
struct _DEV_EXT * pDevExt;
} PatternReadRequest,
* PPatternReadRequest;
//-----------------------------------------------------------
NTSTATUS
IzVPipeDispatchCreate(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
)
/*++
** Dispatch IRP_MJ_CREATE
** Call next driver
** If succes pass read N requests to next driver
--*/
{
NTSTATUS Status;
//Can check Pnp State, write log, PAGED_CODE() and etc.
IoSkipCurrentIrpStackLocation( pIrp );
Status = IoCallDriver(pDevExt->UnderlyingPDO, pIrp);
PassReadRequests( pDevExt );
return( Status );
}
//-----------------------------------------------------------
void
PassReadRequests(
PDEV_EXT pDevExt
)
/*++
** Building MAX_COUNT_RECV_REQUEST read request and pass down
** Adding to list pending read requests
--*/
{
PPatternReadRequest pPatternRequest;
//Validate the once pass read requests
for ( i = 0; i < MAX_COUNT_RECV_REQUEST; ++i ) {
pPatternRequest = BuildPatternRequest( pDevExt );
IoSetCompletionRoutine(
pPatternRequest->pIrp,
ReadComplete,
pPatternRequest,
TRUE,
TRUE,
TRUE
);
//Adding to wait list
KeAcquireSpinLock( &pDevExt->lockRecv, &oldIrql);
InsertTailList( &pDevExt->ReadRequestWait, &pPatternRequest->List );
KeReleaseSpinLock( &pDevExt->lockRecv, oldIrql );
//delay request
Status = IoCallDriver(
pDevExt->NextLowerDriver,
pPatternRequest->pIrp
);
//Validate Status with PENDING
}
}
//-----------------------------------------------------------
PPatternReadRequest
IzVPipeBuildPatternRequest(
PDEV_EXT pDevExt
)
/*++
** Build patter internal read request
--*/
{
LARGE_INTEGER Offset;
PPatternReadRequest patternRequest;
patternRequest = ExAllocatePoolWithTag(
NonPagedPool,
sizeof( PatternReadRequest ),
0
);
if ( patternRequest == NULL ) {
goto exit_error;
}
patternRequest->pBuffer = ExAllocatePoolWithTag(
NonPagedPool,
pDevExt->MaxReceivePacketSize,
0
);
if ( patternRequest->pBuffer == NULL ) {
ExFreePool(patternRequest);
goto exit_error;
}
Offset.QuadPart = 0;
patternRequest->pIrp = IoBuildAsynchronousFsdRequest(
IRP_MJ_READ,
pDevExt->NextLowerDriver,
patternRequest->pBuffer,
pDevExt->MaxReceivePacketSize,
&Offset,
NULL
);
//Validate patternRequest->pIrp
patternRequest->pDevExt = pDevExt;
return (patternRequest);
exit_error:
//this is fail situation
return (NULL) ;
}
//-----------------------------------------------------------
NTSTATUS
DispatchRead(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
)
/*++
** Dispatch IRP_MJ_READ
**
*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG DataLength;
KIRQL oldIrql;
PPatternReadRequest pPatternRequest;
PVOID pIrpBuffer;
ULONG i;
PDEV_EXT pDevExt = ( PDEV_EXT )pDeviceObject->DeviceExtension;
PIO_STACK_LOCATION pIrpStack;
pIrpStack = IoGetCurrentIrpStackLocation( pIrp );
DataLength = pIrpStack->Parameters.Read.Length;
//Validate DataLength
pIrpBuffer = MmGetSystemAddressForMdlSafe(
pIrp->MdlAddress,
NormalPagePriority
);
if ( pIrpBuffer == NULL ) {
Status = STATUS_INVALID_PARAMETER;
pIrp->IoStatus.Status = Status;
IoCompleteRequest(
pIrp,
IO_NO_INCREMENT
);
return ( Status );
}
KeAcquireSpinLock(
&pDevExt->lockRecv,
&oldIrql
);
if ( IsListEmpty ( &pDevExt->ReadRequestComplete ) ) {
pPatternRequest = (PPatternReadRequest)
ExAllocatePoolWithTag(
NonPagedPool,
sizeof( PatternReadRequest ),
0
);
if ( pPatternRequest == NULL ) {
Status = STATUS_INSUFFICIENT_RESOURCES;
pIrp->IoStatus.Status = Status;
IoCompleteRequest(
pIrp,
IO_NO_INCREMENT
);
return ( Status );
}
pPatternRequest->pIrp = pIrp;
// insert to list pending request
InsertTailList(
&pDevExt->ReadRequestPending,
&pPatternRequest->List
);
IoMarkIrpPending( pPatternRequest->pIrp );
KeReleaseSpinLock(
&pDevExt->lockRecv,
oldIrql
);
return ( STATUS_PENDING );
}
else {
pPatternRequest = (PPatternReadRequest)
RemoveHeadList( &pDevExt->ReadRequestComplete );
KeReleaseSpinLock(
&pDevExt->lockRecv,
oldIrql
);
if ( pPatternRequest ) {
RtlCopyMemory(
pIrpBuffer,
pPatternRequest->pBuffer,
pPatternRequest->pIrp->IoStatus.Information
);
pIrp->IoStatus.Status = pPatternRequest->pIrp->IoStatus.Status;
pIrp->IoStatus.Information = pPatternRequest->pIrp->IoStatus.Information;
IoCompleteRequest(
pIrp,
IO_NO_INCREMENT
);
pPatternRequest = IzVPipeReusePatternRequest(pDevExt, pPatternRequest);
//check pPatternRequest
pPatternRequest->pDevExt = pDevExt;
IoSetCompletionRoutine(
pPatternRequest->pIrp,
IzVPipeReadComplete,
pPatternRequest,
TRUE,
TRUE,
TRUE
);
KeAcquireSpinLock( &pDevExt->lockRecv,
&oldIrql );
InsertTailList( &pDevExt->ReadRequestWait, &pPatternRequest->List );
KeReleaseSpinLock( &pDevExt->lockRecv, oldIrql );
Status = IoCallDriver(
pDevExt->NextLowerDriver,
pPatternRequest->pIrp
);
//Validate Status with STATUS_PENDING
return ( STATUS_SUCCESS );
}
}
return ( STATUS_PENDING );
}
//-----------------------------------------------------------
PPatternReadRequest
IzVPipeReusePatternRequest(
PDEV_EXT pDevExt,
PPatternReadRequest patternRequest
)
/*++
** Free old IRP and memory and build new Async read request
--*/
{
PMDL mdl;
PMDL nextMdl;
LARGE_INTEGER Offset;
if ( patternRequest->pIrp->MdlAddress != NULL) {
for ( mdl = patternRequest->pIrp->MdlAddress; mdl != NULL; mdl = nextMdl ) {
nextMdl = mdl->Next;
MmUnlockPages( mdl );
}
patternRequest->pIrp->MdlAddress = NULL;
}
IoFreeIrp ( patternRequest->pIrp );
Offset.QuadPart = 0;
patternRequest->pIrp = IoBuildAsynchronousFsdRequest(
IRP_MJ_READ,
pDevExt->NextLowerDriver,
patternRequest->pBuffer,
pDevExt->MaxReceivePacketSize,
&Offset,
NULL
);
// Check patternRequest->pIrp
return (patternRequest);
exit_error:
//this is fail situation
return ( NULL );
}
//-----------------------------------------------------------
void
IzVPipeFreePatternRequest(
PPatternReadRequest patternRequest
)
/*++
** Free intern pattern read request
--*/
{
PMDL mdl;
PMDL nextMdl;
if ( patternRequest->pIrp->MdlAddress != NULL) {
for ( mdl = patternRequest->pIrp->MdlAddress; mdl != NULL; mdl = nextMdl ) {
nextMdl = mdl->Next;
MmUnlockPages( mdl );
IoFreeMdl( mdl );
}
patternRequest->pIrp->MdlAddress = NULL;
}
IoFreeIrp ( patternRequest->pIrp );
ExFreePoolWithTag( patternRequest, 0 );
}
//-----------------------------------------------------------
NTSTATUS
IzVPipeWriteComplete(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp,
PVOID pUncastedContext // pBufferWorker
)
/*++
Stub write complete with free request
--*/
{
ExFreePool( pUncastedContext );
//IoFreeIrp ( pIrp );
return ( STATUS_MORE_PROCESSING_REQUIRED );
}
//-----------------------------------------------------------
NTSTATUS
IzVPipeDispatchWrite(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
)
/*++
** Dispatch IRP_MJ_WRITE
** Allocate Async request
** Copy request from Dispatch to new Async request
** SetComplete as Success.
** pass Async request to next driver
*/
{
NTSTATUS Status = STATUS_SUCCESS;
PDEV_EXT pDevExt = ( PDEV_EXT )pDeviceObject->DeviceExtension;
PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation( pIrp );
ULONG DataLength;
PIRP pIrpWorker;
PVOID pBufferWorker;
PVOID pIrpBuffer;
//Validate Pnp, increment device usage
DataLength = pIrpStack->Parameters.Write.Length;
pIrpBuffer = MmGetSystemAddressForMdlSafe(
pIrp->MdlAddress,
NormalPagePriority
);
if ( pIrpBuffer == NULL ) {
Status = STATUS_INVALID_PARAMETER;
pIrp->IoStatus.Status = Status;
IoCompleteRequest(
pIrp,
IO_NO_INCREMENT
);
return ( Status );
}
pBufferWorker = ExAllocatePoolWithTag(
NonPagedPool,
DataLength,
0
);
//Check pBufferWorker
//copy memory from request to new async request buffer
RtlCopyMemory(
pBufferWorker,
pIrpBuffer, //pIrp->AssociatedIrp.SystemBuffer,
DataLength
);
// Buildig write request
pIrpWorker = IoBuildAsynchronousFsdRequest(
IRP_MJ_WRITE,
pDevExt->NextLowerDriver,
pBufferWorker,
DataLength,
NULL,
NULL
);
//Check pIrpWorker
pIrp->IoStatus.Status = Status = STATUS_SUCCESS;
//set request success, but this is request not be completeed
IoCompleteRequest(
pIrp,
IO_NO_INCREMENT
);
IoSetCompletionRoutine(
pIrpWorker,
IzVPipeWriteComplete,
pBufferWorker,
TRUE,
TRUE,
TRUE
);
Status = IoCallDriver(
pDevExt->NextLowerDriver,
pIrpWorker
);
if ( Status != STATUS_PENDING ) {
}
return ( Status );
}
for ( mdl = patternRequest->pIrp->MdlAddress; mdl != NULL; mdl = nextMdl ) {
nextMdl = mdl->Next;
MmUnlockPages( mdl );
}
patternRequest->pIrp->MdlAddress = NULL;
}
IoFreeIrp ( patternRequest->pIrp );
Offset.QuadPart = 0;
patternRequest->pIrp = IoBuildAsynchronousFsdRequest(
IRP_MJ_READ,
pDevExt->NextLowerDriver,
patternRequest->pBuffer,
pDevExt->MaxReceivePacketSize,
&Offset,
NULL
);
// Check patternRequest->pIrp
return (patternRequest);
exit_error:
//this is fail situation
return ( NULL );
}
//-----------------------------------------------------------
void
IzVPipeFreePatternRequest(
PPatternReadRequest patternRequest
)
/*++
** Free intern pattern read request
--*/
{
PMDL mdl;
PMDL nextMdl;
if ( patternRequest->pIrp->MdlAddress != NULL) {
for ( mdl = patternRequest->pIrp->MdlAddress; mdl != NULL; mdl = nextMdl ) {
nextMdl = mdl->Next;
MmUnlockPages( mdl );
IoFreeMdl( mdl );
}
patternRequest->pIrp->MdlAddress = NULL;
}
IoFreeIrp ( patternRequest->pIrp );
ExFreePoolWithTag( patternRequest, 0 );
}
//-----------------------------------------------------------
NTSTATUS
IzVPipeWriteComplete(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp,
PVOID pUncastedContext // pBufferWorker
)
/*++
Stub write complete with free request
--*/
{
ExFreePool( pUncastedContext );
//IoFreeIrp ( pIrp );
return ( STATUS_MORE_PROCESSING_REQUIRED );
}
//-----------------------------------------------------------
NTSTATUS
IzVPipeDispatchWrite(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
)
/*++
** Dispatch IRP_MJ_WRITE
** Allocate Async request
** Copy request from Dispatch to new Async request
** SetComplete as Success.
** pass Async request to next driver
*/
{
NTSTATUS Status = STATUS_SUCCESS;
PDEV_EXT pDevExt = ( PDEV_EXT )pDeviceObject->DeviceExtension;
PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation( pIrp );
ULONG DataLength;
PIRP pIrpWorker;
PVOID pBufferWorker;
PVOID pIrpBuffer;
//Validate Pnp, increment device usage
DataLength = pIrpStack->Parameters.Write.Length;
pIrpBuffer = MmGetSystemAddressForMdlSafe(
pIrp->MdlAddress,
NormalPagePriority
);
if ( pIrpBuffer == NULL ) {
Status = STATUS_INVALID_PARAMETER;
pIrp->IoStatus.Status = Status;
IoCompleteRequest(
pIrp,
IO_NO_INCREMENT
);
return ( Status );
}
pBufferWorker = ExAllocatePoolWithTag(
NonPagedPool,
DataLength,
0
);
//Check pBufferWorker
//copy memory from request to new async request buffer
RtlCopyMemory(
pBufferWorker,
pIrpBuffer, //pIrp->AssociatedIrp.SystemBuffer,
DataLength
);
// Buildig write request
pIrpWorker = IoBuildAsynchronousFsdRequest(
IRP_MJ_WRITE,
pDevExt->NextLowerDriver,
pBufferWorker,
DataLength,
NULL,
NULL
);
//Check pIrpWorker
pIrp->IoStatus.Status = Status = STATUS_SUCCESS;
//set request success, but this is request not be completeed
IoCompleteRequest(
pIrp,
IO_NO_INCREMENT
);
IoSetCompletionRoutine(
pIrpWorker,
IzVPipeWriteComplete,
pBufferWorker,
TRUE,
TRUE,
TRUE
);
Status = IoCallDriver(
pDevExt->NextLowerDriver,
pIrpWorker
);
if ( Status != STATUS_PENDING ) {
}
return ( Status );
}
Комментариев нет:
Отправить комментарий