首页 > 编程知识 正文

linux内核设计与实现豆瓣,linux内核设计与实现第四版

时间:2023-05-03 10:34:33 阅读:253210 作者:4471

linux内核简介

Linux系统的基础是内核,C库(库函数里会有些系统调用),工具集和系统的基本工具。

通常一个内核由负责响应中断的中断服务程序,负责管理多个进程从而分享处理器时间的调度程序,负责管理进程地址空间的内存管理程序,和网络、进程间通信等系统服务程序共同组成。

当硬件设备想要跟系统通信的时候,首先要发出一个异步的中断信号去打断处理器的执行,继而打断内核的执行。

为了保证中断服务程序能够在第一时间响应和处理中断请求,然后快速退出,中断服务程序不在进程上下文中执行。

处理器在任何指定时间的活动必然为下列三者之一:

Unix内核几乎毫无例外都是一个不可分割的静态可执行库,它们必须以巨大,单独的可执行块的形式在一个单独的地址空间中运行。Unix内核通常需要硬件系统提供页机制(MMU)以管理内存。

单内核
整个内核都在一个大内核地址空间上运行。

优点:
1.简单。
2.高效:所有内核都在一个大的地址空间上,所以内核各个功能之间的调用和调用函数类似,几乎没有性能开销。

缺点:
一个功能的崩溃会导致整个内核无法使用。

微内核
内核按功能被划分成各个独立的过程。每个过程独立的运行在自己的地址空间上。

优点:
安全:内核的各种服务独立运行,一种服务挂了不会影响其他服务。
可换出:允许一个服务器为了另一个服务器而换出。

缺点:
内核各个服务之间的调用涉及进程间的通信,比较复杂且效率低。

Linux内核
Linux是一个单内核,不过,Linux汲取了微内核的精华:模块化设计、抢占式内核、支持内核线程以及动态装载内核模块的能力。(体现了Linux实用至上的原则)

Linux与传统Unix系统之间的显著差异:

1.支持动态加载内核模块;
2.支持对称多处理(SMP)机制;
3.内核可以抢占(preemptive),允许内核运行的任务有优先执行的能力;
4.内核不区分线程和其他的一般进程。对于内核来说,所有的进程都一样——只不过是其中的一些共享资源而已。

进程管理

每个线程都拥有一个独立的程序计数器,进程栈和一组进程寄存器。

进程提供两种虚拟机制:虚拟处理器和虚拟内存。(在线程之间可以共享虚拟内存,但每个都拥有各自的虚拟处理器)

调用fork之后调用exec就可以创建新的地址空间,并把新的程序载入其中。

进程退出执行后被设置为僵死状态,直到他的父进程调用wait函数。

内核把进程的列表存放在叫做任务队列的双向循环链表中,每一项都是称为进程描述符的结构。

Linux通过slab分配器分配task_struct结构,这样能达到对象复用和缓存着色(参见12章)的目的(通过预先分配和复用,可避免动态分配和释放所带来的损耗)。

通过预先分配和重复使用task_struct,可以避免动态分配和释放带来的资源消耗。

内核通过一个唯一的进程标识值或PID来标识每个进程,PID是一个数,表示为pid_t隐含类型(实际上就是一个int类型)。

内核把每个进程的PID存放在它们各自的进程描述符中。

在中断上下文中,系统不代表进程进行,而是执行一个中断处理程序,不会有进程去干扰这些中断处理程序,所以此时不存在进程上下文。

fork()使用的是写时复制,fork的实际开销就是复制父进程的页表以及给子进程创建唯一的进程描述符

在Linux中,对内核来说,并没有线程这个概念,它把所有的线程当做进程来实现,线程仅仅被视为一个与其他进程共享某些资源的进程。

内核经常需要在后台执行一些操作。内核线程与普通进程的区别在于内核线程没有独立的地址空间(实际上指向地址空间的mm指针被设置为NULL)。它们只运行在内核空间,从来不切换到用户空间。内核进程和普通进程一样,可以被调度和抢占。

进程终结之后,该进程关联的资源被释放掉了,但是它本身占用的内存还没有释放,比如创建时分配的内核栈,thread_info结构和task_struct结构等。此时进程存在的唯一目的是向它的父进程提供信息。父进程检索到信息后,或者通知内核那是无关的信息后,该进程所持有的剩余内存被释放,归还给系统使用。

父进程通过调用wait()一族的函数来检测子进程是否存在。它的标准动作是挂起调用它的进程,直到其中一个子进程退出,此时函数会返回子进程的PID。此外,调用该函数时提供的指针会包含子函数退出时的退出代码。至此,进程描述符和所有进程独享的资源就全部释放掉了。

孤儿进程:

进程调度

进程调度程序是确保进程能有效工作的一个内核子系统。

多任务系统可以划分为两类:非抢占式多任务和抢占式多任务。

Linux更倾向于优先调度IO消耗型进程,调度程序也并未忽略处理器消耗型的进程。

Linux采用了两种不同的优先级范围(nice优先级和实时优先级)

Linux的CFS调度器(完全公平调度)则并没有直接分配时间片到进程,而是将处理器的使用比划分给进程,这样进程获得的处理器时间与系统负载密切相关。这个比例还受nice值影响,nice作为权重将调整进程使用处理器的时间比。

Linux的CFS调度器,抢占时机取决于新的可运行程序消耗了多少处理器使用比,如果消耗的使用比比当前进程小,则新进程立刻投入运行,抢占当前进程,否则推迟运行。(比如当前有个文本编辑器和个视频解码程序在运行,他们的优先级相等,则分别有50%的处理器时间,实际上文本编辑器用不到50%,但是当文本编辑器有有新的输入时检测到他运行的时间少于50%,就会立即完成抢占)

Linux的调度算法(看课本4.4节)

CFS使用调度器实体结构(struct_sched_entity)来追踪进程运行记账。这个结构是进程描述符的一个成员变量。

抢占和上下文切换:把虚拟内存从上一个进程映射切换到新进程。保留上一个进程的寄存器信息等。

内核同步介绍和方法

所谓临界区就是访问和操作共享数据的代码段。编程者必须保证这些代码原子执行。避免并发和防止竞争条件称为同步。

简单的同步可以通过原子操作解决,复杂的需要加锁。

自旋锁:浪费处理器时间,所以不应该被长时间持有。用于在短时间内进行轻量级加锁。

读写自旋锁:
信号量(计数信号量和二值信号量):一种睡眠锁
读写信号量:
互斥体(mutex):比信号量相比,是更简单的睡眠锁(比信号量简洁,高效)

虚拟文件系统

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。