Linux Kernel
文章平均质量分 90
小灵不想卷
过去当做回忆,往事埋在心底,努力拥抱未来。
展开
-
《Linux 内核设计与实现》13. 虚拟文件系统
该对象(切记,不是具体的文件,即不是物理的,而只是存在于内存中的,因此 VFS 的文件对象没有对应的磁盘数据)由相应的 open() 系统调用创建,由 close() 系统调用撤销。各种文件系统都必须实现超级块对象,该对象用于存储特定文件系统的信息,通常对应于存放在磁盘特定扇区中的文件系统超级块或文件系统控制块。其实就是无效目录项,一个负状态的目录项没有对应的有效索引节点(d_inode 为 NULL),因为索引节点已被删除,或路径不在正确,但目录项仍然可以保留,以便快速解析以后的路径查询。原创 2023-10-07 00:45:31 · 373 阅读 · 0 评论 -
《Linux 内核设计与实现》12. 内存管理
当你创建了一个高速缓存后,slab 层所起的作用就像一个专门的分配器,可以为具体的对象类型进行分配。不能给 _get_free_pages() 或 kalloc() 指定 ZONE_HIGHMEM,因为这两个函数返回的都是逻辑地址,而不是 page 结构,这两个函数分配的内存当前有可能还没有映射到内核的虚拟地址空间,因此,也可能根本就没有逻辑地址。若想要释放的内存不是由 kmalloc() 申请的,或想要释放的内存早被释放了,再调用 kfree() 的话,就会导致很严重的后果。原创 2023-05-09 12:27:23 · 1105 阅读 · 1 评论 -
《Linux 内核设计与实现》11. 定时器和时间管理
若随意改变内核中的 HZ 值,而不及时更新用户空间的 HZ,则会给用户空间中的某些程序造成些异常结果。jiffies_to_clock_t() 将一个由 HZ 表示的节拍计数转换成一个由 USER_HZ 表示的节拍计数。jiffies 是无符号长整型,在 32 位,时钟频率为 100HZ 的情况下,497 天会溢出,1000HZ 的情况下,49.7 天就会溢出。其次,一般情况下,应该使用 del_timer_sync() 代替 del_timer(),因为无法确定在删除定时器时,它是否在其它处理器上运行。原创 2023-05-09 12:25:21 · 774 阅读 · 0 评论 -
《Linux 内核设计与实现》10. 内核同步方法
在 Linux 上 atomic_t 整数类型都是 32 位,其中数据位为高 24 位,低 8 位嵌入了一个锁,因为 SPARC 体系结构对原子操作缺乏指令级支持,所以只能利用该锁来避免对原子类型数据的并发访问。down_read_trylock() 和 down_write_trylock() 方法,若成功获得了信号量锁,返回非0,若信号量锁被争用,则返回0,这与普通信号量情况相反,要小心。自旋锁不可递归:你试图得到一个你持有的锁,必须自旋等待,可是你处于自旋等待中,因此无法释放锁,导致给自己锁死了。原创 2023-05-09 12:24:22 · 543 阅读 · 0 评论 -
《Linux 内核设计与实现》09. 内核同步介绍
共享资源之所以要防止并发访问,是因为如果多个执行线程同时访问和操作数据,就有可能发生各线程之间相互覆盖共享数据的情况,从而造成被访问的数据不一致状态。临界区和竞争条件- 临界区:访问和操作共享数据的代码段。- 原子操作:对资源的操作必须保证在结束之前不可被打断。- 竞争条件:两个执行线程对同一个临界区操作。- 同步:避免并发和防止竞争条件。现在有一个队列,有两个函数,一个是在尾部添加元素,另一个是删除尾部元素。这两个函数在内核的各个部分都可以调用,因此现在假设程序 A 要增加一个元素,当增加完了原创 2023-05-08 12:44:26 · 356 阅读 · 0 评论 -
《Linux 内核设计与实现》08. 下半部和推后执行的工作
这个 taskle 被调度之后,还未运行,此时又有一个相同的 tasklet 又被调度了,那么它仍然只会运行一次,或者说后来的那个无法被调度,因为在 task_schedule() 中已经做了判断。在这种情况下,中断处理程序执行硬件相关的操作,然后触发相应的软中断,最后退出。这被称作触发软中断。通常,中断处理程序会在返回前标记它的软中断,使其在稍后被执行。大部分软中断处理程序,都通过采取单处理器数据(仅属于某一个处理器的数据,因此根本不需要加锁)或其它一些技巧来避免显示地加锁,从而提供更出色的性能。原创 2023-05-08 12:43:04 · 570 阅读 · 0 评论 -
《Linux 内核设计与实现》07. 中断和中断处理
但在一条指定的中断线上,对 disable_irq() 或 disable_irq_nosync() 的每次调用,都需要响应地调用一次 enable_irq()。若指定的中断线不是共享的,那么,该函数删除处理程序的同时将禁用这条中断线。若中断线是共享的,则仅仅只是删除 dev 所对应的中断处理程序,而这条中断线只有当最后一个中断处理程序被删除时才会跟着被禁用。即同一条中断线上只允许接收一个中断,而该中断线上的其它中断我们此时不接收,但其它中断线上的不受影响。禁用多个中断处理程序共享的中断线是不合适的。原创 2023-05-08 12:40:32 · 516 阅读 · 0 评论 -
《Linux 内核设计与实现》06. 内核数据结构
链表中添加元素不再是添加一整个结构体 fox,而是添加 list_head 指针,每个 fox 都有一个 list 成员属性,通过这个属性可以得到上一个元素和下一个元素,以及还可以通过 list_entry() 转换得到父结构体 fox。这时因为在 C 语言中,一个给定结构中的变量偏移在编译时地址就被 ABI 固定下来了。而是将 fox 和 next/prev 指针分开,将 next/prev 形成一个新结构体 list_head。原创 2023-05-07 15:22:06 · 103 阅读 · 0 评论 -
《Linux 内核设计与实现》05. 系统调用
在系统调用表添加一个表项。表中的位置序号(索引)就是对应的系统调用号。对于所支持的各种体系结构,系统调用号都必须定义于中。系统调用必须被编译进内核映像(不能被编译成模块)。这只要把它放进 kernel 下的一个相关文件中就可以了,如 sys.c 它包含了各种各样的系统调用。新增系统调用 foo(),此时这个函数只是系统调用的具体实现,是在内核中的。第一步:在系统调用表中添加一个表项。;...;....long sys_foo /* 新增的表项 */第二步:将系统调用号添加到 unistd.h 中。原创 2023-05-07 15:15:15 · 627 阅读 · 0 评论 -
《Linux 内核设计与实现》03. 进程管理
此时内核需要代替用户程序执行用户程序所需的程序(其实就是说,用户程序没权限去得到或执行内核的东西,但是我用户程序需要内核的部分东西来辅助用户程序的执行,所以我需要内核来帮我去执行某些程序,最后将结果给我),这便是“代表进程执行”。调用完 exit() 后,对应的内存位图被重置,但是此时并没有将进程描述符 task_struct 以及 thread_info 给删除掉,由此可见资源的释放和进程描述符的删除是被分开执行的。如果在一个拥有大量进程的系统中遍历所有进程,代价是很大的,因此尽量不要这么做。原创 2023-05-07 15:11:13 · 555 阅读 · 0 评论