信号,进程,线程

1 信号和进程

 Reference 

APUE P240

 #include <signal.h>
 typedef void (*sighandler_t)(int);
 sighandler_t signal(int signum, sighandler_t handler);

#include <signal.h>
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signum);
int sigdelset(sigset_t *set, int signum);
int sigismember(const sigset_t *set, int signum);

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
sigprocmask() is used to fetch and/or change the signal mask of the calling thread.The signal mask is the set of signals whose delivery is
currently blocked for the caller (see also signal(7) for more details).

 #include <signal.h>
 int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);
The sigaction() system call is used to change the action taken by a process on receipt of a specific signal.  (See signal(7) for an overview of signals.)


Example:
void sig_segv(int sig, siginfo_t *info, void *puc)
{
    if (sig != SIGSEGV)
        error("signal");
    longjmp(jmp_env, 1);
}

void test_signal(void)
{
    struct sigaction act;
    struct itimerval it, oit;

    /* timer test */

    alarm_count = 0;

    act.sa_handler = sig_alarm;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    chk_error(sigaction(SIGALRM, &act, NULL));

    it.it_interval.tv_sec = 0;
    it.it_interval.tv_usec = 10 * 1000;
    it.it_value.tv_sec = 0;
    it.it_value.tv_usec = 10 * 1000;
    chk_error(setitimer(ITIMER_REAL, &it, NULL));
    chk_error(getitimer(ITIMER_REAL, &oit));
    if (oit.it_value.tv_sec != it.it_value.tv_sec ||
        oit.it_value.tv_usec != it.it_value.tv_usec)
        error("itimer");

    while (alarm_count < 5) {
        usleep(10 * 1000);
    }

    it.it_interval.tv_sec = 0;
    it.it_interval.tv_usec = 0;
    it.it_value.tv_sec = 0;
    it.it_value.tv_usec = 0;
    memset(&oit, 0xff, sizeof(oit));
    chk_error(setitimer(ITIMER_REAL, &it, &oit));
    if (oit.it_value.tv_sec != 0 ||
        oit.it_value.tv_usec != 10 * 1000)
        error("setitimer");

    /* SIGSEGV test */
    act.sa_sigaction = sig_segv;
    sigemptyset(&act.sa_mask);
    act.sa_flags = SA_SIGINFO;
    chk_error(sigaction(SIGSEGV, &act, NULL));

    if (setjmp(jmp_env) == 0) {
        *(uint8_t *)0 = 0;
    }

    act.sa_handler = SIG_DFL;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    chk_error(sigaction(SIGSEGV, &act, NULL));
}


2 信号和线程

A 线程会继承父线程的信号屏蔽字
例子:该函数很好的说明了属性A 的用法。效果是子线程屏蔽了所有信号,而主线程还是保留原来的屏蔽字。
void qemu_thread_create(QemuThread *thread,
                       void *(*start_routine)(void*),
                       void *arg, int mode)
{
    sigset_t set, oldset;
    int err;
    pthread_attr_t attr;

    err = pthread_attr_init(&attr);
    if (err) {
        error_exit(err, __func__);
    }
    if (mode == QEMU_THREAD_DETACHED) {
        err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
        if (err) {
            error_exit(err, __func__);
        }
    }

    /* Leave signal handling to the iothread.  */
    sigfillset(&set);
    pthread_sigmask(SIG_SETMASK, &set, &oldset);
    err = pthread_create(&thread->thread, &attr, start_routine, arg);
    if (err)
        error_exit(err, __func__);

    pthread_sigmask(SIG_SETMASK, &oldset, NULL);

    pthread_attr_destroy(&attr);
}

B 每个线程可以有自己的信号屏蔽字,即线程可以调用pthread_sigmask 来设置自己的信号屏蔽字。
#include <signal.h>
int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset);
Compile and link with -pthread.
DESCRIPTION
       The  pthread_sigmask() function is just like sigprocmask(2), with the difference that its use in multithreaded programs is explicitly speci‐
       fied by POSIX.1-2001.  Other differences are noted in this page.

C 信号的处理是进程中所有线程共享的。 
    当线程修改了与某个信号相关的处理行为后,所有的线程都必须共享这个处理行为的改变。

D 进程中的信号是递送到单个线程的。 如果信号是与硬件或者计时器超时有关,该信号就被发送到引起该事件的线程中去,而其他的信号则被发送到任意一个线程。
    (3要素)引起该事件的线程,  接受该事件的线程, 建立信号处理函数的线程
     信号处理函数是共享的,在哪个线程建立似乎不重要
     注意,如果一个线程屏蔽了只有它才能接受的信号,该信号将不会触发信号处理函数

E  sigwait 
等待处于未决状态的信号


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值