• Linux线程信号


    源地址:http://blog.csdn.net/copal/archive/2010/04/06/5454279.aspx

    1. 概念

    • 按照 POSIX, 异步 (外部) 信号发送到整个进程.
    • 所有线程共享同一个设置, 即通过 sigaction 设置的线程处置方法.
    • 每个线程有自己的信号掩码, 线程库根据该掩码决定将信号发送到哪个线程.
    • 由于Linux 线程实现上的独特性, 外部信号始终发送到特定的线程.  

    2. 例子

    1. #include <pthread.h>  
    2. #include <stdio.h>  
    3. #include <sys/signal.h>  
    4.   
    5. #define NUMTHREADS 3  
    6. void sighand(int signo);  
    7.   
    8. void *threadfunc(void *parm)  
    9. {  
    10.     pthread_t             tid = pthread_self();  
    11.     int                   rc;  
    12.   
    13.     printf("Thread %u entered\n", tid);  
    14.     rc = sleep(30); /* 若有信号中断则返回剩余秒数 */  
    15.     printf("Thread %u did not get expected results! rc=%d\n", tid, rc);  
    16.     return NULL;  
    17. }  
    18.   
    19. void *threadmasked(void *parm)  
    20. {  
    21.     pthread_t             tid = pthread_self();  
    22.     sigset_t              mask;  
    23.     int                   rc;  
    24.   
    25.     printf("Masked thread %lu entered\n", tid);  
    26.   
    27.     sigfillset(&mask); /* 将所有信号加入mask信号集 */  
    28.   
    29.     /* 向当前的信号掩码中添加mask信号集 */  
    30.     rc = pthread_sigmask(SIG_BLOCK, &mask, NULL);  
    31.     if (rc != 0)  
    32.     {  
    33.         printf("%d, %s\n", rc, strerror(rc));  
    34.         return NULL;  
    35.     }  
    36.   
    37.     rc = sleep(15);  
    38.     if (rc != 0)  
    39.     {  
    40.         printf("Masked thread %lu did not get expected results! rc=%d \n", tid, rc);  
    41.         return NULL;  
    42.     }  
    43.     printf("Masked thread %lu completed masked work\n", tid);  
    44.     return NULL;  
    45. }  
    46.   
    47. int main(int argc, char **argv)  
    48. {  
    49.     int                     rc;  
    50.     int                     i;  
    51.     struct sigaction        actions;  
    52.     pthread_t               threads[NUMTHREADS];  
    53.     pthread_t               maskedthreads[NUMTHREADS];  
    54.   
    55.     printf("Enter Testcase - %s\n", argv[0]);  
    56.     printf("Set up the alarm handler for the process\n");  
    57.   
    58.     memset(&actions, 0, sizeof(actions));  
    59.     sigemptyset(&actions.sa_mask); /* 将参数set信号集初始化并清空 */  
    60.     actions.sa_flags = 0;  
    61.     actions.sa_handler = sighand;  
    62.   
    63.     /* 设置SIGALRM的处理函数 */  
    64.     rc = sigaction(SIGALRM,&actions,NULL);  
    65.   
    66.     printf("Create masked and unmasked threads\n");  
    67.     for(i=0; i<NUMTHREADS; ++i)  
    68.     {  
    69.         rc = pthread_create(&threads[i], NULL, threadfunc, NULL);  
    70.         if (rc != 0)  
    71.         {  
    72.             printf("%d, %s\n", rc, strerror(rc));  
    73.             return -1;  
    74.         }  
    75.   
    76.         rc = pthread_create(&maskedthreads[i], NULL, threadmasked, NULL);  
    77.         if (rc != 0)  
    78.         {  
    79.             printf("%d, %s\n", rc, strerror(rc));  
    80.             return -1;  
    81.         }  
    82.     }  
    83.   
    84.     sleep(3);  
    85.     printf("Send a signal to masked and unmasked threads\n");  
    86.   
    87.      /* 向线程发送SIGALRM信号 */  
    88.     for(i=0; i<NUMTHREADS; ++i)  
    89.     {  
    90.         rc = pthread_kill(threads[i], SIGALRM);  
    91.         rc = pthread_kill(maskedthreads[i], SIGALRM);  
    92.     }  
    93.   
    94.     printf("Wait for masked and unmasked threads to complete\n");  
    95.     for(i=0; i<NUMTHREADS; ++i) {  
    96.         rc = pthread_join(threads[i], NULL);  
    97.         rc = pthread_join(maskedthreads[i], NULL);  
    98.     }  
    99.   
    100.     printf("Main completed\n");  
    101.     return 0;  
    102. }  
    103.   
    104. void sighand(int signo)  
    105. {  
    106.     pthread_t             tid = pthread_self();  
    107.   
    108.     printf("Thread %lu in signal handler\n", tid);  
    109.     return;  
    110. }  

    3. 打印结果

    Enter Testcase - ./test
    Set up the alarm handler for the process
    Create masked and unmasked threads
    Thread 3085065104 entered
    Masked thread 3076672400 entered
    Thread 3068279696 entered
    Masked thread 3059886992 entered
    Thread 3051494288 entered
    Masked thread 3043101584 entered
    Send a signal to masked and unmasked threads
    Thread 3085065104 in signal handler
    Thread 3085065104 did not get expected results! rc=27
    Thread 3068279696 in signal handler
    Thread 3068279696 did not get expected results! rc=27
    Thread 3051494288 in signal handler
    Thread 3051494288 did not get expected results! rc=27

    Wait for masked and unmasked threads to complete
    Masked thread 3076672400 completed masked work
    Masked thread 3059886992 completed masked work
    Masked thread 3043101584 completed masked work

    Main completed

    4. 相关函数

    sigaction(查询或设置信号处理方式)

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


    sigaction()会依参数signum指定的信号编号来设置该信号的处理函数。参数signum可以指定SIGKILL和SIGSTOP以外的所有信号。
    如参数结构sigaction定义如下

    struct sigaction
    {
       void (*sa_handler) (int);
       sigset_t sa_mask;
       int sa_flags;
       void (*sa_restorer) (void);
    }

    sa_handler此参数和signal()的参数handler相同,代表新的信号处理函数,其他意义请参考signal()。
    sa_mask 用来设置在处理该信号时暂时将sa_mask 指定的信号搁置。
    sa_restorer 此参数没有使用。
    sa_flags 用来设置信号处理的其他相关操作,下列的数值可用。

    sigfillset(将所有信号加入此信号集)

    #include<signal.h>
    int sigfillset(sigset_t * set);
     
    sigfillset()用来将参数set信号集初始化,然后把所有的信号加入到此信号集里。
     
    sigemptyset(初始化信号集)  
    #include<signal.h>
    int sigemptyset(sigset_t *set);
     
    sigemptyset()用来将参数set信号集初始化并清空
     
    pthread_sigmask(更改或检查调用线程的信号掩码)
     
    #include <pthread.h>
    #include<signal.h>
    int pthread_sigmask(int how, const sigset_t *new, sigset_t *old);
     
    how用来确定如何更改信号组,可以为以下值之一:
    • SIG_BLOCK:向当前的信号掩码中添加new,其中new表示要阻塞的信号组。
    • SIG_UNBLOCK:向当前的信号掩码中删除new,其中new表示要取消阻塞的信号组。
    • SIG_SETMASK:将当前的信号掩码替换为new,其中new表示新的信号掩码。
     
    pthread_kill(向线程发送信号)
     
    #include <pthread.h>
    #include<signal.h>
    int pthread_kill(thread_t tid, int sig);
     
    pthread_kill()将信号sig发送到由tid指定的线程。tid所指定的县城必须与调用线程在同一个进程中。
  • 相关阅读:
    利用Spring AOP自定义注解解决日志和签名校验
    SpringBoot返回date日期格式化,解决返回为TIMESTAMP时间戳格式或8小时时间差
    @RequestBody配合@JsonFormat注解实现字符串自动转换成Date
    Mysql的时间类型问题
    IntelliJ IDEA使用maven-javadoc-plugin生成Java Doc控制台乱码
    Maven学习笔记(十二)-maven打包之resource配置
    SpringBoot使用@Value从yml文件取值为空--注入静态变量
    cloud server ribbon 自定义策略配置
    JNA 如何 加载多个 存在依赖的 DLL 库
    Remote Desktop File Format
  • 原文地址:https://www.cnblogs.com/hnrainll/p/2031308.html
Copyright © 2020-2023  润新知