文章目录

  • 一. 什么是操作系统
  • 二. 进程和线程
    • 1. 进程
    • 2. 线程
    • 3. 进程的管理
      • 3.1 PBC中的一些属性
      • 3.2 并发和并行
      • 3.3 进程的调度
      • 3.4 内存管理
      • 3.5 进程间的通信
      • 3.6 并发编程
    • 4. 进程与线程的区别

一. 什么是操作系统

操作系统本质上是一个软件, 发挥的是管理作用, 可以管理软件和硬件, 让其有条不紊的运行和使用.

对于操作系统下层, 操作系统需要管理好硬件; 对于操作系统上层要给软件提供稳定的运行环境, 所以操作系统是软件, 硬件, 用户之间交互的媒介.

硬件设备: 实体设备, 比如电脑后盖打开看到的都是硬件设备.

驱动程序: 硬件厂商在开发硬件的同时会提供驱动程序, 电脑安装了对应的驱动程序, 才能让系统正确的识别硬件设备.

操作系统内核: 是操作系统的核心功能, 承上启下.

系统调用: 操作系统给应用程序提供的一些API接口, 比如有个程序想操作一下硬件设备, 就需要先通过系统调用, 把操作命令告诉给系统内核, 内核调用驱动程序, 进一步的操作硬件设备.

应用程序:QQ , 所写的Java代码等都是应用程序.

常见的操作系统:

Windows:windows98, 2000, xp, vista,win7, win10, win11(最熟悉的操作系统).

Linux: 特别适合进行开发和部署(程序员必须掌握的系统).

Mac: 苹果电脑用的系统, 和Linux有一些相似之处.

还有一些手机上运行系统;Android ,IOS等.

二. 进程和线程

1. 进程

简单来说进程就是正在运行的程序, 通过双击一个可执行文件(.exe), 操作系统就会把这个可执行文件加载到内存上, 并在CPU上执行可执行文件中的指令, 此时这个exe就跑起来了, 就成为一个正在运行的程序, 也称作一个进程(process), 也叫做一个任务.

现在的很多电脑都是多进程模式的, 宏观上, 可以有很多个进程同时执行.

上面一部分进程是我们自己去执行应用的可执行文件, 而另一部分是操作系统自动启动的进程.

2. 线程

线程是进程内部的一部分, 将进程类比作一个工厂, 那么线程就是工厂中的生产线, 所以一个进程可以包括很多个线程, 一个进程至少拥有一个线程.

我们日常所写的java代码, 其实最终都是通过java进程(jvm)跑起来的.

3. 进程的管理

进程是一个重要的"软件资源", 是由操作系统内核负责管理的, 进程中含有一个或者多个线程, 在进程中开启第一个线程时, 需要进行资源的分配, 之后进程中开启的其他线程复用的都是同一一份资源.

线程是通过结构体(C语言)来描述的(操作系统基本上都是通过C/C++来实现的), 这个结构体也被称为进程控制块(PCB), 这若干个结构体就描述了进程, 对进程进行描述后, 然后就是组织线程, 线程的本质上也是数据, 那么对数据的组织需要通过数据结构来进行组织, 在Linux系统中是通过双链表来组织线程的, 也就是通过一个双向链表将多个PBC给串到一起.

创建一个线程, 本质上就是创建一个PCB这样的结构体对象, 把它插入到链表中.

销毁一个线程, 本质上就是把链表上的 PCB节点删除掉.

任务管理器查看到进程列表, 本质上就是遍历这个PCB链表.

所以对线程的增删查改本质上就是对双链表进行增删查改, 当然这个双链表是复杂的双链表, 但是对线程的操作的基本思路和操作双链表是一样的.]

3.1 PBC中的一些属性

PCB里包含的属性是非常多的, 下面介绍的是一些核心属性.

进程id(pid): 进程的一个身份标识符, 是一个唯一的数字.

内存指针: 指明了自己分配到的内存.

文件描述符表: 硬盘上的文件等其他资源.

一个进程一运行, 操作系统就会自动打开至少3个文件: 标准输入(System.in), 标准输出(System.out), 标准错误(System.err).

想要一个进程正常工作就需要为这个进程分配资源, 包括但不限于内存, 硬盘, CPU.

3.2 并发和并行

分配资源时, 对于其他资源都比较好分配, 但CPU资源是不太好分配的: 电脑中进程可能有几十上百个, 电脑的CPU(现在电脑大多是多核CPU)资源是很有限的, 远不够给这些进程同时分配.

但我们又希望进程都是同时运行的, 上面说过, 一个进程中可以有多个线程, 我们可以让多个线程去并发执行(分时复用), 那么什么是并发呢?
并行性和并发性是既相似又有区别的两个概念, 并行性是指两个或多个事件在同一时刻发生, 而并发性是指两个或多个事件在同一时间间隔内发生.

从宏观上来讲, 并行与并发没有区别, 或者说是我们肉体凡胎感知不到.
从微观上来讲, 并行表示两个CPU核心同时运行两个任务的代码, 并发表示一个CPU核心先运行任务A的代码,再运行任务B的代码, 也就是多个任务能够在CPU核心上快速的切换运行; 只要运行得足够快, 就可以认为多个任务在同时运行.

3.3 进程的调度

线程是系统调度执行的最基本单位, 为了方便描述进程的调度, 这里假定此处的进程只有一个线程, 这样就可以将线程的调度视为进程的调度, 这里我们谈到的进程调度是基于多任务操作系统, 就是从宏观上看, 同一时间能够同时运行多个进程.

进程的状态:

  • 就绪状态: 准备就绪, 随时等待CPU调度执行.
  • 运行状态: 线程正在CPU上运行的状态.
  • 阻塞状态: 进程由于一系列因素无法及时响应调度, 短时间内无法在CPU上执行.

优先级:

多个进程, 操作系统进行调度的时候, 并不是完全平等, 而是有一定的优先级的.

上下文:

表示上一次进程被调出CPU的时候, 程序的运行状态(将进程的 “中间状态” 保存下来), 这样下一次这个进程调度到CPU时就能接着上次的状态继续运行.

进程的上下文, 就是CPU中的各个寄存器的值, 所以进程调出CPU之前, 需要先把CPU上寄存器上的数据保存到内存中,相当于存档; 下次该进程再被调进CPU时, 就可以根据上次储存在内存中的数据恢复到寄存器中, 相当于读档.

记账信息:

操作系统统计每个进程在CPU上的占用的时间以及指令数目, 根据这个来决定下一阶段如何调度.

举一个形象的场景来进行理解:

比如有三个进程A, B, C, 不妨将操作系统比作一个小姐姐, 将线程A, B, C比作三位小哥哥, A特别帅, B特别有钱, C特别会舔.

这位小姐姐同时与A, B, C 一起谈恋爱, 那么这里小姐姐姐如何同时谈三个男朋友呢, 其实也很简单, 小姐姐只需要做好对ABC的时间管理即可, 让ABC都不知道对方的存在.

所以小姐姐需要妥善地安排与三位小哥哥谈恋爱的时间, 确保时间不能重合, 比如:
因为小姐姐特别喜欢帅的, 其次是有钱的, 最后是会舔的, 所以小姐姐对A, B, C的安排有了优先级, 给A安排的时间多一点, B次之, C最后。
此时小姐姐做了一周时间的规划表, 属实是时间管理大师了.

时间 计划
星期一 与C谈恋爱
星期二到星期三 与B谈恋爱
星期四到星期六 与A谈恋爱
星期日 休息

此时小姐姐这个时间规划, 就是可以理解为进程的调度, 谈恋爱期间, 如果B需要出差一个月, 那么在小姐姐眼中, B这种状态就称为阻塞或睡眠状态, 如果正常, 男朋友可以随叫随到, 则在小姐姐眼中就称这种状态为就绪状态, 小姐姐正在与A谈恋爱的状态称为运行状态.

小姐姐与三位小哥哥同时谈恋爱, 总会有时候"串戏", 比如A需要带小姐姐回家见家长, 让小姐姐准备准备一份礼物, 而B想要带小姐姐去三亚旅游, 要小姐姐做好准备,但是有一天A问小姐姐准备好没?小姐姐说我买了两件泳衣, 这样就 “串戏” 了, 小姐姐最后总算将A忽悠过去了, 小姐姐吸取了教训, 之后每次都会将上次和某人进行到啥程度了, 是否有啥未完成的任务之类的记录下来, 下次约会的时候, 能够恢复出之前的状态, 这样小姐姐在之后就不会串戏了, 这个场景就可以看作是操作系统中的上下文了.

小姐姐和ABC都已经相处了一段时间了, 就需要去想一想, 也就是每隔一段时间,做个总结, 统计一下在每个人身上大概花费了多少精力, 然后根据这个总结做出下一个阶段的时间安排, 要保证和每个人要始终保持好一个合适的尺度, 不能太远也不能太近, 这便可以看作是进程调度中的记账信息了.

3.4 内存管理

我们通过代码程序所获取的内存地址, 其实不是硬件上真真实实的地址, 而是经过一些计算整合出来的虚拟地址.

内存(物理上是一个内存条), 其中可以存很多数据, 内存就可以想象成是一个大走廊, 走廊非常长, 有很多房间, 每个房间大小是1Byte, 每个房间还有个编号, 从0开始依次累加, 这个内存编号就是"地址", 这个地址也就"物理地址".

下面张图就是真实的内存条.

内存有个了不起的特性就是随机访问, 访问内存上的任意地址的数据, 速度都极快, 时间上都差不多, 正是这个特点造就了数组取下标操作的时间复杂度是 O(1).

我们的程序如果直接访问的就是物理地址, 如果程序正常运行还好, 但如果代码出bug了, 就可能出现越界访问的情况, 就可能会对其他进程的数据做出一些操作, 比如进程1的指针变量因为bug变成了0x8000, 也就是说这里明明是进程1的bug却把进程给搞坏了.

为了避免这种问题的出现, 针对进程使用的内存空间进行了"隔离", 引入了虚拟地址空间.

代码里不再直接使用真实的物理地址了, 而是使用虚拟的地址; 由操作系统和专门的硬件设备负责进行虚拟地址到物理地址的转换.

这里引入的虚拟空间地址, 对物理地址进行隐藏和隔离, 避免进程之间的相互影响, MMU硬件设备(很多时候是集成在CPU里的), 可以让虚拟地址和物理地址的转换速度更快.

当我们操作系统内核发现转换后的地址超过了该进程物理地址的访问范围, 就会直接向进程反馈一个错误, 进而引发该进程崩溃, 不会影响到其他进程.

3.5 进程间的通信

上面引入的虚拟空间地址使进程之间相互隔离, 这就导致每个进程只能访问自己的那一块地址空间的数据, 无法访问其他进程的地址空间的数据, 这样当一个进程崩溃时, 另外的进程不会受到影响.

但是, 在实际开发工作中, 有些时候进程间需要进行数据的交互的, 为了实现进程间的通信, 操作系统提供了一块多个进程都能访问到的 “公共空间” , 进程A可以先把数据存入 “公共空间” , 然后进程B可以到 “公共空间” 取出数据, 这样就实现了进程间的通信.

操作系统提供的 “公共空间/通信方式” 有很多种具体的体现形式, 现在最常见的进程间通信机制有:

  • 基于文件操作.
  • 基于网络操作(socket).

3.6 并发编程

CPU进入了多核心的时代, 要想进一步提高程序的执行速度, 就需要充分的利用CPU的多核资源, 这个时候并发编程就应用而生了; 引入进程的概念, 最主要的目的是为了解决"并发编程" 这样的问题, 让代码程序能够把这些CPU核心充分利用.

其实多进程编程已经可以将cpu的多核资源利用起来了, 可以解决并发编程的问题了, 但还是存在一些问题, 进程的创建需要分配资源, 进程的销毁需要回收资源, 而分配和回收资源的效率相对来说是比较低的, 也就是说进程的创建,销毁,调度的开销都是比较大的, 成本是比较高的.

问题解决:

  • 方案1:

使用进程池, 与字符串常量池类似, 将已经创建的进程存入常量池, 后面需要使用时直接加载资源即可, 但是也存在问题, 那就是闲置的进程也会占用资源, 相当于空间换时间, 消耗空间来提升效率.

  • 方案2:

使用多线程来实现并发编程, 因为进程包含线程, 一个进程中包含多个线程,所以线程比进程更轻量,因此也将线程称为 “轻量级进程”, 线程把申请资源/释放资源的操作给省下了, 这就致使线程的创建,销毁,调度的成本很低, 速度更快, 所以使用多线程实现并发编程比多进程更加合适.

类比以下场景进行理解多线程:

我们把进程看做一个工厂, 线程看作工厂中的生产线, 比如有一个任务需要生产一些硬件设备, 想要生产速度更快, 有两个方案:

  1. 建造两个工厂进行生产.
  2. 只建造一个工厂, 多增加一批生产线.

上面两种方案都以相同的效率生产设备, 但是方案1需要多建造一个工厂; 方案2只需要增加一批生产线, 复用同一个工厂的资源即可(原料, 运输资源等), 而方案1较之方案2的付出的代价更大, 类比一下方案1表示就是多进程实现并发编程, 方案2表示的是多线程实现并发编程.

4. 进程与线程的区别

  • 进程包含线程, 一个进程包含一个或者多个线程.
  • 进程间是独立的, 每个进程都有独立的地址空间, 一个进程崩溃不会影响其余的进程, 但是在同一个进程中, 多个线程是共用的是一块资源, 一个线程崩溃, 这个进程中的所有线程都会崩溃.
  • 进程是操作系统分配资源的基本单位, 线程是操作系统调度执行的基本单位.
  • 多进程相比于多线程不会存在线程安全的问题, 多线程编程可能存在线程安全问题.

操作系统之线程和进程相关推荐

  1. java 线程 操作系统线程_线程基础:线程(1)——操作系统和线程原理

    1.概述 我在写"系统间通信技术专栏"的时候,收到很多读者的反馈.其中有一部分读者希望我抽空写一写自己关于对Java线程的使用经验和总结.巧的是,这个月我所在的技术团队也有很多同事 ...

  2. Python | 面试必问,线程与进程的区别,Python中如何创建多线程?

    其实关于元类还有很多种用法,比如说如何在元类当中设置参数啦,以及一些规约的用法等等.只不过这些用法比较小众,使用频率非常低,所以我们 不过多阐述 了,可以在用到的时候再去详细了解.我想只要大家理解了元 ...

  3. 现代操作系统:第二章 进程和线程

    操作系统中最核心的概念就是进程,这是对正在运行的程序的抽象. 进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位. 2.1 进程 操作系统最核心的概念就是进程,它是对正在运行的程序的一 ...

  4. 操作系统原理:进程与线程、进程生命周期、线程的类型

    一.进程定义 进程可以看成程序的执行过程,可以展示在当前时刻的执行状态.它是程序在一个数据集合上的一次动态执行的过程.这个数据集合通常包含存放可执行代码的代码段,存放初始化全局变量和初始化静态局部变量 ...

  5. 操作系统:第二章 进程管理1 - 进程、线程

    本文已收录至 Github(MD-Notes),若博客中图片打不开,可以来我的 Github 仓库,包含了完整图文:https://github.com/HanquanHq/MD-Notes,涵盖了互 ...

  6. 操作系统难点解析之进程和线程

    为什么80%的码农都做不了架构师?>>>    操作系统难点解析之进程和线程 关于操作系统,其中最为核心的概念就是进程和线程(轻量级进程).在进程和线程的基础之上,进而衍生出了并发和 ...

  7. 操作系统 --- 线程与进程的比较

    如果说,在操作系统中引入进程的目的是为了使多个程序能并发执行,以提高资源利用率和系统吞吐量,那么在操作系统中再引入线程,则是为了减少程序在并发执行时所付出的时空开销,使OS(操作系统)具有更好的并发性 ...

  8. 操作系统(7)-进程、线程、协程的区别

    进程 不共享任何状态 调度由操作系统完成 有独立的内存空间(上下文切换的时候需要保存栈.cpu寄存器.虚拟内存.以及打开的相关句柄等信息,开销大) 通讯主要通过信号传递的方式来实现(实现方式有多种,信 ...

  9. 操作系统(1)-进程与线程

    一.进程和线程的定义 1.进程 我们都知道计算机的核心是CPU,它承担了所有的计算任务,而操作系统是计算机的管理者,它负责任务的调度,资源的分配和管理,统领整个计算机硬件:应用程序是具有某种功能的程序 ...

最新文章

  1. Amazon EC2云端服务器的使用方法
  2. 【C++ 语言】容器 ( queue 队列 | stack 栈 | priority_queue 优先级队列 | set 集合 | 容器遍历 | map )
  3. antlr idea 入门_ANTLR入门:构建简单的表达语言
  4. ubuntu 虚拟机 串口 socket_上篇 | 虚拟机Ubuntu向开发板AMR传送文件
  5. Python编程基础04:输入与输出
  6. 一个服务调用另一个服务的步骤
  7. JavaWeb开发通过Socket编程实现网页访问(附源代码)
  8. 安装SQL Server 2012过程中出现“启用windows功能NetFx3时出错”
  9. 数据库课程设计:会议预约管理系统(Java+MySQL)
  10. 针对宝塔面板一个站点多个域名使用SSL证书的解决方案
  11. JAVA微信会员卡接口踩坑
  12. KafkaConsumer实现精确的latest(结尾)开始消费
  13. 计算机系统最主要的弱点,计算机安全弱点及其对应关键技术研究
  14. Android Nginx Retrofit+Okhttp.HTTP 504 Unsatisfiable Request (only-if-cached)
  15. 纯净ROM如何制作?手把手教你一键精简内置推广
  16. 【Python】P1008 [NOIP1998 普及组] 三连击
  17. Instruments 调试
  18. 论文中写伪代码的工具
  19. 让程序自动玩数独游戏让你秒变骨灰级数独玩家
  20. 协和谬误:欲罢不能的困局(博弈论的诡计)

热门文章

  1. 冲压模具中的回弹解决办法
  2. Freemarker生成word:导出多张图片list、同时导出文字+图片的list
  3. html 根据坐标画多边形,Canvas多边形绘制的实现方法
  4. 在线教育-谷粒学院学习笔记(八)
  5. 邮箱163登录入口?邮箱163注册格式是什么?
  6. crt和zoc7的快捷键记录
  7. Android 仿京东商品分类(简单实现 仅供参考)
  8. Java时间操作类库—Joda-Time
  9. Python之第六章 内置容器 --- 字典(映射)
  10. 计算机硬件检测与维修理论试题,计算机硬件检测与维修试题10.doc