在信号部分提到一个可重入函数的概念,先回顾一下。可重入函数是可以在信号处理函数中调用的函数,未使用全局变量、静态变量的函数。
线程这部分有个线程安全函数的概念,和可重入入函数类似。线程安全函数指的是可以在线程中被安全调用的函数,那什么样的函数会被线程不安全的调用呢?访问了临界资源的函数是不安全的。虽然全局、静态变量是属于临界资源,但是这个概念又有别于不可重入函数,如果不安全的函数中对临界区使用了同步的措施,那么这个函数仍然是不可重入的函数,但已经是线程安全的了。
如果一个进程中的多个线程都使用了一个全局变量,那么这个变量就成为了临界资源,Posix线程库中提供给我们一个让同一个全局变量成为每个线程私有的变量的方法(如errno是一个全局变量,但每个线程都有自己的一个errno为私有的)。这个方法称为线程的私有数据(对同一全局变量在每个线程的值不同),通过绑定键值实现,通过pthread_key_create()/pthread_key_delete()函数创建/删除键,使用pthread_setspecific()绑定键值和全局变量,使用pthread_getspecific()获取键值对应的私有全局变量的值。
[cpp] int pthread_key_create(pthread_key_t *key, void(*destructor)(void *));
int pthread_key_delete(pthread_key_t key);
int pthread_setspecific(pthread_key_t key, const void *value);
void *pthread_getspecific(pthread_key_t key);
int pthread_key_create(pthread_key_t *key, void(*destructor)(void *));
int pthread_key_delete(pthread_key_t key);
int pthread_setspecific(pthread_key_t key, const void *value);
void *pthread_getspecific(pthread_key_t key); 信号是进程中的语义,那在线程中信号是怎样处理的呢?之前说过,发送给进程的信号会送往进程中的某一个线程,在创建线程时会继承信号屏蔽字但之后线程之间的信号屏蔽字就不互相影响了,但是我们之前学到的更改屏蔽字的函数sigprocmask()是改变整个进程(所有线程)的屏蔽字,那如何只更改某个线程的屏蔽字呢?使用pthread_sigmask()函数:
[cpp] int pthread_sigmask(int how, const sigset_t *set, sigset_t *oset);
int pthread_sigmask(int how, const sigset_t *set, sigset_t *oset);该函数的参数以及返回值和sigprocmask()是一样的。在多线程编程中处理信号的经典措施是:指定一个专门的线程来处理指定的信号,而其它线程则屏蔽此信号。
如果说我们就像要向某个线程发送信号该怎么处理呢(只能是同一进程中的线程间,因为线程id只在同一进程中有意义)?使用pthread_kill函数:
[cpp] int pthread_kill(pthread_t thread, int signo);
int pthread_kill(pthread_t thread, int signo);如果signo为0,则可用于测试线程是否存在。
还有一个sigwait()函数,该函数将当前线程阻塞,至未决信号集中有set中的信号,则获取该信号放到signop中
[cpp] int sigwait(const sigset_t *set, int *signop);
int sigwait(const sigset_t *set, int *signop);