PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [C] "Block"weise von /dev/<gerät> lesen


Gast
2006-04-02, 15:04:22
Hi,

ich möchte mit einem C-Programm etwas einlesen. Wenn ich mittels "cat /dev/<gerät> | hexdump -x" auf der Konsole die Ausgabe erzeuge, sieht es so aus:

0000000 8000 0000 8010 0000 8010 0000 0006 0000
0000010 0006 0000 2800 0000 2800 0000 8800 0000
0000020 8800 0000 8810 0000 8810 0000 0803 0000
0000030 0803 0000 1800 0000 1800 0000 2000 0000


Ein XXXX-Block (zb 8000) ist jeweils 'interessant'.

Wie kann ich in einem C-Programm nun so einen Block in eine Variable bekommen?

Gast
2006-04-02, 15:19:05
Unices sind Unices weil sich alles wie eine Datei verhält ("unified").unsigned char buffer[256]; //oder short, oder int ... oder ein std::vector ...

FILE* dev_file=fopen("/dev/null","rb");
size_t bytes_gelesen=fread(buffer,1,256,dev_file);

zeckensack
2006-04-02, 15:40:09
Das war ich :|

Wollte noch ergänzen und deine Frage richtig beantworten.int variable; //alle C-Typen würden gehen

fread(&variable,1,sizeof(variable),dev_file);Und wenn du damit fertig bist natürlich fclose(dev_file) nicht vergessen.

Gast
2006-04-02, 15:45:06
int fh, nread;
char stat[256];

fh = open("/dev/gerät", O_RDWR)) < 0 )
nread=read (fh, &stat, 2); // 2, weil ich ja 2 byte (zB 8000 0000) lesen will

printf("%d\n", nread);
printf("%s\n", stat);

Wenn ich das so mache (es soll zwingend read benutzt werden), dann wird zwar die 2 ( =nread) ausgegeben, aber für den Inhalt von stat gibts nur eine leere Zeile. -->?
Per Hexdump werden aber weiterhin Werte 'gedumpt'.
Hilfe. :/

zeckensack
2006-04-02, 15:56:33
int fh, nread;
char stat[256];

fh = open("/dev/gerät", O_RDWR)) < 0 )
nread=read (fh, &stat, 2); // 2, weil ich ja 2 byte (zB 8000 0000) lesen will

printf("%d\n", nread);
printf("%s\n", stat);

Wenn ich das so mache (es soll zwingend read benutzt werden), dann wird zwar die 2 ( =nread) ausgegeben, aber für den Inhalt von stat gibts nur eine leere Zeile. -->?
Per Hexdump werden aber weiterhin Werte 'gedumpt'.
Hilfe. :/ 0x8000 0000 sind vier Byte.
0x80 ist kein besonders erfreuliches ASCII-Zeichen. Versuche://in deinen Code einbauen statt
//der Zeile printf("%s\n",stat);

int i;
for (i=0;i<4;++i) printf("0x%02X ",stat[ i]);
printf("\n");
Vorsicht mit der Anzeige irgendwelcher eingelesener Puffer-Inhalte als C-String. Wenn du Pech hast ist kein Element im Puffer 0, dh der String ist nicht terminiert. Du solltest, falls du es so durchziehen möchtest wie oben, dem Puffer etwas mehr Größe spendieren als du maximal zu lesen planst, und immer nach jedem Lesevorgang terminieren.char stat[256+2];
nread=read (fh, &stat, 4);
stat[nread]=0; //terminieren um String-Verarbeitung zu ermöglichen

Gast
2006-04-02, 16:27:17
Danke!
Aber so ganz passt das dennoch noch nicht:

Das ist die Ausgabe mittels deines Codes oben (ich habe das 0x im printf weggelassen):
00 28 00 00
00 FFFFFF88 00 00
00 FFFFFF88 00 00
10 FFFFFF88 00 00
03 08 00 00


Die Ausgabe passt aber nicht zu der obigen Referenzausgabe (zb 8000 0000).

03 08 00 00 gibt es bspw nicht, aber 0803000 sehr wohl (siehe ganz oben).
Unkar ist mir auch was FFFFFF88 bedeuten soll, wenn ich immer nur Blöcke von 4 positiven 'Nummern' habe. :/

zeckensack
2006-04-02, 17:04:37
Das sollte eigentlich gehen :|
Evtl mag es das Gerät nicht, wenn man nur kleine Bröckchen liest, oder wenn man es mit Read/Write-Zugriff öffnet. Das sieht so aus als würdest du ein paar Bytes einzeln lesen, dann wieder ints, und immer schön im Wechsel.

Wenn du einen großen Block am Stück (256 Bytes würden sich geradezu aufdrängen) liest, sollte das Ergebnis aussehen wie cat, denn cat macht AFAIK nichts anderes -- aber es öffnet das Gerät eben mit reinem Lesezugriff.

Was passiert wenn du das mal versuchst?

Und was ist das eigentlich für ein Gerät? Evtl könnte man erklären warum es nicht klappt, wenn man das wüsste ;)

Gast
2006-04-02, 17:18:37
Hmm, ich habe es nun so gemacht:

int stat;
nread=read (fh, &stat, 1);
printf("%x\n", stat);

Damit bekomme ich die gewünschten Ausgaben (zB 6000, 8700, etc).
(Wieso habe ich das nicht gleich so gemacht? :(( )

Wie komme ich nun an einzelne Werte?
8700 ist ja nur eine andere Schreibweise für 1000 0111 0000 0000, oder? Wie kann ich das Ganze nun so aufdröseln, dass ich die 8 einzeln weiterverarbeiten kann (vergleiche, etc)? Die anderen Stellen für sich alleine natürlich auch?
Geht das mit Bitmanipulation, Shiften usw.? (Hoffentlich gibts da einen leichteren Weg -- bei dem Geshifte gibts nämlich bei mir im Hirn immer einen Segmentation Fault... *gg*).

Xmas
2006-04-02, 18:13:29
(stat >> (x * 4)) & 0xF

wobei x die Stelle im Hex-Wert angibt, von 7 (links) bis 0 (rechts).

Gast
2006-04-04, 14:55:24
Danke.

Ich bin aber dennoch zum Schluss gekommen, dass ich lieber bei Java & C++ bleiben sollte, weil mein Wissen um C einfach viel zu gering ist (Datentypen und deren Umwandlung ineinander, usw). :(

Ich versuche nun beispielsweise einen Vergleich eines Übergabeparameters mit einem festen Wert zu realisieren, was ich nicht hinbekomme. :(
C verwirrt mich da total, weil ein char ein int ist und ein char-Feld hat eine abschliessende 0 oder auch irgendwie nicht, wenn man text in "Gänsefüsschen" schreibt. - *verzweifel*

main (int argc, char** argv) {
if (argv[1] < 0x23) {} // dann irgendwas

Das Programm ruft man mit 'test 0xHH' auf (wobei HH ein Hexwert zwischen 20 und 40 sein darf).
Nur komme ich immer in die if-Verzweigung, egal, was ich für HH übergebe (selbst irgendein Quark als Parameter führt in die If-Verzweigung, zB 'test 1234').

Coda
2006-04-04, 15:19:07
argv[1] ist die Speicheraddresse des ersten Parameterstring, was willst du da auch vergleichen?

Was du evtl. willst ist atoi(argv[1]), aber selbst dann funktioniert das nur mit dezimalen Parametern und nicht mit hexadezimalen. Außerdem solltest du prüfen ob argc überhaupt größer eins ist, sonst ist das sowieso ein Speicherzugriffsfehler.