[Ayuda] SIGNALS: interceptar SIGIO

Miguel Cÿffffe1rdenas warlockxxi en yahoo.com
Sab Ago 28 19:42:34 CDT 2004


Holas!!

Chavos (y chavas, por si si hay :) tengo un pequeño
problema existencial con el manejo del signal SIGIO, a
ver si alguien sabe que rollo o se le ocurre algo     
              tal vez no tecnico pero alguna idea de
que ocurre...

Ya he trabajado con diferentes signals, tengo una
clase en C++ para manejo de los mismos, de hecho el
problema no es el manejo de los signals en si pues eso
ya me funciona, sino la particularidad de SIGIO...

Estoy haciendo una clase para acceso al puerto serial,
esta incluye manejo asincrono de datos (E/S asincrona
sin bloqueo), lo cual requiere el uso de SIGIO... todo
esto lo hice basado en el 'man termios' y el howto...

Basicamente tengo estos 3 problemas:

1. En el ejemplito muy sencillo del howto de
SerialProgramming simplemente abre /dev/ttySn, instala
el nuevo manejador de SIGIO y con fcntl() activa el
modo asincrono (O_ASYNC)... esto funciona
relativamente bien, pues mando un comando al modem
externo (para probar) y este me responde "\nOK\n"...
el problema es que cada que hay un SIGIO (sea o no del
modem) se ejecuta el nuevo manejador de señal y
realiza una lectura... Nota: siempre devuelve lo mismo
el read() aunque no haya datos disponibles, si por
ejemplo mando un "ATZ" el modem responde "\nOK\n" una
y otra vez sin parar cada que hay SIGIO... notese que
el read() no devuelve error, devuelve una lectura de
lo que ya habia sido leido previamente con misma
longitud, en vez de devolver -1 (error) o 0 bytes
leidos...

2. En un libro que tengo viene algo sobre signals y
E/S asincrona, trae un ejemplo, no serial pero tambien
de un descriptor de archivo, solo que con
procedimiento diferente al mencionado antes. segun
este funciona con SIGPOLL en vez de SIGIO, por otro
lado, primero bloquea la señal, instala el nuevo
manejador y desbloquea... el libro no menciona nada
sobre SIGIO, pero implemente lo de bloquear SIGIO,
instalar manejador y desbloquear en el primero que
decia, pero el resultado es el mismo, SIGIO se llama
para todos los signals de I/O...

3. Segun para capturar un signal SIGIO en un
dispositivo en particular, debes usar el fcntl() con
F_SETOWN y el PID del proceso que maneja el file
descriptor... ya hice eso, pero al parecer le vale
sombrilla y se llama el manejador del signal sea del
puerto serial o de cual quier otro dispositivo de
I/O... El codigo que tengo para esto es muy simple:

(verlo como pseudocodigo para no tener que ilustrar
todas las funciones)

RS232C::RS232C (char* dev,void(*handler)(int)) {
...
if ((portFD=open(dev,O_RDWR|O_NOCTTY|O_NONBLOCK))>0) {
   // bloquea, guarda manejador actual,
   // instala nuevo manejador y desbloquea
   vsig.signalBlock(SIGIO);
   vsig.handler(SIGIO,&sa_rs232c_orig);
   vsig.handler(SIGIO,handler);
   vsig.signalUnblock(SIGIO);

   // asigna el PID al descriptor de archivo
   // correspondiente a /dev/ttySn y luego
   // lo hace funcionar en modo asincrono
   fcntl(portFD, F_SETOWN, getpid());
   int fd_flags = fcntl(portFD,F_GETFL,0);
   fcntl(portFD, F_SETFL, fd_flags|O_ASYNC);

   portAvail = _TRUE_; // puerdo disponible
} else {
   printf("ERROR: %s\n",sys_errlist[errno]);
   portAvail = _FALSE_;
}

y pues ya en el programa principal la cosa esta asi
resumidamente:

port = new RS232C(argv[1],handler);

// check if port is opened and available
if (!port->getAvail()) { /* error */ exit... }

termios term;
term.c_iflag = INPCK;
term.c_oflag = 0;
term.c_cflag = CS8 | CREAD | CRTSCTS;
term.c_lflag = ECHO;
term.c_cc[VMIN]=1;
term.c_cc[VTIME]=0;
port->ioFlush();
port->setAttr (&term);
port->ioFlush();

// configurar velocidad... y...

char* AT = "ATZ\n";
printf("%dbytes sent\n",port->ioWrite(AT,strlen(AT)));

while(1)

y ya tan tan.. el rollo es ke instalo el manejador de
SIGIO, envio un simple "ATZ\n" y lo dejo esperando
indefinidamente con while(1) a ver que pasa... y pues
me regresa OK y OK y OK una y otra vez... como
demonios el read() devuelve datos si segun ya fueron
leidos? osea devuelve la longitud del string de
respuesta y el dato, no devuelve cero ni -1...

ya para terminar, mi manejador de signal es muy
simplecito...

RS232C* port; // declarado global mientras prueba

void handler (int stat) {
   char RECV[256];
   int len;
   //printf("BINGO\n"); fflush(stdout);
   if ( (len=port->ioRead(RECV,256)) > 0 ) {
      RECV[len] = 0x00; // agrega fin cadena
      printf("[%d] \"%s\"",len,RECV);
   } else
      printf("handler(): ERROR...");
}

Osea yo creo que todo el problema esta en la
intercepcion de SIGIO, en particular al especificar
que se genere para portFD (el descriptor de archivo
correspondiente del puerto serial)...

Alguien tendra algo de info al respecto? tal vez no
del puerto serie, pero algo de I/O asincrona o de como
manejar en particular el SIGIO...

Sale gracias...




	
		
__________________________________
Do you Yahoo!?
New and Improved Yahoo! Mail - 100MB free storage!
http://promotions.yahoo.com/new_mail 

 
_______________________________________________
Ayuda mailing list
Ayuda en linux.org.mx
Para salir de la lista: http://mail.linux.org.mx/cgi-bin/mailman/listinfo/ayuda/



Más información sobre la lista de distribución Ayuda