电子产业一站式赋能平台

PCB联盟网

帖子
查看: 174|回复: 0
收起左侧

嵌入式Linux:注册线程清理处理函数

[复制链接]

1028

主题

1028

帖子

9360

积分

高级会员

Rank: 5Rank: 5

积分
9360
发表于 2025-1-4 08:00:00 | 显示全部楼层 |阅读模式

1ojrheoo55t64060014359.gif

1ojrheoo55t64060014359.gif
7 e  A/ e$ B) T, u' z7 l
点击上方蓝色字体,关注我们! X) m$ A) U$ w, H7 n
这类似于使用 atexit() 注册进程终止处理函数。
* R) C7 F2 T# j
/ z5 g5 @9 d  U7 G线程清理函数用于在线程退出时执行一些资源释放或清理工作,例如关闭文件描述符、释放内存等。5 f& b! H" y9 E* Z1 M1 ]  h5 \8 y) |

2 A/ A, i) h; {不同于进程,线程可以注册多个清理函数,这些清理函数以栈的形式管理,栈是一种先进后出的数据结构。  i4 j. x' S; P! g+ y, E: H5 _

7 `: ~& \! J( {4 f6 ~$ I* }2 I0 g. z因此,清理函数的执行顺序与注册顺序相反。1 ?& Q# `5 X* O0 h
$ `6 M1 j! v# u' M5 \" f7 {
在 Linux 中,使用 pthread_cleanup_push() 和 pthread_cleanup_pop() 函数分别向线程的清理函数栈添加和移除清理函数。
+ @; |: ~; }6 |/ `: k. T) d5 d9 g4 R% x
其原型如下:
3 n$ G; K6 g# z. ]0 d8 w$ m) e  B0 p8 s
  • void pthread_cleanup_push(void (*routine)(void *), void *arg);void pthread_cleanup_pop(int execute);2 W" a  E6 U/ l3 S5 ]
    参数说明:
    / F( b8 |% H0 m4 J$ R
  • pthread_cleanup_push():用于将清理函数推入栈中。
    6 g% d$ W& p3 s9 |7 V4 l! o  K
  • routine: 指向清理函数的函数指针,清理函数没有返回值,并接受一个 void * 类型的参数。
  • arg: 传递给清理函数的参数,当清理函数执行时,该参数作为 routine() 的输入。
    ! y" Q4 Z3 p, j/ |. {
  • pthread_cleanup_pop():用于从清理函数栈中弹出最近添加的清理函数。
    : O6 _' ?7 u3 _- Y$ R  [6 i; h' f- ]
  • execute: 指定是否执行清理函数。如果为 0,则只移除清理函数而不执行它;如果为非 0,则不仅移除还会执行清理函数。9 s4 Q4 o0 n6 w0 I: n  P
    7 ]+ `8 Y' S. F- _5 d; l' U' S. M
    线程清理函数执行的场景:) ~5 q1 `: ]3 @4 K& q# d
  • 当线程调用 pthread_exit()退出时,清理函数会自动执行。
  • 当线程响应取消请求时(如通过 pthread_cancel()取消线程),清理函数会被执行。
  • 当通过非 0 参数调用 pthread_cleanup_pop() 时,栈顶的清理函数会被执行。! b' A+ j0 T6 S0 b6 m$ a

    + \" ^" `; h, w4 [以下代码展示了如何使用 pthread_cleanup_push() 和 pthread_cleanup_pop() 注册和移除清理函数:
    ( w2 B! j  F3 P( N8 s$ Q
    & c5 n: y1 L4 C6 R* j
  • void cleanup(void *arg) {    printf("Cleaning up: %s3 b' {. n8 q- s% C$ Z
    ", (char *)arg);}
      w3 T4 T  x; X1 j3 Yvoid *thread_function(void *arg) {    pthread_cleanup_push(cleanup, "Resource 1");    pthread_cleanup_push(cleanup, "Resource 2");
    : e: O$ c' I6 l! C2 c# X, M7 m    // 模拟线程工作    printf("Thread is running...
    7 i) `1 y( P: c0 j% {! [");
    4 }) g" v* K# V    // 调用pthread_exit()会触发清理函数的执行    pthread_exit(NULL);" s' S( [, h$ @) _" X  P% @6 ]
        // 清理函数必须成对使用,因此即使退出后也要调用pthread_cleanup_pop    pthread_cleanup_pop(1);    pthread_cleanup_pop(1);}% X$ i, e8 M1 H& _- g: H
    int main() {    pthread_t thread;$ D# D$ V+ U7 M& w
        // 创建一个线程    if (pthread_create(&thread, NULL, thread_function, NULL) != 0) {        perror("Failed to create thread");        return 1;    }
    . M, c* O6 g; G" v8 e    // 等待线程结束    pthread_join(thread, NULL);    return 0;}
    6 e: Z. T1 S; g) L5 c! L# ?解释说明:
    4 x& J# k& g4 a
  • 线程中注册了两个清理函数,分别为 "Resource 1" 和 "Resource 2"。
  • 当线程调用 pthread_exit() 时,栈中的清理函数按后进先出的顺序执行,因此会先打印 "Cleaning up: Resource 2",再打印 "Cleaning up: Resource 1"。) j1 `% l* X( J

      h7 r6 C5 D2 j8 ]! G, ?注意事项:* ~+ o6 E/ N% O; j( x
  • pthread_cleanup_push() 和 pthread_cleanup_pop() 并不是普通函数,而是宏实现的,必须在相同的作用域内成对出现,不能在代码中分开使用。
  • 清理函数只会在线程通过 pthread_exit() 或响应取消请求时执行。
    9 m% I) L3 ~; ^$ k如果线程通过 return 语句退出,清理函数不会被执行。
    : U  s+ M- G" J7 T3 x$ D

    4 Y9 B! ~- r4 h" {5 Q3 l; w; {通过使用 pthread_cleanup_push() 和 pthread_cleanup_pop(),可以确保在线程终止时执行所需的清理操作,这在资源管理和异常处理中非常有用。
    6 W3 _7 p& }* G2 Q. e* F/ }  |' E/ k6 [2 N
    清理函数的自动执行使得多线程编程中的资源释放更加简洁、安全。$ n# l' q7 R/ R

    55hzlbxh5tf64060014459.jpg

    55hzlbxh5tf64060014459.jpg

    $ B) H, Y0 Y5 l' F& j

    aib0uvoos3u64060014559.gif

    aib0uvoos3u64060014559.gif

    $ V# d4 i# B9 ?" B2 j2 u点击阅读原文,更精彩~
  • 回复

    使用道具 举报

    发表回复

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    关闭

    站长推荐


    联系客服 关注微信 下载APP 返回顶部 返回列表