加入收藏 | 设为首页 | 会员中心 | 我要投稿 天瑞地安资讯网 (https://www.52baoding.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Unix > 正文

linux内核学习笔记——概述

发布时间:2022-11-01 13:31:11 所属栏目:Unix 来源:转载
导读: 1.1 linux和其他系统的比较
linux遵从posix标准,具有所有现代OS的特征:虚拟内存,虚拟文件系统,线程,可靠的信号,SVR4进程间通信机制,对称多处理器系统的支持(SMP)等。以下是linux的

1.1 linux和其他系统的比较

linux遵从posix标准,具有所有现代OS的特征:虚拟内存,虚拟文件系统,线程,可靠的信号,SVR4进程间通信机制,对称多处理器系统的支持(SMP)等。以下是linux的主要竞争优势:

(1). 单块结构的内核

和多数UNIX变种OS一样,linux内核是单块结构的。它是由许多不同的逻辑模块构成一个负责的大程序。

(2). 编译的、静态连接的内核

linux能按需求自动地加载和卸载kernel里的某些模块(如某个设备的驱动),这是现代OS的特征。

(3). 内核线程

linux在内核级就支持多线程,这给进程切换带来了高效。linux用内核线程用一种受限的方式来周期性地执行的几个内核函数。

(4). 多线程

linux支持多线程应用程序。多线程的程序就有多个相互独立的执行流,他们共享主程序的代码和某些公用数据,他们有相同的地址空间、使用相同的页以及相同的资源(如打开的文件)。linux的多线程支持是比较独特的,和大多数要依赖内核线程来实现多线程的OS不同,linux使用clone( )系统调用。

(5). 非抢占式的内核

linux在处于内核特权模式下不能任意交叉运行执行流(后继的linux版本可能对此限制有所改变),某些内核部分的执行是不能被打断的。通常,完全抢占式的方式一般用于实时OS。

(6). 多处理器的支持

支持对称式多处理器(SMP)。

(7). 文件系统

linux支持多种形式的文件系统。普通目的的文件系统式Ext2,Ext3文件系统的好处是在文件系统崩溃后不需要做冗长的文件系统检查。ReiserFS文件系统对于处理小文件很方便。

(8). STREAMS

STREAMS I/O子系统是编写设备驱动程序,终端驱动程序和网络协议的首选接口。

1.2 linux操作系统的一些基本概念

操作系统的两大任务:

linux和MS-DOS不同的是,它对用户程序隐藏了所有的底层硬件相关细节。用户不能直接控制硬件,而必须想操作系统通过系统调用来申请,操作系统评估用户的要求是否合理,然后决定是否代表用户来进行硬件操作。为了实现这种目的,操作系统需要硬件的支持。linux通过硬件机制引进了两种模式:无特权的用户模式,有特权的内核模式。

1.2.1 多用户系统

多用户系统能并行地独立地执行多个用户的应用程序。“并行”——同一时刻有多个进程在活动并相互竞争系统的资源。“独立”——进程间能互不干扰地执行。为了支持多用户,系统应该提供:

为了确保各种保护机制的实现,操作系统需要在特权模式下利用硬件来实施。

1.2.2 用户和组

操作系统为每个用户分配适当的资源和权限。用户之间不能相互干扰和破坏。每个用户用一个唯一的数字来标识,称作UID。

为了方便地使多个用户能共享某种资料,每个用户是一个或多个组的成员。每个组用一个的一个数字来标识,称作GID。

每个系统都有个超级用户root,通常为系统的管理员。他有做所以事情的权力。

1.2.3 进程

进程是一种抽象,它是程序的一个活动的实例。现代OS中的进程可以拥有不止一个执行流。系统有多个进程,一个进程伴随多个线程。进程的地址空间指的是进程中所有可访问地址的集合。允许同时多个进程执行的系统叫做“多道程序”或“多线程”系统。进程和程序是有差别的,一个程序可以同时有多个进程,一个进程可以顺序执行几个程序。

“多用户系统”和“多进程系统”是有区别的:多进程系统可以是单用户系统,但多用户系统一定是多进程的。

由于CPU的有限,多进程的系统就需要的进程进行“调度”,通过操作系统提供的“调度器”来完成。调度器负责监视每个进程在CPU中执行的时间,周期性的将CPU在进程之间切换。某些系统的进程调度是“非抢占式”的,即当一个正在执行的进程主动放弃CPU后,调度器才将CPU切换到另一个进程。但,多用户的系统一定是“抢占式”的。

UNIX是“抢占式”的、多用户、多进程的系统。即便没有用户登陆到系统,操作系统仍然有多道进程在并行地运行,来监视硬件和终端。

类UNIX的系统(如linux)也采用进程/内核模式。进程独立地运行。当一个进程系统调用时,硬件就会把特权模式从用户态切换道内核态,然后进程就进入内核态进行受限地执行。当系统调用结束后,操作系统强迫硬件将特权模式返回到用户态,并继续执行系统调用以后的指令。

1.2.4 内核体系结构

UNIX内核是单块的,所以内核层集成到一个完整的程序中,在内核模式下代表用户进程运行。

相比之下,还有一种内核体系结构叫做“微内核”架构。这种内核有比较少的一些函数组成,提供同步原语,调度器,进程间通信的机制。在这之上,运行着一些系统进程,实现进程调度,内存管理,外设管理和系统调用。“微内核”内核结构通常比单块机构的内核慢,这是由于操作系统不同层之间消息传递的花费。但“微内核”结构理论上也有很多有点:(1)使系统程序员采用模块化的方法,因为操作系统的每层都是一个独立的模块,它通过定义良好的结构和其他层进行交互。(2)微内核结构操作系统易于移植,因为所有硬件无关的组件都被封装在微微内核代码里。(3)内存使用率较高,因为暂时不用的系统进程可以被swap out或者撤销。

linux借用单块结构和微内核结构的优点,采用了“模块”。“模块”是一个个目标文件unix内核,它能被动态地连接到内核里,或从内核中卸载下来。这种目标文件通常包含操作文件系统,设备驱动的函数。模块不像微内核结构中的外部层,linux内核中的模块不是进程,他们在内核态下代表用户进程运行,就像其他静态连接的内核函数一样。

linux内核采用“模块”结构的优点:

1.3 UNIX文件系统概览

文件是记录在辅助存储设备上的一串信息的命名集合。linux内核不直接解释文件的格式。文件组织在目录树中,树的每个非叶节点都是一个目录,直接记录着其子目录和子文件的信息。进程的运行设计到“当前目录”的概念,它是程序运行环境。根据是否基于“当前目录”,指定一个文件可以用相对路径或绝对路径。

1.3.1 硬连接和软连接

unix目录下的文件名是文件的“硬连接”或“连接”。同一个文件可以有多个硬连接,即多个文件名,分布在相同的目录或不同的目录下。命令:

ln f1 f2

创建文件f1的一个硬连接f2,两者可以包含路径。

硬连接的两个限制:

为了克服硬连接的限制,unix引入了“软连接”或“符号连接”。软连接是一个短文件,其中包含所要连接的文件的文件路径。该路径可以分布在不同的文件系统中。命令:

ln -s f1 f2

创建了文件f1的一个软连接f2。该命令的效果是系统在路径f2地方建立了一个文件,以f2为该文件的文件名(硬连接),该文件中包含了f1的路径。所有每次引用f2时,系统会自动引索到f1。

1.3.2 文件类型

UNIX文件类型有:

普通文件,目录和软连接是UNIX文件系统的基本类型。设备文件是一个和I/O设备即设备驱动相关联的特殊文件,其效果是当访问设备文件时相当于访问相应的I/O设备。管道和套接字用于进程间通信。

1.3.3 文件描述符和引索节点(inode)

UNIX严格区分文件的内容和文件的相关信息。除设备文件和特殊文件外,所有文件内容本身不包含控制信息(如文件长度和文件定界符EOF),文件内容只是一串字符。

文件在文件系统中的信息被记录在一个叫inode的结构中,任何文件都要它自己的inode。类UNIX系统的文件系统和内核对文件的操作遵循POSIX规范,文件信息中必须包含以下项:

1.3.4 文件访问权限和文件模式

UNIX中访问文件的用户可以分为三类:文件所有者、和该文件同组的用户、其他人。

对访问类型可分为三种:读、写、执行(目录为搜索)。

访问权限的设置用二进制位来标识三类不同用户是否可使用三种不同访问类型,共需9个二进制位。

文件模式由另三个位:suid、sgid、sticky来标识。

当进程创建一个文件时,该文件的UID就是该进程的UID;该文件的GID是该进程的GID(如果可执行文件sgid置1)或是该文件父目录的GID(如果可执行文件sgid清0)。

1.3.5 文件处理的系统调用

由于文件系统实质上是真实物理设备在用户级的一个抽象,所以对文件的操作就是对真实物理设备的操作。而UNIX是不允许用户进程直接操作底层物理设备的,这种操作必须在内核模式下进行,故用户对文件的操作需要借助操作系统提供的系统调用在完成。

1.3.5.1 打开文件

进程只能访问打开的文件,故文件操作的第一步是打开文件。打开文件的系统调用是:

fd = open(path, flag, mode);

该系统调用在系统内部创建了一个“文件对象”并返回一个文件表述符给fid。“文件对象”的内容是:

创建新文件除了使用open( )系统调用,还可以使用creat( )系统调用。

POSIX关于文件打开方面的叙述有:

1.3.5.2 访问打开的文件

普通文件的访问可以有顺序的和随即的两种方式。对于设备文件和管道文件,一般都是顺序访问。文件的访问需要借助文件指针——指示当前操作在文件中的位置,并供下此文件操作定位。

系统调用read( )和write( )用于对文件的顺序访问。一个刚打开的文件,其文件指针总是指向文件的第一个字节(offset 0)。lseek( )用于定位文件指针,以供随机访问。lseek( )的使用方法:

newoffset = lseek(fd, offset, base);

读操作系统调用read( ):

nread = read(fd, buf, count);

写操作的系统调用write( ),参数同read( ):

nwrite = write(fd, buf, count);

读写操作会动态地修改当前文件指针。

1.3.5.3 关闭文件

当文件不再使用时,进程可以“关闭”文件,以释放该文件再系统内的“文件对象”:

res = close(fd); //"res" = "result",指示操作是否成功

当进程结束时,系统自动关闭该进程中所有未关闭的文件。

1.3.5.4 重命名和删除文件

重命名和删除文件前不需要打开该文件。因为实际上,这样的操作不会作用在真实的文件数据上,它们只是对文件所在目录中的目录项进行操作。

重命名文件系统调用:

res = rename(oldpath, newpath); 实际改变了文件原硬连接的名称

删除文件系统调用:

res = unlink(path); 实际是将该文件的硬连接数减1,并在删除了该文件在父目录中的目录项。

当一个文件的硬连接数减到0时,该文件才被真正的删除。

1.4 UNIX内核概览

UNIX内核为应用程序的运行提供良好的环境,包括服务和接口。应用程序使用内核提供的接口访问底层硬件设备。

1.4.1 进程/内核模型

所有标准的UNIX系统都只有两种CPU模式:用户模式和内核模式。进程通常运行在用户模式,当进程运行在用户模式时,它不能直接访问内核模式所提供的一些数据结构和功能函数。进程必须通过系统调用切换到内核模式后才能使用这些数据和函数。当进程在内核态下完成了系统调用和,又回到用户模式继续往下执行。为了在两种模式之间进行相互切换,系统为每种模式提供了相应的特殊指令。

进程都是活动的。进程的创建、销毁、进程间同步由内核中的相关程序实现。内核本身不是进程。用户进程通过发起系统调用从而进入内核模式,利用内核相关程序完成底层功能。进程系统调用时需同时附加相关参数,以通知内核如何实现这些功能。

除了普通的用户进程外,UNIX系统还由一些特权进程,叫做内核线程。内核线程有如下特点:

那么,内核做些什么事情呢?也就是说,什么情况下系统会切换到内核态?如下:

1.4.2 进程的实现

为了能让内核管理进程,每个进程都用一个“进程描述符”来描述,进程描述符包含了进程的当前执行信息。

当内核进程进程切换时,首先当前进程的相关寄存器的值被保存在进程描述符中,包括:

当一个进程不在CPU上执行时,它就在等待某种事件的发生。UNIX通常将这些处于等待的进程通过进程描述符维护在队列中。等待不同的事件的进程放在不同的队列中。

1.4.3 可重入的内核

所有UNIX的内核都是可重入的,即在内核模式下也是多进程的。当某个进程在内核模式下等待某个事件时,内核会阻塞它并处理另一个进程的内核事务和其他内核线程。当前面的进程等待结束后,又重新进程内核。内核的可重入性还表现在当CPU接收到中断时,内核会马上停下手中的进程即使该进程处于内核态,来处理中断。这种机制提高了硬件设备的吞度量。

“内核控制路径”定义了当内核处理系统调用、中断、异常等请求时所执行的指令序列。通常的内核控制路径是顺下地从头到尾,但当出现以下事件是,内核控制路径将出现交叉:

1.4.4 进程地址空间

每个进程在它私有的地址空间内运行。用户模式下的进程使用属于该进程的私有的代码、数据、堆栈区(共享除外)。当进程运行在内核模式时,进程使用内核的代码和数据区,不过进程需使用另外的堆栈。因为内核是可重入的,当内核为几个进程运行这几条内核控制路径是,就分别使用属于每个进程的堆栈。

进程之间可以共享代码和数据,有时这种共享是由进程自己指定的,有时是由内核决策的。利用进程间共享内存的方法可以进程间通信。

linux支持用系统调用mmap( )将磁盘上的文件或是其他设备上的存储空间映射到进程的地址空间来。

1.4.5 同步和临界区

内核可重入的实现需要同步机制的支持。当一个内核控制路径在修改了一半某个内核数据结构时被挂起,就不应当允许另一个内核控制路径来修改这个数据结构,否则系统数据就会被破坏。内核全局数据的同步可以利用“原子操作”,即某一修改内核数据的操作是不可被打断的。但是,对于比较大的数据结构的修改,无法用单一的操作来完成,这时可以利用“临界区”的方法。“临界区”是这样一段代码:某个进程从区首执行,只要没有执行到区尾,都不会允许另一个进程来运行这段代码。

同步的问题不仅发生在内核路径问题上,还存在于进程共享问题上。

1.4.5.1 非抢占内核

大多数传统的UNIX内核都是非抢占式的。即一个处于内核态的进程不能任意地被另一个进程挂起和替换。不过,进程可以出动放弃CPU,只要它保持相关数据结构的一致性。

1.4.5.2 中断的禁止

单CPU系统的另一个同步方法是利用中断禁止:当进程运行在临界区时,一切中断将被禁止。等进程运行到临界区之后时,中断才被开放。这种方法虽然简单,单效率却低,特别是当临界区很大的时候,硬件设备的利用率会降低。

1.4.5.3 信号量

信号量机制被广泛地用于单CPU和多CPU的同步问题。信号量就是和某个要保护的数据结构相关联的计数器。内核线程访问这个数据结构之前,首先要检查该计数器。 信号量可以看成是一种对象,包含:

其中down( )将整数值减1,如果结果小于0,则将访问该数据结构的进程挂起到进程链表中,然后阻塞该进程。up( )将整数值加1,如果结构大于等于0,则激活进程链表中的一个或多个进程,让它们继续执行。

信号量的机制如下:每个想要被保护的数据结构都有其自己的信号量对象,并且信号量的整数值初始化为1。当某个进程访问某数据结构时,它先运行该数据结构信号量的down( )操作。如果进程没有被挂起,并完成了对该数据结构的访问,则在离开时要运行一下其信号量的up( )操作。这样就可以保证数据修改的同步。

1.4.5.4 自旋锁

自旋锁通常用于多CPU的同步问题

1.4.5.6 死锁避免

当多个进程或内核控制路径占用了某些资源同时还想获得对方的资源时,便形成了无限期的循环等待,即发生了死锁。当系统的信号量过多的时候,很难保证不发生死锁。故一些系统,如Linux通过限制信号量的数目来尽量避免死锁。

1.4.6 信号和进程间通信

UNIX信号通知进程某些内核事件。每个内核事件都有其对于的信号数,通常用符合常量表示,如SIGTERM。内核事件有两种:

POSIX定义了大约20种信号。其中两种是用户可定义的,用户可以利用他们进行进程间同步和通信机制。当一个进程接收到一个信号时,进程可采取两种措施:

如果进程没有选择这两种方式的任何一种,内核会根据信号类型采取一个默认的操作,可能有:

AT&T的UNIX V还引入了其他几种进程间通信的机制:信号量,消息队列,共享内存。它们统称为system V IPC。内核将这些进程通信结构通通视为资源,请求这些资源的系统调用有:semget( ),msgget( ),shmget( )。像文件资源一样,IPC资源用完后需要显示地释放。

信号量用于用户模式的进程。消息队列允许进程从队列中取消息(msgget( ))和把消息插入队列(msgsnd( ))。共享内存的一些系统调用有:shmget( ),shmat( ), shmdt( )。

1.4.7 进程管理

有关系统调用:

fork( )复制父进程地址空间到子进程。新的进程产生机制是copy-on-write,即最初子进程和父进程共享一个地址空间。只有在子进程要修改自己的某部分地址空间的时候,再将父进程的那部分拷贝一份给子进程。否则两者将仍然共享一个地址空间。这样可减少地址空间复制的开销。exit( )系统调用结束一个进程,回收该进程的资源,并将一个SIGCHLD信号送给该进程的父进程。

1.4.7.1 僵死进程

父进程通过系统调用wait( )(更高级的有waitpid( ))来获知其某个子进程的结束。当父进程执行wait( )时,若其子进程还在执行,则父进程将自己置入睡眠状态,只要有一个子进程结束就会唤醒父进程。若子进程没有结束,父进程就结束了,那么当子进程结束后,子进程都变成了“僵死进程”。因为内核对结束进程的资源回收机制是通过wait( )进行的,这时子进程的父进程没有执行wait( )就结束了,故不能让父进程处理子进程的身后事,内核就让一个叫init的进程接管这些子进程,而Init进程是个系统启动时就存在的进程,它含有wait( )。通过这种机制,内核可以妥善处理僵死进程的身后事。

1.4.8 内存管理

1.4.8.1 虚拟内存

虚拟内存是一种逻辑概念,它是处于应用程序内存请求和MMU之间的一个逻辑层。虚拟内存的目的和好处:

1.4.8.2 RAM的使用

RAM的使用分为两大块,一块存放内核代码和数据结构,一块由虚拟内存系统使用,主要用来:

1.4.8.3 内核内存分配器

内核内存分配器(KMA)是内核中用于分配内存的子系统,或者为内核其他子系统,或者为通过系统调用请求的用户进程。一个好的KMA应具有一下特点:

内存分配有很多算法,Linux使用的是buddy系统上的slab算法。

1.4.8.4 进程虚拟地址空间处理

进程虚拟地址空间包含了进程可以引用的所有虚拟内存地址。内核用一组内存区描述符来描述进程虚拟地址空间。当进程通过exec( )系统调用开始某个程序的执行时,内核分配给进程的虚拟地址空间有以下内存区组成:

现代操作系统使用了“请求调页”机制(demand paging)。有了请求调用机制,进程可以在它的页还没有进入内存的时候就开始执行。

1.4.9 设备驱动程序

内核通过设备驱动程序与I/O设备交互,设备驱动程序包含在内核中,由控制一个和多个设备的函数和数据结构组成。设备驱动通过特定的接口与内核的其余部分交互,这种方式有如下特点:

(编辑:天瑞地安资讯网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章