IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> linux中线程和进程的区别深度剖析底层实现 -> 正文阅读

[系统运维]linux中线程和进程的区别深度剖析底层实现

前言

在没有仔细了解过Linux的进程和线程实现机制之前,看过很多关于进程和线程的博客,从这些博客中我大概知道进程和线程的区别

1、进程拥有独立的内存空间,因此进程与进程之间相对独立,互不影响,但缺点进程间的通信相对复杂

2、同一进程的线程共享进程的内存和资源(线程有自己的私有空间),因此同一进程下的线程之间的通信很方便,缺点是一个线程的出问题会影响到同一进程下的其他线程

看完这些关于进程和线程的博客后,我有一些疑惑如下:

1、细心的小伙伴会发现,在探讨进程和线程的区别时,默认考虑的是同一进程下的线程,那么不同进程下的线程又当如何通信?

2、在初学Linux时,就被告知Linux是一个多进程的操作系统,那么线程在Linux中又是如何体现?

3、Linux中进程和线程的底层实现逻辑是怎么样?

Linux中进程和线程的共性

在Linux中进程和线程,到了内核里面,统一被称为任务,由结构体task_struct进行描述,也就是说关于任务的管理,最终是对结构体task_struct进行管理

task_struct结构分布图如下所示:

如何管理?

1、每一个任务都有一个自己的专属ID,通过这个ID我们可以判断出这是线程任务,还是进程任务(pid是process id,tgid是thread group )

pid_t pid;
pid_t tgid;
struct task_struct *group_leader; 

如上所示,task_struct中关于ID的变量有三个,如果进程,只有主线程(也就是进程没有创建其他的线程),那pid是自己,tgid是自己,group_leader指向的还是自己。如果进程创建了其他线程,那么这个线程对应的task_struct结构体中的pid代表自己,而tgid则等于进程的主线程的pid,group_leader指向的就是进程的主线程。

image-20220510164326295

这提一点额外的东西,看不懂没关系,一个进程里可以有很多线程,但无论是线程还是进程在内核中都通过task_strut来描述,在这个结构体中可以做什么操作,比如设置一个线程组,将同一个进程的线程,都指向这个线程组。内核可以通过操作线程组,对所以线程进行统一操作(说这个是为了表达,一个系统对于众多资源的管理思路,通过分组,分区,分块将具有相同特性的资源,通过标识符/链表之类的进行归类…)

Linux中进程的创建

首先明确一点,所以进程(0号进程除外)的创建最终通过fork实现的(fork不是一个函数哈,你可以理解为一个操作,这个操作由一系列函数来完成)

以应用层创建一个进程为例,我们来看一看,整个函数调用的过程

fork -> sys_call_table -> sys_fork -> _do_fork->copy_process

1、

copy_process

....->dup_task_struct dup_task_struct完成了对task_struct的建立(从父进程复制来的),同时创建内核栈

...->copy_creds

...->sched_fork 设置进程状态/初始化优先级/设置调度类

....…复制一个进程的文件信息/复制一个进程的目录信息 …

2、

接下来,就是根据初始化的调度类型,将这个进程加入到相应的调度队列中

其实说白了,一个进程的产生,是通过对另一个进程进行复制,然后再进行初始化,将一些不能的共用的资源,重新申请一份给新的进程,具体复制哪些信息,从第一张图中可以看出,这篇文章主要将进程和线程的实现区别,所以这里就不展开了


Linux中线程的实现

主线程和进程说的是一个东西?我感觉是,但不确定

思考:无论是进程还是线程,在内核里面都是任务,管起来不是都一样吗?如果不一样,那怎么在内核里面加以区分呢?

与进程不同的是,线程不是一个完全由内核实现的机制,它是由内核态和用户态合作完成的。

用户态:在用户态中创建线程的栈

这里值的一说的是,为什么要先创建线程栈?虽然一个进程的所有线程共用进程的内存空间,但不同的线程最终是要去执行不同的任务的,栈是时刻要用的东西如果共用那就乱套了,所以线程栈就是线程的私有空间是在进程的堆空间申请的内存。 先创建线程栈也是为了将子线程和主线程(主线程栈跟进程是一样的)进行区分,如果此时不进行区分,那么在内存态中创建的资源属于谁?要知道线程的所有东西都是用的进程的 (说得有点乱,不知道说明了没,哈哈)

内核态:创建进程的话,调用的系统调用是fork,在copy_process函数里面,会将五大结构files_struct、fs_struct、sighand_struct、signal_struct、mm_struct都复制一遍,从此父进程和子进程各用各的数据结构。而创建线程的话,调用的是系统调用clone,在copy_process函数里面, 五大结构仅仅是引用计数加一,也即线程共享进程的数据结构。

总结

进程和线程的实现函数流程图如下,创建进程的话,调用的系统调用是fork,在copy_process函数里面,会将五大结构files_struct、fs_struct、sighand_struct、signal_struct、mm_struct都复制一遍,从此父进程和子进程各用各的数据结构。而创建线程的话,调用的是系统调用clone,在copy_process函数里面, 五大结构仅仅是引用计数加一,也即线程共享进程的数据结构。

image-20220510205039051
参考资料
极客时间:趣谈Linux操作系统

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-05-12 16:43:29  更:2022-05-12 16:44:29 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 15:18:29-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码