Linux中线程的初步认识

线程
先来一张线程图。

Linux中线程的初步认识_第1张图片
轻量化进程

线程是进程中的一条执行流,这个执行流在Linux下是通过PCB实现的,因此Linux下的线程其实就是PCB,但是PCB是进程。因为Linux下的PCB,共用同一个虚拟地址空间,相对于传统PCB更加轻量化,因此也被称为轻量化进程。

线程和进程共享的的数据有很多,包括

  1. 虚拟地址空间(代码段/数据段)
  2. 文件描述符表
  3. 每种信号的处理方式(SIG_ IGN、SIG_ DFL或者自定义的信号处理函数)
  4. 用户ID/组ID/工作路径

虽然线程共享进程数据,但是也拥有自己的一部分数据。
比如:

  • 线程ID
  • 一组寄存器
  • errno
  • 信号屏蔽字
  • 调度优先级

在Linux中,既然线程是轻量化的进程,那么进程就相当于了一个线程组,一个进程中就会有多个线程(即多个PCB),更具体来说,线程就是进程的一条执行流。
那么有一个信号需要被处理,进程中哪一条执行流去处理这个信号?
原则上是谁拿到时间片,能处理的线程进行处理,因为有的线程不希望操作被信号打断,就可以独立屏蔽这个信号。

创建线程

Linux中线程的初步认识_第2张图片
Linux中线程的初步认识_第3张图片
主线程与普通线程

图中可以看到,"hello CSDN - - - 200"是主线程打印的数据,"i am thread !thread~ - - - -100"是普通线程打印的数据。并且当a的值从200变成100,之后主从线程的数据是相同的,说明了线程的数据是共享的。

线程ID
在这里插入图片描述
在线程中会出现这样一个东西,叫做TID。何为TID,其实它是一个线程ID,线程的操作句柄,是用户态线程的ID,就是线程独有的这块空间的首地址,每个进程被创建出来之后,都会开辟一块空间,存储自己的栈和自己的描述信息。

Linux中线程的初步认识_第4张图片
Linux中线程的初步认识_第5张图片

Linux中线程的初步认识_第6张图片

LWP(Light Weight Process):轻量级进程ID
PID:task_struct -> pid :轻量级进程ID,也就是LWP
task_struct -> tgid:线程组ID,就主线程ID,也是所看到的进程ID

线程终止

对于线程终止,有三种方法。

第一种:在线程入口函数中调用return 。
Linux中线程的初步认识_第7张图片
主线程还在运行
Linux中线程的初步认识_第8张图片
但是如果main函数中的return 退出的是进程而不是主线程,相当于调用exit。
Linux中线程的初步认识_第9张图片
进程退出
在这里插入图片描述

第二种:调用void pthread_exit(void* retval);
退出线程接口,谁调用了这个函数谁就退出,retval是退出返回值。
Linux中线程的初步认识_第10张图片
普通线程还在运行
Linux中线程的初步认识_第11张图片

Linux中线程的初步认识_第12张图片
主线程还在运行
Linux中线程的初步认识_第13张图片
第三种:调用int pthread_cancel(pthread_t thread) 来终止一个线程,并且退出的线程是被动取消的

Linux中线程的初步认识_第14张图片
取消掉了普通线程
Linux中线程的初步认识_第15张图片

线程等待

已经退出的线程,它的空间并没有被释放,仍然在进程的地址空间里,而且创建新的线程不会复用之前退出的线程的地址空间。
此时,就需要等待一个线程的退出,获取退出线程的返回值,回收线程所占资源。
线程有一个属性,默认创建出来的这个属性是joinable,处于这个属性的线程,退出后,需要被其它线程等待获取返回值回收资源。
调用的函数体则是int pthread_join(pthread_t thread, void** retval);

Linux中线程的初步认识_第16张图片
其中thread是要等待退出的线程TID,retval是输出型参数,用于返回线程的返回值 。
由于线程的返回值类型是void* 的一级指针类型,所以要传入一个一级指针变量的地址,即二级指针。

一般情况下,一个线程必须被等待,避免造成资源泄漏。

线程分离
将线程joinable属性修改为detach属性
一个线程的属性如果是joinable属性就必须等待,如果是detach属性,那么这个线程退出后则自动释放资源,不需要被等待(资源已被自动释放)。
joinable和分离是冲突的。如果对线程的返回值不关心,不想获取,join则成为了一种负担,不想一直等待线程退出,那么可以告诉操作系统,当线程退出时,自动释放线程资源。

调用的函数体是:int pthread_detach(pthread_t thread);
是将指定的线程分离。

Linux中线程的初步认识_第17张图片
也可以线程自己分离自己,
其函数体是pthread_t pthread_self(void); 还是返回调用线程的TID 。

你可能感兴趣的:(Linux,线程)