linux内核学习-4kernal目录(关注新浪微博:寂寞侵蚀的岁月(4000多篇技术分享))

该目录下的代码文件从功能上可以分为三类,一类是硬件(异常)中断处理程序文件,一类是系统

调用服务处理程序文件,另一类是进程调度等通用功能文件。参见图1.5。我们现在根据这个分类方式,

从实现的功能上进行更详细的说明。

5.1.1.1 硬件中断处理类程序

主要包括两个代码文件:asm.s 和traps.c 文件。asm.s 用于实现大部分硬件异常所引起的中断的汇

编语言处理过程。而traps.c 程序则实现了asm.s 的中断处理过程中调用的c 函数。另外几个硬件中断

处理程序在文件system_call.s 和mm/page.s 中实现。

更多电子书教程下载请登陆http://down.zzbaike.com/ebook

本站提供的电子书教程均为网上搜集,如果该教程涉及或侵害到您的版权请联系我们。

第5 章 内核代码 linux/kernel/

72

中断信号通常可以分为两类:硬件中断和软件中断(异常)。每个中断是由0-255 之间的一个数字来

标识。对于中断int0--int31(0x00--0x1f),每个中断的功能是由Intel 固定设定或保留用的, 属于软

件中断,但Intel 称之为异常。因为是由CPU 执行指令时探测到异常时引起的。通常还可分为故障(Fault)

和陷阱(traps)两类。中断int32--int255 (0x20--0xff)可以由用户自己设定。在Linux 系统中,则将

int32--int47(0x20--0x2f)对应于8259A 中断控制芯片发出的硬件中断请求信号IRQ0-IRQ15;并把程序

编程发出的系统调用(system_call)中断设置为int128(0x80)。

asm.s 代码文件主要涉及对Intel 保留中断int0--int16 的处理,其余保留的中断int17-int31 由

Intel 公司留作今后扩充使用。对应于中断控制器芯片各IRQ 发出的int32-int47 的16 个处理程序将分

别在各种硬件(如时钟、键盘、软盘、数学协处理器、硬盘等)初始化程序中处理。Linux 系统调用中

断int128(0x80)的处理则将在kernel/system_call.s 中给出。各个中断的具体定义见代码注释后其它

信息一节中的说明。

对一个硬件异常所引起的中断的处理过程见下度所示(图5.1)。

图5.1 硬件异常(故障、陷阱)所引起的中断处理流程

由于有些异常引起中断时,CPU 内部会产生一个出错代码压入堆栈(异常中断int 8 和int10 - int

14),而其它的中断却并不带有这个出错代码(例如被零除出错和边界检查出错等),因此,asm.s 程序

中将所有中断的处理根据是否携带出错代码而分别进行处理。但处理流程还是一样的。

会产生出错代码的

5.1.1.2 系统调用处理相关程序

Linux 中应用程序调用内核的功能是通过中断调用int 0x80 进行的,寄存器eax 中放调用号。因此

该中断调用被称为系统调用。实现系统调用的相关文件包括system_call.s、fork.c、signal.c、sys.c

和exit.c 文件。

system_call.s 程序的作用类似于硬件中断处理中的asm.s 程序的作用,另外还对时钟中断和硬盘、

软盘中断进行处理。而fork.c 和signal.c 中的一个函数则类似于traps.c 程序的作用,为系统中断调

用提供C 处理函数。fork.c 程序提供两个C 处理函数:find_empty_process()和copy_process()。

所有寄存器入栈。

出错代码-->入栈

中断返回地址-->入栈

所有段寄存器置为内核

代码段的选择符值

调用相关C 处理函数

弹出入栈的出错码和后

来入栈的中断返回地址

弹出所有入栈寄存器

中断返回

注1:内核代码的选择

符值为0x10;

注2:无出错代码时就

使用0;

注3:调用的C 函数在

traps.c 中实现。压入

堆栈的出错代码和中

断返回地址是用作C 函

数的参数。

更多电子书教程下载请登陆http://down.zzbaike.com/ebook

本站提供的电子书教程均为网上搜集,如果该教程涉及或侵害到您的版权请联系我们。

第5 章 内核代码 linux/kernel/

73

signal.c 程序还提供一个处理有关进程信号的函数do_signal(),在系统调用中断处理过程中被调用。

另外还包括4 个系统调用sys_xxx()函数。

sys.c 和exit.c 程序实现了其它一些sys_xxx()系统调用函数。这些sys_xxx()函数都是相应系统

调用所需调用的处理函数,有些是使用汇编语言实现的,如sys_execve();而另外一些则用C 语言实现

(例如signal.c 中的4 个系统调用函数)。

我们可以根据这些函数的简单命名规则这样来理解:通常以‘do_‘开头的中断处理过程中调用的C

函数,要么是系统调用处理过程中通用的函数,要么是某个系统调用专用的;而以‘sys_‘开头的系统调

用函数则是指定的系统调用的专用处理函数。例如,do_signal()函数基本上是所有系统调用都要执行的

函数,而do_hd()、do_execve()则是某个系统调用专用的C 处理函数。

5.1.1.3 其它通用类程序

这些程序包括schedule.c、mktime.c、panic.c、printk.c 和vsprintf.c。

schedule.c 程序包括内核调用最频繁的schedule()、sleep_on()和wakeup()函数,是内核的核心

调度程序,用于对进程的执行进行切换或改变进程的执行状态。mktime.c 程序中仅包含一个内核使用的

时间函数mktime(),仅在init/main.c 中被调用一次。panic.c 中包含一个panic()函数,用于在内核

运行出现错误时显示出错信息并停机。printk.c 和vsprintf.c 是内核显示信息的支持程序,实现了内

核专用显示函数printk()和字符串格式化输出函数vsprintf()。

时间: 2024-10-05 01:42:04

linux内核学习-4kernal目录(关注新浪微博:寂寞侵蚀的岁月(4000多篇技术分享))的相关文章

linux内核学习-5任务调度(关注新浪微博:寂寞侵蚀的岁月(4000多篇技术分享))

void schedule(void) 105 { 106 int i,next,c; 107 struct task_struct ** p; // 任务结构指针的指针. 108 109 /* check alarm, wake up any interruptible tasks that have got a signal */ /* 检测alarm(进程的报警定时值),唤醒任何得到信号的可中断任务 */ 110 // 从任务数组中最后一个任务开始检测alarm. 111 for(p =

linux内核学习-6信号量(关注新浪微博:寂寞侵蚀的岁月(4000多篇技术分享))

#include // 调度程序头文件,定义了任务结构task_struct.初始任务0 的数据,// 还有一些有关描述符参数设置和获取的嵌入式汇编函数宏语句.8 #include // 内核头文件.含有一些内核常用函数的原形定义.9 #include // 段操作头文件.定义了有关段寄存器操作的嵌入式汇编函数.1011 #include // 信号头文件.定义信号符号常量,信号结构以及信号操作函数原型.1213 volatile void do_exit(int error_code); //

linux内核学习-3 main函数(关注新浪微博:寂寞侵蚀的岁月(4000多篇技术分享))

#ifdef RAMDISK // 如果定义了虚拟盘,则主内存将减少. 124 main_memory_start += rd_init(main_memory_start, RAMDISK*1024); 125 #endif // 以下是内核进行所有方面的初始化工作.阅读时最好跟着调用的程序深入进去看,实在看 // 不下去了,就先放一放,看下一个初始化调用 -- 这是经验之谈?. 126 mem_init(main_memory_start,memory_end); 127 trap_init

linux内核学习-3 init函数(关注新浪微博:寂寞侵蚀的岁月(4000多篇技术分享))

void init(void) 169 { 170 int pid,i; 171 172 setup((void *) &drive_info); // 读取硬盘参数包括分区表信息并建立虚拟盘和 // 安装根文件系统设备.(kernel/blk_drv/hd.c,71) 173 (void) open("/dev/tty0",O_RDWR,0); // 用读写访问方式打开设备"/dev/tty0", // 这里对应终端控制台. // 返回的句柄号0 -- s

Linux内核学习总结

李泽源 原创作品 转载请注明出处 <Linux内核分析>MOOC课程:http://mooc.study.163.com/course/USTC-1000029000 [Linux内核学习总结] 幸福来得很突然,这门课就快结束了…… 是时候,总结下这段时间的坚持了,也给同样对Linux内核有兴趣的你一个指南. 在这门课的学习过程中,按照老师的要求,每次课后都写一篇博文,这是一个很好的学习方式.每当写这些文章的时候,总是要多看几遍视频,再查查相关的资料,才能勉强凑成一个完整的文档:同时也把自己学

Linux内核学习总结(final)

Linux内核学习总结 符钰婧 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 这八周以来,我从拼不出来"Linux"这个词到知道了很多专有名词,也能大概了解Linux的工作机制,这一系列的进步都是一周周积累下来的.现在回过头来看,有种阳光总在风雨后的感觉,虽然这个比喻好像不太恰当. 闲话少说,接下来就进入这次的正题. 一.首先是对Linux操作系统的理解 1.操作系

Python提取Linux内核源代码的目录结构

今天用Python提取了Linux内核源代码的目录树结构,没有怎么写过脚本程序,我居然折腾了2个小时,先是如何枚举出给定目录下的所有文件和文件夹,os.walk可以实现列举,但是os.walk是只给出目录名和文件名,而没有绝对路径.使用os.path.listdir可以达到这个目的,然后是创建目录,由于当目录存在是会提示创建失败的错误,所以我先想删除所有目录,然后再创建,但是发现还是有问题,最好还是使用判断如果不存在才创建目录,存在时就不创建,贴下代码: # @This script can b

Linux内核学习-进程

先说几个术语: 一.Linux进程的五个段 下面我们来简单归纳一下进程对应的内存空间中所包含的5种不同的数据区都是干什么的.重点:代码段.数据段.堆栈段,这是一个概念堆.栈.全局区.常量区,这是另一个概念1)代码段:代码段是用来存放可执行文件的操作指令,也就是说是它是可执行程序在内存中的镜像.代码段需要防止在运行时被非法修改,所以只准许读取操作,而不允许写入(修改)操作--它是不可写的.代码段(code segment/text segment)通常是指用来存放程序执行代码的一块内存区域.这部分

linux内核学习:进程管理

进程状态 TASK_RUNNING 可运行或正在运行 TASK_INTERRUPTIBLE 进程被阻塞,但可以被信号唤醒 TASK_UNINTERRUPTIBLE 进程被阻塞,且不可以被信号唤醒 TASK_STOPPED 进程已停止,且不能再投入运行 TASK_ZOMBIE 所谓的僵死进程,进程描述符仍然保留 关键函数和结构 task_struct thread_info current clone fork exec wait exit linux内核学习:进程管理,布布扣,bubuko.co