【问题标题】:Linux receive signal break for ttycontrol programLinux 接收 ttycontrol 程序的信号中断
【发布时间】:2009-09-29 14:20:25
【问题描述】:

如果我的进程控制 /dev/ttyS2 在串行端口上接收到 BREAK,我想接收 SIGINT。我从 shell 运行这个程序。从我发现的只有“终端是前台进程组的控制终端,它会导致一个 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;
}

【问题讨论】:

  • _POSIX_SOURCE of 1 正在调用 POSIX 1990; '#define _XOPEN_SOURCE 600'(或者可能是 500)可能会更好。使用 sigaction() 比使用 signal() 可能会做得更好。但是,这些都不能说明您没有看到什么。

标签: c linux tty


【解决方案1】:

我终于找到了我的问题的答案。我正在使用自定义板,因此它不必一直工作,但是当正确配置串行端口时,用户可以通过 cat /proc/tty/device/serial 获得串行端口的中断次数,我希望获得的那种功能

【讨论】:

    【解决方案2】:

    #define _POSIX_SOURCE 1 没有任何作用,除非它在 ​​#includes 之前。

    使用 C99 编译器,您可以使用 #include &lt;stdbool.h&gt; 而不是 #define 您自己的 TRUEFALSE

    /* 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 设置的,您似乎缺少它。

    【讨论】:

    • 我编辑了代码并添加了 if ( tcsetpgrp(fd, tcgetpgrp(0) )
    • 不要记录 errno 值!这不是 Windows,用户需要用谷歌搜索错误号!使用“%m”(GNU 扩展),或等效的“%s”,strerror(errno)。
    猜你喜欢
    • 1970-01-01
    • 2012-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多