#include <stdio.h>#include <pthread.h>#include <sched.h>#include <errno.h> /*ESRCH*/#define MINI_STACK_SIZE (0x20000)#define MINI_PRIORITY (66)#define RET_OK (0)#define RET_ERR (-1)/*線程管理結構 -- ID與名字映射,方便從名字找到對應線程*/#define THREAD_NAME_LEN (10)typedef struct{ char thread_name[THREAD_NAME_LEN]; pthread_t thread_id;}THREAD_MGR_s;typedef void (*THREAD_FUNC)(void *param);/********************************************************************************** 局部函式宣告 **********************************************************************************/int add_thread(const char *name, const pthread_t id);int thread_alive(const pthread_t thread_id);int thread_destroy(pthread_t thread_id);/********************************************************************************** 局部函數定義 *********************************************************************************//* *建立線程, *成功返回 > 0 值 *線程屬性主要設定: - 調度策略, - 是否綁定, - 是否分離, - 堆棧大小, - 線程優先順序 */pthread_t thread_create(int stack_size, int priority, int detach, THREAD_FUNC func, const char *name){ pthread_t thread_id; pthread_attr_t attr; struct sched_param schedparam; int ret; /*線程初始化 -- 0為成功*/ ret = pthread_attr_init(&attr); /* 設定調度策略 -- 0為成功 SCHED_OTHER 預設 SCHED_FIFO 先進先出 SCHED_RR 輪轉 */ ret |= pthread_attr_setschedpolicy(&attr, SCHED_RR); /* 設定線程綁定狀態 -- 0為成功 綁定 PTHREAD_SCOPE_SYSTEM 預設 -- 高效線程切換方式 非綁定 PTHREAD_SCOPE_PROCESS 無法設定 線程的調度是面向輕量級線程的,非綁定時,一個輕量線線程對應使用者態下 多個線程;綁定狀態下,一個使用者線程綁定於一個輕量級線程,CPU切換線程 時無需尋找空閑輕量級線程綁定,直接切換,相對於非綁定線程,切換時間減 少 */ ret |= pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); /*設定線程是否分離 -- 0為成功 分離線程 PTHREAD_CREATE_DETACHED - 如果建立分離線程 (PTHREAD_CREATE_DETACHED),則該線程一退出,便可重用 - 其線程 ID 和其他資源。 非分離線程 PTHREAD_CREATE_JOINABLE - 非分離線程在終止後,必須要有一個線程用 join 來等待它。否則,不會釋放 - 該線程的資源以供新線程使用,而這通常會導致記憶體流失。因此,如果不希望 - 線程被等待,請將該線程作為分離線程來建立。 - 需要調用pthread_join(pthread_t thread_id, (void *)ret);等待後線程退出 後的線程ID和其他資源才被釋放(如:fork -- wait 相同) */#if 1 if (0 != detach) { ret |= pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); } else { ret |= pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); }#endif if (MINI_STACK_SIZE > stack_size) { stack_size = MINI_STACK_SIZE; } /*設定線程堆棧大小 -- 0為成功*/ ret |= pthread_attr_setstacksize(&attr, stack_size); /*設定線程優先順序 -- 0為成功*/ schedparam.__sched_priority = priority + MINI_PRIORITY; ret |= pthread_attr_setschedparam(&attr, &schedparam); if (0 != ret) { printf("0 != ret\n"); goto LAB_ERR; } /*線程建立*/ ret = pthread_create(&thread_id, &attr, (void *)func, NULL); if (0 != ret) { printf("pthread_create error\n"); goto LAB_ERR; }#if 0 if (0 != detach) { /*調用者調用pthread_join(pthread_id)後,如果該線程沒有運行結束,調用者會被阻塞*/ ret |= pthread_detach(thread_id); }#endif ret |= add_thread(name, thread_id); if (0 != ret) { thread_destroy(thread_id); goto LAB_ERR; } printf("thread create ok, id = [%lu]\n", (unsigned long int)thread_id);LAB_OK: return (thread_id);LAB_ERR: return (RET_ERR);}/*查看線程是否還存在*/int thread_alive(const pthread_t thread_id){ int ret; ret = pthread_kill(thread_id, 0); if (ESRCH == ret) { printf("thread(%lu) not exit\n", thread_id); goto LAB_ERR; } else if (EINVAL == ret) { printf("signal not legal\n"); goto LAB_ERR; } else { printf("thread alive\n"); } return (RET_OK);LAB_ERR: return (RET_ERR);}int thread_destroy(pthread_t thread_id){ int ret; /* 注意: pthread_kill是向一個線程發送signal訊號,如果線程不存在或不安裝signal處理handle, 那這個signal將會轉向進程進行處理,如果發送pthread_kill(thread_id, SIGKILL),線程 也沒有安裝signal處理handle,那麼整個程式就會退出.發送pthread_kill(thread_id, 0), signal = 0為保留值,只是用於測試線程是否退出. 0:成功 ESRCH:不存在或退出 EINVAL:訊號不合法 */ if (RET_OK == thread_alive(thread_id)) { /*線程還在運行之中*/ printf("thread(%lu) is alive\n", thread_id); /*終止線程運行,pthread_cancel函數的功能是給線程發送取消訊號,使線程從取消點退出. 0:成功,成功並不代表thread會終止 */ ret = pthread_cancel(thread_id); if (0 == ret) { printf("send thread cancel ok\n"); } else { printf("send thread cancel error\n"); goto LAB_ERR; } } printf("thread destroy ok\n"); return RET_OK;LAB_ERR: return RET_ERR;}/*線程執行函數*/static void thread_func(void *param){ int sleep_tm_count = 0; printf("start func now!\n"); while (10 >= sleep_tm_count++) { sleep(1); } printf("thread fun exit\n");}int main(int argc, char *argv[]){ const char thread_name[] = "one"; pthread_t thread_id; unsigned char detach_flag = 0; detach_flag = 1; if (2 == argc) { detach_flag = atoi(argv[0]); } thread_id = thread_create(0x20000, 10, detach_flag, (THREAD_FUNC)thread_func, thread_name); if (RET_ERR == thread_id) { printf("thread create error\n"); } else { printf("pthread join now\n"); pthread_join(thread_id, NULL); printf("pthread join out\n"); }#if 0 printf("go to sleep now\n"); sleep(-1);#else printf("exit process now\n");#endif return 0;}/***************************** 線程管理函數 start********************************** *設計思想: ****************************** 線程管理函數 end **********************************//*添加新線程到線程管理結構*/ int add_thread(const char *name, const pthread_t id) { return (RET_OK);LAB_ERR: return (RET_ERR); }
gcc ./test.c -lpthread -g -o test.elf
root@ubuntu:/home/libz/share/project/gdb-test# gdb ./test.elf -q
Reading symbols from /home/libz/share/project/gdb-test/test.elf...done.
(gdb) set args 0
(gdb) r
Starting program: /home/libz/share/project/gdb-test/test.elf 0
[Thread debugging using libthread_db enabled]
[New Thread 0xb7feab70 (LWP 5174)]
thread create ok, id = [3086920560]
pthread join now
start func now!