C++ pthread 信号量及detach的使用

通过一个简单的例子,总结一下pthread中信号量的使用方式以及使用pthread_detach和使用pthread_join的区别。以备以后查阅。


涉及到的函数:

int pthread_kill(pthread_t thread, int sig) :向线程发送一个信号,参数分别为线程ID和信号量。在线程内部可以对信号进行处理,当然也有一些系统默认的出来方式。比如发送信号SIGQUIT,该线程则会退出。


sigemptyset 初始化信号量并清空。


sigaddset:把信号加入信号集,这样在等待信号量时,也可以等待一个信号量的集合中的某一个信号。


int sigwait(const sigset_t *set, int *sig):等待信号集,并返回接收到的信号量。


pthread_detach(pthread_t thread):如果线程调用了该函数,主进程不会被阻塞等待线程结束才返回,而是启动了线程后去继续自己的工作。这是它与pthread_join()不同的地方。


C++ pthread 信号量及detach的使用_第1张图片


实例程序 1 (使用 pthread_join)

  • 主进程启动一个工作线程
  • 线程启动后等待信号量
  • 主进程向线程发送信号量
  • 主进程使用pthread_join等待线程结束
  • (为了使测试结果更加明显,改程序不设结束方式,主进程会一直等待,直到人为杀死该进程)

#include <signal.h>
#include <errno.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>

void sig_handler(int signum)
{
    printf("Receive signal. %d\n", signum);
}

void* sigmgr_thread(void* p)
{
    sigset_t   waitset, oset;
    int        sig;
    int        rc;
    pthread_t  ppid = pthread_self();

    //pthread_detach(ppid);

    sigemptyset(&waitset);
    sigaddset(&waitset, SIGRTMIN);
    sigaddset(&waitset, SIGRTMIN+2);
    sigaddset(&waitset, SIGRTMAX);
    sigaddset(&waitset, SIGUSR1);
    sigaddset(&waitset, SIGUSR2);

    while (1)  
    {
        sleep(1);
        printf("thread is alive...\n");
        rc = sigwait(&waitset, &sig);
        if (rc != -1) 
        {
            sig_handler(sig);
        }
        else 
        {
            printf("sigwaitinfo() returned err: %d \n", errno);
        }
    }
}

int main()
{
    sigset_t bset, oset;
    int             i;
    printf("main { \n");
    pthread_t       ppid;

    sigemptyset(&bset);
    sigaddset(&bset, SIGRTMIN);
    sigaddset(&bset, SIGRTMIN+2);
    sigaddset(&bset, SIGRTMAX);
    sigaddset(&bset, SIGUSR1);
    sigaddset(&bset, SIGUSR2);

    printf("main pthread_sigmask \n");
    if (pthread_sigmask(SIG_BLOCK, &bset, &oset) != 0)
        printf("!! Set pthread mask failed\n");

    printf("main create thread\n");
    // Create the dedicated thread sigmgr_thread() which will handle signals synchronously
    pthread_create(&ppid, NULL, sigmgr_thread, NULL);

    printf("main start send signal \n");
    pthread_kill(ppid, SIGRTMAX);
    pthread_kill(ppid, SIGRTMAX);
    pthread_kill(ppid, SIGRTMIN+2);
    pthread_kill(ppid, SIGRTMIN);
    pthread_kill(ppid, SIGRTMIN+2);
    pthread_kill(ppid, SIGRTMIN);
    pthread_kill(ppid, SIGUSR2);
    pthread_kill(ppid, SIGUSR2);
    pthread_kill(ppid, SIGUSR1);
    pthread_kill(ppid, SIGUSR1);

    printf("main sleep 20 seconds/n");
    sleep(20);

    pthread_join(ppid, NULL);
    printf("main }\n");

    return 0;
}

测试结果:程序会一直等待,直到人为结束(ctrl+c)

C++ pthread 信号量及detach的使用_第2张图片



实例程序 2 (使用 pthread_detach)

  • 主进程启动一个工作线程
  • 线程内部调用pthread_detach
  • 线程启动后等待信号量
  • 主进程向线程发送信号量
  • 主进程运行直到结束线程结束

#include <signal.h>
#include <errno.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>

void sig_handler(int signum)
{
    printf("Receive signal. %d\n", signum);
}

void* sigmgr_thread(void* p)
{
    sigset_t   waitset, oset;
    int        sig;
    int        rc;
    pthread_t  ppid = pthread_self();

    pthread_detach(ppid);

    sigemptyset(&waitset);
    sigaddset(&waitset, SIGRTMIN);
    sigaddset(&waitset, SIGRTMIN+2);
    sigaddset(&waitset, SIGRTMAX);
    sigaddset(&waitset, SIGUSR1);
    sigaddset(&waitset, SIGUSR2);

    while (1)  
    {
        sleep(1);
        printf("thread is alive...\n");
        rc = sigwait(&waitset, &sig);
        if (rc != -1) 
        {
            sig_handler(sig);
        }
        else 
        {
            printf("sigwaitinfo() returned err: %d \n", errno);
        }
    }
}


int main()
{
    sigset_t bset, oset;
    int             i;
    printf("main { \n");
    pthread_t       ppid;
    
    sigemptyset(&bset);
    sigaddset(&bset, SIGRTMIN);
    sigaddset(&bset, SIGRTMIN+2);
    sigaddset(&bset, SIGRTMAX);
    sigaddset(&bset, SIGUSR1);
    sigaddset(&bset, SIGUSR2);

    printf("main pthread_sigmask \n");
    if (pthread_sigmask(SIG_BLOCK, &bset, &oset) != 0)
        printf("!! Set pthread mask failed\n");

    printf("main create thread\n");
    // Create the dedicated thread sigmgr_thread() which will handle signals synchronously
    pthread_create(&ppid, NULL, sigmgr_thread, NULL);

    printf("main start send signal \n");
    pthread_kill(ppid, SIGRTMAX);
    pthread_kill(ppid, SIGRTMAX);
    pthread_kill(ppid, SIGRTMIN+2);
    pthread_kill(ppid, SIGRTMIN);
    pthread_kill(ppid, SIGRTMIN+2);
    pthread_kill(ppid, SIGRTMIN);
    pthread_kill(ppid, SIGUSR2);
    pthread_kill(ppid, SIGUSR2);
    pthread_kill(ppid, SIGUSR1);
    pthread_kill(ppid, SIGUSR1);

    printf("main sleep 20 seconds/n");
    sleep(20);

    //pthread_join(ppid, NULL);
    printf("main }\n");

    return 0;
}


测试结果:主进程会自己结束
C++ pthread 信号量及detach的使用_第3张图片


你可能感兴趣的:(C++ pthread 信号量及detach的使用)