PDA

Просмотр полной версии : Чтение буфера из системной памяти


xplo
30.10.2007, 14:15
Дано:
1. АЦП/ЦАП на USB.
2. Управление устройством осуществляется через библиотеку функций его драйвера.
3. Драйвер для Windows, не для LabView. Библиотека цепляется корректно, ее функции также работают корректно.
4. Драйвер устройства сваливает получаемые данные в буфер, расположенный в системной памяти.
5. Известны: адрес буфера, его размер, указатель на расположенные в нем данные.
6. Устройство исправно, поскольку ПО поставляемое разработчиком работает корректно.

Задача: Как прочитать полученные данные из буфера?

ЗЫ: Пробовал использовать функцию ReadFromPhysicalMemory из библиотеки cviVXDWrapper.dll и функцию RTLMoveMemory из библиотеки kernel32.dll. Первая читает некие данные, явно не корректные, а вторая так и не заработала. Наверное, неправильно их подключал.

Fakir
30.10.2007, 14:38
Как я понимаю речь идет о внутреннем буфере драйвера?
По идее, как обычно делают в таких системах, в драйвере должна быть функция которая производит чтение данных из своего внутреннего буфера, в качестве входных параметров у нее должен быть указатель на область памяти, куда надо скопировать данные.
Есть список функций, которые можно использовать?

xplo
30.10.2007, 14:41
Речь идет о буфере в области системной памяти, который доступен любой программе. Драйвер дает только адрес этого буфера, его размер и положение каждой новой порции поступающих в него данных.

Fakir
30.10.2007, 15:25
Попробовал вот это http://sine.ni.com/devzone/cda/epd/p/id/1132
вроде работает

xplo
30.10.2007, 16:20
Да, это работает (правда тоже есть отдельные неясности), но оно читает максимум только 2 слова. Данных же по объему гораздо больше, например: 1 канал*2 слова*4096 отсчетов = 65 кб. Если включить не один канал и, например, реализовывать осциллограф с разверткой 5мс/дел, то данная функция не сможет вовремя выбирать все данные.

PS: Можно ли вообще использовать в LabView функции типа RtlMoveMemory из kernel32? Если да, то как правильно импортировать библиотеку и настроить данную функцию?

Fakir
30.10.2007, 17:11
Да действительно только по 2 слова

Конечно можно пользоваться любой функцией из длл-ки, только надо оболочку правильно сделать, тут надо идти к msdn: http://msdn2.microsoft.com/en-us/library/ms803004.aspx

Fakir
30.10.2007, 17:48
Вот что-то получилось с длл-кой, проверь, за правильность работы не отвечаю...

iei
30.10.2007, 18:28
Смотри сюда (http://labview.ilc.edu.ru/forum/showthread.php?t=1283&highlight=%F3%EA%E0%E7%E0%F2%E5%EB%E8). Смотри библиотеку \resource\cviVXDWrapper.dll на предмет функции ReadFromPhysicalMemory, описание здесь (http://zone.ni.com/reference/en-XX/help/370051H-01/cvi/cvireadfromphysicalmemory/).:)
ЗЫ:
Зная как устроен массив LV в памяти можно попробовать "набросить" его на область памяти dll'ки. Но это уже на грани фантастики.:cool:

xplo
31.10.2007, 19:37
Вот что-то получилось с длл-кой, проверь, за правильность работы не отвечаю...
Ааа, эта штука хитрая оказалась. Пока меня не послали из техподдержки вот сюда (http://zone.ni.com/devzone/cda/tut/p/id/2719), я не мог ее корректно запустить. В итоге получилось то же, что и у тебя, только на выходе прицепляется не новый массив, а LocalVariable входного (см. рис. внизу)
Смотри сюда (http://labview.ilc.edu.ru/forum/showthread.php?t=1283&highlight=%F3%EA%E0%E7%E0%F2%E5%EB%E8). Смотри библиотеку \resource\cviVXDWrapper.dll на предмет функции ReadFromPhysicalMemory, описание здесь (http://zone.ni.com/reference/en-XX/help/370051H-01/cvi/cvireadfromphysicalmemory/).:)
С этой штукой я в итоге тоже разобрался. Однако оказалось, что она, в полном соответствии со свом названием :) , читает именно физическую память. А в мое распоряжение, оказывается, попадает некий "виртуальный" указатель на буфер. Не силен в "С", но в прототипе функции, которая возвращает этот указатель, он объявлен как void**buffer. В общем, штатная виндовая RtlMoveMemory прекрасно его понимает.
Что касается PointerTools, то они, насколько я понял, не позволяют читать данные со знаком.
Зная как устроен массив LV в памяти можно попробовать "набросить" его на область памяти dll'ки. Но это уже на грани фантастики.:cool:Чего? :eek:

iei
01.11.2007, 07:59
В общем, штатная виндовая RtlMoveMemory прекрасно его понимает.
Можно использовать не только стандартную виндовую функцию но и стандартную лабвьюшную - MoveBlock из библиотеки lvrt.dll (или labview.exe).

Что касается PointerTools, то они, насколько я понял, не позволяют читать данные со знаком.

Проверить сейчас не смогу. Но по идее должно читаться все. В конце концов, можно преобразовать полученный массив к знаковому типу.
Чего? :eek:
Если у тебя библиотека возвращает только указатель на область памяти. И эта область памяти постоянно занимает одно и то же адресное пространство. Так почему бы LV не сказать, что эта область памяти есть ничто иное, как ее массив.:)

xplo
01.11.2007, 09:04
Проверить сейчас не смогу. Но по идее должно читаться все. В конце концов, можно преобразовать полученный массив к знаковому типу.Проверил, действительно читает значения со знаком и отлично работает в моем приложении :o
Можно использовать не только стандартную виндовую функцию но и стандартную лабвьюшную - MoveBlock из библиотеки lvrt.dll (или labview.exe).О, про такую штуку не слышал. Посмотрю.

xplo
01.11.2007, 09:05
Если у тебя библиотека возвращает только указатель на область памяти. И эта область памяти постоянно занимает одно и то же адресное пространство. Так почему бы LV не сказать, что эта область памяти есть ничто иное, как ее массив.:)Насколько я понял, для этого нужно как минимум научиться говорить LV, в какой области памяти создавать свои переменные ...

xplo
01.11.2007, 09:58
А MoveBlock, похоже, пошустрее работает :)

iei
01.11.2007, 09:59
Насколько я понял, для этого нужно как минимум научиться говорить LV, в какой области памяти создавать свои переменные ...

необязательно, можно все свести к манипуляции c указателями на области памяти. но всего скорей это очень сильно не понравиться Labview.

Fakir
01.11.2007, 13:12
А MoveBlock, похоже, пошустрее работает :)
А почему у тебя функция возвращает Err?
в хедере ничего про это не написано:
VOID
RtlMoveMemory(
IN VOID UNALIGNED *Destination,
IN CONST VOID UNALIGNED *Source,
IN SIZE_T Length
);
З.Ы. В msdn советуют использовать RtlCopyMemory говорят она быстрее

xplo
01.11.2007, 15:31
А почему у тебя функция возвращает Err?
в хедере ничего про это не написано: ...
Это артефакт от применения ReadFromPhysicalMemory - следствие кривого глаза, не совсем прямых рук и спешки. :D
З.Ы. В msdn советуют использовать RtlCopyMemory говорят она быстрееПро эту эту штуку много где говорят на просторах Сети. Есть даже мнение, что RTLCopyMemory - та же RTLMoveMemory, только хитро объявленная. Не знаю, как оно на самом деле, а у меня в kernel32.dll этой функции нет.

vanessa
01.11.2007, 16:56
он объявлен как void**buffer.
Любят они местами так делать, это указатель на массив, причем, неопределенного типа. тоесть то, что ты получаеш это не адрес того места где данные лежат, а адрес того места, в котором записан адрес того места, где данные лежат.

xplo
01.11.2007, 17:14
адрес того места, в котором записан адрес того места, где данные лежат.Вот что-то типа этого мне рассказывал разработчик железки. Однако вот в чем штука - и RTLCopyMemory и MoveBlock и функция из PointerTools читают нужные мне данные только в том случае, если я получаю указатель как ArrayDataPointer, а использую как Value. В общем, в пору учить Си :)

vanessa
01.11.2007, 23:11
все довольно просто виглядит на си. например так

int val;
val=((int*)(*buffer))[0];

таким макаром можно достать значение типа i32 и без всяких дополнительнизх функций.

Vall
02.11.2007, 19:49
все довольно просто виглядит на си. например так

int val;
val=((int*)(*buffer))[0];

таким макаром можно достать значение типа i32 и без всяких дополнительнизх функций.

Еще немного - и свою dll с функцией копирования можно написать:D

vanessa
02.11.2007, 22:33
легко. я сделал CIN для доставания значений из результатов работи запроса mysql. там примерно та же ситуация, тип ROW не что иноє как char**.

Вот код CIN'а


/* CIN source file */

#include "extcode.h"
#include <windows.h>

MgErr CINRun(LStrHandle String, int32 *row, int32 *Index);

MgErr CINRun(LStrHandle String, int32 *row, int32 *Index)
{

char **mrow;


int32 len;

// MessageBox(NULL,s,"Row prt",MB_OK);

/*
if(row[0])
{*/
mrow=(char**)row[0];

if(mrow[Index[0]])
{
len=StrLen(mrow[Index[0]]);

NumericArrayResize(uB, 1L,(UHandle *)&String, len);

LStrLen(*String)=len;

MoveBlock(mrow[Index[0]], LStrBuf(*String), len);
}

else
{
NumericArrayResize(uB, 1L,(UHandle *)&String, 4);

LStrLen(*String)=4;

MoveBlock("NULL", LStrBuf(*String), 4);
}

return noErr;
}


а вот и обертка для того кина

Arcades
31.03.2008, 20:25
а это будет работать для Линукс вызова mmap(.......) функции?