学习内核编程
我想学习linux内核编程。
那会是什么起点呢? 什么可能是一些更简单的问题的目标?
提前致谢
尝试获得罗伯特·洛夫的Linux内核编程的书。 它非常简洁,易于遵循。
之后或者与之一起,你可能想看看“了解Linux内核”。但是我不会在早期阶段推荐它。
另外,看看Linux内核编程指南 。 由于编程内核模块可以学到很多东西,因此该指南将帮助您。 是的,有关许多信息,请查阅内核源代码tarball的“文档”子目录。
**TODO** +editPic: Linux Kernel Developer -> (Ring Layer 0) +addSection: Kernel Virtualization Engine KERN_WARN_CODING_STYLE: Do not Loop unless you absolutely have to.
推荐书籍为未初始化的
void *i
“只有拥有了一定的生命,男人才能理解书本,或者至less在他看到并至less生活过一部分内容之前,没有人能够理解一本深厚的书。” – 埃兹拉庞德
千里之行必须从一个步骤开始。 如果您对以下哪本书感到困惑,请不要担心,请select您的任何一项。 并不是所有的人都stream浪了。 随着所有道路最终连接到高速公路 ,您将在内核旅程中探索新事物,因为页面正在进行而不会遇到任何死angular,并最终连接到code-set
。 谨慎阅读,记住: 代码不是文学 。
剩下的不是一个东西,一个情感,一个形象,一个心理图景,一个记忆甚至是一个想法。 这是一个function。 某种过程。 生命的一个方面可以被描述为“更大”的function。 因此,它似乎并不是与其他东西真的“分离”。 事实上,与刀的function一样,切割的东西并不是与刀本身分开的。 该function目前可能或可能不会被使用,但可能永远不会分开。
Solovay Strassenprimefaces性testing的随机化algorithm :
阅读不要抵触和狡猾; 也不相信和理所当然; 也没有find谈话和话语; 但要权衡和考虑。 有的书要吃,有的要吞下去,有的要嚼消化,有的只能读一部分,一部分要读,但不要好奇,有的要全部读,勤勉和关注。
static void tasklet_hi_action(struct softirq_action *a) { struct tasklet_struct *list; local_irq_disable(); list = __this_cpu_read(tasklet_hi_vec.head); __this_cpu_write(tasklet_hi_vec.head, NULL); __this_cpu_write(tasklet_hi_vec.tail, this_cpu_ptr(&tasklet_hi_vec.head)); local_irq_enable(); while (list) { struct tasklet_struct *t = list; list = list->next; if (tasklet_trylock(t)) { if (!atomic_read(&t->count)) { if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state)) BUG(); t->func(t->data); tasklet_unlock(t); continue; } tasklet_unlock(t); } local_irq_disable(); t->next = NULL; *__this_cpu_read(tasklet_hi_vec.tail) = t; __this_cpu_write(tasklet_hi_vec.tail, &(t->next)); __raise_softirq_irqoff(HI_SOFTIRQ); local_irq_enable(); } }
核心Linux (5 – > 1 – > 3 – > 2 – > 7 – > 4 – > 6)
“大自然既没有内核也没有shell, 她就是一切“ – 约翰·沃尔夫冈·冯·歌德
读者应该熟悉操作系统的概念 ; 对长时间运行的stream程有一个公正的理解,并且与短时间执行stream程的差异; 容错性,同时满足软实时和硬实时的限制。 在阅读时,理解和n/ack
核心子系统中由linux内核源所做的deviseselect是很重要的。
线程[和]信号是一个平台依赖的痛苦,绝望,恐怖和疯狂的踪迹(〜安东尼·巴克斯特)。 这就是说,在深入内核之前,你应该是一个自我评估的C专家。 您还应该有链接列表,堆栈,队列,红黑树,散列函数等等的丰富经验。
volatile int i; int main(void) { int c; for (i=0; i<3; i++) { c = i&&&i; printf("%d\n", c); /* find c */ } return 0; }
Linux内核源码的美妙和艺术在于使用了故意的代码混淆。 这通常是必要的,以便以干净优雅的方式传达涉及两个或更多个操作的计算意义。 编写多核架构代码时尤其如此。
实时系统video讲座 , 任务调度 , 内存压缩 , 内存障碍 , SMP
#ifdef __compiler_offsetof #define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER) #else #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) #endif
- Linux内核开发 – Robert Love
- 了解Linux内核 – Daniel P. Bovet,Marco Cesati
- Linux KerneLdevise的艺术 – 杨立祥
- 专业的Linux内核架构 – Wolfgang Mauerer
- UNIX操作系统的devise – Maurice J. Bach
- 了解Linux虚拟内存pipe理器 – Mel Gorman
- Linux内核内部 – Tigran Aivazian
- embedded式Linux入门 – Christopher Hallinan
Linux设备驱动程序 (1 – > 2 – > 4 – > 3 – > 8 – > …)
“音乐不会带你走,你必须严格按照自己的能力去关注情感或故事的小小内核”。 – 黛比哈利
您的任务基本上是在硬件设备和软件内核之间build立一个高速通信接口。 您应该阅读硬件参考数据表/手册以了解设备的行为,以及它的控制和数据状态,并提供物理通道。 关于您的特定架构的汇编知识以及对VLSI的公平了解硬件描述从VHDL或Verilog等语言将从长远来看帮助您。
- 英特尔®64和IA-32架构软件开发人员手册
- ARM体系结构参考手册
- ARM系统开发人员指南
问 :但是,为什么我必须阅读硬件规格?
答 :因为“碳与硅之间存在鸿沟,软件无法桥接” – Rahul Sonnad
但是,上述方法对计算algorithm ( 驱动程序代码 – 下半部分处理 )没有任何问题,因为它可以在通用图灵机上完全模拟。 如果计算结果在math领域是成立的,那么在物理领域也是如此。
Linux设备驱动程序video讲座 (第17和18章), embedded式KMS驱动程序剖析 , 引脚控制和GPIO更新 , 通用时钟框架 , 编写真实的Linux驱动程序 – Greg KH
static irqreturn_t phy_interrupt(int irq, void *phy_dat) { struct phy_device *phydev = phy_dat; if (PHY_HALTED == phydev->state) return IRQ_NONE; /* It can't be ours. */ /* The MDIO bus is not allowed to be written in interrupt * context, so we need to disable the irq here. A work * queue will write the PHY to disable and clear the * interrupt, and then reenable the irq line. */ disable_irq_nosync(irq); atomic_inc(&phydev->irq_disable); queue_work(system_power_efficient_wq, &phydev->phy_queue); return IRQ_HANDLED; }
- Linux设备驱动程序 – Jonathan Corbet,Alessandro Rubini和Greg Kroah-Hartman
- 基本的Linux设备驱动程序 – Sreekrishnan Venkateswaran
- 编写Linux设备驱动程序 – Jerry Cooperstein
- Linux内核模块编程指南 – Peter Jay Salzman,Michael Burian,Ori Pomerantz
- Linux的PCMCIA程序员指南 – David Hinds
- Linux SCSI编程指南 – Heiko Eibfeldt
- 用于POSIX操作系统的串行编程指南 – Michael R. Sweet
- Linuxgraphics驱动程序:简介 – StéphaneMarchesin
- Linux USB设备驱动程序编程指南 – Detlef Fliegl
- Linux内核设备模型 – Patrick Mochel
内核networking (1 – > 2 – > 3 – > …)
“称它为一个氏族,把它称为一个networking,称之为一个部落,称之为一个家庭:无论你说什么,无论你是谁,你都需要一个。” – 简·霍华德
理解内核中的数据包遍历是理解内核networking的关键。 如果我们想了解Netfilter或者IPSec内部,理解这是必须的。 linux内核networking层的两个最重要的结构是: struct sk_buff
和struct net_device
static inline int sk_hashed(const struct sock *sk) { return !sk_unhashed(sk); }
- 了解Linuxnetworking内部 – Christian Benvenuti
- Linux内核networking:实现和理论 – Rami Rosen
- UNIXnetworking编程 – W. Richard Stevens
- Linuxnetworking编程权威指南 – Keir Davis,John W. Turner,Nathan Yocom
- Linux TCP / IP协议栈:embedded式系统的networking – Thomas F. Herbert
- Linuxsockets编程的例子 – 沃伦W.盖伊
- Linux高级路由和stream量控制HOWTO – Bert Hubert
内核debugging (1 – > 4 – > 9 – > …)
除非与之沟通,否则一定意味着什么,麻烦一定会导致。 〜阿兰·图灵,关于电脑
Brian W. Kernighan在Unix for Beginners(1979年)的论文中说:“最有效的debugging工具仍然是慎重考虑的,加上明智的打印语句”。 了解要收集的内容将有助于快速获取正确的数据以进行快速诊断。 伟大的计算机科学家Edsger Dijkstra曾经说过,testing可以certificate缺陷的存在,但不是缺失。 良好的调查实践应该平衡快速解决问题的需要,build立技能的需要以及主题专家的有效使用。
有些时候你碰到底部,似乎什么都不起作用,你用尽了所有的select。 那么真正的debugging开始了。 一个错误可能会提供你需要脱离对无效解决scheme的修复。
关于内核debugging和性能分析 , 核心转储分析 , 使用GDB进行多核debugging , 控制多核竞争条件 , debugging电子的 video讲座
/* Buggy Code -- Stack frame problem * If you require information, do not free memory containing the information */ char *initialize() { char string[80]; char* ptr = string; return ptr; } int main() { char *myval = initialize(); do_something_with(myval); } /* “When debugging, novices insert corrective code; experts remove defective code.” * – Richard Pattis #if DEBUG printk("The above can be considered as Development and Review in Industrial Practises"); #endif */
- Linuxdebugging和性能调优 – Steve Best
- Linux应用程序debugging技术 – Aurelian Melinte
- 使用GDB进行debugging:GNU源代码级debugging器 – Roland H. Pesch
- debuggingembedded式Linux – Christopher Hallinan
- 用GDB,DDD和Eclipsedebugging的艺术 – Norman S. Matloff
- 为什么程序失败:系统debugging指南 – Andreas Zeller
- 软件驱魔:debugging和优化遗留代码手册 – Bill Blunden
- debugging:发现大多数难以处理的软件和硬件问题 – David J. Agans
- 通过思考进行debugging:多学科方法 – Robert Charles Metzger
- find错误:一本错误的程序 – Adam Barr
文件系统 (1 – > 2 – > 6 – > …)
“我想拥有虚拟内存,至less与文件系统结合在一起”。 肯·汤普森
在UNIX系统上,一切都是文件; 如果某个文件不是文件,那么除了命名pipe道和套接字之外,它是一个进程。 在一个文件系统中,一个文件由一个inode
来表示,这是一种包含组成该文件的实际数据信息的序列号。 Linux虚拟文件系统VFS
信息caching在每个文件系统的内存中,并在其中进行安装和使用。 由于在创build,写入和删除文件和目录时修改了这些caching中的数据,所以必须谨慎地更新文件系统。 这些caching中最重要的是缓冲区caching,它被集成到各个文件系统访问其底层块存储设备的方式中。
存储系统video讲座 , Flash友好文件系统
long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode) { struct open_flags op; int fd = build_open_flags(flags, mode, &op); struct filename *tmp; if (fd) return fd; tmp = getname(filename); if (IS_ERR(tmp)) return PTR_ERR(tmp); fd = get_unused_fd_flags(flags); if (fd >= 0) { struct file *f = do_filp_open(dfd, tmp, &op); if (IS_ERR(f)) { put_unused_fd(fd); fd = PTR_ERR(f); } else { fsnotify_open(f); fd_install(fd, f); } } putname(tmp); return fd; } SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode) { if (force_o_largefile()) flags |= O_LARGEFILE; return do_sys_open(AT_FDCWD, filename, flags, mode); }
- Linux文件系统 – Moshe酒吧
- Linux文件系统 – William Von Hagen
- UNIX文件系统:进化,devise和实现 – Steve D. Pate
- 实用的文件系统devise – Dominic Giampaolo
- 文件系统取证分析 – Brian Carrier
- Linux文件系统层次结构 – Binh Nguyen
- BTRFS:Linux B树文件系统 – Ohad Rodeh
- StegFS:用于Linux的隐写文件系统 – Andrew D. McDonald,Markus G. Kuhn
安全性 (1 – > 2 – > 8 – > 4 – > 3 – > …)
“UNIX的目的不是为了阻止用户做愚蠢的事情,因为这也会阻止他们做出聪明的事情”。 – Doug Gwyn
没有技术的作品,如果不使用。 道德随着技术而改变。
“ F×S = k ”自由和安全的乘积是一个常数。 – 尼文定律
密码学是在线信任的基础。 黑客利用技术,物理或人为因素中的安全控制。 从其他正在运行的程序中保护内核是朝着一个安全稳定的系统迈出的第一步,但这显然是不够的:在不同的用户应用程序之间必须存在一定程度的保护。 漏洞攻击可以针对本地或远程服务。
“你不能破解你的命运,蛮力……你需要一个后门,一个侧面通道进入生活。” – 克莱德Dsouza
电脑不解决问题,他们执行解决scheme。 在每个非确定性algorithm代码的背后,都有一个确定的思想。 – / var / log / dmesg
encryption和networking安全video讲座 ,安全 命名空间 , 远程攻击防护 , 安全embedded式Linux
env x='() { :;}; echo vulnerable' bash -c "echo this is a test for Shellsock"
- 黑客攻击的艺术 – Jon Erickson
- Rootkit Arsenal:逃避和逃避在系统的黑暗angular落 – 比尔布伦登
- 黑客暴露:networking安全的秘密 – Stuart McClure,Joel Scambray,George Kurtz
- 内核开发指南:攻击核心 – Enrico Perla,Massimiliano Oldani
- 记忆取证艺术 – Michael Hale Ligh,Andrew Case,Jamie Levy,AAron Walters
- 实用逆向工程 – Bruce Dang,Alexandre Gazet,Elias Bachaalany
- 实用恶意软件分析 – Michael Sikorski,Andrew Honig
- 最大的Linux安全:保护你的Linux服务器的黑客指南 – 匿名
- Linux安全 – Craig Hunt
- 真实世界的Linux安全 – Bob Toxen
内核源代码 (0.11 – > 2.4 – > 2.6 – > 3.18)
“像葡萄酒一样,对内核编程的掌握随着时间的推移而成熟,但与葡萄酒不同的是,这个过程变得更加甜美。 – 劳伦斯Mucheka
你可能不认为程序员是艺术家,但编程是一个非常有创意的职业。 这是基于逻辑的创造力。 计算机科学教育不能让任何人成为专家程序员,只能学习画笔和颜料才能成为一个专家画家。 正如你所知道的,知道path和走路是有区别的。 最重要的是卷起袖子,用内核源代码弄脏你的手。 最后,凭借您获得的核心知识 ,无论您走到哪里,您都将闪耀光芒 。
不成熟的编码员模仿; 成熟的编码窃取; 糟糕的编码人员玷污了他们所拿的东西,好的编码人员把它变成更好的东西,或者至less有不同的东西。 这位优秀的编码员将他的盗窃行为整合成一种独特的感觉,与撕裂的感觉截然不同。
关于内核食谱的video讲座
linux-0.11 ├── boot │ ├── bootsect.s head.s setup.s ├── fs │ ├── bitmap.c block_dev.c buffer.c char_dev.c exec.c │ ├── fcntl.c file_dev.c file_table.c inode.c ioctl.c │ ├── namei.c open.c pipe.c read_write.c │ ├── stat.c super.c truncate.c ├── include │ ├── a.out.h const.h ctype.h errno.h fcntl.h │ ├── signal.h stdarg.h stddef.h string.h termios.h │ ├── time.h unistd.h utime.h │ ├── asm │ │ ├── io.h memory.h segment.h system.h │ ├── linux │ │ ├── config.h fdreg.h fs.h hdreg.h head.h │ │ ├── kernel.h mm.h sched.h sys.h tty.h │ ├── sys │ │ ├── stat.h times.h types.h utsname.h wait.h ├── init │ └── main.c ├── kernel │ ├── asm.s exit.c fork.c mktime.c panic.c │ ├── printk.c sched.c signal.c sys.c system_calls.s │ ├── traps.c vsprintf.c │ ├── blk_drv │ │ ├── blk.h floppy.c hd.c ll_rw_blk.c ramdisk.c │ ├── chr_drv │ │ ├── console.c keyboard.S rs_io.s │ │ ├── serial.c tty_io.c tty_ioctl.c │ ├── math │ │ ├── math_emulate.c ├── lib │ ├── close.c ctype.c dup.c errno.c execve.c _exit.c │ ├── malloc.c open.c setsid.c string.c wait.c write.c ├── Makefile ├── mm │ ├── memory.c page.s └── tools └── build.c
- 初学者从Linux 0.11源码开始(less于20,000行源代码)。 经过20多年的发展,与Linux 0.11相比,Linux已经变得非常庞大,复杂,难以学习。 但devise理念和主体结构没有根本性的变化。 学习Linux 0.11仍然具有重要的现实意义。
- 内核黑客强制读取=>
Linux_source_dir/Documentation/*
- 您至less应该在一个内核邮件列表上订阅和激活。 从内核新手开始。
- 您不需要阅读完整的源代码。 一旦你熟悉了内核API及其用法,直接从你感兴趣的子系统的源代码开始。你也可以开始编写你自己的即插即用模块来testing内核。
- 设备驱动程序编写者将受益于拥有自己的专用硬件。 从树莓派开始。
查看Linux Kernel Janitor项目
“我们浏览Linux内核源代码,进行代码评论,修复未经维护的代码以及进行其他清理和API转换。 内核入侵是一个好的开始。“
以下的书我读了,发现非常有用:
- Linux内核开发
- 了解Linux内核,第三版
- 专业的Linux内核架构
- 基本的Linux设备驱动程序
- Linux设备驱动程序
- Linux内核编程(第3版)
- LF320 Linux内核内核和debugging
- Linux系统编程:直接与内核和C库对话
- 编写Linux设备驱动程序:练习指南
检查kernelnewbies.org,订阅Kernelnewbies邮件列表,到irc.oftc.org #kernelnewbies
一些资源:
- 本书:罗伯特·爱,Linux内核开发,第3版
- 本书:Corbet,Rubini,Linux设备驱动程序,第3版( 这里是免费版本)
- Book:Linux内核简介(免费版本)
- 自由电子提供的免费材料