Forum: PC-Programmierung Ubuntu - serielle schnittstelle / rs232 schliessen


von phreak (Gast)


Lesenswert?

Hallo, weis zufällig jemand wie ich bei Ubuntu die Serielle 
schnittstelle wieder schliessen kann??
Habe ein Programm dass manchmal abschmiert und die schnittstelle ist 
dann noch offen..

Danke schon mal..

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Fange das Signal SIGSEGV ab, welches an das Programm gesendet wird, wenn 
es durch ungültige Pointer abstürzt, und schließe das Datei-Handle:
1
#include <signal.h>
2
3
// Datei-Handle auf Schnittstelle.
4
int fd_rs232 = -1;
5
6
void on_segv(int sig);
7
8
int main () {
9
 // RS232 -Schnittstelle öffnen
10
 fd_rs232 = open ....
11
 
12
 // Signal SEGFAULT (=Absturz) abfangen
13
 signal(SIGSEGV, on_segv);
14
 
15
 // Irgendwas tuen...
16
}
17
18
// Signal-Handler
19
void on_segv(int sig) {
20
 // Schnittstelle offen?
21
 if(fd_rs232 != -1)
22
   // Schließen
23
   close(fd_rs232);
24
}
Siehe
1
man 2 signal
PS: Die Schnittstelle ist nach einem Absturz nur kurze Zeit noch offen, 
danach schließt der Kernel sie automatisch.

von phreak (Gast)


Lesenswert?

hmm irgdnwie schiesst es mir den Port immer ab, wenn ich dann vom System 
darauf zugreifen will bekomme ich einen "Input/Output Error" und von 
alleine schliesst er sich auch nicht.. ??

von phreak (Gast)


Lesenswert?

irgendwas stimmt da nicht. der port wird nicht mal geschlossen wenn ich 
alle prozesse kille ( strg + alt + <---- )

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

phreak schrieb:
> irgendwas stimmt da nicht. der port wird nicht mal geschlossen wenn ich
> alle prozesse kille ( strg + alt + <---- )
Ähm, das killt nur den X-Server. Grafische Programme können darauf 
reagieren und sich beenden, müssen sie aber nicht und können fröhlich 
weiter laufen.
Versuch mal "lsof | grep /dev/ttyXX" um herauszufinden welche Prozesse 
noch auf die Schnittstelle zugreifen. Hast du mal meinen Code oben 
eingebaut, und die Schnittstelle wird trotzdem nicht geschlossen oder 
was?

von phreak (Gast)


Lesenswert?

habe es eingebaut, aber das programm hat wohl noch andere Porbleme.. :(
1
lsof | grep /dev/ttyUSB0
1
lsof: WARNING: can't stat() fuse.gvfs-fuse-daemon file system /home/user/.gvfs
2
      Output information may be incomplete.

versuche es jetz mal mit der libserial

btw: Danke für die Unterstützung :)

von Sven P. (Gast)


Lesenswert?

Was machsten da fürn Kram? :-)

Beim Beenden sollte eigentlich automatisch aufgeräumt werden. Oder was 
meinst du mit 'schließen'?

von phreak (Gast)


Lesenswert?

hehe ja sollte, aber das klappt noch nicht...
folgendes. Vielleicht hilft das hier ja noch weiter:

1
...
2
...
3
#include <SerialStream.h>
4
using namespace LibSerial ;
5
SerialStream rs232 ;
6
...
7
...
8
// Port öffnen
9
void plot232Dialog::OnOpen(wxCommandEvent& event)
10
{
11
12
    rs232.Open( "/dev/ttyUSB0" );
13
    rs232.SetBaudRate( SerialStreamBuf::BAUD_115200 );
14
    rs232.SetCharSize( SerialStreamBuf::CHAR_SIZE_8 );
15
    rs232.SetNumOfStopBits(1);
16
    rs232.SetParity( SerialStreamBuf::PARITY_ODD );
17
    rs232.SetFlowControl( SerialStreamBuf::FLOW_CONTROL_HARD );
18
    StaticText1->SetLabel(_("port open"));
19
20
}
21
...
22
...
23
// port schliessen
24
void plot232Dialog::OnClose(wxCommandEvent& event)
25
{
26
    rs232.Close();
27
}
28
...
29
...
30
// zum testen ein byte lesen.. 
31
void plot232Dialog::OnTest(wxCommandEvent& event)
32
{
33
34
    char next_char;
35
    rs232.get(next_char);
36
    wxString str;
37
    str<<next_char;
38
    StaticText1->SetLabel(str);
39
}

wenn ich jetzt den Port öffne scheint er irgdnwie offen zu sein, 
zumindest ist er danach blockiert :/ wenn ich ihn wieder schliesse 
rs232.close() ist er trotzdem noch blockiert...
und beim Lesen kommt immer nur 0 raus ... damit ich nicht nach jedem 
build neustarten muss wollt ich fragen wie ich den Port abwürgen kann, 
oder alternativ warum das Programm so ein Blödsinn macht ;)

von Rolf Magnus (Gast)


Lesenswert?

Einfach aus- und wieder einstecken? Ist doch nach dem Namen zu urteilen, 
ein USB-seriell-Wandler.

von phreak (Gast)


Lesenswert?

aus und einstecken hilft auch nicht :(

von Joe (Gast)


Lesenswert?

Hallo, ich hab exakt dasselbe Problem. Ich verwende ebenfalls die 
libserial und muss jedes mal, wenn die Verbindung mit meinem ftdi-device 
(serial2USB-Converter /dev/ttyUSB0) unsanft beendet wird, den PC neu 
starten.

Der Kernel erkennt zwar, wann das device eingesteckt/abgezogen wird 
(dmesg), allerdings meldet er scheinbar nicht den socket ab.

1
lsusb -v
 spuckt folgendes aus...
1
Bus 004 Device 002: ID 0403:6001 Future Technology Devices International, Ltd FT232 USB-Serial (UART) IC
2
Device Descriptor:
3
  bLength                18
4
  bDescriptorType         1
5
  bcdUSB               2.00
6
  bDeviceClass            0 (Defined at Interface level)
7
  bDeviceSubClass         0 
8
  bDeviceProtocol         0 
9
  bMaxPacketSize0         8
10
  idVendor           0x0403 Future Technology Devices International, Ltd
11
  idProduct          0x6001 FT232 USB-Serial (UART) IC
12
  bcdDevice            6.00
13
  iManufacturer           1 
14
  iProduct                2 
15
  iSerial                 3 
16
  bNumConfigurations      1
17
  Configuration Descriptor:
18
    bLength                 9
19
    bDescriptorType         2
20
    wTotalLength           32
21
    bNumInterfaces          1
22
    bConfigurationValue     1
23
    iConfiguration          0 
24
    bmAttributes         0xa0
25
      (Bus Powered)
26
      Remote Wakeup
27
    MaxPower               90mA
28
    Interface Descriptor:
29
      bLength                 9
30
      bDescriptorType         4
31
      bInterfaceNumber        0
32
      bAlternateSetting       0
33
      bNumEndpoints           2
34
      bInterfaceClass       255 Vendor Specific Class
35
      bInterfaceSubClass    255 Vendor Specific Subclass
36
      bInterfaceProtocol    255 Vendor Specific Protocol
37
      iInterface              2 
38
      Endpoint Descriptor:
39
        bLength                 7
40
        bDescriptorType         5
41
        bEndpointAddress     0x81  EP 1 IN
42
        bmAttributes            2
43
          Transfer Type            Bulk
44
          Synch Type               None
45
          Usage Type               Data
46
        wMaxPacketSize     0x0040  1x 64 bytes
47
        bInterval               0
48
      Endpoint Descriptor:
49
        bLength                 7
50
        bDescriptorType         5
51
        bEndpointAddress     0x02  EP 2 OUT
52
        bmAttributes            2
53
          Transfer Type            Bulk
54
          Synch Type               None
55
          Usage Type               Data
56
        wMaxPacketSize     0x0040  1x 64 bytes
57
        bInterval               0
58
can't get device qualifier: Operation not permitted
59
can't get debug descriptor: Operation not permitted
60
cannot read device status, Operation not permitted (1)


...und dmesg nach Abziehen/anstecken folgendes...
1
[15583.748052] usb 4-2: USB disconnect, address 2
2
[15583.749092] ftdi_sio ttyUSB0: FTDI USB Serial Device converter now disconnected from ttyUSB0
3
[15583.749128] ftdi_sio 4-2:1.0: device disconnected
4
[15588.160069] usb 4-2: new full speed USB device using uhci_hcd and address 3
5
[15588.363085] usb 4-2: configuration #1 chosen from 1 choice
6
[15588.365160] ftdi_sio 4-2:1.0: FTDI USB Serial Device converter detected
7
[15588.365232] usb 4-2: Detected FT232RL
8
[15588.365795] usb 4-2: FTDI USB Serial Device converter now attached to ttyUSB0


Also falls es einen Befehl gibt, wie man das Problem beheben kann, ohne 
jedes mal den Rechner neu zu starten, bitte bitte posten.

von Micky (Gast)


Lesenswert?

Ich kann eigentlich jedem nur raten, bei Funktionsaufrufen auch die 
Rückgabewerte zu überprüfen, auszuwerten und angemessen darauf zu 
reagieren. Dafür sind die da!

Wenn ich diese Codesequenz lese:
1
// Port öffnen
2
void plot232Dialog::OnOpen(wxCommandEvent& event)
3
{
4
5
    rs232.Open( "/dev/ttyUSB0" );
6
    rs232.SetBaudRate( SerialStreamBuf::BAUD_115200 );
7
    rs232.SetCharSize( SerialStreamBuf::CHAR_SIZE_8 );
8
    rs232.SetNumOfStopBits(1);
9
    rs232.SetParity( SerialStreamBuf::PARITY_ODD );
10
    rs232.SetFlowControl( SerialStreamBuf::FLOW_CONTROL_HARD );
11
    StaticText1->SetLabel(_("port open"));
12
13
}

dann ist da ein gutes Stück Hoffnung drin, das aber laut Murphy, na Ihr 
wisst schon...

von Hc Z. (mizch)


Lesenswert?

Ich hatte den Effekt auch schon, dass bei einem Fehler in einem 
USB/seriell-Wandler dieser und alle anderen(!) nicht mehr ansprechbar 
waren.  Statt Reboot tut's dann auch ein modprobe -r usbserial 
(natürlich nachdem alle USB/seriell-Prozesse beendet wurden).

Mit neueren Kernels (ab ca. 2.6.29) scheint das Problem weg zu sein; es 
trat jedenfalls nicht mehr auf.

----
(Übrigens, weiter oben: Ein SIGSEGV kann vom verursachenden Prozess 
nicht abgefangen werden - der Prozess bekommt vom Kernel keine Chance 
dazu mehr, denn er wird sofort beendet und hört mit dem SEGV auf zu 
laufen.  Es wird kein Signalhandler im Prozess aufgerufen.  Sein I/O 
wird geschlossen (auch vom Kernel).)

von Micky (Gast)


Lesenswert?

Der mizch mag ja Recht haben, aber wer Returncodes von Libc-Aufrufen, 
auch wenn sie in C++ verpackt sind, ignoriert, der soll hiermit gewarnt 
werden: Irgendwann geht das in die Hose!

Unter Linux ist es ja doch so, dass wenn ein Prozess endet, alle von ihm 
belegten Dateien (dazu zählen auch die seriellen Schnittstellen) 
freigegeben werden.
Aber darum geht es doch hier nicht!
Das laufende Programm soll bemerken, dass ihm die Schnittstelle abhanden 
gekommen ist. Wie soll das denn gehen, wenn sich keiner darum kümmert?

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Hazeh Zimmerer schrieb:
> (Übrigens, weiter oben: Ein SIGSEGV kann vom verursachenden Prozess
> nicht abgefangen werden - der Prozess bekommt vom Kernel keine Chance
> dazu mehr, denn er wird sofort beendet und hört mit dem SEGV auf zu
> laufen.  Es wird kein Signalhandler im Prozess aufgerufen.  Sein I/O
> wird geschlossen (auch vom Kernel).)
Ganz sicher? Bei mir funktioniert's:
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <signal.h>
4
5
void onsegv(int sig) {
6
  printf("Programm abgeschmiert\n");
7
  exit (0);
8
}
9
10
int main () {
11
  signal(SIGSEGV, onsegv);
12
  int* i = 0;
13
  printf("%d\n", *i);
14
}
Müsste der Gnome Bug Buddy nicht auch so funktionieren?

von Hc Z. (mizch)


Lesenswert?

Da passiert kein SEGV, sondern es wird über den normalen Mechanismus ein 
Signal gesendet.  Greif mal spaßeshalber auf einen Nullpointer zu und 
aus ist's damit.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Hazeh Zimmerer schrieb:
> Da passiert kein SEGV, sondern es wird über den normalen Mechanismus ein
> Signal gesendet.  Greif mal spaßeshalber auf einen Nullpointer zu und
> aus ist's damit.
Was, wenn nicht ein Null-Pointer-Zugriff, ist denn das:
1
int* i = 0;
2
printf("%d\n", *i);
Edit: Okay, int* i = NULL wäre vermutlich sauberer, wie hier auch 
irgendwo im Forum durchdiskutiert wurde.

von Hc Z. (mizch)


Lesenswert?

Ich denke, ich muss mich korrigieren.  SEGV ist nicht zwingend fatal und 
kann von einem Handler abgefangen werden.  Man lernt nie aus.

von Frank L. (florenzen)


Lesenswert?

POSIX schreibt das sogar vor.


gruß
f

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
Noch kein Account? Hier anmelden.