
OS教科书简单地概述了进程和线程之间的区别: 进程是资源分配的单位,而线程是调度的单位. 但是,Linux内核不区分进程和线程. 它们都由任务(task_struct)表示. 什么时候称为进程,什么时候称为线程,取决于上下文. 尽管没有特殊的线程实现,但内核使用轻量级进程LWP(轻量级进程)来替换线程.
内核就像服务器,而用户任务就像客户端. 内核中的所有内容都为用户模式服务. 轻量级过程是支持用户模式线程库.
Posix线程是一个通用术语,符合posix标准线程库. 有许多具体的实现方式,这里不再赘述. 只要您知道线程库的实现可以根据用户模式线程数与内核进程数的比率分为三个模型: N: 1,M: N和1: 1. 执行以下命令以检查系统上使用了哪个线程库:
$ getconf GNU_LIBPTHREAD_VERSION
NPTL 2.22
NPTL(本地Posix线程库)是Linux的线程实现,使用1: 1模型. 这里有一篇很好的文章,请参考NPTL分析线程的创建.
轻量级进程是Linux的所谓“线程”. 它仅共享父进程的许多资源,例如进程地址空间posix 进程 线程,文件描述符和信号灯. 唯一的独立资源是任务描述符task_struct,内核堆栈等. 关于调度,它可以实现: 资源共享,调度独立性.
共享进程地址空间struct task_struct {struct mm_struct * mm;}是通过使多个进程的mm指向同一虚拟内存struct mm_struct来实现的. 通过pthread_create()创建线程时,标志的各种组合会通过clone()系统调用传递,以确定哪些资源需要与父进程共享.

struct mm_struct表示进程虚拟地址空间. 关于虚拟地址空间的布局,有许多参考书. struct mm_struct {unsigned long start_code,end_code,start_data,end_data;无符号长start_brk,brk,start_stack; unsigned long arg_start,arg_end,env_start,env_end;},代码,数据,堆,堆栈,参数,环境变量在每个空间中都有点. 这些虚拟内存段和物理内存之间的映射关系如何建立?答案是通过内存映射mmap. VMA(虚拟内存区域)列表struct mm_struct {struct vm_area_struct * mmap; / * VMA列表* /},某些vma如动态库,可执行程序通过mmap,某些vma如堆,堆栈由匿名映射完成.
在进程描述符中有一个字段struct task_struct {struct list_head thread_group;},该字段显然希望将线程组的线程放在一起. 进程组struct task_struct {pid_t tgid},tgid是线程组中领先的进程struct task_struct {struct task_struct * group_leader;}的pid.
LinuxThreads是用户空间中的线程库. 它使用线程进程模型(即,用户线程对应于轻量级进程,而轻量级进程对应于特定的内核线程). 的调度等效于进程的调度,调度由内核完成,线程的创建,同步和销毁由内核外线程库完成(LinuxThtreads已绑定到GLIBC版本).
在LinuxThreads中,专用的管理线程处理所有线程管理任务. 当进程首次调用pthread_create()创建线程时,它将首先创建(clone())并启动管理线程. 当后续进程pthread_create()创建线程时,它是作为pthread_create()调用者的子线程的管理线程. 通过调用clone()创建用户线程,并记录轻量进程号和线程ID之间的映射关系. 因此,用户线程实际上是管理线程的子线程.
1. 进程,轻量级进程,线程和线程组之间的关系
2及其识别相关说明

首先,进程,轻量级进程,线程和线程组之间的关系
借助上图:
进程P0具有四个执行流,即线程,
主线程t0是它的第一个线程,并且与进程P0相关联,
此后派生了三个线程t1,t2和t3. 这三个线程分别与轻量级进程P1,P2和P3关联.
所有进程,轻量级进程和线程组成一个线程组.
轻量级进程也是一个进程,但是它与进程的特定线程相关联.

两个. 徽标说明
pid是进程标识符,tgid是线程组标识符
每个进程都有自己的pid,如图所示: 进程pid(P0)= a,轻量级进程pid(P1)= b / pid(P1)= c / pid(P1)= d.
属于同一线程组的所有进程和轻量级进程都具有相同的线程组标识符,这是与第一个线程相关联的进程标识符posix 进程 线程,
例如: 图中的第一个线程为t0,其关联进程为P0,pid(P0)= a,因此tgid(P1)= a / tgid(P1)= a / tgid(P1)= a / tgid(P1)= a.
当我们使用函数getpid(current_p)时,返回值不是current_p的pid,而是其tgid. (Current_p是当前进程)
一个程序具有至少一个进程,并且一个进程具有至少一个线程. 线程的划分规模小于进程的划分规模,这使得多线程程序具有较高的并发性.

此外,该进程在执行过程中具有一个独立的存储单元,并且多个线程共享内存,这大大提高了程序的效率.
同一进程的多个子线程在进程的共享内存中分配独立的堆栈空间
堆栈: 它是线程唯一的,并保存其运行状态和局部自动变量. 线程启动时将初始化堆栈,并且每个线程的堆栈彼此独立,因此该堆栈是线程安全的. 每个C ++对象的数据成员也存在于堆栈中,并且每个函数都有其自己的堆栈. 堆栈用于在函数之间传递参数. 切换线程(即切换SS / ESP寄存器)时,操作系统将自动切换堆栈. 不需要使用高级语言显式分配和释放堆栈空间.
Linux系统上的每个线程实际上都有两个独立的堆栈空间,即用户堆栈空间和内核堆栈空间. (请注意每个线程)
在Linux上,进程和线程之间的唯一区别是同一进程的不同线程共享进程的地址空间,仅此而已.
tgid: 线程组ID(由多个线程组成)
pid: 进程ID(进程是否等同于线程组?)
ppid: 父进程ID
pgid: 进程组ID(由多个进程组成),其功能是简化向组中所有进程发送信号的过程
sid: 会话组ID(由多个进程组组成)在bash上运行的所有程序都属于一个会话(除非经过特殊处理),并且该bash是该会话的领导者. 每个会话都可以与一个控制终端相关联
父进程的退出不会影响子进程,但是对话组负责人的进程将退出,整个对话组中的进程将退出. 这也是使用nohup的原因
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-285465-1.html
打
大家说对吧
你以为是小学的数学题
晚安好梦小王子
否则哪里来的12海里之说