Linux程序/进程/文件
- 程序是存在文件中的机器指令及其数据的序列,编译器将高级语言编写的源代码编译成CPU可执行的二进制可执行文件。
- 进程存在于用户空间,用户空间是存放运行中程序和他们的数据的一部分内存空间。
- 进程运行在内存中,内存实际是一个很大的字节数组,对应着内存条上的所有二进制内存位置,进程并不占用连续的内存位置,内核帮进程找到可用的空闲内存页来保存它的机器指令和数据,并建立数据结构来保存内存分配情况和进程属性。
- shell是新建一个进程来执行命令行程序,通过fork创建一个和原进程一模一样的新进程,通过execvp来调用指定程序代码覆盖fork出来的进程的代码并执行
Linux进程调度机制
- Linux的进程调度算法基本上是基于优先级的时间片轮转法,将CPU时间分片,给每个可运行进程分配一片,目的就是既能够实现进程之间的抢占,又不至于让低优先级的进程被饿死。。每个进程在创建之初有一个基本的优先级,执行期间调度系统会动态调整它的优先级,交互性高的任务会获得一个高的动态优先级,而交互性低的任务获得一个低的动态优先级;在较长的时间间隔内没有使用CPU的进程,通过动态地增加它们的优先级来提升它们。相应地,对于已经在CPU上运行了较长时间的进程,通过减少它们的优先级来处罚它们。
- Linux系统中进程调度操作由一个只在内核态运行的函数schedule()函数执行,该函数代码为所有进程共享;进程控制块PCB(Process ControlBlock)是系统中最为重要的数据结构之一。用来存放进程所必需的各种信息,PCB用结构task—struct来表示,包括进程的类型、进程状态、优先级、时钟信息等。
- Linux中设置了进程调度标志need—resched ,当标志为1时,可执行调度程序.通常,Linux 调度时机分以下两种情况:(1)主动调度:指显式调用schedule() 函数明确释放CPU ,引起新一轮调度.一般发生在当前进程状态改变,如:进程终止、进程睡眠、进程对某些信号处理过程中等(2)被动调度:指不显示调用schedule() 函数,只是PCB 中的need_resched 进程调度标志,该域置位为1 将引起新的进程调度 (3)三种情况:中断处理过程(包括时钟中断、I/O中断、系统调用和异常)中,直接调用schedule(),或者返回用户态时根据need_resched标记调用schedule();内核线程可以直接调用schedule()进行进程切换,也可以在中断处理过程中进行调度,也就是说内核线程作为一类的特殊的进程可以主动调度,也可以被动调度;用户态进程无法实现主动调度,仅能通过陷入内核态后的某个时机点进行调度,即在中断处理过程中进行调度
- Linux将进程分为实时进程和普通进程(又称非实时进程或一般进程),实时进程的优先级要高于其他进程,如果一个实时进程处于可执行状态,它将先得到执行.实时进程又有两种策略:SCHED—RR时间片轮转和和SCHED—FIFO先进先出,在时间片轮转策略中每个可执行实时进程轮流执行一个时间片,而先进先出策略每个进程按各自在运行队列中的顺序执行且顺序不能变化。普通进程SCHED_OTHER也按照轮转调度策略处理
进程生命周期依次定义的数据结构为:TASK—RUNNING,TASK—INTERRUPTIBLE。TASK—UNINTERRUPTIBLE,TASK—ZOMBIE和TASK—STOPPED,一个进程在其生存期间,状态会发生多次变化。与其数据结构相对应的即是Linux进程的状态,分别是:运行态、等待态、暂停态和僵死态。
中断和异常:
- 中断又叫异步中断,是指CPU在正常运行程序时,由于程序的预先安排或内外部事件,引起CPU中断正在运行的程序,而转到发生中断事件程序中。这些引起程序中断的事件称为中断源
- 异常是指CPU内部控制单元出现的中断,即在CPU执行特定指令时出现的非法情况。异常也称为同步中断,因此只有在一条指令执行后才会发出中断(程序执行异常或者系统调用),不可能在指令执行期间发生异常
Linux内存管理机制
Linux中无论物理内存有多大,都将其充份利用,将一些程序调用过的硬盘数据读入内存,利用内存读写的高速特性来提高Linux系统的数据访问性能;页高速缓存(cache)是Linux内核实现的一种主要磁盘缓存。它主要用来减少对磁盘的I/O操作。是通过把磁盘中的数据缓存到物理内存中,把对磁盘的访问变为对物理内存的访问。查看内存状态命令top,free,vmstat
Link
- 物理内存就是系统硬件提供的内存大小,是真正的内存,相对于物理内存,虚拟内存就是为了满足物理内存的不足而提出的策略,它是利用磁盘空间虚拟出的一块逻辑内存,用作虚拟内存的磁盘空间被称为交换空间(Swap Space);虚拟内存作为物理内存的扩展,linux会在物理内存不足时,使用虚拟内存,更详细的说,就是Linux内核会将暂时不用的物理内存块信息写到交换空间,这样以来,物理内存得到了释放,这块内存就可以用于其它目的,当需要用到原始的内容时,这些信息会被重新从交换空间读入物理内存。
- Linux的内存管理采取的是分页存取机制,为了保证物理内存能得到充分的利用,内核会在适当的时候将物理内存中不经常使用的数据块自动交换到虚拟内存中,而将经常使用的信息保留到物理内存。Linux系统会不时的进行页面交换操作,以保持尽可能多的空闲物理内存,即使并没有什么事情需要内存,Linux也会交换出暂时不用的内存页面。这可以避免等待交换所需的时间;Linux进行页面交换是有条件的,不是所有页面在不用时都交换到虚拟内存,linux内核根据”最近最经常使用“算法,仅仅将一些不经常使用的页面文件交换到虚拟内存
- 逻辑地址是对应用程序而言的,一般以Seg:Offset段内偏移来表示;线性地址是CPU所能寻址的空间或者范围,是逻辑地址到物理地址变换之间的中间层;物理地址是机器中实际的内存地址,换言之,是机器中的内存容量范围
- 逻辑地址 -(段表)-> 线性地址 — (页表)—> 物理地址的转换过程(由大到小):CPU将一个虚拟内存空间中的地址转换为物理地址,需要进行两步:首先将一个逻辑地址(其实是段内偏移量),CPU要利用其段式内存管理单元,先将逻辑地址加上相应段的基地址转换成一个线性地址;如果启用了分页机制,再利用其页式内存管理单元,通过查询页表来将线性地址转换为最终物理地址;若没有启用分页机制,那么线性地址直接就是物理地址 Link
- 不同的逻辑地址可以映射到同一个线性地址上;不同的线性地址也可以映射到同一个物理地址上;所以是多对一的关系。另外,同一个线性地址,在发生换页以后,也可能被重新装载到另外一个物理地址上。所以这种多对一的映射关系也会随时间发生变化。
Unix文件系统的内部结构
- 硬盘是由磁性盘片组成的计算机硬件设备,一个磁盘可以被划分成多个分区,每个分区都可以看做独立的磁盘。盘面上的一个有一个同心圆叫做磁道,磁道再分成扇区,就是磁盘的基本存储单元,可以存储固定字节数的数据。
- 文件系统由三部分组成,superblock是文件系统的第一个块,存放文件系统本身的结构信息;接着是inode table,里边是一个个inode,负责存放文件属性,例如数据块列表;然后是数据区,磁盘上所有块的大小一样,大文件会分布在多个独立的磁盘块中。如果文件相当大,固定大小的inode不够存放这么多块编号,就会引入数据块作为间接块,保存着数据块编号,然后把指针存到inode里。inode号是文件的唯一标识。
- 目录是一种包括了文件名字列表的特殊文件,本质是一个包括
的表,可以通过ls -1ia查看详细信息,当前目录的信息保存在.对应的inode节点中,Unix中根目录/的父目录指向自己。cat,cp等命令读取文件的过程:目录查找到inode — inode查找到数据块编号列表 — 不断调用read函数读取数据到内核缓冲区,再到用户空间。有时候会因为没有权限而打不开文件,这就是格局inode数据中的文件属性(权限位和owner ID)来判断的。 - 一个文件可以有多个链接,链接数也被记录在inode中。rm命令当inode的链接数减到0时才会真正删除数据块和inode。磁盘上每个分区都包含一棵独立的目录树,linux会有个根文件系统来把多个分区的目录树关联到一起,某一个文件系统的目录树会被附加在子目录上。linux拒绝跨设备的链接,也就是说磁盘1和2上都有个叫做402的inode,但是指向不同的文件。
- FD文件描述符:Linux中一个进程会打开一组文件,它们保存在一个数组中,FD是指某个文件在数组中的索引,0、1、2分别表示标准输入,标准输出,标准错误输出。
Linux通用文件系统
所谓文件系统,就是文件的储存方式。简单说,它就是一个门牌系统,为储存设备划分门牌号,每个文件分配一个门牌,然后就能按照门牌找到文件。
储存设备都需要指定文件系统,计算机才能读写。所谓”格式化”,就是为硬盘安装文件系统。不同的操作系统有不同的文件系统,Linux 使用 ext4,OSX使用 HFS +,Windows 使用 NTFS(Mac可以读,但是默认不能写入, 移动硬盘一般也是NTFS格式;win还支持FAT32,exFAT文件系统, FAT32中文件不能超过4GB,分区不能超过8TB, exFAT支持mac和win读写),Solaris 和 Unix 使用ZFS。
大部分 Linux 文件系统都默认采用 ext4 文件系统。在有 ext 之前,使用的是 MINIX 文件系统。如果你不熟悉 Linux 历史,那么可以理解为 MINIX 是用于 IBM PC/AT 微型计算机的一个非常小的类 Unix 系统。年轻的 Linus Torvalds 使用 MINIX 来开发原始 Linux 内核,并于 1991 年首次公布。
ext2的问题:在大部分情况下,ext2 在 Linux 发行版中工作得很好,但像 FAT、FAT32、HFS 和当时的其它文件系统一样 —— 在断电时容易发生灾难性的破坏。如果在将数据写入文件系统时候发生断电,则可能会将其留在所谓 不一致 的状态 —— 事情只完成一半而另一半未完成。这可能导致大量文件丢失或损坏,这些文件与正在保存的文件无关甚至导致整个文件系统无法卸载。
ext3 文件系统的 Linux 内核中实现了三个级别的日志记录方式来解决数据不一致问题:日记journal、顺序ordered和回写writeback。
ext4 特地设计为尽可能地向后兼容 ext3。这不仅允许 ext3 文件系统原地升级到 ext4;也允许 ext4 驱动程序以 ext3 模式自动挂载 ext3 文件系统,因此使它无需单独维护两个代码库
Linux /proc 文件系统
Linux 内核提供了一种通过 /proc 文件系统,在运行时访问内核内部数据结构、改变内核设置的机制。proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间。它以文件系统的方式为访问系统内核数据的操作提供接口。
用户和应用程序可以通过proc得到系统的信息,并可以改变内核的某些参数。由于系统的信息,如进程,是动态改变的,所以用户或应用程序读取proc文件时,proc文件系统是动态从系统内核读出所需信息并提交的。另外,在/proc下还有三个很重要的目录:net,scsi和sys。 Sys目录是可写的,可以通过它来访问或修改内核的参数,而net和scsi则依赖于内核配置。例如,如果系统不支持scsi,则scsi 目录不存在
Linux 内核态和用户态的模式切换
关系图:
用户态的应用程序可以通过三种方式来访问内核态的资源:系统调用, 库函数, Shell脚本
- 内核负责向下控制硬件资源,向内管理操作系统资源:包括进程的调度和管理、内存的管理、文件系统的管理、设备驱动程序的管理以及网络资源的管理,向上则向应用程序提供系统调用的接口
- 进程从用户态到内核态的切换,一般存在以下三种情况, 进程在用户态和内核态之间的切换会消耗一定资源:
- 系统调用(其实也是中断,相对于外围设备的硬中断,这种中断称为软中断):比如C函数库中的内存分配函数malloc(),它具体是使用sbrk()系统调用来分配内存,当malloc调用sbrk()的时候就涉及一次从用户态到内核态的切换,类似的函数还有printf(),调用的是wirte()系统调用来输出字符串。
- 异常事件: 当CPU正在执行运行在用户态的程序时,突然发生某些预先不可知的异常事件,这个时候就会触发从当前用户态执行的进程转向内核态执行相关的异常事件,典型的如缺页异常。
- 外围设备的中断:当外围设备完成用户的请求操作后,会像CPU发出中断信号,此时,CPU就会暂停执行下一条即将要执行的指令,转而去执行中断信号对应的处理程序,如果先前执行的指令是在用户态下,则自然就发生从用户态到内核态的转换。系统调用是进程主动请求切换的,而异常和硬中断则是被动的。
“操作系统的进程切换和CPU的模式切换并没有什么关系,发生模式切换可以不改变正处于运行态的进程状态,主要是寄存器上下文的切换,这种情况下,保存上下文环境和以后恢复上下文环境只需要很少的开销。但是,如果改变正处于运行态的进程状态到另一个状态(就绪、阻塞等),则操作系统必须使其环境产生实质性的变化,包括寄存器,堆栈信息,数据等”
Linux磁盘挂载/卸载/格式化操作
linux系统中只能在root权限用户下挂载设备。
BIOS vs UEFI
BIOS(Basic Input/Output System)和 UEFI(Unified Extensible Firmware Interface )是不同的计算机启动固件(Fireware),需要硬件(通常为主板)支持,相互代替,其中 UEFI 是比较新的方式。
- BIOS:经典的启动固件,会调用磁盘的 MBR,然后由 MBR 中的 loader 继续加载操作系统。
- UEFI:UEFI 用来代替 BIOS,并克服 BIOS 的缺点,大多数的 UEFI 固件会提供兼容 BIOS 的启动方式。
MBR vs GPT
- MBR 与 GPT 用于存储硬盘的分区信息,是不同的硬盘分区表类型。MBR支持最大约2T的硬盘,最多能划分4个主分区,更多分区需要使用拓展分区实现。
- GPT 表示 GUID(Globally Unique Identifier) 分区表,是 UEFI 规范的一部分,用于替换 MBR 的分区方式。GPT 没有分区数和分区大小限制。
- BIOS/UEFI 跟 MBR/GPT 是不同层级的,BIOS/UEFI 是 Fireware,MBR/GPT 是分区表。
- 分区表的两种格式:MBR 和 GPT。前者是传统格式,兼容性好;后者更现代,功能更强大。一般来说,都推荐使用 GPT。gdisk命令用于分区操作。
所谓硬盘分区,就是指一块硬盘上面,同时存在多个文件系统。每个文件系统管理的区域,就称为一个分区(partition)。比如,一块 100 GB 的硬盘,可以一半是 NTFS 分区,另一半是 exFAT 分区。
硬盘必须先分区,才能指定每个区的文件系统。分区大小、起始位置、结束位置、文件系统等信息,都储存在分区表里面。
File System(文件系统)是存储媒介中文件存储的组织方式。
不同的文件系统类型有不同的速度,灵活性,安全性和占用空间。不同操作系统只支持特定的文件系统类型。常见的文件系统类型有 FAT16,FAT32,NTFS,EXT3,EXT4,HFS 等。
- 磁盘文件系统包括硬盘、U盘、磁盘阵列、CDROM、DVD等。常见文件系统有autofs、coda、Ext2、Ext3、Ext4、VFAT、ISO9660(光盘或者光盘镜像)、UFS(Unix File System,Unix文件系统)、FAT(File Allocation Table,文件分配表)、FAT16、FAT32、NTFS(New TechnologyFile System)等。
- 网络文件系统可以远程访问的文件系统,这种文件系统在服务器端仍是本地的磁盘文件系统,客户机通过网络远程访问数据。常见文件系统格式有:NFS(Network File System,网络文件系统)、Samba(SMB/CIFS)、AFP(Apple FillingProtocol,Apple文件归档协议)和WebDAV等。
- 专有/虚拟文件系统不驻留在磁盘上的文件系统。常见格式有:TMPFS(临时文件系统)、PROCFS(Process FileSystem,进程文件系统)和LOOPBACKFS(Loopback File System,回送文件系统)。
GRUB(Grand Unified Boot loader)
GRUB是硬盘中的软件,引导器(loader)的一种。目前主流版本是 GRUB2,GRUB 用于从多操作系统的计算机中选择一个系统来启动,或从系统分区中选择特殊的内核配置。