pos口:太棒了!最后有人清楚地解释了Linux系统结构

配图

pos口-Java面试那些事儿


  Linux系统通常有四个主要部分:内核、外壳、文件系统和应用程序。内核、shell和文件系统共同构成了基本的操作系统结构,使用户能够运行程序、管理文件和使用系统。

  1.Linux内核

  内核是操作系统的核心,具有许多基本功能。它负责管理系统进程、内存、设备驱动程序、文件和网络系统,这决定了系统的性能和稳定性。

  Linux内核由以下部分组成:内存管理、进程管理、设备驱动程序、文件系统和网络管理。如图所示:

  系统调用接口:SCI层提供了一些机制来执行从用户空间到内核的函数调用。此接口依赖于体系结构,即使在同一处理器系列中也是如此。SCI实际上是一个非常有用的函数调用多路复用和解多路复用服务。是/您可以在Linux/kernel中找到SCI的实现,在Linux/arch中找到与体系结构相关的部分。

  1.1内存管理

  对任何一台计算机而言,其内存以及其它资源都是有限的。为了让有限的物理内存满足应用程序对内存的大需求量,Linux采用了称为“虚拟内存”的内存管理方式。Linux将内存划分为容易处理的“内存页”(对于大部分体系结构来说都是4KB)。Linux包括了管理可用内存的方式,以及物理和虚拟映射所使用的硬件机制。

  不过内存管理要管理的可不止4KB缓冲区。Linux提供了对4KB缓冲区的抽象,例如slab分配器。这种内存管理模式使用4KB缓冲区为基数,然后从中分配结构,并跟踪内存页使用情况,比如哪些内存页是满的,哪些页面没有完全使用,哪些页面为空。这样就允许该模式根据系统需要来动态调整内存使用。

  为了支持多个用户使用内存,有时会出现可用内存被消耗光的情况。由于这个原因,页面可以移出内存并放入磁盘中。这个过程称为交换,因为页面会被从内存交换到硬盘上。内存管理的源代码可以在./linux/mm中找到。

  1.2进程管理

  进程实际是某特定应用程序的一个运行实体。在Linux系统中,能够同时运行多个进程,Linux通过在短的时间间隔内轮流运行这些进程而实现“多任务”。这一短的时间间隔称为“时间片”,让进程轮流运行的方法称为“进程调度”,完成调度的程序称为调度程序。

  进程调度控制进程对CPU的访问。当需要选择下一个进程运行时,由调度程序选择最值得运行的进程。可运行进程实际上是仅等待CPU资源的进程,如果某个进程在等待其它资源,则该进程是不可运行进程。Linux使用了比较简单的基于优先级的进程调度算法选择新的进程。

  通过多任务机制,每个进程可认为只有自己独占计算机,从而简化程序的编写。每个进程有自己单独的地址空间,并且只能由这一进程访问,这样,操作系统避免了进程之间的互相干扰以及“坏”程序对系统可能造成的危害。为了完成某特定任务,有时需要综合两个程序的功能,例如一个程序输出文本,而另一个程序对文本进行排序。为此,操作系统还提供进程间的通讯机制来帮助完成这样的任务。

  Linux中常见的进程间通讯机制有信号、管道、共享内存、信号量和套接字等。

  内核通过SCI提供了一个应用程序编程接口(API)来创建一个新进程(fork、exec或PortableOperatingSystemInterface[POSⅨ]函数),停止进程(kill、exit),并在它们之间进行通信和同步(signal或者POSⅨ机制)。

  1.3文件系统

  和DOS等操作系统不同,Linux操作系统中单独的文件系统并不是由驱动器号或驱动器名称(如A:或C:等)来标识的。相反,和UNIX操作系统一样,Linux操作系统将独立的文件系统组合成了一个层次化的树形结构,并且由一个单独的实体代表这一文件系统。Linux将新的文件系统通过一个称为“挂装”或“挂上”的操作将其挂装到某个目录上,从而让不同的文件系统结合成为一个整体。Linux操作系统的一个重要特点是它支持许多不同类型的文件系统。Linux中最普遍使用的文件系统是Ext2,它也是Linux土生土长的文件系统。但Linux也能够支持FAT、VFAT、FAT32、MINIX等不同类型的文件系统,从而可以方便地和其它操作系统交换数据。由于Linux支持许多不同的文件系统,并且将它们组织成了一个统一的虚拟文件系统.

  虚拟文件系统(VirtualFileSystem,VFS):隐藏了各种硬件的具体细节,把文件系统操作和不同文件系统的具体实现细节分离了开来,为所有的设备提供了统一的接口,VFS提供了多达数十种不同的文件系统。虚拟文件系统可以分为逻辑文件系统和设备驱动程序。逻辑文件系统指Linux所支持的文件系统,如ext2,fat等,设备驱动程序指为每一种硬件控制器所编写的设备驱动程序模块。

  虚拟文件系统(VFS)是Linux内核中非常有用的一个方面,因为它为文件系统提供了一个通用的接口抽象。VFS在SCI和内核所支持的文件系统之间提供了一个交换层。即VFS在用户和文件系统之间提供了一个交换层。

  VFS在用户和文件系统之间提供了一个交换层:

  在VFS上面,是对诸如open、close、read和write之类的函数的一个通用API抽象。在VFS下面是文件系统抽象,它定义了上层函数的实现方式。它们是给定文件系统(超过50个)的插件。文件系统的源代码可以在./linux/fs中找到。

  文件系统层之下是缓冲区缓存,它为文件系统层提供了一个通用函数集(与具体文件系统无关)。这个缓存层通过将数据保留一段时间(或者随即预先读取数据以便在需要是就可用)优化了对物理设备的访问。缓冲区缓存之下是设备驱动程序,它实现了特定物理设备的接口。

  因此,用户和进程不需要知道文件所在的文件系统类型,而只需要象使用Ext2文件系统中的文件一样使用它们。

  1.4设备驱动程序

  设备驱动程序是Linux内核的主要部分。和操作系统的其它部分类似,设备驱动程序运行在高特权级的处理器环境中,从而可以直接对硬件进行操作,但正因为如此,任何一个设备驱动程序的错误都可能导致操作系统的崩溃。设备驱动程序实际控制操作系统和硬件设备之间的交互。

  设备驱动程序提供一组操作系统可理解的抽象接口完成和操作系统之间的交互,而与硬件相关的具体操作细节由设备驱动程序完成。一般而言,设备驱动程序和设备的控制芯片有关,例如,如果计算机硬盘是SCSI硬盘,则需要使用SCSI驱动程序,而不是IDE驱动程序。

  1.5网络接口(NET)

  提供了对各种网络标准的存取和各种网络硬件的支持。网络接口可分为网络协议和网络驱动程序。网络协议部分负责实现每一种可能的网络传输协议。众所周知,TCP/IP协议是Internet的标准协议,同时也是事实上的工业标准。

  Linux的网络实现支持BSD套接字,支持全部的TCP/IP协议。Linux内核的网络部分由BSD套接字、网络协议层和网络设备驱动程序组成。网络设备驱动程序负责与硬件设备通讯,每一种可能的硬件设备都有相应的设备驱动程序。

  2.LinuxShell

  shell是系统的用户界面,提供了用户与内核进行交互操作的一种接口。它接收用户输入的命令并把它送入内核去执行,是一个命令解释器。另外,shell编程语言具有普通编程语言的很多特点,用这种编程语言编写的shell程序与其他应用程序具有同样的效果。

  目前主要有下列版本的shell。

  1.BourneShell:是贝尔实验室开发的。

  2.BASH:是GNU的BourneAgainShell,是GNU操作系统上默认的shell,大部分linux的发行套件使用的都是这种shell。

  3.KornShell:是对BourneSHell的发展,在大部分内容上与BourneShell兼容。

  4.CShell:是SUN公司Shell的BSD版本。

  3.linux文件系统

  文件系统是文件存放在磁盘等存储设备上的组织方法。Linux系统能支持多种目前流行的文件系统,如EXT2、EXT3、FAT、FAT32、VFAT和ISO9660。

  3.1文件类型

  Linux下面的文件类型主要有:

  普通文件:C语言元代码、SHELL脚本、二进制的可执行文件等。分为纯文本和二进制。

  目录文件:目录,存储文件的唯一地方。

  链接文件:指向同一个文件或目录的文件。

  设备文件:与系统外设相关的,通常在/dev下面。分为块设备和字符设备。

  管道(FIFO)文件:提供进程之间通信的一种方式

  套接字(socket)文件:该文件类型与网络通信有关

  可以通过ls–l,file,stat几个命令来查看文件的类型等相关信息。

  3.2Linux目录

  文件结构是文件存放在磁盘等存贮设备上的组织方法。主要体现在对文件和目录的组织上;

  目录提供了管理文件的一个方便而有效的途径。

  Linux使用标准的目录结构,在安装的时候,安装程序就已经为用户创建了文件系统和完整而固定的目录组成形式,并指定了每个目录的作用和其中的文件类型。

  完整的目录树可划分为小的部分,这些小部分又可以单独存放在自己的磁盘或分区上。这样,相对稳定的部分和经常变化的部分可单独存放在不同的分区中,从而方便备份或系统管理。目录树的主要部分有root、/usr、/var、/home等。这样的布局可方便在Linux计算机之间共享文件系统的某些部分。

  Linux采用的是树型结构。最上层是根目录,其他的所有目录都是从根目录出发而生成的。

  微软的DOS和windows也是采用树型结构,但是在DOS和windows中这样的树型结构的根是磁盘分区的盘符,有几个分区就有几个树型结构,他们之间的关系是并列的。最顶部的是不同的磁盘(分区),如:C,D,E,F等。

  但是在linux中,无论操作系统管理几个磁盘分区,这样的目录树只有一个。从结构上讲,各个磁盘分区上的树型目录不一定是并列的。

  3.3Linux磁盘分区

  主分区,扩展分区和逻辑分区:

  linux分区不同于windows,硬盘和硬盘分区在Linux都表示为设备.

  硬盘分区一共有三种:主分区,扩展分区和逻辑分区。

  硬盘的分区主要分为主分区(PrimaryPartion)和扩展分区(ExtensionPartion)两种,主分区和扩展分区的数目之和不能大于四个。

  主分区(PrimaryPartion):可以马上被使用但不能再分区。

  扩展分区(ExtensionPartion):必须再进行分区后才能使用,也就是说它必须还要进行二次分区。

  逻辑分区((LogicalPartion)):由扩展分区建立起来的分区,逻辑分区没有数量上限制。

  扩展分区只不过是逻辑分区的“容器”,实际上只有主分区和逻辑分区进行数据存储。

  Linux下硬盘分区的标识

  硬盘分区的标识一般使用/dev/hd[a-z]X或者/dev/sd[a-z]X来标识,其中[a-z]代表硬盘号,X代表硬盘内的分区号。

  整块硬盘分区的块号标识:Linux下用hda、hdb、sda、sdb等来标识不同的硬盘;

  其中:

  IDE接口硬盘:表示为/dev/hda1、/dev/hdb…;

  SCSI接口的硬盘、SATA接口的硬盘表示为/dev/sda、/dev/sdb……;

  硬盘内的分区:如果X的值是1到4,表示硬盘的主分区(包含扩展分区);逻辑分区从是从5开始的,比如/dev/hda5肯定是逻辑分区了;

  例如:

  用hda1、hda2、hda5、hda6来标识不同的分区。其中,字母a代表第一块硬盘,b代表第二块硬盘,依次类推。而数字1代表一块硬盘的第一个分区、2代表第二个分区,依次类推。1到4对应的是主分区(PrimaryPartition)或扩展分区(ExtensionPartition)。从5开始,对应的都是硬盘的逻辑分区(LogicalPartition)。一块硬盘即使只有一个主分区,逻辑分区也是从5开始编号的,这点应特别注意。

  总结:一个硬盘分区首先要确认在哪个硬盘,然后再确认它所在硬盘内的哪个分区。

  对于/dev/hda类似的表示方法,也并不寞生吧;我们在Linux通过fdisk-l就可以查到硬盘是/dev/hda还是/dev/hdb;

  请注意第一行,Disk/dev/hda:80.0GB,80026361856bytes,这个就是表示机器中只有一个硬盘设备/dev/hda,体积大小为80.0G;下面的就是硬盘的分区,每个分区都有详细的信息,在这里不详细说了;

  Linux下磁盘分区和目录的关系如下:

  –任何一个分区都必须挂载到某个目录上。

  –目录是逻辑上的区分。分区是物理上的区分。

  –磁盘Linux分区都必须挂载到目录树中的某个具体的目录上才能进行读写操作。

  –根目录是所有Linux的文件和目录所在的地方,需要挂载上一个磁盘分区。

  3.4linux主要目录的功用。

  /bin二进制可执行命令

  /dev设备特殊文件

  /etc系统管理和配置文件

  /etc/rc.d启动的配置文件和脚本

  /home用户主目录的基点,比如用户user的主目录就是/home/user,可以用~user表示

  /lib标准程序设计库,又叫动态链接共享库,作用类似windows里的.dll文件

  /sbin系统管理命令,这里存放的是系统管理员使用的管理程序

  /tmp公用的临时文件存储点

  /root系统管理员的主目录(呵呵,特权阶级)

  /mnt系统提供这个目录是让用户临时挂载其他的文件系统。

  /lostfound这个目录平时是空的,系统非正常关机而留下“无家可归”的文件(windows下叫什么.chk)就在这里

  /proc虚拟的目录,是系统内存的映射。可直接访问这个目录来获取系统信息。

  /var某些大文件的溢出区,比方说各种服务的日志文件

  /usr最庞大的目录,要用到的应用程序和文件几乎都在这个目录。其中包含:

  /usr/X11R6存放Xwindow的目录

  /usr/bin众多的应用程序

  /usr/sbin超级用户的一些管理程序

  /usr/doclinux文档

  /usr/includelinux下开发和编译应用程序所需要的头文件

  /usr/lib常用的动态链接库和软件包的配置文件

  /usr/man帮助文档

  /usr/src源代码,linux内核的源代码就放在/usr/src/linux里

  /usr/local/bin本地增加的命令

  /usr/local/lib本地增加的库

  3.5linux文件系统

  文件系统指文件存在的物理空间,linux系统中每个分区都是一个文件系统,都有自己的目录层次结构。linux会将这些分属不同分区的、单独的文件系统按一定的方式形成一个系统的总的目录层次结构。一个操作系统的运行离不开对文件的操作,因此必然要拥有并维护自己的文件系统。

  1.文件系统类型:

  2.文件系统特性:

  磁盘分区完毕后还需要进行格式化(format),之后操作系统才能够使用这个分区。格式化的目的是能使操作系统可以使用的文件系统格式(即我们上面提到文件系统类型).

  每种操作系统能够使用的文件系统并不相同.如windows98以前的微软操作系统主要利用的文件系统是FAT(或FAT16),windows2000以后的版本有所谓的NTFS文件系统,至于Linux的正统文件系统则为Ext2(Linuxsecondextendedfilesystem,ext2fs)这一个。此外,在默认的情况下,windows操作系统是不会认识Linux的Ext2的。

  传统的磁盘与文件系统之应用中,一个分区就是只能够被格式化成为一个文件系统,所以我们可以说一个filesystem就是一个partition。但是由于新技术的利用,例如我们常听到的LVM与软件磁盘阵列(softwareraid),这些技术可以将一个分区格式化为多个文件系统(例如LVM),也能够将多个分区合成一个文件系统(LVM,RAID)!所以说,目前我们在格式化时已经不再说成针对partition来格式化了,通常我们可以称呼一个可被挂载的数据为一个文件系统而不是一个分区喔!

  那么文件系统是如何运行的呢?这与操作系统的文件数据有关。较新的操作系统的文件数据除了文件实际内容外,通常含有非常多的属性,例如Linux操作系统的文件权限(rwx)与文件属性(拥有者、群组、时间参数等)。文件系统通常会将这两部份的数据分别存放在不同的区块,权限与属性放置到inode中,至于实际数据则放置到datablock区块中。另外,还有一个超级区块(superblock)会记录整个文件系统的整体信息,包括inode与block的总量、使用量、剩余量等。

  对于一个磁盘分区来说,在被指定为相应的文件系统后,整个分区被分为1024,2048和4096字节大小的块。根据块使用的不同,可分为:

  超级块(Superblock):这是整个文件系统的第一块空间。包括整个文件系统的基本信息,如块大小,inode/block的总量、使用量、剩余量,指向空间inode和数据块的指针等相关信息。

  inode块(文件索引节点):文件系统索引,记录文件的属性。它是文件系统的最基本单元,是文件系统连接任何子目录、任何文件的桥梁。每个子目录和文件只有唯一的一个inode块。它包含了文件系统中文件的基本属性(文件的长度、创建及修改时间、权限、所属关系)、存放数据的位置等相关信息.在Linux下可以通过“ls-li”命令查看文件的inode信息。硬连接和源文件具有相同的inode。

  数据块(Block):实际记录文件的内容,若文件太大时,会占用多个block。为了提高目录访问效率,Linux还提供了表达路径与inode对应关系的dentry结构。它描述了路径信息并连接到节点inode,它包括各种目录信息,还指向了inode和超级块。

  就像一本书有封面、目录和正文一样。在文件系统中,超级块就相当于封面,从封面可以得知这本书的基本信息;inode块相当于目录,从目录可以得知各章节内容的位置;而数据块则相当于书的正文,记录着具体内容。

  Linux正统的文件系统(如ext2、3等)将硬盘分区时会划分出超级块、inodeTable区块和datablock数据区域。一个文件由一个超级块、inode和数据区域块组成。

  Inode包含文件的属性(如读写属性、owner等,以及指向数据块的指针),数据区域块则是文件内容。当查看某个文件时,会先从inodetable中查出文件属性及数据存放点,再从数据块中读取数据。

  我们将inode与block区块用图解来说明一下,如下图所示,文件系统先格式化出inode与block的区块,假设某一个文件的属性与权限数据是放置到inode4号(下图较小方格内),而这个inode记录了文件数据的实际放置点为2,7,13,15这四个block号码,此时我们的操作系统就能够据此来排列磁盘的阅读顺序,可以一口气将四个block内容读出来!那么数据的读取就如同下图中的箭头所指定的模样了。

  这种数据存取的方法我们称为索引式文件系统(indexedallocation)。那有没有其他的惯用文件系统可以比较一下啊?有的,那就是我们惯用的闪盘(闪存),闪盘使用的文件系统一般为FAT格式。FAT这种格式的文件系统并没有inode存在,所以FAT没有办法将这个文件的所有block在一开始就读取出来。每个block号码都记录在前一个block当中,其读取方式有点像下图所示:

  上图中我们假设文件的数据依序写入1->7->4->15号这四个block号码中,但这个文件系统没有办法一口气就知道四个block的号码,他得要一个一个的将block读出后,才会知道下一个block在何处。如果同一个文件数据写入的block分散的太过厉害时,则我们的磁盘读取头将无法在磁盘转一圈就读到所有的数据,因此磁盘就会多转好几圈才能完整的读取到这个文件的内容!

  **常常会听到所谓的“碎片整理”吧?**需要碎片整理的原因就是文件写入的block太过于离散了,此时文件读取的效能将会变的很差所致。这个时候可以透过碎片整理将同一个文件所属的blocks汇整在一起,这样数据的读取会比较容易啊!想当然,FAT的文件系统需要经常的碎片整理一下,那么Ext2是否需要磁盘重整呢?

  由于Ext2是索引式文件系统,基本上不太需要常常进行碎片整理的。但是如果文件系统使用太久,常常删除/编辑/新增文件时,那么还是可能会造成文件数据太过于离散的问题,此时或许会需要进行重整一下的。不过,老实说,我倒是没有在Linux操作系统上面进行过Ext2/Ext3文件系统的碎片整理说!似乎不太需要啦!

  可以用ln命令对一个已经存在的文件再建立一个新的连接,而不复制文件的内容。

  连接有软连接和硬连接之分,软连接又叫符号连接。它们各自的特点是:

  硬连接:原文件名和连接文件名都指向相同的物理地址。目录不能有硬连接;硬连接不能跨越文件系统(不能跨越不同的分区)文件在磁盘中只有一个拷贝,节省硬盘空间;

  由于删除文件要在同一个索引节点属于唯一的连接时才能成功,因此可以防止不必要的误删除。

  符号连接:用ln-s命令建立文件的符号连接符号连接是linux特殊文件的一种,作为一个文件,它的数据是它所连接的文件的路径名。类似windows下的快捷方式。

  可以删除原有的文件而保存连接文件,没有防止误删除功能。

  这一段的内容过于抽象,又是节点又是数组的,我已经尽量通俗再通俗了,又不好加例子作演示。大家如果还是云里雾里的话,我也没有什么办法了,只有先记住,日后在实际应用中慢慢体会、理解了。这也是我学习的一个方法吧。

  3.6文件系统在内核中的表示

  内核数据结构

  Linux内核的VFS子系统可以图示如下:

  文件与IO:每个进程在PCB(ProcessControlBlock)中都保存着一份文件描述符表,文件描述符就是这个表的索引,每个表项都有一个指向已打开文件的指针,现在我们明确一下:已打开的文件在内核中用file结构体表示,文件描述符表中的指针指向file结构体。

  在file结构体中维护FileStatusFlag(file结构体的成员f_flags)和当前读写位置(file结构体的成员f_pos)。在上图中,进程1和进程2都打开同一文件,但是对应不同的file结构体,因此可以有不同的FileStatusFlag和读写位置。file结构体中比较重要的成员还有f_count,表示引用计数(ReferenceCount),后面我们会讲到,dup、fork等系统调用会导致多个文件描述符指向同一个file结构体,例如有fd1和fd2都引用同一个file结构体,那么它的引用计数就是2,当close(fd1)时并不会释放file结构体,而只是把引用计数减到1,如果再close(fd2),引用计数就会减到0同时释放file结构体,这才真的关闭了文件。


发表评论