VPS测评 VPS推荐 VPS优惠
Linux运维

linux的进程和内存管理

什么是进程

磁盘上有很多文件,但它只有在运行的时候才会成为进程。进程是运行中的程序的一个副本,是被载入内存的一个指令集合,是资源分配的单位。

  • 进程ID(Process ID,PID)号码被用来标记各个进程
  • UID、GID、和SELinux语境决定对文件系统的存取和访问权限
  • 通常从执行进程的用户来继承
  • 存在生命周期

进程的创建

  • init:第一个进程,从 CentOS7 以后为systemd
  • 进程:都由其父进程创建,用fork()函数创建子进程。机制叫做 COW:Copy On Write(写时复制)

什么是写时复制?

父进程P1都有自己占用的一块内存空间,它有一个子进程P2。如果P2只是被P1创建出来,里面的数据没有发生更新,那么P1和P2其实指向的是同一块内存空间。直到P2发生了数据的更新,它才会复制一份新的内存空间,用来存放自己的数据。

进程,线程和协程

进程和线程的关系

进程是整个系统中用来分配资源的一个单位,进程里面存放了很多的资源,里面有数据、程序代码、打开的文件、地址空间。由于进程需要处理这些数据,它需要找一个帮他干活的人,这个人就是线程了,一个进程里面至少会有一个线程。所以如果把进程看成一个公司,线程就是公司里面的员工。进程包含线程,线程隶属于进程,多个线程共享某些资源,这就是进程和线程之间的逻辑关系。

协程Coroutines,是一种基于线程之上,但又比线程更加轻量级的存在,这种由程序员自己写程序来管理的轻量级线程叫做『用户空间线程』,具有对内核来说不可见的特性。简单来说可以理解为它是程序员写的一段代码。

#列出当前系统中的所有进程和线程
pstree -p
#查看进程中的线程数
grep -i threads /proc/进程的PID编号/status

进程结构

linux中运行着多个进程,内核把进程存放在叫做任务队列(task list) 的双向循环链表中。链表中的每一项都是类型为task_struct,称为进程控制块(Processing Control Block),PCB中包含一个具体进程的所有信息。

进程控制块PCB包含信息:

  • 进程id、用户id和组id
  • 程序计数器
  • 进程的状态(有就绪、运行、阻塞)
  • 进程切换时需要保存和恢复的CPU寄存器的值
  • 描述虚拟地址空间的信息
  • 描述控制终端的信息
  • 当前工作目录
  • 文件描述符表,包含很多指向file结构体的指针
  • 进程可以使用的资源上限(ulimit –a命令可以查看)
  • 输入输出状态:配置进程使用I/O设备

进程相关概念

Page Frame: 页框,用存储页面数据,存储Page 4k。

我们在使用进程的时候,必须要给他分配内存空间,这里就会用到一个单位,页(Page),它是分配内存的最小单位,大小一般为4K。

#用linux命令查看页的大小
getconf -a |grep -i size

物理地址空间和虚拟地址空间

MMU:Memory Management Unit 负责虚拟地址转换为物理地址。

程序在访问一个内存地址指向的内存时, CPU不是直接把这个地址送到内存总线上,而是被送到MMU(Memory Management Unit),然后把这个内存地址映射到实际的物理内存地址上,然后通过总线再去访问内存,程序操作的地址称为虚拟内存地址。

TLB:Translation Lookaside Buffer 翻译后备缓冲区,用于保存虚拟地址和物理地址映射关系的缓存。

说人话就是,假设我服务器的内存有4个G,我想运行磁盘上的某个应用程序,它就会分配一块内存空间出来。如果这时候程序想去内存中处理数据了,它就必须知道这个数据在什么位置。但事实上每个程序每一次运行,操作系统给它分配的内存的物理空间地址都是不同的,这就产生了一个问题,程序不知道确定地址怎么去内存中访问数据呢?其实当一个应用程序去访问数据的时候,虽然物理地址不固定,但是 相对位置是固定的,也就是说站在程序的角度上看,它所看到的不是一个绝对的空间,而是一个虚拟的地址空间,它是一个相对的地址。操作系统会通过MMU(硬件中的一个设备,由CPU来实现)把虚拟地址转换成物理地址。由于每次转换都要做计算,所以引入了TLB缓存来提高性能。

用户和内核空间

对于每一个应用程序来讲,它并不知道自己是和其他应用程序共存的。在每个应用程序的眼里,它看到的只是虚拟内存,以为自己拥有了整个内存空间。

C代码和内存布局之间的对应关系

每个进程都包括5种不同的数据段

  • 代码段:用来存放可执行文件的操作指令,也就是说是它是可执行程序在内存中的镜像。代码段需 要防止在运行时被非法修改,所以只准许读取操作,而不允许写入(修改)操作——它是不可写的。
  • 数据段:用来存放可执行文件中已初始化全局变量,换句话说就是存放程序静态分配的变量和全局 变量。
  • BSS段:Block Started by Symbol”的缩写,意为“以符号开始的块,BSS段包含了程序中未初始化的 全局变量,在内存中 bss段全部置零。
  • 堆(heap):存放数组和对象,堆是用于存放进程运行中被动态分配的内存段,它的大小并不固 定,可动态扩张或缩减。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆 上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)。
  • 栈(stack):栈是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量 (但不包括static声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时, 其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。 由于栈的后进先出特点,所以栈特别方便用来保存/恢复调用现场。可以把堆栈看成一个寄存、交换临时数据的内存区。

进程使用内存问题

内存泄漏:Memory Leak

指程序中用malloc或new申请了一块内存,但是没有用free或delete将内存释放,导致这块内存一直处 于占用状态。

内存溢出:Memory Overflow

指程序申请了10M的空间,但是在这个空间写入10M以上字节的数据,就是溢出。

内存不足:OOM

OOM 即 Out Of Memory,“内存用完了”情况在java程序中比较常见。

进程状态

基本状态

  • 创建状态:进程在创建时需要申请一个空白PCB(process control block进程控制块),向其中填写控制和管理进程的信息,完成资源分配。如果创建工作无法完成,比如资源无法满足,就无法被调度运行,把此时进程所处状态称为创建状态。
  • 就绪状态:进程已准备好,已分配到所需资源,只要分配到CPU就能够立即运行。
  • 执行状态:进程处于就绪状态被调度后,进程进入执行状态。
  • 阻塞状态:正在执行的进程由于某些事件(I/O请求,申请缓存区失败)而暂时无法运行,进程受到阻塞。在满足请求时进入就绪状态等待系统调用。
  • 终止状态:进程结束,或出现错误,或被系统终止,进入终止状态。无法再执行

进程更多的状态:

  • 运行态:running
  • 就绪态:ready
  • 睡眠态:分为两种,可中断:interruptable,不可中断:uninterruptable
  • 停止态:stopped,暂停于内存,但不会被调度,除非手动启动
  • 僵死态:zombie,僵尸态,结束进程,父进程结束前,子进程不关闭,杀死父进程可以关闭僵死 态 的子进程
#观察进程
ps aux
#统计进程数量
top
#停止进程
kill -19 PID
#恢复停止的进程
kill -18 PID
#杀死进程
kill -9 PID

LRU 算法

LRU:Least Recently Used 近期最少使用算法(喜新厌旧),释放内存。

内存的空间终究有限,不可能把所有的数据都放到内存中处理。所以一般只存储经常用的数据,旧的数据会被淘汰。

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

范例:利用管道文件实现IPC

#在XSHELL新建2个终端
#在其中一个终端创建管道文件
mkfifo test.fifo
#往里面写一句话
echo hello > test.fifo
#在另一个终端查看文件可以读取到刚才的话
root@DMIT-iJboSKPbP4:~# cat test.fifo
hello

范例:查找socket类型的文件

find / -type s -ls

进程优先级

优先级范围描述
0-99实时进程,实时优先级,越大优先级越高
100-139非实时进程,系统优先级。越小优先级越高。
-20-19NICE值,对应系统优先级的100-139。
#查看进程编号,命令,优先级
ps axo pid,cmd,ni,pri,rtprio
#把某个进程PID的优先级改成5
renice -n 5 PID

进程分类

操作系统分类:

  • 协作式多任务:早期 windows 系统使用,即一个任务得到了 CPU 时间,除非它自己放弃使用
    CPU ,否则将完全霸占 CPU ,所以任务之间需要协作——使用一段时间的 CPU ,主动放弃使用。
  • 抢占式多任务::Linux内核,CPU的总控制权在操作系统手中,操作系统会轮流询问每一个任务是
    否需要使用 CPU ,需要使用的话就让它用,不过在一定时间后,操作系统会剥夺当前任务的 CPU
    使用权,把它排在询问队列的最后,再去询问下一个任务。

进程类型:

  • 守护进程:daemon,在系统引导过程中启动的进程,和终端无关进程。
  • 前台进程:跟终端相关,通过终端启动的进程。 注意:两者可相互转化

按进程资源使用的分类:

  • CPU-Bound:CPU 密集型,非交互
  • IO-Bound:IO 密集型,交互
未经允许不得转载:青蛙主机 » linux的进程和内存管理

VPS相关常用工具

PING测试工具自用毛子接码站