Hallo,
ich programmiere unter Linux C#. Ich bin an einem problem angekommen wo
ich einfach nicht weiterkomme.
Ich lese mit read () und rbuffer34, aus einen Device die Anzahl
BytesToRead aus.
hDevice = open("/dev/ics554-1", O_RDWR);
ULONGLONG *rbuffer34[10];
if (0 > read (hDevice, rbuffer34[x], BytesToRead)) {
perror("read34[0]");
}
anschliessend wollte ich diese Daten, also die kompletten BytesToRead,
in ein Shared Mamory Blockweise schreiben und mit printf(..) einen int
wert auf den terminal ausgeben lassen(um zu gucken ob bzw. was dort
steht).
Man könnte zwar sofort, die BytesToRead, in eine Datei schreiben, das
wollte ich allerdings mit einem anderen Prozess machen und die Daten
vorher im Shared Mamory puffern.
int *shPtr2I, WriteBytes;
shID2I = shmget(IPC_PRIVATE, MAXMYMEM, IPC_CREAT|0666);
shPtr2I = shmat(shID2I, 0, 0);
WriteBytes = write(*shPtr2I, rbuffer34[x], BytesToRead);
printf("WriteBytes = d%, *shPtr2I = %d \n\r",WriteBytes,*shPtr2I );
Für WriteBytes kriege ich eine Zahl raus die BytesToRead entspricht, was
richtig ist, allesdings kriege ich im terminal für *shPtr2I immer eine
Null = 0; geprintet. Ich weiss nicht was ich falsch mache, printe ich
Falsch oder klappt das so nicht mit dem write() bzw read() wie ich es
mir vorstelle?? jemand eine Idee?
mfg
Hans
> WriteBytes = write(*shPtr2I, rbuffer34[x], BytesToRead);
Bist Du Dir sicher, daß Du hier den Pointer shPtr2I dereferenzieren
möchtest?
Übrigens: Es heißt M_e_mory.
Hey!
Ist schon Jahre her, das ich shared mems benutzt habe. Aber ich stelle
mal ein paar Fragen zum Nachdenken.
Wieso "write" auf nem SHM? Um ins SHM zu schreiben "memcpy" und deren
Derivate. Um aus einer Datei zu lesen und direkt ins SHM zu schreiben
"read" nehmen.
1
ULONGLONG*rbuffer34[10];
ist nicht schön, wenn ich Bytes lesen und schreiben will. Besser UCHAR
nehmen und die echte Anzahl Bytes allokieren (malloc etc).
1
if(0>read(hDevice,rbuffer34[x],BytesToRead)){
2
perror("read34[0]");
3
}
Nochmal den Rückgabewert von "read" prüfen. Ist der -1 im Fehlerfall?
Rufus Τ. Firefly schrieb:> Übrigens: Es heißt M_e_mory.
Danke für den Tipp.
Olaf H. schrieb:> Wieso "write" auf nem SHM?
Weil ich auf eine andere Lösung nicht gekommen bin(fehlt einwenig die
Erfahrung). Ist memcpy schneller als read? oder nur einfacher zu
handhaben muss die daten so schnell wie möglich schaufeln, desshalb
wollte ich das blockweise machen. Kenn mich noch nicht mit dem schaufeln
so aus ;-).
Olaf H. schrieb:> Besser UCHAR> nehmen und die echte Anzahl Bytes allokieren (malloc etc).
Es ist so, dass eigenlich mit 64 bit Werten gearbeitet wird. Später
werden die 64bit in zwei 32 bit Werte auseinander gepflückt.
Die Daten liegen im hDevice Binär vor. Es wird auch alloiert wie das
aussieht im DMA Speicher: (Sorry aber ich habe den C-Code nicht komplett
geschrieben, muss mich erst durchkämpfen)
rbuffer34[i] = (ULONGLONG *) ics554AllocateDmaBuffer
(hDevice,BytesToRead);
if (NULL == rbuffer34[i]) {
printf ("\nCouldn't allocate memory or insufficient memory.\n");
goto ErrorExit;
}
memset (rbuffer34[i], 0, BytesToRead);
}
Olaf H. schrieb:> Nochmal den Rückgabewert von "read" prüfen.
Der Rückgabewert von read entspricht BytesToRead, es wurde also richtig
gelesen.
Olaf H. schrieb:> Du druckst den Wert des ersten Bytes im SHM aus
Ja das ist was ich will, nur habe ich gedacht, das ich nicht das erste
byte ausdrucke sondern die ersten 4byte(da ein 64bit system und
printf(%d) bzw. int *shPtr2I).
Hans schrieb:>> Olaf H. schrieb:>> Nochmal den Rückgabewert von "read" prüfen.>> Der Rückgabewert von read entspricht BytesToRead, es wurde also richtig> gelesen.
OK
>> Olaf H. schrieb:>> Du druckst den Wert des ersten Bytes im SHM aus>> Ja das ist was ich will, nur habe ich gedacht, das ich nicht das erste> byte ausdrucke sondern die ersten 4byte(da ein 64bit system und> printf(%d) bzw. int *shPtr2I).
OK. Du druckst auch nicht das erste Byte aus. Die Typen müssen auch beim
printf stimmen. Wenn Du 32 oder 64-bittige Werte ausdruckst unbedingt
die man-page von printf konsultieren. Da müsste noch eine Option an das
"d" angehängt werden. Bei "int" ist das nicht notwendig. Ich glaube ja
Du schreibst keine oder nicht die richtigen WErte ins SHM, weil Du
"write" benutzt. "memcpy" ist glaube ich "oldstyle" und ich bin nicht
sicher ob das durch "write" ersetzt wird, weil "write" eigentliche eine
Funktion im Zusammenhang mit Files ist. Daher nochmal manpage von
"write" lesen. Wenn Du nichts ins SHM schreibst bekommst du evtl. immer
Nullen ausgelesen, weil der Speicher beim anlegn genullt wurde.
und da ich mit Files arbeite, ist doch write dann die richtige wahl
oder?
die syntax von read/write sieht wie folgt aus:
int read(int fh, const void *puffer, site_t bytezahl);
int write(int fh, const void *puffer, size_t bytezahl);
Demnach ist doch meine Verwendung von read/write richtig? oder sehe ich
den Fehler einfach nicht????
zuerst lesen und in puffer(rbuffer34[x]) ablegen.
hDevice = open("/dev/ics554-1", O_RDWR);
ULONGLONG *rbuffer34[10];
int *shPtr2I, WriteBytes;
shID2I = shmget(IPC_PRIVATE, MAXMYMEM, IPC_CREAT|0666);
shPtr2I = shmat(shID2I, 0, 0);
if (0 > read (hDevice, rbuffer34[x], BytesToRead)) {
perror("read34[0]");
}
Dann ins Shared Memory schreiben:
WriteBytes = write(*shPtr2I, rbuffer34[x], BytesToRead);
printf("WriteBytes = d%, *shPtr2I = %d \n\r",WriteBytes,*shPtr2I );
keine Ahnung wie ich jetzt überprüfen soll was in rbuffer[x] jetzt
steht??
> WriteBytes = write(*shPtr2I, rbuffer34[x], BytesToRead);
Ist "shPtr2I" ein Dateihandle?
Was gibt shmat zurück?
Lies Dir nochmal ganz genau die Dokumentation von shmat durch.
Und überleg mal, warum das ganze shared memory und nicht shared file
heißt.
Rufus Τ. Firefly schrieb:> Ist "shPtr2I" ein Dateihandle?
Nein es ist kein handle sondern ein (int *shPtr2I;).
Habs jetzt auf
FILE *shPtr2I;
WriteBytes = write(shPtr2I, rbuffer34[x], BytesToRead);
printf("WriteBytes = d%, *shPtr2I = %d \n\r",WriteBytes,*shPtr2I );
geändert.
Rufus Τ. Firefly schrieb:> Was gibt shmat zurück?
shmat gibt die Adresse zurück und mit shPtr2I = shmat(shID2I, 0, 0);
zeigen wir darauf.
Rufus Τ. Firefly schrieb:> Und überleg mal, warum das ganze shared memory und nicht shared file> heißt.
Ich wollte mehrere Binäre Blöcke dort ablegen und mit einem anderen
prozess verabeiten bzw. formatiert auf die Festplatte schreiben. Da auf
die Festplatte schreiben länger dauert als ins RAM/Shared memory, wollte
ich die Blöcke in einem Ringpuffer im SHM anlegen. Bis jetzt habe ich
gedacht, dass gerade für sowas ein shared memory gut ist??? kann man
etwa nicht blockweise ins shared memory schreiben?
Hans schrieb:> Ich wollte mehrere Binäre Blöcke dort ablegen und mit einem anderen> prozess verabeiten bzw. formatiert auf die Festplatte schreiben. Da auf> die Festplatte schreiben länger dauert als ins RAM/Shared memory, wollte> ich die Blöcke in einem Ringpuffer im SHM anlegen.
sotwas würde ich mit threads machen, es gibt ein schreibethread und eine
liste von Zeiger incl Größe wo steht was alles rauszuschreiben ist. Wenn
es rausgeschrieben ist, wird er speicher freigeben.
Hans schrieb:> das ist auch c aber ich benutze kein windows sondern Linux bzw. Suse 11.
Ich habe da ein kleines Verständnisproblem. Wieso bezeichnet man
heutzutage "C unter Linux" als "C#"? Habe ich da irgendetwas verpasst?
Oder geht es hier in Wirklichkeit um eine Anwendung unter Mono?
Peter II schrieb:> sotwas würde ich mit threads machen, es gibt ein schreibethread und eine> liste von Zeiger incl Größe wo steht was alles rauszuschreiben ist.
ob thread oder eigener prozess, die Daten müssen doch irgendwo gepuffert
werden?? z.B. in einem Shared Memory, denn die Zeiger müssen doch
irgendwohin zeigen? Oder vertue ich mich da??
Hans schrieb:> ob thread oder eigener prozess, die Daten müssen doch irgendwo gepuffert> werden??
bei thread braucht man aber kein shared memory sonder kann den ganz
normale speicher nutzen sie wie man es ständig bei C macht.
Rufus bist du noch da??
Rufus Τ. Firefly schrieb:
> Ist "shPtr2I" ein Dateihandle?
Nein es ist kein handle sondern ein (int *shPtr2I;).
Habs jetzt auf
FILE *shPtr2I;
WriteBytes = write(shPtr2I, rbuffer34[x], BytesToRead);
printf("WriteBytes = d%, *shPtr2I = %d \n\r",WriteBytes,*shPtr2I );
geändert.
Rufus Τ. Firefly schrieb:
> Was gibt shmat zurück?
shmat gibt die Adresse zurück und mit shPtr2I = shmat(shID2I, 0, 0);
zeigen wir darauf.
Rufus Τ. Firefly schrieb:
> Und überleg mal, warum das ganze shared memory und nicht shared file> heißt.
Ich wollte mehrere Binäre Blöcke dort ablegen und mit einem anderen
prozess verabeiten bzw. formatiert auf die Festplatte schreiben. Da auf
die Festplatte schreiben länger dauert als ins RAM/Shared memory, wollte
ich die Blöcke in einem Ringpuffer im SHM anlegen. Bis jetzt habe ich
gedacht, dass gerade für sowas ein shared memory gut ist??? kann man
etwa nicht blockweise ins shared memory schreiben?
warum willst du es immer noch mit shared memory machen? das ist doch der
falsche ansatz für dein Problem!
Du handelst dir damit mehr Probeme ein als du löst. Du muss dafür eine
Komplette IPC machen damit sich die beiden Prozesse nicht in die quere
kommen. Wenn du 2 Prozesse hast muss du dich auch um das Starten und
beenden kömmen ( wer startet zu erst und was soll passieren wenn sich
einer unerwartet beendet?).
Wie übergibt du die Parameter für den den beiden Prozessen z.b. in
welche Datei soll geschrieben werden usw.
Mach es mit threads das sollte für den zweck das richtige sein.
Also "write" ist immer noch falsch. Du hast in die falsche Ríchtung
geändert. Der Pointer darf kein FH sein.
- Entweder kopierst Du beim Lesen aus dem Gerät die Daten direkt ins SHM
(mittels "read") oder kopier sie aus dem Zwischenspeicher mittels
"memcpy" nachdem sie mittels "read" gelesen wurden.
- Der Pointer auf das SHM darf natürlich kein Dateihandle sein. SHM
haben immer einen Pointer auf die Anfangsadresse des Speicherbereichs.
Keinen FH.
- Wenn Du "write" benutzt beteutet das, das Daten auf ein "Gerät" mit
Filehandle geschrieben werden. SHM hat kein FH (jedenfalls
normalerweise)
AgentP
Peter II schrieb:> warum willst du es immer noch mit shared memory machen?
Ich habe mir es so gedacht, dass ich die Id des angelegten Shm in eine
Datei schreibe, auf diese Datei und somit auf das shm, können dann zich
Prozesse zugreifen und die binären Daten dann verarbeiten.
Die IPC habe ich bereits hin gekriegt. Es ist so, dass ich in den SHM
momentan formatiert befülle(shPtr2I[laufshm] =
(int)(buffer[jdx*16+j*8+1] & 0xFFFFFF00);) und mit nem anderen Prozess
die Daten abhole alles kein Problem, weil die formatierte
Beschreibung etwas rechenintensiv ist,wollte ich die Daten binär ins shm
schreiben und später mit nem zweiten Prozess verarbeiten(ja das stimmt
das könnte ich auch mit nem thread tun, aber wenn es schon so läuft).
Werd auf jedenfall mich mal mit den threads auseinandersetzen. Hast du
einpar tipps für mich? wo soll ich anfangen? Danke trotzdem.
Olaf H. schrieb:> - Entweder kopierst Du beim Lesen aus dem Gerät die Daten direkt ins SHM> (mittels "read") oder kopier sie aus dem Zwischenspeicher mittels> "memcpy" nachdem sie mittels "read" gelesen wurden.
Werd es sofort mal testen, beides!! Danke
Moin,
nur so als Anregung. In meinem aktuellen Projekt verwende ich
Messagequeues. Ein Prozess sendet die Daten msgsnd() und der andere
empfängt sie per msgrcv().
Ich muss gestehen mit memcpy() klappt es wunderbar.
Es hat sich jedoch ein neues Problem aufgetan.
Wenn ich die Daten durch ein sherad Memory hin und her schiebe, müsste
es nicht so sein, dass die Startadresse des SHM bei beiden Prozessen die
selbe sein müsste?
Ich printe die Startadresse, in beiden Prozessen, mit(2 SHM`s):
printf("shPtr1I = %u,shPtr2I = %u \n\r \n\r" shPtr1I, shPtr2I);
und die Unterscheiden sich.
Kann das sein das ich beim attach eine Startadresse angeben muss, ich
attache so?
Prozess main (1) // Erzeuger
shID1I = shmget(IPC_PRIVATE, MAXMYMEM, IPC_CREAT|0666);
shPtr1I = shmat(shID1I, 0, 0);
SHMStartPtr12 = shmat(shID1I, 0, 0);
shPtrCtrlFile[1] = shPtr1I;
shID2I = shmget(IPC_PRIVATE, MAXMYMEM, IPC_CREAT|0666);
shPtr2I = shmat(shID2I, 0, 0);
SHMStartPtr34 = shmat(shID2I, 0, 0);
shPtrCtrlFile[2] = shPtr2I;
Prozess 2:
shPtr1I = shmat(SHMidBuffer[0], 0, SHM_RDONLY);
ShPtrStart1 = shmat(SHMidBuffer[0], 0, SHM_RDONLY);
shPtr2I = shmat(SHMidBuffer[2], 0, SHM_RDONLY);
ShPtrStart2 = shmat(SHMidBuffer[2], 0, SHM_RDONLY);
die SHMid stimmt überein. Ich vermute, dass es die Richtigen SHM`s sind
nur nicht die Startadresse. Die Startadresse benötige ich da der SHM wie
ein Ringpuffer aufgebaut ist.
hat einer Tipps wegen der Startadresse??
danke
Hans schrieb:> Es hat sich jedoch ein neues Problem aufgetan.> Wenn ich die Daten durch ein sherad Memory hin und her schiebe, müsste> es nicht so sein, dass die Startadresse des SHM bei beiden Prozessen die> selbe sein müsste?
Nö, wieso sollte das so sein? Da ist eine MMU involviert, und damit kann
der Speicher, der natürlich nur eine physikalische Adresse hat, an
beliebige Adressen im Adressraum der Prozesse gemappt werden.
Hans schrieb:> Die Startadresse benötige ich da der SHM wie> ein Ringpuffer aufgebaut ist.
Keine Pointer im Shared Memory verwenden, sondern Offsets relativ zu
dessen Startadresse. Und schon stört die unterschiedliche Startadresse
nicht mehr.
Hans schrieb:> die SHMid stimmt überein. Ich vermute, dass es die Richtigen SHM`s sind> nur nicht die Startadresse. Die Startadresse benötige ich da der SHM wie> ein Ringpuffer aufgebaut ist.
das sind genau die Probleme die man bei Thread nicht hat.
Rufus Τ. Firefly schrieb:> Keine Pointer im Shared Memory verwenden, sondern Offsets relativ zu> dessen Startadresse
Wenn man den shm-Bereich:
shPtr1I = shmat(SHMidBuffer[0], 0, SHM_RDONLY);
gibt doch shmat() eine Adresse zurück. Allerdings weiss ich nicht wo
diese im shm liegt. oder ist das die Startadresse? Wenn man jetzt wüsste
wo diese liegt, könnte man ja einen offset erzeugen, relativ zur
startadresse.
Wie findet man das herraus?? wenn beide Prozesse eine andere
Adressierung verwenden bzw. wie auf den shm zugreifen wenn nicht über
int *shPtr1I;??
danke
Die von shmat zurückgegebene Adresse ist die Startadresse im
Adressraum des aufrufenden Prozesses, an der der "shared memory"-Block
eingeblendet wird.
Angenommen, Dein "shared memory"-Block ist 8 kiB groß, und shmat gibt
die Adresse 0x12340000 zurück, dann belegt der Block die Adressen von
0x12340000 bis 0x12341fff
Wenn in Deinem anderen Prozess der Block beispielsweise an die Adresse
0x76540000 gemappt wird, belegt er dort folglich die Adressen von
0x76540000 bis 0x76541fff
Wo liegt jetzt Dein Verständnisproblem?
Rufus Τ. Firefly schrieb:> Wo liegt jetzt Dein Verständnisproblem?
Danke ich habe kein verständnisproblem. Hast mir alles beantwortet ich
war mir nur unsicher ob ich würklich auf mit shmat() auf die
startadresse gucke oder nicht.
Mich hat durcheinander gebracht:
void *shmat(int shmid, const void *shmaddr, int shmflg);
Zitat: Der Parameter shmid ist die von shmget() ermittelte ID. An den
Parameter shmaddr kann eine 0 übergegeben werden, dann sucht sich das
System eine passende Stelle.
passende Stelle ????
Rufus Τ. Firefly schrieb:> Angenommen, Dein "shared memory"-Block ist 8 kiB groß, und shmat gibt> die Adresse 0x12340000 zurück, dann belegt der Block die Adressen von>> 0x12340000 bis 0x12341fff
Bei diesem Beispiel beinhaltet eine Adresse 1Byte. Ist das immer so??
in meinem Bsp. ist shPtr1I ein int *(int *shPtr1I) ich lese den shm mit
fwrite(shPtr1I, 1, BytesToRead, fdBin12); blöcke aus und inkrementiere
die Adresse dann mit shPtr1I += BytesToRead/sizeof(*shPtr1I);
demnach würde sich doch der speicherbereich um
BytesToRead/sizeof(*shPtr1I) verändern. Ist korreckt so??
sorry für die, für manche leichten fragen aber ich bin noch nicht so
lange dabei und ich würde gerne alles genau wissen.
Hans schrieb:> Bei diesem Beispiel beinhaltet eine Adresse 1Byte. Ist das immer so??
Auf den üblichen Geräten, mit denen man so hantiert, ja.
Hans schrieb:> ich lese den shm mit> fwrite(shPtr1I, 1, BytesToRead, fdBin12); blöcke aus
Nein. Damit liest Du den shared memoryNICHT aus. Das ist an der
Stelle vollkommener Unfug. fwrite hat da GARNICHTS verloren.
Rufus Τ. Firefly schrieb:> Auf den üblichen Geräten, mit denen man so hantiert, ja.
Ich habe ein 64bit system (Suse). Die adressen sind dann doppelt so
gross wie bei 32bit system, ist das der Unterschied??
Rufus Τ. Firefly schrieb:> Nein. Damit liest Du den shared memory NICHT aus. Das ist an der> Stelle vollkommener Unfug. fwrite hat da GARNICHTS verloren.
Sorry hab mich Falsch ausgedrück. Mit fwrite(shPtr1I, 1, BytesToRead,
fdBin12); schreibe(kopiere) ich was im shm steht, in das File wo ich mit
dem Filedescriptor (FILE fdBin12) hinzeige. RICHTIG?
Hans schrieb:> Ich habe ein 64bit system (Suse). Die adressen sind dann doppelt so> gross wie bei 32bit system, ist das der Unterschied??
Auch diese Adressen adressieren Bytes.