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

Unix——线程和线程控制

发布时间:2023-01-09 10:52:25 所属栏目: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不能保证是线程安全的函数,系统提供他们的线程安全版本
 

(编辑:我爱资讯网)

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

    推荐文章