In Named Pipe schreiben ohne SIGPIPE auszulösen.

12/01/2009 - 14:33 von Jan Kandziora | Report spam
Hallo,

ich steh' vermutlich einfach auf dem Schlauch. Folgende Umstànde:

Für einen Touchscreen existiert ein selbstgemachtes XInput-Treibermodul. Zur
Kalibrierung dient ein selbstgemachtes Programm, das genau wie der Treiber
die Rohdaten vom per RS232 angebundenen Controller lesen muss.

Soweit, so gut. Nun kann aber natürlich immer nur ein Prozess die serielle
Schnittstelle kontrollieren. Das ist wàhrend der ganzen Zeit der Treiber.
Für das Kalibrierprogramm würde es jedoch auch ausreichen, nur "mitlesen"
zu können. Daher will ich eine Named Pipe einrichten, in die der Treiber
die vom Controller gelesenen Daten einfach nur abkippt. Das
Kalibrierprogramm soll sie dort abholen.

Nun das Problem: Wie erreiche ich zuverlàssig, dass beim Schließen der Named
Pipe durch das Kalibrierprogramm der Treiber *kein SIGPIPE* erhàlt? Ich
möchte das Signal ungern einfach ignorieren, da der Treiber ja nur ein
einzelnes Modul von X ist und ich nicht weiß, wie die anderen Programmteile
auf das SIGPIPE bzw. auf das Fehlen von SIGPIPE reagieren.

Ich habe schon versucht, mittels select() herauszufinden, ob der
Dateideskriptor geschrieben werden kann. select() liefert jedoch
grundsàtzlich 0 zurück, wenn ich es auf die zuvor erfolgreich geöffnete
Named Pipe anwende, egal ob ein anderer Prozess daran horcht oder nicht.



Funktionierende Testcode mit signal():

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>

const char *buf = "BLA";

#define FD_INVALID -1

int main(void)
{
int fdý_INVALID;
ssize_t count;

signal(SIGPIPE, SIG_IGN);

while (1)
{
if (fd == FD_INVALID)
{
if ((fd=open("xfifo", O_WRONLY|O_NONBLOCK)) < 0)
{
if (errno == ENXIO) goto end;

perror("open");
exit(EXIT_FAILURE);
}
}

if ((count=write(fd, buf, sizeof(buf)-1)) < 0)
{
if (errno == EPIPE)
{
close(fd);
fdý_INVALID;
}
else
{
perror("write");
exit(EXIT_FAILURE);
}
}

end:
fprintf(stderr,".");
usleep(100000);
}

return 0;
}

Die Gegenseite ist einfach "cat xfifo"


Vielleicht hat ja jemand von euch eine Idee.

Mit freundlichem Gruß

Jan
 

Lesen sie die antworten

#1 Rainer Weikusat
12/01/2009 - 14:46 | Warnen spam
Jan Kandziora writes:

[...]

Daher will ich eine Named Pipe einrichten, in die der Treiber
die vom Controller gelesenen Daten einfach nur abkippt. Das
Kalibrierprogramm soll sie dort abholen.

Nun das Problem: Wie erreiche ich zuverlàssig, dass beim Schließen der Named
Pipe durch das Kalibrierprogramm der Treiber *kein SIGPIPE* erhàlt? Ich
möchte das Signal ungern einfach ignorieren, da der Treiber ja nur ein
einzelnes Modul von X ist und ich nicht weiß, wie die anderen Programmteile
auf das SIGPIPE bzw. auf das Fehlen von SIGPIPE reagieren.



Eine (Linux-)Alternativmogelichkeit waere, eine PF_UNIX stream socket zu
benutzen und Daten mit 'send' und MSG_NOSIGNAL als flag zu
schreiben. Man koennte wohl auch einen Hilfs-Prozess benutzen, dem der
Treiber die Daten via pipe uebertraegt, und der selber die 'named
pipe' fuettert, wobei er SIGPIPE so behandeln koennte, wie es ihm
passen wuerde. Allerdings gibt es (meines Wissens nach) keine
zuverlaessige Moeglichkeit, ein unzeitiges Ableben dieses
Hilfsprozesses vor einem SIGPIPE zu erkennen. Schliesslich koennte man
die Daten auch noch einfach an eine PF_UNIX datagram socket mit einer
'bekannten' Addresse schicken (sendto). Sollte die im Moment niemand haben
wollen, gaebe es 'nur' einen Fehler, den man vollstaendig ignorieren
kann.

Ähnliche fragen