Linux实验总结分析报告

一、Linux系统概念模型

从整体来看,Linux可以划分为用户空间内核空间,我们平常编写的用户程序以及C库函数都位于用户空间,而内核空间自顶向下可分为系统调用、内核(进程管理、内存管理、文件管理、中断等)以及平台架构相关代码。

1、Linux启动分析

当我们打开PC的电源,BIOS开机自检,按BIOS中设置的启动设备(通常是硬盘)启动,接着启动设备上安装的引导程序lilo或grub开始引导Linux,Linux首先进行内核的引导,接下来执行init程序,init程序调用了rc.sysinit和rc等程序,rc.sysinit和rc当完成系统初始化和运行服务的任务后,返回init;init启动了mingetty后,打开了终端供用户登录系统,用户登录成功后进入了Shell,这样就完成了从开机到登录的整个启动过程。

2、进程管理

linux内核通过task_struct(进程描述符)结构体来管理进程,多个任务的task struct组成的链表,被称为task list(任务列表)。

(1)进程创建:

在Linux系统中,所有的进程都是PID为1的init进程的后代。内核在系统启动的最后阶段启动init进程。该进程读取系统的初始化脚本(initscript)并执行其他的相关程序,最终完成系统启动的整个进程。Linux提供两个函数去处理进程的创建和执行:fork()和exec()。首先,fork()通过拷贝当前进程创建一个子进程。子进程与父进程的区别仅仅在于PID(每个进程唯一),PPID(父进程的PID)和某些资源和统计量(例如挂起的信号)。exec()函数负责读取可执行文件并将其载入地址空间开始运行。

(2)进程终止

依靠do_exit()(在kernel/exit.c文件中)把与进程相关联的所有资源都被释放掉(假设进程是这些资源的唯一使用者)。至此,与进程相关的所有资源都被释放掉了。进程不可运行(实际上也没有地址空间让它运行)并处于TASK_ZOMBIE状态。它占用的所有资源就是内核栈、thread_info和task_struct。

(3)进程调度

针对CFS调度实现部分主要涉及如下几个数据结构:

  • task_struct:为进程任务基础数据结构,存储着进程相关信息。

  • sched_entity:存储着进程调度相关的信息,其中run_node为可执行红黑树的节点。

  • ofs_rq: 存储着rb_root,红黑树的根节点task_timeline。

  • slab: linux内核对于对象内存的一种高效的管理机制, 可以有效的降低内存碎片。task_struct这类数据结构由slab分配并管理。

上下文切换,处理器从即为从一个可执行的进程切换到另一个可执行的进程,其中包含了两个关键的函数。

  • switch_mm:把虚拟内存从上一个进程映射切换到新进程中
  • switch_to:负责将上一个处理器状态信息切换到新进程的处理器状态。包括保存,恢复栈信息和寄存器信息。

简单的来说,CFS是动态计算程序优先级的一种调度算法,其内部算法核心是选取vruntime最小的进程进行调度运行,而维护最小的进程,使用了红黑树,而计算vruntime使用了所有进程数以及nice值的加权。Linux内核的调度程序CFS,尽可能的满足了各个方面的需求,并找到了一种在调度周期和吞吐量之间的平衡。

3、内存管理

Linux在内存管理上分为两级,一级是线性区,类似于00c73000-00c88000,对应于虚拟内存,它实际上不占用实际物理内存;一级是具体的物理页面,它对应我们机器上的物理内存。Linux内核在用户申请内存的时候,只是给它分配了一个线性区(也就是虚存),并没有分配实际物理内存;只有当用户使用这块内存的时候,内核才会分配具体的物理页面给用户,这时候才占用宝贵的物理内存。内核释放物理页面是通过释放线性区,找到其所对应的物理页面,将其全部释放的过程。

char *p=malloc(2048)  //实际只分配了虚拟内存,并不占用实际内存。
strcpy(p,”123”) // 分配了物理页面,虽然只是使用了3个字节,但内存还是为它分配了2048字节的物理内存
free(p) //通过虚拟地址,找到其所对应的物理页面,释放物理页面,释放线性区。

标准C库中,提供了malloc/free函数分配释放内存,这两个函数底层是由brk,mmap,munmap这些系统调用实现的

  • brk是将数据段(.data)的最高地址指针_edata往高地址推;
  • mmap是在进程的虚拟地址空间中(堆和栈中间,称为文件映射区域的地方)找一块空闲的虚拟内存

Malloc(<128K)时使用brk进行分配,malloc(>128K)时使用mmap进行分配。

4、文件管理

Linux支持了很多种类的文件系统,包含本地文件系统ext3ext4到网络文件系统NFSHDFS等,VFS系统屏蔽了不同文件系统的操作差异和实现细节,提供了统一的实现框架,也提供了标准的操作接口,这大大降低了操作文件和接入新文件系统的难度。

比如Linux写一个文件:

int ret = write(fd, buf, len);

调用了write()系统调用,它的过程简要如下:

  • 首先,勾起VFS通用系统调用sys_write()处理。
  • 接着,sys_write()根据fd找到所在的文件系统提供的写操作函数,比如op_write()。
  • 最后,调用op_write()实际的把数据写入到文件中。

5、中断管理

中断请求(IRQ)是由可编程的中断控制器(PIC)发起的,其目的是为了中断 CPU 和执行中断服务程序(ISR)。中断服务程序(ISR)是一个小的程序,用来处理具体的数据,其具体的处理方式依赖于造成中断请求(IRQ)的原因。之前正在运行的进程在中断服务程序(ISR)运行结束前都会被中断。如今中断请求(IRQ)由 CPU 中的高级可编程中断控制器advanced programmable interrupt controller(APIC)部分来处理。每个核中都拥有属于自己的高级可编程中断控制器。

Linux中断机制由三部分组成:

(1)中断子系统初始化:内核自身初始化过程中对中断处理机制初始化,例如中断的数据结构以及中断请求等。

(2)中断或异常处理:中断整体处理过程。

(3)中断API:为设备驱动提供API,例如注册,释放和激活等。

以上输出显示了中断号、各个cpu接收中断次数、中断控制器(interrupt controller)和中断名称等信息。

二、Linux系统性能分析

对于linux系统负载情况,可以使用uptime命令。

系统负载(load),反应服务器1,5,15分钟各个时间段的负载情况。

当load的值超出cpu总数的60%,系统负载过高。

  • 平均负载高有可能是cpu密集型进程导致的,也有可能是I/O密集型进程导致的,也有可能是大量进程处于等待CPU调度的情况导致的。
  • 平均负载高并不意味着CPU使用率高。

cpu上下文切换,是保证linux正常工作的核心功能之一,一般情况下不需要我们特别关注。

但过多的上下文切换,造成cpu时间消耗在寄存器,内核栈以及虚拟内存等数据的保存和恢复上,从而缩短进程真正运行的时间,导致系统的整体性能大幅下降。

通过vmstat命令实时监控是否是换入换出操作,swap换入换出比较频繁,内存可能出现瓶颈。

free命令:查看内存使用情况。

如果可用内存/物理内存<20%,说明内存紧缺,需要增加内存。

iostat命令:查看磁盘使用情况。

磁盘IO性能优化

(1)可以用追加写代替随机写,减少寻址开销,加快 I/O 写的速度。

(2)可以借助缓存 I/O ,充分利用系统缓存,降低实际 I/O 的次数。

(3)在需要频繁读写同一块磁盘空间时,可以用 mmap 代替 read/write,减少内存的拷贝次数。

(4)在需要同步写的场景中,尽量将写请求合并,而不是让每个请求都同步写入磁盘,即可以用 fsync() 取代 O_SYNC。

posted @ 2021-05-13 16:49  Ls,  阅读(808)  评论(0编辑  收藏  举报