[os] 进程

进程,线程和协程

  1. 进程是操作系统资源分配的基本单位, 线程是cpu调度的基本单位

  2. 协程是一种用户态的轻量级线程,协程的调度完全由用户控制。协程拥有自己的寄存器上下文和栈。协程调度切换没有内核切换的开销,且非常快。

  3. 进程死了那么他的线程都要进行销毁

  4. 先有进程,然后进程可以创建线程,线程是依附在进程里面的, 线程里面可以包含多个协程

  5. 进程之间不共享全局变量,线程之间共享全局变量,但是要注意资源竞争的问题

  6. 多线程开发线程之间执行是无序的,协程之间执行按照一定顺序交替执行

  7. 开辟一个协程大概需要5k空间,开辟一个线程需要512k空间, 开辟一个进程占用资源最多

  8. 在有大量异步IO操作业务的情况下,我们采用协程替换线程,可一是降低了系统内存,二是减少了系统切换开销,因此系统的性能也会提升。以一个 Web 请求的处理为例,当用户发起请求时,我们需要从后端数据库中提取所需的数据,这个操作可能会很慢。这时,如果是协程,则可以在此先中断,转而让别人先执行,待数据库的查询返回之后再返回来继续完成数据的组装并最终返回给用户。

进程线程切换的性能消耗:

1、主要的一个区别在于进程切换涉及虚拟地址空间的切换而线程不会。因为每个进程都有自己的虚拟地址空间,而线程是共享所在进程的虚拟地址空间的,因此同一个进程中的线程进行线程切换时不涉及虚拟地址空间的转换。

2、另外一个隐藏的损耗是上下文的切换会扰乱处理器的缓存机制。简单的说,一旦去切换上下文,处理器中所有已经缓存的内存地址一瞬间都作废了。还有一个显著的区别是当你改变虚拟内存空间的时候,处理的页表缓冲(processor’s Translation Lookaside Buffer (TLB))或者相当的神马东西会被全部刷新,这将导致内存的访问在一段时间内相当的低效。但是在线程的切换中,不会出现这个问题。

进程状态

  • 创建状态:进程在创建时需要申请一个空白PCB,向其中填写控制和管理进程的信息,完成资源分配。

  • 就绪状态:进程已经准备好,已分配到所需资源,只要分配到CPU就能够立即运行

  • 执行状态:得到CPU,进程进入执行状态

  • 阻塞状态:正在执行的进程由于某些事件(I/O请求,申请缓存区失败)而暂时无法运行,进程受到阻塞。在满足请求时进入就绪状态等待系统调用

  • 终止状态:进程结束,或出现错误,或被系统终止,进入终止状态。无法再执行

  • 挂起状态:暂时调到外存等待的进程状态为挂起状态,挂起态又可以进一步细分为就绪挂起、阻塞挂起两种状态

常见的通信方式

1. 管道pipe和命名管道FIFO

管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。

创建匿名管道的过程:

  • 父进程通过pipe函数创建一个管道,得到两个文件描述符指向管道的两端。

  • 父进程调用fork函数创建一个子进程,子进程会继承父进程PCB中的一部分数据,所以子进程也有两个文件描述符指向管道的两端。

  • 父进程关闭管道读端,子进程关闭管道写端(close函数关闭读/写端)。注:应该先写入数据再进行读操作
    在这里插入图片描述

有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。两者最大的区别就是打开方式匿名管道需要pipe()创建并打开;命名管道FIFO需要mkfifo()创建+open()打开。

管道读写规则

  • 当前没有数据可读时,即read要读而write未写时,read会被阻塞。
  • 当前管道已被写满,即write要写而read不读时,write被阻塞。
  • 若管道写端被关闭,则read返回0。因为不会发生写入所以类似读到文件末尾。
  • 若管道读端被关闭,则write退出。因为此时写入无任何意义,所以被OS退出。

管道(pipe)通信到底能不能同时进行读写操作?

首先作为缓冲区(缓冲区访问是互斥的)它只有满才能读,所以符合那句“因为写进程会先把缓冲区写满,然后才让读进程读”,其次同样作为缓冲区它只有空才能写,也符合书中那句“当缓冲区中还有数据时,写进程不会往缓冲区写数据”,最后回到“写进程会先把缓冲区写满”这句话,应该是即使一次数据量不够4Kb(管道容量)也会填充使得管道满,所以写程序写完之后只有一种情况:满了(无论是不够4kb还是正好4kb还是多于4kb),这也是为什么我在网上搜有的地方用原子性来描述这种操作

2. 消息队列MessageQueue

特点:

  • 与命名管道一样,消息队列进行通信的进程可以是不相关的进程。同时它们都是通过发送和接收的方式来传递数据的。在命名管道中,发送数据用write,接收数据用read,则在消息队列中,发送数据用msgsnd,接收数据用msgrcv。而且它们对每个数据都有一个最大长度的限制。

  • 消息队列是一个有消息的链表,存放在内核中并由消息队列标识符标识。

  • 消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级。

  • 消息队列独立于发送与接收进程。进程终止时,消息队列及其内容并不会被删除,而管道会被释放。

  • 消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取。管道有着严格的先入先出行为:

3. 共享存储SharedMemory+信号量Semaphore

共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,但是会出现并发问题,一般和信号量一起使用。

共享内存使用流程

  1. 创建/获取共享内存(shmget)
  2. 把共享内存连接到当前进程的地址空间(shmat)
  3. 通过指针访问共享内存
  4. 将共享内存从当前进程中分离(shmdt)
  5. 删除共享内存(shmctl)

信号量本质上是计数器,是衡量临界资源的数量的 ,可以用来控制多个进程对共享资源的访问。信号量也是一种临界资源。信号量只有两种操作,PV原语,P表示申请资源(上锁),V表示释放资源(解锁);//上锁就是能利用cpu资源对公共资源进行访问 //解锁就是即使得到cpu资源也访问不了

使用步骤

  1. 进程调用semget函数创建新的信号量集合,或者获取已有得到信号量集合。
  2. 调用semctl函数给集合中的每个信号量设置初值。
  3. 调用semop函数对集合中的信号量进行PV操作。(P加锁:对信号量-1,如果信号量的值为0,P操作会阻塞。V解锁:对信号量+1,不存在阻塞问题)。
  4. 调用semctl删除信号量集合。

4. 套接字Socket

Socket的英文原义是“插座”(还有其他含义,但是当初网络变成起名为socket主要是借用了插座的概念)。通常也称作”套接字”,主要用于解决网络进程间通信。

两个进程如果需要进行通讯最基本的一个前提能能够唯一的标示一个进程。本地进程间通信(PIPE、FIFO、message queue、semaphore、shared memary)可以通过进程ID唯一标识一个进程。网络进程间通信呢?PID只在本地唯一,网络中的两个进程PID冲突几率很大,这时候我们需要另辟它径了,我们知道IP层的ip地址可以唯一标识主机,而TCP层协议和端口号可以唯一标示主机的一个进程,这样我们可以利用ip地址+协议+端口号唯一标示网络中的一个进程。

5. 信号 ( sinal )

信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。

进程的数据结构

进程控制块PCB的作用

PCB作为进程实体的一部分,记录了操作系统所需的,用于描述进程的当前情况以及管理进程运行的全部信息,是操作系统中最重要的记录型数据结构。

PCB的作用是使一个在多道程序环境下不能独立运行的程序(含数据)成为一个能独立运行的基本单位,一个能与其他进程并发执行的进程。

具体作用进一步阐述:

1)作为独立运行基本单位的标志

系统是通过PCB感知进程的存在的,PCB已成为进程存在于系统的唯一标识

2)能实现间断性运行方式

进程因阻塞而暂停运行时 —— 必须保留运行时的CPU现场信息

系统将CPU现场信息保存在被中断进程的PCB中,供其再次被调用时恢复

3)提供进程管理所需要的信息

当调度程序调度到某进程运行时,只能根据该进程PCB中记录的程序和数据在内存或外村中的始址指针,找到相应的程序和数据

在进程运行过程中,当需要访问文件系统中的文件或I/O设备时,也需要借助于PCB中的信息

还可根据PCB中的资源清单了解到该进程所需的全部资源等。

4)提供进程调度所需要的信息

PCB中提供了进程处于何种状态的信息

在进行调度时往往还需要了解进程的其他信息 —— 优先级、等待时间、已执行时间

5)实现与其他进程的同步通信

进程同步机制是用于实现诸进程的协调运行的,在采用信号量机制时,它要求在每个进程中都设置有相应的用于同步的信号量。在PCB中还具有用于实现进程通信的区域或通信队列指针。

进程控制块PCB中的信息

1)进程标识符

用于唯一地标识一个进程。一个进程通常有两种标识符:

外部标识符内部标识符
方便用户(进程)访问方便系统对进程的使用
由字母、数字组成唯一的数字标识符,通常是一个进程的序号
创建者提供操作系统设置

2)处理机状态

主要是由处理机的各种寄存器中的内容组成的。

寄存器类型作用
通用寄存器用户程序可访问,用于暂存信息
指令计数器存放要访问的下一条指令的地址
程序状态字PSW含有状态信息,如条件码、执行方式、中断屏蔽标志等
用户栈指针用户进程与之相关的系统栈,存放过程、系统调用参数及调用地址

处理机处于执行状态时,正在处理的许多信息都是放在寄存器中。当进程被切换时,处理机状态信息都必须保存在相应的PCB中,以便在该进程重新执行时能再从断点继续执行。

3)进程调度信息

OS进行调度时 —— 须了解进程状态和有关调度的信息 ——

  • 进程状态
  • 进程优先级
  • 进程调度所需的其他信息 与采用的调度算法有关
  • 事件 阻塞原因

4)进程控制信息

  • 程序和数据的地址
  • 进程同步和通信机制
    实现进程同步和进程通信时必需的机制,如消息队列指针、信号量等(全部或部分存放在PCB)
  • 资源清单
    除了运行期间所需的全部资源(除CPU)外,还有一张已经分配到该进程的资源的清单
  • 链接指针
    给出本进程(PCB)所在队列中的下一个进程的PCB的首地址

进程控制块的组织方式

  • 线性方式
    组织在一张线性表中 —— 实现简单、开销小,每次查找需要扫描整个表 —— 适合进程数目不多的系统

  • 链接方式
    把同状态进程的PCB分别通过PCB的链接字链接成一个队列
    形成就绪队列、若干个阻塞队列、空白队列
    就绪队列 —— 按优先级排列,高的在前面
    阻塞队列 —— 按阻塞原因的不同,排成多个阻塞队列

  • 索引方式
    系统根据所有进程状态的不同,建立几张索引表,例如就绪索引表、阻塞索引表等,把各索引表在内存的首地址记录在内存的一些专用单元中。在每个索引表的表目中,记录具有相应状态的某个PCB在PCB表的地址。

临界资源

虽然多个进程可以共享系统中的各种资源,但其中许多资源一次只能为一个进程所使用,我们把一次仅允许一个进程使用的资源称为临界资源。许多物理设备都属于临界资源,如打印机等。此外,还有许多变量、数据等都可以被若干进程共享,也属于临界资源。

对临界资源的访问,必须互斥地进行,在每个进程中,访问临界资源的那段代码称为临界区。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值