分享

pthread lib

 海漩涡 2016-07-24
// 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;
}


================================================================




    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多