// libthread.h #ifndef _LIBPTHREAD_H_ #define _LIBPTHREAD_H_ #include <pthread.h> #include <stdio.h> /* 線程相關(guān)功能函數(shù) 1、int pthread_join(pthread_t thread, void **retval); 阻塞到線程ID為thread的線程結(jié)束,并捕捉線程的pthread_exit()返回值到retval,線程默認(rèn)joinable The pthread_join() function waits for the thread specified by thread to terminate. If that thread has already terminated, then pthread_join() returns immediately. The thread specified by thread must be joinable. 2、void pthread_exit(void *retval); 停止當(dāng)前線程,并返回值retval此值被pthread_join捕獲(thread must be joinable) 【注:retval不能為局部變量,否則pthread_exit捕獲的是已經(jīng)釋放的值,出錯】 3、int pthread_detach(pthread_t thread); 將線程設(shè)置為detach狀態(tài),當(dāng)線程結(jié)束后自動釋放資源。此時線程不能被pthread_join即為unjoinable 4、int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate); 設(shè)置線程創(chuàng)建時為detach還是joinable狀態(tài),此函數(shù)在pthread_create前 detachstate: PTHREAD_CREATE_DETACHED 線程創(chuàng)建的時候為detach狀態(tài) PTHREAD_CREATE_JOINABLE 線程創(chuàng)建的時候為joinable狀態(tài) 【系統(tǒng)默認(rèn)】 獲得線程狀態(tài) int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate); 5、int pthread_cancel(pthread_t thread); 向某線程發(fā)送取消消息,即停止某線程。線程能否被取消取決于stat(默認(rèn)enable)和type(默認(rèn)deferred) 6、int pthread_setcancelstate(int state, int *oldstate); 設(shè)置當(dāng)前線程是否可被pthread_cancel取消 PTHREAD_CANCEL_ENABLE 可被取消 【系統(tǒng)默認(rèn)】 PTHREAD_CANCEL_DISABLE 不可 7、int pthread_setcanceltype(int type, int *oldtype); 設(shè)置當(dāng)前線程被 pthread_cancel取消的類型 PTHREAD_CANCEL_DEFERRED 延期到調(diào)用下一個函數(shù)才cancel【系統(tǒng)默認(rèn)】 PTHREAD_CANCEL_ASYNCHRONOUS 立即被取消 8、pthread_t pthread_self(void); 返回當(dāng)前線程ID 9、在線程異常結(jié)束時用于釋放資源(mutex、free等),防止內(nèi)存泄漏和死鎖 例被pthread_cancel、pthread_exit終止 將釋放資源函數(shù)入棧 void pthread_cleanup_push(void (*routine)(void *),void *arg); routine:釋放資源函數(shù) arg:釋放資源函數(shù)的參數(shù) 【注:arg可為局部變量,因為pthread_cleanup_pop會運行完routine】 將釋放資源函數(shù)出棧 void pthread_cleanup_pop(int execute); execute: 0 ,不運行routine 。 其他,運行routine 10、設(shè)置和獲取線程競爭資源的范圍:整個系統(tǒng),還是當(dāng)前線程 int pthread_attr_setscope(pthread_attr_t *attr, int scope); scope: PTHREAD_SCOPE_SYSTEM 整個系統(tǒng)【系統(tǒng)默認(rèn)】 PTHREAD_SCOPE_PROCESS 當(dāng)前線程 int pthread_attr_getscope(pthread_attr_t *attr, int *scope); 11、線程屬性: pthread_attr_t attr; 初始化線程屬性,給pthread_attr_setscope、pthread_attr_setdetachstate等使用 然后在pthread_creat后生效 int pthread_attr_init(pthread_attr_t *attr); 銷毀此屬性變量,不會改變線程的任何屬性,不會對線程的運行有任何影響 int pthread_attr_destroy(pthread_attr_t *attr); 12、設(shè)置線程棧大小 int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize); 獲取線程棧大小 int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *stacksize); 13、其他不常用功能函數(shù) int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy); int pthread_attr_getschedpolicy(pthread_attr_t *attr, int *policy); pthread_testcancel(3), pthread_attr_setaffinity_np(3), pthread_attr_setinheritsched(3), pthread_attr_setschedparam(3), pthread_attr_setschedpolicy(3), */ /* 線程函數(shù) */ typedef void *(*FuncRouteThread)(void *); int CreateRouteThread(pthread_t *thread,FuncRouteThread route, void *param, int scope, int detach); #endif ================================================================= // libpthread.c #include "libpthread.h" /* parameter: OUT: 1 : pthread_t 線程ID INPUT: 2 : route 線程運行函數(shù) 3 : param 線程運行函數(shù)的參數(shù) 4 : scope 線程資源競爭范圍 0,系統(tǒng)默認(rèn) 1,與系統(tǒng)所有線程 2,與同一進(jìn)程 5 : detach 線程狀態(tài): 0,系統(tǒng)默認(rèn) 1,joinable 2,detach */ int CreateRouteThread(pthread_t *thread,FuncRouteThread route, void *param, int scope, int detach) { int ret = -1; pthread_attr_t attr; pthread_attr_init(&attr); if(1 == scope) { /*表示與系統(tǒng)中所有線程一起競爭資源,如CPU時間*/ pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); } else if(2 == scope) { /*僅與同進(jìn)程中的線程競爭資源*/ pthread_attr_setscope(&attr, PTHREAD_SCOPE_PROCESS); } if(1 == detach) { /* 線程能用pthread_join()來阻塞,系統(tǒng)默認(rèn)PTHREAD_CREATE_JOINABLE狀態(tài)*/ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); } else if(2 == detach) { /*線程不能用pthread_join()來阻塞,在退出時自行釋放所占用的資源*/ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); } ret = pthread_create(thread, &attr, route, param); /* Destroying a thread attributes object has no effect on threads that were created using that object. 不需要改變線程屬性后destroy,此時對線程的運行無影響 */ pthread_attr_destroy(&attr); return ret; } ================================================================== // lib pthread cond /* 條件變量相關(guān)函數(shù) pthread_cond_t pthread_cond_init pthread_cond_wait pthread_cond_signal pthread_cond_timewait int pthread_cond_broadcast(pthread_cond_t *cv); */ ============================================================== // libmutex.h #ifndef _LIBMUTEX_H_ #define _LIBMUTEX_H_ #include <pthread.h> #include <stdio.h> #include <errno.h> typedef void *(* mutexFunc)(void *); typedef void *(* mutexFunc2)(void *, void *); typedef struct mutex{ pthread_nutex_t bin_mutex; func lib_pthread_mutex_lock; func lib_pthread_mutex_trylock; func lib_pthread_mutex_unlock; func lib_pthread_mutex_destroy; }lib_mutex; #endif ============================================================== // libmutex.c #include "libmutex.h" /* 互斥變量相關(guān)函數(shù) 1、int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr); pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 2、int pthread_mutex_lock(pthread_mutex_t *mutex); (1)PTHREAD_MUTEX_NORMAL 描述: 此類型的互斥鎖不會檢測死鎖。如果線程在不首先解除互斥鎖的情況下嘗試 重新鎖定該互斥鎖,則會產(chǎn)生死鎖。嘗試解除由其他線程鎖定的互斥鎖會產(chǎn)生不確 定的行為。如果嘗試解除鎖定的互斥鎖未鎖定,則會產(chǎn)生不確定的行為。 (2)PTHREAD_MUTEX_ERRORCHECK 此類型的互斥鎖可提供錯誤檢查。如果線程在不首先解除鎖定互斥鎖的情況下嘗試 重新鎖定該互斥鎖,則會返回錯誤。如果線程嘗試解除鎖定的互斥鎖已經(jīng)由其他線 程鎖定,則會返回錯誤。如果線程嘗試解除鎖定的互斥鎖未鎖定,則會返回錯誤。 (3)PTHREAD_MUTEX_RECURSIVE 如果線程在不首先解除鎖定互斥鎖的情況下嘗試重新鎖定該互斥鎖,則可成功鎖 定該互斥鎖。 與 PTHREAD_MUTEX_NORMAL 類型的互斥鎖不同,對此類型互斥鎖進(jìn) 行重新鎖定時不會產(chǎn)生死鎖情況。多次鎖定互斥鎖需要進(jìn)行相同次數(shù)的解除鎖定才 可以釋放該鎖,然后其他線程才能獲取該互斥鎖。如果線程嘗試解除鎖定的互斥鎖 已經(jīng)由其他線程鎖定,則會返回錯誤。 如果線程嘗試解除鎖定的互斥鎖未鎖定, 則會返回錯誤。 (4)PTHREAD_MUTEX_DEFAULT 如果嘗試以遞歸方式鎖定此類型的互斥鎖,則會產(chǎn)生不確定的行為。對于不是由調(diào) 用線程鎖定的此類型互斥鎖,如果嘗試對它解除鎖定,則會產(chǎn)生不確定的行為。對 于尚未鎖定的此類型互斥鎖,如果嘗試對它解除鎖定,也會產(chǎn)生不確定的行為。允 許在實現(xiàn)中將該互斥鎖映射到其他互斥鎖類型之一。對于 Solaris 線程, PTHREAD_PROCESS_DEFAULT 會映射到 PTHREAD_PROCESS_NORMAL。 pthread_mutexattr_settype 返回值 如果運行成功,pthread_mutexattr_settype 函數(shù)會返回零。否則,將返回用于指明錯誤的錯誤號。 3、int pthread_mutex_trylock(pthread_mutex_t *mutex); 4、int pthread_mutex_unlock(pthread_mutex_t *mutex); 5、int pthread_mutex_destroy(pthread_mutex_t *mutex); 6、 設(shè)置互斥鎖范圍 pthread_mutexattr_setpshared 語法 獲取互斥鎖范圍 pthread_mutexattr_getpshared 語法 int pthread_mutexattr_getpshared(const pthread_mutexattr_t * restrict attr, int *restrict pshared); int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared); 設(shè)置互斥鎖的類型屬性 pthread_mutexattr_settype 語法 獲取互斥鎖的類型屬性 pthread_mutexattr_gettype 語法 設(shè)置互斥鎖屬性的協(xié)議 pthread_mutexattr_setprotocol 語法 獲取互斥鎖屬性的協(xié)議 pthread_mutexattr_getprotocol 語法 設(shè)置互斥鎖屬性的優(yōu)先級上限 pthread_mutexattr_setprioceiling 語法 獲取互斥鎖屬性的優(yōu)先級上限 pthread_mutexattr_getprioceiling 語法 設(shè)置互斥鎖的優(yōu)先級上限 pthread_mutex_setprioceiling 語法 獲取互斥鎖的優(yōu)先級上限 pthread_mutex_getprioceiling 語法 設(shè)置互斥鎖的強(qiáng)健屬性 pthread_mutexattr_setrobust_np 語法 獲取互斥鎖的強(qiáng)健屬性 pthread_mutexattr_getrobust_np 語法 */ ================================================================= // semaphore.h #ifndef _LIBSEMAPHORE_H_ #define _LIBSEMAPHORE_H_ #include <semaphore.h> #include <stdio.h> #include <errno.h> typedef void *(* func)(void *); typedef void *(* func2)(void *, void *); typedef struct sema{ sem_t bin_sem; func lib_sem_wait; func lib_sem_trywait; func2 lib_sem_timedwait; func lib_sem_post; func lib_sem_destory; }lib_sema; /* param 1. 信號量管理結(jié)構(gòu)體 2. pshared 0,信號量作用域進(jìn)程 非0,作用域為所有進(jìn)程 3. 信號量的初始值 */ int init_semaphore(lib_sema *p_lib_sema, int pshared, unsigned int value); #endif ================================================================== // semaphore.c #include "libsemaphore.h" /* #include <semaphore.h> 信號量相關(guān)函數(shù) 1、int sem_init(sem_t *sem, int pshared, unsigned int value); pshared: 0,信號量作用范圍是進(jìn)程 非0,作用范圍是所有進(jìn)程 2、int sem_wait(sem_t *sem); 信號量值大于0,減1返回。小于0,阻塞線程。 3、int sem_trywait(sem_t *sem); 信號量值大于0,減1返回。小于0,不阻塞線程,返回error 4、int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout); 信號量值大于0,減1返回。等于0,阻塞線程當(dāng)超過abs_timeout的時間,進(jìn)程繼續(xù)運行, 信號量的值還是0時。 struct timespec { time_t tv_sec; // Seconds long tv_nsec; // Nanoseconds [0 .. 999999999] }; 5、int sem_destroy(sem_t *sem); 銷毀一個信號量 6、int sem_getvalue(sem_t *sem, int *sval); 獲得當(dāng)前信號量值 注:當(dāng)信號量為0時,用此函數(shù)會有點問題,我再用sem_timedwait產(chǎn)生段錯誤 7、sem_open 8、sem_unlink 9、sem_close */ int lib_sem_wait_(lib_sema *p_lib_sema) { int ret; ret = sem_wait(&p_lib_sema->bin_sem); if(ret!=0) { printf("sem_wait error [%s]\n",strerror(ret)); return -1; } return 0; } int lib_sem_trywait_(lib_sema *p_lib_sema) { int ret; ret = sem_trywait(&p_lib_sema->bin_sem); if(ret!=0) { printf("sem_trywait error [%s]\n",strerror(ret)); return -1; } return 0; } int lib_sem_timedwait_(lib_sema *p_lib_sema, struct timespec *abs_timeout) { int ret; ret = sem_timedwait(&p_lib_sema->bin_sem, abs_timeout); if(ret!=0) { printf("sem_timedwait error [%s]\n",strerror(ret)); return -1; } return 0; } int lib_sem_post_(lib_sema *p_lib_sema) { int ret; ret = sem_post(&p_lib_sema->bin_sem); if(ret!=0) { printf("sem_post error [%s]\n",strerror(ret)); return -1; } return 0; } int lib_sem_destroy_(lib_sema *p_lib_sema) { int ret; ret = sem_destroy(&p_lib_sema->bin_sem); if(ret!=0) { printf("sem_post error [%s]\n",strerror(ret)); return -1; } return 0; } /* param 1. 2. pshared 0,信號量作用域進(jìn)程 非0,作用域為所有進(jìn)程 3. 信號量的初始值 */ int init_semaphore(lib_sema *p_lib_sema, int pshared, unsigned int value) { int ret = -1; ret = sem_init(&(p_lib_sema->bin_sem), pshared, value); if(-1 == ret) { printf("sem_init error [%s]\n", strerror(errno)); return -1; } p_lib_sema->lib_sem_wait = (func )lib_sem_wait_; p_lib_sema->lib_sem_trywait = (func )lib_sem_trywait_; p_lib_sema->lib_sem_timedwait = (func2 )lib_sem_timedwait_; p_lib_sema->lib_sem_post = (func )lib_sem_post_; p_lib_sema->lib_sem_destory = (func )lib_sem_destroy_; return 0; } ================================================================ |
|