// libthread.h #ifndef _LIBPTHREAD_H_ #define _LIBPTHREAD_H_ #include <pthread.h> #include <stdio.h> /* 线程相关功能函数 1、int pthread_join(pthread_t thread, void **retval); 阻塞到线程ID为thread的线程结束,并捕捉线程的pthread_exit()返回值到retval,线程默认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); 停止当前线程,并返回值retval此值被pthread_join捕获(thread must be joinable) 【注:retval不能为局部变量,否则pthread_exit捕获的是已经释放的值,出错】 3、int pthread_detach(pthread_t thread); 将线程设置为detach状态,当线程结束后自动释放资源。此时线程不能被pthread_join即为unjoinable 4、int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate); 设置线程创建时为detach还是joinable状态,此函数在pthread_create前 detachstate: PTHREAD_CREATE_DETACHED 线程创建的时候为detach状态 PTHREAD_CREATE_JOINABLE 线程创建的时候为joinable状态 【系统默认】 获得线程状态 int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate); 5、int pthread_cancel(pthread_t thread); 向某线程发送取消消息,即停止某线程。线程能否被取消取决于stat(默认enable)和type(默认deferred) 6、int pthread_setcancelstate(int state, int *oldstate); 设置当前线程是否可被pthread_cancel取消 PTHREAD_CANCEL_ENABLE 可被取消 【系统默认】 PTHREAD_CANCEL_DISABLE 不可 7、int pthread_setcanceltype(int type, int *oldtype); 设置当前线程被 pthread_cancel取消的类型 PTHREAD_CANCEL_DEFERRED 延期到调用下一个函数才cancel【系统默认】 PTHREAD_CANCEL_ASYNCHRONOUS 立即被取消 8、pthread_t pthread_self(void); 返回当前线程ID 9、在线程异常结束时用于释放资源(mutex、free等),防止内存泄漏和死锁 例被pthread_cancel、pthread_exit终止 将释放资源函数入栈 void pthread_cleanup_push(void (*routine)(void *),void *arg); routine:释放资源函数 arg:释放资源函数的参数 【注:arg可为局部变量,因为pthread_cleanup_pop会运行完routine】 将释放资源函数出栈 void pthread_cleanup_pop(int execute); execute: 0 ,不运行routine 。 其他,运行routine 10、设置和获取线程竞争资源的范围:整个系统,还是当前线程 int pthread_attr_setscope(pthread_attr_t *attr, int scope); scope: PTHREAD_SCOPE_SYSTEM 整个系统【系统默认】 PTHREAD_SCOPE_PROCESS 当前线程 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、设置线程栈大小 int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize); 获取线程栈大小 int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *stacksize); 13、其他不常用功能函数 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), */ /* 线程函数 */ 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 线程运行函数 3 : param 线程运行函数的参数 4 : scope 线程资源竞争范围 0,系统默认 1,与系统所有线程 2,与同一进程 5 : detach 线程状态: 0,系统默认 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) { /*表示与系统中所有线程一起竞争资源,如CPU时间*/ pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); } else if(2 == scope) { /*仅与同进程中的线程竞争资源*/ pthread_attr_setscope(&attr, PTHREAD_SCOPE_PROCESS); } if(1 == detach) { /* 线程能用pthread_join()来阻塞,系统默认PTHREAD_CREATE_JOINABLE状态*/ 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 /* 条件变量相关函数 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" /* 互斥变量相关函数 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 描述: 此类型的互斥锁不会检测死锁。如果线程在不首先解除互斥锁的情况下尝试 重新锁定该互斥锁,则会产生死锁。尝试解除由其他线程锁定的互斥锁会产生不确 定的行为。如果尝试解除锁定的互斥锁未锁定,则会产生不确定的行为。 (2)PTHREAD_MUTEX_ERRORCHECK 此类型的互斥锁可提供错误检查。如果线程在不首先解除锁定互斥锁的情况下尝试 重新锁定该互斥锁,则会返回错误。如果线程尝试解除锁定的互斥锁已经由其他线 程锁定,则会返回错误。如果线程尝试解除锁定的互斥锁未锁定,则会返回错误。 (3)PTHREAD_MUTEX_RECURSIVE 如果线程在不首先解除锁定互斥锁的情况下尝试重新锁定该互斥锁,则可成功锁 定该互斥锁。 与 PTHREAD_MUTEX_NORMAL 类型的互斥锁不同,对此类型互斥锁进 行重新锁定时不会产生死锁情况。多次锁定互斥锁需要进行相同次数的解除锁定才 可以释放该锁,然后其他线程才能获取该互斥锁。如果线程尝试解除锁定的互斥锁 已经由其他线程锁定,则会返回错误。 如果线程尝试解除锁定的互斥锁未锁定, 则会返回错误。 (4)PTHREAD_MUTEX_DEFAULT 如果尝试以递归方式锁定此类型的互斥锁,则会产生不确定的行为。对于不是由调 用线程锁定的此类型互斥锁,如果尝试对它解除锁定,则会产生不确定的行为。对 于尚未锁定的此类型互斥锁,如果尝试对它解除锁定,也会产生不确定的行为。允 许在实现中将该互斥锁映射到其他互斥锁类型之一。对于 Solaris 线程, PTHREAD_PROCESS_DEFAULT 会映射到 PTHREAD_PROCESS_NORMAL。 pthread_mutexattr_settype 返回值 如果运行成功,pthread_mutexattr_settype 函数会返回零。否则,将返回用于指明错误的错误号。 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、 设置互斥锁范围 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); 设置互斥锁的类型属性 pthread_mutexattr_settype 语法 获取互斥锁的类型属性 pthread_mutexattr_gettype 语法 设置互斥锁属性的协议 pthread_mutexattr_setprotocol 语法 获取互斥锁属性的协议 pthread_mutexattr_getprotocol 语法 设置互斥锁属性的优先级上限 pthread_mutexattr_setprioceiling 语法 获取互斥锁属性的优先级上限 pthread_mutexattr_getprioceiling 语法 设置互斥锁的优先级上限 pthread_mutex_setprioceiling 语法 获取互斥锁的优先级上限 pthread_mutex_getprioceiling 语法 设置互斥锁的强健属性 pthread_mutexattr_setrobust_np 语法 获取互斥锁的强健属性 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. 信号量管理结构体 2. pshared 0,信号量作用域进程 非0,作用域为所有进程 3. 信号量的初始值 */ int init_semaphore(lib_sema *p_lib_sema, int pshared, unsigned int value); #endif ================================================================== // semaphore.c #include "libsemaphore.h" /* #include <semaphore.h> 信号量相关函数 1、int sem_init(sem_t *sem, int pshared, unsigned int value); pshared: 0,信号量作用范围是进程 非0,作用范围是所有进程 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,阻塞线程当超过abs_timeout的时间,进程继续运行, 信号量的值还是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); 获得当前信号量值 注:当信号量为0时,用此函数会有点问题,我再用sem_timedwait产生段错误 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,信号量作用域进程 非0,作用域为所有进程 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; } ================================================================ |
|