转载自:https://www.cnblogs.com/zhaoyl/p/3620204.html

首先从OS设计原理上阐明三种线程:内核线程、轻量级进程、用户线程

内核线程

内核线程就是内核的分身,一个分身可以处理一件特定事情。这在处理异步事件如异步IO时特别有用。内核线程的使用是廉价的,唯一使用的资源就是内核栈和上下文切换时保存寄存器的空间。支持多线程的内核叫做多线程内核(Multi-Threads kernel )。

轻量级进程

轻量级线程(LWP)是一种由内核支持的用户线程。它是基于内核线程的高级抽象,因此只有先支持内核线程,才能有LWP。每一个进程有一个或多个LWPs,每个LWP由一个内核线程支持。这种模型实际上就是恐龙书上所提到的一对一线程模型。在这种实现的操作系统中,LWP就是用户线程。

由于每个LWP都与一个特定的内核线程关联,因此每个LWP都是一个独立的线程调度单元。即使有一个LWP在系统调用中阻塞,也不会影响整个进程的执行。

轻量级进程具有局限性。首先,大多数LWP的操作,如建立、析构以及同步,都需要进行系统调用。系统调用的代价相对较高:需要在user mode和kernel mode中切换。其次,每个LWP都需要有一个内核线程支持,因此LWP要消耗内核资源(内核线程的栈空间)。因此一个系统不能支持大量的LWP。

注:

LWP 的术语是借自于 SVR4/MP 和 Solaris 2.x 。有些系统将 LWP 称为虚拟处理器。而将之称为轻量级进程的原因可能是:在内核线程的支持下, LWP 是独立的调度单元,就像普通的进程一样。所以 LWP 的最大特点还是每个 LWP 都有一个内核线程支持。

用户线程

LWP虽然本质上属于用户线程,但LWP线程库是建立在内核之上的,LWP的许多操作都要进行系统调用,因此效率不高。而这里的用户线程指的是完全建立在用户空间的线程库,用户线程的建立,同步,销毁,调度完全在用户空间完成,不需要内核的帮助。因此这种线程的操作是极其快速的且低消耗的。

上图是最初的一个用户线程模型,从中可以看出,进程中包含线程,用户线程在用户空间中实现,内核并没有直接对用户线程进程调度,内核的调度对象和传统进程一样,还是进程本身,内核并不知道用户线程的存在。用户线程之间的调度由在用户空间实现的线程库实现。

这种模型对应着恐龙书中提到的多对一线程模型,其缺点是一个用户线程如果阻塞在系统调用中,则整个进程都将会阻塞。

加强版的用户线程——用户线程+LWP

这种模型对应着恐龙书中多对多模型。用户线程库还是完全建立在用户空间中,因此用户线程的操作还是很廉价,因此可以建立任意多需要的用户线程。操作系统提供了 LWP 作为用户线程和内核线程之间的桥梁。 LWP 还是和前面提到的一样,具有内核线程支持,是内核的调度单元,并且用户线程的系统调用要通过 LWP ,因此进程中某个用户线程的阻塞不会影响整个进程的执行。用户线程库将建立的用户线程关联到 LWP 上, LWP 与用户线程的数量不一定一致。当内核调度到某个 LWP 上时,此时与该 LWP 关联的用户线程就被执行。

很多文献中都认为轻量级进程就是线程,实际上这种说法并不完全正确,从前面的分析中可以看到,只有在用户线程完全由轻量级进程构成时,才可以说轻量级进程就是线程

LinuxThreads

  所实现的就是基于核心轻量级进程的"一对一"线程模型,一个线程实体对应一个核心轻量级进程,而线程之间的管理在核外函数库(我们常用的pthread库)中实现。 一直以来, linux内核并没有线程的概念. 每一个执行实体都是一个task_struct结构, 通常称之为进程.

  进程是一个执行单元, 维护着执行相关的动态资源. 同时, 它又引用着程序所需的静态资源.通过系统调用clone创建子进程时, 可以有选择性地让子进程共享父进程所引用的资源. 这样的子进程通常称为轻量级进程,如上文所述,又叫内核线程

[插曲]说下fork和vfork的区别
  fork时,子进程是父进程的一个拷贝。子进程从父进程那得到了数据段和堆栈段,但不是与父进程共享而是单独分配内存。然而这里的非共享最初状态是共享的,linux下使用了写时复制技术,刚开始共享父进程的数据段,在写数据段的时候才进行复制,以fork为例,最终共享的资源就是task_struct、系统空间堆栈(copy_thread)、页面表等。vfork时,因为实现为子进程先执行,所以是不拷贝(没必要)父进的虚存空间,也就是用户空间堆栈,clone(clone_vfork|clone_vm|sigchld,0),指明的参数是不会拷贝,注定共享的。因为现在的fork都是写实拷贝,所以vfork的优势便不明显了——只是不用向vfork那样拷贝页表。另外,内核都是优先让子进程先执行,考虑到调度问题,fork不保证;但vfork可保证这点  2.4内核 do_dork是fork/vfork/clone系统调用的共同代码,其核心流程如下:1) 默认对所有资源进行共享暂不复制;2) 如果flags未指定共享(相应位为0),则进行深层次复制。包括,file,fs,sighand,mm。以CLONE_FILES为例,对fork而言为1,也就是必须复制两份files,这样父子进程才有独立上下文(各自独立lseek不影响,但是文件指针肯定还是指向一个);但是对于vfork,这个标志为1,也就是父子进程共享文件上下文(注意这里不是共享文件指针,连上下文都共享!也就是子进程lseek会改变父进程读写位置),这岂不乱套(类似还有vfork的CLONE_VM标志)!别担心,do_fork中会保证vfork时候,自进程先执行完!特殊说下,mm资源即使是非共享的,即CLONE_VM=1(fork如此),也不马上复制,而是复制页面表后,把也表项设置为写保护,这样无论谁写,届时都会再复制一份出来,这才完成的资源的独立——对fork而言。3) 复制系统堆栈(区别于用户空间VM)

 

用户态线程由pthread库实现,使用pthread以后, 在用户看来, 每一个task_struct就对应一个线程, 而一组线程以及它们所共同引用的一组资源就是一个进程.  但是, 一组线程并不仅仅是引用同一组资源就够了, 它们还必须被视为一个整体.

 

转载于:https://www.cnblogs.com/SoftAndHard/p/8553756.html

(转载)Linux多线程实现相关推荐

  1. Linux 多线程应用中编写安全的信号处理函数

    2019独角兽企业重金招聘Python工程师标准>>> Linux 多线程应用中编写安全的信号处理函数 在 开发多线程应用时,开发人员一般都会考虑线程安全,会使用 pthread_m ...

  2. 新书预告:《Linux 多线程服务端编程——使用 muduo C++ 网络库》

    看完了 W. Richard Stevens 的传世经典<UNIX 网络编程>, 能照着例子用 Sockets API 编写 echo 服务, 却仍然对稍微复杂一点的网络编程任务感到无从下 ...

  3. 《Linux多线程服务端编程:使用muduo C++网络库》书摘6.6.2节

    6.6.2 常见的并发网络服务程序设计方案 W. Richard Stevens 的<UNIX 网络编程(第2 版)>第27 章"Client-ServerDesign Alte ...

  4. 3、Linux多线程,线程同步(转)

    3.Linux多线程,线程同步 5)线程私有数据 进程内的所有线程共享进程的数据空间,因此全局变量为所有线程所共有.但有时线程也需要保存自己的私有数据,这时可以创建线程私有数据(Thread-spec ...

  5. ZT 为什么pthread_cond_t要和pthread_mutex_t同时使用 || pthread/Linux多线程编程

    为什么线程同步的时候pthread_cond_t要和pthread_mutex_t同时使用 (2009-10-27 11:07:23) 转载▼ 标签: 杂谈 分类: 计算机 举一个例子(http:// ...

  6. 转Linux多线程条件下的计数器 2011-11-15 00:00中国IT实验室佚名

    Linux多线程条件下的计数器 2011-11-15 00:00中国IT实验室佚名 字号:A+|A- 最近编码需要实现多线程环境下的计数器操作,统计相关事件的次数.下面是一些学习心得和体会.不敢妄称原 ...

  7. linux c进程线程的面试问题,linux 多线程面试题_linux进程线程_linux 线程 pthread_create...

    你写了一个简单的mandelbrot set程序,也就是说用ps命令行是可以看见多个线程,win32里同一个进程里各个线程之间是共享数据段的,win32的进程管理方式与unix上有着很大区别.adob ...

  8. Linux多线程的同步------读写锁

    前面介绍过Linux多线程同步的另外两个方法------互斥锁和信号量 Linux多线程的同步-----信号量和互斥锁_神厨小福贵!的博客-CSDN博客 下面来看一下读写锁: 读写锁和互斥锁都带有一个 ...

  9. Linux多线程的同步-----信号量和互斥锁

    前面两篇给基本概念讲过了,大家有兴趣的可以去看一下: Linux多线程_神厨小福贵!的博客-CSDN博客进程和线程的区别有哪些呢?进程是资源分配的最小单位,线程是CPU调度的最小单位进程有自己的独立地 ...

  10. linux 内核信号量与用户态信号量(system v,信号量在Linux多线程机制中的应用

    [摘 要]本文以信号量原理为基础,重点阐述信号量在Linux多线程同步机制中的实现特色. [关键词]信号量:Linux:多线程:同步 1 信号量 1965年E. W. Dijkstra首次提出信号量的 ...

最新文章

  1. UA MATH565C 随机微分方程III Ito积分简介
  2. 数据挖掘-分类与预测-神经网络算法
  3. gtone eclipse plugin install
  4. Android Studio的TableLayout的使用(自定义列拉伸,收缩,隐藏,横跨列)
  5. python连接池 commit,连接池请求Python
  6. 引导滤波 Guided Image Filtering
  7. dnSpy反编译C#编译以后dll文件并调试
  8. 由一篇作文《一件有意义的事》展开的
  9. 新中大冲刺科创板:年营收2.84亿 拟募资5.57亿
  10. java杯子换水_水壶问题(向水壶中倒z升水) Water and Jug Problem
  11. 部署3PAR VSP5.0.9.2监控3PAR实时邮件告警状态
  12. python判断信用卡号是否合法_三十八、练习、Python判断一个信用卡号是否合理
  13. 进销存软件的价值是多少?它能帮企业做什么?
  14. 任意斜率的中点画线算法
  15. 什么是文件管理软件?你为什么需要它?
  16. 使用nginx搭建音视频点播服务——基于DASH协议
  17. 史上最详细log4j使用文档
  18. 开发一款抓取Android系统Log的APP(logcat, kernel, Memory, cpu)
  19. 新零售全能商城多商户拼团砍价秒杀周期购分销论坛投票收银台点餐外卖小程序公众号
  20. web前端-day-33

热门文章

  1. jQuery EasyUI Datagrid组件的完整的基础DOM结构
  2. 后端选型中不同语言及对应的Web框架
  3. WCF 之 消息契约(MessageContract)
  4. msysGit管理GitHub代码
  5. RHEL6入门系列之十,常用命令3
  6. 装了Visual Studio 2005之后重装IIS的问题解决方法
  7. MongoDb 中 serverStatus was very slow 的原因分析
  8. 出现ORA - 1017用户名/口令无效; 登录被拒绝 的问题
  9. Flink实时计算性能分析
  10. 利用python实现ORM