Linux里面查看组里面x是i和x可以组什么词意思?

之前给大家整理了很多Linux系统运维常用的工具及命令,但是,如果想要学好Linux的话,更重要的是先了解Linux系统结构。

今天三花喵整理的就是Linux系统结构的详解,文章篇幅有点长,大家一定要耐心看完哦~

Linux系统一般有4个主要部分:

内核、shell、文件系统和应用程序。内核、shell和文件系统一起形成了基本的操作系统结构,它们使得用户可以运行程序、管理文件并使用系统。部分层次结构如图所示:

01左中括号linux内核左中括号

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

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

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

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

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

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

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

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

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

和 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 文件系统中的文件一样使用它们。

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

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

05网络接口(NET)

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

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

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

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

03左中括号linux 文件系统左中括号

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

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

1) 普通文件:C语言元代码、SHELL脚本、二进制的可执行文件等。分为纯文本和二进制。2) 目录文件:目录,存储文件的唯一地方。3) 链接文件:指向同一个文件或目录的的文件。4) 设备文件:与系统外设相关的,通常在/dev下面。分为块设备和字符设备。

5)管道(FIFO)文件 :提供进程建通信的一种方式6)套接字(socket) 文件: 该文件类型与网络通信有关

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

二、Linux下硬盘分区的标识

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

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

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

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

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

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

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

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

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

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

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

/bin 二进制可执行命令    /dev 设备特殊文件   /etc 系统管理和配置文件   /etc/rc.d 启动的配置文件和脚本   /home 用户主目录的基点,比如用户user的主目录就是/home/user,可以用~user表示   /lib 标准程序设计库,又叫动态链接共享库,作用类似windows里的.dll文件   /sbin 系统管理命令,这里存放的是系统管理员使用的管理程序   /tmp 公用的临时文件存储点   /root 系统管理员的主目录(呵呵,特权阶级)   /mnt 系统提供这个目录是让用户临时挂载其他的文件系统。   /lost+found 这个目录平时是空的,系统非正常关机而留下“无家可归”的文件(windows下叫什么.chk)就在这里   /proc 虚拟的目录,是系统内存的映射。可直接访问这个目录来获取系统信息。   /var 某些大文件的溢出区,比方说各种服务的日志文件   /usr 最庞大的目录,要用到的应用程序和文件几乎都在这个目录。其中包含:    /usr/X11R6 存放X window的目录    /usr/bin 众多的应用程序    /usr/sbin 超级用户的一些管理程序    /usr/doc

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

ext2 :早期linux中常用的文件系统ext3 : ext2的升级版,带日志功能RAMFS : 内存文件系统,速度很快NFS : 网络文件系统,由SUN发明,主要用于远程文件共享MS-DOS : MS-DOS文件系统VFAT 由SGI开发的先进的日志文件系统,支持超大容量文件JFS :IBM的AIX使用的日志文件系统ReiserFS : 基于平衡树结构的文件系统udf: 可擦写的数据光盘文件系统

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

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

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

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

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

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

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

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

Linux正统的文件系统(如ext2、3等)将硬盘分区时会划分出超级块、inode Table区块和data block数据区域。一个文件由一个超级块、inode和数据区域块组成。Inode包含文件的属性(如读写属性、owner等,以及指向数据块的指针),数据区域块则是文件内容。当查看某个文件时,会先从inode table中查出文件属性及数据存放点,再从数据块中读取数据。

ext2文件系统示意图

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

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

图、FAT文件系统数据存取示意图

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

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

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

可以用ln命令对一个已经存在的文件再建立一个新的连接,而不复制文件的内容。连接有软连接和硬连接之分,软连接又叫符号连接。它们各自的特点是:

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

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

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

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

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

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

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

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

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

每个file结构体都指向一个file_operations结构体,这个结构体的成员都是函数指针,指向实现各种文件操作的内核函数。比如在用户程序中read一个文件描述符,read通过系统调用进入内核,然后找到这个文件描述符所指向的file结构体,找到file结构体所指向的file_operations结构体,调用它的read成员所指向的内核函数以完成用户请求。在用户程序中调用lseek、read、write、ioctl、open等函数,最终都由内核调用file_operations的各成员所指向的内核函数完成用户请求。

file_operations结构体中的release成员用于完成用户程序的close请求,之所以叫release而不叫close是因为它不一定真的关闭文件,而是减少引用计数,只有引用计数减到0才关闭文件。对于同一个文件系统上打开的常规文件来说,read、write等文件操作的步骤和方法应该是一样的,调用的函数应该是相同的,所以图中的三个打开文件的file结构体指向同一个file_operations结构体。如果打开一个字符设备文件,那么它的read、write操作肯定和常规文件不一样,不是读写磁盘的数据块而是读写硬件设备,所以file结构体应该指向不同的file_operations结构体,其中的各种文件操作函数由该设备的驱动程序实现。

每个file结构体都有一个指向dentry结构体的指针,“dentry”是directory entry(目录项)的缩写。我们传给open、stat等函数的参数的是一个路径,例如/home/akaedu/a,需要根据路径找到文件的inode。为了减少读盘次数,内核缓存了目录的树状结构,称为dentry cache,其中每个节点是一个dentry结构体,只要沿着路径各部分的dentry搜索即可,从根目录/找到home目录,然后找到akaedu目录,然后找到文件a。dentry cache只保存最近访问过的目录项,如果要找的目录项在cache中没有,就要从磁盘读到内存中。

每个dentry结构体都有一个指针指向inode结构体。inode结构体保存着从磁盘inode读上来的信息。在上图的例子中,有两个dentry,分别表示/home/akaedu/a和/home/akaedu/b,它们都指向同一个inode,说明这两个文件互为硬链接。inode结构体中保存着从磁盘分区的inode读上来信息,例如所有者、文件大小、文件类型和权限位等。每个inode结构体都有一个指向inode_operations结构体的指针,后者也是一组函数指针指向一些完成文件目录操作的内核函数。

和file_operations不同,inode_operations所指向的不是针对某一个文件进行操作的函数,而是影响文件和目录布局的函数,例如添加删除文件和目录、跟踪符号链接等等,属于同一文件系统的各inode结构体可以指向同一个inode_operations结构体。

inode结构体有一个指向super_block结构体的指针。super_block结构体保存着从磁盘分区的超级块读上来的信息,例如文件系统类型、块大小等。super_block结构体的s_root成员是一个指向dentry的指针,表示这个文件系统的根目录被mount到哪里,在上图的例子中这个分区被mount到/home目录下。

file、dentry、inode、super_block这几个结构体组成了VFS的核心概念。对于ext2文件系统来说,在磁盘存储布局上也有inode和超级块的概念,所以很容易和VFS中的概念建立对应关系。而另外一些文件系统格式来自非UNIX系统(例如Windows的FAT32、NTFS),可能没有inode或超级块这样的概念,但为了能mount到Linux系统,也只好在驱动程序中硬凑一下,在Linux下看FAT32和NTFS分区会发现权限位是错的,所有文件都是rwxrwxrwx,因为它们本来就没有inode和权限位的概念,这是硬凑出来的。

linux系统中每个分区都是一个文件系统,都有自己的目录层次结构。linux会将这些分属不同分区的、单独的文件系统按一定的方式形成一个系统的总的目录层次结构。这里所说的“按一定方式”就是指的挂载。

将一个文件系统的顶层目录挂到另一个文件系统的子目录上,使它们成为一个整体,称为挂载。把该子目录称为挂载点.

例如要读取硬盘中的一个格式化好的分区、光盘或软件等设备时,必须先把这些设备对应到某个目录上,而这个目录就称为“挂载点(mount point)”,这样才可以读取这些设备。挂载后将物理分区细节屏蔽掉,用户只有统一的逻辑概念。所有的东西都是文件。

注意:1、挂载点必须是一个目录。

2、一个分区挂载在一个已存在的目录上,这个目录可以不为空,但挂载后这个目录下以前的内容将不可用。

NTFS。挂载前要了解linux是否支持所要挂载的文件系统格式。

挂载时使用mount命令,其格式:mount [-参数] [设备名称] [挂载点]其中常用的参数有

-t 指定设备的文件系统类型(什么提到的文件类型)-o 指定挂载文件系统时的选项。有些也可用在/etc/fstab中。常用的有

1、挂载windows的文件系统:

首先要安装虚拟电脑工具包:在VirtualBox的菜单里选择”设备”->”安装虚拟电脑工具包”,你会发现在Ubuntu桌面上多出一个光盘图标,这张光盘默认被自动加载到了文件夹/media/cdom0,而且/cdrom自动指向这个文件夹。默认设置下文件管理器会自动打开这张光盘,可以看到里面有个”VBoxLinuxAdditions.run”文件。打开一个命令行终端,依次输入”cd /cdrom”和”sudo sh ./VBoxLinuxAdditions.run”,不含双引号,开始安装工具包。安装完毕,会用英文提示要重启Ubuntu,建议立刻重启。重启后,比较明显的变化是鼠标是共享模式,并且剪贴板也和Windows共享了。如果有这些变化,说明虚拟电脑工具包已经装成功。

2). 下一步设置共享文件夹。

在共享文件夹设置窗口中,单击右侧的”添加一个共享文件夹”,路径选择你想要共享的Windows文件夹,共享名任取一个自己喜欢的,比如”myshare”,选项read-only是指是否只允许ubuntu读这个文件夹,请根据需要选择这个选项。

每次开机访问windows分区都要运行mount命令显然太烦琐,为什么访问其他的linux分区不用使用mount命令呢?

其实,每次开机时,linux自动将需要挂载的linux分区挂载上了。那么我们是不是可以设定让linux在启动的时候也挂载我们希望挂载的分区,如windows分区,以实现文件系统的自动挂载呢?

这是完全可以的。在/etc目录下有个fstab文件,它里面列出了linux开机时自动挂载的文件系统的列表。我的/etc/fstab文件如下:

在/etc/fstab文件里,第一列是挂载的文件系统的设备名,第二列是挂载点,第三列是挂载的文件系统类型,第四列是挂载的选项,选项间用逗号分隔。第五六列不知道是什么意思,还望高手指点。

在最后两行是我手工添加的windows下的C;D盘,加了codepage=936和iocharset=cp936参数以支持中文文件名。参数defaults实际上包含了一组默认参数:

rw 以可读写模式挂载suid 开启用户ID和群组ID设置位dev 可解读文件系统上的字符或区块设备exec 可执行二进制文件auto 自动挂载nouser 使一般用户无法挂载async 以非同步方式执行文件系统的输入输出操作

大家可以看到在这个列表里,光驱和软驱是不自动挂载的,参数设置为noauto。(如果你非要设成自动挂载,你要确保每次开机时你的光驱和软驱里都要有盘,呵呵。)

可以用ln命令对一个已经存在的文件再建立一个新的连接,而不复制文件的内容。连接有软连接和硬连接之分,软连接又叫符号连接。它们各自的特点是:

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

修改其中一个,与其连接的文件同时被修改。如果删除其中任意一个其余的文件将不受影响。

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

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

当然删除这个连接,也不会影响到源文件,但对连接文件的使用、引用都是直接调用源文件的。

从图上可以看出硬链接和软链接的区别:

1:硬链接原文件和新文件的inode编号一致。而软链接不一样。2:对原文件删除,会导致软链接不可用,而硬链接不受影响。3:对原文件的修改,软、硬链接文件内容也一样的修改,因为都是指向同一个文件内容的。

04左中括号linux 应用左中括号

标准的Linux系统一般都有一套都有称为应用程序的程序集,它包括文本编辑器、编程语言、X Window、办公套件、Internet工具和数据库等。

05左中括号linux内核参数优化左中括号

内核参数是用户和系统内核之间交互的一个接口,通过这个接口,用户可以在系统运行的同时动态更新内核配置,而这些内核参数是通过Linux Proc文件系统存在的。因此,可以通过调整Proc文件系统达到优化Linux性能的目的。

如果想了解更多关于Linux的技术干货,请关注公众号【Linux架构师训练营】

每一个不曾起舞的日子,都是对生命的辜负。

  • 2.3 查看进程的另一种方式(了解)
  • 2.5 常见进程调用(父进程、子进程)
  • 2.6 通过系统调用创建进程-fork初识
    • 3.1 普遍的操作系统层面
  • 5. 进程优先级(了解范畴)

那在还没有学习进程之前,就问大家,操作系统是怎么管理进行进程管理的呢?很简单,先把进程描述起来,再把进程组织起来!

对于我们的了解来说,什么是进程呢? 有的资料是这么说:一个运行起来的程序(加载到内存)叫做进程;在内存中的程序叫做进程。也就是说,进程和程序相比具有动态属性。

对于之前我们通过C写出的进度条程序来说,其本质就是一个文件并且存放在磁盘中。但是其并没有真正的运行,当我们运行程序的时候,文件就会从磁盘加载到内存,但是磁盘中那么多的文件全部加载到内存中明显是不现实的并且我们也不需要其他文件加载到内存,这时候就需要操作系统对文件进行管理从而只让我们想要执行的程序加载到内存,那操作系统是如何管理的呢?

即上篇提到的:先描述,再组织

通过上述的概念,我们了解的并不多,那么接下来就来分析一下:如果有很多这样的进程加载到内存中,操作系统要如何进行管理呢? 即利用先描述再组织的思想。

而所谓的先描述,这里引进了一个新的概念:PCB :进程控制块 struct task_struct{}

1. 那么什么是进程控制块呢?

进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合,称之为PCB(process control block)在Linux中描述进程的结构体叫做task_struct。

在磁盘中的程序中,并没有进程控制块以及内部属性信息的存在,而是加载到内存之后通过操作系统的一系列的管理才出现的。


 
 

2. 进程控制块如何对进程进行管理的呢?

  • 磁盘中的可执行程序在将要运行时,所有的进程中的数据(并不是程序本身)加载到内存中,此时操作系统会建立起一个PCB来保存每一个程序的信息
  • 这个时候PCB就会对每一个进程都建立起相应的结构体(即进程控制块)将对应的进程的属性、代码等匹配的传到这个结构体中:(这就是先描述)

  • 此时,操作系统就会将每一个进程控制块都连接起来,形成链表结构,并返回头结点。这样便通过数据结构的形式将进程的信息组织起来。

通过这样的先描述再组织的思想,当我们处理优先级高的进程时,我们就可以通过遍历头结点,找到优先级最高的那个节点的信息,并将这个进程的代码执行。

因此通过上面的描述,我们就可以回答1.2开始时所问的问题:操作系统要如何进行管理呢?

答:所谓的对进程进行管理,会变成对进程对应的PCB进行相关的管理,也就是说:对进程的管理变成了对链表的增删查!

最终,通过上述的解释,进程究竟是什么我们也就知晓了:进程 = 内核数据结构(task_struct) + 进程对应的磁盘代码

3.为什么要有进程控制块(PCB)呢?

通过上一篇介绍的软硬件体系结构以及刚才的描述,对于为什么要有PCB进行了解答:

对进程管理的核心是对数据进行管理,因此当我们加载程序到内存之前,我们必须拿到所有程序的数据,由于拿到的数据杂乱无章并且未进行分类,这时候就需要PCB将其归类,将对应的数据放到相应的进程控制块里!

即加载进程的时候,操作系统为了方便管理会new一个struct task_struct也就是进程控制块的结构体,然后一点点的将上面加载的数据填充到这里的内部属性(状态,标记,追踪等),因此这里再一次强调了:进程不是程序加载到内存,而是在内存中new了task_struct结构体!

  1. 执行,并通过打开复制ssh渠道,输入指令:

    (//&&的左右是两个指令,通过&&可以将两个指令一起执行。左面是通过管道将进程的第一行显示出来,右面是将myproc相关的进程信息打印出来,不利用管道将会出现其他没必要的信息)

    动图:(在运行中,进程就具有动态属性)

结束进程有两种方式,下面就来介绍:

这样就可以结束掉我们的进程了。

通过快捷键ctrl + c也可以结束进程。

2.3 查看进程的另一种方式(了解)

通过上面的描述,查看进程和结束进程我们都已经了解,在这里还要引入一个新的关于查看进程的知识。

仍是对于这个程序,我们让其运行(实际上进程在调度运行的时候,就有了动态属性)。

通过指令:ls /proc/5058我们就可以看到这个进程中的信息。

这也可以说明,进程实际上也是一个Linux中能够保存的文件。我们进入到5058:

我们发现,其中生成了一个这样的.exe文件,这实际上就是我们正在运行的程序。

那如果我们把这个文件删除了,程序还会不会运行呢?我们接下来试一试:

我们发现,左面的颜色变红提示了已经删掉,但是右下角的程序仍然在进行,这也恰恰说明了加载到内存的数据不会受到磁盘文件的影响!

我们发现,上面的执行过程中我们如果想要结束进程,就需要kill 9 PID,而这个PID的值我们该如何获取呢?我们可以通过getpid函数获取。

我们发现,getpid()函数的返回类型是pid_t,这是我们在C/C++所不曾见到的类型,而getpid()的功能就是:返回这个进程的pid。

因此我们就可以根据这个信息编写代码:

我们发现,确实是一样的。也就是说,当我们想知道一个进程的PID,就可以通过getpid获取。

2.5 常见进程调用(父进程、子进程)

我们将上述myproc.c增加一个父进程的打印:

当我们结束时,发现父进程的PID并没有发生变化,事实上父进程的PID就是bash即命令行的PID,父进程本身因此在下一次登陆之前,父进程的PID不会发生变化。

2. 子bug父进程的变化

为了解释这个,我们将myproc.c内部增加一个bug:

这说明这个程序执行了,并且报错了,但是仍然可以通过命令提示错误,因此我们可以看出,程序执行是以子进程在执行,其出错并不会导致父进程错误,父进程也就是命令行的进程,因为提示的错误就是父进程在提示!因此父进程并没有错误!

2.6 通过系统调用创建进程-fork初识

我们通过man fork了解到,fork是创建子进程的函数,但是当这个函数执行前,只有自己本身这个进程和他的父进程,执行之后,这个自己本身的进程就会变成子进程的父进程,而相应的这个进程的父进程也就变成了父进程的父进程。

我们发现,这就相当于bash是爷爷进程,而程序本身是父进程,fork创建出的的是子进程。

通过man查看fork手册/return val,我们发现fork有两个返回值,那具体是什么含义呢?接下来我们实验一下:

我们发现,同一个变量id,在后续不会被修改的情况下,竟然有不同的内容!但是这里我们还不知道为什么也没办法解释,因此在这里我们打不过,就加入他,利用这个规则,我们来看看下面的程序:(注意sleep这里的细节)

// 创建子进程 -- fork是一个函数 -- 函数执行前:只有一个父进程 -- 函数执行后:父进程+子进程

我们发现,两个进程同时执行,即if可以执行,elseif的也一起执行,没错,if和elseif竟然同时执行了,这就是引入fork的缘故(多进程)。

即fork()之后,因为pid既可以是0也可以是1,会有父进程+子进程两个进程在执行后续代码(即两条路线去执行if和else if两个分支),fork()的后续代码,被父子进程共享,让父子进程执行后续共享代码的一部分,这就叫做并发式的编程!

对于运行状态,有以下几种:

对于这些运行状态,都是操作系统层面上的说法,为了让理解的更加深刻,接下来以两方面去解释:

3.1 普遍的操作系统层面

**进程状态的概念:**通过上面的学习我们知道,当一个程序执行加载到内存时,操作系统就会创建对应的PCB(进程控制块:struct),而在这个PCB结构体中,有一个位置存放着整型的成员变量,而这个整形变量的不同数值,就代表不同的进程状态。

进程状态一共有九种:运行、新建、就绪、挂起、阻塞、等待、停止、挂机、死亡 ;其中运行、阻塞、挂起是最为重要的进程状态。下面就讲解这三个最重要的状态:

对于运行状态来说,并不是在CPU中正在运行才是运行状态,只要是进程在CPU的等待队列中,那么就可以称之为进程的运行状态(R)

对于阻塞状态来说,进程在磁盘中的阻塞队列中,就称之为进程的阻塞状态。

通过上面的描述,事实上等于没说什么,什么是运行队列?什么是阻塞队列?为什么会有运行队列和阻塞队列?二者之间存在着什么关系? 事实上这才是运行状态和阻塞状态的切入点,那我们带着疑问一起了解:

当一个进程开始执行时,会将二进制代码从磁盘加载到CPU中去执行,但是我们知道,进程的数量远远多于CPU的数量,这个时候操作系统就会将这些进程进行管理,让一些进程去等待,另一些进程去运行。假设我们只有一个CPU。当一个进程正在执行是,那么其他进程就需要去排队等待CPU资源(CPU会维护一个运行队列让这些要执行的进程去排队,这个运行队列是内核为CPU准备的,一个CPU,一个运行队列)(注:让进程入队列的本质就是将该进程的PCB结构体对象放入运行队列中,而不是让进程(程序)自己去排队)而等待的这些进程都在运行队列中,那么他们就都处于运行状态!

我们知道,冯诺依曼体系结构中的CPU很快,但是(外设)磁盘相对较慢,但是进程除了访问CPU,也避免不了访问磁盘(外设),比如fwrite就是将进程与磁盘之间相联系(而对于scanf、cin这些函数也会访问显示器,一些代码也会通过网络访问网卡,这些都是与外设想交互)但是磁盘很慢,不像CPU一样,所以当A用着,其他的进程就需要等待,因此这样看来进程也可能在外设上等待,也就是说,不要只意味着进程只会占用CPU资源,进程同样也会占用外设资源,因此外设也有自己的描述结构体,也可以维护自己的等待队列! 进程在外设的等待队列中就是进程的阻塞状态!

由于外设的等待队列过慢,CPU因为会执行代码但被外设的速度限制,这时CPU就会对外设说,不好意思,你太慢了,我不想等你了!因此这个时候CPU就会将对应的代码的进程从CPU的等待队列(也就是运行队列)中放到外设的等待队列中,从而去执行CPU运行队列中的下一个进程。

这就好比什么呢?就相当于当你去银行办理业务,当到你到指定柜台去填表时,由于你填的太慢,这时候工作人员为了不让你占用过多时间,就会让你离开窗口,去旁边的桌子上继续填表,为的就是不耽误你后面人的时间让他们继续办理业务。因此这就将这个进程从CPU的运行队列里强行拉到了外设的等待队列中。这个进程也就从运行状态切换到了阻塞状态!

而当你填完表之后,你通过其他工作人员的告知,就会直接进入窗口处理业务,也就是从阻塞状态直接变成运行状态,这个操作就是CPU自动调度而不是操作系统处理的,因为操作系统之前已经处理完你,也就是把你从窗口移到了附近的桌子,就不会继续管你了!

需要注意的是:我们所提到的这些拖拽,排队,不是进程本身的行为,而是他们PCB的行为!

因此所谓的进程的不同状态,本质就是进程在不同的队列中,等待某种资源!

对于新建和就绪状态其实是同一种状态,很好理解,就是这个进程刚刚被创建好,也就是我们所谓的make,因此我们不需要去描述。

将内存中进程的数据和代码转移到磁盘的状态被称为挂起状态。

为了解释挂起状态,我们建立这样一个场景:如果阻塞的进程过多,那么他们是不会被立即调度的,也就是说不会将这些进程从阻塞状态同时转换成运行状态,因为这些阻塞的进程本身也需要彼此之间进程排队。那么我们知道,在进程阻塞时,其对应的数据和代码还在内存中,万一内存不够了,怎么办?

由于过多的进程站着茅坑不拉屎的不良行为,这时操作系统就会体现他的义务将这些有不良行为的阻塞进程体验社会的毒打,因此为了不让阻塞的进程占用内存,操作系统就会将阻塞状态的进程的数据和代码转移到磁盘上储存,这样这个进程就从阻塞状态变成了挂起状态!

此时内存中仍有挂起状态进程的PCB,只是其中的代码和数据转移到了磁盘,减少了内存占用的空间。将内存的相关数据加载或保存到磁盘,叫做内存数据的换入换出。

阻塞状态和挂起状态的区别:阻塞不一定挂起,但挂起一定是阻塞!

就好比几年前用过的安卓手机,比如王者荣耀,如果手机用的时间久或者内存小的话,每一次后台运行之后点进去,就有可能重新开始而不是接着上次的界面,这就是因为占用内存过多,内存不够,于是操作系统(安卓系统)将这个进程挂起了。

为了弄明白正在运行的进程是什么意思,我们需要知道进程的不同状态。一个进程可以有几个状态(在Linux内核里,进程有时候也叫做任务)。
下面的状态在kernel源代码里定义:


其中,这个结构体中的各种状态就一一对应着我们在普遍的操作系统层面上的状态,分别是:运行状态,睡眠状态,深度睡眠状态,停止状态,停止追踪,死亡状态,僵尸状态。下面先从定义上描述一下一些状态,之后再具体分析。

  • R运行状态(running): 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。
  • S睡眠状态(sleeping):意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠
  • D磁盘休眠状态(Disk sleep):有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。
  • T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。
  • X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态。

那当我们执行,看生成的可执行程序是什么状态:(STAT就代表这个进程的状态)

通过./myprocess,执行后这个程序便处于运行状态(R+)。

我们将上面的代码加上一行printf输出的形式:

有了printf,就需要动图展示一下具体的状态了:(动图)

我们发现,在打印的过程中,myprocess的状态不是运行状态,而是S+休眠状态。事实上,这是由于我们通过printf访问的是外设,而我们知道外设很慢,因此进程等待显示器就绪需要花费很长时间,于是就会把该进程的PCB转移到外设的PCB上排队,这也就对应了普遍操作系统层面上的阻塞状态。

当然,这也不是绝对的,只是对大多数进程而言(99%),因为大多数都是在等待显示器就绪,如果我们想访问变成R状态,可以sleep一个很大的秒数,这样就有机会看到是R状态了

我们之前用的printfscanf事实上都算是浅度睡眠,即S即为浅度睡眠状态,浅度睡眠状态是可以终止的,也就是ctrl c就可以直接终止。而深度睡眠状态是不可以终止的,即无法被操作系统杀死,只能通过断电解决。

对于这个状态,我们通过想象这样的一个场景去理解他:

当一个用户给操作系统、进程、磁盘三个人制定任务时,其中进程和磁盘说这是1万条用户数据,你帮我拷贝一下,磁盘答应了,但是磁盘有可能拷贝成功,也有可能失败。然而这个时候由于进程过多,内存不够了,此时操作系统就会站出来将一些不干活的进程杀掉,但内存仍然不够,于是操作系统秉着他的责任,将所有的进程全部杀掉,自己累的够呛也挂了。但这时磁盘处理数据失败了,就回去找进程,让他重新搞来一份数据,但是此时进程没有回应他,喊了很多次仍无人回应,最后也就这样草草了事。

当用户知道这个任务没有完成,就找到他们三个追究责任,磁盘率先站出来说:这不关我的事,我本来就有可能成功有可能失败,当我失败的时候去找进程发现他不见了,和我没有关系;这时候进程也出来说话了:这和我也没有关系,我是被操作系统杀掉了,怎么能回应你呢?最后操作系统发现他们两个把矛头指向了自己,就气愤的说:我有我的职责,内存不够了,我必须杀掉进程防止内存不够,这就是我的任务,并不是只针对你这一个进程,所有进程在我眼里都是一样的。用户听了他们说的话,却都觉得没什么问题,于是就对操作系统说:下次对于这样的情况,不要杀掉指定的进程,这就相当于给了这个进程一个免死金牌,操作系统也是清楚了具体的规则,同意了,进程和磁盘也表示没问题。这个时候,这个给予免死金牌的进程就处于所谓的深度睡眠状态,不可被操作系统杀死,只能断电处理!

需要注意的是:深度睡眠一般只会在高IO的情况发生下,且如果操作系统中存在多个深度睡眠状态的程序,那么说明该操作系统也即将崩溃了。

当我们查看kill 手册,找到对应的19号选项后:

我们发现,状态就从R状态变成了T状态,变成了之后呢,T状态代表什么呢?事实上,T状态也是阻塞状态中的一种,因为其代码不被CPU执行,但是其属不属于挂起状态呢?这个我们无从得知,因为这是操作系统所做的事情。

既然有暂停,那么就一定有继续。我们看上面的kill选项中,18号就是继续的选项,那我们来看看:

我们发现,又变回了R状态,只不过有个细微的差别,和最初的R+相比,+不见了。

如果我们将程序加上printf,让其变成S+状态,当我们再对应的显示器上输入除了ctrl c的其他命令行,我们会发现其并不会执行,而显示器上照常打印,这就是所谓的前台进程。如果我们将其T掉,再kill 18对应的进程让其继续,我们会发现状态变成了S,出现了和运行状态时一样的情况,而这时当我们再输入命令行时,会发现可以显示对应的结果,并且可以继续打印,这就是所谓的后台进程,但是对于后台进程,不能用ctrl c结束,只能通过kil -9 PID的形式结束进程。因此我们也就知道了+的意义,有+的是前台进程,没有+的是后台进程。

对于追踪暂停状态,其实是一种特殊的停止状态,即进程在调试时就处于追踪暂停状态:(gdb)

死亡状态代表着一个进程结束运行,该进程对应的PCB以及代码和数据全部被操作系统回收。

我们知道,进程被创建出来是为了完成任务的,而完成的结果也是需要被关注的,即进程完成的结果会被其父进程或者操作系统接收,因此在进程退出的时候,不能释放该进程对应的资源,而是保存一段时间,让父进程或者操作系统来进行读取。因此在这个进程退出后到被回收(OS、父进程)前的状态就是僵尸状态!

对于僵尸状态的进程,事实上不是数据存在在内存,而是其对应的PCB在内存中占用空间,因此如果这种进程过多导致PCB占用内存过大,并且父进程和操作系统没有及时回收这种资源,那么就极易发生内存泄漏。由此可见。除了malloc或者new,系统层面上也是有可能发生内存泄漏的。

既然有僵尸状态的危害,就一定有解决的方法,解决的方法将在后续讲解,在此只需要知道僵尸状态是什么,有什么危害就是我们这一节的目标。

具体的Linux操作系统下的进程状态和普遍的操作系统上进程的状态的分类是不同的,Linux操作系统和普通的进程状态相比没有阻塞和挂起状态,普通OS的阻塞状态在LinuxOS中通过睡眠、深度睡眠、暂停、追踪暂停等状态表现出来,而进程处于这些状态时是否会被调整为挂起状态,用户是不可得知的,因为操作系统没必要将挂起状态暴露给用户,用户也不关心一个进程是否会处于挂起状态。

上述已经提到过僵尸状态的进程的概念,那么在这里就详细演示一下僵尸进程的具体面貌:(代码)

我们发现,通过sleep,为4044的子进程被杀掉了,此时父进程并没有处理子进程,因此出现了default(失效)并且子进程变成了Z状态,并且左侧也验证了只剩下父进程,并没有子进程的存在了!如果父进程一直不对这个子进程进行收取,那么这个子进程就会变成僵尸进程。

1. 什么是孤儿进程?

上述我们提到,如果一个子进程被杀,那么其暂时就会处于僵尸状态,如果没有父进程回收就会变成僵尸进程。那如果是父进程被杀,父进程和子进程又会发生什么呢?事实上,父进程被杀,**即父进程比子进程先退出,那么剩下的子进程就叫做孤儿进程。**这种现象也确实存在。

2.孤儿进程的表现形式

我们知道,如果一个进程变成了僵尸进程,其进程状态就会变成T,那我们来看看孤儿进程是如何表现的。

  1. 首先,我们仍然展示一下具体代码:(和僵尸进程中的代码一致)
  1. 接下来,复制SSH渠道,杀掉父进程,观察子进程的状态。(父进程也关注一下)动图展示:

我们发现,有三处发生了变化,其一是父进程被杀之后,变成了S状态,但是这样不就与我们之前的僵尸状态违背了吗?为什么不是T状态呢?事实上我们在上述僵尸状态中讲过,在被父进程回收之前就是T状态,而这个父进程被杀掉,也有其相应的父进程,这个父进程的父进程就是bash,bash相比较普通的父进程,bash进程将他的子进程进行了及时的回收,而这个父进程却不会对其子进程进行及时的回收。因此对比之下bash进程比一般的父进程更加负责。

其二就是我们子进程的状态,由S+变成了S进程,即从前台进程变成了后台进程,这就是孤儿进程最明显的变化,变成后台进程后不能通过ctrl c快捷键暂停,而只能通过kill结束进程(当然,断电处理也可以,但是没必要)

其三我们发现,子进程的PPID也就是这个子进程的父进程因为被杀掉而变成了1,而这个1所对应的其实就是操作系统,即父进程被杀掉之后,这个子进程被操作系统所领养,操作系统就变成了他的父进程,这也正对应了冯诺依曼体系中的进程被操作系统所管理。如果不领养,那么当这个子进程被杀掉时,就会因为没有后续处理从而将变成僵尸进程,这是整个体系都不愿看到的结果,因此操作系统必须领养。

对于进程优先级,我们采取三个问题将这个概念解释清楚:

1. 什么叫做优先级?

只凭字面意思来说,优先级和权限有没有区别呢?答案是一定有的,即权限是能做或者不能做的问题,而优先级是先做和后做的问题。

2. 为什么会存在优先级?

那为什么会存在优先级呢?那是因为在一定范围内的资源是有限的,为了获得这个资源就必须赶在其他人的前面,否则就有可能最后什么也捞不到。举个例子:我们知道在一个内存中有许多的进程,但是CPU只有一个,这个时候进程为了能够先执行就会产生优先级的概念,即重要的进程先运行,其他的进程后运行。

在Linux操作系统中,在ps ajx 选项中出现的PRI(priority)下的数字就是所谓的优先级,即这个数字和我们现实中的排名一样,数值越低,优先级就越高。而这个数值PRI = 基础数值(80) + nice值,(NI)nice值是可以进行修改的,其修改区间为[-20,19],因此PRI的范围为[60, 99]。

仍然是利用孤儿进程的代码:

我们发现,初始状态下,PRI和NI的值为80和0,加起来就是基础数值。

通过如下指令:进入top后按“r”–>输入进程PID–>输入nice值

第一步:sudo top(改变优先级需要提权)

第二步:输入r,输入对应要修改优先级进程的PID,回车

第三步:输入修改之后的NI值。回车。

这样就修改完成了,接下来我们看一看结果:

  • 竞争性: 系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级
  • 独立性: 多进程运行,需要独享各种资源,多进程运行期间互不干扰
  • 并行: 多个进程在多个CPU下分别,同时进行运行,这称之为并行
  • 并发: 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发(一段时间采用:时间片轮转的方式)

在定义之前,我们需要举例引入进程切换的概念,对于我们常用的手机、电脑等,一般只有一个CPU,我们知道一个CPU一次只能运行一个进程,但是我们发现,在电脑上,我们可以在打开PDF的同时,去浏览一些其他网页,即同一个时间段内,多个进程可以被CPU同时运行,这是为什么呢?事实上这就是进程切换的效果。

由于Linux的CPU一次只能运行一个进程,但是我们一个时间段内却可以运行多个进程,因为CPU是足够快的,因此我们人感觉的一瞬间就相当于CPU的一个时间段,想一想1ms对于人来说算是一瞬间,但是CPU却是以纳秒为单位计时的,因此在我们自身感觉到的一瞬间也就是CPU的一个时间段内,会将执行的多个进程按照一定的周期分别运行,一个运行到固定周期之后就强行拉入运行队列的末尾等待,就这样直到完成所有执行的进程,这就是进程之间在一定的时间内相互切换,叫做进程切换。而所谓的周期就是时间片。(并发中提到)

当CPU在进行进程切换的时候,要进行进程的上下文保护,当进程在恢复运行的时候,要进行上下文进程的恢复!

进程在运行时会产生非常多的临时数据,同时CPU中存在一套寄存器硬件,当进程运行时,进程的PCB会被放入CPU内的寄存器中,此时CPU就可以通过进程PCB(暂时理解成PCB)得到进程代码数据的地址;CPU在运行进程时所产生的大量的临时数据也都会被保存在寄存器中;因此在进行进程切换时需要进行进程的上下文保护与上下文恢复,进程停止运行时将寄存器里面的数据保存起来,进程重新运行时将保存的数据再放入到寄存器中;所以进程的上下文就是一个进程完成他的时间片后所保存的数据。

CPU寄存器硬件被所有进程共享,但CPU在具体运行某一进程时,CPU寄存器中的数据只属于该进程;同时,我们进行上下文保护时保存的是寄存器中的数据,而不是寄存器硬件。

用Root账号登录,运行下面指令,创建所需要用户和用户组;

passwd oracle   #设置用户oracle的登陆密码,不设置密码,在CentOS的图形登陆界面没法登陆

ls  #创建完毕检查一下

#分配安装文件授权Oracle

这时会报错,要求至少256种

第一项为安装数据库软件并创建一个数据库实例

第二项为只安装数据库软件

第三项为升级已经存在的数据库

选择第二项,可以在安装数据库软件后,手工通过dbca来创建实例。

这个界面上选择支持的语言,在左面列表里面选择“Simplified Chinese”,添加到右面列表,点击Next继续:

选择oralce使用的操作系统用户组,保持默认,点击Next继续

Oracle安装程序用检查系统参数,以确定是否满足了安装oracle的前提条件,包括系统内核、虚拟内存和软件包等。安装3.3章节介绍的方法把包安装好之后,由于操作系统的包版本过高,会导致oracle提示如下包缺失,实际上已经安装好了。勾选右上角的“Ignore All”复选框,点击Next继续:

如果提示没有pdksh-5.2.14,请根据64位或者32位系统安装对应的包。

Oracle安装程序提示安装摘要,点击Finish继续:

Oracle开始按照前面步骤的设定,开始安装:

使用root用户执行系统提示的2个脚本,完成安装:

对于脚本中的提示,直接回车确认即可,执行完毕后,点击OK安装过程就完成了。

dbca  (本人执行命令后一直报错,后来重启机器后没报错,

(0)欢迎界面,在界面上点击Next继续

如果是单节点数据库那么此处应该选择“General Purpose”,如果是集群数据库系统那么此处选择“custom database”选项

当数据库运行在没有域服务的环境中时,两个值是相同的;当运行在域环境中时,Global Database Name应该设置为SID.域名。注意:这里设置的SID值,要跟oracle用户.bash_profile中的ORACLE_SID设置保持一致。

勾选之后,如果有下面的提示,可以根据8.1章节的介绍,用netca创建一个监听并继续:

(5)设置oracle用户的密码,建议为所有用户设置相同的密码,密码最好不要含有”@”特殊字符,在界面上点击Next继续 (本人设置密码:)

如果你设置的密码太简单,会有以下提示界面,选择Yes继续

(6)选择存储设置,这里选择File System,把数据库文件保存在本地磁盘,在界面上点击Next继续

选择File System,把数据库文件保存在本地磁盘。

ASM即自动存储管理,是oracle提供的一套存储管理程序,可以平台无关的方式提供文件系统、逻辑卷管理器以及软件 RAID(磁盘阵列)等服务,有ASM管理经验的可以选择这个选项。

(7)在安装界面上点击Next继续

这个界面设置Flash Recovery Area的位置和大小,保持默认即可。下面的复选框,“Enable Archiving”是启用归档日志,并可以指定归档日志的位置,默认是没有启用归档日志的。

(8)在安装界面上点击Next继续

这里选择,是否安装Oracle的演示数据,包括几个测试用户及其表、视图等数据。生产系统不用安装这些演示数据,会占用一部分资源,而且会产生安全问题。

(9)初始化参数选项,设置完毕后在安装界面上点击Next继续

或者选择Custom,SGA设置为内存的一半,PGA设置为SGA的一半,即

   如果SGA设置超过1G,那么必须设置为16M的倍数,SGA设置小于等于1G,那么必须将它的大小设置为4M的倍数,这个倍数被称之为granules(颗粒),SGA必须是granules的整数倍。

即同时连接到数据库的客户端进程的最大数目,在专用服务器模式下,等同于oracle前台进程的数量,恒生推荐值是 1500到3000

必须选择ZHS16GBK,否则保存和显示中文数据的时候会产生乱码

选择oracle数据库工作在专用模式还是共享模式,现在生产系统都是专用模式,性能更好一些,适合于中间件与数据库保持持续连接。

(10)数据库文件的存放位置,设置完毕后,在界面上点击Next继续

Groups)的位置和大小。对于重做日志组,文件大小默认是50M,默认值太小了,对于业务比较频繁的系统建议调整到500M至1G,重做日志组数据量默认为3个,增加到5个,尽可能减少日志切换发生checkpoint时造成数据库性能下降。如果没有在这个界面添加,也可以通过以下语句手工添加:

推荐将上面所有文件保存在/u02/oradata目录

(11)确认创建数据库实例,在安装界面上点击Finish结束

保持默认即可,不用保存模版,也不用保存数据库的创建语句。

(12)确认创建数据库实例,在界面上点击OK

(13)oracle执行创建实例的过程

在linux无论怎么连接数据库都报错,下面是报错截图

L/SQL不论是连接LINUX上的baiduORACLE还是windows上的oracle 都是一样的,只要你把服务zhi器上的监听dao打开,根本不用去管服务端是啥操作系统。

最简单的办法是在你的本机上装个oracle客户端,安装完成后

再点下左边的绿色加号,添加一个新的

第一步:网络服务名:这个填写你连接时需要使用的字符串可随便取名如test

第三步:主机名:填写服务器IP 端口: 一般为1521

第四步:填写oracle的实例名

Oracle实例和监听创建完毕后,需要设置oracle随着操作系统自动启动,这里介绍两种方法,rc.local方式或者增加一个系统服务,两者是等效的。

把文件尾部的N改为Y:

用root用户创建并编辑服务脚本:

勘误:有以上两步就足够了。有的文档会要求执行

关闭OEM,使用oracle用户登录,执行命令:

以下命令推荐用sys用户登录PLSQL Developer,使用命令窗口执行:

Oracle 11g默认密码过期日为180天,设置为永不过期:

Oracle 11g默认密码是大小写敏感的,设置为大小写不敏感:

06版应该设置为基于成本的:

UF20设置为基于规则的:

取消登录失败超过10次锁定用户的限制

重新设置SGA和PGA大小:(慎用)

如果为SGA和PGA分别设置:

请根据实际情况修改上面的值,如果启用了AMM则将memory_target和memory_max_target设置为物理内存的75%,这部分内存oracle会动态的分配给SGA和PGA。如果分别为SGA和PGA设置,前2个命令设置SGA,最后一个命令设置PGA,修改完毕后重启实例检查数据库是否正常。

我要回帖

更多关于 i和x可以组什么词 的文章

 

随机推荐