精华内容
下载资源
问答
  • Linux kernel 单内核体系设计、但充分借鉴了微内核设计体系的优点,为内核引入模块化机制。 内核组成部分: kernel:内核核心,一般为bzImage,通常在/boot目录下,名称为vmlinuz-VERSION-RELEASE kernel object:...
    • Linux kernel
      单内核体系设计、但充分借鉴了微内核设计体系的优点,为内核引入模块化机制。
      内核组成部分:
      kernel:内核核心,一般为bzImage,通常在/boot目录下,名称为vmlinuz-VERSION-RELEASE
      kernel object:内核对象,一般放置于/lib/modules/VERSION-RELEASE/
      [ ]:N
      [M]:M
      [*]:Y
      辅助文件:ramdisk
      initrd
      initramfs

    • 运行中的内核:
      uname命令:uname - print system information
      uname [OPTION]…
      -n:显示节点名称
      -r:显示VERSION-RELEASE

    • 模块:

    • lsmod命令:显示由核心已经装载的内核模块,显示的内容来自于:/proc/modules文件

    • modinfo命令;显示模块的详细描述信息
      moinfo [ -k kernel ] [ modulename|fielname… ]
      -n 只显示模块文件
      -p 显示模块参数
      -a author
      -d description
      -l license

    • modprobe命令:
      装载或卸载内核模块
      modprobe [ -C config-file ] [ modulename ] [ module parame-ters… ]
      配置文件:/etc/modprobe.conf,/etc/modprobe.d/*.conf
      modprobe [ -r ] modulename…

    • depmod命令:内核模块依赖关系文件及系统信息映射文件的生成工具

    • 装载或卸载内核模块
      insmod命令:insmod [ filename ] [ module options… ]
      rmmod rmmod [ modulename ]

    • proc目录:
      内核把自己内部状态信息及统计信息,以及可配置参数通过proc伪文件系统加以输出
      参数:
      只读:输出信息
      可写:可接受用户指定新值来实现对内核某功能或特性的配置/proc/sys
      1sysctl命令用于查看或设定此目录中诸多参数
      sysctl -w path.to.parameter=VALUE
      sysctl -w kernel.hostname=mail.magedu.com
      2echo命令通过重定向的方式也可以修改大多数参数的值
      echo “www.magedu.com” > /proc/sys/kernel/hostname

    • sysctl命令:
      配置文件:/etc/sysctl.conf
      1设置某参数:sysctl -w parameter=VALUE
      2通过读取配置文件设置参数
      sysctl -p [/path/to/conf_file]
      内核中的路由转发:/proc/sys/net/ipv4/ip_forward
      常用的几个参数:
      net.ipv4.ip_forward
      vm.drop_caches
      kernel.hostname

    • /sys目录
      sysfs:输出内核识别出的各硬件设备的相关属性信息,也有内核对硬件特性的设定信息,有些参数是可以修改的,用于调整硬件工作特性
      udev通过此路径下的输出的信息动态为各设备创建所需要设备文件,udev是运行用户空间程序,专用工具:udevadmn,hotplug
      udev为设备创建设备文件时,会读取其事先定义好的规则文件,一般在/etc/udev/rules.d及/usr/lib/udev/rules.d目录下

    • ramdisk文件的制作:
      1mkinitrd命令
      为当前正在使用的内核重新制作ramdisk文件
      mkinitrd /boot/initramfs-$(uname -r).img $(uname -r)
      2dracut命令:
      为当前正在使用的内核重新制作ramdisk文件
      dracut /boot/initramfs-¥(uname -r).img $(uname -r)

    • 编译内核:
      前提:1准备好开发环境
      2获取目标主机上硬件设备的相关信息
      3获取目标主机系统功能的相关信息,例如要启用的文件系统
      4获取内核
      准备好开发环境:
      包组(centos 6):
      server platform development
      development tools
      目标主机硬件设备相关信息:
      CPU:cat /proc/cpuinfo
      x86info -a
      lscpu
      PCI设备:
      lspci
      -v
      -vv
      或lsusb
      -v
      -vv
      或lsblk
      了解全部硬件设备信息
      hal-device
      简单依据模板文件的制作过程:
      tar xf linux-3.10.67.tar.xz -C /usr/src
      cd /usr/src
      Ln -sv Linux-3.10.67 Linux
      cd Linux
      cp /boot/config-$(uname -r) ./.config
      make menuconfig
      screen
      make -j #
      make modules_install
      make install
      重启系统,并测试使用新内核

    展开全文
  • linux内核学习(好东西)  2012-05-11 21:12:13| 分类: linux学习博客|字号 订阅 1. 内核学习方法,编译、调试等常见问题 1.1 关于编译升级内核到2.6.0的一些问题 作

    转自:http://blog.csdn.net/michaelrun/archive/2010/05/30/5634390.aspx

    linux内核学习(好东西)  

    2012-05-11 21:12:13|  分类: linux学习博客|字号 订阅

    1. 内核学习方法,编译、调试等常见问题

    1.1 关于编译升级内核到2.6.0的一些问题 作者:ommm
            http://linux.chinaunix.net/bbs/thread-281831-1-5.html
    1.2 VMWare Workstation 6.0调试Linux Kernel,竟如此方便 作者:albcamus
            http://linux.chinaunix.net/bbs/thread-896214-1-5.html
    1.3 基于S3C2410的Linux全线移植文档 作者:dozec
            http://linux.chinaunix.net/bbs/thread-798304-1-6.html
    1.4 【原创】《Linker Script in Linux》 作者: zx_wing
            http://linux.chinaunix.net/bbs/viewthread.php?tid=1032711
    1.5 月经结贴 -- 《Segmentation Fault in Linux》 作者: zx_wing
            http://linux.chinaunix.net/bbs/thread-1149936-1-19.html
    1.6 【译】linux-2.6.31内核文档系列 作者:openspace
            http://linux.chinaunix.net/bbs/thread-1149917-1-23.html
    1.7 Solaris、Linux和FreeBSD的内核比较 作者:compnik
            http://linux.chinaunix.net/bbs/thread-783940-1-24.html
    1.8 定位Oops的具体代码行 作者:albcamus
            http://linux.chinaunix.net/bbs/thread-1008573-1-25.html
    1.9 调试KERNEL时,找出当前进程信息的方法 作者:accessory 
            http://linux.chinaunix.net/bbs/thread-1147973-1-36.html
    1.10 Linux内核配置文档!!!(make menuconfig) 作者:HopeCao 
            http://linux.chinaunix.net/bbs/thread-16106-1-58.html
    1.11 Git 中文教程 作者:swanrobin 
            http://linux.chinaunix.net/bbs/thread-724949-1-79.html
    1.12 怎样为Linux内核打补丁 作者:jeffshia 
            http://linux.chinaunix.net/bbs/thread-811431-1-87.html
    1.13 2.6 内核中宏定义 #define DEFINE(sym, val)的问题 ? 作者:kimyoung 
            http://linux.chinaunix.net/bbs/thread-702373-1-94.html
    1.14 Linux内核中的红黑树 作者:Godbach 
            http://linux.chinaunix.net/bbs/thread-1055772-1-94.html
    1.15 Linux内核解读入门 作者:小皮 
            http://linux.chinaunix.net/bbs/thread-85340-1-99.html
    1.16 Linux汇编语言开发指南(zt) 作者:mmgg00 
            http://linux.chinaunix.net/bbs/thread-508038-1-99.html
    1.17 Netconsole实例源代码分析 作者:dreamice 
            http://linux.chinaunix.net/bbs/thread-1047519-1-105.html
    1.20 使用git参与kernel开发 作者:albcamus 
            http://linux.chinaunix.net/bbs/thread-920610-1-109.html
    1.21 http://lwn.net/Articles/2.6-kernel-api/的翻译 作者:co63 
            http://linux.chinaunix.net/bbs/thread-1040681-1-113.html
    1.22 linux情景分析非扫描带书签版本 作者:onlyflyer 
            http://linux.chinaunix.net/bbs/thread-1016938-1-123.html
    1.23 kallsyms的分析 作者:qtdszws
            http://linux.chinaunix.net/bbs/thread-1013999-1-135.html
    1.24 【求助】关于inb和inw的疑问 作者:njngypp 
            http://linux.chinaunix.net/bbs/thread-992279-1-147.html
    1.25 绝对精品--linux 内核代码构架图 作者:achlice 
            http://linux.chinaunix.net/bbs/thread-983931-1-153.html
    1.26 [转贴]用tags/cscope看内核源代码-HOWTO 作者:leviathan.alan 
            http://linux.chinaunix.net/bbs/thread-719390-1-153.html
    1.27 linux-2.6内核升级文档(全) 作者:killua 
            http://linux.chinaunix.net/bbs/thread-484867-1-155.html
    1.28 请教一个扩展汇编的问题 作者:flw2 
            http://linux.chinaunix.net/bbs/thread-901464-1-169.html
    1.29 前段时间arch/i386/kernel/head.S注解 作者:alasijiabandao 
            http://linux.chinaunix.net/bbs/thread-909584-1-177.html
    1.30 ud2是什么指令? 作者:netentsec 
            http://linux.chinaunix.net/bbs/thread-901519-1-191.html
    1.31 使用GDB与QEMU调试内核时的问题分析 作者:mingyanguo 
            http://linux.chinaunix.net/bbs/thread-702878-1-200.html
    1.32 什么是module 以及如何写一个module(转) 作者:我菜我怕谁 
            http://linux.chinaunix.net/bbs/thread-612522-1-207.html
    1.33 用netconsole从网络上收集Kernel Panic信息详细方法 作者:Jobs.AE@
            http://linux.chinaunix.net/bbs/thread-811116-1-225.html
    1.34 升级2.6内核的经验与心得 作者:vikingpro 
            http://linux.chinaunix.net/bbs/thread-251091-1-260.html

     

     

     

     

    2. 进程管理与进程间通信、模块间通信等

    2.1 内核通知链 学习笔记 作者:scutan
        http://linux.chinaunix.net/bbs/thread-1051266-1-2.html
    2.2 使用netlink通讯时需要注意的一些问题 作者:duanjigang
        http://linux.chinaunix.net/bbs/thread-1144547-1-9.html
    2.3 工作队列分析 作者: rwen2012
        http://linux.chinaunix.net/bbs/thread-882951-1-15.html
    2.4 [原创]QEMU小实验:手工遍历所有进程的方法 作者:accessory
        http://linux.chinaunix.net/bbs/thread-1155784-1-16.html
    2.5 用户空间内核空间ipc总结(sockopt,ioctl,mmap,netlink,proc,seq,file,copy_user) 作者:ubuntuer
        http://linux.chinaunix.net/bbs/thread-1154038-1-23.html
    2.6 netlink socket 编程之 why & how 作者:duanjigang 
        http://linux.chinaunix.net/bbs/thread-1031932-1-39.html
    2.7 linux2.6.29 swtich_to 详细分析(一) 作者:liujunwei1234 
        http://linux.chinaunix.net/bbs/thread-1099177-1-57.html
    2.8 Linux 用户态与内核态的交互——netlink 篇 作者:独孤九贱
        http://linux.chinaunix.net/bbs/thread-822500-1-60.html
    2.9 基于NETLINK的内核与用户空间共享内存的实现 作者:bripengandre 
        http://linux.chinaunix.net/bbs/thread-1113929-1-63.html
    2.10 内核源码kfifo分析(原创) 作者:springtty
        http://linux.chinaunix.net/bbs/thread-1089313-1-74.html
    2.11 Unreliable Guide to Locking -by Rusty Russell-中文版 作者:albcamus
        http://linux.chinaunix.net/bbs/thread-656347-1-79.html
    2.12 完全公平调度(CFS) 作者:wxc200 
        http://linux.chinaunix.net/bbs/thread-1063798-1-90.html
    2.13 Linux 2.4 内核说明文档(进程与中断管理篇) 作者:xuediao 
        http://linux.chinaunix.net/bbs/thread-571760-1-127.html
    2.14 写了一个内核模块 实现简单的类似ps命令. 作者:mq110 
        http://linux.chinaunix.net/bbs/thread-653764-1-130.html
    2.15 PAE机制分析 作者:vestige 
        http://linux.chinaunix.net/bbs/thread-986982-1-149.html
    2.16 Linux2.6内核进程创建过程分析 作者:scriptkidz
        http://linux.chinaunix.net/bbs/thread-912485-1-172.html
    2.17 [转贴]用户态和内核共享内存--最简单的例子 作者:leviathan.alan 
        http://linux.chinaunix.net/bbs/thread-719393-1-183.html
    2.18 Linux 调度的科普文章 作者:raise_sail 
        http://linux.chinaunix.net/bbs/thread-903481-1-186.html
    2.19 linux 2.4内核之信号(一) 作者:yjfpb04 
        http://linux.chinaunix.net/bbs/thread-900690-1-191.html 本帖最后由 Godbach 于 2010-05-29 01:48 编辑

     

     

     

     

    3. 内存管理及地址相关

    3.1 Linux内存管理大图(第三稿) 作者:Aryang
            http://linux.chinaunix.net/bbs/thread-1043740-1-1.html
    3.2 我理解的逻辑地址、线性地址、物理地址和虚拟地址(补充完整了) 作者:独孤九贱
            http://linux.chinaunix.net/bbs/thread-919019-1-6.html
    3.3 发个简单(易用)的内存池 作者:duanjigang
            http://linux.chinaunix.net/bbs/thread-1153205-1-20.html
    3.4 Linux内存:内存管理的实质 作者:frank_seng
            http://linux.chinaunix.net/bbs/thread-1003872-1-21.html
    3.5 查找X86_64下内核代码段物理地址的方法 作者:accessory
            http://linux.chinaunix.net/bbs/thread-1151780-1-26.html
    3.6 linux内存管理报告 作者:kendyke
            http://linux.chinaunix.net/bbs/thread-1145231-1-35.html
    3.7 [推荐] LKML上一篇关于barrier文档草案的讨论 作者:xiaozhaoz 
            http://linux.chinaunix.net/bbs/thread-713279-1-44.html
    3.8 还是不理解IOMMU、北桥、PCI的MMIO和ioremap 作者:epegasus 
            http://linux.chinaunix.net/bbs/thread-985872-1-50.html
    3.9 求助:将用户空间的虚拟地址映射到内核态的逻辑地址。 作者:onlyflyer 
            http://linux.chinaunix.net/bbs/thread-885038-1-80.html
    3.10 VMALLOC_RESERVE 和 896M 作者:思一克 
            http://linux.chinaunix.net/bbs/thread-690010-1-80.html
    3.11 对Linux堆内存释放的总结 作者:snow_insky
            http://linux.chinaunix.net/bbs/thread-677609-1-82.html
    3.12 请问完全内存虚拟化处理缺页异常的流程是什么? 作者:kikanjuu 
            http://linux.chinaunix.net/bbs/thread-978835-1-88.html
    3.13 Linux 内核中Demand paging 与swap机制的源码分析 作者:crosskernel 
            http://linux.chinaunix.net/bbs/thread-1060602-1-93.html
    3.14 Linux sys_exec中可执行文件映射的建立及读取 作者:frank_seng 
            http://linux.chinaunix.net/bbs/thread-1000474-1-116.html
    3.15 请教大家一个mmap的问题 作者:blossom007cn 
            http://linux.chinaunix.net/bbs/thread-900802-1-191.html
    3.16 映射的冲突 作者:qtdszws
            http://linux.chinaunix.net/bbs/thread-901328-1-190.html
    3.17 Linux Memory Management or 'Why is there no free RAM?' 作者:snow_insky 
            http://linux.chinaunix.net/bbs/thread-686942-1-209.html

     

     

     

     

     

    4. 中断相关

    4.1 《Interrupt in Linux(硬件篇)》(1楼有更新 2008.5.3) 作者:zw_wing
            http://linux.chinaunix.net/bbs/thread-996409-1-23.html
    4.2 [保留] 关于LINUX在中断(硬软)中不能睡眠的真正原因 作者:思一克 
            http://linux.chinaunix.net/bbs/thread-902033-1-38.html
    4.3 2.6.10的中断处理分析 作者:normalnotebook 
            http://linux.chinaunix.net/bbs/thread-685702-1-126.html
    4.4 请问如果在中断上下文中调用可能引起阻塞的代码到底会怎么样? 作者:dengcainiao 
            http://linux.chinaunix.net/bbs/thread-802655-1-256.html

     

     

     

     

    5. 文件系统方面

    5.1 内核模块中对文件的读写 作者:ubuntuer
            http://linux.chinaunix.net/bbs/thread-1148680-1-7.html
    5.2 一个简单文件系统的实现 作者:goter
            http://linux.chinaunix.net/bbs/thread-1113528-1-23.html
    5.3 最近看vfs部分,写了个笔记,大家看看.(37 ~ 39 楼更新了mount 文件系统部分) 作者:xpl
            http://linux.chinaunix.net/bbs/thread-1005219-1-27.html
    5.4 何把内核中的信息打印到文件 作者:xiaozhe2000 
            http://linux.chinaunix.net/bbs/thread-738197-1-112.html
    5.5 2.4.18预读算法详解 作者:taoistf 
            http://linux.chinaunix.net/bbs/thread-1029156-1-122.html
    5.6 [转] Dr.Wu 的博士论文: linux内核中的预取算法 作者:albcamus
            http://linux.chinaunix.net/bbs/thread-1029420-1-122.html
    5.7 UNIX传统文件系统s5fs的实现 作者:xzh2002 
            http://linux.chinaunix.net/bbs/thread-13214-1-171.html
    5.8 nfs权限 作者:zhaixinshe 
            http://linux.chinaunix.net/bbs/thread-557038-1-174.html .

     

     

     

    6.网络协议栈方面

    6.1 基于2.6.20版本的《Linux内核源码剖析--TCP/IP实现》【样章01 02 03 22 30】 作者:lmarsin
            http://linux.chinaunix.net/bbs/thread-1157659-1-1.html
    6.2 [出版]--基于2.6.26内核的《追踪LINUX TCP/IP代码运行》 作者:qinjiana0786
            http://linux.chinaunix.net/bbs/thread-1064374-1-2.html
    6.3 PF_RING实现分析 作者:独孤九贱
            http://linux.chinaunix.net/bbs/thread-1149919-1-5.html
    6.4 Netfilter 连接跟踪与状态检测的实现 作者:独孤九贱
            http://linux.chinaunix.net/bbs/thread-815129-1-9.html
    6.5 Netfilter之连接跟踪实现机制初步分析 作者:Minit
            http://linux.chinaunix.net/bbs/thread-1057483-1-9.html
    6.6 教你修改以及重构skb 作者:ubuntuer
            http://linux.chinaunix.net/bbs/thread-1152885-1-10.html
    6.7 共享RFC集合,linux网络源码伴侣 作者:lmarsin
            http://linux.chinaunix.net/bbs/thread-1159286-1-11.html
    6.8 关于ptype_all和pypte_base中的pt_prev的说明[转] 作者:Godbach
            http://linux.chinaunix.net/bbs/thread-1160785-1-12.html
    6.9 Linux内核IP Queue机制的分析(三)——ip_queue内核模块的分析 作者:Godbach
            http://linux.chinaunix.net/bbs/thread-1152070-1-17.html
    6.10 udp数据报从网卡驱动到用户空间流程总结 作者:peimichael 
            http://linux.chinaunix.net/bbs/thread-1133017-1-38.html
    6.11 Linux内核发送构造数据包的方式 作者:Godbach 
            http://linux.chinaunix.net/bbs/thread-1133084-1-42.html
    6.12 Netfilter CONNMARK用法及分析(二)-- 内核代码分析 作者:godbach 
            http://linux.chinaunix.net/bbs/thread-1142069-1-44.html
    6.13 [保留] 2.6内核数据包接收流程分析 作者:瀚海书香 
            http://linux.chinaunix.net/bbs/thread-1132965-1-45.html
    6.14 敬告:已完成--基于LINUX内核中的TCP/IP的核心过程分析 作者:qinjiana0786
            http://linux.chinaunix.net/bbs/thread-1049757-1-64.html
    6.15 Netfilter 地址转换的实现 作者:独孤九贱
            http://linux.chinaunix.net/bbs/thread-886488-1-71.html
    6.16 [原]Netfilter实现机制分析 作者:Minit 
            http://linux.chinaunix.net/bbs/thread-1054981-1-78.html
    6.17 Linux内核IP Queue机制的分析(二)——用户态处理并回传数据包 作者:Godbach
            http://linux.chinaunix.net/bbs/thread-1063004-1-82.html
    6.18 网络子系统在链路层的收发过程剖析 作者:rwen2012
            http://linux.chinaunix.net/bbs/thread-886985-1-87.html
    6.19 Netfilter源码分析-我来抛砖,望能引玉 作者:独孤九贱
            http://linux.chinaunix.net/bbs/thread-670248-1-87.html
    6.20 Hacking the Linux Kernel Network Stack(译本) 作者: duanjigang 
            http://linux.chinaunix.net/bbs/thread-758787-1-91.html
    6.21 skbuff解释 - [转贴自CLF,作者:wheelz] 作者:leviathan.alan 
            http://linux.chinaunix.net/bbs/thread-776678-1-124.html
    6.22 如何让 linux 包转发达到 40万pps,尝试中! 作者:sbyond 
            http://linux.chinaunix.net/bbs/thread-641802-1-142.html
    6.23 我自己分析内核tc的一点心得 作者:qtdszws
            http://linux.chinaunix.net/bbs/thread-854814-1-145.html
    6.24 网络代码学习第二部分:网络子系统在IP层的收发过程剖析 作者:rwen2012
            http://linux.chinaunix.net/bbs/thread-888336-1-150.html
    6.25 Netfliter状态跟踪之动态协议的实现浅析(tftp实现) 作者:独孤九贱
            http://linux.chinaunix.net/bbs/thread-841944-1-160.html
    6.26 内核netfilter处理问题(暨packet接受与NAPI介绍) 作者:guotie 
            http://linux.chinaunix.net/bbs/thread-684828-1-200.html

     

     

     

     

     

     

    7. CPU与多核方面

     

    7.1 关于LINUX上中断在各个CPU之间的负载平衡问题 作者:思一克
            http://linux.chinaunix.net/bbs/thread-902244-1-3.html
    7.2 在多核系统上网络数据转发实验和一点思考 作者:独孤九贱
            http://linux.chinaunix.net/bbs/thread-1112413-1-3.html
    7.3 关于 atomic 的话题 作者:mik 
            http://linux.chinaunix.net/bbs/thread-1145097-1-40.html
    7.4 关于AMD TLB bug 作者:crspo 
            http://linux.chinaunix.net/bbs/thread-984846-1-153.html

     

     

     

     

    8. 硬件相关与设备驱动

     

    8.1 [原创] 写一个块设备驱动 作者:OstrichFly
            http://linux.chinaunix.net/bbs/thread-1045283-1-2.html
    8.2 LINUX下USB1.1设备学习小记(更新完毕) 作者:superfight
            http://linux.chinaunix.net/bbs/thread-1067271-1-2.html
    8.3 请教个网卡驱动的问题 作者:VIP_fuck
            http://linux.chinaunix.net/bbs/thread-1158886-1-11.html
    8.4 个人对kobject的一点研究 作者:superfight
            http://linux.chinaunix.net/bbs/thread-1058833-1-12.html
    8.5 RTL8139网卡驱动程序分析[转] 作者:Godbach
            http://linux.chinaunix.net/bbs/thread-1095257-1-14.html
    8.6 Linux那些事儿之我是USB Core——PDF下载 作者:ilttv.cn
            http://linux.chinaunix.net/bbs/thread-913310-1-14.html
    8.7 【原】Linux-千兆网卡驱动实现机制浅析 作者:Minit
            http://linux.chinaunix.net/bbs/thread-1094725-1-17.html
    8.8 利用udev在/dev下动态生成/移除设备文件 作者:albcamus
            http://linux.chinaunix.net/bbs/thread-892777-1-18.html
    8.9 ACPI in Linux - Myths vs. Reality 中文版 作者:albcamus 
            http://linux.chinaunix.net/bbs/thread-903433-1-24.html
    8.10 Intel-E100网卡驱动实例分析 作者:lenn
            http://linux.chinaunix.net/bbs/thread-690741-1-24.html
    8.11 说一说:关于数据传送中 address bus 的工作原理 作者:mik
            http://linux.chinaunix.net/bbs/thread-1145254-1-39.html
    8.12 有谁对网卡DMA有所了解 作者:duanius 
            http://linux.chinaunix.net/bbs/thread-983479-1-49.html
    8.13 [转] linux那些事儿之我是HUB - PDF文件 作者:albcamus
            http://linux.chinaunix.net/bbs/thread-912798-1-57.html
    8.14 网卡驱动注册到PCI总线这一过程的分析 作者: scutan 
            http://linux.chinaunix.net/bbs/thread-1052717-1-59.html
    8.15 PCI驱动的suspend/resume方法,在何时调用? 作者:albcamus 
            http://linux.chinaunix.net/bbs/thread-984759-1-65.html
    8.16 请教e1000中DMA传输的问题 作者:tqkangkang 
            http://linux.chinaunix.net/bbs/thread-896596-1-71.html
    8.17 改写drivers/net/8139too.c 作者:xiongce 
            http://linux.chinaunix.net/bbs/thread-895246-1-72.html
    8.18 字符设备驱动 架构分析 作者:xpl 
            http://linux.chinaunix.net/bbs/thread-1027719-1-82.html
    8.19 看块设备驱动部分的笔记 作者:xpl 
            http://linux.chinaunix.net/bbs/thread-1008997-1-113.html
    8.20 关于iptables中ip_conntrack_max和hash表的关系及调整 作者:NetDC 
            http://linux.chinaunix.net/bbs/thread-596067-1-150.html
    8.21 pci_dma_sync_single_for_cpu到底同步的是什么? 作者:smalloc 
            http://linux.chinaunix.net/bbs/thread-987061-1-151.html
    8.22 关于ROM BIOS的启动问题 作者:daidongly 
            http://linux.chinaunix.net/bbs/thread-979127-1-153.html
    8.23 最近在学习2.6的device model,写了篇学习文档,分享给大家 作者:semiyd 
            http://linux.chinaunix.net/bbs/thread-905104-1-162.html
    8.24 Linux那些事儿之我是U盘 提供pdf格式下载 作者:冷月葬花魂 
            http://linux.chinaunix.net/bbs/thread-905580-1-169.html
    8.25 [转一好文]从 2.4 到 2.6:Linux 内核可装载模块机制的改变对设备驱动的影响 作者:albcamus
            http://linux.chinaunix.net/bbs/thread-700366-1-177.html
    8.26 硬盘扇区的读写函数及其调用路径 作者:思一克 
            http://linux.chinaunix.net/bbs/thread-718919-1-197.html

     

     


    9. 安全相关

     

    9.1 使用 netfilter/iptables 为 Linux(内核 2.4.x )配置防火墙 作者:轩辕砍刀
            http://linux.chinaunix.net/bbs/thread-63898-1-3.html
    9.2 使用kprobes,截获execve系统调用 作者:albcamus
            http://linux.chinaunix.net/bbs/thread-909712-1-8.html
    9.3 Adore-ng-0.56源码分析 作者:ubuntuer
            http://linux.chinaunix.net/bbs/thread-1138561-1-8.html
    9.4 突破linux内核模块验证 作者:W.Z.T
            http://linux.chinaunix.net/bbs/thread-1150719-1-15.html
    9.5 【iptables交流贴】iptables执行的流程分析 作者:Godbach
            http://linux.chinaunix.net/bbs/thread-1022438-1-16.html
    9.6 剖析一个由sendfile引发的linux内核BUG 作者:kouu
            http://linux.chinaunix.net/bbs/thread-1153577-1-16.html
    9.7 Linux堆栈溢出的经典问题,欢迎围观!大牛前进 作者:GoldenSoldier
            http://linux.chinaunix.net/bbs/thread-1145802-1-19.html
    9.8 [欢迎进入讨论] 关于syn-proxy的一些问题 作者:Godbach
            http://linux.chinaunix.net/bbs/thread-1065143-1-21.html
    9.9 新爆内核高危漏洞sock_sendpage的利用分析的讨论 作者: 独孤九贱
            http://linux.chinaunix.net/bbs/thread-1130648-1-21.html
    9.10 Linux下实现劫持系统调用的总结 作者:Godbach
            http://linux.chinaunix.net/bbs/thread-1147025-1-23.html
    9.11 Snort 入侵检测系统源码分析 作者:Godbach 原创作者:独孤九贱
            http://linux.chinaunix.net/bbs/thread-1122507-1-23.html
    9.12 呵呵,我也凑个热闹,转发一个原来写的 iptables 版 DNS 匹配模块 作者:platinum
            http://linux.chinaunix.net/bbs/thread-1149676-1-25.html
    9.13 netlink+netfilter+BloomFilter内核态过滤URL 作者:ubuntuer 
            http://linux.chinaunix.net/bbs/thread-1149519-1-34.html
    9.14 共享:linux arp 欺骗程序 作者:wojiaohesen 
            http://linux.chinaunix.net/bbs/thread-1134584-1-35.html
    9.15 劫持函数调用 作者:ubuntuer 
            http://linux.chinaunix.net/bbs/thread-1148600-1-36.html
    9.16 [原创]关于劫持系统调用隐藏进程的一些心得 作者:g84ch 
            http://linux.chinaunix.net/bbs/thread-1135859-1-38.html
    9.17 Linux内核的加密函数框架 作者:richardhesidu 
            http://linux.chinaunix.net/bbs/thread-1098120-1-56.html
    9.18 Linux-Netfilter&iptables实现机制的分析及应用 作者:Minit 
            http://linux.chinaunix.net/bbs/thread-1117331-1-59.html
    9.19 iptables 源码分析 作者:独孤九贱
            http://linux.chinaunix.net/bbs/thread-663849-1-93.html
    9.20 get system call table in x86-64 Linux - 欢迎测试并报BUG 作者:albcamus
            http://linux.chinaunix.net/bbs/thread-885248-1-100.html 

    展开全文
  • 采用的方式:插入内核模块 使用的方法:遍历进程链表 先在https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=linux-5.3.y&id=d4f3318ed8fab6316cb7a269b8f42306632a3876下载源码,...

    采用的方式:插入内核模块

    使用的方法:遍历进程链表

    先在https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=linux-5.3.y&id=d4f3318ed8fab6316cb7a269b8f42306632a3876 下载源码,用sublim浏览,在include目录下打开头文件。

    下载好源码,解压后,用Sublime File--->OpenFolder打开源码所在目录

    打开后,就会显示类似的目录结构

    在include文件的目录下打开头文件。task_struct结构位于sched.h头文件中。/include/linux/sched.h

    schde.h就显示了pcb在内核中的全貌。涉及的字段非常多。这里只关注pcb本身,能反映器其结构的字段。

    首先看第一个字段thread_info,也就是它的状态信息,

    打印pcb的重要信息,比如状态信息,优先级信息,亲属关系,文件系统信息以及内存方面的信息。

    Makefile

    # Makefile文件注意:加入前面的.c文件起名为first.c,那么这里的Makefile文件中的.o文件就要起名first.o
    # 只有root用户才能加载和卸载模块
    obj-m:=task_struct.o                                     # 产生first模块的目标文件
    #目标文件   文件       要与模块名字相同
    CURRENT_PATH:=$(shell pwd)
    LINUX_KERNEL:=$(shell uname -r)
    LINUX_KERNEL_PATH:=/usr/src/linux-headers-$(LINUX_KERNEL)
    
    all:
    	make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules     # 编译模块
    #[TAB]            内核的路径       当前目录编译完放哪里?    表明编译的是内核模块
    
    clean:
    	make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean     # 清理模块

    task_struct.c

    book@100ask:~/Mooc/CH03$ cat task_struct.c
    #include <linux/kernel.h>
    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/sched.h>   //task结构体
    #include <linux/fdtable.h>      //files
    #include <linux/fs_struct.h>   //fs
    #include <linux/mm_types.h>   //打印内存信息
    #include <linux/init_task.h>   
    
    MODULE_LICENSE("GPL");  //许可证
    
    //入口函数
    static int __init print_pcb(void)    //init宏是由init.h文件所支持
    {
            struct task_struct *task,*p;
            struct list_head *pos;   //双向链表
            int count=0;
    
            printk("begin...\n");
    
            //对链表遍历时,希望从第一个开始
            task=&init_task;  //指向0号进程pcb
    
            list_for_each(pos,&task->tasks) //遍历操作,使用pos指向,传入的参数task指向tasks字段.0号进程的tasks进行遍历。tasks将所有的进程连在一块。
            {
                    p=list_entry(pos,struct task_struct,tasks);    //找到一个节点,就可以用这个节点的tasks字段,找到这个结构体的出口地址.对应的字段tasks
                    //此时的p指针已经指向task_struct结构体的首部,后面就可以通过p指针进行操作
                    count++;  //找到一个进程,自加
                    printk("\n\n");
                    printk("pid: %d; state: %lx; prior: %d; static_pri: %d; parent_pid: %d; count: %d; umask: %d",p->pid,p->state,p->prio,p->static_prio,(p->parent)->pid,(p->files)->count,(p->fs)->umask);
            //linux中内核线程的mm是空的,要对它进行打印,就会出错,指针错误
            if((p->mm)!=NULL)
                    printk("Total_vm: %ld",(p->mm)->total_vm);
    
            }
    
            printk("进程的个数:%d\n",count);
    
            return 0;
    }
    
    static void __exit exit_pcb(void)    //出口函数
    {
            printk("Exiting...\n");
    }
    
    // 指明入口点与出口点,入口/出口点是由module.h支持的
    
    module_init(print_pcb);
    module_exit(exit_pcb);
    
    book@100ask:~/Mooc/CH03$ make
    make -C /usr/src/linux-headers-5.4.0-42-generic M=/home/book/Mooc/CH03 modules     # 编译模块
    make[1]: Entering directory '/usr/src/linux-headers-5.4.0-42-generic'
      CC [M]  /home/book/Mooc/CH03/task_struct.o
    /home/book/Mooc/CH03/task_struct.c: In function ‘print_pcb’:
    /home/book/Mooc/CH03/task_struct.c:30:83: warning: format ‘%d’ expects argument of type ‘int’, but argument 7 has type ‘atomic_t {aka struct <anonymous>}’ [-Wformat=]
       printk("pid: %d; state: %lx; prior: %d; static_pri: %d; parent_pid: %d; count: %d; umask: %d",p->pid,p->state,p->prio,p->static_prio,(p->parent)->pid,(p->files)->count,(p->fs)->umask);
                                                                                      ~^                                                                     ~~~~~~~~~~~~~~~~~
      Building modules, stage 2.
      MODPOST 1 modules
      CC [M]  /home/book/Mooc/CH03/task_struct.mod.o
      LD [M]  /home/book/Mooc/CH03/task_struct.ko
    make[1]: Leaving directory '/usr/src/linux-headers-5.4.0-42-generic'
    book@100ask:~/Mooc/CH03$ ls
    Makefile  modules.order  Module.symvers  task_struct.c  task_struct.ko  task_struct.mod  task_struct.mod.c  task_struct.mod.o  task_struct.o
    book@100ask:~/Mooc/CH03$ make clean
    make -C /usr/src/linux-headers-5.4.0-42-generic M=/home/book/Mooc/CH03 clean     # 清理模块
    make[1]: Entering directory '/usr/src/linux-headers-5.4.0-42-generic'
      CLEAN   /home/book/Mooc/CH03/Module.symvers
    make[1]: Leaving directory '/usr/src/linux-headers-5.4.0-42-generic'
    book@100ask:~/Mooc/CH03$ cat task_struct.c
    #include <linux/kernel.h>
    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/sched.h>   //task结构体
    #include <linux/fdtable.h>      //files
    #include <linux/fs_struct.h>   //fs
    #include <linux/mm_types.h>   //打印内存信息
    #include <linux/init_task.h>   
    #include <linux/types.h>
    #include <linux/atomic.h>
    
    MODULE_LICENSE("GPL");  //许可证
    
    //入口函数
    static int __init print_pcb(void)    //init宏是由init.h文件所支持
    {
            struct task_struct *task,*p;
            struct list_head *pos;   //双向链表
            int count=0;
    
            printk("begin...\n");
    
            //对链表遍历时,希望从第一个开始
            task=&init_task;  //指向0号进程pcb
    
            list_for_each(pos,&task->tasks) //遍历操作,使用pos指向,传入的参数task指向tasks字段.0号进程的tasks进行遍历。tasks将所有的进程连在一块。
            {
                    p=list_entry(pos,struct task_struct,tasks);    //找到一个节点,就可以用这个节点的tasks字段,找到这个结构体的出口地址.对应的字段tasks
                    //此时的p指针已经指向task_struct结构体的首部,后面就可以通过p指针进行操作
                    count++;  //找到一个进程,自加
                    printk("\n\n");
                    printk("pid: %d; state: %lx; prior: %d; static_pri: %d; parent_pid: %d; count: %d; umask: %d",p->pid,p->state,p->prio,p->static_prio,(p->parent)->pid,atomic_read(&(p->files)->count),(p->fs)->umask);
            //linux中内核线程的mm是空的,要对它进行打印,就会出错,指针错误
            if((p->mm)!=NULL)
                    printk("Total_vm: %ld",(p->mm)->total_vm);
    
            }
    
            printk("进程的个数:%d\n",count);
    
            return 0;
    }
    
    static void __exit exit_pcb(void)    //出口函数
    {
            printk("Exiting...\n");
    }
    
    // 指明入口点与出口点,入口/出口点是由module.h支持的
    
    module_init(print_pcb);
    module_exit(exit_pcb);

     

    book@100ask:~/Mooc/CH03$ make
    make -C /usr/src/linux-headers-5.4.0-42-generic M=/home/book/Mooc/CH03 modules     # 编译模块
    make[1]: Entering directory '/usr/src/linux-headers-5.4.0-42-generic'
      CC [M]  /home/book/Mooc/CH03/task_struct.o
      Building modules, stage 2.
      MODPOST 1 modules
      CC [M]  /home/book/Mooc/CH03/task_struct.mod.o
      LD [M]  /home/book/Mooc/CH03/task_struct.ko
    make[1]: Leaving directory '/usr/src/linux-headers-5.4.0-42-generic'

    sudo insmod task_struct.ko  加载内核模块

    dmesg 查看内核打印信息

    
    [ 5751.081752] pid: 1985; state: 1; prior: 120; static_pri: 120; parent_pid: 1847; count: 3; umask: 2
    [ 5751.081752] Total_vm: 49445
    [ 5751.081753] 
    
    [ 5751.081755] pid: 2013; state: 1; prior: 120; static_pri: 120; parent_pid: 1; count: 3; umask: 18
    [ 5751.081755] Total_vm: 79477
    [ 5751.081756] 
    
    [ 5751.081757] pid: 2093; state: 1; prior: 120; static_pri: 120; parent_pid: 1240; count: 3; umask: 2
    [ 5751.081758] Total_vm: 65159
    [ 5751.081758] 
    
    [ 5751.081761] pid: 2509; state: 1; prior: 120; static_pri: 120; parent_pid: 1; count: 1; umask: 2
    [ 5751.081761] Total_vm: 19293
    [ 5751.081761] 
    
    [ 5751.081763] pid: 2510; state: 1; prior: 120; static_pri: 120; parent_pid: 2509; count: 1; umask: 2
    [ 5751.081763] Total_vm: 49029
    [ 5751.081764] 
    
    [ 5751.081765] pid: 2523; state: 1; prior: 120; static_pri: 120; parent_pid: 1; count: 4; umask: 2
    [ 5751.081765] Total_vm: 70315
    [ 5751.081766] 
    
    [ 5751.081767] pid: 2529; state: 1; prior: 120; static_pri: 120; parent_pid: 2093; count: 3; umask: 2
    [ 5751.081768] Total_vm: 51256
    [ 5751.081768] 
    
    [ 5751.081770] pid: 2531; state: 1; prior: 120; static_pri: 120; parent_pid: 2529; count: 2; umask: 18
    [ 5751.081770] Total_vm: 98052
    [ 5751.081771] 
    
    [ 5751.081772] pid: 2536; state: 1; prior: 120; static_pri: 120; parent_pid: 2509; count: 1; umask: 18
    [ 5751.081773] Total_vm: 12817
    [ 5751.081773] 
    
    [ 5751.081775] pid: 2539; state: 1; prior: 120; static_pri: 120; parent_pid: 2529; count: 4; umask: 2
    [ 5751.081776] Total_vm: 174903
    [ 5751.081776] 
    
    [ 5751.081777] pid: 2634; state: 1; prior: 120; static_pri: 120; parent_pid: 2539; count: 1; umask: 2
    [ 5751.081778] Total_vm: 2825
    [ 5751.081778] 
    
    [ 5751.081780] pid: 2663; state: 1; prior: 120; static_pri: 120; parent_pid: 2509; count: 4; umask: 18
    [ 5751.081780] Total_vm: 87322
    [ 5751.081781] 
    
    [ 5751.081813] pid: 2668; state: 1; prior: 120; static_pri: 120; parent_pid: 2663; count: 1; umask: 18
    [ 5751.081814] Total_vm: 12480
    [ 5751.081815] 
    
    [ 5751.081845] pid: 2671; state: 1; prior: 120; static_pri: 120; parent_pid: 2509; count: 3; umask: 18
    [ 5751.081846] Total_vm: 55177
    [ 5751.081846] 
    
    [ 5751.081848] pid: 2690; state: 1; prior: 120; static_pri: 120; parent_pid: 2539; count: 12; umask: 2
    [ 5751.081848] Total_vm: 830957
    [ 5751.081849] 
    
    [ 5751.081851] pid: 2700; state: 1; prior: 120; static_pri: 120; parent_pid: 2509; count: 3; umask: 18
    [ 5751.081851] Total_vm: 71216
    [ 5751.081851] 
    
    [ 5751.081928] pid: 2705; state: 1; prior: 120; static_pri: 120; parent_pid: 2509; count: 6; umask: 18
    [ 5751.081961] Total_vm: 104028
    [ 5751.081962] 
    
    [ 5751.081964] pid: 2721; state: 1; prior: 109; static_pri: 109; parent_pid: 1; count: 4; umask: 18
    [ 5751.081965] Total_vm: 333507
    [ 5751.081965] 
    
    [ 5751.081967] pid: 2753; state: 1; prior: 120; static_pri: 120; parent_pid: 2690; count: 3; umask: 2
    [ 5751.081967] Total_vm: 106998
    [ 5751.081968] 
    
    [ 5751.081969] pid: 2758; state: 1; prior: 120; static_pri: 120; parent_pid: 2753; count: 4; umask: 2
    [ 5751.081970] Total_vm: 68409
    [ 5751.081970] 
    
    [ 5751.081973] pid: 2760; state: 1; prior: 120; static_pri: 120; parent_pid: 1; count: 3; umask: 2
    [ 5751.081973] Total_vm: 84220
    [ 5751.081975] 
    
    [ 5751.081978] pid: 2762; state: 1; prior: 120; static_pri: 120; parent_pid: 2509; count: 3; umask: 18
    [ 5751.081979] Total_vm: 67862
    [ 5751.081981] 
    
    [ 5751.081983] pid: 2800; state: 1; prior: 120; static_pri: 120; parent_pid: 2509; count: 6; umask: 18
    [ 5751.081984] Total_vm: 172441
    [ 5751.081986] 
    
    [ 5751.081990] pid: 2805; state: 1; prior: 120; static_pri: 120; parent_pid: 2509; count: 4; umask: 18
    [ 5751.081991] Total_vm: 324879
    [ 5751.081993] 
    
    [ 5751.081996] pid: 2815; state: 1; prior: 120; static_pri: 120; parent_pid: 2509; count: 4; umask: 18
    [ 5751.081997] Total_vm: 194163
    [ 5751.081999] 
    
    [ 5751.082003] pid: 2823; state: 1; prior: 120; static_pri: 120; parent_pid: 2509; count: 3; umask: 18
    [ 5751.082004] Total_vm: 46976
    [ 5751.082006] 
    
    [ 5751.082007] pid: 2827; state: 1; prior: 120; static_pri: 120; parent_pid: 2509; count: 3; umask: 18
    [ 5751.082009] Total_vm: 74834
    [ 5751.082010] 
    
    [ 5751.082013] pid: 2836; state: 1; prior: 120; static_pri: 120; parent_pid: 2509; count: 4; umask: 18
    [ 5751.082014] Total_vm: 74063
    [ 5751.082017] 
    
    [ 5751.082020] pid: 2841; state: 1; prior: 120; static_pri: 120; parent_pid: 2509; count: 3; umask: 18
    [ 5751.082022] Total_vm: 67190
    [ 5751.082026] 
    
    [ 5751.082030] pid: 2845; state: 1; prior: 120; static_pri: 120; parent_pid: 2509; count: 3; umask: 18
    [ 5751.082031] Total_vm: 66734
    [ 5751.082034] 
    
    [ 5751.082036] pid: 2849; state: 1; prior: 120; static_pri: 120; parent_pid: 2509; count: 4; umask: 18
    [ 5751.082036] Total_vm: 92928
    [ 5751.082037] 
    
    [ 5751.082038] pid: 2854; state: 1; prior: 120; static_pri: 120; parent_pid: 2509; count: 3; umask: 18
    [ 5751.082038] Total_vm: 70388
    [ 5751.082039] 
    
    [ 5751.082041] pid: 2858; state: 1; prior: 120; static_pri: 120; parent_pid: 2539; count: 4; umask: 2
    [ 5751.082041] Total_vm: 127531
    [ 5751.082042] 
    
    [ 5751.082043] pid: 2859; state: 1; prior: 120; static_pri: 120; parent_pid: 2539; count: 3; umask: 2
    [ 5751.082043] Total_vm: 85556
    [ 5751.082043] 
    
    [ 5751.082045] pid: 2862; state: 1; prior: 120; static_pri: 120; parent_pid: 2539; count: 3; umask: 2
    [ 5751.082045] Total_vm: 104059
    [ 5751.082046] 
    
    [ 5751.082047] pid: 2864; state: 1; prior: 120; static_pri: 120; parent_pid: 2539; count: 3; umask: 2
    [ 5751.082048] Total_vm: 67156
    [ 5751.082048] 
    
    [ 5751.082080] pid: 2868; state: 1; prior: 120; static_pri: 120; parent_pid: 2539; count: 4; umask: 2
    [ 5751.082081] Total_vm: 111432
    [ 5751.082081] 
    
    [ 5751.082083] pid: 2872; state: 1; prior: 120; static_pri: 120; parent_pid: 2539; count: 4; umask: 2
    [ 5751.082083] Total_vm: 81439
    [ 5751.082083] 
    
    [ 5751.082085] pid: 2873; state: 1; prior: 120; static_pri: 120; parent_pid: 2539; count: 4; umask: 2
    [ 5751.082085] Total_vm: 121857
    [ 5751.082086] 
    
    [ 5751.082087] pid: 2879; state: 1; prior: 120; static_pri: 120; parent_pid: 2539; count: 5; umask: 2
    [ 5751.082088] Total_vm: 92705
    [ 5751.082088] 
    
    [ 5751.082090] pid: 2887; state: 1; prior: 120; static_pri: 120; parent_pid: 2539; count: 3; umask: 2
    [ 5751.082090] Total_vm: 105343
    [ 5751.082090] 
    
    [ 5751.082092] pid: 2896; state: 1; prior: 120; static_pri: 120; parent_pid: 2539; count: 4; umask: 2
    [ 5751.082092] Total_vm: 67760
    [ 5751.082093] 
    
    [ 5751.082094] pid: 2897; state: 1; prior: 120; static_pri: 120; parent_pid: 2539; count: 3; umask: 2
    [ 5751.082094] Total_vm: 84125
    [ 5751.082095] 
    
    [ 5751.082097] pid: 2898; state: 1; prior: 120; static_pri: 120; parent_pid: 2539; count: 4; umask: 2
    [ 5751.082097] Total_vm: 162918
    [ 5751.082098] 
    
    [ 5751.082099] pid: 2900; state: 1; prior: 120; static_pri: 120; parent_pid: 2539; count: 4; umask: 2
    [ 5751.082100] Total_vm: 115658
    [ 5751.082100] 
    
    [ 5751.082101] pid: 2903; state: 1; prior: 120; static_pri: 120; parent_pid: 2539; count: 4; umask: 2
    [ 5751.082102] Total_vm: 89334
    [ 5751.082102] 
    
    [ 5751.082104] pid: 2904; state: 1; prior: 120; static_pri: 120; parent_pid: 2539; count: 4; umask: 2
    [ 5751.082104] Total_vm: 124862
    [ 5751.082105] 
    
    [ 5751.082106] pid: 2905; state: 1; prior: 120; static_pri: 120; parent_pid: 2539; count: 4; umask: 2
    [ 5751.082107] Total_vm: 268116
    [ 5751.082107] 
    
    [ 5751.082109] pid: 2911; state: 1; prior: 120; static_pri: 120; parent_pid: 2539; count: 4; umask: 2
    [ 5751.082109] Total_vm: 67763
    [ 5751.082109] 
    
    [ 5751.082111] pid: 2932; state: 1; prior: 120; static_pri: 120; parent_pid: 1; count: 3; umask: 2
    [ 5751.082112] Total_vm: 125415
    [ 5751.082112] 
    
    [ 5751.082114] pid: 2956; state: 1; prior: 120; static_pri: 120; parent_pid: 2539; count: 3; umask: 2
    [ 5751.082114] Total_vm: 67983
    [ 5751.082114] 
    
    [ 5751.082116] pid: 2965; state: 1; prior: 120; static_pri: 120; parent_pid: 1; count: 4; umask: 2
    [ 5751.082116] Total_vm: 119454
    [ 5751.082117] 
    
    [ 5751.082118] pid: 2966; state: 1; prior: 120; static_pri: 120; parent_pid: 2539; count: 4; umask: 2
    [ 5751.082118] Total_vm: 229089
    [ 5751.082119] 
    
    [ 5751.082120] pid: 2983; state: 1; prior: 120; static_pri: 120; parent_pid: 2700; count: 3; umask: 18
    [ 5751.082121] Total_vm: 90282
    [ 5751.082121] 
    
    [ 5751.082123] pid: 2999; state: 1; prior: 120; static_pri: 120; parent_pid: 2509; count: 5; umask: 18
    [ 5751.082123] Total_vm: 221251
    [ 5751.082124] 
    
    [ 5751.082156] pid: 3047; state: 1; prior: 120; static_pri: 120; parent_pid: 2999; count: 9; umask: 18
    [ 5751.082156] Total_vm: 263758
    [ 5751.082157] 
    
    [ 5751.082159] pid: 3049; state: 1; prior: 120; static_pri: 120; parent_pid: 2753; count: 3; umask: 2
    [ 5751.082160] Total_vm: 49445
    [ 5751.082160] 
    
    [ 5751.082162] pid: 3066; state: 1; prior: 120; static_pri: 120; parent_pid: 2509; count: 5; umask: 18
    [ 5751.082162] Total_vm: 181428
    [ 5751.082162] 
    
    [ 5751.082164] pid: 3077; state: 1; prior: 120; static_pri: 120; parent_pid: 3066; count: 6; umask: 18
    [ 5751.082165] Total_vm: 252524
    [ 5751.082165] 
    
    [ 5751.082167] pid: 3322; state: 1; prior: 120; static_pri: 120; parent_pid: 2539; count: 4; umask: 2
    [ 5751.082167] Total_vm: 109559
    [ 5751.082167] 
    
    [ 5751.082169] pid: 3324; state: 1; prior: 120; static_pri: 120; parent_pid: 2539; count: 4; umask: 2
    [ 5751.082170] Total_vm: 334283
    [ 5751.082170] 
    
    [ 5751.082172] pid: 3351; state: 1; prior: 120; static_pri: 120; parent_pid: 1; count: 5; umask: 18
    [ 5751.082204] Total_vm: 145759
    [ 5751.082206] 
    
    [ 5751.082208] pid: 3540; state: 1; prior: 120; static_pri: 120; parent_pid: 1; count: 1; umask: 18
    [ 5751.082208] Total_vm: 25147
    [ 5751.082209] 
    
    [ 5751.082210] pid: 3541; state: 1; prior: 120; static_pri: 120; parent_pid: 1; count: 3; umask: 18
    [ 5751.082211] Total_vm: 75882
    [ 5751.082211] 
    
    [ 5751.082213] pid: 3609; state: 1; prior: 120; static_pri: 120; parent_pid: 1140; count: 1; umask: 2
    [ 5751.082214] Total_vm: 26945
    [ 5751.082214] 
    
    [ 5751.082216] pid: 3666; state: 1; prior: 120; static_pri: 120; parent_pid: 2539; count: 4; umask: 2
    [ 5751.082216] Total_vm: 197501
    [ 5751.082216] 
    
    [ 5751.082218] pid: 3746; state: 1; prior: 120; static_pri: 120; parent_pid: 3609; count: 1; umask: 2
    [ 5751.082219] Total_vm: 27519
    [ 5751.082219] 
    
    [ 5751.082221] pid: 3747; state: 1; prior: 120; static_pri: 120; parent_pid: 3746; count: 1; umask: 2
    [ 5751.082221] Total_vm: 5668
    [ 5751.082222] 
    
    [ 5751.082224] pid: 3837; state: 402; prior: 120; static_pri: 120; parent_pid: 2; count: 199; umask: 0
    [ 5751.082224] 
    
    [ 5751.082226] pid: 6105; state: 402; prior: 120; static_pri: 120; parent_pid: 2; count: 199; umask: 0
    [ 5751.082226] 
    
    [ 5751.082227] pid: 6122; state: 402; prior: 120; static_pri: 120; parent_pid: 2; count: 199; umask: 0
    [ 5751.082228] 
    
    [ 5751.082230] pid: 6443; state: 402; prior: 120; static_pri: 120; parent_pid: 2; count: 199; umask: 0
    [ 5751.082230]  //没有打印total_vm,说明它的mm字段为空,是内核线程?
    
    [ 5751.082231] pid: 6859; state: 1; prior: 120; static_pri: 120; parent_pid: 3747; count: 1; umask: 18
    [ 5751.082232] Total_vm: 18034     //说明该进程的线性空间共有18034个页
    [ 5751.082232] 
    
    [ 5751.082234] pid: 6861; state: 1; prior: 120; static_pri: 120; parent_pid: 1; count: 3; umask: 18
    [ 5751.082235] Total_vm: 53708
    [ 5751.082235] 
    
    [ 5751.082236] pid: 6867; state: 0; prior: 120; static_pri: 120; parent_pid: 6859; count: 1; umask: 18
    [ 5751.082237] Total_vm: 1163
    [ 5751.082237] 进程的个数:342    //共342个进程

     

    #include/linux/list.h

    /**
     * list_for_each	-	iterate over a list
     * @pos:	the &struct list_head to use as a loop cursor.
     * @head:	the head for your list.
     */
    #define list_for_each(pos, head) \
    	for (pos = (head)->next; pos != (head); pos = pos->next)
    
    #书写遍历所有进程的代码,此处需要用到list.h这个宏。在list.h中首先用到的是list_for_each,
    遍历的是head链表。遍历到每一个节点时,使用pos指向。具体到某一个节点>
    ,用到list_entry.
    /**
     * list_entry - get the struct for this entry
     * @ptr:	the &struct list_head pointer.
     * @type:	the type of the struct this is embedded in.
     * @member:	the name of the list_head within the struct.
     */
    #define list_entry(ptr, type, member) \
    	container_of(ptr, type, member)
    
    list_entry实际上使用的container_of宏,这个宏中ptr代表的是结构体中member的地址。
    type就是结构体的类型,member就是结构体中的成员。上一步,使用for语句遍历到每一个节点,
    在这个节点,前面所了解到的字段中已经是tasks来连接起来。即可以利用tasks字段来得到当前
    结构体的首地址。之后我们再使用一个指针指向,然后就可以对这个结构体进行打印操作。

     fdtable.h

    struct files_struct {
      /*
       * read mostly part
       */
    	atomic_t count;  //count是原子操作,加1操作,分三步: 1- 从内存中读取数值到寄存器中; 2-寄存器加1  3-存寄存器中返回内存。如果执行过程中发送中断,则会影响到值。需要用到同步机制。
    	bool resize_in_progress;
    	wait_queue_head_t resize_wait;
    
    	struct fdtable __rcu *fdt;
    	struct fdtable fdtab;
      /*
       * written part on a separate cache line in SMP
       */
    	spinlock_t file_lock ____cacheline_aligned_in_smp;
    	unsigned int next_fd;
    	unsigned long close_on_exec_init[1];
    	unsigned long open_fds_init[1];
    	unsigned long full_fds_bits_init[1];
    	struct file __rcu * fd_array[NR_OPEN_DEFAULT];
    };

    原子的操作,都在atomic.h文件中。 

    ​
    struct task_struct {
    #ifdef CONFIG_THREAD_INFO_IN_TASK
    	/*
    	 * For reasons of header soup (see current_thread_info()), this
    	 * must be the first element of task_struct.
    	 */
    	struct thread_info		thread_info;
    #endif
    	/* -1 unrunnable, 0 runnable, >0 stopped: */   //状态信息
    	volatile long			state;
    
    	/*
    	 * This begins the randomizable portion of task_struct. Only
    	 * scheduling-critical items should be added above here.
    	 */
    	randomized_struct_fields_start
    
    	void				*stack;
    	refcount_t			usage;
    	/* Per task flags (PF_*), defined further below: */ //内核栈
    	unsigned int			flags;     //标计
    	unsigned int			ptrace;    //主要用于断点调试
    
    #ifdef CONFIG_SMP
    	struct llist_node		wake_entry;
    	int				on_cpu;
    #ifdef CONFIG_THREAD_INFO_IN_TASK
    	/* Current CPU: */
    	unsigned int			cpu;
    #endif
    	unsigned int			wakee_flips;
    	unsigned long			wakee_flip_decay_ts;
    	struct task_struct		*last_wakee;
    
    	/*
    	 * recent_used_cpu is initially set as the last CPU used by a task
    	 * that wakes affine another task. Waker/wakee relationships can
    	 * push tasks around a CPU where each wakeup moves to the next one.
    	 * Tracking a recently used CPU allows a quick search for a recently
    	 * used CPU that may be idle.
    	 */
    	int				recent_used_cpu;
    	int				wake_cpu;
    #endif
    	int				on_rq;
    
    	int				prio;                                //优先级信息,动态优先级
    	int				static_prio;                         //静态优先级
    	int				normal_prio;
    	unsigned int			rt_priority;                 //实时优先级
    
    	const struct sched_class	*sched_class;
    	struct sched_entity		se;
    	struct sched_rt_entity		rt;
    #ifdef CONFIG_CGROUP_SCHED
    	struct task_group		*sched_task_group;
    #endif
    	struct sched_dl_entity		dl;
    
    #ifdef CONFIG_UCLAMP_TASK
    	/* Clamp values requested for a scheduling entity */
    	struct uclamp_se		uclamp_req[UCLAMP_CNT];
    	/* Effective clamp values used for a scheduling entity */
    	struct uclamp_se		uclamp[UCLAMP_CNT];
    #endif
    
    #ifdef CONFIG_PREEMPT_NOTIFIERS
    	/* List of struct preempt_notifier: */
    	struct hlist_head		preempt_notifiers;
    #endif
    
    #ifdef CONFIG_BLK_DEV_IO_TRACE
    	unsigned int			btrace_seq;
    #endif
    
    	unsigned int			policy;      //进程调度策略
    	int				nr_cpus_allowed;
    	const cpumask_t			*cpus_ptr;
    	cpumask_t			cpus_mask;
    
    #ifdef CONFIG_PREEMPT_RCU
    	int				rcu_read_lock_nesting;
    	union rcu_special		rcu_read_unlock_special;
    	struct list_head		rcu_node_entry;
    	struct rcu_node			*rcu_blocked_node;
    #endif /* #ifdef CONFIG_PREEMPT_RCU */
    
    #ifdef CONFIG_TASKS_RCU
    	unsigned long			rcu_tasks_nvcsw;
    	u8				rcu_tasks_holdout;
    	u8				rcu_tasks_idx;
    	int				rcu_tasks_idle_cpu;
    	struct list_head		rcu_tasks_holdout_list;
    #endif /* #ifdef CONFIG_TASKS_RCU */
    
    	struct sched_info		sched_info;        //调度器统计进程的运行信息
    
    	struct list_head		tasks;             //tasks字段是一个双向链表,正是这个字段将所有的进程连在一块,然后才能对进程进行遍历。
    #ifdef CONFIG_SMP
    	struct plist_node		pushable_tasks;
    	struct rb_node			pushable_dl_tasks;
    #endif
    
    	struct mm_struct		*mm;     //线性地址的所有信息
    	struct mm_struct		*active_mm;    //最后访问的地址空间指针
    
    	/* Per-thread vma caching: */
    	struct vmacache			vmacache;
    
    #ifdef SPLIT_RSS_COUNTING
    	struct task_rss_stat		rss_stat;
    #endif
    	int				exit_state;                //判断标志
    	int				exit_code;                 //进程终止代号
    	int				exit_signal;
    	/* The signal sent when the parent dies: */
    	int				pdeath_signal;
    	/* JOBCTL_*, siglock protected: */
    	unsigned long			jobctl;
    
    	/* Used for emulating ABI behavior of previous Linux versions: */
    	unsigned int			personality;
    
    	/* Scheduler bits, serialized by scheduler locks: */
    	unsigned			sched_reset_on_fork:1;
    	unsigned			sched_contributes_to_load:1;
    	unsigned			sched_migrated:1;
    	unsigned			sched_remote_wakeup:1;
    #ifdef CONFIG_PSI
    	unsigned			sched_psi_wake_requeue:1;
    #endif
    
    	/* Force alignment to the next boundary: */
    	unsigned			:0;
    
    	/* Unserialized, strictly 'current' */
    
    	/* Bit to tell LSMs we're in execve(): */
    	unsigned			in_execve:1;
    	unsigned			in_iowait:1;
    #ifndef TIF_RESTORE_SIGMASK
    	unsigned			restore_sigmask:1;
    #endif
    #ifdef CONFIG_MEMCG
    	unsigned			in_user_fault:1;
    #endif
    #ifdef CONFIG_COMPAT_BRK
    	unsigned			brk_randomized:1;
    #endif
    #ifdef CONFIG_CGROUPS
    	/* disallow userland-initiated cgroup migration */
    	unsigned			no_cgroup_migration:1;
    	/* task is frozen/stopped (used by the cgroup freezer) */
    	unsigned			frozen:1;
    #endif
    #ifdef CONFIG_BLK_CGROUP
    	/* to be used once the psi infrastructure lands upstream. */
    	unsigned			use_memdelay:1;
    #endif
    
    	unsigned long			atomic_flags; /* Flags requiring atomic access. */
    
    	struct restart_block		restart_block;
    
    	pid_t				pid;     //进程标识符
    	pid_t				tgid;
    
    #ifdef CONFIG_STACKPROTECTOR
    	/* Canary value for the -fstack-protector GCC feature: */
    	unsigned long			stack_canary;
    #endif
    	/*
    	 * Pointers to the (original) parent process, youngest child, younger sibling,
    	 * older sibling, respectively.  (p->father can be replaced with
    	 * p->real_parent->pid)
    	 */
    
    	/* Real parent process: */
    	struct task_struct __rcu	*real_parent;           //进程的亲属关系
    
    	/* Recipient of SIGCHLD, wait4() reports: */
    	struct task_struct __rcu	*parent;
    
    	/*
    	 * Children/sibling form the list of natural children:
    	 */
    	struct list_head		children;
    	struct list_head		sibling;
    	struct task_struct		*group_leader;
    
    	/*
    	 * 'ptraced' is the list of tasks this task is using ptrace() on.
    	 *
    	 * This includes both natural children and PTRACE_ATTACH targets.
    	 * 'ptrace_entry' is this task's link on the p->parent->ptraced list.
    	 */
    	struct list_head		ptraced;
    	struct list_head		ptrace_entry;
    
    	/* PID/PID hash table linkage. */
    	struct pid			*thread_pid;
    	struct hlist_node		pid_links[PIDTYPE_MAX];
    	struct list_head		thread_group;
    	struct list_head		thread_node;
    
    	struct completion		*vfork_done;
    
    	/* CLONE_CHILD_SETTID: */
    	int __user			*set_child_tid;
    
    	/* CLONE_CHILD_CLEARTID: */
    	int __user			*clear_child_tid;
    
    	u64				utime;
    	u64				stime;
    #ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME
    	u64				utimescaled;
    	u64				stimescaled;
    #endif
    	u64				gtime;
    	struct prev_cputime		prev_cputime;
    #ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
    	struct vtime			vtime;
    #endif
    
    #ifdef CONFIG_NO_HZ_FULL
    	atomic_t			tick_dep_mask;
    #endif
    	/* Context switch counts: */
    	unsigned long			nvcsw;      //这两个字段是用来反映上下文切换的次数,其中nvcsw反映主动上下文切换的次数;
    	unsigned long			nivcsw;      //nivcsw反映被动上下文切换的次数
    
    	/* Monotonic time in nsecs: */
    	u64				start_time;
    
    	/* Boot based time in nsecs: */
    	u64				real_start_time;
    
    	/* MM fault and swap info: this can arguably be seen as either mm-specific or thread-specific: */
    	unsigned long			min_flt;     //缺页统计
    	unsigned long			maj_flt;
    
    #ifdef CONFIG_POSIX_TIMERS
    	struct task_cputime		cputime_expires;
    	struct list_head		cpu_timers[3];
    #endif
    
    	/* Process credentials: */
    
    	/* Tracer's credentials at attach: */
    	const struct cred __rcu		*ptracer_cred;
    
    	/* Objective and real subjective task credentials (COW): */
    	const struct cred __rcu		*real_cred;
    
    	/* Effective (overridable) subjective task credentials (COW): */
    	const struct cred __rcu		*cred;
    
    #ifdef CONFIG_KEYS
    	/* Cached requested key. */
    	struct key			*cached_requested_key;
    #endif
    
    	/*
    	 * executable name, excluding path.
    	 *
    	 * - normally initialized setup_new_exec()
    	 * - access it with [gs]et_task_comm()
    	 * - lock it with task_lock()
    	 */
    	char				comm[TASK_COMM_LEN];  //该数组是相应程序的名字
    
    	struct nameidata		*nameidata;
    
    #ifdef CONFIG_SYSVIPC
    	struct sysv_sem			sysvsem;    //如下两个字段负责进程间通信
    	struct sysv_shm			sysvshm;
    #endif
    #ifdef CONFIG_DETECT_HUNG_TASK
    	unsigned long			last_switch_count;
    	unsigned long			last_switch_time;
    #endif
    	/* Filesystem information: */
    	struct fs_struct		*fs;     //文件信息,fs保持指向文件信息的指针
    
    	/* Open file information: */
    	struct files_struct		*files;  //保存指向进程的文件,描述表的指针
    
    	/* Namespaces: */
    	struct nsproxy			*nsproxy;  //命名空间
    
    	/* Signal handlers: */
    	struct signal_struct		*signal;   //信号描述符
    	struct sighand_struct		*sighand;
    	sigset_t			blocked;
    	sigset_t			real_blocked;
    	/* Restored if set_restore_sigmask() was used: */
    	sigset_t			saved_sigmask;
    	struct sigpending		pending;
    	unsigned long			sas_ss_sp;
    	size_t				sas_ss_size;
    	unsigned int			sas_ss_flags;
    
    	struct callback_head		*task_works;
    
    #ifdef CONFIG_AUDIT
    #ifdef CONFIG_AUDITSYSCALL
    	struct audit_context		*audit_context;
    #endif
    	kuid_t				loginuid;
    	unsigned int			sessionid;
    #endif
    	struct seccomp			seccomp;
    
    	/* Thread group tracking: */
    	u32				parent_exec_id;
    	u32				self_exec_id;
    
    	/* Protection against (de-)allocation: mm, files, fs, tty, keyrings, mems_allowed, mempolicy: */
    	spinlock_t			alloc_lock;
    
    	/* Protection of the PI data structures: */
    	raw_spinlock_t			pi_lock;
    
    	struct wake_q_node		wake_q;
    
    #ifdef CONFIG_RT_MUTEXES
    	/* PI waiters blocked on a rt_mutex held by this task: */
    	struct rb_root_cached		pi_waiters;
    	/* Updated under owner's pi_lock and rq lock */
    	struct task_struct		*pi_top_task;
    	/* Deadlock detection and priority inheritance handling: */
    	struct rt_mutex_waiter		*pi_blocked_on;
    #endif
    
    #ifdef CONFIG_DEBUG_MUTEXES
    	/* Mutex deadlock detection: */
    	struct mutex_waiter		*blocked_on;
    #endif
    
    #ifdef CONFIG_TRACE_IRQFLAGS
    	unsigned int			irq_events;       //irq
    	unsigned long			hardirq_enable_ip;
    	unsigned long			hardirq_disable_ip;
    	unsigned int			hardirq_enable_event;
    	unsigned int			hardirq_disable_event;
    	int				hardirqs_enabled;
    	int				hardirq_context;
    	unsigned long			softirq_disable_ip;
    	unsigned long			softirq_enable_ip;
    	unsigned int			softirq_disable_event;
    	unsigned int			softirq_enable_event;
    	int				softirqs_enabled;
    	int				softirq_context;
    #endif
    
    #ifdef CONFIG_LOCKDEP
    # define MAX_LOCK_DEPTH			48UL
    	u64				curr_chain_key;
    	int				lockdep_depth;
    	unsigned int			lockdep_recursion;
    	struct held_lock		held_locks[MAX_LOCK_DEPTH];
    #endif
    
    #ifdef CONFIG_UBSAN
    	unsigned int			in_ubsan;
    #endif
    
    	/* Journalling filesystem info: */
    	void				*journal_info;
    
    	/* Stacked block device info: */
    	struct bio_list			*bio_list;
    
    #ifdef CONFIG_BLOCK
    	/* Stack plugging: */
    	struct blk_plug			*plug;
    #endif
    
    	/* VM state: */
    	struct reclaim_state		*reclaim_state;    //内存回收
    
    	struct backing_dev_info		*backing_dev_info;
    
    	struct io_context		*io_context;    //记录进程的io计数
    
    #ifdef CONFIG_COMPACTION
    	struct capture_control		*capture_control;
    #endif
    	/* Ptrace state: */
    	unsigned long			ptrace_message;
    	kernel_siginfo_t		*last_siginfo;
    
    	struct task_io_accounting	ioac;
    #ifdef CONFIG_PSI
    	/* Pressure stall state */
    	unsigned int			psi_flags;
    #endif
    #ifdef CONFIG_TASK_XACCT
    	/* Accumulated RSS usage: */
    	u64				acct_rss_mem1;
    	/* Accumulated virtual memory usage: */
    	u64				acct_vm_mem1;
    	/* stime + utime since last update: */
    	u64				acct_timexpd;
    #endif
    #ifdef CONFIG_CPUSETS
    	/* Protected by ->alloc_lock: */
    	nodemask_t			mems_allowed;
    	/* Seqence number to catch updates: */
    	seqcount_t			mems_allowed_seq;
    	int				cpuset_mem_spread_rotor;
    	int				cpuset_slab_spread_rotor;
    #endif
    #ifdef CONFIG_CGROUPS
    	/* Control Group info protected by css_set_lock: */
    	struct css_set __rcu		*cgroups;
    	/* cg_list protected by css_set_lock and tsk->alloc_lock: */
    	struct list_head		cg_list;
    #endif
    #ifdef CONFIG_X86_CPU_RESCTRL
    	u32				closid;
    	u32				rmid;
    #endif
    #ifdef CONFIG_FUTEX
    	struct robust_list_head __user	*robust_list;
    #ifdef CONFIG_COMPAT
    	struct compat_robust_list_head __user *compat_robust_list;
    #endif
    	struct list_head		pi_state_list;
    	struct futex_pi_state		*pi_state_cache;
    #endif
    #ifdef CONFIG_PERF_EVENTS
    	struct perf_event_context	*perf_event_ctxp[perf_nr_task_contexts];
    	struct mutex			perf_event_mutex;
    	struct list_head		perf_event_list;
    #endif
    #ifdef CONFIG_DEBUG_PREEMPT
    	unsigned long			preempt_disable_ip;
    #endif
    #ifdef CONFIG_NUMA
    	/* Protected by alloc_lock: */
    	struct mempolicy		*mempolicy;
    	short				il_prev;
    	short				pref_node_fork;
    #endif
    #ifdef CONFIG_NUMA_BALANCING
    	int				numa_scan_seq;
    	unsigned int			numa_scan_period;
    	unsigned int			numa_scan_period_max;
    	int				numa_preferred_nid;
    	unsigned long			numa_migrate_retry;
    	/* Migration stamp: */
    	u64				node_stamp;
    	u64				last_task_numa_placement;
    	u64				last_sum_exec_runtime;
    	struct callback_head		numa_work;
    
    	/*
    	 * This pointer is only modified for current in syscall and
    	 * pagefault context (and for tasks being destroyed), so it can be read
    	 * from any of the following contexts:
    	 *  - RCU read-side critical section
    	 *  - current->numa_group from everywhere
    	 *  - task's runqueue locked, task not running
    	 */
    	struct numa_group __rcu		*numa_group;
    
    	/*
    	 * numa_faults is an array split into four regions:
    	 * faults_memory, faults_cpu, faults_memory_buffer, faults_cpu_buffer
    	 * in this precise order.
    	 *
    	 * faults_memory: Exponential decaying average of faults on a per-node
    	 * basis. Scheduling placement decisions are made based on these
    	 * counts. The values remain static for the duration of a PTE scan.
    	 * faults_cpu: Track the nodes the process was running on when a NUMA
    	 * hinting fault was incurred.
    	 * faults_memory_buffer and faults_cpu_buffer: Record faults per node
    	 * during the current scan window. When the scan completes, the counts
    	 * in faults_memory and faults_cpu decay and these values are copied.
    	 */
    	unsigned long			*numa_faults;
    	unsigned long			total_numa_faults;
    
    	/*
    	 * numa_faults_locality tracks if faults recorded during the last
    	 * scan window were remote/local or failed to migrate. The task scan
    	 * period is adapted based on the locality of the faults with different
    	 * weights depending on whether they were shared or private faults
    	 */
    	unsigned long			numa_faults_locality[3];
    
    	unsigned long			numa_pages_migrated;
    #endif /* CONFIG_NUMA_BALANCING */
    
    #ifdef CONFIG_RSEQ
    	struct rseq __user *rseq;
    	u32 rseq_sig;
    	/*
    	 * RmW on rseq_event_mask must be performed atomically
    	 * with respect to preemption.
    	 */
    	unsigned long rseq_event_mask;
    #endif
    
    	struct tlbflush_unmap_batch	tlb_ubc;
    
    	struct rcu_head			rcu;
    
    	/* Cache last used pipe for splice(): */
    	struct pipe_inode_info		*splice_pipe;
    
    	struct page_frag		task_frag;
    
    #ifdef CONFIG_TASK_DELAY_ACCT
    	struct task_delay_info		*delays;
    #endif
    
    #ifdef CONFIG_FAULT_INJECTION
    	int				make_it_fail;
    	unsigned int			fail_nth;
    #endif
    	/*
    	 * When (nr_dirtied >= nr_dirtied_pause), it's time to call
    	 * balance_dirty_pages() for a dirty throttling pause:
    	 */
    	int				nr_dirtied;
    	int				nr_dirtied_pause;
    	/* Start of a write-and-pause period: */
    	unsigned long			dirty_paused_when;
    
    #ifdef CONFIG_LATENCYTOP
    	int				latency_record_count;
    	struct latency_record		latency_record[LT_SAVECOUNT];
    #endif
    	/*
    	 * Time slack values; these are used to round up poll() and
    	 * select() etc timeout values. These are in nanoseconds.
    	 */
    	u64				timer_slack_ns;
    	u64				default_timer_slack_ns;
    
    #ifdef CONFIG_KASAN
    	unsigned int			kasan_depth;
    #endif
    
    #ifdef CONFIG_FUNCTION_GRAPH_TRACER
    	/* Index of current stored address in ret_stack: */
    	int				curr_ret_stack;
    	int				curr_ret_depth;
    
    	/* Stack of return addresses for return function tracing: */
    	struct ftrace_ret_stack		*ret_stack;
    
    	/* Timestamp for last schedule: */
    	unsigned long long		ftrace_timestamp;
    
    	/*
    	 * Number of functions that haven't been traced
    	 * because of depth overrun:
    	 */
    	atomic_t			trace_overrun;
    
    	/* Pause tracing: */
    	atomic_t			tracing_graph_pause;
    #endif
    
    #ifdef CONFIG_TRACING
    	/* State flags for use by tracers: */
    	unsigned long			trace;
    
    	/* Bitmask and counter of trace recursion: */
    	unsigned long			trace_recursion;
    #endif /* CONFIG_TRACING */
    
    #ifdef CONFIG_KCOV
    	/* Coverage collection mode enabled for this task (0 if disabled): */
    	unsigned int			kcov_mode;
    
    	/* Size of the kcov_area: */
    	unsigned int			kcov_size;
    
    	/* Buffer for coverage collection: */
    	void				*kcov_area;
    
    	/* KCOV descriptor wired with this task or NULL: */
    	struct kcov			*kcov;
    #endif
    
    #ifdef CONFIG_MEMCG
    	struct mem_cgroup		*memcg_in_oom;
    	gfp_t				memcg_oom_gfp_mask;
    	int				memcg_oom_order;
    
    	/* Number of pages to reclaim on returning to userland: */
    	unsigned int			memcg_nr_pages_over_high;
    
    	/* Used by memcontrol for targeted memcg charge: */
    	struct mem_cgroup		*active_memcg;
    #endif
    
    #ifdef CONFIG_BLK_CGROUP
    	struct request_queue		*throttle_queue;
    #endif
    
    #ifdef CONFIG_UPROBES
    	struct uprobe_task		*utask;
    #endif
    #if defined(CONFIG_BCACHE) || defined(CONFIG_BCACHE_MODULE)
    	unsigned int			sequential_io;
    	unsigned int			sequential_io_avg;
    #endif
    #ifdef CONFIG_DEBUG_ATOMIC_SLEEP
    	unsigned long			task_state_change;
    #endif
    	int				pagefault_disabled;
    #ifdef CONFIG_MMU
    	struct task_struct		*oom_reaper_list;
    #endif
    #ifdef CONFIG_VMAP_STACK
    	struct vm_struct		*stack_vm_area;
    #endif
    #ifdef CONFIG_THREAD_INFO_IN_TASK
    	/* A live task holds one reference: */
    	refcount_t			stack_refcount;
    #endif
    #ifdef CONFIG_LIVEPATCH
    	int patch_state;
    #endif
    #ifdef CONFIG_SECURITY
    	/* Used by LSM modules for access restriction: */
    	void				*security;
    #endif
    
    #ifdef CONFIG_GCC_PLUGIN_STACKLEAK
    	unsigned long			lowest_stack;
    	unsigned long			prev_lowest_stack;
    #endif
    
    	/*
    	 * New fields for task_struct should be added above here, so that
    	 * they are included in the randomized portion of task_struct.
    	 */
    	randomized_struct_fields_end
    
    	/* CPU-specific state of this task: */
    	struct thread_struct		thread;
    
    	/*
    	 * WARNING: on x86, 'thread_struct' contains a variable-sized
    	 * structure.  It *MUST* be at the end of 'task_struct'.
    	 *
    	 * Do not put anything below here!
    	 */
    };
    
    ​

     

    展开全文
  • 这个题目取得好,好像底层离我们越来越远了,因为内核在一步一步脱壳,很快漂亮的形状就会展现在我们眼前,在这之前,我们得屏气凝神,静静地等待这一时刻的到来。进入真实内核的第一个文件是arch/x86/kernel/...

    这个题目取得好,好像底层离我们越来越远了,因为内核在一步一步脱壳,很快漂亮的形状就会展现在我们眼前,在这之前,我们得屏气凝神,静静地等待这一时刻的到来。进入真实内核的第一个文件是arch/x86/kernel/head_32.S。

    /*
     * 32-bit kernel entrypoint; only used by the boot CPU.  On entry,
     * %esi points to the real-mode code as a 32-bit pointer.
     * CS and DS must be 4 GB flat segments, but we don't depend on
     * any particular GDT layout, because we load our own as soon as we
     * can.
     */
    __HEAD
    ENTRY(startup_32)
        /* test KEEP_SEGMENTS flag to see if the bootloader is asking
            us to not reload segments */
        testb $(1<<6), BP_loadflags(%esi)    # 这个标志见过,询问是否重新加载一遍段寄存器
        jnz 2f

    /*
     * Set segments to known values.
     */
        lgdt pa(boot_gdt_descr)     # boot_gdt_descr在下面数据区中有设置,记载GDT表首地址
        movl $(__BOOT_DS),%eax
        movl %eax,%ds
        movl %eax,%es
        movl %eax,%fs
        movl %eax,%gs
    2:

    /*
     * Clear BSS first so that there are no surprises...
     */
    # 将bss段清0
        cld             /*di,si ++*/
        xorl %eax,%eax
        movl $pa(__bss_start),%edi
        movl $pa(__bss_stop),%ecx
        subl %edi,%ecx
        shrl $2,%ecx
        rep ; stosl
    /*
     * Copy bootup parameters out of the way.
     * Note: %esi still has the pointer to the real-mode data.
     * With the kexec as boot loader, parameter segment might be loaded beyond
     * kernel image and might not even be addressable by early boot page tables.
     * (kexec on panic case). Hence copy out the parameters before initializing
     * page tables.
     */
    # 拷贝实模式中的boot_params结构体
        movl $pa(boot_params),%edi
        movl $(PARAM_SIZE/4),%ecx    /*PARAM_SIZE ==struct boot_params*/
        cld
        rep
        movsl           /*ds:esi copy to es:edi*/
    # 拷贝命令行参数到boot_command_line
    # 得到命令行参数地址
        movl pa(boot_params) + NEW_CL_POINTER,%esi  /*boot_params->hdr.cmd_line_ptr*/
        andl %esi,%esi                               /*test if point is null*/ # 检查指针是否为空
        jz 1f            # No comand line
        movl $pa(boot_command_line),%edi        /*in the init/main.c*/
        movl $(COMMAND_LINE_SIZE/4),%ecx
        rep
        movsl
    1:
    # 不用管
    #ifdef CONFIG_OLPC_OPENFIRMWARE         /*firmware*/
        /* save OFW's pgdir table for later use when calling into OFW */
        movl %cr3, %eax
        movl %eax, pa(olpc_ofw_pgd)
    #endif
    # 虚拟环境,直接飘过~
    #ifdef CONFIG_PARAVIRT          /*virtual environment*/
        /* This is can only trip for a broken bootloader... */
        cmpw $0x207, pa(boot_params + BP_version)
        jb default_entry

        /* Paravirt-compatible boot parameters.  Look to see what architecture
            we're booting under. */
        movl pa(boot_params + BP_hardware_subarch), %eax
        cmpl $num_subarch_entries, %eax
        jae bad_subarch         /*if eax >= num_subarch_entries*/

        movl pa(subarch_entries)(,%eax,4), %eax   /*eax=subarch_entries+eax*4*/
        subl $__PAGE_OFFSET, %eax
        jmp *%eax

    bad_subarch:
    WEAK(lguest_entry)
    WEAK(xen_entry)
        /* Unknown implementation; there's really
           nothing we can do at this point. */
        ud2a

        __INITDATA

    subarch_entries:
        .long default_entry        /* normal x86/PC */     /*if hardware_subarch=0*/
        .long lguest_entry        /* lguest hypervisor */  /*0x00000001*/
        .long xen_entry            /* Xen hypervisor */     /*0x00000002*/
        .long default_entry        /* Moorestown MID */
    num_subarch_entries = (. - subarch_entries) / 4
    .previous
    #endif /* CONFIG_PARAVIRT */

    /*
     * Initialize page tables.  This creates a PDE and a set of page
     * tables, which are located immediately beyond __brk_base.  The variable
     * _brk_end is set up to point to the first "safe" location.
     * Mappings are created both at virtual address 0 (identity mapping)
     * and PAGE_OFFSET for up to _end.
     *
     * Note that the stack is not yet set up!
     */
    # 这段非常关键,之前的保护模式是没有分页功能的,这段就是设置全局页目录和页表项
    # 然后开启分页机制
    default_entry:
    # 如果启用了PAE,也就是物理地址扩展,变成64G,这里不用考虑
    #ifdef CONFIG_X86_PAE           /*physical address extend , 64G */

        /*
         * In PAE mode swapper_pg_dir is statically defined to contain enough
         * entries to cover the VMSPLIT option (that is the top 1, 2 or 3
         * entries). The identity mapping is handled by pointing two PGD
         * entries to the first kernel PMD.
         *
         * Note the upper half of each PMD or PTE are always zero at
         * this stage.
         */

    #define KPMDS (((-__PAGE_OFFSET) >> 30) & 3) /* Number of kernel PMDs */
                    /*__PAGE_OFFSET = 0xc0000000*/
        xorl %ebx,%ebx                /* %ebx is kept at zero */

        movl $pa(__brk_base), %edi
        movl $pa(swapper_pg_pmd), %edx
        movl $PTE_IDENT_ATTR, %eax
    10:
        leal PDE_IDENT_ATTR(%edi),%ecx        /* Create PMD entry */
        movl %ecx,(%edx)            /* Store PMD entry */
                            /* Upper half already zero */
        addl $8,%edx
        movl $512,%ecx
    11:
        stosl
        xchgl %eax,%ebx
        stosl
        xchgl %eax,%ebx
        addl $0x1000,%eax
        loop 11b

        /*
         * End condition: we must map up to the end + MAPPING_BEYOND_END.
         */
        movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp
        cmpl %ebp,%eax
        jb 10b
    1:
        addl $__PAGE_OFFSET, %edi
        movl %edi, pa(_brk_end)
        shrl $12, %eax
        movl %eax, pa(max_pfn_mapped)

        /* Do early initialization of the fixmap area */
        movl $pa(swapper_pg_fixmap)+PDE_IDENT_ATTR,%eax
        movl %eax,pa(swapper_pg_pmd+0x1000*KPMDS-8)
    #else    /* Not PAE */

    # 如果没有启用PAE,那么线性地址为4G,一般都属于这里
                            /*4G physical address*/
    # 这个很重要,内核的线性地址偏移
    # 我们知道在liunx中,进程空间为0-3G,高1G是内核空间使用的
    # 也就是3G之后
    # 这里的这个偏移是相对于全局页目录的,全局页目录大小为4k,每项大小为4b
    # 每项可以表示4M的线性范围
    # 因此这个偏移3k刚好就是3G,3k/4*4M=3G。
    page_pde_offset = (__PAGE_OFFSET >> 20);   /*0xc00= 3k , PGD(3k)=3G*/

    # 这里的这个__brk_base在文件vmlinux.lds.S中,链接后,表示页表的首地址
    . = ALIGN(PAGE_SIZE);
        .brk : AT(ADDR(.brk) - LOAD_OFFSET) {
            __brk_base = .;
            . += 64 * 1024;        /* 64k alignment slop space */
            *(.brk_reservation)    /* areas brk users have reserved */
            __brk_limit = .;
        }

        _end = .;
    # 可以看到总大小为64k,也就是说可以设置线性地址64M
        movl $pa(__brk_base), %edi             /*__brk_base==PTD*/
        movl $pa(swapper_pg_dir), %edx    # 全局页目录地址
    # 这个宏只是个属性而已
    # 不管是全局页目录项还是页表项都是4B
    # 4B中最后12位来表示属性
        movl $PTE_IDENT_ATTR, %eax              /*PTE_IDENT_ATTR= 0x00000067*/
    10:
    # 外循环是填充全局页目录项的
    # edi为页表首地址
        leal PDE_IDENT_ATTR(%edi),%ecx        /* Create PDE entry */
    # 将计算出的页目录项填充到全局页目录中
    # edx表示全局页目录地址
        movl %ecx,(%edx)            /* Store identity PDE entry */
        movl %ecx,page_pde_offset(%edx)        /* Store kernel PDE entry */
    # 填充下一个全局页目录项
        addl $4,%edx
        movl $1024, %ecx
    11:                     /*fill 4k PTD*/
    # 内循环填充页表
    # edi为页表地址,eax为页表项
        stosl           /*es:edi= eax,edi++*/
        addl $0x1000,%eax  # 注意理解这里的0x1000,后12位为属性,前20位为页地址,4k对齐
        loop 11b
        /*
         * End condition: we must map up to the end + MAPPING_BEYOND_END.
         */  /*_end-__brk_base = 64k*/
    # 如果64k页表还没用完,那么继续,eax表示当前页表地址(当然包括了属性)
    # 都忽略属性标志,则eax表示在__brk_base中的偏移/4
    # 这里没有看懂MAPPING_BEYOND_END
    # 这个在上面定义的,我计算了一下为0x0c400000
    # 不过这里好像有些不对,不过看程序没有影响,就是判断是否还有页表可以设置
        movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp
        cmpl %ebp,%eax
        jb 10b          /*if eax < ebp jump*/
    # 将页表末尾的线性地址存入_brk_end变量中
        addl $__PAGE_OFFSET, %edi
        movl %edi, pa(_brk_end)         /*_brk_end = _end=edi+__PAGE_OFFSET*/
    # 这次映射了多少物理页面都在eax中,存好
        shrl $12, %eax
        movl %eax, pa(max_pfn_mapped)   /*previous eax pages(4k) in physical address*/

        /* Do early initialization of the fixmap area */
    # 这里还加了一个全局页目录项,页表地址为swapper_pg_fixmap
    # 放入了全局页目录项的最后一项
        movl $pa(swapper_pg_fixmap)+PDE_IDENT_ATTR,%eax
        movl %eax,pa(swapper_pg_dir+0xffc)      /*a 4k PTD in the end of PGT*/
    #endif
        jmp 3f
    /*
     * Non-boot CPU entry point; entered from trampoline.S
     * We can't lgdt here, because lgdt itself uses a data segment, but
     * we know the trampoline has already loaded the boot_gdt for us.
     *
     * If cpu hotplug is not supported then this code can go in init section
     * which will be freed later
     */

    __CPUINIT
    # 多处理器平台
    #ifdef CONFIG_SMP
    ENTRY(startup_32_smp)
        cld
        movl $(__BOOT_DS),%eax
        movl %eax,%ds
        movl %eax,%es
        movl %eax,%fs
        movl %eax,%gs
    #endif /* CONFIG_SMP */
    3:

    /*
     *    New page tables may be in 4Mbyte page mode and may
     *    be using the global pages.
     *
     *    NOTE! If we are on a 486 we may have no cr4 at all!
     *    So we do not try to touch it unless we really have
     *    some bits in it to set.  This won't work if the BSP
     *    implements cr4 but this AP does not -- very unlikely
     *    but be warned!  The same applies to the pse feature
     *    if not equally supported. --macro
     *
     *    NOTE! We have to correct for the fact that we're
     *    not yet offset PAGE_OFFSET..
     */
    # 这里可以设置页面大小为4M,cr4的PSE如果置位的话
    # 可以完全飘过~ 飘到下标6f
    #define cr4_bits pa(mmu_cr4_features)           /*the bit in PSE on the cr4*/
        movl cr4_bits,%edx
        andl %edx,%edx          /*if set the bit then start 4M page*/
        jz 6f                   /*assume don't set the PSE bit*/
        movl %cr4,%eax        # Turn on paging options (PSE,PAE,..)
        orl %edx,%eax
        movl %eax,%cr4

        testb $X86_CR4_PAE, %al        # check if PAE is enabled
        jz 6f

        /* Check if extended functions are implemented */
        movl $0x80000000, %eax
        cpuid
        /* Value must be in the range 0x80000001 to 0x8000ffff */
        subl $0x80000001, %eax
        cmpl $(0x8000ffff-0x80000001), %eax
        ja 6f
        mov $0x80000001, %eax
        cpuid
        /* Execute Disable bit supported? */
        btl $(X86_FEATURE_NX & 31), %edx
        jnc 6f

        /* Setup EFER (Extended Feature Enable Register) */
        movl $MSR_EFER, %ecx
        rdmsr

        btsl $_EFER_NX, %eax
        /* Make changes effective */
        wrmsr

    6:

    /*
     * Enable paging
     */
    # 从这里开始我们将完全进入保护模式
    # initial_page_table就是全局页目录的首地址
    # 放入cr3
        movl pa(initial_page_table), %eax
        movl %eax,%cr3        /* set the page table pointer.. */
    # 将cr0的分页机制打开
        movl %cr0,%eax
        orl  $X86_CR0_PG,%eax   /*X86_CR0_PG=0x80000000*/
        movl %eax,%cr0        /* ..and set paging (PG) bit */

    # 这里,我们调皮的跳一下,完全进入保护模式,呵呵!linux内核学习(13)我们开始慢慢地往上爬... - 小鱼 - ringk--linuxer
        ljmp $__BOOT_CS,$1f    /* Clear prefetch and normalize %eip */
    1:                              /*Now completely go to protected mode...*/
        /* Set up the stack pointer */
    # 设置好栈
        lss stack_start,%esp

    /*
     * Initialize eflags.  Some BIOS's leave bits like NT set.  This would
     * confuse the debugger if this code is traced.
     * XXX - best to initialize before switching to protected mode.
     */
    # 将标志寄存器清0
        pushl $0
        popfl

    # 多处理器,直接飘过~
    #ifdef CONFIG_SMP
        cmpb $0, ready
        jz  1f                /* Initial CPU cleans BSS */
        jmp checkCPUtype
    1:
    #endif /* CONFIG_SMP */

    /*
     * start system 32-bit setup. We need to re-do some of the things done
     * in 16-bit mode for the "real" operations.
     */
    # 设置IDT,中断向量表,这个非常重要
    # 不过现在还没有什么的
        call setup_idt

    # 检查一下CPU类型
    checkCPUtype:

        movl $-1,X86_CPUID        #  -1 for no CPUID initially

    /* check if it is 486 or 386. */
    /*
     * XXX - this does a lot of unnecessary setup.  Alignment checks don't
     * apply at our cpl of 0 and the stack ought to be aligned already, and
     * we don't need to preserve eflags.
     */
    # 这段可以完全跳过,直接进入is386下标继续看
        movb $3,X86        # at least 386
        pushfl            # push EFLAGS
        popl %eax        # get EFLAGS
        movl %eax,%ecx        # save original EFLAGS
        xorl $0x240000,%eax    # flip AC and ID bits in EFLAGS
        pushl %eax        # copy to EFLAGS
        popfl            # set EFLAGS
        pushfl            # get new EFLAGS
        popl %eax        # put it in eax
        xorl %ecx,%eax        # change in flags
        pushl %ecx        # restore original EFLAGS
        popfl
        testl $0x40000,%eax    # check if AC bit changed
        je is386

        movb $4,X86        # at least 486
        testl $0x200000,%eax    # check if ID bit changed
        je is486

        /* get vendor info */
        xorl %eax,%eax            # call CPUID with 0 -> return vendor ID
        cpuid
        movl %eax,X86_CPUID        # save CPUID level
        movl %ebx,X86_VENDOR_ID        # lo 4 chars
        movl %edx,X86_VENDOR_ID+4    # next 4 chars
        movl %ecx,X86_VENDOR_ID+8    # last 4 chars

        orl %eax,%eax            # do we have processor info as well?
        je is486

        movl $1,%eax        # Use the CPUID instruction to get CPU type
        cpuid
        movb %al,%cl        # save reg for future use
        andb $0x0f,%ah        # mask processor family
        movb %ah,X86
        andb $0xf0,%al        # mask model
        shrb $4,%al
        movb %al,X86_MODEL
        andb $0x0f,%cl        # mask mask revision
        movb %cl,X86_MASK
        movl %edx,X86_CAPABILITY

    is486:    movl $0x50022,%ecx    # set AM, WP, NE and MP
        jmp 2f

    # 在往下看,无非就是加载了GDT、IDT
    is386:    movl $2,%ecx        # set MP
    2:    movl %cr0,%eax
        andl $0x80000011,%eax    # Save PG,PE,ET
        orl %ecx,%eax
        movl %eax,%cr0

        call check_x87
        lgdt early_gdt_descr
        lidt idt_descr

        ljmp $(__KERNEL_CS),$1f
    1:    movl $(__KERNEL_DS),%eax    # reload all the segment registers
        movl %eax,%ss            # after changing gdt.

        movl $(__USER_DS),%eax        # DS/ES contains default USER segment
        movl %eax,%ds
        movl %eax,%es

        movl $(__KERNEL_PERCPU), %eax
        movl %eax,%fs            # set this cpu's percpu

    # 栈保护,飘过~
    #ifdef CONFIG_CC_STACKPROTECTOR
        /*
         * The linker can't handle this by relocation.  Manually set
         * base address in stack canary segment descriptor.
         */
        cmpb $0,ready
        jne 1f
        movl $gdt_page,%eax
        movl $stack_canary,%ecx
        movw %cx, 8 * GDT_ENTRY_STACK_CANARY + 2(%eax)
        shrl $16, %ecx
        movb %cl, 8 * GDT_ENTRY_STACK_CANARY + 4(%eax)
        movb %ch, 8 * GDT_ENTRY_STACK_CANARY + 7(%eax)
    1:
    #endif
    # 飘到这里了~
        movl $(__KERNEL_STACK_CANARY),%eax
        movl %eax,%gs

        xorl %eax,%eax            # Clear LDT
        lldt %ax

        cld            # gcc2 wants the direction flag cleared at all times
        pushl $0        # fake return address for unwinder
    # 又是多处理器,继续飘~
    #ifdef CONFIG_SMP
        movb ready, %cl
        movb $1, ready
        cmpb $0,%cl        # the first CPU calls start_kernel
        je   1f
        movl (stack_start), %esp
    1:
    #endif /* CONFIG_SMP */
    # 关键点了,即将进入C代码了,哈哈!linux内核学习(13)我们开始慢慢地往上爬... - 小鱼 - ringk--linuxer
        jmp *(initial_code)

    /*
     * We depend on ET to be correct. This checks for 287/387.
     */
    # is386里的调用,居然还要检查一下x87
    check_x87:
        movb $0,X86_HARD_MATH
        clts
        fninit
        fstsw %ax
        cmpb $0,%al
        je 1f
        movl %cr0,%eax        /* no coprocessor: have to set bits */
        xorl $4,%eax        /* set EM */
        movl %eax,%cr0
        ret
        ALIGN
    1:    movb $1,X86_HARD_MATH
        .byte 0xDB,0xE4        /* fsetpm for 287, ignored by 387 */
        ret

    /*
     *  setup_idt
     *
     *  sets up a idt with 256 entries pointing to
     *  ignore_int, interrupt gates. It doesn't actually load
     *  idt - that can be done only after paging has been enabled
     *  and the kernel moved to PAGE_OFFSET. Interrupts
     *  are enabled elsewhere, when we can be relatively
     *  sure everything is ok.
     *
     *  Warning: %esi is live across this function.
     */
    # 这就是设置IDT表了
    setup_idt:
    # 默认中断处理程序
        lea ignore_int,%edx
    # 注意得用代码段选择子,而且肯定是内核代码段
        movl $(__KERNEL_CS << 16),%eax  /*set selector in the GDT*/
        movw %dx,%ax        /* selector = 0x0010 = cs */
        movw $0x8E00,%dx    /* interrupt gate - dpl=0, present */

        lea idt_table,%edi    # idt_table为idt表的首地址
        mov $256,%ecx   # 总共设置256项
    rp_sidt:
        movl %eax,(%edi)
        movl %edx,4(%edi)
        addl $8,%edi
        dec %ecx
        jne rp_sidt

    # 下面先设置几个后面可能会用的着的中断向量
    .macro    set_early_handler handler,trapno
        lea /handler,%edx
        movl $(__KERNEL_CS << 16),%eax
        movw %dx,%ax
        movw $0x8E00,%dx    /* interrupt gate - dpl=0, present */
        lea idt_table,%edi
        movl %eax,8*/trapno(%edi)
        movl %edx,8*/trapno+4(%edi)
    .endm

    # 宏描述,类似C里的define
        set_early_handler handler=early_divide_err,trapno=0
        set_early_handler handler=early_illegal_opcode,trapno=6
        set_early_handler handler=early_protection_fault,trapno=13
        set_early_handler handler=early_page_fault,trapno=14

        ret
    # 对应的中断处理程序
    early_divide_err:
        xor %edx,%edx
        pushl $0    /* fake errcode */
        jmp early_fault

    early_illegal_opcode:
        movl $6,%edx
        pushl $0    /* fake errcode */
        jmp early_fault

    early_protection_fault:
        movl $13,%edx
        jmp early_fault

    early_page_fault:
        movl $14,%edx
        jmp early_fault

    early_fault:
        cld     /*di,si ++*/
    #ifdef CONFIG_PRINTK
        pusha
        movl $(__KERNEL_DS),%eax
        movl %eax,%ds
        movl %eax,%es
        cmpl $2,early_recursion_flag
        je hlt_loop
        incl early_recursion_flag
        movl %cr2,%eax
        pushl %eax
        pushl %edx        /* trapno */
        pushl $fault_msg
        call printk
    #endif
        call dump_stack
    hlt_loop:
        hlt
        jmp hlt_loop

    /* This is the default interrupt "handler" :-) */
        ALIGN
    # 这就是那个默认中断处理程序
    ignore_int:
        cld
    #ifdef CONFIG_PRINTK
        pushl %eax
        pushl %ecx
        pushl %edx
        pushl %es
        pushl %ds
        movl $(__KERNEL_DS),%eax
        movl %eax,%ds
        movl %eax,%es
        cmpl $2,early_recursion_flag
        je hlt_loop
        incl early_recursion_flag
        pushl 16(%esp)
        pushl 24(%esp)
        pushl 32(%esp)
        pushl 40(%esp)
        pushl $int_msg
        call printk

        call dump_stack

        addl $(5*4),%esp
        popl %ds
        popl %es
        popl %edx
        popl %ecx
        popl %eax
    #endif
        iret

        __REFDATA
    .align 4
    # 看到没,之前那个跳转就是这里设置的这个,my name is "i386_start_kernel"。
    ENTRY(initial_code)
        .long i386_start_kernel
    ENTRY(initial_page_table)
        .long pa(swapper_pg_dir)

    /*
     * BSS section
     */
    # bss段
    __PAGE_ALIGNED_BSS
        .align PAGE_SIZE_asm
    #ifdef CONFIG_X86_PAE
    swapper_pg_pmd:
        .fill 1024*KPMDS,4,0
    #else
    # 这就是那个全局页目录共4k,1024项,每项4B
    ENTRY(swapper_pg_dir)           /*a page for 4k*/
        .fill 1024,4,0
    #endif
    # 这个是设置的最后那个全局页目录项的页表地址
    swapper_pg_fixmap:              /*a page for 4k*/
        .fill 1024,4,0
    #ifdef CONFIG_X86_TRAMPOLINE
    ENTRY(trampoline_pg_dir)
        .fill 1024,4,0
    #endif
    ENTRY(empty_zero_page)
        .fill 4096,1,0

    /*
     * This starts the data section.
     */
    # 注意这里我们假设没有开启PAE物理地址扩展的
    #ifdef CONFIG_X86_PAE   /*if physical address extend 64G*/
    __PAGE_ALIGNED_DATA
        /* Page-aligned for the benefit of paravirt? */
        .align PAGE_SIZE_asm
    ENTRY(swapper_pg_dir)
        .long    pa(swapper_pg_pmd+PGD_IDENT_ATTR),0    /* low identity map */
    # if KPMDS == 3
        .long    pa(swapper_pg_pmd+PGD_IDENT_ATTR),0
        .long    pa(swapper_pg_pmd+PGD_IDENT_ATTR+0x1000),0
        .long    pa(swapper_pg_pmd+PGD_IDENT_ATTR+0x2000),0
    # elif KPMDS == 2
        .long    0,0
        .long    pa(swapper_pg_pmd+PGD_IDENT_ATTR),0
        .long    pa(swapper_pg_pmd+PGD_IDENT_ATTR+0x1000),0
    # elif KPMDS == 1
        .long    0,0
        .long    0,0
        .long    pa(swapper_pg_pmd+PGD_IDENT_ATTR),0
    # else
    #  error "Kernel PMDs should be 1, 2 or 3"
    # endif
        .align PAGE_SIZE_asm        /* needs to be page-sized too */
    #endif

    .data
    # 栈的存放处
    ENTRY(stack_start)
        .long init_thread_union+THREAD_SIZE
        .long __BOOT_DS

    ready:    .byte 0

    early_recursion_flag:
        .long 0

    int_msg:
        .asciz "Unknown interrupt or fault at: %p %p %p/n"

    fault_msg:
    /* fault info: */
        .ascii "BUG: Int %d: CR2 %p/n"
    /* pusha regs: */
        .ascii "     EDI %p  ESI %p  EBP %p  ESP %p/n"
        .ascii "     EBX %p  EDX %p  ECX %p  EAX %p/n"
    /* fault frame: */
        .ascii "     err %p  EIP %p   CS %p  flg %p/n"
        .ascii "Stack: %p %p %p %p %p %p %p %p/n"
        .ascii "       %p %p %p %p %p %p %p %p/n"
        .asciz "       %p %p %p %p %p %p %p %p/n"
    # 这个我们好像不是感兴趣
    #include "../../x86/xen/xen-head.S"

    /*
     * The IDT and GDT 'descriptors' are a strange 48-bit object
     * only used by the lidt and lgdt instructions. They are not
     * like usual segment descriptors - they consist of a 16-bit
     * segment size, and 32-bit linear address value:
     */

    .globl boot_gdt_descr   # 很久以前设置的GDT了
    .globl idt_descr             # IDT中断向量表描述符

        ALIGN
    # early boot GDT descriptor (must use 1:1 address mapping)
        .word 0                # 32 bit align gdt_desc.address
    boot_gdt_descr:
        .word __BOOT_DS+7
        .long boot_gdt - __PAGE_OFFSET

        .word 0                # 32-bit align idt_desc.address
    idt_descr:
        .word IDT_ENTRIES*8-1        # idt contains 256 entries
        .long idt_table

    # boot GDT descriptor (later on used by CPU#0):
        .word 0                # 32 bit align gdt_desc.address
    ENTRY(early_gdt_descr)
        .word GDT_ENTRIES*8-1
        .long gdt_page            /* Overwritten for secondary CPUs */

    /*
     * The boot_gdt must mirror the equivalent in setup.S and is
     * used only for booting.
     */
        .align L1_CACHE_BYTES
    ENTRY(boot_gdt)
        .fill GDT_ENTRY_BOOT_CS,8,0
        .quad 0x00cf9a000000ffff    /* kernel 4GB code at 0x00000000 */
        .quad 0x00cf92000000ffff    /* kernel 4GB data at 0x00000000 */

    我的妈呀!看看这段程序,长得跟什么似的,其实真正我们关心的也没几个,其实即使是我们关心的,也不会成为我们的后面的焦点,因为这些还太底层了,我们不需要,呵呵!还得往上爬点,到了,我们自然就会流露处欣喜的表情。如果你也认真分析了,而且一直坚持到现在,估计后面的分析会比较好了,至少说遇到不懂的问题,你不会放弃,当然这里指的“不懂的问题”是我们所关心的。

    展开全文
  • Linux-内核-学习笔记(13):移植三星官方内核 一、移植前的准备 当拿到源代码时,首先要在window下利用SourceInsight创建一个工程,并将uboot源代码加载到SI中,方便修改和查看函数调用。 项目->新项目->设置...
  • 以前从来不做笔记,好多东西学了忘,忘了学,今天开始记录下来。 X86的分段  x86微处理器有两种工作模式,实模式和保护模式。... 16位的高13位是段描述的索引号(段描述符马上就讨论),TI位指示是全...
  • 这个题目取得好,好像底层离我们越来越远了,因为内核在一步一步脱壳,很快漂亮的形状就会展现在我们眼前,在这之前,我们得屏气凝神,静静地等待这一时刻的到来。进入真实内核的第一个文件是arch/x86/kernel/head_...
  •  set_early_handler handler=early_protection_fault,trapno=13  set_early_handler handler=early_page_fault,trapno=14  ret # 对应的中断处理程序 early_divide_err:  xor %edx,%edx  pushl ...
  • 所以告诫各位技术男敲醒警钟,不要想我看齐,不然就只能和代码为伴了的~~话说没了腊八粥但还是有代码,还有各位读者的支持呀,所以得继续写下去,静下心来,完成Linux内核学习,坚持,加油~&#13;  到目前为止,...
  • 一直以来,笔者只知道重启Linux系统性使用reboot,但对其过程却无所知,涉及到哪些知识点也无概念。本文就跟踪一下重启的流程,平台为Intel x86,Linux内核版本为3.17。
  • 嵌入式LINUX驱动学习13内核数据结构(链表)一、头文件、函数及说明 一、头文件、函数及说明 /* 1、初始化链表函数 :INIT_LIST_HEAD() */ static inline void INIT_LIST_HEAD(struct list_head *list) { ...
  • linux内核学习(21)设备模型之第二层device_register  2010-12-30 13:05:30| 分类: Linux_内核|字号 订阅 这篇文章将那个3个注册函数说说,把整个设备模型框架搭建起来,当然,是重点部分了...
  • 参考资料 : linux内核设计和实现 P13 likely()和unlikely()是内核编译时用于优化 if 判断语句的宏likely()代表优化unlikely()代表不优化一般为了效率 由程序员自己判断if语句里面的内容是否要优化,显然...
  • 难点一是对硬盘的结构和术语没有一个概念,二是从硬盘加载内核镜像的代码段逻辑较为复杂,三是对汇编指令的作用还不是很清楚,四是对BIOS中断的不熟悉,主要是INT10和INT13号中断。最后还是在下班前把它搞懂了。 ...
  • Linux内核设计与实现》学习笔记第三章 进程管理第四章 进程调度第五章 系统调用第六章 内核数据结构第七章 中断和中断处理第十章 内核同步方法第11章 定时器和时间管理第12章 内存管理第13章 虚拟文件系统第14章 ...
  • 通用寄存器的作用r0 :在函数开始时使用r1 :存放堆栈指针,相当于ia32架构中的esp寄存器r2 :存放当前进程的描述符的地址r3 :存放第一个参数和返回地址r4-r10 :存放...Linux启动过程描述 第一步:使用Boot ...
  • 转自  http://www.cnblogs.com/bastard/archive/2012/09/13/2683771.html
  • 参考资料:  1. 《IBM-PC汇编语言程序设计》  2....  3.http://www.ctyme.com/intr/int-13.htm  ◆ 磁盘复位:  功能号:AH = 00H  调用参数:DL = 驱动器号 (00H~7FH为软盘;8...
  • 本书共13章,其中第1~3章是总览,第4~13章是分领域阐述。第1~3章总体介绍Linux的基本知识;第4章以Linux系统的启动开始深入叙述;第5章是Linux系统运行中使用者*常接触到的进程概念,重点介绍进程的原理;第6章是...
  • http://news.51tester.cn/www/13/2010-01/7011.html 转载于:https://blog.51cto.com/liubinwei/554111
  • _Linux内核的整体架构

    2020-11-04 02:08:58
    转载自蜗窝科技Linux内核的整体架构​www.wowotech.net作者:wowo发布于:2014-2-21 13:23 分类:Linux内核分析0. 转载者说在前面的话转载目的:能够让更多的小伙伴发现优质的文章对原文进行重新排版梳理替换,让...
  • 根据以前学习内核源码的经验,在学习文件系统实现之前,我大概定了个目标:&#13; 1、 建立一个清晰的全局概念。为将来需要研究代码细节打下坚实基础。&#13; 2、 只研究虚拟文件系统 VFS 的实现,不研究...
  • 转载自蜗窝科技Linux内核的整体架构​www.wowotech.net作者:wowo发布于:2014-2-21 13:23 分类:Linux内核分析0. 转载者说在前面的话转载目的:能够让更多的小伙伴发现优质的文章对原文进行重新排版梳理替换,让...
  • 一、所用函数如下 1、 void init_timer(struct timer_list *timer) 函数->负责初始化timer_list类型变量 2、 void add_timer(struct...用于向Linux内核注册定时器 3、 int del_timer(struct timer_list * timer) ...
  • 全局的段描述表寄存器中用作GDT下标的有13位(其它,0和1位表示特权级别,2位表示使用的是全局还是局部描述表),共可以有8192项,除去第1项永远是0,第2、3项表示内核的代码段和数据段,4、5项表示当前进程的代码段...
  • 前面两节介绍了一下 linux 中进程的资源,本节再来学习linux 中 cfs 进程的调度。linux 进程的时间记账上一节说到为了尽量让每个进程都有相对公平的机会运行,linux 在设计进程调度时,提出了 cpu使用比的概念,...
  • 关注”技术简说“(13站同名),带你由浅入深学习linux内核源码。linux内核开发100讲免费教程,每周二、四晚9点准时更新,敬请收看。进我主页点”视频“栏目即可观看。改造前的字符设备驱动源码:#include #include #...
  • 阅读学习教材「Linux内核设计与实现 (Linux Kernel Development)」第教材第13,14章。二是学习MOOC「Linux内核分析」第七讲「Linux内核的实质和Linux系统的一般执行过程」,并完成实验楼上配套实验。 然后我们开始这...

空空如也

空空如也

1 2 3 4 5 ... 11
收藏数 214
精华内容 85
关键字:

linux内核学习13

linux 订阅