• Linux内核设计与实现 总结笔记(第二章)


    一、Linux内核中的一些基本概念

    内核空间:内核可独立于普通应用程序,它一般处于系统态,拥有受保护的内存空间和访问硬件设备的所有权限。这种系统态和被保护起来的内存空间,称为内核空间。

    进程上下文:当应用程序执行一条系统调用,通过系统调用运行在内核空间,而内核被称为运行在进程上下文中。

    当你开发内核代码时,有一个重要的论坛是linux kernel mailing list(常缩写为lkml),你可以在http://vger.kernel.org上订阅邮件。

    二、内核的一些常用的准备和操作

    2.1 准备一个内核代码

    • 下载地址:http://www.kernel.org
    • 使用git获取最新的linux版本树:$git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
      • 更新linus的最新分支:$git pull

    2.2 安装内核源码

    • 解压压缩包
    tar xvjf linux-x.y.z.tar.bz2
    tar xvzf linux-x.y.z.tar.gz

    安装源码的位置注意:内核源码通常安装在/usr/src/linux目录下。不能把这个源码树用作开发,因为编译工具C库就是链接到这里的。

    并且不能用root对内核进行修改,哪怕是root安装内核,它都应该原封不动。

    • 使用补丁的方法
    patch -p1 < ../patch-x.y.z
    • 内核配置
    make config               老旧的方法,低效
    make menuconfig           最常用的方法
    make gconfig              基于个gtk+的图形工具
    make defconfig 创建一个默认的配置
    make oldconfig .config不存在,运行make config/menuconfig,设置是子目录中的Kconfig的设置
    .config存在,运行make config/menuconfig时的缺省设置即当前的.config设置
                    备份当前.config文件为.config.old,如果make config/menuconfig设置不当可用于恢复
    • 当内核运行时则可以将/proc/config.gz文件复制出来,并且解压得到此内核的.config配置文件
    zcat /proc/config.gz > .config                  #解压命令
    make oldconfig
    • 内核编译
    make -jn
    make -j32 > /dev/null
    • 安装新内核

    一定要保证随时有一个或两个可以启动的内核,以防新编译的内核出现问题。

    例如,在使用grub的x86系统上,可能需要把arch/i386/boot/bzImage拷贝到/boot目录下,像vmlinuz-version这样命名它。并且编辑/etc/grub/grub.conf文件,为新内核建立一个新的启动项。使用LILO启动的系统应当编辑etc/lilo.conf,然后运行lilo

    make moudles_install

    三、内核编译之外的信息

    • 内核和应用程序的差别包括以下几种:
    • 内核编程时既不能访问C库也不能访问标准的C头文件
    • 内核编程时必须使用GNU C
    • 内核编程时缺乏像用户空间那样的呢村保护机制
    • 内核编程时难以执行浮点运算
    • 内核给每个进程只有一个很小的定长堆栈
    • 由于内核支持异步中断、抢占和SMP,因此必须时刻注意同步和并发
    • 要考虑可移植性的重要性

    3.1 没有libc库抑或无标准头文件

    内核不能连接和使用标准C函数库,主要原因是使用库非常低效。

    而且大部分库中的函数,在内核中都有对应的函数实现了。

    3.2 头文件

    体系结构相关的头文件集位于内核源码树的arch/<architecture>/include/asm目录下

    • 内联函数

    内核开发者通常把那些对时间要求比较高,而本身长度有比较短的函数定义成内联函数。

    定义内联函数需要使用static作为关键字,并且用inline限定它。

    static inline void wolf(unsinged long tail_size);
    • 分支声明

    内核把gcc优化指令封装成宏,likely()和unlikely()。

    也就是说,使用likely(),执行if后面的语句的机会更大,使用unlikely(),执行else后面的语句机会更大一些。

    通过这种方式,编译器在编译过程中,会将可能性更大的代码紧跟着后面的代码,从而减少指令跳转带来的性能上的下降。
    比如 :
    if (likely(a>b)) {
      fun1();
    }
    if (unlikely(a>b)){
     fun2();
    }

    这里就是程序员可以确定 a>b 在程序执行流程中出现的可能相比较大,因此运用了likely()告诉编译器将fun1()函数的二进制代码紧跟在前面程序的后面,这样就cache在预取数据时就可以将fun1()函数的二进制代码拿到cache中。这样,也就添加了cache的命中率。

  • 相关阅读:
    docker容器中查看容器linux版本
    mac 安装docker
    音视频流处理
    激光雷达
    sick 激光
    Ubuntu 14.04 安装Docker
    W: GPG error: http://ppa.launchpad.net trusty InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 8CF63AD3F06FC659
    rtp发送 h265
    pytorch 环境搭建
    Linux 修改文件夹的用户组权限
  • 原文地址:https://www.cnblogs.com/ch122633/p/9934544.html
Copyright © 2020-2023  润新知