linux 之线程基础 (一)、 线程的基本概念

1. 线程基本概念

1.1 为什么需要引入线程?

现代操作系统OS引入了多任务的概念,传统上多任务的实现是多进程完成的。支持多任务就涉及到进程的切换,也就意味着进程上下文的切换。

如果我们进程有很多,多进程的频繁切换,每次上下文切换都要做这些事,还是很耗资源的,我们想用一种机制能减少进程切换带来的资源消耗,所以很多操作系统中都引入了轻量级的进程的概念。也称之为线程。

注意:上下文切换,上下文的意思是,我们运行一个进程所需要的资源。那就有内存,快速缓存,PC指针等等。切换上下文就是替换原先的内容,从某中角度去看需要切换task_struct结构以及虚拟内存空间。

1.2 什么是线程?

线程(thread),被称为轻量级进程(Lightweight Process Lwp)是程序执行调度的最小单位。在传统的系统中,一个进程只包含有一个线程。但在现代操作系统中,允许一个进程里面可以同时运行多个线程,这类程序就被称为多线程程序。一个进程内的各个线程之间共享程序的内存空间以及其他的资源(如打开的文件和信号等)。

Linux实现线程的机制非常特别,从内核角度来说并没有线程的概念,Linux将线程仅仅视作一个与其他进程共享某些资源的特殊进程。所以Linux并没有特别的数据结构来描述线程,依然沿用task_struct结构来描述线程。

注意:

  • 进程和线程 的比喻:公司、部门、部门员工。一个公司有多个部门,一个部门有多个员工。一个公司相当于一个完整的系统,一个部门相当于系统中的一个进程,一个员工相当于一个线程。部门员工之间许多信息可以共享,但是不同部门之间的信息共享比较麻烦。
  • 内核没有准备专门的机制来描述线程,它用的还是进程的那一套东西。只不过多个线程共享同一个进程中的资源

1.3 多线程设计的优点

  • 大大提高了任务切换的效率。
  • 避免了额外的TLB(页表缓冲器)& cache的刷新。

1.4 总结线程与进程的异同点

线程就理解为一个执行者,它没有资源(线程是CPU调度的最小单位)。进程概念上是资源的宿主(进程是资源分配的最小单位)。Linux上的理念是大家都是执行者,资源共享。

1.4.1相同点

  • 比如都具有ID,一组寄存器,状态,优先级以及所要遵循的调度策略。
  • 每个进程都有一个进程控制块,线程也拥有一个线程控制块(在Linux内核,线程控制块与进程控制块用同一个结构体描述,即struct
    task_struct),这个控制块包含线程的一些属性信息,操作系统使用这些属性信息来描述线程。
  • 线程和子进程的创建者可以在线程和子进程上实行某些控制,比如,创建者可以取消、挂起、继续和修改线程和子进程的优先级。

1.4.2 不同点

  • 每个进程都拥有自己的地址空间,但线程没有自己独立的地址空间,而是运行在一个进程里的所有线程共享该进程的整个虚拟地址空间。
  • 线程的上下文切换时间开销比进程上下文切换时间开销要小的多。
  • 线程的创建开销远远小于进程的创建。
  • 子进程拥有父进程的地址空间和数据段的拷贝,因此当子进程修改它的变量和数据时,它不会影响父进程中的数据,但线程可以直接访问它进程中的数据段。
  • 进程之间通讯必须使用进程间通讯机制,但线程可以与进程中的其他线程直接通讯。
  • 线程可以对同一进程中的其他线程实施大量控制,但进程只能对子进程实施控制。
  • 改变主线程的属性可能影响进程中其他的线程,但对父进程的修改不影响子进程。

1.5 与线程相关的命令

1.5.1 查看线程

ps 命令,-L参数显示进程,并尽量显示其LWP(线程ID)和NLWP(线程的个数)。

ps -eLF |  grep  ^syslog

在这里插入图片描述
在这里插入图片描述

1.5.2 pstree命令

查看进程和线程的树形结构关系:

pstree -p | grep syslog

在这里插入图片描述

1.6 线程组概念

  • 线程组是进程的别称
  • 对于多线程的进程,我们称之为线程组。其中开天劈地的main函数我们称为主线程,也就是线程组的组长,主线程的线程id等于进程id。主线程中会调用相关接口创建子线程。

注意:

  • getpid函数,本质取得是线程组id,所以无论是在主线程还是在子线程中调用getpid都是都是获取线程组id。

1.7 NPTL库的特点

多线程运用了第三方库,因此在编译时,要加-lpthread 。(New POSIX Thread Library,NPTL库)。(也就是说标准C库,以及系统库中都没有提供 线程的库,我们所使用的线程库是第三方库。)

  • 是早期Linux Threads的改进
  • 采用1:1的线程模型
  • 显著的提高了运行效率
  • 信号处理效率更高

1.8 同一进程的不同线程的资源共享

1.8.1 一个进程中的多个线程共享以下资源

  • 可执行的指令(代码段共享)
  • 静态数据(全局变量和静态变量)
  • 进程中打开的文件描述符
  • 信号处理函数
  • 当前工作目录
  • 用户ID
  • 用户组ID

1.8.2 每个线程私有的资源如下

  • 线程ID (TID)
  • PC(程序计数器)和相关寄存器
  • 堆栈(栈区)
  • 局部变量
  • 返回地址
  • 错误号 (errno)
  • 信号掩码和优先级
  • 执行状态和属性
posted @ 2020-03-26 22:44  江南又一春  阅读(558)  评论(0编辑  收藏  举报