Linux内核设计与实现总结(3) —— 进程管理与进程调度

进程与线程

Linux内核是不区分线程与进程的,线程只是一种特殊的进程,被视为与其他进程共享地址空间的进程。与windows这种在内核专门提供线程支持的操作系统不一样。

task_struct与thread_struct

task_struct(进程描述符)描述了一个进程的所有信息,包含进程打开的文件、挂起的信号、进程的状态、进程的pid等。它保存在tasks双向循环链表中(见上一节的链表结构体总结),因此可以从一个进程结构体出发,索引到任何其他进程结构体。目前内核中,进程描述符是用slab分配器动态生成的,并且task_struct有一个void *stack变量指向进程的内核栈。

thread_struct是与体系强相关的,存放了一些进程切换时的 上下文。

早期内核代码中,在X86体系并且CONFIG_THREAD_INFO_IN_TASK设置为N时,进程的thread_struct存放在进程的内核栈。如果是向上增长的栈,thread_struct则在栈顶。在thread_struct中,有一个struct task_struct *task变量。后来内核代码把X86的thread_struct结构体中的task指针给去掉了(Move thread_info into task_struct),因为这个变量本来是为了寄存器在不够多的体系上,可以通过内核栈与偏移找到进程描述符。但是X86一直使用的是per_cpu的变量来保存正在使用cpu的进程的进程描述符:

1
DECLARE_PER_CPU(struct task_struct *, current_task);

所以thread_struct中的task变量可有可无,就去掉了。

在进程调度时,会更新这个变量:

1
this_cpu_write(current_task, next_p);
Read more

Linux内核设计与实现总结(2) —— 内核数据结构

内核数据结构

Linux内核中实现了一些常见的数据结构,而且内核要求代码越高效越好,所以这些数据结构的实现极为优雅!因此,千万不要自己实现山寨的数据结构。

内核的数据结构包括:

  1. 链表(双向循环)
  2. 队列
  3. IDR & IDA
  4. 红黑树

链表

链表头文件

位于include/linux/link.h

Read more

Linux内核设计与实现总结(1) —— qemu内核调试环境搭建(macOS)

宿主机系统

  1. macOS 12.4 (x86)

安装qemu

qemu相比于vmware,简单、轻便,可以直接指定linux内核,再指定一个文件系统,即可调试。硬盘、网络设备可以后加。

首先我尝试了utmapp/UTM,这是个适用于iOS/macOS的虚拟机,基于qemu。但是在指定内核启动镜像bzImage和initramfs后,遇到了问题,一直报错:

1
The bootindex 0 has already been used

搞了一会没搞出来,索性不用UTM了,直接上qemu。

使用homebrew可以直接安装qemu。

1
➜  ~ brew install qemu

目前安装的是7.0.0_2。

安装完成之后验证一下:

1
2
3
4
5
6
7
➜  ~ qemu-system-x86_64 --help
QEMU emulator version 7.0.0
Copyright (c) 2003-2022 Fabrice Bellard and the QEMU Project developers
usage: qemu-system-x86_64 [options] [disk_image]

'disk_image' is a raw hard disk image for IDE hard disk 0
....
Read more

折腾:无线宝鲁班openwrt 21.02.1

免责声明

  1. 仅用于测试与学习研究,作者没有对该设备进行任何形式的“破解”,所有信息都是通过正常的方式获取。
  2. 如果任何单位或个人认为本文内容可能涉嫌侵犯其权利,则应及时联系作者并要求删除相关内容。
  3. 作者对本文带来的潜在问题概不负责,包括但不限于由任何错误导致的任何损失或损害。

前言

前几天在京东上买了个京东云无线宝鲁班,硬件配置如下:

1
2
3
4
5
CPU:MT7621A
内存:南亚512MB
闪存:XM25QH128C 128Mit/16MB
无线:MT7975DN + MT7905DAN
网口:全千兆LLLW

本来天天放那边跑分换京豆的,但是这官方固件实在有点用不下去,所以给它搞个适配个openwrt吧。

Read more

Kernel Compile Guide(clang)

Guide

  1. Add the Clang commits to your kernel source
    https://android.googlesource.com/kernel/common/+log/f0907aa15ed9f9c7541bb244ed3f52c376ced19c
  2. Download/build a compatible Clang toolchain
  3. Download/build a copy of binutils
  4. Compile the kernel (for arm64, x86_64 is similar - example using AOSP’s toolchains):
1
2
3
4
5
6
7
8
9
10
11
export PATH=/home/ubuntu/gcc/bin:$PATH
export PATH=/home/ubuntu/clang/bin:$PATH
export CROSS_COMPILE=aarch64-linux-android-
export CLANG_TRIPLE=aarch64-linux-gnu-
export ARCH=arm64
export SUBARCH=arm64

make clean
make mrproper
make O=out lcblues-perf_defconfig
make -j$(nproc --all) O=out CC=clang CONFIG_DEBUG_SECTION_MISMATCH=y
1
make -j$(nproc --all) O=out

CC=clang CLANG_TRIPLE=aarch64-linux-gnu-

op5-perf_defconfig or msmcortex-perf_defconfig
After compiling, you can verify the toolchain used by opening out/include/generated/compile.h and looking at the LINUX_COMPILER option.

A couple of notes:

CLANG_TRIPLE is only needed when using AOSP’s version of Clang
export CC=clang does not work. You need to pass CC=clang to make like above.

关于git cherry-pick

首先fork一加官方kernel,然后clone自己仓

1
git clone 

清除无用的分支,再add一个一加官方的remote

1
2
git branch -r -d <branch>
git push origin <branch>
1
2
git remote add op https://github.com/OnePlusOSS/android_kernel_oneplus_msm8998
git fetch op HEAD:oneplus/QC8998_P_9.0

把它这个拿下来
切换到自己的QC8998_P_9.0分支,并merge一下

1
2
git checkout oneplus/QC8998_P_9.0
git merge op/oneplus/QC8998_P_9.0

或者自己cherry-pick

1
git cherry-pick commitid^..commitid

Problem

  1. WLAN驱动qca_cld3_wlan.ko的问题

一加官方内核repo里面是不包含qcacld3.0的源码的。它在开机的时候加载insmod /vedor/lib/module/qca_cl3_wlan.ko,见 /vendor/etc/init/hw/init.target.rc

但模块存在一个check_version的校验的问题,你如果不是从源码编译而来的,基本是过不去的,因此在启动的时候,驱动没加载,开机就没WiFi。

那么为什么Custom Rom没有这个问题?Custom Rom的内核是由CAF基线+一加的一些修改而成的,包含qcacld3源码,并且配置成includes到内核里。

那为什么第三方基于一加内核源码魔改的内核没有这个问题呢?特意看了commit,它魔改了/kernel/module.c,check_version遇到wlan直接return 1了。

现在我处于菜鸟阶段,因此我cherry-pick了这个commit…嘻嘻

  1. Clang LTO

还没开始,但可以肯定的是必遇到问题。

  1. 手势用不了

fixed

  1. Clang编译 CPU 总是Max Freq

fixed

  1. ZRAM LZ4

added

  1. EAS

added

  1. Dynamic SchedTune Boost

added

  1. wakelock

todo

  1. more tcp congestion control algorithm

todo

OrangeFox Recovery编译记录

基于TWRP修改的,界面挺帅

问题:

  1. /sbin/foxstart.sh找不到
  2. 系统开机卡第一界面
  3. App Manager用不了
  4. 中文显示为口口

解决

Read more

编译适用于mt7620a的OpenWrt

前言

OpenWRT是一个高度模块化、自动化的嵌入式Linux系统,拥有强大的网络组建和扩展性,常常被用于工控设备、电话、小型机器人、智能家居、路由器以及VOIP设备中,其中在智能路由器上有广泛使用。同时它还提供了100多个已编译好的软件,而且数量还在不断增加。

OpenWRT支持各种处理器架构,无论是ARM、X86、PowerPC或者MIPS都有很好的支持。其多达3000多种软件包,囊括从工具链(toolchain),到内核(Linux Kernel),到软件包(packages),再到根文件系统(rootfs)整个体系,是的开发者只需要简单的一个make命令就可以方便快速的定制一个具有特定功能的嵌入式系统。

对于想学习嵌入式Linux开发的工程师来说,OpenWRT是非常适合的(引用)

我第一次接触Openwrt是在2013年,那是正是高二,家里有一个TP-Link的wr740路由器,mips架构,4M的Flash,16M的内存,当时刷过dd-wrt和openwrt。

第二次是在大二了,当时为了用路由器上校园网,撸了几台k2,研究了如何在openwrt等第三方路由器固件下实现锐捷和安腾的认证。

今天我要给k2编译一下Openwrt最新的Snapshot固件,顺便解决一下不识别16M闪存的问题。

Read more

温习一波GCC

GCC

GCC是GNU Compiler Collection的缩写,跨平台编译器集合。
支持C,C++,Java等语言。

C的编译

  1. 预处理
  2. 编译:生成汇编语言.s文件
  3. 汇编:生成目标代码.o文件
  4. 链接:生成可执行程序
Read more