LINUX内核学习
1. 系统调用
1.1. 什么是系统调用
当你运行的程序调用了open, fork, read, write等等,你就做了系统调用 。
系统调用就是程序如何进入内核执行任务。程序使用系统调用执行一系列的操作诸如:创建进程,网络和文件IO等等。
你可以在man page for syscalls(2)里面看到系统调用的列表。 用户程序做系统调用有不同的方法,CPU架构不同做系统调用的底层指令也不同。
作为应用开发者,你不需要经常思考系统调用如何正确执行。你只需要把头文件引入,然后像普通功能一样调用。
1.2 传统系统调用
有两个需要预先准备的知识:
- 我们可以通过生成软中断触发内核调用。
- 我们可以用汇编指令int生成软中断。
结合这两个概念让我们看Linux传统系统调用接口。
用户空间程序可以取到Linux内核软中断号,这样就可以进入内核和执行系统调用。
1.3 系统调用大致可分为六大类
- 进程控制(process control)
- 文件管理(file manipulation)
- 设备管理(device manipulation):操作系统控制的各种资源可看作设备。
- 信息维护(information maintenance):操作系统维护所有进程的信息,这些可通过系统调用来访问。
- 通信(communication) :进程间通信的常用模型有两个:消息传递模型和共享内存模型。
- 保护(protection):保护提供控制访问计算机的系统资源的机制
1.4 参考文档
2. 内核数据结构
2.1 传统的双向链表和内核中的双向链表的区别
- 有个单独的头结点(head)
- 每个节点(node)除了包含必要的数据之外,还有2个指针(pre,next)
- pre指针指向前一个节点(node),next指针指向后一个节点(node)
- 头结点(head)的pre指针指向链表的最后一个节点
- 最后一个节点的next指针指向头结点(head)
传统的链表有个最大的缺点就是不好共通化,因为每个node中的data1,data2等等都是不确定的(无论是个数还是类型)。linux中的链表巧妙的解决了这个问题,linux的链表不是将用户数据保存在链表节点中,而是将链表节点保存在用户数据中.linux的链表节点只有2个指针(pre和next),这样的话,链表的节点将独立于用户数据之外,便于实现链表的共同操作。
2.2 队列
2.3 映射
映射是实现(key,value)绑定的一种数据结构。也称为关联数组。可以视为由唯一key组成的集合。每个key对应这一个value。
常规的映射实现有hash表和二叉树,以及二叉树的变种。
2.1 参考文档
- 《Linux内核设计与实现》读书笔记(六)- 内核数据结构 (链表、队列、映射、红黑树)
- Linux内核中的算法和数据结构 (链表、双向链表、无锁链表、B+树、优先排序列表、红黑树)
- Linux Kernel - 第六讲 内核数据结构-讲解版_x264_哔哩哔哩_bilibili (链表、队列、映射、二叉树)
- linux内核中的链表 - wangLinuxer - 博客园 (cnblogs.com) (内核中的链表)
- linux内核之Kfifo环形队列 - super_xueyi - 博客园 (cnblogs.com) (Kfifo)
3. 中断处理
3.1 中断
中断请求(IRQ)是由可编程的中断控制器(PIC)发起的,其目的是为了中断 CPU 和执行中断服务程序(ISR)
Linux内核使用中断的方式来管理硬件设备,中断本质上是一种电信号,设备通过和中断控制器引脚相连的总线发出电信号来发出中断。中断控制器是一种控制芯片,多个设备的中断请求线同时连接到中断控制器上,如果多个设备同时发出中断信号,中断控制器根据优先级选择其中一个发送给处理器处理器,处理器收到中断请求后,就中断当前正在执行的任务,进行中断处理。内核通过中断号(中断号是系统为每个中断请求线interrupt request line分