++++++APUE读书笔记-12线程控制-07取消相关的选项++++++
7、取消相关的选项
================================================
有两个没有包含在pthread_attr_t结构中的属性是取消状态和取消类型,它们会影响线程对pthread_cancel属性的响应。
取消状态的属性值可以是PTHREAD_CANCEL_ENABLE或者PTHREAD_CANCEL_DISABLE。线程可以通过pthread_setcancelstate改变它的取消状态。
#include
int pthread_setcancelstate(int state, int *oldstate);
如果成功返回0,如果失败返回错误号码。
这个函数将线程的取消属性设置成state,并且把之前的属性保存在oldstate所指向的内存中,这些在一个原子操作中完成。
通过前面的讲述我们可以知道调用pthread_cancel之后并不会等待一个线程的终止。默认来说,在做出了取消的请求之后,那个线程会继续执行直到到达一个“取消点”。取消点就是线程检查它是否被取消的地方,并且执行取消请求。POSIX.1保证线程调用某些函数会遇到取消点,这些函数在下表中列出。
POSIX.1中定义的取消点
+--------------------------------------------------------------------------+
| accept | mq_timedsend | putpmsg | sigsuspend |
|-----------------+-------------------------+---------------+--------------|
| aio_suspend | msgrcv | pwrite | sigtimedwait |
|-----------------+-------------------------+---------------+--------------|
| clock_nanosleep | msgsnd | read | sigwait |
|-----------------+-------------------------+---------------+--------------|
| close | msync | readv | sigwaitinfo |
|-----------------+-------------------------+---------------+--------------|
| connect | nanosleep | recv | sleep |
|-----------------+-------------------------+---------------+--------------|
| creat | open | recvfrom | system |
|-----------------+-------------------------+---------------+--------------|
| fcntl2 | pause | recvmsg | tcdrain |
|-----------------+-------------------------+---------------+--------------|
| fsync | poll | select | usleep |
|-----------------+-------------------------+---------------+--------------|
| getmsg | pread | sem_timedwait | wait |
|-----------------+-------------------------+---------------+--------------|
| getpmsg | pthread_cond_timedwait | sem_wait | waitid |
|-----------------+-------------------------+---------------+--------------|
| lockf | pthread_cond_wait | send | waitpid |
|-----------------+-------------------------+---------------+--------------|
| mq_receive | pthread_join | sendmsg | write |
|-----------------+-------------------------+---------------+--------------|
| mq_send | pthread_testcancel | sendto | writev |
|-----------------+-------------------------+---------------+--------------|
| mq_timedreceive | putmsg | sigpause | |
+--------------------------------------------------------------------------+
默认线程启动的时候,其取消状态是PTHREAD_CANCEL_ENABLE.如果取消状态设置成PTHREAD_CANCEL_DISABLE,那么pthread_cancel调用不会将线程杀死,反而这个线程的取消请求会被挂起,知道状态再次被设置成enabled,线程将会在下一个取消点执行挂起的取消的请求。除了前面列出的一定保证遇到取消点的函数,POSIX.1也提供了一些可选的函数,可以做为取消点,如下表所示。
POSIX.1定义的可选的取消点
+-------------------------------------------------------------------------------------------+
| catclose | ftell | getwc | printf |
|-------------+------------------+---------------------------------------+------------------|
| catgets | ftello | getwchar | putc |
|-------------+------------------+---------------------------------------+------------------|
| catopen | ftw | getwd | putc_unlocked |
|-------------+------------------+---------------------------------------+------------------|
| closedir | fwprintf | glob | putchar |
|-------------+------------------+---------------------------------------+------------------|
| closelog | fwrite | iconv_close | putchar_unlocked |
|-------------+------------------+---------------------------------------+------------------|
| ctermid | fwscanf | iconv_open | puts |
|-------------+------------------+---------------------------------------+------------------|
| dbm_close | getc | ioctl | pututxline |
|-------------+------------------+---------------------------------------+------------------|
| dbm_delete | getc_unlocked | lseek | putwc |
|-------------+------------------+---------------------------------------+------------------|
| dbm_fetch | getchar | mkstemp | putwchar |
|-------------+------------------+---------------------------------------+------------------|
| dbm_nextkey | getchar_unlocked | nftw | readdir |
|-------------+------------------+---------------------------------------+------------------|
| dbm_open | getcwd | opendir | readdir_r |
|-------------+------------------+---------------------------------------+------------------|
| dbm_store | getdate | openlog | remove |
|-------------+------------------+---------------------------------------+------------------|
| dlclose | getgrent | pclose | rename |
|-------------+------------------+---------------------------------------+------------------|
| dlopen | getgrgid | perror | rewind |
|-------------+------------------+---------------------------------------+------------------|
| endgrent | getgrgid_r | popen | rewinddir |
|-------------+------------------+---------------------------------------+------------------|
| endhostent | getgrnam | posix_fadvise | scanf |
|-------------+------------------+---------------------------------------+------------------|
| endnetent | getgrnam_r | posix_fallocate | seekdir |
|-------------+------------------+---------------------------------------+------------------|
| endprotoent | gethostbyaddr | posix_madvise | semop |
|-------------+------------------+---------------------------------------+------------------|
| endpwent | gethostbyname | posix_spawn | setgrent |
|-------------+------------------+---------------------------------------+------------------|
| endservent | gethostent | posix_spawnp | sethostent |
|-------------+------------------+---------------------------------------+------------------|
| endutxent | gethostname | posix_trace_clear | setnetent |
|-------------+------------------+---------------------------------------+------------------|
| fclose | getlogin | posix_trace_close | setprotoent |
|-------------+------------------+---------------------------------------+------------------|
| fcntl | getlogin_r | posix_trace_create | setpwent |
|-------------+------------------+---------------------------------------+------------------|
| fflush | getnetbyaddr | posix_trace_create_withlog | setservent |
|-------------+------------------+---------------------------------------+------------------|
| fgetc | getnetbyname | posix_trace_eventtypelist_getnext_id | setutxent |
|-------------+------------------+---------------------------------------+------------------|
| fgetpos | getnetent | posix_trace_eventtypelist_rewind | strerror |
|-------------+------------------+---------------------------------------+------------------|
| fgets | getprotobyname | posix_trace_flush | syslog |
|-------------+------------------+---------------------------------------+------------------|
| fgetwc | getprotobynumber | posix_trace_get_attr | tmpfile |
|-------------+------------------+---------------------------------------+------------------|
| fgetws | getprotoent | posix_trace_get_filter | tmpnam |
|-------------+------------------+---------------------------------------+------------------|
| fopen | getpwent | posix_trace_get_status | ttyname |
|-------------+------------------+---------------------------------------+------------------|
| fprintf | getpwnam | posix_trace_getnext_event | ttyname_r |
|-------------+------------------+---------------------------------------+------------------|
| fputc | getpwnam_r | posix_trace_open | ungetc |
|-------------+------------------+---------------------------------------+------------------|
| fputs | getpwuid | posix_trace_rewind | ungetwc |
|-------------+------------------+---------------------------------------+------------------|
| fputwc | getpwuid_r | posix_trace_set_filter | unlink |
|-------------+------------------+---------------------------------------+------------------|
| fputws | gets | posix_trace_shutdown | vfprintf |
|-------------+------------------+---------------------------------------+------------------|
| fread | getservbyname | posix_trace_timedgetnext_event | vfwprintf |
|-------------+------------------+---------------------------------------+------------------|
| freopen | getservbyport | posix_typed_mem_open | vprintf |
|-------------+------------------+---------------------------------------+------------------|
| fscanf | getservent | pthread_rwlock_rdlock | vwprintf |
|-------------+------------------+---------------------------------------+------------------|
| fseek | getutxent | pthread_rwlock_timedrdlock | wprintf |
|-------------+------------------+---------------------------------------+------------------|
| fseeko | getutxid | pthread_rwlock_timedwrlock | wscanf |
|-------------+------------------+---------------------------------------+------------------|
| fsetpos | getutxline | pthread_rwlock_wrlock | |
+-------------------------------------------------------------------------------------------+
如果你的程序在很长的时间内没有调用前面列出的取消点函数,那么你可以调用pthread_testcancel来自己亲自为程序添加取消点。
#include
void pthread_testcancel(void);
调用了这个函数之后,如果存在被提交的取消请求并且取消的状态没有被disable,那么这个线程将会被取消。如果取消状态被disabled了,那么这个函数没有任何作用。
我们所描述的默认的取消类型是"延迟取消",也就是说调用pthread_cancel函数之后,实际的取消动作并没有立即发生而是在遇到了第一个取消点的时候才发生。我们可以通过调用pthread_setcanceltype函数来设置取消类型。
#include
int pthread_setcanceltype(int type, int *oldtype);
函数成功返回0,失败返回错误号码。
参数type可以是PTHREAD_CANCEL_DEFERRED或者PTHREAD_CANCEL_ASYNCHRONOUS,这个函数会设置线程的取消类型为type,然后返回之前的类型保存在oldtype整形指针所指的地方。
异步取消类型和延迟取消类型是不一样的,异步取消类型导致线程可以在任何时候被取消而不用非得遇到一个取消点。
参考:
阅读(732) | 评论(0) | 转发(0) |