Linux x86 stability和coredump

发布于:2025-09-14 ⋅ 阅读:(11) ⋅ 点赞:(0)

1 POSIX pthread_create原理
1)fork()、pthread_create()、vfork()对应的系统调用分别是sys_fork()、sys_clone()、sys_vfork(),它们在内核中都是通过do_fork()实现的。
2)系统中所有的进程都组织在init_task.tasks链表下面,每个进程的线程组织在每个进程task_sturct->signal的链表下。参考函数for_each_process()和for_each_process_thread()。
3)根据上述分析,Linux用户态和内核线程都由task_struct结构体描述,是一个轻量级的进程,因此内核中current变量可以表示进程、用户态线程和内核线程。

2 kernel的log机制
2.1 kernel代码中调整loglevel
int old_lvl = console_loglevel;
console_loglevel = CONSOLE_LOGLEVEL_MOTORMOUTH;
// TODO
console_loglevel = old_lvl;

2.2 Linux Kernel动态log
- 需在内核中配置CONFIG_DYNAMIC_DEBUG,并且将debugfs挂载到某个文件夹mount -t debugfs none /sys/kernel/debug/
- 通过echo -n "file xxxxxx.c +p" > /sys/kernel/debug/dynamic_debug/control(或者/d/dynamic_debug/control)来打开调试信息

2.3 Kernel hexdump
print_hex_dump(KERN_INFO, "",
    DUMP_PREFIX_OFFSET, 16, 1,
    buf,
    len,
    true);

3 Interrupt
3.1 中断上半部
arch/x86/kernel/irq.c
do_IRQ()
分析do_IRQ()函数可知,Linux内核在x86平台上不支持中断嵌套。

3.2 中断下半部
tasklet基于softirq。

3.3 irqbalance
https://github.com/ix5/android-irqbalance

4 x86 NMI watchdog
4.1 工作原理
soft lockup:禁止抢占,使用了spin_lock()
hard lockup:禁止抢占和禁止CPU local irq,使用了spin_lock_irqsave()
用户态watchdog:/dev/watchdog

kernel/watchdog.c
hrtimer的处理函数:watchdog_timer_fn
调用wake_up_process函数唤醒此cpu上的watchdog线程,如果watchdog线程被唤醒就会去刷新时间戳。如果系统关了抢占,此watchdog线程不会被唤醒,这样时间戳就不会更新。

4.2 soft lockup
Soft Lockup refers to the occurrence of the CPU that has occurred in 20 seconds (default) does not have scheduling switching.
Refer to Analysis of soft lockup mechanism of Linux series AND Using RCU’s CPU Stall Detector.

echo 30 > /proc/sys/kernel/watchdog_thresh

4.3 watchdog线程调度方式
- kernel/watchdog.c
- SCHED_FIFO,最高优先级MAX_RT_PRIO - 1 = 99
- 实时进程的优先级(rt_priority)数字越大则优先级越高,99最高,0最低;而普通进程正好相反,优先级(prio)数字越大则优先级越低,100最高,139最低(对应nice值-20 ~ 19)
- 内核调度是按照task_struct中的prio来调度的,所以内核会将实时线程的rt_priority转换成prio:prio = MAX_RT_PRIO - 1 - p->rt_priority;prio的值越小,优先级就越高

4.4 进程的调度方式和优先级
ps -Al
chrt -p $PID

4.5 per-CPU变量
current,每个CPU一个变量:
arch/x86/include/asm/current.h
DECLARE_PER_CPU(struct task_struct *, current_task);

抢占计数,每个CPU一个变量:
arch/x86/include/asm/preempt.h
DECLARE_PER_CPU(int, __preempt_count);
CPUx的抢占禁止了后,实际上就是一个单片机,只能执行关闭抢占的线程以及响应硬件的中断。

4.6 kmod demo
#include<linux/kernel.h>
#include<linux/module.h>
#include<linux/kthread.h>

static struct task_struct *task0;
static spinlock_t spinlock;
static int val;

int task(void *arg)
{
    printk(KERN_INFO "%s:%d\n",
        __func__, __LINE__);
    /* To generate panic uncomment following */
    /* panic("softlockup: hung tasks"); */

    while (!kthread_should_stop()) {
        printk(KERN_INFO "%s:%d\n",
            __func__, __LINE__);
        spin_lock(&spinlock);
        /* busy loop in critical section */
        while(1) {
            // printk(KERN_INFO "%s:%d\n",
                __func__, __LINE__);
        }
        spin_unlock(&spinlock);
    }
    return val;
}

static int softlockup_init(void)
{
    printk(KERN_INFO "%s:%d\n",
        __func__, __LINE__);

    val = 1;
    spin_lock_init(&spinlock);
    task0 = kthread_run(&task, (void *)val,
        "softlockup_thread");
    set_cpus_allowed_ptr(task0, cpumask_of(0));
    return 0;
}

static void softlockup_exit(void)
{
    printk(KERN_INFO "%s:%d\n",
        __func__, __LINE__);
    kthread_stop(task0);
}

module_init(softlockup_init);
module_exit(softlockup_exit);
MODULE_LICENSE("GPL");

4.7 lockdep
lockdep:lock dependency
CONFIG_PROVE_LOCKING=y
打开lockdep时内核启动后会自动配置console loglevel到CONSOLE_LOGLEVEL_MOTORMOUTH(=15),可以修改代码将这个配置屏蔽,不然打印的内核log太多。

5 addr2line和objdump使用
5.1 带有完整调试信息的符号路径
./out/target/product/[PROJECT]/symbols/vendor/lib64/

5.2 addr2line
addr2line -C -f -e libxxx.so <地址>
其中地址为#00 Frame前面显示的pc指向的地址

aarch64-linux-android-addr2line -C -f -e vmlinux <目标地址>

5.3 objdump
objdump -l -C -S libxxx.so > deasm.log
vi deasm.log
输入#00 Frame前面显示的pc指向的地址(需要去掉前面的多个0)

5.4 gdb vmlinux
Use 7-Zip to extract vmlinux from IPK file. The following l means list.
gdb vmlinux
l *func_name+offset_addr

6 coredump
Aarch64 Linux SDK中可以运行xxx-gdb来调试core dump。

Default core dump, must use sudo bash -c 'shell command' to run coredump configuration.
sudo bash -c 'echo "/data/core.%e.%p" > \
/proc/sys/kernel/core_pattern'
ulimit -c <size>: unit is block (= 512bytes)
ulimit -c unlimited
gdb main core.main.19188

7 Abbreviations
HECI:Host Embedded Controller Interface,Host OS和x86 ME的通信接口,只有4pin,分别是REQ#、GNT#、TX和RX,目的是为了代替SMBus


网站公告

今日签到

点亮在社区的每一天
去签到