本教程不是基础线程,希望有点基础的POSIX 线程知识。 高手也不用看了。。
第一篇:Linux线程的信号处理行为
大家都知道linux 2.5内核之后 引入了NPTL ,让自己的用户态线程行为更符合Poxis口味。。下面就来看看NPTL的线程对信号的行为。
当然我们得首先复习..几个linux上的函数
tkill
NAME tkill
- send a signal to a single process SYNOPSIS int tkill(int tid, int sig);
DESCRIPTION
The tkill() system call is analogous to kill(2), except when the specified process is part of a thread group (created by specifying the CLONE_THREAD flag in the call to clone). Since all the processes in a thread group have the same PID, they cannot be individually sig-nalled with kill(2). With tkill(), however, one can address each process by its unique TID.These are the raw system call interfaces, meant for internal thread library use.
我个人感觉这个man写的不怎么好: 因为你不能把他翻译成中文去理解
通俗易懂的说: tkill 可以发给特定的 LWP,比如一个进程,他产生了很多LWP, 那么我可以想发给谁发给谁。
如果他不产生,就他一个独苗,那么我用tikll对他发信号,和kill发效果是一样的。
我们都知道如果通过kill 发信号给一个PID ,如果你没有做什么的话,正常情况下,应该是main线程接受。这个时候你会想,太搓了! 我要把信号发给我指定的人!
好linux知道你有这个怪癖,提供了tkill。 问题来了 tid是啥。。2.6内核proc下面看不到了!当然你可以猜:
现在的进程是 PID, 那么我产生的应该是 PID+1,但是当你产生了1000个,就找不到北了。。
linux当然早提供了gettid ,你可能需要通过
syscall(SYS_gettid);
记住 pthread_self 得到是线程自己的一个pthread_t ,这个玩意内核是没有数据结构记录的,应该只是一个用户态的东东,对他发信号,只需要 pthread_kill();
这个时候,你是不是开始跃跃欲试的,想试试看 tkill了? 于是你会这样写
测试进程:
static void* is_receive(void* arg)
{
while(1) {
printf("%d LWP RUNNING\n",
syscall(SYS_gettid); );
sleep(5);
}
return (void*)(-1);
}
int main(int argc, char *argv[])
{
pthread_t t;
pthread_attr_t prattr;
pthread_attr_init(&prattr);
pthread_attr_setdetachstate(&prattr,
PTHREAD_CREATE_JOINABLE);
pthread_attr_setscope(&prattr, PTHREAD_SCOPE_SYSTEM);
pthread_create(&t, &prattr, is_receive, NULL);
pause();
}
然后很开心的用
syscall(__NR_tkill, tid, SIGUSR1);
发送完了,你ps -ef一看,说,cao 。。不对啊,主线程也没了。
记住,如果你用任何测试信号的时候。 请记得他在 APUE书中写的默认行为 ,改整个进程退出的他们还是会退出,不是你发给 某个LWP,就可以改变Poxis的。。
所以你最好找那种默认行为为SIG_IGN的测试。。或者你自己之前改写了如SIGPIPE这样的信号行为。
于是你会得到你想要的结果。
然后你会说,我不想用tkill ,因为是custom 发信息给我。他不知道TID,只知道PID。这个时候你只能用kill(sigqueue)
于是谁去处理信号的问题,就需要你编程手动处理。
我们先来看看thread prime上怎么说:
我觉得T_P上面很多话都没用。 关于这个话题我提炼出一句话: 你需要发给哪个LWP ,把不需要的BLOCK就行!
代码看起来可能应该这样写。
void block_it(int sig)
{
sigset_t sig_block;
sigemptyset(&sig_block);
sigaddset( &sig_block, sig);
sigprocmask( SIG_BLOCK, &sig_block, NULL );
//pthread_sigmask( SIG_BLOCK, &sig_block, NULL );
}
static void* receive_signal(void* arg)
{
//block_it(SIGUSR2);
while(1) {
sleep(5);
}
return (void*)(-1);
}
static void just_printf(int arg){
printf("%d RECEIVING\n",syscall(SYS_gettid));
}
int main(int argc, char *argv[])
{
signal(SIGUSR2,just_printf);
int tid;
pthread_t t;
pthread_attr_t prattr;
pthread_attr_init(&prattr);
pthread_attr_setdetachstate(&prattr,PTHREAD_CREATE_JOINABLE);
pthread_attr_setscope(&prattr, PTHREAD_SCOPE_SYSTEM);
pthread_create(&t, &prattr, receive_signal, NULL);
block_it(SIGUSR2);//让子线程接受信号
pause();
}
看到block_it 这个函数了吗? 没错。just do it, 在信号来之前赶快哦。 这样你用kill(getpid(),SIG___) 你会发现他们工作的很好。 就算你个pid发送,子线程也帮你处理了这个信号~。
方法告诉你了,具体几千个LWP怎么指派某一个,就要自己发挥想象啦。 P_T中告诉你。。你可以用一个专门的信号处理线程~~
同样你也可能看到注释掉的pthread_sigmask() 为啥呢。因为
The function shall be equivalent to sigprocmask(), without the restriction that the call be made in a single-threaded process.
大家考虑一下,怎么实现一个异步IO ?
>
>
>
>
没错 ,如果了解 softirq 的人 都知道通过 参考ksoftirqd 线程
A: dedicated kernel<use process> thread ; B : work queues 在加上上面说的唤醒锁机制 就ok 啦
- 大小: 28.1 KB
分享到:
相关推荐
嵌入式Liunx应用程序开发笔记-代码.zip嵌入式Liunx应用程序开发笔记-代码.zip嵌入式Liunx应用程序开发笔记-代码.zip嵌入式Liunx应用程序开发笔记-代码.zip嵌入式Liunx应用程序开发笔记-代码.zip嵌入式Liunx应用程序...
Liunx内核完全注释-1.9.5
liunx shell脚本编程-全网最全
数据库备份工具, 有 win, liunx , mac 三个版本的, 对应的mysql版本为5.7 , 主要是mac版本的不好找.
liunx ftp服务器搭建
liunx版apche-tomcat-6.0.48压缩包 tar xvf newFileName.tar fileName
zookeeper-3.4.9-liunx.zip zookeeper-3.4.9-liunx.zip zookeeper-3.4.9-liunx.zip
pid_t fork(void)失败返回-1,成功返回:1。父进程返回子进程的ID 2.子进程返回0 pid_t类型表示进程ID,但为了表示-1,它是有符号整型笔记返回值,不是fork函数能返回两个值,或者fork后,fork函数变成两个,父子...
liunx下jdk-tomcat-mysql的安装配置以及tomcat与mysqld的开机自启动的配置
liunx版nginx-1.12.0、openssl-1.1.0e、pcre-8.37、zlib-1.2.11
nexus-3.6.2-01-unix.tar.gz,nexus在Linux上安装部署的文件包
Oracle Instant client 是oracle提供的简便客户端,instantclient-basic-linux-11.2.0.3.0
docker-compose liunx(64) 和 window(64)两个版本 构建版本 docker-compose version 1.25.4, build 8d51620a
Nexus 3.7.1-02 Linux版本
带视频教程
mariadb老版数据库下载资源安装包,应对旧系统框架不支持新版数据库。
本人编写的基于AT89S52的DYP-ME007超声波测距模块源代码,C语言版,数码管显示或串口返回测试数据,经测试成功。
mysql-5.6.38-liunx-64bit,mysql-5.6.38-liunx-64bit
外加安装说明,MySQL-5.6.17-liunx-32bit,MySQL-5.6.17-liunx-32bit
oracle 数据库驱动 instantclient-basic-linux.x64-12.2.0.1.0.zip instantclient-basiclite-linux.x64-12.2.0.1.0.zip