线程的清理处理程序pthread_cleanup_(线程六)

1.pthread_cleanup_push(),注册清理函数,押栈。

pthread_cleanup_pop(),清理函数,出栈。

这两个函数是成对出现的,少一个会导致编译不通过

参数详解:

pthread_cleanup_push(),该函数的第一个参数是清理函数参数是void*,返回值是void类型的,第二个函数是押栈需要传的参数。

pthread_cleanup_pop(),出栈,调用清理函数,其中只有一个参数,改参数是非零会响应清理函数,是0的话,不做处理

=

注意该处理函数是被放在栈区,所以先进栈的后出栈。,也就是说先进栈的函数,最后被调用。

当有以下三种操作的时候会调用清理函数:

1.调用pthread_exit()函数,会响应清理处理函数。

2.用非零的函数调用pthread_cleanup_pop()函数

3.响应取消请求。

二:程序设计

基本思路:在主进程中创造两个线程,在线程一二中,分别用pthread_cleanup_push()注册清理函数,用pthread_cleanup_pop响应处理函数,再用return 和pthread_exit退出时,分别验证:结果pthread_cleanup_pop()中参数是非0时会调用清理处理函数,当参数是0的时候,pthread_cleanup_pop该函数的参数在pthread_exit()退出前调用无论是0还是非0,都会响应清理处理函数,但是pthread_exit()在pthread_cleanup_pop函数之后调用,pthread_cleanup_pop函数的参数是0的话,清理函数已经退出,所以就不会再调用到清理处理函数了。

运行结果:

先进栈的后运行。

三、pthread_exit ()和return以及exit()的区别

首先return是关键字不是函数,而pthread_exit ()和exit()是退出函数。

在main函数中return是给main函数一个返回值,然后主函数在隐身调用exit()给操作系统,整个进程才结束,exit()主要用于进程退出,直接交给操作系统,退出进程, pthread_exit()用于线程退出,可以指定返回值,以便其他线程通过pthread_join()函数获取该线程的返回值。

return,是函数返回,不一定是线程函数哦! 只有线程函数return,线程才会退出
exit()是进程退出,如果在线程函数中调用exit,那改线程的进程也就挂了。。。。会导致该线程所在进程的其他线程也挂掉,比较严重

1、exit函数和return函数的主要区别是:

1)exit用于在程序运行的过程中随时结束程序,其参数是返回给OS的。也可以这么讲:exit函数是退出应用程序,并将应用程序的一个状态返回给OS,这个状态标识了应用程序的一些运行信息。

main函数结束时也会隐式地调用exit函数,exit函数运行时首先会执行由atexit()函数登记的函数,然后会做一些自身的清理工作,同时刷新所有输出流、关闭所有打开的流并且关闭通过标准I/O函数tmpfile()创建的临时文件。

exit是系统调用级别的,它表示了一个进程的结束,它将删除进程使用的内存空间,同时把错误信息返回父进程。通常情况:exit(0)表示程序正常, exit(1)和exit(-1)表示程序异常退出,exit(2)表示系统找不到指定的文件。在整个程序中,只要调用exit就结束。

  

2)return是语言级别的,它表示了调用堆栈的返回;return是返回函数值并退出函数,通常0为正常退出,非0为非正常退出,请注意,如果是在主函数main, 自然也就结束当前进程了(也就是说,在main()里面,你可以用return n,也能够直接用exit(n)来做),如果不是在main函数中,那就是退回上一层调用。在多个进程时,如果有时要检测上个进程是否正常退出,就要用到上个进程的返回值。

`pthread_cleanup_push` 和 `pthread_cleanup_pop` 是 POSIX 线程库提供的两个函数,用于在线程退出时清理资源。 具体来说,当线程执行到 `pthread_cleanup_push` 函数时,它会将一个清理函数和一个参数压入线程清理栈中。当线程退出时,无论是通过线程函数的 return 语句、pthread_exit 函数还是被取消,都会自动调用清理栈中的每个清理函数,并按照压入栈的顺序依次执行。 在多线程编程中,线程可能会因为各种原因(如出现异常)而异常终止,导致没有机会清理资源,从而造成资源泄漏或者其他问题。使用 `pthread_cleanup_push` 和 `pthread_cleanup_pop` 可以保证线程退出时一定会执行清理函数,避免这些问题。 下面是一个示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <pthread.h> void cleanup_handler(void *arg) { printf("cleanup: %s\n", (char *) arg); } void *thread_func(void *arg) { char *msg = (char *) arg; printf("thread: %s\n", msg); // 压入清理函数 pthread_cleanup_push(cleanup_handler, "thread is finished"); // 执行任务 sleep(5); // 弹出清理函数 pthread_cleanup_pop(1); pthread_exit(NULL); } int main() { pthread_t tid; int ret; ret = pthread_create(&tid, NULL, thread_func, "hello world"); if (ret != 0) { fprintf(stderr, "pthread_create error\n"); exit(EXIT_FAILURE); } // 等待线程退出 ret = pthread_join(tid, NULL); if (ret != 0) { fprintf(stderr, "pthread_join error\n"); exit(EXIT_FAILURE); } printf("main: thread is finished\n"); return 0; } ``` 在这个示例中,线程执行到 `pthread_cleanup_push` 函数时,它会将 `cleanup_handler` 函数和字符串 `"thread is finished"` 压入清理栈中。当线程执行完任务后,无论是正常退出还是被取消,都会自动调用 `cleanup_handler` 函数,并打印出 `"cleanup: thread is finished"` 的消息。 需要注意的是,如果在 `pthread_cleanup_push` 和 `pthread_cleanup_pop` 之间调用了 `pthread_exit`,那么清理函数也会被执行。但是如果在 `pthread_cleanup_push` 和 `pthread_cleanup_pop` 之间调用了 `longjmp`,那么清理函数就不会被执行。因此,不要在使用 `setjmp` 和 `longjmp` 的代码中使用 `pthread_cleanup_push` 和 `pthread_cleanup_pop`。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值