2009-09-29 2 views
0

/dev/ttyS2를 제어하는 ​​프로세스가 직렬 포트에서 BREAK를 수신하는 경우 SIGINT를 수신하고 싶습니다. 쉘에서이 프로그램을 실행합니다. "터미널이 전경 프로세스 그룹의 제어 터미널 인 경우에만이 전경 프로세스 그룹에 SIGINT가 전송됩니다"터미널에서 컨트롤러를 만드는 프로세스를 만들었지 만 실패합니다.리눅스가 ttycontrol 프로그램에 대한 신호 수신

#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; 
} 
+0

_POSIX_SOURCE가 1 인 경우 POSIX 1990이 호출됩니다. #define _XOPEN_SOURCE 600 '(또는 아마도 500)을 사용하면 더 잘 수행 할 수 있습니다. 아마도 signal()보다 sigaction()을 더 잘 사용했을 것이다. 그러나 이들 중 어느 것도 당신이 보지 못하는 것을 설명하지 못합니다. –

답변

0

#define _POSIX_SOURCE 1 그것이 #include의 선행하지 않으면 효과가 없습니다.

C99 컴파일러에서는 #defineTRUEFALSE 대신 #include <stdbool.h>을 사용할 수 있습니다.

/* 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에 의해 설정됩니다.

+0

코드를 편집하고 을 추가했습니다. (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은 % d", EPERM 임); } 그러나 tcsetpgrp가 ENOTTY – CrazyChris

+0

으로 실패합니다. errno 값을 기록하지 마십시오! 이것은 사용자가 Google에 오류 번호를 표시 할 것으로 예상되는 Windows가 아닙니다! "% m"(GNU 확장자) 또는 이와 동등한 "% s", strerror (errno)를 사용하십시오. –

1

마침내 내 문제에 대한 답변을 찾았습니다. 나는 커스텀 보드를 사용하고 있기 때문에 항상 작동 할 필요는 없지만 시리얼 포트가 올바르게 설정되어 있다면 사용자는 cat/proc/tty/device/serial에 의해 직렬 포트에 의한 휴식 횟수를 얻을 수있다.

관련 문제