// 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;
}
================================================================