加入收藏 | 设为首页 | 会员中心 | 我要投稿 站长网 (https://www.zhandada.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Unix > 正文

Unix——线程和线程控制

发布时间:2023-01-10 14:00:55 所属栏目:Unix 来源:转载
导读: 注:写得非常乱,以后有空再整理(在我们业界称为重构),没空就这样放着吧。
线程包含了表示进程内执行环境的必须信息。其中包括进程中的线程ID,一组寄存器值,栈,调度优先级和策略,

注:写得非常乱,以后有空再整理(在我们业界称为重构),没空就这样放着吧。

线程包含了表示进程内执行环境的必须信息。其中包括进程中的线程ID,一组寄存器值,栈,调度优先级和策略,

信号屏蔽字,errno变量,线程私有数据。进程所有信息对该进程的所有线程都是共享的包括,可执行的程序文本,

程序全局内存和堆内存,栈,文件描述符。

线程接口-POSIX.1-2001,"pthread","POSIX线程"

#include

int pthread_equal(pthread_t id1, pthread_t id2);//相等返回非0;否则返回0

#include

pthread_t pthread_self(void);//获得自身线程ID,参见getpid()

#include

int pthread_create(pthread_t *restrict id,

const pthread_attr_t *restrict attr,//线程属性NULL

void *(*fun)(void *), void *restrict arg);//新线程入口,函数fun,

//如果函数参数有多个,则把这些参数放到一个结构中,然后把这个结构地址传入。

成功返回0,每个线程都提供errno的副本

C语言题外话:volatile和restrict

方便编译器优化,

restrict,C99引入,只可以用于限定指针,并表明指针是访问一个数据对象的唯一且初始的方式;

指向的内容改变,则只能通过指针进行存取。

volatile告诉编译器该变量除了可被程序修改以外还可能被其他代理修改,因此,当要求使用

volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,而不是使用寄存器中的缓存。

线程退出:

1)线程从启动历程中返回,返回值是线程退出码。

2)线程可以被统一进程中的其它线程取消。

3)pthread_exit(void *rval_ptr);

线程被取消rval_ptr指向单元置为PTHREAD_CANCELED

int pthread_join(pthread_t thread, void **rval_ptr);

//调用线程阻塞,直到指定的线程调用pthread_exit,从启动例程中返回或者被取消

自动使线程处于分离状态。

int pthread_cancel(pthread_t tid);//提出请求取消同一进程中的其他线程,不等待线程终止。

线程清理处理程序

void pthread_cleanup_push(void (*fun)(void *), void *arg);--注册清理函数fun

void pthread_cleanup_pop(int execute);--execute!=0执行清理,后注册先执行。

清理函数的调用顺序由pthread_cleanup_push函数来安排,线程执行以下动作时调用清理函数:

1)调用pthread_exit

2)响应取消请求时

3)用非零execute调用pthread_cleanup_pop时

int pthread_detach(pthread_t tid);使线程进入分离状态。

线程的状态:分离状态

线程的同步问题(互斥量,读写锁,条件变量)

互斥量

#include

int pthread_mutex_init(pthread_mutex_t *restrict mutex,

const pthread_mutexattr_t *restrict attr);//默认attr=NULL

int pthread_mutex_destroy(pthread_mutex_t *mutex);//成功返回0

int pthread_mutex_lock(pthread_mutex_t *mutex);//加锁,互斥量已经上锁则线程阻塞,直到该互斥量解锁。

int pthread_mutex_unlock(pthread_mutex_t *mutex);//解锁

int pthread_mutex_trylock(pthread_mutex_t *mutex);//尝试加锁,不阻塞。已加锁,返回EBUSY

避免死锁:两个线程同时请求两一个线程拥有的资源,从而产生死锁。

产生死锁的必要条件:

1)互斥

2)占有并等待

3)非抢先

4)循环等待

读写锁(共享独占锁),允许更高的并行性(三种状态,读模式下加锁,写模式下加锁,不加锁状态)

读写锁同互斥锁一样,在使用前初始化,在释放底层内存时必须销毁。

int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,

const pthread_rwlock_t *restrict attr);

int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);//读模式加锁

int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);//写模式加锁

int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);//解锁

int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);//可以获取锁,返回0;否则返回EBUSY

int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);

条件变量:

#include

int pthread_cond_init(pthread_cond_t *restrict cond,

pthread_cond_t *restrict attr);

int pthread_cond_destroy(pthread_cond_t *cond);

int pthread_cond_wait(pthread_cond_t *restrict cond,

pthread_mutex_t *restrict mutex);

int pthread_cond_timedwait(pthread_cond_t *restrict cond,

pthread_mutex_t *restrict mutex,

const struct timespec *restrict timeout);

int pthread_cond_signal(pthread_cond_t *cond);//向线程或条件发送信号

int pthread_cond_broadcast(pthread_cond_t *cond);

线程限制(略)

线程属性 struct pthread_attr_t{};该结构不透明

#include

int pthread_attr_init(pthread_attr_t *attr);

int pthread_attr_destroy(pthread_attr_t *attr);

detachstate 线程分离状态属性

guardsize 线程栈末尾的警戒缓冲区大小(字节数)

stackaddr 线程栈的最低地址

stacksize 线程栈的大小(字节数)

若对某个线程的终止状态不感兴趣,调用int pthread_detach(pthread_t id)函数,

让OS在线程退出时,回收它所占用的资源。

分离状态属性:

int pthread_attr_getdetachstate(const pthread_attr_t *restrict attr,

int *detachstate);

创建线程,以分离状态启动

int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);

detachstate=PTHREAD_CANCEL_DETACHE

PTHREAD_CREATE_JOINABLE(默认)

线程栈大小属性和线程栈最低地址:

int pthread_attr_getstack(const pthread_attr_t *restrict attr,

void **restrict stackaddr,

size_t *restrict stacksize);

int pthread_attr_setstack(pthread_attr_t *attr,

void *stackaddr,

size_t *stacksize)

线程栈大小属性

int pthread_attr_getstacksize(const pthread_attr_t *restrict attr, size_t *restrict stacksize);

int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);

guardsize属性,控制着线程末尾之后用以避免栈溢出的扩展内存的大小。默认PAGESIZE

int pthread_attr_getguardsize(const pthread_attr_t *restrict attr,

size_t *restrict guardsize);

int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize);

有两个没有包含在pthread_attr_t结构中的属性——可取消状态和可取消类型,他们影响着pthread_cancel函数

调用时所呈现的行为。

可取消状态:PTHREAD_CANCEL_ENABLE默认,PTHREAD_CANCLE_DISABLE

#include

int pthread_setcancelstate(int state, int *oldstate);

void pthread_testcancel(void);//手动添加取消点。

可取消类型:PTHREAD_CANCEL_DEFERRED延迟取消,PTHREAD_CANCEL_ASYNCHRONOUS异步取消,任意时间取消

int pthread_setcanceltype(int type, int *oldtype);

同步属性

互斥量属性pthread_mutexattr_t

int pthread_mutexattr_init(pthread_mutexattr_t *mutexattr);

int pthread_mutexattr_destroy(pthread_mutexattr_t *mutexattr);

进程共享互斥量属性:PTHREAD_PROCESS_SHARED,PTHREAD_PROCESS_PRIVATE(default)

int pthread_mutexattr_getpshared(const pthread_mutexattr_t *restrict attr, int *restrict pshared);

int pthread-mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared);

类型互斥量属性:PTHREAD_MUTEX_NORMALunix线程切换,PTHREAD_MUTEX_ERRORCHECK,

PTHREAD_MUTEX_RECURSIVE使之等同于信号量的功能.递归锁。

PTHREAD_MUTEX_DEFAULT,系统将其映射到其它类型

int pthread_mutexattr_gettype(const pthread_mutexattr_t *restrict attr, int *restrict type);

int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type);

读写锁属性pthread_rwlockattr_t

读写锁的唯一属性是进程共享属性,参见互斥量。

条件变量属性pthread_condattr_t

也支持进程共享属性

重入问题,有了信号处理程序和线程,多个控制线程在同一时间可能潜在的调用同一个函数。

如果一个函数在同一时刻可以被多个线程安全的调用,则该函数是线程安全的。

如果一个函数对多个线程来说是可重入的,则这个函数是线程安全的,但并不说明对信号处理程序来说该函数也是可重入的。

若果函数对异步信号处理程序的重入是安全的,那么就可以说函数是异步信号安全函数。

线程安全函数(线程可重入的)和异步信号安全函数(信号处理程序可重入的)

POSIX.1不能保证是线程安全的函数,系统提供他们的线程安全版本

(编辑:站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章