Linux 内核

  • 开发的特点
    • 无 libc 库抑或无标准头文件库
    • GUN C
    • 没有内存保护机制
    • 不要再内核中轻易使用浮点数
    • 容积小而且固定的栈
    • 同步和并发
    • 可移植性的重要性
    • 参考文献

开发的特点

相对于用户空间内应用程序的开发,内核在开发上是有一些区别的。尽管这些区别不会增大内核开发的难度,但是依然与开发用户代码有很大不同。
最主要的差异有以下几种:

1.内核编程时既不能访问 C 库也不能访问标准的 C 头文件;
2.内核编程时必须使用 GUN C;
3.内核编程时缺乏内存保护机制;
4.内核编程时难以执行浮点运算;
5.内核只分配给每个进程很小的定长堆栈;
6.由于内核支持异步中断、抢占和 SMP,因此必须时刻注意同步和并发,
7.要考虑可移植的重要性。

无 libc 库抑或无标准头文件库

内核不能链接使用标准的 C 函数库,而且其它的库也不行。造成这种情况的主要原因是速度和大小,对于内核而言,完整的 C 库或者仅仅是其一个子集,都太低效且大了。

针对这样的情况,大部分常用的 C 库在内核中都已经得到了实现。
当然了,也存在有没有实现的函数,例如 printf() 函数。内核代码虽然无法调用 printf() 函数,但是它提供了 printk() 函数,与 printf() 函数几乎相同。printk() 函数负责把格式化好的字符串拷贝到内核日志缓冲区上,syslog 程序就可以通过读取该缓冲区来获得内核信息。

GUN C

Linux 的内核是由 C 语言编写的,但是内核并不完全符合 ANSI C 标准。实际上,内核开发者总是用到 gcc 提供的许多语言的扩展部分。(gcc 是多种 GUN 编译器的集合,它包含的 C 编译器既可以编译内核,也可以编译 Linux 系统上用 C 语言编写的其它代码。)

没有内存保护机制

如果一个用户程序试图进行一次非法访问内存,内核就会发现这个错误,发送 SIGSEGV 信号,并结束这个进程。如果是内核自己非法访问内存,那么结果很难控制了。内核中发生内存错误会导致 oops。(当某些比较致命的问题出现时,我们的Linux内核会抱歉的对我们说:“哎呦(Oops),对不起,我把事情搞砸了”。Linux内核在发生kernel panic时会打印出 Oops 信息,把目前的寄存器状态、堆栈内容、以及完整的 Call trace 都 show 给我们看,这样就可以帮助我们定位错误。)

在内核中,不应该去做访问非法的内存地址,以及引用空指针之类的操作。此外,内核中的内存不分页。也就是说,每用掉一个字节,物理内存就减少一个字节。

不要再内核中轻易使用浮点数

在用户空间的进程内进行浮点操作的时候,内核会完成从整数操作到浮点数操作的模式转换。在执行浮点指令时到底会做些什么,因体系结构不同,内核的选择也不同,但是,内核通常捕获陷阱并着手于整数到浮点方式的转变。

与用户空间进程不同,内核并不能完美地支持浮点操作,因为它本身不能陷入。 在内核中使用浮点数时,除了要人工保存和恢复浮点寄存器,还有其他一些琐碎的事情要做。如果要直截了当地回答,那就是:别这么做了,除了一些极少的情况,不要在内核中使用浮点操作。

浮点数的编码跟整数编码是不一样的,计算时需要专门的寄存器和浮点计算单元来处理,一个浮点运算指令使用的CPU周期也更长。因此对于内核来说就会想尽量回避浮点数运算,譬如说浮点数经过定点整数转换后进行运算,效率会高很多,即使CPU带有浮点数运算部件,一般内核还是要避免直接进行浮点数运算,因为这些部件有可能被用户进程占用了,内核要判断这些浮点数部件是否被占用,保护现场,然后用浮点运算部件计算结果,恢复现场,开销会很大。如果CPU不支持浮点数运算,也就只能软件实现浮点数运算,要是你设计内核的话,相比起多做额外功夫(写浮点数实现代码)并且使得内核的效率不高,大家更加情愿避免这个问题。

容积小而且固定的栈

用户空间的栈比较大,且可以动态增长,所以用户进程可以从栈上分配大量的空间存放变量,甚至包含巨大的结构体和数组。而内核的栈随体系结构而变化,到那时固定而小,每个处理器都有自己的栈。

同步和并发

内核很容易产生竞争条件。这是因为内核的许多特性要求能够并发地址访问共享数据,这就要求有同步机制以保证不出现竞争条件,特别是:

1.Linux 是抢占多任务操作系统。
2.Linux 内核支持对称多处理器系统(SMP),两个或多个处理器上执行的中断代码可能会同时访问共享的资源。
3.中断是异步到来的,完全不顾及当前正在执行的代码。如果不加以适当的保护,中断完全可能会在代码访问资源时到来,这样中断处理函数就可能访问同一资源。
4.Linux 内核可以抢占,内核中一段正在执行的代码可能被另一段代码抢占,从而导致几段代码访问相同资源。

常见的解决办法:

1.自旋锁(spin_lock),是为实现保护共享资源而提出一种锁机制。其实,自旋锁与互斥锁比较类似,它们都是为了解决对某项资源的互斥使用。无论是互斥锁,还是自旋锁,在任何时刻,最多只能有一个保持者,也就说,在任何时刻最多只能有一个执行单元获得锁。但是两者在调度机制上略有不同。对于互斥锁,如果资源已经被占用,资源申请者只能进入睡眠状态。但是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁,"自旋"一词就是因此而得名。

2.信号量 (Saphore) 是用来解决进程/线程之间的同步和互斥问题的一种通信机制,是用来保证两个或多个关键代码不被并发调用。信号量由一个值和一个指针组成,指针指向等待该信号量的进程。信号量的值表示相应资源的使用情况。信号量 S>=0 时,S 表示可用资源的数量。执行一次 P 操作意味着请求分配一个资源,因此 S 的值减 1;当 S<0 时,表示已经没有可用资源,S 的绝对值表示当前等待该资源的进程数。请求者必须等待其他进程释放该类资源,才能继续运行。而执行一个 V 操作意味着释放一个资源,因此 S 的值加 1;若 S<0,表示有某些进程正在等待该资源,因此要唤醒一个等待状态的进程,使之运行下去。 信号量是选择睡眠的方式来对共享工作停止访问的。也就是说信号量通过PV操作同步解决了进程/线程对临界资源利用的冲突问题。

可移植性的重要性

尽管用户空间的应用程序不太注意移植问题,然而Linux却是一个可移植的操作系统,并且一直保持这种特点。也就是说,大部分C代码应该与体系结构无关,在许多不同体系结构的计算机上都能够编译和执行,因此,必须把体系结构相关的代码从内核代码树的特定目录中适当地分离出来。

诸如保持字节序、64位对齐、不假定字长和页面长度等一系列准则都有助于移植性。

参考文献

《Linux 内核设计与实现(第三版)》

Linux 内核开发特点相关推荐

  1. Linux内核开发工作方向

    Linux内核开发工作方向

  2. 嵌入式系统Linux内核开发工程师必须掌握的三十道题

    嵌入式系统Linux内核开发工程师必须掌握的三十道题 如果你能正确回答以下问题并理解相关知识点原理,那么你就可以算得上是基本合格的Linux内核开发工程师,试试看! 1) Linux中主要有哪几种内核 ...

  3. linux 内核开发_25年Linux内核开发中的9课

    linux 内核开发 由于Linux内核社区在2016年庆祝了25年的开发历史,因此许多人向我们询问了该项目的长寿和成功秘诀. 我通常会开玩笑,说我们真的不知道如何到达这里. 在此过程中,该项目面临许 ...

  4. Linux学习总结(68)——Linux 30年专访:Linus Torvalds谈Linux内核开发与Git

    三十年前,当Linus Torvalds(林纳斯·托瓦兹,下文统称Linus)首次发布Linux内核时,他还是赫尔辛基大学(University of Helsinki)的一名21岁的学生,他宣布说: ...

  5. Linux 30年专访:Linus Torvalds谈Linux内核开发与Git

    作者 | Jeremy Andrews 译者 | 火火酱,责编 | Carol 出品 | CSDN(ID:CSDNnews) 三十年前,当Linus Torvalds(林纳斯·托瓦兹,下文统称Linu ...

  6. 嵌入式Linux内核开发工程师必须掌握的三十道题

    如果你能正确回答以下问题并理解相关知识点原理,那么你就可以算得上是基本合格的Linux内核开发工程师. 1. Linux中主要有哪几种内核锁?(进程同步与互斥) (1)自旋锁:非睡眠锁 (2)信号量: ...

  7. 如何进行linux内核开发,2. 开发流程如何工作 — The Linux Kernel documentation

    2.1.总览¶ 内核开发人员使用一个松散的基于时间的发布过程,每两到三个月发布一次新的主要 内核版本.最近的发布历史记录如下: 4.11 四月 30, 2017 4.12 七月 2, 2017 4.1 ...

  8. 何为 Linux 内核开发,怎么学好 Linux 内核?

    此文包含 Linux 系统的学习路径和书籍推荐. 我觉得学习 Linux 系统,内核驱动时,最开始只需要 'Know what, not know how '. 不用去探究细节,只需要知道整体的框架, ...

  9. linux内核开发(基础)

    linux内核开发(基础) 树莓派等芯片带操作系统的启动过程 树莓派Linux源码目录树分析 tree指令 大概了解 具体内容 文件系统 什么是文件系统? 文件系统(文件管理系统的方法)的种类 分区 ...

最新文章

  1. php根据IP地址跳转对应的城市,淘宝REST api调用地址直接使用
  2. XHTML 结构化:使用 XHTML 重构网站
  3. SwiftUI3.0用户登录输入非空校验经典案例
  4. [导入]身份验证方面的问题
  5. pandas 判断是否等于nan_Python之pandas笔记
  6. Mysql 启动失败没日志,MySQL Server 5.7将无法启动,并且未填充错误日志
  7. 计算机专业本科毕业转行会计,大学里就业最难的5个专业,毕业后难找工作,很多同学都转行了!...
  8. CLO Standalone OnlineAuth for Mac(3D可视化服装设计软件)
  9. 南京审计学院计算机专业老师,南京审计学院如此对待一位好老师!!(转载)
  10. git ssh-keygen
  11. 盯盯拍罗勇:公司就是我最好的产品
  12. 麦库记事如何导出html,麦库记事使用问题解答
  13. 微信小程序用vant自定义tabbar页面并跳转相应页面
  14. 19 | 耗电优化(下):耗电的优化方法与线上监控
  15. 数据驱动运营,为门店开拓第二增长曲线。
  16. lsdyna如何设置set中的node_list_如何理解vue的双向绑定
  17. termux python3-dev_termux进阶
  18. 地质勘查土质分类图片_工程土质分类
  19. 王老吉药业“关爱烈日下最可爱的人”公益活动在杭启动
  20. hcna网络技术学习指南_网络工程与弱电工程师有什么区别?这些你都会吗

热门文章

  1. 教育部:全国高考延期一个月,湖北北京再行决定
  2. 给Python加Markdown式排版,在线运行可做Jupyter替身丨谷歌大脑出品
  3. 清华伯克利造出机械小强:承重200万倍踩不死,跑得和真蟑螂一样快
  4. GraphQL 01--- GraphQL 介绍及资源总结
  5. sprint计划会议总结
  6. centos7.5 升级kernel内核版本
  7. MySQL多源复制【转】
  8. 【Linux使用技巧】linux 死机了怎么办
  9. 《libGDX移动游戏开发从入门到精通》一第2章 libGDX的架构分析
  10. Verilog篇(三)仿真原理