Posix 线程

fork问题:
a. fork是昂贵的。内存映像要从父进程拷贝到子进程,所有描述字要在子进程中复制等等。写时拷贝技术(copy-on-write)。
b. fork进程后,需要用进程间通信(IPC)在父子进程之间传递信息。

线程,有时被称为轻权进程(lightweight process)。 创建线程要比创建进程快10~100倍。
进程中的所有线程共享:
1. 全局变量
2. 进程指令
3. 大多数数据
4. 打开的文件(如描述字)
5. 信号处理程序和信号处置
6. 当前工作目录
7. 用户ID和组ID
但是每个线程有:
1. 线程ID
2. 寄存器集合,包括程序计数器和栈指针
3. 栈(用于存放局部变量和返回指针)
4. errno
5. 信号掩码
6. 优先级

#include <pthread.h>
int pthread_create(pthread_t *tid, const pthread_attr_t *attr)
            void *(*func)(void *), void *arg);
返回: 成功时返回0,出错时返回正的Exxx值。
typedef unsigned long int pthread_t         <bits/pthreadtypes.h>

typedef union {                    <bits/pthreadtypes.h>
    char    __size[__SIZEOF_PTHREAD_ATTR_T];
    long int    __align;
} pthread_attr_t;

#if    WORDSIZE == 64                <bits/pthreadtypes.h>
#define __SIZEOF_PTHREAD_ATTR_T    56   
#else
#define __SIZEOF_PTHREAD_ATTR_T    36
#endif

tid:    返回新创建线程的ID(thread ID)标识
attr:    要创建的新线程的属性: 优先级,起始栈大小,是否应该是一个守护线程等等。通常使用缺省值,为NULL。
func:    创建线程后要执行的函数
arg:    函数func的参数,如果需要多个参数,可打包成一个结构,然后传递结构的地址。

Pthread函数不设置errno。成功时返回0,出错时返回非0。例如:pthread_create因为超过了对系统线程数目的限制而不能创建新线程,将返回EAGAIN。
#define EAGAIN    11    /* Try again */    <asm-generic/errno-base.h>

#include <pthread.h>
int pthread_join(pthread_t tid, void **status);
返回:成功时为0, 出错时为正Exxx值
等待一个线程终止。
tid:    要等待终止的线程
status: 如果status不为NULL,线程的返回值将存放在status指向的位置。

#include <pthread.h>
pthread_t pthread_self(void)
返回: 调用线程的ID

线程: 可汇合的(joinable)线程(缺省值), 脱离的线程(detached).
当可汇合的线程终止时,其线程ID和退出状态将保留,知道另外一个线程调用pthread_join。
脱离的线程则像守护进程:当它终止时,所有的资源都将释放,我们不能等待它终止。

#include <pthread.h>
int pthread_detach(pthread_t tid);
返回: 成功时为0,出错时为正的Exxx值。
将指定的线程变为脱离的。该函数通常被想脱离自己的线程调用。

#include <pthread.h>
void pthread_exit(void *status);
不返回调用者
如果线程未脱离,其线程ID和退出状态将一直保留到调用进程中的某个其他线程调用pthread_join.
指针status不能指向局部于调用线程的对象,因为线程终止时这些对象也消失了。

线程终止的三种方法:
1. 线程调用 pthread_exit 函数
2. 启动线程的函数指向完毕返回。
3. 进程的main函数返回或者任何线程调用函数exit,进程将终止,线程将随之终止。

线程特定数据

每个系统支持有限数量的线程特定数据项。Posix.1要求这个上限不小于128(每个进程)。
系统(很可能是线程库)为每个进程维护一个结构数组。

#include <pthread.h>
int pthread_once(pthread_once_t *onceptr, void (* init)(void));
int pthread_key_create(pthread_key_t *keyptr, void (* destructor)(void *value));
返回: 成功返回0,出错返回正的Exxx值
通常每当一个使用线程特定数据的函数调用时就要调用pthread_once,但pthread_once使用onceptr所指的变量来保证
每个进程只调用一次init函数。
对于一个进程内的给定键,pthread_key_create只能被调用一次。键通过keyptr指针返回,如果想要的destructor函数
不为NULL,而且线程为这个键存储了值,那么该线程终止时,destructor函数将被调用。

typedef int pthread_once_t;            <bits/pthreadtypes.h>
typedef unsigned int pthread_key_t;        <bits/pthreadtypes.h>

#include <pthread.h>
void *pthread_getspecific(pthread_key_t key);
返回:指向线程特定数据的指针(可能为空指针)
int pthread_setspecific(pthread_key_t key, const void *value);
返回: 成功时为0,出错时为正的Exxx值

typedef union {
    struct __pthread_mutex_s {
        int    __lock;
        unsigned int    __count;
        int    __owner;
#if __WORDSIZE == 64
        unsigned int    __nusers;
#endif
        int __kind;
#if __WORDSIZE == 64
        int __spins;
        __pthread_list_t __list;
#define __PTHREAD_MUTEX_HAVE_PREV    1
#else
        unsigned int    __nusers;
        __extension__    union {
            int    __spins;
            __pthread_slist_t    __list;
        };
#endif
    } __data;
    char    __size[__SIZEOF_PTHREAD_MUTEX_T];
    long int    __align;
} pthread_mutex_t;

#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mptr);
int pthread_mutex_unlock(pthread_mutex_t *mptr);
返回:正确时为0,出错时为正Exxx值

如果试图为一个已被其他线程锁住的互斥琐加锁,程序便会阻塞直到该互斥锁被解锁。
如果互斥锁变量是静态分配的,必须将它初始化为常值PTHREAD_MUTEX_INITIALIZER.

#define PTHREAD_MUTEX_INITIALIZER /
    { { 0, 0, 0, 0, 0, { 0 } } }

互斥锁加锁并没有太大的开销。

条件变量

#include <pthread.h>
int pthread_cond_wait(pthread_cond_t *cptr, pthread_mutex_t *mptr);
int pthread_cond_signal(pthread_cond_t *cptr);
返回:成功时返回0,出错时为正的Exxx值

typedef union {
    struct {
        int    __lock;
        unsigned int    __futex;
        __extension__ unsigned long long int    __total_seq;
        __extension__ unsigned long long int    __wakeup_seq;
        __extension__ unsigned long long int    __woken_seq;
        void     *__mutex;
        unsigned int    __nwaiters;
        unsigned int    __broadcast_seq;
    } __data;
    char __size[__SIZEOF_PTHREAD_COND_T];
    __extension__ long long int    __align;
} pthread_cond_t;

#define PTHREAD_COND_INITIALIZER /
    { { 0, 0, 0, 0, 0, (void *) 0, 0, 0, 0 } }

#include <pthread.h>
int pthread_cond_broadcast(pthread_cond_t *cptr);
int pthread_cond_timedwait(pthread_cond_t *cptr, pthread_mutex_t *mptr,
                    const struct timespec *abstime);
返回: 成功返回0, 出错返回正的Exxx值
函数pthread_cond_broadcast唤醒阻塞在该条件变量上的所有线程。
函数pthread_cond_timedwait允许一个线程设置阻塞时间的上限。abstime是一个timespec结构,
指定函数必须返回的系统时间,即使条件变量信号还没有被发出。如果超时发生,则返回ETIME错误。

#define ETIME    62    /* Timer expired */     <asm-generic/errno.h>

struct timespec {
    long    ts_sec;
    long    ts_nsec;
};

墨菲定律(Murphy's Law): If there are two or more ways to do something, and one of those ways can
result in a catastrophe, then someone will do it.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值