Linux的C编程中多线程如何终止某个线程示例与要点

描述

示例 demo

最简单的 demo:

static void* thread1_func(void *arg)

{

int i = 0;

// able to be cancel

pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);

pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);

for(i=0; ; i++) {

printf(“thread1 %d

”, i);

sleep(1);

}

}

int main(int argc, char **argv)

{

pthread_t t;

void *res;

pthread_create(&t, NULL, thread1_func, NULL);

sleep(3);

pthread_cancel(t); // cancel thread1

pthread_join(t, &res); // wait thread1

if (res == PTHREAD_CANCELED)

printf(“thread1 was terminate by cancel

”);

else

printf(“thread1 was not terminate by cancel

”);

exit(EXIT_SUCCESS);

}

为了突出重点,省略了检查返回值。

运行效果:

thread1 0

thread1 1

thread1 2

thread1 was terminate by cancel

主线程先创建线程 thread1,然后睡眠 3 秒后发出终止 thread1 的请求。

接收到终止请求后,thread1 会在合适的时机被终止掉。

主线程通过 pthread_join() 阻塞等待 thread1 退出。

几个要点

线程终止的 4 种方式:

线程的执行函数返回了,这和 main() 函数结束类似。

线程调用了 pthread_exit() 函数,这和调用 exit() 返回类似。

线程被另一个线程通过 pthread_cancel() 函数取消,这和通过kill() 发送 SIGKILL 信号类似。

进程终止了,则进程中的所有线程也会终止。

取消某个线程的常规步骤

被取消的线程:

允许取消,pthread_setcancelstate(),参数可选值:

PTHREAD_CANCEL_ENABLE,这是默认值;

PTHREAD_CANCEL_DISABLE;

设置取消类型,pthread_setcanceltype(),参数可选值:

PTHREAD_CANCEL_ASYNCHRONOUS,异步方式,当发出取消请求后,线程可能会在任何点被杀死。

PTHREAD_CANCEL_DEFERRED,延迟方式,线程只会在特定的取消点(cancellation points,调用某个函数前)被杀死。

发起取消的线程:

发送取消要求,pthread_cancel(),发出取消请求后,pthread_cancel() 当即返回,不会等待目标线程的退出。

等待取消完成,pthread_join()。

哪些函数是取消点?

POSIX.1 指定了哪些函数一定是取消点:

c编程

更多关于取消点的介绍:

$ man 7 pthreads

Cancellation points

。..

accept()

aio_suspend()

clock_nanosleep()

close()

。..

阅读开源软件 MJPG-streamer

MJPG-streamer 是什么?

简单地说,就是一个开源的流媒体服务器:

https://github.com/jacksonliam/mjpg-streamer

通过 mjpg-streamer,你可以通过 PC 浏览器访问到板子上的摄像头图像。

MJPG-streamer 是如何结束工作线程的?

MJPG-streamer 运行时一般会有 3 个线程:

主线程;

负责数据的输入的线程 (例如 camera capture thread);

负责输出数据的线程 (例如 http server thread)。

以 http server thread 为例:

plugins/output_http/httpd.c

void *server_thread(void *arg)

{

。..

pthread_cleanup_push(server_cleanup, pcontext);

// 处理连接

while(!pglobal-》stop) {

。..

}

pthread_cleanup_pop(1);

}

pthread_cleanup_push() 用于注册清理函数到栈中,当线程遭取消时,会沿该栈自顶向下依次执行清理函数。

当用户通过按下 ctrl + c 要求结束程序时,主线程会要求杀掉 http server thread 等各种线程:

static void signal_handler(int sig)

{

for(i = 0; i 《 global.outcnt; i++) {

。..

pthread_cancel(servers[id].threadID);

。..

}

}

接下来,当 http server thread 遇到某个取消点时,server_cleanup() 会被调用以完成清理工作。

这里只是简单地分析一下,MJPG-Streamer 里多线程相关的代码挺复杂的,有兴趣的小伙伴们自行阅读吧。
编辑:lyn

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分