INFO: Dieses Forum nutzt Cookies...
Cookies sind für den Betrieb des Forums unverzichtbar. Mit der Nutzung des Forums erklärst Du dich damit einverstanden, dass wir Cookies verwenden.

Es wird in jedem Fall ein Cookie gesetzt um diesen Hinweis nicht mehr zu erhalten. Desweiteren setzen wir Google Adsense und Google Analytics ein.


Antwort schreiben 

LV Handles



Wenn dein Problem oder deine Frage geklärt worden ist, markiere den Beitrag als "Lösung",
indem du auf den "Lösung" Button rechts unter dem entsprechenden Beitrag klickst. Vielen Dank!

11.03.2009, 13:53 (Dieser Beitrag wurde zuletzt bearbeitet: 11.03.2009 13:57 von abrissbirne.)
Beitrag #1

abrissbirne Offline
LVF-Stammgast
***


Beiträge: 480
Registriert seit: Aug 2007

LV2009, LV2010
2007
EN

66123
Deutschland
LV Handles
Hallo,

ich dachte ich hätte so langsam das Prinzip von Handles verstanden, aber eine neue Aufgabe hat mit gezeigt das ich wohl doch noch nicht ganz durchgestiegen bin.
Mein Problem:
Ich möchte Speicherplatz reservieren. Dazu verwende ich LV Memory Manager Funktionen. Über eine externe Bibliothek soll diese Platz beschrieben werden. Die Funktion die ich aufrufe erwartet als Übergabewert einen Daten-Pointer (DataPtr specifies a physical address that points to the data). Mein Handle besteht ja aus einem Master-Pointer der wiederum auf eine Liste von Pointern sieht. Ich dachte mir eigentlich es müsste irgendwie so funktionieren &(*Handle)->value. Wie kann ich also aus meinem Handle den Datenpointer extrahieren?

Danke, eure abrissbirne
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
Anzeige
11.03.2009, 16:46 (Dieser Beitrag wurde zuletzt bearbeitet: 11.03.2009 16:52 von abrissbirne.)
Beitrag #2

abrissbirne Offline
LVF-Stammgast
***


Beiträge: 480
Registriert seit: Aug 2007

LV2009, LV2010
2007
EN

66123
Deutschland
LV Handles
' schrieb:Hallo,

ich dachte ich hätte so langsam das Prinzip von Handles verstanden, aber eine neue Aufgabe hat mit gezeigt das ich wohl doch noch nicht ganz durchgestiegen bin.
Mein Problem:
Ich möchte Speicherplatz reservieren. Dazu verwende ich LV Memory Manager Funktionen. Über eine externe Bibliothek soll diese Platz beschrieben werden. Die Funktion die ich aufrufe erwartet als Übergabewert einen Daten-Pointer (DataPtr specifies a physical address that points to the data). Mein Handle besteht ja aus einem Master-Pointer der wiederum auf eine Liste von Pointern sieht. Ich dachte mir eigentlich es müsste irgendwie so funktionieren &(*Handle)->value. Wie kann ich also aus meinem Handle den Datenpointer extrahieren?

Danke, eure abrissbirne
Nochmal zum bessern Verständnis:
Ich befasse mich mit einer Datenaufnahme, welche über eine Bibliothek in C++ abläuft. Hier gibt es die Möglichkeit eine Funktion zu verwenden, die mir in einen von mir allocierten Speicherbereich Daten hineinschreibt. Diese Funktion erwartet von mir einen Daten-Pointer (siehe oben).
Ich bin nun folgendermaßen vorgegangen:
Ich reserviere mir Speicher mittels der Funktion DSNewHandle.
<div class='codetop'>CODE</div><div class='codemain' style='height:200px;white-space:pre;overflow:auto'>struct {
int32 dimSize[2];
uInt16 elmements;
} **UInt16Handle;

UInt16Handle MemoryHdl;
MemoryHdl = (UInt16Handle)DSNewHClr(sizeof(uInt16)*SizeX*SizeY);
</div>
Habs alternativ auch so versucht:
<div class='codetop'>CODE</div><div class='codemain' style='height:200px;white-space:pre;overflow:auto'>struct {
int32 dimSize[2];
uInt16 elmements;
} **UInt16Handle;

UInt16Handle MemoryHdl = NULL;
NumericArrayResize(uW, 2, (UHandle*)&MemoryHdl, SizeX*SizeY);
(*MemoryHdl)->dimSize[1] = SizeX;
(*MemoryHdl)->dimSize[2] = SizeY;
</div>
Die Funktion aus der Bibliothek sieht in etwa so aus:
<div class='codetop'>CODE</div><div class='codemain' style='height:200px;white-space:pre;overflow:auto'>CreateBuffer(SystemID, long SizeX, long SizeY, long Type, Attribute, long ControlFlag, long Pitch, void *DataPtr, BufferID);</div>
System ID: ergibt sich aus nach dem Verbindungsaufbau mit der Karte (OK)
SizeX: Ist ebenso kein Problem und wird aus einer Datei ausgelesen (OK)
SizeY: siehe SizeX
Type: UInt16 (OK)
Attribute: Können aus einer Liste gewählt werden (OK)
ControlFlag: PHYSICAL_ADDRESS (Specifies that DataPtr is a physical address that points to the data) (OK)
Pitch: Abstand zwischen zwei Zeilen des Arrays (Kann in Bildpunkten und Bytes angegeben werden). Entspricht quasi meinem SizeX (OK?)
DataPtr: Hier muss nun aus dem Handle der Datenpointer extrahiert werden. (NICHT OK)
BufferID: Ergibt sich wieder aus dem vorherigen Programmablauf (OK)

Diese Funktion sollte nun laut Beschreibung die Daten direkt in den von mir reservierten Speicher schreiben. Leider funktioniert es bis jetzt nicht.

Danke, eure abrissbirne
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
11.03.2009, 19:44
Beitrag #3

rolfk Offline
LVF-Guru
*****


Beiträge: 2.306
Registriert seit: Jun 2007

alle seit 6.0
1992
EN

2901GG
Niederlande
LV Handles
' schrieb:Nochmal zum bessern Verständnis:
Ich befasse mich mit einer Datenaufnahme, welche über eine Bibliothek in C++ abläuft. Hier gibt es die Möglichkeit eine Funktion zu verwenden, die mir in einen von mir allocierten Speicherbereich Daten hineinschreibt. Diese Funktion erwartet von mir einen Daten-Pointer (siehe oben).
Ich bin nun folgendermaßen vorgegangen:
Ich reserviere mir Speicher mittels der Funktion DSNewHandle.
<div class='codetop'>CODE</div><div class='codemain' style='height:200px;white-space:pre;overflow:auto'>struct {
int32 dimSize[2];
uInt16 elmements;
} **UInt16Handle;

UInt16Handle MemoryHdl;
MemoryHdl = (UInt16Handle)DSNewHClr(sizeof(uInt16)*SizeX*SizeY);
</div>
Habs alternativ auch so versucht:
<div class='codetop'>CODE</div><div class='codemain' style='height:200px;white-space:pre;overflow:auto'>struct {
int32 dimSize[2];
uInt16 elmements;
} **UInt16Handle;

UInt16Handle MemoryHdl = NULL;
NumericArrayResize(uW, 2, (UHandle*)&MemoryHdl, SizeX*SizeY);
(*MemoryHdl)->dimSize[1] = SizeX;
(*MemoryHdl)->dimSize[2] = SizeY;
</div>
Die Funktion aus der Bibliothek sieht in etwa so aus:
<div class='codetop'>CODE</div><div class='codemain' style='height:200px;white-space:pre;overflow:auto'>CreateBuffer(SystemID, long SizeX, long SizeY, long Type, Attribute, long ControlFlag, long Pitch, void *DataPtr, BufferID);</div>
System ID: ergibt sich aus nach dem Verbindungsaufbau mit der Karte (OK)
SizeX: Ist ebenso kein Problem und wird aus einer Datei ausgelesen (OK)
SizeY: siehe SizeX
Type: UInt16 (OK)
Attribute: Können aus einer Liste gewählt werden (OK)
ControlFlag: PHYSICAL_ADDRESS (Specifies that DataPtr is a physical address that points to the data) (OK)
Pitch: Abstand zwischen zwei Zeilen des Arrays (Kann in Bildpunkten und Bytes angegeben werden). Entspricht quasi meinem SizeX (OK?)
DataPtr: Hier muss nun aus dem Handle der Datenpointer extrahiert werden. (NICHT OK)
BufferID: Ergibt sich wieder aus dem vorherigen Programmablauf (OK)

Diese Funktion sollte nun laut Beschreibung die Daten direkt in den von mir reservierten Speicher schreiben. Leider funktioniert es bis jetzt nicht.

Danke, eure abrissbirne

Also die Funktion sollte eigentlich sogar mit der Call Library Node direkt aufrufbar sein. Allerdings macht mir das ControlFlag = PHYSICAL_ADDRESS einige Sorgen. In Windows 32Bit gibt es auf Ring3 Ebene (dem User Space) keine physikalischen Adressen sondern nur lineare Addressen. Zugriff auf physikalische Addressen sind dem Kernel und Treibern die darin laufen vorenthalten.

Rolf Kalbermatter

Rolf Kalbermatter
Technische Universität Delft, Dienst Elektronik und Mechanik
https://blog.kalbermatter.nl
Webseite des Benutzers besuchen Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
11.03.2009, 22:06
Beitrag #4

abrissbirne Offline
LVF-Stammgast
***


Beiträge: 480
Registriert seit: Aug 2007

LV2009, LV2010
2007
EN

66123
Deutschland
LV Handles
' schrieb:Also die Funktion sollte eigentlich sogar mit der Call Library Node direkt aufrufbar sein. Allerdings macht mir das ControlFlag = PHYSICAL_ADDRESS einige Sorgen. In Windows 32Bit gibt es auf Ring3 Ebene (dem User Space) keine physikalischen Adressen sondern nur lineare Addressen. Zugriff auf physikalische Addressen sind dem Kernel und Treibern die darin laufen vorenthalten.

Rolf Kalbermatter
Ok, dann wird der Fehler wohl bei mir liegen. Ich dachte das die Option PHYSICAL ADDRESS die Richtige wäre. Es gab aber noch 3 andere Möglichkeiten. Diese habe ich aber nicht im Kopf und muss sie nachlesen. Auf jeden Fall gab es eine HOST_ADDRESS. Allerdings ist mir der Begriff HOST in diesem Zusammenhang nicht ganz klar. Leider kann ich erst am Montag die genaue PArameterbeschreibung einsehen. Aber wenn du sagst das es PHYSICAL ADDRESS schonmal nicht sein kann wird es so seinBig Grin
Kannst du mir evt. erklären wie das Aufgebaut ist? Du sagtest ja etwas von Ring3 Eben. Oder hast du einen guten Link? Mich interessiert diese ganze Geschichte mit Speicherallozierung usw.

Danke schonmal dafür.

Gruß, eure abrissbirne
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
12.03.2009, 09:49 (Dieser Beitrag wurde zuletzt bearbeitet: 12.03.2009 09:55 von rolfk.)
Beitrag #5

rolfk Offline
LVF-Guru
*****


Beiträge: 2.306
Registriert seit: Jun 2007

alle seit 6.0
1992
EN

2901GG
Niederlande
LV Handles
' schrieb:Ok, dann wird der Fehler wohl bei mir liegen. Ich dachte das die Option PHYSICAL ADDRESS die Richtige wäre. Es gab aber noch 3 andere Möglichkeiten. Diese habe ich aber nicht im Kopf und muss sie nachlesen. Auf jeden Fall gab es eine HOST_ADDRESS. Allerdings ist mir der Begriff HOST in diesem Zusammenhang nicht ganz klar. Leider kann ich erst am Montag die genaue PArameterbeschreibung einsehen. Aber wenn du sagst das es PHYSICAL ADDRESS schonmal nicht sein kann wird es so seinBig Grin
Kannst du mir evt. erklären wie das Aufgebaut ist? Du sagtest ja etwas von Ring3 Eben. Oder hast du einen guten Link? Mich interessiert diese ganze Geschichte mit Speicherallozierung usw.

Also x86 Prozessoren haben sogenannte Rings. Alles was hier folgt ist aus meiner Erinnerung und schon einige Zeit alt und könnte deswegen in Details nicht ganz richtig sein, aber im Grossen und Ganzen sollte es die Wirklichkeit beschreiben.
Die x86 CPU hat 4 Ringe wenn ich mich nicht irre. Ein Betriebssystem kann nun bestimmte Operationen, Speicherzugriffe etc. an verschiedene Rings zuweisen. Ring 1 ist der meist privilegierte und Ring 4 der am Geringsten. Windows verwendet nur Ring 1 für den Kernel und Ring 3 für den User Space.

Speicher wird durch eine Speicherverwaltungseinheit verwaltet. Das ist ein Hardwareteil dass für jeden Prozess einen virtuellen (in Windows 32Bit auch linearen) Speicherbereich bereitstellt und diese an verschiedenen Orten im physikalischen Speicher mappt. Auch verwaltet sie das Paging des Speichers. Das heisst länger nicht gebrauchte physikalische Speicherbereiche werden mittels Interrupt zum OS ausgelagert um Platz zu machen für andere Applikationen. Wenn jetzt eine Applikation auf eine lineare Adresse zugreifen will die ausgelagert wurde merkt das die Speicherverwaltungseinheit und macht einen Interrupt zum OS um den entsprechenden Bereich wieder in den physikalischen Speicher zu laden. Obwhol ein Prozess einen linearen Speicherbereich sieht kann der entsprechenden Bereich im physikalischen Speicher wild durcheinander liegen da das OS mit sogenannten Pages arbeitet (ich glaube 4K gross unter Windows aber kann auch grösser sein) die immer als Ganzes verwaltet werden.

Zugriff auf die entsprechenden Selector Register um die lineare Adresse innerhalb eines Prozesses auf die physikalische Adresse zu übersetzen ist auch nur im Kernel möglich, wie auch die Ausführung bestimmter Opcodes, so auch beispielsweise inp und outp um auf IO Port Adressen zuzugreifen (ausser man verändert die IO Permission Map so dass inp und outp auf die entsprechenden Adressen keine Exception erzeugen wenn innerhalb des User Spaces ausgeführt). Dies nur mal eine Information am Rande ^_^

Ob PHYSICAL_ADDRESS in Deinem API wirklich phyikalische Speicheradressen bedeutet, kann ich Dir nicht sagen, Es kann sein dass der Programmierer da irgendwie etwas anderes meinte. An sich macht es nicht so viel Sinn um auf einem User Space API die Möglichkeit zu bieten eine wirkliche physikalische Adresse anzugeben.

Informationen zur Speicherverwaltung mit x86 CPUs findest Du in den entsprechenden Hardwarereferenzmanuals dieser Prozessoren Achtung das ist schwere Materie sowohl physikalisch schwer (die entsprechenden Manuals können Dein Büchergestell ziemlich belasten) als auch theoretisch.Big Grin

Rolf Kalbermatter

Rolf Kalbermatter
Technische Universität Delft, Dienst Elektronik und Mechanik
https://blog.kalbermatter.nl
Webseite des Benutzers besuchen Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
16.03.2009, 08:45
Beitrag #6

abrissbirne Offline
LVF-Stammgast
***


Beiträge: 480
Registriert seit: Aug 2007

LV2009, LV2010
2007
EN

66123
Deutschland
LV Handles
' schrieb:Also x86 Prozessoren haben sogenannte Rings. Alles was hier folgt ist aus meiner Erinnerung und schon einige Zeit alt und könnte deswegen in Details nicht ganz richtig sein, aber im Grossen und Ganzen sollte es die Wirklichkeit beschreiben.
Die x86 CPU hat 4 Ringe wenn ich mich nicht irre. Ein Betriebssystem kann nun bestimmte Operationen, Speicherzugriffe etc. an verschiedene Rings zuweisen. Ring 1 ist der meist privilegierte und Ring 4 der am Geringsten. Windows verwendet nur Ring 1 für den Kernel und Ring 3 für den User Space.

Speicher wird durch eine Speicherverwaltungseinheit verwaltet. Das ist ein Hardwareteil dass für jeden Prozess einen virtuellen (in Windows 32Bit auch linearen) Speicherbereich bereitstellt und diese an verschiedenen Orten im physikalischen Speicher mappt. Auch verwaltet sie das Paging des Speichers. Das heisst länger nicht gebrauchte physikalische Speicherbereiche werden mittels Interrupt zum OS ausgelagert um Platz zu machen für andere Applikationen. Wenn jetzt eine Applikation auf eine lineare Adresse zugreifen will die ausgelagert wurde merkt das die Speicherverwaltungseinheit und macht einen Interrupt zum OS um den entsprechenden Bereich wieder in den physikalischen Speicher zu laden. Obwhol ein Prozess einen linearen Speicherbereich sieht kann der entsprechenden Bereich im physikalischen Speicher wild durcheinander liegen da das OS mit sogenannten Pages arbeitet (ich glaube 4K gross unter Windows aber kann auch grösser sein) die immer als Ganzes verwaltet werden.

Zugriff auf die entsprechenden Selector Register um die lineare Adresse innerhalb eines Prozesses auf die physikalische Adresse zu übersetzen ist auch nur im Kernel möglich, wie auch die Ausführung bestimmter Opcodes, so auch beispielsweise inp und outp um auf IO Port Adressen zuzugreifen (ausser man verändert die IO Permission Map so dass inp und outp auf die entsprechenden Adressen keine Exception erzeugen wenn innerhalb des User Spaces ausgeführt). Dies nur mal eine Information am Rande ^_^

Ob PHYSICAL_ADDRESS in Deinem API wirklich phyikalische Speicheradressen bedeutet, kann ich Dir nicht sagen, Es kann sein dass der Programmierer da irgendwie etwas anderes meinte. An sich macht es nicht so viel Sinn um auf einem User Space API die Möglichkeit zu bieten eine wirkliche physikalische Adresse anzugeben.

Informationen zur Speicherverwaltung mit x86 CPUs findest Du in den entsprechenden Hardwarereferenzmanuals dieser Prozessoren Achtung das ist schwere Materie sowohl physikalisch schwer (die entsprechenden Manuals können Dein Büchergestell ziemlich belasten) als auch theoretisch.Big Grin

Rolf Kalbermatter
Jo, das klingt doch als würde es etwas länger dauern bis man durchsteigt. Ich habe die Beschreibung nochmal durchforstet und poste mal die Möglichkeiten für das Control Flag:
HOST_ADDRESS:
Specifies that DataPtr is a logical address that points to the data. Specifies that DataPtr is a logical address that points to the data ...

Note that when using logical addresses, memory protection errors could result.


PHYSICAL_ADDRESS:
Specifies that DataPtr is a physical address that points to the data ...

Note that using physical addresses provides direct access to any of your computer's memory mapped devices.

Specifics
This setting must be used for all buffers with the AQUIS attribute.

Ich muss doch den Parameter PHYSICAL_ADDRESS wählen, da ich ja daten erfassen möchte (Attribut AQUIS). Ich habe aber trotzdem schon den ein oder anderen schönen Bluescreen erzeugt Pccrash
Also scheine ich bei der Übergabe etwas falsch zu machen und die Funktion möchte in den falschen Speicherbereich schreiben. Damit wäre ich wieder bei dem Punkt wie ich den richtigen Adressbereich aus dem Handle ziehe. ODer liege ich mit meiner Einschätzung komplett daneben?

THX
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
16.03.2009, 10:16 (Dieser Beitrag wurde zuletzt bearbeitet: 16.03.2009 10:23 von rolfk.)
Beitrag #7

rolfk Offline
LVF-Guru
*****


Beiträge: 2.306
Registriert seit: Jun 2007

alle seit 6.0
1992
EN

2901GG
Niederlande
LV Handles
' schrieb:Jo, das klingt doch als würde es etwas länger dauern bis man durchsteigt. Ich habe die Beschreibung nochmal durchforstet und poste mal die Möglichkeiten für das Control Flag:
HOST_ADDRESS:
Specifies that DataPtr is a logical address that points to the data. Specifies that DataPtr is a logical address that points to the data ...

Note that when using logical addresses, memory protection errors could result.
PHYSICAL_ADDRESS:
Specifies that DataPtr is a physical address that points to the data ...

Note that using physical addresses provides direct access to any of your computer's memory mapped devices.

Specifics
This setting must be used for all buffers with the AQUIS attribute.

Ich muss doch den Parameter PHYSICAL_ADDRESS wählen, da ich ja daten erfassen möchte (Attribut AQUIS). Ich habe aber trotzdem schon den ein oder anderen schönen Bluescreen erzeugt Pccrash
Also scheine ich bei der Übergabe etwas falsch zu machen und die Funktion möchte in den falschen Speicherbereich schreiben. Damit wäre ich wieder bei dem Punkt wie ich den richtigen Adressbereich aus dem Handle ziehe. ODer liege ich mit meiner Einschätzung komplett daneben?

THX

Also so wie ich das lese, müsstest Du bei der Übergabe eines Pointers auf den Datenbereich eines LabVIEW Handles doch echt HOST_ADRESS verwenden. PHYSICAL_ADDRESS wäre sinnvoll wenn Du die Daten direkt per DMA auf den in den PCI-Bus gemappten Speicher einer PCI-Karte verschieben lassen möchtest. Das mit dem ACQUIS Attribute verstehe ich nicht ganz, aber trotzdem. Ein User Space Datenpointer, und das ist jeder Memorybereich der vom Speichermanager angefragt wird, ist wirklich keine Physical Address!!

Eventuel hat Dein API noch andere Funktionen wo Du direkt auf der Karte einen Onboardbuffer anlegen kannst. Dieser könnte dann das besagteAttribute bekommen und müsste auch als PhysicalAddress übergeben werden. NI hatte das mal vor vielen Jahren mit ihren DSP Karten so gemacht. Das Ganze war dazu gedacht um direkt optimal von den DMA Möglichkeiten Gebrauch zu machen.

Inzwischen wird das alles ganz transparent hinter den Kulissen in DAQmx gemacht und ist nicht wirklich langsamer und hat als Vorteil, dass sich der Benützer nicht mit solchen unverständlichen Details rumschlagen muss.

Dass Du bei der Übergabe eines Speicherpointers einen Bluescreen erzeugst wenn Du dem Treiber mitteilst dass er das als Physical Adress behandeln soll ist nicht verwunderlich. Effektiv könntest Du damit eventuel sogar die eine oder andere Hardware in Deinem PC per Unglück "bricken". Das ist der Ausdruck wenn man einen Chip auf der Hardware so anspricht, dass er irgendwas unzulässiges ausführt und sich selber oder eine andere Hardwarekomponente dabei so beschädigt dass sie ungefähr so wertlos wird wie ein Ziegelstein (engl. Brick) Lol. Meistens ist das auch unreparierbar.

Rolf Kalbermatter

Rolf Kalbermatter
Technische Universität Delft, Dienst Elektronik und Mechanik
https://blog.kalbermatter.nl
Webseite des Benutzers besuchen Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
30
Antwort schreiben 


Gehe zu: