pthread函数

内容:POSIX Threads 和 Language Features

1. 创建一个 thread

int pthread_create (pthread_t * thread, pthread_attr_t * attr, void * (*start_routine)(void *), void * arg)
而从一个 thread 中返回,可以用 return,也可以用
void pthread_exit (void *retval)
而返回的 retval 可以在该 thread 为 JOINABLE 时,被一个 join 的 thread 获得。该函数会调用
一个 thread 的 cleanup handlers。
int pthread_cancel (pthread_t thread)
会 cancel 掉一个 thread。
int pthread_join (pthread_t th, void **thread_return)
使一个 thread 挂起,直到 th 返回或者 cancel 掉。一个线程只能被 join 一次。
一个 thread 的性质由 pthread_attr_t 类型决定,可以为
int pthread_attr_init (pthread_attr_t *attr)
初始化(默认的类型),
int pthread_attr_destroy (pthread_attr_t *attr)
销毁,函数
int pthread_attr_setattr (pthread_attr_t *obj, int value)
int pthread_attr_getattr (const pthread_attr_t *obj, int *value)
用于设置和获取。其中如该线程是否 detatch,PTHREAD_CREATE_JOINABLE(返回后等待 join)
或者 PTHREAD_CREATE_DETACHED(返回后即释放相关资源);schedule 的方式,
SCHED_OTHER(一般,非实时)或者 SCHED_RR(实时,round robin)、SCHED_FIFO
(实时,先到先服务);schedule 的参数(在后面两种情况下表示优先级);是否继承创建线程的
schedule 参数,PTHREAD_EXPLICIT_SCHED(不继承,显式说明)或者 PTHREAD_INHERIT_SCHED
(继承);竞争范围,PTHREAD_SCOPE_SYSTEM(与其他进程一起),PTHREAD_SCOPE_PROCESS
(同进程间线程之间进行,Linux 下不支持);stack 地址,该 stack 必需有至少 PTHREAD_STACK_MIN 大;
stack 的大小;为了避免 stack 溢出设置的 guard area 大小。
函数
int pthread_setcancelstate (int state, int *oldstate)
设置一个 thread 的 cancel state,可以为 PTHREAD_CANCEL_ENABLE(允许别的线程 cancel)或者
PTHREAD_CANCEL_DISABLE(不允许)。
int pthread_setcanceltype (int type, int *oldtype)
设置 cancel type,PTHREAD_CANCEL_ASYNCHRONOUS(收到 cancel 立即执行),
PTHREAD_CANCEL_DEFERRED 推迟 cancel 直到 cancellation point,这些points 可以是:使得
线程处于等待状态(wait、join、sleep 等),或者是 I/O 时,如 accept、read 等。而
void pthread_testcancel (void)
将测试是否有 cancellation 的 request,如果有就 cancel。
为了在线程终结时释放一些东西,如 mutex 等,需要为其设置 cleanup handlers,如
void pthread_cleanup_push (void (*routine) (void *), void *arg)
可以用
void pthread_cleanup_pop (int execute)
将设置的 handler 移出执行( excute 非零)或者不执行(excute 为 0)。另外还有
void pthread_cleanup_push_defer_np (void (*routine) (void *), void *arg)
void pthread_cleanup_pop_restore_np (int execute)
是为了确保在 defer cancellation 下执行 handler。
2. 为了实现线程之间的同步,glibc 提供了一些有用的东西,如 mutex、semaphore
(和 Sys V IPC 的不一样)、condition variable。
可以用函数
int pthread_mutex_init (pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr)
初始化一个 mutex,或者用 PTHREAD_MUTEX_INITIALIZER(timed)、
PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP(recursive,锁多少次就得打开多少次)、
PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP(fast,用户自己保证正确性)、
PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP(error check,检查权限是否锁上)。
函数
int pthread_mutex_lock (pthread_mutex_t *mutex)
执行锁上,如果没锁上就锁上;若被自己锁上,则如 fast 类型产生死锁,如 error check 产生错误,
recursive 再锁一遍;若被别人锁上就等待开锁。
int pthread_mutex_trylock (pthread_mutex_t *mutex)
尝试上锁,但是不成功不会挂起等待。
int pthread_mutex_timedlock (pthread_mutex_t *mutex, const struct timespec *abstime)
超时不候型。函数
int pthread_mutex_unlock (pthread_mutex_t *mutex)
进行解锁,如 fast 则不管是谁锁上的都打开,recursive 是打开一次直到 unlock 为止,error check
会检查是谁锁的。
int pthread_mutex_destroy (pthread_mutex_t *mutex)
释放 mutex 的资源。
mutex 的性质可以用 pthread_mutexattr_t 表示,函数
int pthread_mutexattr_init (pthread_mutexattr_t *attr)
进行初始化,
int pthread_mutexattr_destroy (pthread_mutexattr_t *attr)
进行释放。通过
int pthread_mutexattr_settype (pthread_mutexattr_t *attr, int type)
int pthread_mutexattr_gettype (const pthread_mutexattr_t *attr, int *type)
进行设置和获取,只有 PTHREAD_MUTEX_ADAPTIVE_NP(fast)、PTHREAD_MUTEX_RECURSIVE_NP
(recursive)、PTHREAD_MUTEX_TIMED_NP(timed)、PTHREAD_MUTEX_ERRORCHECK_NP
(error check)这几种。
condition variable 是一个可以让其他线程等待某个事情发生的信号,
要和 mutex 一起使用才能避免一些异常。函数
int pthread_cond_init (pthread_cond_t *cond, pthread_condattr_t *cond_attr)
进行初始化,而
int pthread_cond_signal (pthread_cond_t *cond)
就是对该 condition vairable 进行一次信号的触发,只有一个在监视的线程可以获取,如果
希望都获得,则
int pthread_cond_broadcast (pthread_cond_t *cond)
一般调用
int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)
int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)
进行监控,其中的 mutex 是如下作用,防止在 wait 之前该 signal 被触发,此时再去 wait 就
无效了,因此,调用 wait 的 thread 首先应该 lock 这个 mutex,通过 wait 首先自动会 unlock
此 mutex,然后进入挂起,一旦 wait 获得 signal 又会 lock 该 mutex,因此之后注意记得 unlock
该 mutex。而 signal 的发出者应该在发出之前首先 lock 该 mutex(这样防止 wait 的 thread 尚未就绪),
然后才能发出信号。函数
int pthread_cond_destroy (pthread_cond_t *cond)
将释放 condition variable。虽然 condition variable 也有性质,但是 glibc 的并没有实现,但是仍然提供了
两个空函数
int pthread_condattr_init (pthread_condattr_t *attr)
int pthread_condattr_destroy (pthread_condattr_t *attr)

semaphore 是一个公用的变量,每个线程都可以改变其值或者等待。函数
int sem_init (sem_t *sem, int pshared, unsigned int value)
将初始化一个 semaphore,其中 pshared 表明是否在进程间共享,value 是初始的 semaphore 值。
int sem_destroy (sem_t * sem)
将释放资源。
int sem_wait (sem_t * sem)
等待直到 semaphore 非零,并且从 semaphore 上减 1,而
int sem_trywait (sem_t * sem)
仅仅测试,如非零则执行,否则返回 -1。
int sem_post (sem_t * sem)
将增加 semaphore。
int sem_getvalue (sem_t * sem, int * sval)
获取 semaphore 的值。
3. 线程由于共享进程的地址空间,因此如全局变量都是共享的,为了每个线程享有一些私有的数据,
则可以通过
int pthread_key_create (pthread_key_t *key, void (*destr_function) (void *))
创建,其中 key 将存放获取该区域内存地址的信息,最多可以有 PTHREAD_KEYS_MAX 个,而
int pthread_key_delete (pthread_key_t key)
将删除之,调用 destr_function,
int pthread_setspecific (pthread_key_t key, const void *pointer)
将指明储存的区域。
信号与 thread 如果需要混用特别需要注意,可以为每个线程设置 signal 的掩膜,如
int pthread_sigmask (int how, const sigset_t *newmask, sigset_t *oldmask)
同时,在主线程中设置好的 mask 可以保留在各个子线程中(当然是先设置掩膜,再创建线程)。
注意处理 signal 的线程或者安装了对应的 handler 否则一般都会忽略,且仅仅会有一个
线程处理这个 signal,其余的线程都不会接收到。函数
int sigwait (const sigset_t *set, int *sig)
将线程挂起等待某个 signal,将该 signal 存在 sig 中并返回。这个函数无视掩膜。函数
int pthread_kill (pthread_t thread, int signo)
可以向特定线程发送 signal。
将 thread 和 fork 混用时注意,新的 child process 不会继承 parent 的线程,理论上应该是
调用 fork 的线程的副本(Linux 中线程当作进程管理的)。
int pthread_atfork (void (*prepare)(void), void (*parent)(void), void (*child)(void))
可以在调用 fork 产生 child 之间执行 prepare,产生 child process 之后 parent process 执行 parent、
child process 执行 child。并且可以累次增加这些 handler。为了避免产生不完整的数据的拷贝,
如进行某些非原子级操作,需要利用 mutex 避免。
4. 这里是一些相关的函数,
pthread_t pthread_self (void)
返回本线程的 pthread_t 编号,
int pthread_equal (pthread_t thread1, pthread_t thread2)
测试是否相同的 thread,
int pthread_detach (pthread_t th)
将 th 变成 detach 的类型,不可 join,
void pthread_kill_other_threads_np (void)
杀掉所有其他线程,
int pthread_once (pthread_once_t *once_control, void (*init_routine) (void))
保证代码仅仅被执行过一次,
int pthread_setschedparam (pthread_t target_thread, int policy, const struct sched_param *param)
int pthread_getschedparam (pthread_t target_thread, int *policy, struct sched_param *param)
设置/获得 schedule 参数,
int pthread_setconcurrency (int level)
int pthread_getconcurrency ()
在 Linux 中没有实际效果。
5. 多使用 assert 可以帮助诊断程序,通过 NDEBUG 就可以忽略该宏。
void assert (int expression)
preprocessor 会产生 __FILE__、__LINE__、__PRETTY_FUNCTION__对应的错误信息,
void assert_perror (int errnum)
是针对 errno 产生的。
参数个数变化的函数声明应该用 ...,而编写对应的程序主要用
void va_start (va_list ap, last-required)
type va_arg (va_list ap, type)
void va_end (va_list ap)
为了保存 va_list 的临时状态,可以用
void __va_copy (va_list dest, va_list src)

NULL 作为 void * 被赋值为不可使用内存地址(多为 0),指针相减产生 ptrdiff_t 类型数据,
size_t 多记为 unsigned int(long)。
关于数据大小,多在 limits.h 和 floats.h 中用宏定义。
size_t offsetof (type, member)
返回一个结构体中成员的偏移量。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值