MST

星途 面试题库

面试题:C语言中Linux线程的优先级设置与调度策略优化

阐述在Linux系统中,使用C语言如何设置线程的优先级以及不同的调度策略(如SCHED_FIFO、SCHED_RR、SCHED_OTHER)对线程运行的影响,并举例说明如何根据实际需求优化调度策略。
44.0万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

设置线程优先级和调度策略

在Linux系统中,使用C语言设置线程优先级和调度策略,需要用到pthread库和sys/sched.h头文件。以下是详细步骤:

  1. 包含头文件
#include <pthread.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
  1. 设置调度策略和优先级
int set_thread_sched_policy(pthread_t thread, int policy, int priority) {
    struct sched_param param;
    param.sched_priority = priority;

    if (pthread_setschedparam(thread, policy, &param) != 0) {
        perror("pthread_setschedparam");
        return -1;
    }
    return 0;
}

不同调度策略对线程运行的影响

  1. SCHED_FIFO(先进先出调度策略)

    • 特点:SCHED_FIFO调度策略下,线程按照先进先出的顺序执行。一旦一个SCHED_FIFO线程开始运行,它会一直运行,直到它自愿放弃CPU(例如调用sched_yield()函数、等待I/O、被更高优先级的SCHED_FIFO或SCHED_RR线程抢占)。
    • 适用场景:适用于对响应时间要求极高,不希望被频繁中断的实时任务,例如工业控制中的一些关键操作。
  2. SCHED_RR(时间片轮转调度策略)

    • 特点:与SCHED_FIFO类似,但SCHED_RR为每个线程分配一个时间片。当时间片用完时,即使线程没有执行完,也会被抢占,放到运行队列末尾等待下次调度。相同优先级的SCHED_RR线程之间会以时间片轮转的方式共享CPU。
    • 适用场景:适用于对响应时间有要求,同时需要公平分配CPU时间的实时任务,例如多媒体播放任务,既要保证流畅性,又要公平处理不同的媒体流任务。
  3. SCHED_OTHER(普通分时调度策略)

    • 特点:这是Linux内核默认的调度策略,用于普通的用户空间进程和线程。内核会根据进程的动态优先级(基于nice值等因素动态调整)来分配CPU时间,采用分时复用的方式,使得各个进程/线程都能得到合理的执行时间。
    • 适用场景:适用于大多数普通的应用程序,对实时性要求不高,更注重系统整体的公平性和资源利用率。

示例:根据实际需求优化调度策略

假设我们有一个实时数据采集任务和一个普通的日志记录任务。实时数据采集任务对时间非常敏感,需要尽可能快地处理数据,而日志记录任务相对不那么紧急。

void* data_collection(void* arg) {
    // 设置为SCHED_FIFO调度策略,优先级较高
    if (set_thread_sched_policy(pthread_self(), SCHED_FIFO, sched_get_priority_max(SCHED_FIFO) - 1) != 0) {
        printf("Failed to set SCHED_FIFO policy for data collection thread\n");
    }
    // 数据采集任务逻辑
    while (1) {
        // 模拟数据采集
        printf("Data collection in progress...\n");
    }
    return NULL;
}

void* log_recording(void* arg) {
    // 设置为SCHED_OTHER调度策略,默认优先级
    if (set_thread_sched_policy(pthread_self(), SCHED_OTHER, 0) != 0) {
        printf("Failed to set SCHED_OTHER policy for log recording thread\n");
    }
    // 日志记录任务逻辑
    while (1) {
        // 模拟日志记录
        printf("Log recording in progress...\n");
    }
    return NULL;
}

int main() {
    pthread_t data_thread, log_thread;

    if (pthread_create(&data_thread, NULL, data_collection, NULL) != 0) {
        perror("pthread_create data_collection");
        return 1;
    }

    if (pthread_create(&log_thread, NULL, log_recording, NULL) != 0) {
        perror("pthread_create log_recording");
        return 1;
    }

    pthread_join(data_thread, NULL);
    pthread_join(log_thread, NULL);

    return 0;
}

在这个示例中,数据采集任务设置为SCHED_FIFO调度策略并具有较高优先级,以确保它能优先获取CPU资源,满足实时性需求;而日志记录任务设置为SCHED_OTHER调度策略,使用系统默认的调度方式,不会影响实时任务的执行。