许多教程中,总是把进程定义为程序的执行实例,它并不执行什么,只是维护应用程序所需的各种资源。
而线程则是真正的执行实体,为了让进程完成一定的工作,进程必须至少包含一个线程。
进程所维护的是程序所包含的资源(静态资源),如:地址空间,打开的文件句柄集,文件系统状态,信号处理handler等。
线程所维护的是运行相关的资源(动态资源),如:运行栈,调度相关的控制信息,待处理的信号集等。
然而,一直以来,linux内核并没有线程的概念。每一个执行实体都是一个task_struct结构,通常称之为进程。
linux进程是一个执行单元,维护着执行相关的动态资源,同时,它又引用着程序所需的静态资源。
通过系统调用clone创建子进程时,可以有选择性地让子进程共享父进程所引用的资源,这样的子进程通常称为轻量级进程。
linux上的线程就是基于轻量级进程,由用户态的pthread库实现的。
使用pthread以后,在用户看来,每一个task_struct就对应一个线程,而一组线程以及它们所共同引用的一组资源就是一个进程。
但是,一组线程并不仅仅是引用同一组资源就够了,它们还必须被视为一个整体,对此,POSIX标准提出了如下要求:
1、查看进程列表的时候,相关的一组task_struct应当被展现为列表中的一个节点
2、发送给这个“进程”的信号(对应kill系统调用),将被对应的这一组task_struct所共享,并且被其中的任意一个“线程”处理
3、发送给某个“线程”的信号(对应pthread_kill),将只被对应的一个task_struct接收,并且由它自己来处理
4、当“进程”被停止或继续时(对应SIGSTOP/SIGCONT信号),对应的这一组task_struct状态将改变
5、当“进程”收到一个致命信号(比如由于段错误收到SIGSEGV信号),对应的这一组task_struct将全部退出
6、等等(以上可能不够全)
linuxthreads
在linux 2.6以前,pthread线程库对应的实现是一个名叫linuxthreads的库。
linuxthreads利用前面提到的轻量级进程来实现线程,但是对于POSIX提出的那些要求,linuxthreads除了第5点以外,都没有实现(实际上是无能为力):
1、如果运行了A程序,A程序创建了10个线程,那么在shell下执行ps命令时将看到11个A进程,而不是1个(注意,也不是10个,下面会解释)
2、不管是kill还是pthread_kill, 信号只能被一个对应的线程所接收
3、SIGSTOP/SIGCONT信号只对一个线程起作用
还好linuxthreads实现了第5点,我认为这一点是最重要的。
如果某个线程“挂”了,整个进程还在若无其事地运行着,可能会出现很多的不一致状态,进程将不是一个整体,而线程也不能称为线程了。
或许这也是为什么linuxthreads虽然与POSIX的要求差距甚远,却能够存在,并且还被使用了好几年的原因吧。
但是,linuxthreads为了实现这个“第5点”,还是付出了很多代价,并且创造了linuxthreads本身的一大性能瓶颈。
接下来要说说为什么A程序创建了10个线程,但是ps时却会出现11个A进程了。
因为linuxthreads自动创建了一个管理线程,上面提到的“第5点”就是靠管理线程来实现的。
当程序开始运行时,并没有管理线程存在(因为尽管程序已经链接了pthread库,但是未必会使用多线程)。
程序第一次调用pthread_create时,linuxthreads发现管理线程不存在,于是创建这个管理线程,这个管理线程是进程中的第一个线程(主线程)的儿子。
然后在pthread_create中,会通过pipe向管理线程发送一个命令,告诉它创建线程,即是说,除主线程外,所有的线程都是由管理线程来创建的,管理线程是它们的父亲。
于是,当任何一个子线程退出时,管理线程将收到SIGUSER1信号(这是在通过clone创建子线程时指定的)。
管理线程在对应的sig_handler中会判断子线程是否正常退出,如果不是,则杀死所有线程,然后自杀。
那么,主线程怎么办呢?主线程是管理线程的父亲,其退出时并不会给管理线程发信号,于是,在管理线程的主循环中通过getppid检查父进程的ID号,如果ID号是1,说明父亲已经退出,并把自己托管给了init进程(1号进程),这时候,管理线程也会杀掉所有子线程,然后自杀。
可见, 线程的创建与销毁都是通过管理线程来完成的,于是管理线程就成了linuxthreads的一个性能瓶颈,
创建与销毁需要一次进程间通信,一次上下文切换之后才能被管理线程执行,并且多个请求会被管理线程串行地执行。
相关推荐
Linux多线程服务端编程:使用muduo+C网络库.pdf Linux多线程服务端编程:使用muduo+C网络库.pdfLinux多线程服务端编程:使用muduo+C网络库.pdfLinux多线程服务端编程:使用muduo+C网络库.pdfLinux多线程服务端编程:...
在Linux系统中,多线程编程是实现高效并发执行任务的一种常见方法。通过创建和管理多个线程,程序可以充分利用现代多核处理器的资源,提高软件的响应速度和整体性能。"linux_code.rar"这个压缩包包含了一些关于Linux...
Linux多线程编程是操作系统中并发程序设计的一个重要领域,它允许开发者在同一程序中创建多个线程,以实现并行执行,从而提高程序的执行效率和响应能力。Linux下的多线程编程通常基于POSIX线程(pthread)库来实现,...
【Linux多线程编程】是Linux系统开发中的一个重要主题,主要涉及如何在Linux环境中创建、管理和同步线程。华清远见的这份PPT为学习者提供了深入的理解和实践指导。 在Linux系统中,线程是进程内的执行单元,是...
嵌入式Linux多线程编程 嵌入式Linux多线程编程是嵌入式系统开发中的一种重要技术,能够提高系统的效率和响应速度。本章节将详细介绍嵌入式Linux多线程编程的基本概念、线程的创建、同步和互斥、线程属性、多线程...
Linux多线程服务端编程,高清无水印!~
### Linux多线程手册知识点详解 #### 一、多线程基础介绍 ##### 定义多线程术语 - **线程**:是进程中的一个执行单元,它共享进程的资源,但拥有独立的栈和寄存器上下文。 - **多线程**:指在一个进程中同时运行...
Linux多线程服务端编程是陈硕大神的一本linux服务端开发实战书籍。
在Linux系统中,多线程编程是一种常见的提升程序并发性能的技术。它允许一个进程内同时执行多个线程,每个线程都有自己的执行上下文,但共享同一份内存空间。这使得线程间通信更为便捷,同时也增加了编程的复杂性。 ...
Linux多线程编程是计算机编程中一个高级主题,涉及到同时执行多个任务的能力,这些任务共享公共地址空间。它允许程序更有效地利用多核处理器的能力,提高性能和响应速度,优化资源利用,并改善程序的结构。Linux多...
《Linux多线程服务端编程:使用muduo C++网络库》主要讲述采用现代C++在x86-64 Linux上编写多线程TCP网络服务程序的主流常规技术,重点讲解一种适应性较强的多线程服务器的编程模型,即one loop per thread。...
《C++实现的Linux多线程聊天室》 在计算机编程领域,多线程技术是提升程序并发性能的重要手段,特别是在服务器端应用中,如聊天室。本项目以C++语言在Linux环境下实现了一个多线程聊天室,利用了Linux系统强大的多...
《Linux多线程服务端编程:使用muduo C++网络库》这本书是陈硕的作品,专注于讲解如何在Linux环境中构建高效、稳定的多线程服务器程序。书中主要围绕muduo网络库进行深入探讨,该库是专为C++开发者设计的,用于简化...
linux系统下建立多线程程序设计,完成UDP网络通信的发送与接收,包括总结与源代码,实测效果可见链接https://blog.csdn.net/zxp121127/article/details/78506081
Linux 多线程编程 Linux 多线程编程是操作系统课程设计的重要组成部分,多线程技术早在 60 年代就被提出,但真正应用多线程到操作系统中去,是在 80 年代中期,solaris 是这方面的佼佼者。传统的 Unix 也支持线程的...
Linux线程的挂起与恢复是一个复杂且需要谨慎处理的问题。通过互斥锁和条件变量,我们可以实现一种用户空间的模拟方式,但这并不总是一种安全或高效的方法。在设计多线程程序时,应优先考虑使用更安全的同步机制,如...
在Linux系统中,多线程编程是实现并发执行任务的重要技术。这个"linux多线程demo"示例可能是一个用于教学或实践的项目,通过CMake构建系统进行编译,适用于嵌入式环境,比如ARM架构设备。让我们深入探讨一下多线程、...