Linux 应用程序多线程编程

本文深入探讨了在多线程环境中利用 POSIX 线程库 pthread 实现信号处理与等待机制,包括创建线程、线程间通信、信号的发送与接收,以及如何使用 sigwait 函数实现信号的同步处理。通过实例展示了如何在一个线程中监听信号,另一个线程接收信号并作出响应,从而有效管理多线程环境中的信号交互。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 #include <pthread.h>
       int pthread_create(pthread_t *restrict thread,
              const pthread_attr_t *restrict attr,
              void *(*start_routine)(void*), void *restrict arg);、

创建线程,其中:

thread:指向标志线程标识符的指针;

attr:用来设置线程的属性;

start_routine:线程的执行行数;

arg:传递给线程的唯一指针。

所有线程都有一个线程号,也就是Thread ID。其类型为pthread_t。通过调用pthread_self()函数可以获得自身的线程号。

  #include <pthread.h>

int pthread_join(pthread_t thread, void **value_ptr);

pthread_join使一个线程等待另一个线程结束。

代码中如果没有pthread_join主线程会很快结束从而使整个进程结束,从而使创建的线程没有机会开始执行就结束了。加入pthread_join后,主线程会一直等待直到等待的线程结束自己才结束,使创建的线程有机会执行。当然可以设置线程的属性,子线程自己回收资源,而主线程退出不影响子线程继续执行。

pthread_t tid;线程pid

sigset_t set; 线程集结构体

int pthread_kill(pthread_t thread, int sig)   向线程thread 传递sig信号


 #include <signal.h>
 int sigwait(const sigset_t *restrict set, int *restrict sig);

在多线程中处理信号的原则却完全不同,它的基本原则是:将对信号的异步处理,转换成同步处理,也就是说用一个线程专门的来“同步等待”信号的到来,而其它的线程可以完全不被该信号中断/打断(interrupt)。这样就在相当程度上简化了在多线程环境中对信号的处理。

 在多线程代码中,总是使用sigwait或者sigwaitinfo或者sigtimedwait等函数来处理信号;

而不是signal或者sigaction等函数。因为在一个线程中调用signal或者sigaction等函数会改变所以线程中;

 信号处理函数。而不是仅仅改变调用signal/sigaction的那个线程的信号处理函数。

监听信号集set中所包含的信号,并将其存在signo中。注意:sigwait函数所监听的信号在之前必须被阻塞。
sigwait函数将阻塞调用他的线程,直到收到它所监听的信号发生了,然后sigwait将其从未决队列中取出(因为被阻塞了,所以肯定是未决了),但是有一点需要注意的是:它从未决队列取出之后,并不影响那个被取出的信号原来被阻塞的状态。它所做的工作只有两个:第一,监听被阻塞的信号;第二,如果所监听的信号产生了,则将其从未决队列中移出来(这里实时信号和非实时信号又有区别,体现在取出的顺序等,具体自己取网上查,这里不再详述)。
#include <stdio.h>
#include <pthread.h>
#include <signal.h>
#include <unistd.h>


pthread_t ntid;定义线程ID
sigset_t set; 定义一个信号集
void *child_thread(void *p)
{
int signum;
while(1)
{
sigwait(&set, &signum); 监听信号的发生,把发送的信号保存在signum中
switch(signum)
{
case SIGUSR1:
printf("pthread running.\n");
continue;
case SIGUSR2:
      printf("sleep 2s quit.\n");
sleep(1);
break;
default:
printf("no  symbol..\n");
}
}
sigdelset(&set, SIGUSR2);
}
int main()
{
int retu;
char tmpc;
void *status;


sigemptyset(&set); 初始化set
sigaddset(&set, SIGUSR1);
sigaddset(&set, SIGUSR2);把信号加入信号集
sigprocmask(SIG_SETMASK,&set,NULL);
retu = pthread_create(&ntid, NULL, child_thread, NULL);
if(retu < 0)
{
printf("create thread fail,rerurn.\n");
return -1;
}
while(1)
{
printf("Please input a char.\n");
scanf("%c",&tmpc);
switch(tmpc)
{
case 'a':
pthread_kill(ntid, SIGUSR1);发送信号
continue;
case 'q':
pthread_kill(ntid, SIGUSR2);
pthread_join(ntid,&status); 同步等待子线程退出
      printf("finish\n");
break;
default:
printf("unknown symbol..\n");
}
}
return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值