注:本分类下文章大多整理自《深入分析linux内核源代码》一书,另有参考其他一些资料如《linux内核完全剖析》、《linux c 编程一站式学习》等,只是为了更好地理清系统编程和网络编程中的一些概念性问题,并没有深入地阅读分析源码,我也是草草翻过这本书,请有兴趣的朋友自己参考相关资料。此书出版较早,分析的版本为2.4.16,故出现的一些概念可能跟最新版本内核不同。
中断控制是计算机发展中一种重要的技术,最初它是为克服对 I/O 接口控制采用程序查询所带来的处理器低效率而产生的。
该文介绍了中断和异常的基本概念、分类,以及Linux 中中断和异常的处理方式,包括硬件中断、软件中断和异常的分类和处理。
中断描述符表是保护模式下用于存储中断处理程序的数据结构。CPU在接收到中断时,会根据中断向量在中断描述符表中检索对应的描述符。
80386的各种寄存器一览:通用寄存器(32位)、段寄存器(16位)、标志寄存器(32位)、系统地址寄存器、调试寄存器和测试寄存器(32位)。
本文涉及的硬件平台是X86,如果是其他平台的话,如ARM,是会使用到MMU,但是没有使用到分段机制; 最近在学习Linux内核,读到《深入理解Linux内核》的内存寻址一章。原本以为自己对分段分页机制已经理解了,结果发现其实是一知半解。于是,查找了很多资料,最终理顺了内存寻址的知识。现在把我的理解记录下来,希望对内核学习者有一定帮助,也希望大家指出错误之处。
PS:原先实模式下的各个段寄存器作为保护模式下的段选择器,80486中有6个(即CS,SS,DS,ES,FS,GS)80位的段寄存器。由选择器CS对应表示的段仍为代码段,选择器SS对应表示的段仍为堆栈段。
前段时间,我连续写了十来篇CPU底层系列技术故事文章,有不少读者私信我让我写一下CPU的寄存器。
中断,英文名为Interrupt,计算机的世界里处处都有中断,任何工作都离不开中断,可以说整个计算机系统就是由中断来驱动的。那么什么是中断?简单来说就是CPU停下当前的工作任务,去处理其他事情,处理完后回来继续执行刚才的任务,这一过程便是中断。
至此,我们已经理解了X86架构如何在硬件层面如何处理中断和异常,那么接下来,我们看看Linux内核管理这些中断和异常。
在前面文章图解中断 | 中断从产生到消失的一生中提到了中断的整个生命周期,其中有一个关键的环节是CPU在接收到中断向量号后是如何找到对应的中断服务程序的,今天我们就来一探究竟。
虽然计算机相关专业,操作系统和计算机组成原理是必修课。但是大学时和真正从事相关专业工作之后,对于知识的认知自然会发生变化。还很有可能,一辈子呆在学校的老师们只是照本宣科,自己的理解也不深。所以今天我站在真正排查解决问题时的需要层面,用白话说一说linux操作系统的那些知识。
中断描述符表简单来说说是定义了发生中断/异常时,CPU按这张表中定义的行为来处理对应的中断/异常。
之前所说 GDT表 中存储了一些段描述符. 比如有调用门 段描述符. 代码段段描述符. 数据段段描述符 TSS段段描述符
按照中断的来源分类,来自CPU外部的中断称为外部中断,来自CPU内部的称为内部中断;细分的话,外部中断根据严重程度,分为可屏蔽中断和不可屏蔽中断;内部中断按照是否正常分为软中断和异常。
与硬件相关的代码全部放在 arch(architecture 一词的缩写,即体系结构相关)目录下。
此前我们对操作系统中的分段、分页机制以及虚拟地址、逻辑地址、线性地址、物理地址进行了较为详细的介绍。 操作系统的内存管理 — 分段与分页、虚拟地址、逻辑地址、线性地址、物理地址
CS部分后面又4个0,相当于是左移了4位。总之就是要让CS左移4位之后加上EIP来得到要跳转的地址。
最近看到这个github仓库flash-linux0.11-talk,觉得还算是蛮有意思的,加上网络编程的课程又有抄写一段tcp协议实现代码或者交一篇linux内核源码阅读的笔记,还是比较讨厌这种低效率的抄写的所以就想写篇文章记录一下粗浅阅读源码后的大概了解,这个github仓库作者的文章我觉得写的还是不错的对于我这类小白而言,也比较有看得下去的动力。
准备工作:下载ucorelab在的master分支(注意不是main分支),需要用到的资料以及答案都在里面。
硬件逻辑设计为加电瞬间强行设置:CS=0xF000,IP=0xFFF0,CS:IP=0xFFFF0
在上一篇文章中,我们已经了解了中断和异常的一些概念,对于中断和异常也有了大概的理解。那么,系统中硬件到底是如何处理中断和异常的呢?本文我们就以常见的X86架构为例,看看中断和异常的硬件工作原理。
不知道大家有没有产生过一个疑问:从给 Linux 服务器按下开机电源按钮后到启动成功的一段时间里,在这中间 Linux 操作系统都做了哪些事情?
(1)中断有两种,一种是由CPU外部硬件产生的,另一种是由CPU本身执行程序的过程中产生的;外部中断即我们所说的中断(interrupt),外部中断是异步的,由硬件产生,我们无法预测它什么时候发生; (2)x86软件产生的中断是由“INT n”同步产生的,由程序产生,只要CPU执行了一条INT指令,就知道在开始执行下一条指令前就会进入中断服务程序,我们又称此类中断为“陷阱”;int 80为系统调用的陷阱号; (3)异常,是被动的,如页面异常,除数为0的异常; 因此系统调用是中断中的陷阱的一种,系统调用只发生在用户空间,必然会发生用户栈和内核栈的切换。
没有虚拟化基础的童鞋可先阅读Linux阅码场前几天刊发的《KVM最初的2小时——KVM从入门到放弃(修订版) 》入门。
下面从逻辑上完整走一遍中断处理过程(结合中断上下文的切换,以定时器中断为例,假设从用户态进入中断):
内存管理无疑是操作系统最重要的工作之一,本文我们就来详细介绍一下操作系统是如何管理内存的,分段、分页机制又是什么,线性地址、逻辑地址、物理地址、虚拟地址分别指的又是什么。
经过一系列的文章,我们通过汇编语言,体验了保护模式下分段、分页、特权级跳转、中断、异常等机制。 那么,事到如今,你是否已经深谙保护模式的设计之道了呢?究竟什么是保护模式,保护模式又在“保护”什么呢?他为了什么诞生,又和实模式有什么区别呢? 本文我们就来详细总结一下。
本系列是对 陈莉君 老师 Linux 内核分析与应用[1] 的学习与记录。讲的非常之好,推荐观看
bootloader主要做四件事,1.开启A20地址线;2.探测内存,把内存相关信息告诉内核;3.初始化全局描述符表,开启分段机制,进入保护模式;4.把操作系统内核从磁盘加载到内存指定位置,跳转到内核,执行内核代码。
不论是在 x86 平台上,还是在嵌入式平台上,系统的启动一般都经历了 bootloader 到 操作系统,再到应用程序,这样的三级跳过程。
中断其实就是在CPU正在做某件事的时候,收到了通知告诉CPU你要放下手头现在做的事,去处理另一件事(当然这个是立即处理还是过一会处理以及如何处理取决于中断的类型)。
上一次我们说到了文件的常规操作,打开,读,写,关闭这些,重点在于打开是以什么样的方式来打开,包括文件的权限,内容是否清空,打开不存在的文件等等情形。今天继续说一下文件IO操作。
Intel 微处理器的段机制是从8086 开始提出的, 那时引入的段机制解决了从CPU 内部 16 位地址到20 位实地址的转换。为了保持这种兼容性,386 仍然使用段机制,但比以前复杂。 因此,Linux 内核的设计并没有全部采用Intel 所提供的段方案,仅仅有限度地使用 了一下分段机制。这不仅简化了Linux 内核的设计,而且为把Linux 移植到其他平台创造了 条件,因为很多RISC 处理器并不支持段机制。但是,对段机制相关知识的了解是进入Linux 内核的必经之路。
Workqueue 工作队列是利用内核线程来异步执行工作任务的通用机制,利用进程上下文来执行中断处理中耗时的任务,因此它允许睡眠。而 Softirq 和 Tasklet 在处理任务时不能睡眠。Softirq 是内核中常见的一种下半部机制,适合系统对性能和实时响应要求很高的场合,比如网络子系统,块设备,高精度定时器,RCU 等。
在 32 位的 linux/unix 系统下,每个程序打开一个文件都会有一段 4G 的虚拟地址空间,这部分空间中,有1G是内核地址空间,3G是用户地址空间,这个概念我们在之前的文章中有介绍过,可参考 “不同位置的变量在内存中的排布”,其中在内核地址空间中,维护着一个 PCB 进程控制块,其中包含很多进程相关的信息,比如进程ID、用户ID、组ID等等,但本文我们最关注的,是 PCB 进程控制块中维护的一份“文件描述符表”,表的格式抽象成下图的样子。
本文需要接着系统调用,也是接着 $xv6$ 文件系统的最后一层,讲述各种具体的文件系统调用是怎么实现的,文件描述符,$inode$,文件之间到底有什么关系,创建打开关闭删除文件到底是何意义,文件删除之后数据就不存在了吗,链接又作何解释等等问题,看完本文相信你能找到答案。
写Java的朋友一定对上面的命令很熟悉,相信大部分人都知道>表示的是重定向,那么什么是重定向?2>&1又是什么意思?
上一节,我们开发了一个流氓程序,当他运行起来后,能够把自己的数据写入到另一个进程的数据内存中。之所以产生这样的漏洞,是因为被入侵进程的数据段所对应的全局描述符在全局描述符表中。恶意程序通过在全局描述符表中查找,当找到目标程序的内存描述符后,将对应的描述符加载到自己的ds寄存器里,于是恶意程序访问内存时,就相当于读写目标程序的内存。 要防范此类入侵,最好的办法是让恶意程序无法读取自己内存段对应的描述符,但是如果不把自己的内存描述符放置在全局描述符表中的话,还能放哪里呢?Intel X86架构还给我们提供了另一
在前文中学习了open函数,我们知道open函数的返回值就是文件描述符,本章将对文件描述符进行详细讲解。
在Linux系统中一切皆可以看成是文件,文件又可分为:普通文件、目录文件、链接文件和设备文件。 文件描述符(file descriptor)是内核为了高效管理已被打开的文件所创建的索引,其是一个非负整数(通常是小整数),用于指代被打开的文件,所有执行I/O操作的系统调用都通过文件描述符。 程序刚刚启动的时候,0是标准输入,1是标准输出,2是标准错误。如果此时去打开一个新的文件,它的文件描述符会是3。POSIX标准要求每次打开文件时(含socket)必须使用当前进程中最小可用的文件描述符号码,因此,在网络通信过程中稍不注意就有可能造成串话。标准文件描述符图如下:
x86 系统中的保护模式,给系统的安全性提供了很大的保障,但是在我们之前的文章中,一直都淡化了特权级别这个概念。
如前面所述,当某个设备被连接到 USB 主机上,该设备会向主机提供其功能和电源要求。通常,设备会通过一个描述符表格(其固件的一部分)来提供这些信息。描述符表格是数据的结构化序列,描述了设备信息;这些值由开发人员定义。所有描述符表格都具有一个标准信息,用于介绍设备属性和电源要求。如果某个设计满足指定 USB 设备类别的要求,则该 USB 设备必须具备的其他描述符信息都将包含在设备描述符结构中。附录 A 包含一个 PSoC USB 的全功能设备描述符的示例。如果您正在阅读或创建您自己的描述符,那么请注意,传输数据字段时,优先传输最低有效位。许多参数的长度均为 2个字节。请确保先发送低字节,然后再发送高字节。
1. 网络中进程之间如何通信 进程通信的概念最初来源于单机系统。由于每个进程都在自己的地址范围内运行,为保证两个相互通信的进程之间既互不干扰又协调一致工作,操作系统为进程通信提供了相应设施,如UNIX BSD有:管道(pipe)、命名管道(named pipe)软中断信号(signal) UNIX system V有:消息(message)、共享存储区(shared memory)和信号量(semaphore)等. 他们都仅限于用在本机进程之间通信。网间进程通信要解决的是不同主机进程间的相互通信问题(可把
3.系统级别。当打开文件并设置了O_APPEND标识,内核会共享文件写入游标,保证内容不会被覆盖。
fd 是(file descriptor)即文件描述符,这种一般是BSD Socket的用法,用在Unix/Linux系统上。fd全称是file descriptor,是进程独有的文件描述符表的索引。
大家好,我是架构君,一个会写代码吟诗的架构师。今天说一说XV6操作系统代码阅读心得(一):启动加载、中断与系统调用,希望能够帮助大家进步!!!
既然叫中断, 那我们首先就会想到这个中断是中断谁?想一想计算机最核心的部分是什么?没错, CPU, 计算机上绝大部分的计算都在CPU中完成,因此这个中断也就是中断CPU当前的运行,让CPU转而先处理这个引起中断的事件,通常来说这个中断的事件比较紧急,处理完毕后再继续执行之前被中断的task。比如,我们敲击键盘,CPU就必须立即响应这个操作,不然我们打字就全变成了慢动作~。说白了中断其实就是一种主动通知机制,如果中断源不主动通知,那想知道其发生了什么事情,只能一次次地轮询了,白白耗费CPU。
领取专属 10元无门槛券
手把手带您无忧上云