Linux C Read von ttys0

Gast #3185520
Lesenswert?

Moin,

ich habe ein Gerät das 30Sec lang ASCII Zeichen sendet und diese will 
ich empfangen und bearbeiten.

Als System ist ein Debian vorhanden mit gcc.

Ich habe schon versucht so was zu lesen:

res = read(fd,(char *)buf,sizeof(buf));

aber irgendwie kommen da nur ca.9 Zeilen an....Ist das die große des 
Hardware Buffers? Wie zeichnet mann denn alles auf in C?


Ich wäre für einen Tip dankbar

Lars
Gast #3185537
Lesenswert?

> Ich habe schon versucht so was zu lesen:
>
> res = read(fd,(char *)buf,sizeof(buf));

Na nur damit wirst Du nicht weit kommen :-) Zeig mal den ganzen 
Quellcode. Falls Du das nicht möchtest lies wenigstens die Manpage.
Gast #3185541
Lesenswert?

Lars schrieb:
> Ich habe schon versucht so was zu lesen:
>
> res = read(fd,(char *)buf,sizeof(buf));
>
> aber irgendwie kommen da nur ca.9 Zeilen an....Ist das die große des
> Hardware Buffers?

Wie groß ist denn dein Buffer?

> Wie zeichnet mann denn alles auf in C?

read() in einer Schleife aufrufen.
Gast #3185547
Lesenswert?

Moin,


ich habe den Buffer schon auf > 10000 gestellt aber es kommen immer 
gleich wenig Zeichen.

Ich habe noch nicht viel Code...ich geben den Buffer danch einfach per 
Prinf aus.

Wenn ich eine while Schleife wie bekomme ich denn alle Daten in eine 
Variable?

Ich will ja alle gesammelten Daten zusammen auswerten.



Lars
Gast #3185560
Lesenswert?

Lars schrieb:
> ich habe den Buffer schon auf > 10000 gestellt aber es kommen immer
> gleich wenig Zeichen.

Dann ist wohl der interne Puffer voll.

> Wenn ich eine while Schleife wie bekomme ich denn alle Daten in eine
> Variable?

Du merkst dir einfach, wieviele Zeichen schon gelesen wurden und 
übergibst read() halt als Startposition die entsprechende Stelle in 
deinem Puffer statt dessen Anfang.
Du mußt auch noch definieren, was "alle Daten" sind. Mit anderen Worten: 
Du brauchst eine Möglichkeit, das Ende zu erkennen. Hast du dir dazu 
schon Gedanken gemacht?
Gast #3185563
Lesenswert?

> ich habe den Buffer schon auf > 10000 gestellt aber es kommen immer
> gleich wenig Zeichen.

Sachichdoch - Manpage lesen wäre zweckmäßig.

> Wenn ich eine while Schleife wie bekomme ich denn alle Daten in eine
> Variable?

Mitzählen. Das war jetzt einfach :-)
Gast #3185589
Lesenswert?

Buffersize ist 1
1
  char buf[BUFFSIZE];
2
  int res=0;
3
  int i=0;
4
  char spei[10000];    
5

6

7
  do{
8
  
9
    res = read(fd,(char *)buf,sizeof(buf));
10
    
11
    strncpy(spei, buf, i);  
12
  
13
    i++;
14
    
15
  }while(i < 2);
16
  
17

18
  printf("read:%s\n",spei);
19

20

21
  return;

Warum kann ich den dem While kein Strcopy machen? Da hängt das Programm
#3185596
Lesenswert?

Lars schrieb:

> Warum kann ich den dem While kein Strcopy machen? Da hängt das Programm

Ja, hast du denn überhaupt Strings?


Ich seh schon.
WIr sind wieder mal an dem Punkt an dem man sagen muss: Es hilft alles 
nichts. Wer Programm in der realen Welt schreiben will muss erst mal die 
Grundlagen lernen! Das geht nun mal nicht so, wie sich manche das 
vorstellen: vormittags den Entschluss gefasst Programmierer zu werden, 
und nachmittags die Killerapplikation geschrieben, die einen reich 
macht.
#3185603
Lesenswert?

Karl Heinz Buchegger schrieb:
> Lars schrieb:
>
>> Warum kann ich den dem While kein Strcopy machen? Da hängt das Programm
>
> Ja, hast du denn überhaupt Strings?

Und ehe du dich in einen Wirbel reinredest.
Nein, du hast erst mal keine Strings.
read befüllt dir den buffer mit den Zeichen die gerade da sind bzw. in 
den buffer passen. Nicht mehr und nicht weniger. Von Strings kann zu 
diesem Zeitpunkt noch überhaupt keine Rede sein.
#3186536
Lesenswert?

Lars schrieb:
> Ist nicht ein Char ein String?

Nein das ist ein Array of Bytes, In C sind Strins mit \0 terminert. Dann 
sind es Strings und können mit den Funktionen aus der string.h behandelt 
werden. Sonst ist das nur irgendwelcher Datenkram...

Gegenvorschlag:

char *spei; // Wir machen einen Pointer daraus
spei = (char)malloc(10000) // Speicher reservieren;
char *mark;

mark = spei; // alten Pointer merken

do{

    res = read(fd,(char *)buf,sizeof(buf));
if (spei < mark + 10000) { // Sicher stellen, dass nocht über den 
allocierten Speicher geschrieben wird
    memcpy(spei, buf, res); // anzahl der gelesenen Zeichen umschaufeln
    spei += rc // pointer hochzählen
  }
  }while( res > 0);

// hoffen, dass es sich um strings handelt, sonst als letztes Zeichen \0 
anfügen


  printf("read:%s\n",mark); // nicht wundern, wir nehmen hier den Anfang 
des spei Pointers, da wir den ja oben laufend verschoben haben


// Speicher wieder frei geben
free(spei);
free(mark);


So, das ist nicht getestet, sollte aber gehen..

Grpßle aus dem Ländle von Jörg
Gast #3186561
Lesenswert?

Jörg Bernau schrieb:
> So, das ist nicht getestet, sollte aber gehen..

Wenn die kleinen Elflein kommen und die Speicherlecks entfernen. Ja dann 
funzt es xD

-->siehe malloc
->res = read(fd,(char *)buf,sizeof(buf)); ^^
wohle eher res = read(fd, buf, sizeof(buf) / sizeof(buf[0]);
-->memcpy(spei, buf, res); // anzahl der gelesenen Zeichen umschaufeln
    spei += rc // pointer hochzählen
SoSo ^^
--> Speicher wieder frei geben
char *spei; // Wir machen einen Pointer daraus
spei = (char)malloc(10000) // Speicher reservieren ^^ Witzig
char *mark;
...
mark = spei; // alten Pointer merken
free(spei);
free(mark);
:) jaja speicher von einem nicht reservierten Speicherbereich freigeben 
xD

Sry, musste sein.
:)
Gast #3187897
Lesenswert?

Ok danke für die Tips.

Aber ein Problem habe ich immer noch.....

Wenn ich z.b das hier:
1
  char string[] = "Die schoenen Dinge im Leben sind umsonst.";
2
  int laenge = strlen(string);
3
  printf("Laenge: %d Zeichen\n", laenge);

In meinen Code einfüge bleibt da das Programm stehn :-(

Ich habe auch das diese Includes drin:
/* lesen.c */
#include <termios.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <stdlib.h>
#3188083
Lesenswert?

In dem Codeschnipsel ist kein Fehler, also muß er irgendwo anders 
liegen. Sinnvoll ist es deshalb, ein minimales, aber vollständiges 
Programm zu posten, das den Fehler noch enthält.
Folgendes Programm funktioniert bei mir jedenfalls einwandfrei:
1
/* lesen.c */
2
#include <termios.h>
3
#include <fcntl.h>
4
#include <sys/ioctl.h>
5
#include <stdio.h>
6
#include <sys/types.h>
7
#include <sys/stat.h>
8
#include <string.h>
9
#include <stdlib.h>
10

11
int main(void)
12
{
13
    char string[] = "Die schoenen Dinge im Leben sind umsonst.";
14
    int laenge = strlen(string);
15
    printf("Laenge: %d Zeichen\n", laenge);
16
    return 0;
17
}

Es gibt aus:
1
Laenge: 41 Zeichen

Mehmet Kendi schrieb:
> Dem Compiler ist die Laenge des Strings bereits bekannt, weshalb ich
> anstelle von strlen() sizeof() benutzen würde.

Der Compiler (zumindest gcc) ist so intelligent, in so einem Fall auch 
bei strlen() die Länge schon zur Compilezeit zu ermitteln.
Gast #3188401
Lesenswert?

Lass es Lars, hier wirst Du nicht wirklich eine "vernünftige" Antwort 
erhalten.
BTW: Nimm Dir mal das Buch von K&R und lerne erst einmal, denn Dir 
fehlen noch viele Grundlagen. Erst wenn Dir klar ist, was Du eigentlich 
machst (Pointer und so Sachen), dann wirst Du auch ein einges, positives 
Ergebnis bekommen.

Ein guter Compiler zum üben unter Windoof ist:
http://www.cs.virginia.edu/~lcc-win32/

Der ist sehr gut zu bedienen und die gesamte Doku ist dabei.
Und er ist für Lau!
#3188617
Lesenswert?

Lars schrieb:
> Wenn ich string[100] schreibe gehts.

Und wenn du den exakten Code von mir nimmst, geht es nicht? In dem 
Fall stimmt irgendwas mit deinem Compiler nicht, oder er ist extrem 
veraltet. Oder hast du's nur in deinem Programm probiert? Dann gilt 
immer noch:

Rolf Magnus schrieb:
> Sinnvoll ist es deshalb, ein minimales, aber vollständiges
> Programm zu posten, das den Fehler noch enthält.

> Wie kompilierst du mit gcc?

gcc datei.c -o datei
Gast #3190811
Lesenswert?

Die habe ich gar nicht konfiguriert.

So sieht es bei mir aus:

  struct termios port_settings;      // structure to store the port 
settings in

  cfsetispeed(&port_settings, B300);    // set baud rates
  cfsetospeed(&port_settings, B300);

  port_settings.c_cflag |= PARENB;    // setze 7E1
  port_settings.c_cflag &= ~PARODD;
  port_settings.c_cflag &= ~CSTOPB;
  port_settings.c_cflag &= ~CSIZE;
  port_settings.c_cflag |= CS7;
  port_settings.c_lflag = ICANON;
  tcsetattr(fd, TCSANOW, &port_settings);    // apply the settings to 
the port
  return(fd);
#3190833
Lesenswert?

Lars schrieb:
> res = read(fd,(char *)buf,sizeof(buf));
>
> aber irgendwie kommen da nur ca.9 Zeilen an....Ist das die große des
> Hardware Buffers? Wie zeichnet mann denn alles auf in C?

Der Linux-Kernel macht bei einem read()-Syscall keine Garantien, dass 
der Buffer gefüllt wird, es wird das rausgereicht, was gerade da ist. 
Nur wenn nix da ist wird blockiert (ok, man kann die Datei auch 
nonblocking öffnen, dann kommt "nix" zurück).

Wenn man darauf angewiesen ist, dann macht man das mit den 
"highlevel"-Funktionen der libc (fread etc.).

Ich habe mal ein winz-Programm angehängt, welches auf eine serielle 
Schnittstelle zugreift und die empfangenen Daten auf stdout als Hexdump 
ausgibt. Als Bonus wird da auch gezeigt, wie man mit poll() auf das 
Vorhandensein von Daten warten kann - hier nutze ich das dafür, dass 
nach einer kleinen Pause ein Zeilenumbruch ausgegeben wird, also 
typischerweise nach einem Telegramm.

Ich hoffe das hilft weiter.

Viele Grüße,
         Simon
Angehängte Dateien:
(Firma: von Dänemark) #3191058
Lesenswert?

@Simon
Nice trick with the polling.

@Lars
I have used this code on an Arduino , and it seems to be ok. For reading 
serial responses from an Arduino.
Beitrag "PortableSerialLib - Portable Serial Port Library"

Maybe it should be extended with the poll Simon shows.

I haven't tried it on windows , but used it in hope of a "dual platform" 
support.

regards
Karsten - Denmark
Gast #3191082
Lesenswert?

1
...
2
if (pfd[0].revents & POLLIN) {
3
    ret = read (serial_fd, buffer, 255);
4
    if (ret < 0 && errno != EAGAIN) {
5
        ...
6
...

@Simon

Muss man ret hier wirklich auf /EAGAIN/prüfen? - Mit der vorigen 
Abfrage sollte doch sichergestellt sein, dass Daten vorhanden sind, oder 
nicht (immer)?
#3191223
Lesenswert?

mar IO schrieb:
> Muss man ret hier wirklich auf /EAGAIN/prüfen? - Mit der vorigen
> Abfrage sollte doch sichergestellt sein, dass Daten vorhanden sind, oder
> nicht (immer)?

Ja, im Prinzip hast Du recht, es sollten Daten verfügbar sein.

Hier ist das ein bischen defensiv programmiert und schützt einen vor 
irgendwelchen komischen Situationen mit z.B. kaputten Treibern. Ich weiß 
jetzt gerade nicht, ob ich diese Situation schonmal konkret hatte, aber 
ich weiß: Wenn read() EAGAIN zurückgibt, dann will ich es nochmal 
probieren, insofern teste ich lieber drauf.

Viele Grüße,
         Simon
#3191345
Lesenswert?

mar IO schrieb:
> Muss man ret hier wirklich auf /EAGAIN/prüfen? - Mit der vorigen
> Abfrage sollte doch sichergestellt sein, dass Daten vorhanden sind, oder
> nicht (immer)?

In der Man-Page steht:
1
BUGS  See the discussion of spurious readiness notifications under the
2
      BUGS  section of select(2).

Und bei select steht dann:
1
BUGS:
2
       Under Linux, select() may report a socket file  descriptor
3
       as  "ready  for  reading", while nevertheless a subsequent
4
       read blocks.  This could for example happen when data  has
5
       arrived  but  upon  examination  has wrong checksum and is
6
       discarded.  There may be other circumstances  in  which  a
7
       file  descriptor is spuriously reported as ready.  Thus it
8
       may be safer to use O_NONBLOCK on sockets that should  not
9
       block.

O_NONBLOCK hat er ja wohl schon, aber dann muß man auch auf EAGAIN 
prüfen, um das von einem echten Fehler unterscheiden zu können.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren