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
Peter II schrieb: > da glaube ich nicht. Es sieht mir mehr wie C aus. das ist auch c aber ich benutze kein windows sondern Linux bzw. Suse 11. ;-)
> 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?
1 | printf("WriteBytes = d%, *shPtr2I = %d \n\r",WriteBytes,*shPtr2I ); |
Du druckst den Wert des ersten Bytes im SHM aus. Ist das was Du willst oder willst Du den WErt des Pointers ausgeben? Agentp
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 memory NICHT 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?
Example two processes comunicating via shared memory: shm_server.c, shm_client.c http://www.cs.cf.ac.uk/Dave/C/node27.html HTH! :)
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.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.