商丘网站公司电话号码,厚街网站建设公司,wordpress 粘贴表格,dedecms 做微网站上篇文章#xff1a;Linux操作系统5- 补充知识#xff08;可重入函数#xff0c;volatile关键字#xff0c;SIGCHLD信号#xff09;-CSDN博客 本篇Gitee仓库#xff1a;myLerningCode/l27 橘子真甜/Linux操作系统与网络编程学习 - 码云 - 开源中国 (gitee.com) 目录 一.… 上篇文章Linux操作系统5- 补充知识可重入函数volatile关键字SIGCHLD信号-CSDN博客 本篇Gitee仓库myLerningCode/l27 · 橘子真甜/Linux操作系统与网络编程学习 - 码云 - 开源中国 (gitee.com) 目录 一. Linux中的线程
1.1 线程的概念
1.2 OS管理线程的方式
1.3 线程与进程
二. Linux中创建线程 ⭐
1.1 pthread_create系统调用
1.2 线程之间的资源共享
1.3 线程的私有资源⭐
三. 线程的优缺点 ⭐
3.1 线程的优点
3.2 线程的缺点 一. Linux中的线程
1.1 线程的概念 进程是OS调度的基本单位进程 PCB 进程对应数据与代码。而线程是进程内的一个执行流。 对于一个进程来说进程是通过虚拟内存与页表的映射来访问物理内存的。所以一个进程的虚拟内存决定了这个进程所拥有的资源。 在linux中对于一个进程如果定义多个PCB指向同一个虚拟内存。让后让这些PCB指向不同的物理内存区域这些PCB就是线程。 通过虚拟内存和页表的映射我们对一个进程的资源进行了划分这样一来单个PCB的粒度就比整个进程粒度低。 关系如下图 其中所有的PCB 进程虚拟内存 页表 进程对应数据代码 一个进程 单个PCB 单个PCB占用的虚拟内存 页表 线程对应数据代码 一个线程
1.2 OS管理线程的方式 OS通过PCB来管理进程同样所有的线程也需要被OS管理。 如果想要管理线程首先需要设计特定的内核数据结构来表示线程对象即设计一个TCB线程控制块。 Windows就是这样设计线程的。不过需要重新设计一个内核数据结构太麻烦了 线程和进程有很多资源是一样的比如id状态优先级上下文页表虚拟内存文件描述符... 因此Linux工程师使用直接复用进程的PCB使用PCB来表示线程。而cpu只关心PCB不关心你是线程还是进程。 所以线程在进程的地址空间中运行拥有该进程一部分虚拟内存和资源。
1.3 线程与进程 进程是承担系统分配资源的基本单位PCB虚拟内存页表代码和数据等资源 而线程是CPU调度的基本单位在linux中称为轻量级进程\
总结 1 在Linux中没有严格的线程只有轻量级进程使用进程来模拟线程。 2 线程是cpu调度的基本单位进程是系统分配资源的基本单位 linux使用轻量级进程模拟线程的好处降低维护成本提高效率 linux使用轻量级进程模型线程的坏处用户只认线程不认进程所以linux需要为轻量级进程和线程之间提供线程库 二. Linux中创建线程 ⭐
1.1 pthread_create系统调用 使用man手册查看如下 可以看到使用这个接口需要在编译的时候带上参数 -pthread
//头文件
#include pthread.h
//库名称
pthreadint pthread_creat(pthread_t *thread, const pthread_attr_t *attr, void* (*start_routine)(void*), void *arg)//参数说明
thread 用于定义线程tid的地址是输入输出型参数调用后tid获取线程的id
attr 用于控制线程的属性我们一般设置为0.表示默认属性
start_routine 线程运行函数的指针即线程的执行流函数。调用后线程就执行该函数内部的代码
arg 线程函数start_routine的参数
测试代码
makefile文件
test:test.cppg -o $ $^ -lpthread -stdc11
.PHONY:clean
clean:rm -rf test 在Linux中使用线程必须要使用-l pthread用于链接原生线程库
test.cpp
#include iostream#include unistd.h
#include pthread.hvoid *start_routine(void *args)
{const char *name static_castconst char *(args);while (true){std::cout 我是新线程,我的名字是 name pid为: getpid() std::endl;sleep(1);}
}int main()
{pthread_t tid; // 定义线程tidpthread_create(tid, nullptr, start_routine, (void *)I am thread); // 创建线程while (true){std::cout 我是主线程,我的pid为: getpid() std::endl;sleep(1);}return 0;
}
测试结果如下 可以看到主线程和新线程是并发执行的。 并且使用 ps axj 命令查看只有一个test进程二使用 ps -aL查看线程可以看到test进程内有两个线程它们的pid是由于的而LWP是不一样的 CPU调度的时候使用LWP来标识每一个线程。并且以进程中的主线程的LWP就是这个进程的pid。 1.2 线程之间的资源共享 线程被创建后会共享全局变量函数等资源。
测试代码:
#include iostream#include unistd.h
#include pthread.h// 全局变量
std::string name 线程基础;// 全局函数
inline void f()
{std::cout 调用全局函数 读取全局变量: name std::endl;
}void *start_routine(void *args)
{const char *name static_castconst char *(args);while (true){std::cout 我是新线程,我的名字是 name pid为: getpid();f();sleep(1);}
}int main()
{pthread_t tid; // 定义线程tidpthread_create(tid, nullptr, start_routine, (void *)I am thread); // 创建线程while (true){std::cout 我是主线程,我的pid为: getpid();f();sleep(1);}return 0;
}
测试结果 可以说明线程能够调用全局函数也可以读写全局变量。这说明两个线程之间如果想要进行通信是非常简单的。不像进程间通信需要通过OS创建资源然后让两个进程看到同一份资源 线程之间共享 虚拟内存的代码区全局变量区堆区文件信号处理 1.3 线程的私有资源⭐ 线程之间共享全局资源每一个线程也有着自己独立的资源。 1 线程是CUP调度的基本单位每一个线程有着自己的PCB有自己独立的id优先级 2 线程有着自己的上下文结构这体现线程切换的动态属性。上下文是指线程切换的时候cpu寄存器中的值PCB的状态PCB对应的堆栈结构。 3 每一个线程都有自己独立的栈结构。这个栈结构位于共享区 三. 线程的优缺点 ⭐
3.1 线程的优点 1 线程的创建消耗比进程低很多 2 线程切换与进程切换相比需要OS工作更少消耗低 为什么线程切换比进程切换开销小 1 进程切换需要切换进程的虚拟内存页表切换所有的PCB和上下文 2 线程切换只需要切换一个PCB和线程自己的上下文 3 线程切换不太用更新catch进程切换需要更新所有的catch。catch是高速缓存CPU通过catch与内存交流一个稳定的进程会缓存很多热点数据这样一来catch的命中率高线程切换不怎么影响catch的命中率。 如果切换了进程需要全部更新catch这个需要消耗较多的时间 3.2 线程的缺点 1 如果创建的线程过多会造成一定的性能损失 2 线程会导致代码的健壮性降低因为一个线程异常退出了会导致整个进程退出线程崩溃了整个进程会崩溃 3 线程之间共享资源需要考虑访问控制和同步互斥问题