面试题答案
一键面试设置线程优先级和调度策略
在Linux系统中,使用C语言设置线程优先级和调度策略,需要用到pthread
库和sys/sched.h
头文件。以下是详细步骤:
- 包含头文件
#include <pthread.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
- 设置调度策略和优先级
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, ¶m) != 0) {
perror("pthread_setschedparam");
return -1;
}
return 0;
}
不同调度策略对线程运行的影响
-
SCHED_FIFO(先进先出调度策略)
- 特点:SCHED_FIFO调度策略下,线程按照先进先出的顺序执行。一旦一个SCHED_FIFO线程开始运行,它会一直运行,直到它自愿放弃CPU(例如调用
sched_yield()
函数、等待I/O、被更高优先级的SCHED_FIFO或SCHED_RR线程抢占)。 - 适用场景:适用于对响应时间要求极高,不希望被频繁中断的实时任务,例如工业控制中的一些关键操作。
- 特点:SCHED_FIFO调度策略下,线程按照先进先出的顺序执行。一旦一个SCHED_FIFO线程开始运行,它会一直运行,直到它自愿放弃CPU(例如调用
-
SCHED_RR(时间片轮转调度策略)
- 特点:与SCHED_FIFO类似,但SCHED_RR为每个线程分配一个时间片。当时间片用完时,即使线程没有执行完,也会被抢占,放到运行队列末尾等待下次调度。相同优先级的SCHED_RR线程之间会以时间片轮转的方式共享CPU。
- 适用场景:适用于对响应时间有要求,同时需要公平分配CPU时间的实时任务,例如多媒体播放任务,既要保证流畅性,又要公平处理不同的媒体流任务。
-
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调度策略,使用系统默认的调度方式,不会影响实时任务的执行。