Linux получает разрыв сигнала для программы ttycontrol

Я хотел бы получать SIGINT, если мой процесс, управляющий /dev/ttyS2, получает BREAK на последовательном порту. Я запускаю эту программу из оболочки. Из того, что я обнаружил, только «терминал является управляющим терминалом группы процессов переднего плана, это приведет к отправке SIGINT в эту группу процессов переднего плана». Я попытался сделать процесс, создающий контроллер терминала, но он терпит неудачу.

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h> 
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>

#define BAUDRATE B115200
#define MODEMDEVICE "/dev/ttyS2"
#define _POSIX_SOURCE 1 /* POSIX compliant source */
#define FALSE 0
#define TRUE 1


__sighandler_t sighandle(int signum, __sighandler_t h) { 
    fprintf(stderr, "BREAK DETECTED\n"); 
    signal(SIGINT, (__sighandler_t) sighandle); 
    return SIG_IGN; 
}
volatile int STOP=FALSE; 

int    main()
{
    int fd,c, res;
    struct termios oldtio,newtio;
    char buf[255];
    pid_t  pid; 
    signal(SIGINT, (__sighandler_t) sighandle);

    fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY ); 
    if (fd <0) {perror(MODEMDEVICE); return (-1); }


    tcgetattr(fd,&oldtio); /* save current port settings */

    memset(&newtio, 0,sizeof(newtio));
    newtio.c_cflag |= BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD | BRKINT;
    newtio.c_iflag &= ~IGNBRK ;
    newtio.c_oflag = 0;

    /* set input mode (non-canonical, no echo,...) */
    newtio.c_lflag = 0;

    newtio.c_cc[VTIME]    = 0;   /* inter-character timer unused */
    newtio.c_cc[VMIN]     = 1;   /* blocking read until 5 chars received */

    tcflush(fd, TCIFLUSH);
    tcsetattr(fd,TCSANOW,&newtio);

    if( ioctl(fd, TIOCSCTTY, 1) <0 )
    {
        printf("Error number: %d\n", errno);
    }
   if ( tcsetpgrp(fd, tcgetpgrp(0) ) < 0 )
   {
   syslog(LOG_PERROR,"tcsetpgrp failed: %d " ,errno);
   syslog(LOG_PERROR,"EBADF is %d " ,EBADF);    
   syslog(LOG_PERROR,"EINVAL is %d " ,EINVAL);
   syslog(LOG_PERROR,"ENOTTY is %d " ,ENOTTY);    
   syslog(LOG_PERROR,"EPERM is %d " ,EPERM);  
   }
    while (STOP==FALSE) {       /* loop for input */
        res = read(fd,buf,255);   /* returns after 5 chars have been input */
        buf[res]=0;               /* so we can printf... */

        printf(":%s:%d\n", buf, res);
        if (buf[0]=='z') {STOP=TRUE;}
    }
    tcsetattr(fd,TCSANOW,&oldtio);
    return 0;
}

person CrazyChris    schedule 29.09.2009    source источник
comment
_POSIX_SOURCE из 1 вызывает POSIX 1990; вам, вероятно, будет лучше с '#define _XOPEN_SOURCE 600' (или, возможно, 500). Вероятно, вам лучше использовать sigaction() вместо signal(). Однако ни один из них не объясняет то, чего вы не видите.   -  person Jonathan Leffler    schedule 29.09.2009


Ответы (2)


Наконец-то я нашел ответ на свою проблему. Я использую пользовательскую плату, поэтому она не должна работать всегда, но когда последовательный порт настроен правильно, пользователь может получить количество разрывов по последовательному порту с помощью cat /proc/tty/device/serial, такие функции я надеялся получить

person CrazyChris    schedule 30.09.2009

#define _POSIX_SOURCE 1 не действует, если перед ним не стоят #includes.

С компилятором C99 вы можете #include <stdbool.h> вместо #define своих собственных TRUE и FALSE.

/* from signal.h, */
typedef void(*sighandler_t)(int);
/* which means the handler must be declared thusly */
void sighandle(int);
/* as a result, no casting is necessary */
sighandler_t p_sighandle = &sighandle;

Группа процессов переднего плана задается tcsetpgrp, которую вы отсутствующий.

person ephemient    schedule 29.09.2009
comment
Я отредактировал код и добавил: системный журнал (LOG_PERROR, EBADF равен %d, EBADF); системный журнал (LOG_PERROR, EINVAL равен %d, EINVAL); syslog(LOG_PERROR,ENOTTY равно %d ,ENOTTY); системный журнал (LOG_PERROR, EPERM равен %d, EPERM); } но tcsetpgrp не работает с ENOTTY - person CrazyChris; 29.09.2009
comment
не записывайте ошибочные значения! Это не Windows, где пользователи должны гуглить номера ошибок! Используйте %m (расширение GNU) или эквивалент %s, strerror(errno). - person Peter Cordes; 10.12.2009