跳转到主内容
极星编程网:以代码为星,赴技术山海!

怎么理解线程,进程和pthread库?创建、等待、退出线程详解!

一、线程概念

线程是啥?先来简单了解一下:

进程?先来简单了解一下:

这里只是意会一下,不是说进程就只有一个PCB+进程地址空间而已(进程 = 内核数据结构 + 可执行程序),这样画是比较简单示意。

创建进程:进程创建的时空成本是较高的,有各种数据结构的创建,数据的加载。

如地址空间就是父子进程各有一个:

文件系统也是需要各有一个的:

关于这一点,进程地址空间和文件系统这两个文章中都可见端倪,上面两个图都是从这两个文中拿来的(文章都很短,如果有兴趣可以翻翻)。

创建线程:地址空间和地址空间上的虚拟地址,本质是一种“资源”,是资源就可以共享。

将代码分成几份,并创建对应个数的PCB,分别执行不同的代码区,就可以将串行执行变成了并发执行了。

我们的代码在进程中,全都是串行调用的,创建进程,是为了多执行流并发执行,所以创建进程和创建线程都可以,但是显然创建一个线程的成本要低得多啊!

2. linux 对线程的设计

操作系统(OS)要对线程进行管理——先描述,再组织。

下面我们来看,描述线程的结构体:

描述线程的结构体中要有各种信息,如对应的进程,线程标识符,线程优先级,上下文状态等,大概就如下:

我们觉得这样还是复杂,而且我们发现,线程中的很多信息是和进程的重合的,所以Linux的设计者认为,进程和线程都是执行流,有很高的相似性,没必要单独设计数据结构和算法,可以直接复用代码,使用进程来模拟线程。如下:

3. 线程

所以,我们可以了解到线程:

线程是进程内部的一个执行分支,线程在进程的地址空间内运行。

线程是CPU调度的基本单位。

CPU调度是让PCB排队的,现在线程就是复用的进程的PCB, 所以CPU是可以调度一个个线程的。

二、进程和线程

1. 进程和线程的关系

进程是承担分配系统资源的基本实体,而线程是进程内的一个执行分支。所以线程算是包含在进程中的。

2. 进程的调度

CPU不关心你是进程还是线程,按正常的调度算法执行就行了(当然有些属于线程、进程的细节会区别处理)。

3. 轻量级进程

从上面,我们可以看到,CPU调度的执行流要么就是进程,要不就是线程。

对于Linux来说,所有的调度执行流都叫做轻量级进程,不区分进程和线程了。在Linux中,线程是用进程模拟的,在CPU看来,看到的PCB都比传统的进程更轻量化,所以叫“轻量级进程”。

对于操作系统,进程内部只有一个执行流,那这个执行流就叫进程:

进程内部有多个执行流,那每个执行流都叫做线程:

三、pthread库

1. pthread 库的作用

上面我们说过了,Linux中线程是用进程模拟而成的,那么使用的时候就会跟纯粹的线程使用有区别。

在用户层,用户只认识进程和线程,用户可不管你底层是怎么封装的,用户我就只会用线程,可不会用什么用进程模拟的线程。

在内核层,我的线程是用进程模拟的,所有的在我这里都叫轻量级进程,我提供的也是轻量级进程的接口。

所以,就需要一个中间层,将内核有的和用户需求的连接起来。这就是pthread库的作用。

2. 手动链接 pthread库

多线程程序,都要链接pthread库。因为转换的方法都在这个库中,如果不链接这个库,那程序中用到的线程函数根本找不到。

其实我们使用库函数也是有链接C/C++的库的,但是因为我们使用的编译器gcc和g++是编译C/C++的,所以形成可执行程序时自动就链接C/C++的库了,所以我们不用手动链接。

但线程的库可不是必须的,用不到线程部分的程序在编译时就不需要链接原生线程库,你用线程的才需要这个库,所以既然不是必须的,那就交给用户手动链接了。

四、创建线程

1. pthread_create()

想创建一个新线程,使用的是pthread_create()接口。

2. 函数的使用

pthread_create(&rid,nullptr,pfunc,(void*)

相关文章