如何选择STDIN_FILENO忽略信号?

时间:2010-02-05 06:57:56

标签: c select pipe signals stdin

请检查以下代码

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/time.h>
#include <time.h>

#define CLOCKID CLOCK_REALTIME
#define SIG SIGRTMIN
int reset = 0;
void changemode(int);
int  kbhit(void);
int pfds[2];

static void handler(int sig, siginfo_t *si, void *uc)
{
    write(pfds[1], "reset", 6);
}

int main(void)
{
    int ch;
    timer_t timerid;
    struct sigaction sa;
    struct itimerspec its;
    struct sigevent sev;
    long long freq_nanosecs;
    char buf[30];

    pipe(pfds);

    sa.sa_flags = 0;
    sa.sa_sigaction = handler;
    sigemptyset(&sa.sa_mask);
    if (sigaction(SIG, &sa, NULL) == -1)
    {
        printf("Error\n");
        exit(1);
    }

    changemode(1);

    sev.sigev_notify = SIGEV_SIGNAL;
    sev.sigev_signo = SIG;
    sev.sigev_value.sival_ptr = &timerid;
    if (timer_create(CLOCKID, &sev, &timerid) == -1)
    {
        printf("Error timer_create");
        exit(1);
    }

    its.it_value.tv_sec = 1;
    its.it_value.tv_nsec = 0;
    its.it_interval.tv_sec = its.it_value.tv_sec;
    its.it_interval.tv_nsec = its.it_value.tv_nsec;

    if (timer_settime(timerid, 0, &its, NULL) == -1)
    {
        printf("Error timer_settime");
        exit(1);
    }

    while(1)
    {
        if (kbhit())
        {
            ch = getchar();
            printf("%d %c\n", ch, ch);
            if (ch == 'q')
            {
                printf("\nQuitting...\n");
                break;
            }
        }
        else
        {
            memset(buf, 0, 30);
            read(pfds[0], buf, 6);
            printf("\n%s", buf);
        }
    }

    changemode(0);
    return 0;
}

void changemode(int dir)
{
    static struct termios oldt, newt;

    if ( dir == 1 )
    {
        tcgetattr( STDIN_FILENO, &oldt);
        newt = oldt;
        newt.c_lflag &= ~( ICANON | ECHO );

        tcsetattr( STDIN_FILENO, TCSANOW, &newt);
    }
    else
        tcsetattr( STDIN_FILENO, TCSANOW, &oldt);
}

int kbhit (void)
{
    fd_set rdfs;

    FD_ZERO(&rdfs);
    FD_SET (STDIN_FILENO, &rdfs);
    FD_SET (pfds[0], &rdfs);

    select(FD_SETSIZE, &rdfs, NULL, NULL, NULL);
    return FD_ISSET(STDIN_FILENO, &rdfs);

}

但是每当生成信号SIGRTMIN时,STDIN_FILENO被设置(FD_ISSET),但我没有在终端中输入任何内容。如何在定时器生成SIGRTMIN时选择忽略STDIN_FILENO?

1 个答案:

答案 0 :(得分:1)

如果您使用的是Linux,则应使用pselect而不是select。

如果没有,您应该检查select返回的错误代码。如果它是EINTR,则可能(但我不确定)您可能需要再次调用select以检查fds的状态。