7、取消点的进一步讨论
来源:互联网 发布:jquery confirm.js 编辑:程序博客网 时间:2024/06/07 22:19
线程取消的方法是向目标线程发Cancel信号,但如何处理Cancel信号则由目标线程自己决定,或者忽略、或者立即终止、或者继续运行至Cancelation-point(取消点),由不同的Cancelation状态决定。
线程接收到CANCEL信号的缺省处理(即pthread_create()创建线程的缺省状态)是继续运行至取消点,也就是说设置一个CANCELED状态,线程继续运行,只有运行至Cancelation-point的时候才会退出。
(1)什么是线程取消点
根据POSIX标准,pthread_join()、pthread_testcancel()、pthread_cond_wait()、pthread_cond_timedwait()、sem_wait()、sigwait()等函数以及read()、write()等会引起阻塞的系统调用都是Cancelation-point,而其他pthread函数都不会引起Cancelation动作。但是pthread_cancel的手册页声称,由于LinuxThread库与C库结合得不好,因而目前C库函数都不是Cancelation-point;但CANCEL信号会使线程从阻塞的系统调用中退出,并置EINTR错误码,因此可以在需要作为Cancelation-point的系统调用前后调用pthread_testcancel(),从而达到POSIX标准所要求的目标,即如下代码段:
pthread_testcancel();
retcode = read(fd, buffer, length);
(2)与线程取消相关的pthread函数
int pthread_cancel(pthread_t thread)
发送终止信号给thread线程,如果成功则返回0,否则为非0值。发送成功并不意味着thread会终止。
int pthread_setcancelstate(int state, int *oldstate)
设置本线程对Cancel信号的反应,state有两种值:PTHREAD_CANCEL_ENABLE(缺省)和PTHREAD_CANCEL_DISABLE,分别表示收到信号后设为CANCLED状态和忽略CANCEL信号继续运行;old_state如果不为NULL则存入原来的Cancel状态以便恢复。
int pthread_setcanceltype(int type, int *oldtype)
设置本线程取消动作的执行时机,type由两种取值:PTHREAD_CANCEL_DEFFERED和PTHREAD_CANCEL_ASYCHRONOUS,仅当Cancel状态为Enable时有效,分别表示收到信号后继续运行至下一个取消点再退出和立即执行取消动作(退出);oldtype如果不为NULL则存入运来的取消动作类型值。
void pthread_testcancel(void)
Calling pthread_testcancel() creates a cancellation point within the calling thread, so that a thread that is otherwise executing code that contains no cancellation points will respond to a cancellation request.
If cancelability is disabled (using pthread_setcancelstate(3)), or no cancellation request is pending, then a call to pthread_cancel(3) has no effect.
也就是说pthread_testcancel在不包含取消点,但是又需要取消点的地方创建一个取消点,以便在一个没有包含取消点的执行代码线程中响应取消请求。
示例代码【3】
#include <pthread.h>#include <sys/types.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <errno.h>#define handle_error_en(en, msg) \ do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)staticint done =0;staticint cleanup_pop_arg =0;staticint cnt =0;staticvoidcleanup_handler(void*arg){ printf("Called clean-up handler\n"); cnt =0;}staticvoid*thread_start(void*arg){ time_t start, curr; printf("New thread started\n"); pthread_cleanup_push(cleanup_handler, NULL); curr = start = time(NULL); while (!done) { pthread_testcancel(); /* A cancellation point */ if (curr < time(NULL)) { curr = time(NULL); printf("cnt = %d\n", cnt); /* A cancellation point */ cnt++; } } pthread_cleanup_pop(cleanup_pop_arg); return NULL;}intmain(int argc, char*argv[]){ pthread_t thr; int s; void*res; s = pthread_create(&thr, NULL, thread_start, NULL); if (s !=0) handle_error_en(s, "pthread_create"); sleep(2); /* Allow new thread to run a while */ if (argc >1) { if (argc >2) cleanup_pop_arg = atoi(argv[2]); done =1; } else { printf("Canceling thread\n"); s = pthread_cancel(thr); if (s !=0) handle_error_en(s, "pthread_cancel"); } s = pthread_join(thr, &res); if (s !=0) handle_error_en(s, "pthread_join"); if (res == PTHREAD_CANCELED) printf("Thread was canceled; cnt = %d\n", cnt); else printf("Thread terminated normally; cnt = %d\n", cnt); exit(EXIT_SUCCESS);}
示例代码跟踪
[root@localhost CFunctionTest]# ./threadNew thread startedcnt =0cnt =1Canceling threadCalled clean-up handlerThread was canceled; cnt =0[root@localhost CFunctionTest]# gdb thread(gdb) b 18//...(gdb) rStarting program: /home/***/a***/CFunctionTest/thread [Thread debugging using libthread_db enabled]Breakpoint 6, main (argc=1, argv=0xbffff374) at testthread.cpp:5454 s = pthread_create(&thr, NULL, thread_start, NULL);Missing separate debuginfos, use: debuginfo-install glibc-2.12.90-17.i686 libgcc-4.5.1-4.fc14.i686 libstdc++-4.5.1-4.fc14.i686(gdb) n[New Thread 0xb7fecb70 (LWP 4845)]New thread started[Switching to Thread 0xb7fecb70 (LWP 4845)]Breakpoint 2, thread_start (arg=0x0) at testthread.cpp:2929 pthread_cleanup_push(cleanup_handler, NULL);(gdb) n31 curr = start = time(NULL);(gdb) n33while (!done) {(gdb) nBreakpoint 3, thread_start (arg=0x0) at testthread.cpp:3434 pthread_testcancel(); /* A cancellation point */(gdb) nCanceling thread[Switching to Thread 0xb7fee6d0 (LWP 4840)]Breakpoint 7, main (argc=1, argv=0xbffff374) at testthread.cpp:7070 s = pthread_cancel(thr);(gdb) ncnt =0[Switching to Thread 0xb7fecb70 (LWP 4845)]Breakpoint 4, thread_start (arg=0x0) at testthread.cpp:3939 cnt++;(gdb) n33while (!done) {(gdb) nBreakpoint 3, thread_start (arg=0x0) at testthread.cpp:3434 pthread_testcancel(); /* A cancellation point */(gdb) n35if (curr < time(NULL)) (gdb) n37 curr = time(NULL);(gdb) n38 printf("cnt = %d\n", cnt); /* A cancellation point */(gdb) ncnt =1[Switching to Thread 0xb7fee6d0 (LWP 4840)]Breakpoint 8, main (argc=1, argv=0xbffff374) at testthread.cpp:7575 s = pthread_join(thr, &res);(gdb) n[Switching to Thread 0xb7fecb70 (LWP 4845)]Breakpoint 4, thread_start (arg=0x0) at testthread.cpp:3939 cnt++;(gdb) n33while (!done) {(gdb) nBreakpoint 3, thread_start (arg=0x0) at testthread.cpp:3434 pthread_testcancel(); /* A cancellation point */(gdb) nBreakpoint 1, cleanup_handler (arg=0x0) at testthread.cpp:1818 printf("Called clean-up handler\n");(gdb) nCalled clean-up handler19 cnt =0;(gdb) n20 }(gdb) n
参考:
【1】 http://blog.csdn.net/yanook/article/details/6589798
【2】http://blog.csdn.net/yulanarti/article/details/6197769
【3】http://www.kernel.org/doc/man-pages/online/pages/man3/pthread_cleanup_push.3.html
- 7、取消点的进一步讨论
- 关于考试的进一步讨论
- 关于win32 Dll开发的进一步讨论
- 对话:关于委托的进一步讨论
- 关于类和对象的进一步讨论
- vxworks启动进一步讨论
- 对JavaScript的eval()中使用函数的进一步讨论~
- 对JavaScript的eval()中使用函数的进一步讨论~
- 对JavaScript的eval()中使用函数的进一步讨论
- SDL入门教程(五):3、对SDL_BlitSurface()的进一步讨论
- 编程之美 中国象棋将帅问题 的再进一步讨论
- SDL入门教程(五):3、对SDL_BlitSurface()的进一步讨论
- C++类与对象的进一步讨论(1)
- C++类与对象的进一步讨论(2)
- C++类与对象的进一步讨论(1)
- C++类与对象的进一步讨论(2)
- 第四章 类和对象的进一步讨论
- 第四章 类和对象的进一步讨论-续
- tcpdump 使用
- NavigationViewController的backBarButtonItem的设置技巧 ...
- VS2005下opengl的helloworld
- hdu 2845 Beans--二维DP
- 阻抗匹配
- 7、取消点的进一步讨论
- Android中的多线程-Timer
- android 设备唯一码的获取,Cpu号,Mac地址
- Objective C 建造者模式
- jquery 元素选择器集合
- java.lang.UnsatisfiedLinkError解决方法汇集
- 普通用户眼中的云
- linux 下 automake 生成 makefile
- IT软件开发人员必去的10个社区