本系列是对 陈莉君 老师 Linux 内核分析与应用[1] 的学习与记录。讲的非常之好,推荐观看
内存 是操作系统非常重要的资源,操作系统要运行一个程序,必须先把程序代码段的指令和数据段的变量从硬盘加载到内存中,然后才能被运行。如下图所示:
Redis 的缓存淘汰算法则是通过实现 LFU 算法来避免「缓存污染」而导致缓存命中率下降的问题(Redis 没有预读机制)。
作者简介 赵晨雨:西安邮电大学2018级陈莉君教授研究生,天真无邪小白一枚,已经爱上linux内核而不能自拔,正在成长为内核狂热爱好者? 跟随陈老师学习linux内核两个月了,对linux内核
关于空闲空间的管理,前面提到的是已被占用的数据块的组织和管理。接下来要解决的问题是,当我要保存一个数据块时,应该将其放在硬盘的哪个位置。难道需要扫描所有的块,随意找个空的地方放吗?
在 Linux 源码 linux-5.6.18\include\linux\rculist.h 头文件中定义的就是 RCU 链表的操作 ,
对 Linux 稍有了解的人都知道,Linux 会将物理的随机读取内存(Random Access Memory、RAM)按页分割成 4KB 大小的内存块,而今天要介绍的 Swapping 机制就与内存息息相关,它是操作系统将物理内存页中的内容拷贝到硬盘上交换空间(Swap Space)以释放内存的过程,物理内存和硬盘上的交换分区组成了操作系统上可用的虚拟内存,而这些交换空间都是系统管理员预先配置好的[^1]。
多线程调试的主要任务是准确及时地捕捉被调试程序线程状态的变化的事件,并且GDB针对根据捕捉到的事件做出相应的操作,其实最终的结果就是维护一根叫thread list的链表。上面的调试命令都是基于thread list链表来实现的,后面会有讲到。
/**************************************************************** 文件内容:内核之链队操作 版本V1.0 作者:HFL 时间:2013-12-22 说明:用户态中链表每个节点包含数据域和指针域,而内核态是每个数据中包含链表 因此内核态链表一般是嵌套在某个包含数据成员的结构体来实现。 内核的链表应用非常广泛:进程管理,定时器,工作队列,运行队列。总之 内核对于多个数据的组织和多个熟悉的描述都是通过链表串起来的。 *****************************************************************/ #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/list.h> MODULE_DESCRIPTION("My Module"); MODULE_ALIAS("My module"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("HFL21014"); struct student { char name[100]; int counter; struct list_head list; }; struct student *Mystudent; struct student *Temp_student; struct list_head student_list; struct list_head *pos; int Kernel_list_init() { int j = 0; INIT_LIST_HEAD(&student_list); Mystudent = kmalloc(sizeof(struct student)*5,GFP_KERNEL); memset(Mystudent,0,sizeof(struct student)*5); for(j=0;j<5;j++) { sprintf(Mystudent[i].name,"Student%d",j+1); Mystudent[j].counter = j+1; list_add( &(Mystudent[j].list), &student_list); } list_for_each(pos,&student_list) //遍历整个内核链表,pos其实就是一个for循环标量。中间临时使用,既不输入也不输出 { Temp_student = list_entry(pos,struct student,list); printk("hello,my student %d name: %s\n",Temp_student->counter,Temp_student->name); } return 0; } void Kernel_list_exit() { int k ; /* 模块卸载是要删除链表,并释放内存 */ for(k=0;k<10;jk++) { list_del(&(Mystudent[k].list)); } kfree(Mystudent); } module_init(Kernel_list_init);
很多时候,我们要监控系统状态,即监控系统cpu负载、进程状态等情况,如果我们在 Linux 应用层,我们有很多方式,命令行中常用 top、ps 命令,代码中,我们可以使用 popen 函数去执行一个 top 命令,获取返回值。或者我们直接读写 /proc下面的文件,都可以达到目的。
链表是基本数据结构, 一开始学习数据结构时, 我一般这么定义, 对应实现从头或尾插入的处理函数,
[121] 编写UNIX/Linux命令以列出目录中所有文件的名称(例如/usr/bin/dir/)(及其子目录),文件应该包含不区分大小写的“I am preparing for Interview”。
OS的正常工作依赖于存储程序原理、堆栈、中断三个部分。 linux内核从一个初始化上下文环境的函数开始执行,即start_kernel函数,创建多个进程或者fork(创建一个与原来进程几乎完全相同的进程)若干进程,我们为每个进程维护一个进程描述和以及进程间的关系PCB。 当中断发生的时候,如mykernel中就是时钟中断发生之后,接下来OS就会为各进程进行调度,利用Swich_to函数在调度队列中选取出一个适合的进程(系统会根据中断向量号来调用相应的中断异常程序)。由CPU和内核堆栈保存当前进程的各寄存器信息(CPU要做两件工作,一是将当前的eip和esp压入到当前进程的内核栈,二是将esp指向当前进程的内核栈,并将eip指向中断处理入口,进入到内核态。),将eip指向要调度的进程执行的代码区,开始执行。
在linux内核中封装了一个通用的双向链表库,这个通用的链表库有很好的扩展性和封装性,它给我们提供了一个固定的指针域结构体,我们在使用的时候,只需要在我们定义的数据域结构体中包含这个指针域结构体就可以了,具体的实现、链接并不需要我们关心,只要调用提供给我们的相关接口就可以完成了。
Linux有Linux kernal,我们的客户端,进行连接,首先到达的是Linux kernal,在Linux的早期版本,只有read和write进行文件读写。我们使用一个线程/进程 进行调用read和write函数,那么将会返回一个文件描述符fd(file description)。我们开启线程/进程去调用read进行读取。因为socket在这个时期是blocking(阻塞的),遇到高并发,就会阻塞,也就是bio时期。
注:本分类下文章大多整理自《深入分析linux内核源代码》一书,另有参考其他一些资料如《linux内核完全剖析》、《linux c 编程一站式学习》等,只是为了更好地理清系统编程和网络编程中的一些概念
epoll有EPOLLLT和EPOLLET两种触发模式,水平触发和边缘触发. 此处略
操作系统为进程维护了打开的文件列表,每个进程维护了一个file数组字段(struct file * fd[NR_OPEN]);每个元素指向一个file结构体。每个file结构体有一个字段指向inode结构体,inode管理这个文件的内容、权限等信息。这里分析的是file结构体的管理。
文件系统是操作系统中负责管理持久数据的子系统,说简单点,就是负责把用户的文件存到磁盘硬件中,因为即使计算机断电了,磁盘里的数据并不会丢失,所以可以持久化的保存文件。
在《Netfilter & iptables 原理》一文中,我们介绍了 Netfilter 和 iptables 的原理,而本文主要通过源码分析来介绍一下 Netfilter 与 iptables 的实现过程。
inotify是Linux中用于监控文件系统变化的一个框架,不同于前一个框架dnotify, inotify可以实现基于inode的文件监控。也就是说监控对象不再局限于目录,也包含了文件。不仅如此,在事件的通知方面,inotify摈弃了dnotify的信号方式,采用在文件系统的处理函数中放置hook函数的方式实现。
本文讲述了Linux中RCU(Read-Copy-Update)机制在内存管理中的重要作用,以及如何在Linux内核中实现和管理RCU。在Linux内核中,RCU用于在多个进程共享相同内存空间时,保证这些进程之间的数据一致性。本文首先介绍了RCU的基本原理,然后逐步深入介绍了Linux内核中RCU的实现细节。最后,通过一个具体的例子,展示了如何在Linux内核中实现一个简单的RCU。
unix操作系统里面,有一个fork操作,可以创建进程的子进程,或者说是复制一个进程完全一样的子进程,共享代码空间,但是各自有独立的数据空间,不过子进程的数据空间是拷贝父进程的数据空间的。
输入输出(input/output)的对象可以是文件(file), 网络(socket),进程之间的管道(pipe)。在linux系统中,都用文件描述符(fd)来表示。
继上一篇文章:https://cloud.tencent.com/developer/article/1053882 3. 文件系统的注册 这里的文件系统是指可能会被挂载到目录树中的各个实际文件系统,所谓实际文件系统,即是指VFS 中的实际操作最终要通过它们来完成而已,并不意味着它们一定要存在于某种特定的存储设备上。比如在笔者的 Linux 机器下就注册有 "rootfs"、"proc"、"ext2"、"sockfs" 等十几种文件系统。 3.1 文件系统的数据结构 在 Linux 源代码中,每种实际的文件
本文对双向链表进行探讨,介绍的内容是Linux内核中双向链表的经典实现和用法。其中,也会涉及到Linux内核中非常常用的两个经典宏定义offsetof和container_of。内容包括: 1.Linux中的两个经典宏定义 2.Linux中双向链表的经典实现
树是数据结构中的重中之重,尤其以各类二叉树为学习的难点。先从整体上认识下二叉树及其他各种树的区别和用途。
什么是VFS? Linux内核使用工厂的设计模式抽象出实际文件系统统一接口,这个就是虚拟文件系统(VFS),根据应用程序调用虚拟文件系统接口,根据不同的文件系统类型(xfs/zfs/ext4)来调用实
本文基于 Linux-2.4.16 内核版本 由于计算机的物理内存是有限的, 而进程对内存的使用是不确定的, 所以物理内存总有用完的可能性. 那么当系统的物理内存不足时, Linux内核使用什么方案来
uC/os内存管理机制为内存块形式,用户申请内存是需要自己指定内存区内内存块数和内存块大小,看起来很灵活,实际上很不方便,需要使用者记住内存块大小,自己维护内存区,给使用者增加了负担。
现代的应用程序都运行在一个内存空间里,在 32 位系统中,这个内存空间拥有 4GB (2 的 32 次方)的寻址能力。
在接入日志组件xlog的工作中,对mmap内存映射加深了了解,分享一下学习心得。 1.一个Linux进程的虚拟内存 如图展示了一个Linux进程的虚拟内存。 虚拟的意思是进程以为自己有这么一
来源:Linux爱好者 ID:LinuxHub Linux文件管理从用户的层面介绍了Linux管理文件的方式。Linux有一个树状结构来组织文件。树的顶端为根目录(/),节点为目录,而末端的叶子为包含数据的文件。当我们给出一个文件的完整路径时,我们从根目录出发,经过沿途各个目录,最终到达文件。 我们可以对文件进行许多操作,比如打开和读写。在Linux文件管理相关命令中,我们看到许多对文件进行操作的命令。它们大都基于对文件的打开和读写操作。比如cat可以打开文件,读取数据,最后在终端显示: $cat test
网上看了很多的嵌入式学习路线,有的比较片面,有的为了博人眼球东拼西凑,几乎把整个行业用得着用不着的技术都写上去了,没有侧重点,简直是劝退指南,还有的纯粹是打广告卖板子招生。
Linux文件管理从用户的层面介绍了Linux管理文件的方式。Linux有一个树状结构来组织文件。树的顶端为根目录(/),节点为目录,而末端的叶子为包含数据的文件。当我们给出一个文件的完整路径时,我们从根目录出发,经过沿途各个目录,最终到达文件。 我们可以对文件进行许多操作,比如打开和读写。在Linux文件管理相关命令中,我们看到许多对文件进行操作的命令。它们大都基于对文件的打开和读写操作。比如cat可以打开文件,读取数据,最后在终端显示: $cat test.txt 对于Linux下的程序员来说,了解文件
一、概念: 大多数内核子系统都是相互独立的,因此某个子系统可能对其它子系统产生的事件感兴趣。为了满足这个需求,也即是让某个子系统在发生某个事件时通知其它的子 系统,Linux内核提供了通知链的机制。通知链表只能够在内核的子系统之间使用,而不能够在内核与用户空间之间进行事件的通知。 通知链表是一个函数链表,链表上的每一个节点都注册了一个函数。当某个事情发生时,链表上所有节点对应的函数就会被执行。所以对于通知链表来说有一个通知 方与一个接收方。在通知这个事件时所运行的函数由被通知方决定,实际上也即是被通
操作系统内核提供 read(系统调用),读文件描述符 一个client连接就是一个文件描述符fd socket为阻塞的,socket产生的文件描述符,如左边的fd8,当数据包没到的时候,上面左边read不能返回,阻塞着。 即有一个client连接,就需要开一个进程(或者线程),读这个连接,有数据就处理,没数据就阻塞着。
也就是我们实际中编码时遇到的内存地址并不是对应于实际内存上的地址,我们编码中使用的地址是一个逻辑地址,会通过分段和分页这两个机制把它转为物理地址。而由于linux使用的分段机制有限,可以认为,linux下的逻辑地址=线性地址。也就是,我们编码使用的是线性地址,之后只需要经过一个分页机制就可以把这个地址转为物理地址了。所以我们更重要的可能是去说明一下linux的分页模型。
除了原子操作,中断屏蔽,自旋锁以及自旋锁的衍生锁之外,在Linux内核中还存在着一些其他同步互斥的手段。
免责声明:本文介绍的安全知识方法以及代码仅用于渗透测试及安全教学使用,禁止任何非法用途,后果自负 前言:作者最近在学习有关linux rootkit的原理与防范,在搜索资料中发现,在freebuf上,对rootkit进行介绍的文章并不是很多。在此我斗胆献丑,总结了下我最近的学习收获,打算发表一系列关于linux rootkit的文章在freebuf上,希望能够帮助到大家。 对于这个系列文章,我的规划如下:这一系列文章的重点集中在介绍linux rootkit中最讨论最多也是最受欢迎的一种:loadable
什么是epoll epoll是什么?按照man手册的说法:是为处理大批量句柄而作了改进的poll。当然,这不是2.6内核才有的,它是在2.5.44内核中被引进的(epoll(4) is a new API introduced in Linux kernel 2.5.44),它几乎具备了之前所说的一切优点,被公认为Linux2.6下性能最好的多路I/O就绪通知方法。 epoll的相关系统调用 epoll只有epoll_create,epoll_ctl,epoll_wait 3个系统调用。 1. int ep
一. linux内核简介 1. linux简介 1.1 unix的特点 unix很简洁,仅提供几百个系统调用,并有非常明确的设计目的 unix所有东西都当作文件对待,这种抽象使对数据和设备都通过一套相同的系统调用接口进行 内核用C语言编写,移植能力很强 进程创建迅速,独特的fork调用 提供了简洁但是稳定的进程间通讯原语 1.2 unix和linux linux克隆unix,但不是unix linux借鉴了unix很多的设计,并且实现了 unix的api linux没有直接使用unix的源代码,但完整表达了
点击蓝字,关注我们 导言 splice pipe pool for splice pipe pool in HAProxy pipe pool in Go 小结 参考&延伸 导言 相信那些曾经使用 Go 写过 proxy server 的同学应该对 io.Copy()/io.CopyN()/io.CopyBuffer()/io.ReaderFrom 等接口和方法不陌生,它们是使用 Go 操作各类 I/O 进行数据传输经常需要使用到的 API,其中基于 TCP 协议的 socket 在使用上述接口和
导语:掐指一算自己从研究生开始投入到Linux的海洋也有几年的时间,即便如此依然对其各种功能模块一知半解。无数次看了Linux内核的技术文章后一头雾水,为了更系统地更有方法的学Linux,特此记录。 历史 1991年,还在芬兰赫尔辛基大学上学的Linus Torvalds在自己的Intel 386计算机上开发了属于他自己的第一个程序,并利用Internet发布了他开发的源代码,将其命名为Linux,从而创建了Linux操作系统,并在同年公开了Linux的代码,从而开启了一个伟大的时代。在之后的将近30
epoll是一种I/O事件通知机制,是linux 内核实现IO多路复用的一个实现。IO多路复用是指,在一个操作里同时监听多个输入输出源,在其中一个或多个输入输出源可用的时候返回,然后对其的进行读写操作。 epoll有两种工作方式, LT-水平触发 和ET-边缘触发(默认工作方式),主要区别是: LT,内核通知你fd是否就绪,如果没有处理,则会持续通知。而ET,内核只通知一次。 什么是I/O? 输入输出(input/output)的对象可以是文件(file), 网络(socket),进程之间的管道(pipe)。在linux系统中,都用文件描述符(fd)来表示。 什么是事件? IO中涉及到的行为,建立连接、读操作、写操作等抽象出一个概念,就是事件,在jdk中用类SelectionKey.java来表示,例如:可读事件,当文件描述符关联的内核读缓冲区可读,则触发可读事件(可读:内核缓冲区非空,有数据可以读取);可写事件,当文件描述符关联的内核写缓冲区可写,则触发可写事件(可写:内核缓冲区不满,有空闲空间可以写入)。 什么是通知机制? 通知机制,就是当事件发生的时候,则主动通知。通知机制的反面,就是轮询机制。
在上期文章中,已经给大家分享过offsetof()和container_of两个宏函数,这两个宏函数在Linux内核链表里面有大量的应用,对于我们平时工作写代码有很大的帮助。下面是Linux内核链表的内容分享。
领取专属 10元无门槛券
手把手带您无忧上云