Linux

boot flow

xiru2ly3rd88
17 min readMay 20, 2022
sudo dd if=/dev/sda bs=512 count=1 2>/dev/null | strings | grep -Eoi ‘grub|lilo|acronis|reboot’

bootm -> kernel

bootstrap介紹

  • Linux system須具備:
    1. Bootloader
    2. Linux Kernel
    3. Root Filesystem: busybox, user用的程式, ex: bash, ls…
  • bootstrap flow:
    BIOS -> MBR -> boot loader -> kernel -> init process -> login
  • Different type kernel:

Linux 核心設計: 作業系統術語及概念

Basic command

鳥哥指令教學

VMBox雙向剪貼

sudo VBoxClient --clipboard

BASH教學

10.2.2 變數的取用與設定:echo, 變數設定規則, unset

讀:
echo ${myname}

set:
myname=VBird

unset:
unset myname

dmesg: display開機訊息

變更為/usr/include目錄
cd /usr/include
// Compile or assemble the source files, but do not link, 產出.o
gcc -c test.c
ex: project, 執行檔由a,b,c 3個檔案組成// 個別編譯
gcc -c a.c
gcc -c b.c
gcc -c c.c
//產出output executable/object/assemble file
//沒指定output name, default a.out
gcc -o test.c
// 指定output name: test, 產出 test.a
gcc -o test test.c
執行
./test
//印出warning msg: -Wall
ex: var沒有initialize
gcc -Wall -o test test.c //只編譯不連結
//連結 產生output: app
gcc -o app a.o b.o c.o
note: 只改b檔案, b重新編譯 -> 再連結即可
//最佳化 -O
數字越高: 最佳化程度越高, 通常用-O2
gcc -O2 -o test test.c

The Linux Kernel Module Programming Guide

module指令:

.ko: kernel object

// module information
modinfo hello-1.ko
// 載入多少 有hello字串的module
sudo lsmod | grep hello
//install module
sudo insmod hello-1.ko
// 傳入command line paramater:mystring="bebop" myintarray=-1
sudo insmod hello-5.ko mystring="bebop" myintarray=-1
// remove module
sudo rmmod hello_1
// 看install/remove module的資訊
sudo dmesg -t | tail -7

Makefile

ex: The Linux Kernel module programing

obj-m += hello-1.o 

PWD := $(CURDIR)

all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
//will build hello-1.o from hello-1.c, after linking get hello-1.ko
obj-m += hello-1.o
obj-m += test.o // test.o 不會編進kernel, 編成test.koobj-y += test.o // test.o 會編進kernel

ref:
https://mropengate.blogspot.com/2018/01/makefile.html

4.7 Building modules for a precompiled kernel 不懂

  • syscall tracer
strace ./hello

5. Device Drivers

分為 block/character device:

  • block device:
    1. have a buffer for requests, can choose best order
    2. can only accept input and return output in blocks (傳輸用block)
  • character device:
    allowed to use as many or as few bytes as they like (傳輸用任意bytes)

第一個字b: block device
第一個字c: character device

ls -l

6.3 Registering A Device

  1. 要知道major number
    dynamic allocate major number
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name);

2. initialize the data structure cdev

void cdev_init(struct cdev *cdev, const struct file_operations *fops);

3. add the char device to the system

int cdev_add(struct cdev *p, dev_t dev, unsigned count);

6.4 Unregistering A Device

module沒人用(count=0), 才可以remove

increase, decrease and display this counter

  • try_module_get(THIS_MODULE) : Increment the reference count of current module.
  • module_put(THIS_MODULE) : Decrement the reference count of current module.
  • module_refcount(THIS_MODULE) : Return the value of reference count of current module.

7 The /proc File System

the /proc file system allow easy access to information about processes
可以從user space read/write kernel space

8 sysfs: Interacting with your module

sysfs allows you to interact with the running kernel from userspace by reading or setting variables inside of modules.

  • read:
cat /sys/kernel/mymodule/myvariable
  • set:
echo "32" > /sys/kernel/mymodule/myvariable

9 Talking To Device Files

Device files are supposed to represent physical devices.

ioctl用來 read/write device

10 System Calls

system call 用來跟kernel溝通
system call帶number -> look at sys_call_table, call kernel function

system call stealing的例子,

11 Blocking Processes and threads

11.1 Sleep 例子做不出來

題目

delay vs sleep

delay: busy wait

sleep: non-busy wait

  • Atomic context: 不能被打斷, 用delay
  • non-atomic context: 依delay時間決定

https://blog.csdn.net/cherylchenyajun/article/details/110088333

spin_lock, spin_lock_irq, spin_lock_irqsave

  • spin_lock:
    preempt_disable();

interrupt搶占會出問題
ex:

// in normal run level
extern spinlock_t lock;
// …
spin_lock(&lock);
// do something
// interrupted by IRQ …
// in IRQ
extern spinlock_t lock;
spin_lock(&lock); // dead lock
  • spin_lock_irq:
    local_irq_disable();
    preempt_disable();
  • spin_unlock_irq: enable IRQ

要確認獲得鎖之前IRQ是enable

  • spin_lock_irqsave: disable preempt/interrupt, save irq flag
    local_irq_save(flags);
    preempt_disable();
  • spin_unlock_irqrestore: restore IRQ status

每次關閉中斷前紀錄當前中斷的狀態,然後恢復它而不是直接把中斷開啟。

ISR Top and Bottom Halves

Top half: interrupt發生馬上要處理的事, 寫在ISR
Bottom half:
1.可以晚點做的事 -> schedule
2. interrupt enable

3種schdule:SoftIRQ, Tasklet, Workqueue

SoftIRQ vs Tasklet vs Workqueue

  • softIRQ:
    1. only static allocate
    2. can not sleep
    3. reentrant: same/different type can run concurrently on several CPUs
    4. run interrupt context
    5. can be interrupt by HW interrupt
  • Tasklet:
    1. static + dynamic allocate
    2. non-reentrant:
    2.1 same type cannot run concurrently on several CPUs
    2.2 different types can run concurrently on several CPUs
    3. can not sleep
    4. run interrupt context

softIRQ vs Tasklet

  • Workqueue:
    1. can schedule
    2. can sleep
    3. run process context
  • Threaded IRQs:

目的: reduce the time spent with interrupts disabled

會create thread

https://ithelp.ithome.com.tw/articles/10252646

查看process memory

cat /proc/[pid]/status

check process CPU/memory usage:

ps -aux // find the pid of process
ps -p <pid> -o %cpu,%mem,cmd

perf分析CPU usage
用tick中斷採樣 -> 找出哪段程式最花時間

# perf record -a -e cycles -o cycle.perf -g sleep 10 // sampling
# perf report -i cycle.perf | more // report

Debug segmentation fault

用GDB + backtrace

Debug kernel panic

kernel panic: low-level error, OS can not fix it

設定kdump -> crash發生產生crash.log -> dump crash.log(vmlinux)

user space communication with kernel space

  • proc file

install proc file module -> create file in /proc/proc_name
讀:
cat /proc/proc_name
寫:
echo “hello123” > /proc/proc_name

procfs vs sysfs vs debugfs

install character driver -> user process use ioctl_fun

input/output/redirection

3種資料流:

  • 標準輸入(standard input,代碼為 0:程式執行所需要的輸入資料
cat 鍵盤輸入< 從檔案讀取資料
cat < input.txt
  • 標準輸出(standard output,代碼為 1:程式正常執行所產生的輸出資料。運算子: >, >>
ls > output.txt 存到output.txt, 原本內容清空
ls >> output.txt 存到output.txt, 原本內容保留, 加在原本內容之後
  • 標準錯誤輸出(standard error output,代碼為 2:程式出錯時通知使用者用的訊息,或是呈現程式狀態用的訊息。
使用 > 運算子,把標準錯誤輸出(2)導至指定的檔案:
ls non_exist > output.txt 2> error.txt
正常的輸出導入 output.txt
標準錯誤輸出導入 error.txt
ls non_exist > output.txt 2>&1
2>&1 就是把標準錯誤輸出(2)導入標準輸出(1),再靠著 > 把所有的資料全部導入 output.txt
  • Redirection:
pipe 運作

把兩個程式的輸入與輸出串接起來,就可以使用管線pipe, 運算子: |

ls | nl 每個檔案名加上行號
ls | nl
ls | grep keyword | nl | head -n 5
ls 的輸出中,以 grep 篩選出有 keyword 的檔名,交給 nl 加上行號,最後交給 head 輸出前 5 行資料。

ref:

程式開發教學

基本指令/linux寫code/安裝VSCode, NodeJS, Python

  • file: 檢查檔案

GDB教學

教學2
檢查memory leak

sudo apt install gdb  // install GDB
  • 指令
    增加 break point: b or break
    刪除 break point: d or delete
    list all break point: i b
    跑程式: run
    印出: p
    繼續跑: c
    step: 只跑一行程式 // 不用一直加break point
  • back trace: bt
    frame + 數字: 跳到第幾號frame
    up: 回到上個frame
    down: 到下個frame
gcc simple.c -g  // 加-g, 才可以用GDB
gcc -g gdb_example.c -o gdb_example //
gdb ./a.out
l // 1次show 10行code
b simple.c:7 // add break in line 7 of simple.c
b simple.c:9
i b // list all break point
break point list
run // execute -> stop at line 7
p x // print x
c // continue -> stop at line 9
p x // print x
bt // back trace
back trace & change frame

RTOS

  • Linux embedded system vs RTOS

HAL(hardware abstraction layer)

讓APP 不用知道HW細節就可以access, 提高code的移植性

https://kezeodsnx.pixnet.net/blog/post/24676754

  • BSP (Board Support Package):

主要功能:
1. 硬體的初始化,主要是針對CPU做初始化,為上層軟體提供硬體支援。

2. 為作業系統提供設備驅動程式與系統中斷服務程式。

3. 定製作業系統功能,提供軟體一個多工的操作環境。

4. 初始化作業系統,讓作業系統能夠正常運行。

開發流程:

--

--

xiru2ly3rd88
0 Followers

學習筆記不保證100%正確, 只是用來快速複習; 聯絡信箱: xiru2ly3rd88@gmail.com