linux系统卡死卡顿死锁问题场景c语言举例并分析

C语言程序可能导致Linux系统卡死或卡顿的场景主要包括内存泄漏、死锁、CPU资源耗尽、硬件交互问题和文件I/O阻塞。

linux用户态问题场景分析

1,内存问题

查看进程内存使用情况,ps aux

cat /proc/pid/status以及其他内存相关信息

cat /proc/smaps

2,死锁/CPU资源耗尽

#include <stdio.h>
#include <pthread.h>

pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;

void* thread1(void* arg) {
    pthread_mutex_lock(&mutex1);
    printf("Thread1: Locked mutex1\n");
    pthread_mutex_lock(&mutex2); // 等待mutex2
    printf("Thread1: Locked mutex2\n");
    pthread_mutex_unlock(&mutex2);
    pthread_mutex_unlock(&mutex1);
    return NULL;
}

void* thread2(void* arg) {
    pthread_mutex_lock(&mutex2);
    printf("Thread2: Locked mutex2\n");
    pthread_mutex_lock(&mutex1); // 等待mutex1
    printf("Thread2: Locked mutex1\n");
    pthread_mutex_unlock(&mutex1);
    pthread_mutex_unlock(&mutex2);
    return NULL;
}

int main() {
    pthread_t t1, t2;
    pthread_create(&t1, NULL, thread1, NULL);
    pthread_create(&t2, NULL, thread2, NULL);
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    return 0;
}

使用top/perf top -g火焰图分析// cpu_hog.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
    printf("CPU Hog process started. PID: %d\n", getpid());
    printf("This process will consume 100%% of one CPU core.\n");
    printf("Press Ctrl+C to stop it.\n");

    // 一个简单的无限循环,持续消耗CPU
    while (1) {
        // 空循环体,什么也不做,就是占用CPU时间
        // 为了防止编译器优化掉这个循环,可以加一个小的计算
        volatile int dummy = 0;
        for (int i = 0; i < 100000; ++i) {
            dummy += i;
        }
    }

    return 0;
}


可以看到cpu运行差不多达到了100%.

gdb工具分析卡死的进程。

strace分析进程

3,文件I/O阻塞,同步write()大文件

使用strace查看阻塞进程相关信息,并且查看i/o通信过程中的errno信息打印出来进行错误码分析,或者查看进程状态为 D状态。// io_hog.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>

#define BUFFER_SIZE (4 * 1024 * 1024) // 4MB buffer
#define FILE_SIZE (1024 * 1024 * 1024) // 1GB file

int main() {
    printf("I/O Hog process started. PID: %d\n", getpid());
    printf("This process will write a 1GB file synchronously.\n");

    int fd = open("large_file.dat", O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if (fd == -1) {
        perror("open");
        return 1;
    }

    char *buffer = malloc(BUFFER_SIZE);
    if (!buffer) {
        perror("malloc");
        close(fd);
        return 1;
    }
    memset(buffer, 'A', BUFFER_SIZE);

    size_t total_written = 0;
    while (total_written < FILE_SIZE) {
        // write() 是一个同步阻塞调用
        // 它会等待数据从用户空间拷贝到内核空间页缓存,
        // 并且默认情况下,会等待数据真正写入磁盘(或至少被内核调度写入)才返回。
        ssize_t bytes_written = write(fd, buffer, BUFFER_SIZE);
        
        if (bytes_written == -1) {
            perror("write");
            break;
        }
        total_written += bytes_written;
    }

    printf("Finished writing %zu bytes.\n", total_written);

    free(buffer);
    close(fd);
    return 0;
}


查看进程是否进去了D状态,如果是可以使用开启hungtask监控进程状态进行分析。

使用iostat查看I/O等待时间

使用strace查看调用关系。

linux内核态问题场景分析

1,内存分析

slabinfo/meminfo/page fault内存分析

dmesg | grep “page fault”

2,死锁/softlockdep/hardlockdep/

   cat /proc/sys/watchdog
   cat /proc/sys/soft_watchdog
   cat /proc/sys/hard_watchdog
  cat /proc/sys/soft_watchdog_panic

  cat /proc/sys/hard_watchdog_panic

自旋锁卡死问题场景举例分析

#include <linux/spinlock.h>
#include <linux/module.h>
#include <linux/kernel.h>

static spinlock_t lock1;
static spinlock_t lock2;

void thread1(void) {
    spin_lock(&lock1);
    printk(KERN_INFO "Thread1: Locked lock1\n");
    spin_lock(&lock2); // 尝试获取lock2,但lock2已被Thread2持有
    printk(KERN_INFO "Thread1: Locked lock2\n");
    spin_unlock(&lock2);
    spin_unlock(&lock1);
}

void thread2(void) {
    spin_lock(&lock2);
    printk(KERN_INFO "Thread2: Locked lock2\n");
    spin_lock(&lock1); // 尝试获取lock1,但lock1已被Thread1持有
    printk(KERN_INFO "Thread2: Locked lock1\n");
    spin_unlock(&lock1);
    spin_unlock(&lock2);
}

卡死场景举例:

#include <linux/module.h>
#include <linux/kernel.h>

void busy_loop(void) {
    while (1) {
        // 忙等待,不释放CPU
    }
}

lockdep工具使用/watchdog /hungtask分析

3,中断风暴

cat /proc/interrupt,查看是否有很多的异常中断信息。

#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/kernel.h>

irqreturn_t high_freq_interrupt(int irq, void *dev_id) {
    while (1) {
        // 模拟高频中断处理
        printk(KERN_INFO "Handling interrupt...\n");
    }
    return IRQ_HANDLED;
}

static int __init storm_init(void) {
    // 注册一个中断处理程序
    request_irq(10, high_freq_interrupt, IRQF_SHARED, "storm_handler", &high_freq_interrupt);
    printk(KERN_INFO "Interrupt storm module loaded\n");
    return 0;
}

static void __exit storm_exit(void) {
    free_irq(10, &high_freq_interrupt);
    printk(KERN_INFO "Interrupt storm module unloaded\n");
}

module_init(storm_init);
module_exit(storm_exit);
MODULE_LICENSE("GPL");

4,硬件交互问题

dmesg/cat /proc/kmsg &查看是否有异常信息

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陌上花开缓缓归以

你的鼓励将是我创作的最大动力,

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值