线程的概念:在进程内部运行的一个执行分支(执行流),属于进程的一部分,粒度要比进程更细更轻量化
现在出现了很多新的问题,什么叫做进程内部?什么是执行分支?为什么属于进程的一部分?
下面通过画图理解的方式来解决上述的问题
目录
一、多线程理解
二、Linux进程和线程的区别
1、创建过程
2、CPU调度
3、资源承担的实体
4、从图的角度理解进程和线程
三、线程之间的私有资源和共享资源
四、创建线程(代码实现)
1、线程创建函数pthread_create
(1) 参数解析
(2) 返回值
(3) 编译方式
2、使用pthread_create创建线程
一、多线程理解
当一个进程被CPU调度的时候,其实就是进程的PCB被CPU调度了
在运行的时候,发现要处理一下其他东西,但是又不能妨碍到当前进程,按照我们以前的思路,或许就直接fork一个子进程,但是创建一个子进程的成本太高了,除了要创建一个task_struct,还要创建虚拟地址空间、页表等等。
现在我们换个方式,我们只创建一个task_struct,也就是进程控制块(PCB),然后让这个PCB指向原来的虚拟地址空间,每个区分出一小块给这个PCB使用,因为指向的是同一块虚拟地址,大部分内容是共享的(也有私有的),所以新创建出来的PCB就能看到所有的代码,现在OS只要告诉这个PCB执行哪一段代码就行
只能创建一个吗?并不,你可以创建多个,每有一根线指向虚拟内存(每存在一个PCB),这根线就代表一条执行分支(执行流),每一条执行分支我们称之为线程!因为有多个执行分支,所以我们称之为多线程!
二、Linux进程和线程的区别
1、创建过程
一个进程 = PCB(至少一个) + 虚拟内存 + 页表 + 代码和数据,所以进程在被创建的时候,先要创建PCB、虚拟内存、页表,然后通过页表建立虚拟内存和物理内存之间的映射关系。
一个线程只是进程的一个执行分支,即一个PCB代表一个线程,所以创建一个线程只需要新增一个PCB
2、CPU调度
以前常说,把xx进程加入到运行队列中,这种说法是错误的!!CPU调度的不是进程,线程才是CPU调度的基本单位!加入到运行队列的是PCB;进程是系统资源分配的基本单位!
3、资源承担的实体
进程和线程都是资源承担的实体,区别在于,进程是承担系统资源的基本实体,一个进程在被创建的时候OS要创建虚拟地址、页表,这些系统资源是由OS分配的。
线程是承担进程资源的基本实体!因为是进程把一部分资源拿出来分给新增的PCB,才有了新的线程。
4、从图的角度理解进程和线程
进程是一个大家庭,线程只是进程的一个执行分支
三、线程之间的私有资源和共享资源
一个PCB代表一个线程,而且指向的是同一个虚拟地址,那是不是所有的资源都是共享的,比如在全局区设置一个变量,其他线程也能看到??
答案是对的!大部分的资源,线程之间都是可以共享的,比如进程的代码、全局变量等,我们只需要了解线程的私有资源有哪些即可
进程的私有资源 ——》线程ID、栈、信号屏蔽字、调度优先级、上下文数据
四、创建线程(代码实现)
从上面我们了解到,线程本质是轻量级的进程,并没有为线程设置专门的数据结构,自然也就不存在创建线程的系统调用,只有创建和控制进程的系统调用,所以后来的系统工程师将这些进程的系统调用打包成了第三方库pthread
因此下面编译线程创建函数时,需要手动链接到第三方库 pthread
1、线程创建函数pthread_create
下面我们主要介绍这个函数的参数,以及编译方式
(1) 参数解析
第一个参数是线程ID
第二个参数是线程属性,一般设置为NULL
第三个参数是要线程执行进程中的哪一部分代码,一般写函数的地址
第四个参数是要给线程传递的参数
(2) 返回值
创建成功返回0,创建失败返回一个错误码
(3) 编译方式
线程创建函数属于第三方库pthread,所以在使用的时候需要动态链接到第三方库
2、使用pthread_create创建线程
下面就通过实际案例来演示一下多线程,多线程是多条执行支路同时运行,其实站在CPU的角度,依然是一个PCB的运行时间片到了,就轮到下一个PCB,只不过在我们看来就相当于在同时运行
核心代码和Makefile文件的代码如下
测试结果如下,我们发现主线程和子进程同属于一个进程
那我要怎么知道两个是不同的线程呢??重新运行执行文件,然后新开一个窗口,在命令行输入
ps -aL #-L查看轻量级进程
LWP:Light Weight Process(轻量级进程)
我们会发现PID是一样的,但是LWP是不同的,这就证明我们的子线程创建成功了,此时依旧是一个进程,但是有两个执行流



