프로세스 그룹은 Linux 시스템에서 프로세스를 분류하고 관리하는 방법으로, 동일한 특성이나 관계를 가진 프로세스를 모아 논리적 단위를 형성할 수 있습니다. 프로세스 그룹의 기능은 프로세스의 제어, 통신 및 리소스 할당을 촉진하여 시스템의 효율성과 보안을 향상시키는 것입니다. 프로세스 그룹 스케줄링은 Linux 시스템에서 프로세스 그룹을 스케줄링하는 메커니즘으로, 프로세스 그룹의 속성과 요구 사항에 따라 적절한 CPU 시간과 리소스를 할당하여 시스템의 동시성과 응답성을 향상시킬 수 있습니다. 그러나 Linux 프로세스 그룹 스케줄링 메커니즘을 정말로 이해하고 있습니까? Linux에서 프로세스 그룹을 생성하고 관리하는 방법을 알고 계십니까? Linux에서 프로세스 그룹 스케줄링 메커니즘을 사용하고 구성하는 방법을 알고 계십니까? 이 기사에서는 Linux 프로세스 그룹 스케줄링 메커니즘에 대한 관련 지식을 자세히 소개하여 Linux에서 이 강력한 커널 기능을 더 잘 사용하고 이해할 수 있도록 합니다.
시스템 재시작 프로세스 중에 또 다른 마법의 프로세스 스케줄링 문제가 발생했는데, 시스템이 중단되고 30초 후에 시스템이 재설정되는 것을 발견했습니다. 시스템 재설정의 실제 이유는 원래 시스템이 아닌 하드웨어 감시 장치가 시스템을 다시 시작했기 때문입니다. 정상적인 재부팅 과정. Dog가 공급되지 않으면 하드웨어 Dog 기록의 재설정 시간이 30초 앞으로 밀립니다. 직렬 포트 기록 로그를 분석하면 당시 로그에 "sched: RT throttling activate"라는 문장이 인쇄되었습니다.
sched_rt_runtime_exceeded가 이 문장을 인쇄하는 것은 linux-3.0.101-0.7.17 버전 커널 코드에서 볼 수 있습니다. 커널 프로세스 그룹 스케줄링 프로세스에서 실시간 프로세스 스케줄링은 rt_rq->rt_throttled에 의해 제한됩니다. 아래에서 Linux의 프로세스 그룹 스케줄링 메커니즘에 대해 자세히 설명하겠습니다.
그룹 스케줄링은 N개의 프로세스를 전체적으로 처리하고 시스템의 스케줄링 프로세스에 참여하는 것을 의미하는 cgroup의 개념입니다. 이는 특히 예에 반영되어 있습니다. 작업 A에는 8개의 프로세스 또는 스레드가 있고 작업 B에는 2개의 프로세스가 있습니다. 아직 다른 프로세스나 스레드가 있는 경우 작업 A의 CPU 사용량은 40% 이하, 작업 B의 CPU 사용량은 40% 이하, 기타 작업의 CPU 사용량을 제어해야 합니다. 그러면 cgroup 임계값을 설정할 수 있는 권한이 있습니다. cgroup A는 200으로 설정되고, cgroup B는 200으로 설정되며, 기타 작업은 기본적으로 100으로 설정되어 CPU 제어 기능을 실현합니다.
커널에서 프로세스 그룹은 task_group에 의해 관리되며 관련된 내용 중 상당수는 cgroup 제어 메커니즘입니다. 또한 개발 단위가 작성됩니다. 여기서는 그룹 스케줄링에 중점을 둔 부분을 참조합니다. .
스케줄링 단위에는 일반 스케줄링 단위와 실시간 프로세스 스케줄링 단위의 두 가지 유형이 있습니다.
으아악실시간 예약과 일반 예약 대기열에 대해 설명해야 할 옵션이 유사하므로 예약 대기열을 살펴보겠습니다. 실시간 대기열을 예로 들어보겠습니다.
으아악위의 세 가지 구조를 분석하면 다음 그림을 얻을 수 있습니다(그림을 확대하려면 클릭).
task_group
그림에서 볼 수 있듯이 스케줄링 단위와 스케줄링 큐는 또 다른 별도의 트리 구조인 트리 노드로 결합됩니다. 그러나 스케줄링 단위는 TASK_RUNNING 프로세스가 있는 경우에만 배치됩니다. 스케줄링 단위에서 디스패치 큐로 들어갑니다.
또 다른 점은 그룹 스케줄링이 있기 전에는 각 CPU에 하나의 스케줄링 큐만 있었다는 것입니다. 그 당시에는 모든 프로세스가 하나의 스케줄링 그룹에 있었다는 것을 이해할 수 있습니다. 이제 각 스케줄링 그룹은 각 CPU에 스케줄링 큐를 갖습니다. 스케줄링 프로세스 중에 시스템은 원래 실행할 프로세스를 선택합니다. 스케줄링이 발생하면 스케줄링 프로세스는 스케줄링 정책에 따라 결정된 스케줄링 단위를 찾습니다. 단위가 task_group이면 실행 큐는 적합한 스케줄링 단위를 선택하고 마지막으로 적합한 태스크 스케줄링 단위를 찾습니다. 전체 프로세스는 트리 순회입니다. TASK_RUNNING 프로세스가 있는 task_group은 트리의 노드이고 작업 예약 단위는 트리의 리프입니다.
그룹 프로세스 스케줄링의 목적은 실시간 프로세스 스케줄링과 일반 프로세스 스케줄링, 즉 rt 및 cfs 스케줄링을 완료하는 것인 원본과 다르지 않습니다.
文章前面示例中提到的任务分配CPU,说的就是cfs调度,对于CFS调度而言,调度单元和普通调度进程没有多大区别,调度单元由自己的调度优先级,而且不受调度进程的影响,每个task_group都有一个shares,share并非我们说的进程优先级,而是调度权重,这个是cfs调度管理的概念,但在cfs中最终体现到调度优先排序上。shares值默认都是相同的,所有没有设置权重的值,CPU都是按旧有的cfs管理分配的。总结的说,就是cfs组调度策略没变化。具体到cgroup的CPU控制机制上再说。
实时进程的优先级是设置固定,调度器总是选择优先级最高的进程运行。而在组调度中,调度单元的优先级则是组内优先级最高的调度单元的优先级值,也就是说调度单元的优先级受子调度单元影响,如果一个进程进入了调度单元,那么它所有的父调度单元的调度队列都要重排。实际上我们看到的结果是,调度器总是选择优先级最高的实时进程调度,那么组调度对实时进程控制机制是怎么样的?
在前面的rt_rq实时进程运行队列里面提到rt_time和rt_runtime,一个是运行累计时间,一个是最大运行时间,当运行累计时间超过最大运行时间的时候,rt_throttled则被设置为1,见sched_rt_runtime_exceeded函数。
if (rt_rq->rt_time > runtime) { rt_rq->rt_throttled = 1; if (rt_rq_throttled(rt_rq)) { sched_rt_rq_dequeue(rt_rq); return 1; } }
设置为1意味着实时队列中被限制了,如__enqueue_rt_entity函数,不能入队。
static inline int rt_rq_throttled(struct rt_rq *rt_rq) { return rt_rq->rt_throttled && !rt_rq->rt_nr_boosted; } static void __enqueue_rt_entity(struct sched_rt_entity *rt_se, bool head) { /* * Don't enqueue the group if its throttled, or when empty. * The latter is a consequence of the former when a child group * get throttled and the current group doesn't have any other * active members. */ if (group_rq && (rt_rq_throttled(group_rq) || !group_rq->rt_nr_running)) return; ..... }
其实还有一个隐藏的时间概念,即sched_rt_period_us,意味着sched_rt_period_us时间内,实时进程可以占用CPU rt_runtime时间,如果实时进程每个时间周期内都没有调度,则在do_sched_rt_period_timer定时器函数中将rt_time减去一个周期,然后比较rt_runtime,恢复rt_throttled。
//overrun来自对周期时间定时器误差的校正 rt_rq->rt_time -= min(rt_rq->rt_time, overrun*runtime); if (rt_rq->rt_throttled && rt_rq->rt_time rt_throttled = 0; enqueue = 1;
则对于cgroup控制实时进程的占用比则是通过rt_runtime实现的,对于root_task_group,也即是所有进程在一个cgroup下,则是通过/proc/sys/kernel/sched_rt_period_us和/proc/sys/kernel/sched_rt_runtime_us接口设置的,默认值是1s和0.95s。这么看以为实时进程只能占用95%CPU,那么实时进程占用CPU100%导致进程挂死的问题怎么出现了?
原来实时进程所在的CPU占用超时了,实时进程的rt_runtime可以向别的cpu借用,将其他CPU剩余的rt_runtime-rt_time的值借过来,如此rt_time可以最大等于rt_runtime,造成事实上的单核CPU达到100%。这样做的目的自然规避了实时进程缺少CPU时间而向其他核迁移的成本,未绑核的普通进程自然也可以迁移其他CPU上,不会得不到调度,当然绑核进程仍然是个杯具。
static int do_balance_runtime(struct rt_rq *rt_rq) { struct rt_bandwidth *rt_b = sched_rt_bandwidth(rt_rq); struct root_domain *rd = cpu_rq(smp_processor_id())->rd; int i, weight, more = 0; u64 rt_period; weight = cpumask_weight(rd->span); raw_spin_lock(&rt_b->rt_runtime_lock); rt_period = ktime_to_ns(rt_b->rt_period); for_each_cpu(i, rd->span) { struct rt_rq *iter = sched_rt_period_rt_rq(rt_b, i); s64 diff; if (iter == rt_rq) continue; raw_spin_lock(&iter->rt_runtime_lock); /* * Either all rqs have inf runtime and there's nothing to steal * or __disable_runtime() below sets a specific rq to inf to * indicate its been disabled and disalow stealing. */ if (iter->rt_runtime == RUNTIME_INF) goto next; /* * From runqueues with spare time, take 1/n part of their * spare time, but no more than our period. */ diff = iter->rt_runtime - iter->rt_time; if (diff > 0) { diff = div_u64((u64)diff, weight); if (rt_rq->rt_runtime + diff > rt_period) diff = rt_period - rt_rq->rt_runtime; iter->rt_runtime -= diff; rt_rq->rt_runtime += diff; more = 1; if (rt_rq->rt_runtime == rt_period) { raw_spin_unlock(&iter->rt_runtime_lock); break; } } next: raw_spin_unlock(&iter->rt_runtime_lock); } raw_spin_unlock(&rt_b->rt_runtime_lock); return more; }
通过本文,你应该对 Linux 进程组调度机制有了一个深入的了解,知道了它的定义、原理、流程和优化方法。你也应该明白了进程组调度机制的作用和影响,以及如何在 Linux 下正确地使用和配置进程组调度机制。我们建议你在使用 Linux 系统时,使用进程组调度机制来提高系统的效率和安全性。同时,我们也提醒你在使用进程组调度机制时要注意一些潜在的问题和挑战,如进程组类型、优先级、限制等。希望本文能够帮助你更好地使用 Linux 系统,让你在 Linux 下享受进程组调度机制的优势和便利。
위 내용은 Linux 프로세스 그룹 스케줄링 메커니즘: 프로세스를 그룹화하고 스케줄링하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!