什么是进程
什么是进程
进程:
- 运行中的程序的一个副本,是被载入内存的一个指令集合,是资源分配的单位
- 进程ID(Process ID,PID)号码被用来标记各个进程
- UID、GID、和SELinux语境决定对文件系统的存取和访问权限
- 通常从执行进程的用户来继承
- 存在生命周期
进程创建
- init:第一个进程,从 CentOS 7 以后为systemd
- 进程:都由其父进程创建,fork(),父子关系,CoW:Copy On Write
刚创建时,共用父进程的内存,有新数据像刚创建的子进程写入时,单独开辟一个内存空间,把父进程内存复制一份给子进程做数据修改
通过pid获取运行的真实程序
!!面试题
ps aux|grep ssh
ll /prox/ssh的pid/exe
cat /prox/ssh的pid/status
物理地址空间和虚拟地址空间
MMU:Memory Management Unit 负责虚拟地址转换为物理地址 程序在访问一个内存地址指向的内存时,CPU不是直接把这个地址送到内存总线上,而是被送到MMU(Memory Management Unit),然后把这个内存地址映射到实际的物理内存地址上,然后通过总线再去访问内存,程序操作的地址称为虚拟内存地址
TLB:Translation Lookaside Buffer 翻译后备缓冲器,用于保存虚拟地址和物理地址映射关系的缓存
空间分配:程序申请的内存,申请内存是一个值,内核根据他使用的空间给的是最小值,其申请的理想空间是线性空间(虚拟空间),真实分配的是物理地址中可能断续的地址
C代码和内存布局之间的对应关系
每个进程都包括5种不同的数据段
- 代码段:用来存放可执行文件的操作指令,也就是说是它是可执行程序在内存中的镜像。代码段需要防止在运行时被非法修改,所以只准许读取操作,而不允许写入(修改)操作——它是不可写的
- 数据段:用来存放可执行文件中已初始化全局变量,换句话说就是存放程序静态分配的变量和全局变量
- BSS段:Block Started by Symbol”的缩写,意为“以符号开始的块,BSS段包含了程序中未初始化的全局变量,在内存中 bss段全部置零
- 堆(heap):存放数组和对象,堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)
- 栈:栈是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的后进先出特点,所以栈特别方便用来保存/恢复调用现场。可以把堆栈看成一个寄存、交换临时数据的内存区
进程使用内存问题
内存泄漏:Memory Leak 指程序中用malloc或new申请了一块内存,但是没有用free或delete将内存释放,导致这块内存一直处于占用状态
内存溢出:Memory Overflow 指程序申请了10M的空间,但是在这个空间写入10M以上字节的数据,就是溢出
内存不足:OOM Out Of Memory,“内存用完了”, 在情况在java程序中比较常见。系统会选一个进程将之杀死,在日志messages中看到类似下面的提示
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
说明: 默认内存分配是申请多少就给多少(大部分用不到那么多)如果超出分的空间,就采用OOM killer机制 作用是选出一个进程来杀掉,来腾出内存空间,如果还不够就继续杀,一般占用资源越大的被杀几率越大
vm.panic_con_oom,发生oom时进行的操作设置,取值是:
0 默认值,当出现oom的时候,触发oom killer
1 程序在有cpuset、memory policy、memcg的约束情况下的OOM,可以考虑不panic,而是启动OOM killer。其它情况触发 kernel panic,即系统直接重启
2 当出现oom,直接触发kernel panic,即系统直接重启
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比例的内存请求。如果您希望减小内存过度使用的风险,这个设置就是最好的
申请内存的算法: 单次申请的内存大小不能超过以下值,否则本次申请就会失败
free memory + free swap + pagecache的大小 + SLAB
kernel设有一个阈值,申请的内存总数超过这个阈值就算overcommit,在/proc/meminfo中可以看到这个阈值的大小
查看阀值大小:grep -i commit /proc/meminfo
vm.overcommit_ratio
内核参数,缺省值是50,表示物理内存的50%。如果你不想使用比率,也可以直接指定内存的字节数大小,通过另一个内核参数 vm.overcommit_kbytes 即可;
如果使用了huge pages,那么需要从物理内存中减去,公式变成
CommitLimit = ([total RAM] – [total huge TLB RAM]) * vm.overcommit_ratio / 100 + swap
进程状态
进程更多的状态:
- 运行态:running
- 就绪态:ready
- 睡眠态:分为两种,可中断:interruptable,不可中断:uninterruptable
- 停止态:stopped,暂停于内存,但不会被调度,除非手动启动
- 僵死态:zombie,僵尸态,结束进程,父进程结束前,子进程不关闭,杀死父进程可以关闭僵死态的子进程
LRU算法
Least Recently Used 近期最少使用算法(喜新厌旧),释放内存
IPC进程间通信
IPC: Inter Process Communication
同一主机:
pipe 管道,单向传输,1v1
socket 套接字文件
Memory-maped file 文件映射,将文件中的一段数据映射到物理内存,多个进程共享这片内存
shm shared memory 共享内存
signal 信号
Lock 对资源上锁,如果资源已被某进程锁住,则其它进程想修改甚至读取这些资源,都将被阻塞,直到锁被打开
semaphore 信号量,一种计数器
不同主机:
socket=IP和端口号
RPC remote procedure call
MQ消息队列,生产者和消费者,如:Kafka,RabbitMQ,ActiveMQ
例: 创建管道文件,实现两个进程通信 1 号终端:
mkfifo xxxx
cat > xxxx
12345
2号终端:
cat xxxx #此时能动态显示1号终端输出的内容
进程优先级
系统优先级: 0-139,数字越小,优先级越高 (CentOS 4,5),各有140个运行队列和过期队列 0-98,99(CentOS 6)
实时优先级: 0-99 静态优先级: 100-139,此对应的是nice值:-20~19 Big O: 时间(空间)复杂度,用时(空间)和规模的关系O(1), O(logn), O(n)线性, O(n^2)抛物线, O(2^n)
进程调度机制:
总共有280个队列
其中140个队列对应优先级,也叫运行队列,如1号队列对应0优先级,以此类推;
另外140个队列对应优先级的过期队列,如1号过期队列是对应0优先级,以此类推。两个对应关系的队列会进行交替
所有的进程,按各自的优先级进入对应的运行队列,运行完后会进入过期队列,当运行队列执行完成,就会执行过期队列,此时过期队列变成运行队列,之前的运行队列变成过期队列,存放新运行完的进程
IO调度算法
- NOOP
- Deadline scheduler
- Anticipatory scheduler
- CFQ
查看系统IO算法:
cat /sys/block/sda/queue/scheduler
- 0
- 0
- 0
- 0
- 0
- 0