进程、线程 及其在 linux中的实现

1       进程,线程是怎么来的?

抛开技术细节,从使用角度来讲:

1.     在单核计算机里,有一个资源是无法被多个程序并行使用的: cpu

Cpu,承担计算任务,单个cpu一次只能运行一个任务。

 

没有操作系统的情况下,一个程序一直独占着全部cpu

若有2个任务来共享一cpu,需要程序员安排程序运行计划,使得某时刻cpu被A程序独占,下一时刻cpu被程序B独占

这种安排计划就是OS核心组件,被命名为‘scheduler’,调度器,负责把cpu的运行拆分成一段一段的运行片轮流分给不同的程序去使用,在宏观上,由于分配切换的速度极快,制造出多程序并行在一个cpu上的假象。【真正的并行执行多任务只能在多核cpu上实现】

 

2.     单核计算机里,有一个资源可以被多个程序共享: 内存

在一个只有调度器,没有内存管理组件的OS里,程序员手动为每个程序安排运行的空间:程序A使用物理地址0x00-0xff,程序B使用物理地址0x100-0x1ff。

这种方式的问题是,每个程序都要协商好怎么使用同一个内存上的不同空间,软件系统与硬件系统千差万别,这种高度定制化的方案没有可行性。因此,引入了“虚拟地址”的概念,从3方面着手来解决这个问题:

1) 硬件上,CPU增加了一个专门的模块叫MMU,负责转换虚拟地址和物理地址

2) OS上,OS增加一个核心组件,内存管理模块,管理物理内存、虚拟内存相关的一系列事物

3) 应用程序上,发现一个叫做进程的模型,每个进程都用完全一样的虚拟内存地址,然后经由操作系统和硬件MMU协作,映射到不同的物理地址空间不同的进程,都有各自独立的物理内存空间,不使用特殊手段,是无法访问别的进程的物理内存的。所以说,【进程是资源分配的基本单位

3.     现在,不同的应用程序,不关心底层的物理内存分配,也不关心CPU的协调共享,然后有一些程序,想要共享CPU而且还要共享同样的物理内存,这时,【线程】模型出现了,它们被包裹在进程里边,在调度器的管理下共享CPU,用于同样的虚拟地址空间,同样也共享同一个物理地址空间,然后,它们法跨越包裹自己的进程,去访问别的进程的物理地址空间。【这里,进程和线程共享同一个物理地址空间

4.     进程之间怎样共享同一个物理地址空间呢?不同的系统方法各异,符合posix规范的操作系统都提供一个接口,叫mmap,可以把一个物理地址空间映射不同的进程中,由不同的进程来共享。

5.     有的OS里,进程不是调度单位,线程是最基本的调度单位,调度器只调度线程。

 

2       进程是什么

对于OS来说,一个任务就是一个进程,比如打开一个浏览器就启动一个浏览器进程,打开一个记事本,就启动一个记事本进程,打开两个记事本,就启动2个记事本进程,打开一个word就启动一个word进程。所以说,【进程,是程序的一次运行

         有些进程,还不止同时干一件事,比如word,可以同时进程打字、拼写检查、打印等待,在一个进程内部,要同时干多件事,就需要同时运行多个‘子任务’,我们把进程内的这些‘子任务’称为线程

         每个进程至少干一件事,所以每个进程中至少有一个线程。多个线程同时执行,类似于多进程的执行方式,也OS在多个线程之间快速切换。每个线程短暂交替运行,看起来像同时执行一样。【所以说,线程,是cpu调度的基本单位,是最小的执行单元】。

         如何调度进程和线程,完全由OS决定,程序自己不能决定

3       多任务模型

执行单任务的进程,就只有一个线程,怎样同时执行多个任务?

两种解决方案:

1) 启动多个进程,每个进程虽然只有一个线程,但是多个进程可以一块执行多个任务

2) 启动一个进程,在一个进程内启动多个线程,这样多个线程可以一块执行多个任务。

3) 启动多个进程,每个进程再启动多个线程,这样同时执行的任务就更多了,当然这种模型,实际很少采用

总结起来,多任务的的实现3种方式:

1.      多进程模式

2.      多线程模式

3.      多进程+多线程模式

4       Linux 中线程的实现

4.1      线程,进程的共享关系

进程是用进程描述符表示的,那么线城是怎么实现和表示的呢?

线程机制,提供了在同一程序内共享内存地址空间运行的一组线程,这些线程可以共享打开的文件和进程的其他资源。如下图所示:



4.2      Linux中,线程机制的实现

在linux系统中,线程进程的关系更像下图所示。


线程和进程是一样的,只是进程比线程大,它们都指向相同的内存地址空间。

Linux实现线程的机制非常独特。

从内核来讲,并没有线程的概念,linux把线程当做进程来实现。内核并没有特殊的调度算法或者定义特别的数据结构来表征线程。线程仅被看做一个与其它进程共享某些资源的进程。每个线程都拥有唯一属于自己的task_struct,所以在内核中,它看起来像是一个普通的进程(只是它和其他一些进程共享某些资源),只是它没有自己独立的内存地址空间

在microsoft Windows等OS中,内核提供专门支持线程的机制(这些系统常把线程称作是轻量级进程)。

 

如果现在需要一个包含4个线程的进程,在提供专门支持线程的系统中,会有一个指向4个不同线程的指针的进程描述符。该描述符负责描述像地址空间,打开的文件这样的共享资源。线程本身再去描述它独占的资源。而,linux仅创建4个进程并分配4个普通的task_struct结构,建立这4个进程时,指定它们共享某些资源。

5       Linux中进程的管理

Linux中,触发任何一个事件时,系统都会把它定义成一个进程,同时根据触发这个进程的用户,给予这个进程一组有效的权限设置。

5.1          进程是什么样的

程序运行起来后,我们看不到摸不着,linux提供一系列命令来查看正在运行的进程。

ps -el 查看当前bash下的相关进程全部信息。、

pstree 显示整棵进程树

Init进程是所有进程的根节点,通过ps可以看到init的PID为1.

linux启动的时候,init是系统创建的第一个进程,这个进程会一直存在,直到关闭计算机。所有其他进程由init进程衍生出来的。

5.2      父子进程

衍生出来的进程,就是linux父子进程的概念

当我们登录系统后,会取得一个bashshell,然后利用这个bash提供的接口去执行另一个命令,如bash、ps等,这些另外执行的命令也会触发称为PID,这个后来执行的命令产生的PID就是子进程。而原本的bash环境就是父进程了。

         一个进程除了有PID之外,还会有一个PPID(ParentPID),父进程PID。

5.3      Fork和exec

计算机开机时,内核只建立一个init进程,linux内核不提供直接建立新进程的系统调用。剩下的所有进程都是init进程通过fork机制建立。新的进程通过老的进程复制自身得到,这就是fork。Fork是一个系统调用,进程存活在内存中。每个进程都在内存中分配一块属于自己的空间(内存空间,包括堆、栈、全局静态区、文本常量区、程序代码区)。当一个程序调用fork时,实际上就是将上面的内存空间,又复制出来一个,构成一个新的进程。在内核中为该进程创建新的附加信息(如新的PID,PPID为原进程的PID),此后,两个进程分别继续运行下去。新的进程和原有进程有相同的运行状态(相同的变量值,相同的指令。。。),只能通过进程的附加信息区分两者。

         程序调用exec时,进程清空自身的内存空间,根据新的程序文件重建程序代码、文本常量、全局静态、堆和栈,并开始运行。

5.4      Linux中查看线程

 查看线程数的三种方法:

1.     top –H

-H:threadstoggle

加上这个选项启动top,top一行显示一个线程。否则。显示一个进程。

2.     ps xH

H shows threadsas if there were processed

这样可以查看所有存在的线程

 

3.     ps -mp <PID>

m : shows threads after processes.

查看一个进程起的线程数

5.5      linux最大线程数限制

1.     OS系统级的限制

/proc/sys/kernel/pid_max

/proc/sys/kernel/thread_max

max_user_processes(ulimit-u) #系统限制某用户下最多可以运行多少进程或线程

/proc/sys/vm/max_map_count

以及硬件内存大小(free -g)

2.     Java虚拟机本身限制

-Xms  #initial java heap size

-Xmx  #maximum java heap size

-Xss   #the stack size for each thread

6       参考资料

进程和线程:

http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/0013868322563729e03f6905ea94f0195528e3647887415000

进程与线程的一个简单解释:

http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html

线程在Linux中的实现

http://blog.csdn.net/dlutbrucezhang/article/details/10047049

Linux基础:进程管理:

http://wuchong.me/blog/2014/07/24/linux-process-manage/

Linux下查看进程和线程:

http://stark-summer.iteye.com/blog/2173704

Linux最大线程数限制及当前线程数查询:

http://blog.csdn.net/wang7dao/article/details/16369381


转载自:https://blog.csdn.net/u013933870/article/details/51693484

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值