1、进程简介
运行中的程序的一个副本,是被载入内存的一个指令集合,是资源分配的单位
- 进程ID(Process ID,PID)号码被用来标记各个进程
- UID、GID、和SELinux语境决定对文件系统的存取和访问权限
- 通常从执行进程的用户来继承
- 存在生命周期
进程创建:
- init:第一个进程,从 CentOS7 以后为systemd
- 进程:都由其父进程创建,fork(),父子关系,CoW:Copy On Write
进程
进程是一个具有一定独立功能的程序在一个数据集上的一次动态执行的过程,是操作系统进行资源分配和调度的一个独立单位,是应用程序运行的载体。进程是一种抽象的概念,从来没有统一的标准定义。
进程的组成进程一般由程序、数据集合和进程控制块三部分组成。
程序用于描述进程要完成的功能,是控制进程执行的指令集;数据集合是程序在执行时所需要的数据和工作区;程序控制块(Program Control Block,简称PCB),包含进程的描述信息和控制信息,是进程存在的唯一标
志。
进程具有的特征:
- 动态性:进程是程序的一次执行过程,是临时的,有生命期的,是动态产生,动态消亡的;
- 并发性:任何进程都可以同其他进程一起并发执行;
- 独立性:进程是系统进行资源分配和调度的一个独立单位;
- 结构性:进程由程序、数据和进程控制块三部分组成。
线程
在早期的操作系统中并没有线程的概念,进程是能拥有资源和独立运行的最小单位,也是程序执行的最小单位。任务调度采用的是时间片轮转的抢占式调度方式,而进程是任务调度的最小单位,每个进程有各自独立的一块内存,使得各个进程之间内存地址相互隔离。
后来,随着计算机的发展,对CPU的要求越来越高,进程之间的切换开销较大,已经无法满足越来越复杂的程序的要求了。于是就发明了线程。
线程是程序执行中一个单一的顺序控制流程,是程序执行流的最小单元,是处理器调度和分派的基本单位。一个进程可以有一个或多个线程,各个线程之间共享程序的内存空间(也就是所在进程的内存空间)。一个标准的线程由线程ID、当前指令指针(PC)、寄存器和堆栈组成。而进程由内存空间(代码、数据、进程空间、打开的文件)和一个或多个线程组成。
进程与线程的区别
- 线程是程序执行的最小单位,而进程是操作系统分配资源的最小单位;
- 一个进程由一个或多个线程组成,线程是一个进程中代码的不同执行路线;
- 进程之间相互独立,但同一进程下的各个线程之间共享程序的内存空间(包括代码段、数据集、堆等)及一些进程级的资源(如打开文件和信号),某进程内的线程在其它进程不可见;
- 调度和切换:线程上下文切换比进程上下文切换要快得多。
进程使用内存问题
- 内存泄漏:Memory Leak
- 指程序中用malloc或new申请了一块内存,但是没有用free或delete将内存释放,导致这块内存一直处于占用状态。
- 内存溢出:Memory Overflow
- 指程序申请了10M的空间,但是在这个空间写入10M以上字节的数据,就是溢出。
- 内存不足:OOM
- OOM 即 Out Of Memory,“内存用完了”,在情况在java程序中比较常见。系统会选一个进程将之杀死。
- 在日志messages中看到类似下面的提示
- Jul 10 10:20:30 kernel: Out of memory: Kill process 9527 (java) score 88 or sacrifice child
- 当JVM因为没有足够的内存来为对象分配空间并且垃圾回收器也已经没有空间可回收时,就会抛出这个error,因为这个问题已经严重到不足以被应用处理)。
原因:
- 给应用分配内存太少:比如虚拟机本身可使用的内存(一般通过启动时的VM参数指定)太少。
- 应用用的太多,并且用完没释放,浪费了。此时就会造成内存泄露或者内存溢出。
解决办法:
- 限制java进程的max heap,并且降低java程序的worker数量,从而降低内存使用
- 给系统增加swap空间
#设置内核参数(不推荐),不允许内存申请过量
echo 2 > /proc/sys/vm/overcommit_memory
echo 80 > /proc/sys/vm/overcommit_ratio
echo 2 > /proc/sys/vm/panic_on_oom
Linux默认是允许memory overcommit的,只要你来申请内存我就给你,寄希望于进程实际上用不到那么多内存,但万一用到那么多了呢?Linux设计了一个OOM killer机制挑选一个进程出来杀死,以腾出部
分内存,如果还不够就继续。也可通过设置内核参数 vm.panic_on_oom 使得发生OOM时自动重启系统。这都是有风险的机制,重启有可能造成业务中断,杀死进程也有可能导致业务中断。所以Linux 2.6之后允许通过内核参数 vm.overcommit_memory 禁止memory overcommit。
vm.overcommit_memory 接受三种取值:
- 0 – Heuristic overcommit handling. 这是缺省值,它允许overcommit,但过于明目张胆的overcommit会被拒绝,比如malloc一次性申请的内存大小就超过了系统总内存。Heuristic的意思是“试探式的”,内核利用某种算法猜测你的内存申请是否合理,它认为不合理就会拒绝overcommit。
- 1 – Always overcommit. 允许overcommit,对内存申请来者不拒。内核执行无内存过量使用处理。使用这个设置会增大内存超载的可能性,但也可以增强大量使用内存任务的性能。
- 2 – Don’t overcommit. 禁止overcommit。 内存拒绝等于或者大于总可用 swap 大小以及overcommit_ratio 指定的物理 RAM 比例的内存请求。如果希望减小内存过度使用的风险,这个设就是最好的。
2、进程状态
![图片[1]-进程-李佳程的个人主页](http://www.lijiach.com/wp-content/uploads/2022/11/image-60.png)
进程的基本状态
- 创建状态:进程在创建时需要申请一个空白PCB(process control block进程控制块),向其中填写控制和管理进程的信息,完成资源分配。如果创建工作无法完成,比如资源无法满足,就无法被调度运行,把此时进程所处状态称为创建状态;
- 就绪状态:进程已准备好,已分配到所需资源,只要分配到CPU就能够立即运行;
- 执行状态:进程处于就绪状态被调度后,进程进入执行状态;
- 阻塞状态:正在执行的进程由于某些事件(I/O请求,申请缓存区失败)而暂时无法运行,进程受到阻塞。在满足请求时进入就绪状态等待系统调用;
- 终止状态:进程结束,或出现错误,或被系统终止,进入终止状态。无法再执行;
#进程控制块PCB包含信息
进程id、用户id和组id
程序计数器
进程的状态(有就绪、运行、阻塞)
进程切换时需要保存和恢复的CPU寄存器的值
描述虚拟地址空间的信息
描述控制终端的信息
当前工作目录
文件描述符表,包含很多指向file结构体的指针
进程可以使用的资源上限(ulimit –a命令可以查看)
输入输出状态:配置进程使用I/O设备
状态之间转换六种情况
- 运行——>就绪
- 主要是进程占用CPU的时间过长,而系统分配给该进程占用CPU的时间是有限的;
- 在采用抢先式优先级调度算法的系统中,当有更高优先级的进程要运行时,该进程就被迫让出CPU,该进程便由执行状态转变为就绪状态;
- 就绪——>运行
- 运行的进程的时间片用完,调度就转到就绪队列中选择合适的进程分配CPU;
- 运行——>阻塞
- 正在执行的进程因发生某等待事件而无法执行,则进程由执行状态变为阻塞状态,如发生了I/O请求;
- 阻塞——>就绪
- 进程所等待的事件已经发生,就进入就绪队列;
- 以下两种状态是不可能发生的:
- 阻塞——>运行
- 即使给阻塞进程分配CPU,也无法执行,操作系统在进行调度时不会从阻塞队列进行挑选,而是从就绪队列中选取;
- 就绪——>阻塞
- 就绪态根本就没有执行,谈不上进入阻塞态;
进程更多的状态:
- 运行态:running;
- 就绪态:ready;
- 睡眠态:分为两种,可中断:interruptable,不可中断:uninterruptable;
- 停止态:stopped,暂停于内存,但不会被调度,除非手动启动;
- 僵死态:zombie,僵尸态,结束进程,父进程结束前,子进程不关闭,杀死父进程可以关闭僵死态的子进程;
3、LRU 算法
LRU:Least Recently Used 近期最少使用算法,释放内存
![图片[2]-进程-李佳程的个人主页](http://www.lijiach.com/wp-content/uploads/2022/11/image-61.png)
假设序列为 4 3 4 2 3 1 4 2, 物理块有3个,则
第1轮 4调入内存 4
第2轮 3调入内存 3 4
第3轮 4调入内存 4 3
第4轮 2调入内存 2 4 3
第5轮 3调入内存 3 2 4
第6轮 1调入内存 1 3 2
第7轮 4调入内存 4 1 3
第8轮 2调入内存 2 4 1
4、IPC 进程间通信
IPC: Inter Process Communication
#同一主机
pipe 管道,单向传输
socket 套接字文件,双工通信
Memory-maped file 文件映射,将文件中的一段数据映射到物理内存,多个进程共享这片内存
shm shared memory 共享内存
signal 信号
Lock 对资源上锁,如果资源已被某进程锁住,则其它进程想修改甚至读取这些资
源,都将被阻塞,直到锁被打开
semaphore 信号量,一种计数器
#不同主机
#socket=IP和端口号
RPC remote procedure call
MQ 消息队列,生产者和消费者,如:Kafka,RabbitMQ,ActiveMQ
5、进程优先级
![图片[3]-进程-李佳程的个人主页](http://www.lijiach.com/wp-content/uploads/2022/11/image-62.png)
系统优先级:0-139, 数字越小,优先级越高,各有140个运行队列和过期队列
实时优先级: 99-0 值最大优先级最高
nice值:-20到19,对应系统优先级100-139
6、进程分类
操作系统分类:
- 协作式多任务
- 早期 windows 系统使用,即一个任务得到了 CPU 时间,除非它自己放弃使用CPU ,否则将完全霸占 CPU ,所以任务之间需要协作——使用一段时间的 CPU ,主动放弃使用。
- 抢占式多任务
- Linux内核,CPU的总控制权在操作系统手中,操作系统会轮流询问每一个任务是否需要使用 CPU ,需要使用的话就让它用,不过在一定时间后,操作系统会剥夺当前任务的 CPU使用权,把它排在询问队列的最后,再去询问下一个任务。
进程类型:
- 守护进程
- daemon,在系统引导过程中启动的进程,和终端无关进程;
- 前台进程
- 跟终端相关,通过终端启动的进程;
按进程资源使用的分类:
- CPU-Bound
- CPU 密集型,非交互
- IO-Bound
- IO 密集型,交互