事件驱动编程——《Unix/Linux编程实践教程》读书笔记(第7章)

1、curses库

/* 基本curses函数 */
initscr();            // 初始化curses库和tty
endwin();             // 关闭curses并重置tty
refresh();            // 使屏幕按照你的意图显示
move(r, c);           // 移动光标到屏幕的(r, c)位置
addstr(s);            // 在当前位置画字符串s
addch(c);             // 在当前位置画字符c
clear();              // 清屏
standout();           // 启动standout模式(一般使屏幕反色)
standend();           // 关闭standout模式



2、
man 3 sleep
#include <unistd.h>
unsigned int sleep(unsigned int n);
/*
 * sleep() makes the calling thread sleep until n seconds
 * have elapsed or a signal arrives which is not ignored.
 * 
 * Zero if the requested time has elapsed, or the number
 * of seconds left to sleep, if the call was interrupted
 * by a signal handler.
 */



sleep()的工作原理

系统中的每个进程都有一个私有的闹钟(alarm clock)。这个闹钟很像一个计时器,可以设置在一定秒数后闹铃。时间一到,时钟就发送一个信号SIGALRM到进程。除非进程为SIGALRM设置了处理函数(handler),否则信号将杀死这个进程。sleep函数由3个步骤组成:

/* sleep()的工作原理 */
signal(SIGALRM, handler);
alarm(num_seconds);
pause();

一下是对alarm()和pause()的描述。



man 2 alarm



#include <unistd.h>
unsigned int alarm(unsigned int n_seconds);
/*
 * alarm() arranges for a SIGALRM signal to be delivered to
 * calling process in n seconds.
 * If n_seconds is zero, any pending alarm is canceled.
 * In any envet any previously set alarm() is canceled.
 *
 * alarm() returns the number of seconds remaining until
 * any previously scheduled alarm was due to be delivered,
 * or zero if there was no previously scheduled alarm.
 */



man 2 pause



#include <unistd.h>
int pause(void);
/*
 * pause() causes the calling process (or thread) to sleep until
 * a signal is delivered that either terminates the process or
 * causes the invocation of a signal-catching function.
 *
 * pause() returns only when a signal was caught and the
 * signal-catching function returned. In this case pause()
 * returns -1, and errno is set to EINTR.
 */



精度更高的时延:
#include <unistd.h>
int usleep(useconds_t usec);



3、三种计时器:真实、进程和实用

(1)ITIMER_REAL:这个计时器计量真实时间。当这个计时器用尽,发送SIGALRM消息。

(2)ITIMER_VIRTUAL:虚拟计时器(virtual timer)只有进程在用户态运行时才计时。当虚拟计时器用尽,发送SIGVTALRM消息。

(3)ITIMER_PROF:这个计时器在进程运行于用户态或由该进程调用而陷入核心态时计时。当这个计时器用尽,发送SIGPROF消息。

4、set_ticker.c

/* 
 * set_ticker.c
 * set_ticker(number_of_milliseconds)
 * arranges for interval timer to issue SIGALRMs at regular intervals
 * return 01 on error, 0 for ok
 * arg in milliseconds, converted into whole seconds and microseconds
 * note: set_ticker(0) turns off ticker
 */

#include <stdio.h>
#include <sys/time.h>

int set_ticker(int n_msecs)
{
    struct itimerval new_timeset;
    long n_sec, n_usecs;

    n_sec = n_msecs / 1000;
    n_usecs = (n_msecs % 1000) * 1000L;

    new_timeset.it_interval.tv_sec = n_sec;
    new_timeset.it_interval.tv_usec = n_usecs;

    new_timeset.it_value.tv_sec = n_sec;
    new_timeset.it_value.tv_usec = n_usecs;

    return setitimer(ITIMER_REAL, &new_timeset, NULL);
}



结构体itimerval、timeval的描述:
struct itimerval
{
    struct timeval it_valuse;      /* time to next timer expiration */
    struct timeval it_interval;    /* reload it_value with this */
}

struct timeval
{
    time_t      tv_sec;        /* seconds */
    suseconds   tv_usec;       /* and microseconds */
}



函数getitimer、setitimer的描述:
man 2 getitimer



#include <sys/time.h>
int getitimer(int which, struct itimerval *curr_value);
int setitimer(int which, const struct itimerval *new_value,
              struct itimerval *old_value);



5、早期的信号处理机制

各种事件促使内核向进程发送信号。这些事件包括用户的击键、进程的非法操作和计时器到时。一个进程调用signal在以下3种处理信号的方法之中选择:

(1)默认操作(一般是终止进程),比如,signal(SIGALRM, SIG_DFL)



(2)忽略信号,比如,signal(SIGALRM, SIG_IGN)

(3)调用一个函数,比如,signal(SIGALRM, handler)

6、POSIX中替代signal()的函数sigaction()

(1)

man 2 sigaction

#include <signal.h>
int sigaction(int signum, const struct sigaction *act,
              struct sigaction *oldact);

/* 其中 */
struct sigaction {
    void (*sa_handler)(int);  /* SIG_DFL, SIG_IGN, or function */
    void (*sa_sigaction)(int, siginfo_t *, void *);  /* new handler */
    sigset_t sa_mask;  /* signals to block while handling */
    int sa_flags;  /* enable various behaviors */
    void (*sa_restorer)(void);/* POSIX does not specify this element */
};



(2)sa_flags是用一些位来控制处理函数如何应对上述4



sigaction()的概述比较麻烦,用一个例程来了解一下吧:

/*
 * sigactdemo.c
 * purpose: shows use of sigaction()
 * feature: blocks ^\ while handling ^C
 *          does not reset ^C handler, so two kill
 */

#include <stdio.h>
#include <signal.h>

#define INPUTLEN (100)

int main(void)
{
    struct sigaction    newhandler;         /* new settings */
    sigset_t            blocked;            /* set of blocked sigs */
    void                inthandler(int);
    char                x[INPUTLEN];

    /* load these two members first */
    newhandler.sa_handler = inthandler;     /* handler function */
    newhandler.sa_flags = SA_RESETHAND | SA_RESTART;
                                            /* options */

    /* then build the list of blocked signals */
    sigemptyset(&blocked);                  /* clear all bits */
    sigaddset(&blocked, SIGQUIT);           /* add SIGQUIT to list */
    newhandler.sa_mask = blocked;           /* store blockmask */

    if (sigaction(SIGINT, &newhandler, NULL) == -1)
        perror("sigaction");
    else
        while (1)
        {
            fgets(x, INPUTLEN, stdin);
            printf("input: %s\n", x);
        }
    return 0;
}

void inthandler(int s)
{
    printf("Called with signal %d\n", s);
    sleep(s);
    printf("done handling signal %d\n", s);
}





事件驱动编程——《Unix/Linux编程实践教程》读书笔记(第7章),古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。