嵌入式Linux:注冊線程清理處理函數(shù)
在 Linux 多線程編程中,線程終止時可以執(zhí)行特定的清理操作,通過注冊線程清理函數(shù)(thread cleanup handler)來實現(xiàn)。
這類似于使用 atexit() 注冊進(jìn)程終止處理函數(shù)。
線程清理函數(shù)用于在線程退出時執(zhí)行一些資源釋放或清理工作,例如關(guān)閉文件描述符、釋放內(nèi)存等。
不同于進(jìn)程,線程可以注冊多個清理函數(shù),這些清理函數(shù)以棧的形式管理,棧是一種先進(jìn)后出的數(shù)據(jù)結(jié)構(gòu)。
因此,清理函數(shù)的執(zhí)行順序與注冊順序相反。
在 Linux 中,使用 pthread_cleanup_push() 和 pthread_cleanup_pop() 函數(shù)分別向線程的清理函數(shù)棧添加和移除清理函數(shù)。
其原型如下:
void pthread_cleanup_push(void (*routine)(void *), void *arg);void pthread_cleanup_pop(int execute);
參數(shù)說明:
pthread_cleanup_push():用于將清理函數(shù)推入棧中。
routine: 指向清理函數(shù)的函數(shù)指針,清理函數(shù)沒有返回值,并接受一個 void * 類型的參數(shù)。
arg: 傳遞給清理函數(shù)的參數(shù),當(dāng)清理函數(shù)執(zhí)行時,該參數(shù)作為 routine() 的輸入。
pthread_cleanup_pop():用于從清理函數(shù)棧中彈出最近添加的清理函數(shù)。
execute: 指定是否執(zhí)行清理函數(shù)。如果為 0,則只移除清理函數(shù)而不執(zhí)行它;如果為非 0,則不僅移除還會執(zhí)行清理函數(shù)。
線程清理函數(shù)執(zhí)行的場景:
當(dāng)線程調(diào)用 pthread_exit()退出時,清理函數(shù)會自動執(zhí)行。
當(dāng)線程響應(yīng)取消請求時(如通過 pthread_cancel()取消線程),清理函數(shù)會被執(zhí)行。
當(dāng)通過非 0 參數(shù)調(diào)用 pthread_cleanup_pop() 時,棧頂?shù)那謇砗瘮?shù)會被執(zhí)行。
以下代碼展示了如何使用 pthread_cleanup_push() 和 pthread_cleanup_pop() 注冊和移除清理函數(shù):
void cleanup(void *arg) { printf("Cleaning up: %s\n", (char *)arg); } void *thread_function(void *arg) { pthread_cleanup_push(cleanup, "Resource 1"); pthread_cleanup_push(cleanup, "Resource 2"); // 模擬線程工作 printf("Thread is running...\n"); // 調(diào)用pthread_exit()會觸發(fā)清理函數(shù)的執(zhí)行 pthread_exit(NULL); // 清理函數(shù)必須成對使用,因此即使退出后也要調(diào)用pthread_cleanup_pop pthread_cleanup_pop(1); pthread_cleanup_pop(1); } int main() { pthread_t thread; // 創(chuàng)建一個線程 if (pthread_create(&thread, NULL, thread_function, NULL) != 0) { perror("Failed to create thread"); return 1; } // 等待線程結(jié)束 pthread_join(thread, NULL); return 0; }
解釋說明:
線程中注冊了兩個清理函數(shù),分別為 "Resource 1" 和 "Resource 2"。
當(dāng)線程調(diào)用 pthread_exit() 時,棧中的清理函數(shù)按后進(jìn)先出的順序執(zhí)行,因此會先打印 "Cleaning up: Resource 2",再打印 "Cleaning up: Resource 1"。
注意事項:
pthread_cleanup_push() 和 pthread_cleanup_pop() 并不是普通函數(shù),而是宏實現(xiàn)的,必須在相同的作用域內(nèi)成對出現(xiàn),不能在代碼中分開使用。
清理函數(shù)只會在線程通過 pthread_exit() 或響應(yīng)取消請求時執(zhí)行。
如果線程通過 return 語句退出,清理函數(shù)不會被執(zhí)行。
通過使用 pthread_cleanup_push() 和 pthread_cleanup_pop(),可以確保在線程終止時執(zhí)行所需的清理操作,這在資源管理和異常處理中非常有用。
清理函數(shù)的自動執(zhí)行使得多線程編程中的資源釋放更加簡潔、安全。
*博客內(nèi)容為網(wǎng)友個人發(fā)布,僅代表博主個人觀點,如有侵權(quán)請聯(lián)系工作人員刪除。