gpt4 book ai didi

c - 在linux中,为什么一个正常的进程仍然可以运行,而实时进程却不退出?

转载 作者:太空狗 更新时间:2023-10-29 12:24:25 24 4
gpt4 key购买 nike

我写了一个 c 程序来测试 linux 调度器。这是我的代码:

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

void Thread1()
{
sleep(1);
int i,j;
int policy;
struct sched_param param;
pthread_getschedparam(pthread_self(),&policy,&param);
if(policy == SCHED_OTHER)
printf("SCHED_OTHER\n");
if(policy == SCHED_RR)
printf("SCHED_RR 1 \n");
if(policy==SCHED_FIFO)
printf("SCHED_FIFO\n");
/* for(i=1;i<100;i++) */
while(1)
{
for(j=1;j<5000000;j++)
{
}
printf("thread 1\n");
}
printf("Pthread 1 exit\n");
}

void Thread2()
{
sleep(1);
int i,j,m;
int policy;
struct sched_param param;
pthread_getschedparam(pthread_self(),&policy,&param);
if(policy == SCHED_OTHER)
printf("SCHED_OTHER\n");
if(policy == SCHED_RR)
printf("SCHED_RR\n");
if(policy==SCHED_FIFO)
printf("SCHED_FIFO\n");
/* for(i=1;i<10;i++) */
while(1)
{
for(j=1;j<5000000;j++)
{
}
printf("thread 2\n");
}
printf("Pthread 2 exit\n");
}

void Thread3()
{
sleep(1);
int i,j;
int policy;
struct sched_param param;
pthread_getschedparam(pthread_self(),&policy,&param);
if(policy == SCHED_OTHER)
printf("SCHED_OTHER\n");
if(policy == SCHED_RR)
printf("SCHED_RR \n");
if(policy==SCHED_FIFO)
printf("SCHED_FIFO\n");

/* for(i=1;i<10;i++) */
while(1)
{
for(j=1;j<5000000;j++)
{
}
printf("thread 3\n");
}
printf("Pthread 3 exit\n");
}

int main()
{
int i;
i = getuid();
if(i==0)
printf("The current user is root\n");
else
printf("The current user is not root\n");

pthread_t ppid1,ppid2,ppid3;
struct sched_param param;

pthread_attr_t attr3,attr1,attr2;
pthread_attr_init(&attr1);
pthread_attr_init(&attr3);
pthread_attr_init(&attr2);

param.sched_priority = 97;
pthread_attr_setschedpolicy(&attr1,SCHED_RR);
pthread_attr_setschedparam(&attr1,&param);
pthread_attr_setinheritsched(&attr1,PTHREAD_EXPLICIT_SCHED);

param.sched_priority = 98;
pthread_attr_setschedpolicy(&attr2,SCHED_RR);
pthread_attr_setschedparam(&attr2,&param);
pthread_attr_setinheritsched(&attr2,PTHREAD_EXPLICIT_SCHED);

pthread_create(&ppid3,&attr3,(void *)Thread3,NULL);
pthread_create(&ppid2,&attr2,(void *)Thread2,NULL);
pthread_create(&ppid1,&attr1,(void *)Thread1,NULL);

pthread_join(ppid3,NULL);
pthread_join(ppid2,NULL);
pthread_join(ppid1,NULL);
pthread_attr_destroy(&attr2);
pthread_attr_destroy(&attr1);
return 0;
}

在这个程序中,我创建了一个具有默认属性的线程和两个调度策略为 SCHED_RR 和特定优先级的线程。我的问题是:当我运行程序时,我几乎看不到线程 1 的输出。这是怎么发生的? 我认为线程 1 和线程 2 是实时进程,线程 3 是正常进程。因此线程 3 永远不会运行,直到线程 1 和线程 2 退出。但是在我的程序线程 1 和线程 2 永不退出,所以我预计只有线程 2 可以实际运行。 为什么我能看到线程2和线程3的输出,而看不到线程1的输出?

最佳答案

线程 3 可以运行,因为 0.05s 是为非运行时任务预留的,通过 echo -1 >/proc/sys/kernel/sched_rt_runtime_us 禁用它:

The default values for sched_rt_period_us (1000000 or 1s) and sched_rt_runtime_us (950000 or 0.95s). This gives 0.05s to be used by SCHED_OTHER (non-RT tasks). These defaults were chosen so that a run-away realtime tasks will not lock up the machine but leave a little time to recover it. By setting runtime to -1 you'd get the old behaviour back.

sched-rt-group.txt

线程 1 无法运行,因为线程 2 具有更高的优先级(注意 99 是 pthread 调用中的最高 RT 优先级,这与 Linux 内部编号矛盾并解释为 here ),并且循环调度仅在具有相同优先级的进程队列:

SCHED_RR tasks are scheduled by priority, and within a certain priority they are scheduled in a round-robin fashion. Each SCHED_RR task within a certain priority runs for its allotted timeslice, and then returns to the bottom of the list in its priority array queue.

Understanding the Linux 2.6.8.1 CPU Scheduler


关于如何找出发生这种情况的原因的一些说明。为此,我们需要源代码和动态跟踪器,如 SystemTap。切换线程(或者更准确地说上下文切换)can be traced通过 scheduler.ctxswitch 探测器,它是 sched_switch 跟踪点的包装器。

检查跟踪点周围的源代码表明新任务由调用 pick_next_task__schedule 函数处理:

3392    next = pick_next_task(rq, prev, cookie);
...
3397 if (likely(prev != next)) {
...
3402 trace_sched_switch(preempt, prev, next);

爬取源代码将我们引导至 pick_next_task_rt,它在特定条件下返回 NULL 而不是我们的线程。 SystemTap 时间到了!

# stap -e 'probe kernel.function("pick_next_task_rt").return { 
if ($return == 0) {
println($rq->rt$) } }' -c ./a.out
...
{.active={...}, .rt_nr_running=2, .highest_prio={...}, .rt_nr_migratory=2, .rt_nr_total=2,
.overloaded=1, .pushable_tasks={...}, .rt_throttled=1, .rt_time=950005330, .rt_runtime=950000000,
.rt_runtime_lock={...}, .rt_nr_boosted=0, .rq=0xffff8801bfc16c40,
.leaf_rt_rq_list={...}, .tg=0xffffffff81e3d480}
SCHED_OTHER

因此,当我们切换到 SCHED_OTHER 时,rt_time 似乎大于 950 毫秒并且设置了 rt_throttled 标志。进一步谷歌搜索导致 this answer和上面链接的文档。

关于c - 在linux中,为什么一个正常的进程仍然可以运行,而实时进程却不退出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46262490/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com