Видео ролики бесплатно онлайн

Смотреть мамочки видео

Официальный сайт morning-news 24/7/365

Смотреть видео бесплатно

dementiy 13.03.2010 00:36

CodingУправление процессами в Linux

Хочу рассказать в общих чертах об управлении процессами в Linux. Итак...

Может показаться, что в вашей системе все процессы выполняются одновременно, но это иллюзия, которую создает планировщик задач (sheduler). Планировщик задач отвечает за распределение процессорного времени между всеми процессами в системе.
Планировщик не представлен в виде какой-то одной функции, которая выполняла бы всю работу, но есть главная функция — schedule(), она определена в файле kernel/sched.c:

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
asmlinkage void __sched schedule(void)
{
struct task_struct *prev, *next;
unsigned long *switch_count;
struct rq *rq;
int cpu;

need_resched:
...
cpu = smp_processor_id();
rq = cpu_rq(cpu);
...
prev = rq->curr;
...
if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
if (unlikely(signal_pending_state(prev->state, prev)))
prev->state = TASK_RUNNING;
else
deactivate_task(rq, prev, 1);
switch_count = &prev-;>nvcsw;
}
...
if (unlikely(!rq->nr_running))
idle_balance(cpu, rq);
put_prev_task(rq, prev);
next = pick_next_task(rq);
if (likely(prev != next)) {
...
rq->curr = next;
...
context_switch(rq, prev, next); /* unlocks the rq */
...
} else
spin_unlock_irq(&rq-;>lock);
...
if (need_resched())
goto need_resched;
}
EXPORT_SYMBOL(schedule);


префикс __sched используется для функций, которые потенциально могут вызывать планировщик, в том числе и для самой функции schedule().

В schedule() выбирается очередь выполнения (в старых версиях планировщика, таких как O(1)-scheduler, очередь содержала списки задач, которые обслуживались по принципу FIFO - First Input First Output), которая связанна с конкретным процессором в системе (если процессор один, то и очередь всего одна) и из очереди выбирается следующий наиболее подходящий процесс на выполнение.
Как уже было сказано, с каждым процессором связана своя очередь выполнения (run queue, см. рис. 1).



Рис.1. Каждому процессору соответствует своя очередь выполнения

Очередь описывается структурой struct rq, которая определена в файле kernel/sched.c:

 1
2
3
4
5
6
7
8
9
10
11
12
struct rq {
...
unsigned long nr_running;
...
struct cfs_rq cfs;
struct rt_rq rt;
...
struct task_struct *curr, *idle;
...
int cpu;
...
};

nr_running содержит количество задач готовых к выполнению;
curr указывает на текущую выполняемую задачу;
idle указывает на idle процесс, работает, когда нет ни одной другой готовой к выполнению задачи;
cpu это номер процессора, с которым связана данная очередь;
cfs очередь выполнения CFS (Completely Fair Scheduler);
rt очередь выполнения RT (Real-Time).
процессы реального времени отличаются от обычных процессов приоритетом. Для процессов реального времени приоритеты находятся в диапазоне от 0 до 99, а для обычных процессов в диапазоне от 100 до 139. Чем меньше значение приоритета, тем выше сам приоритет (важность задачи).

В ядре Linux, начиная с версии 2.6.23, были введены классы планирования (schedule class). На сегодняшний день (для версии ядра 2.6.32) можно выделить два основных класса (есть третий для idle):
CFS schedule class — отвечает за работу с обычными процессами (kernel/sched_fair.c);
RT schedule class — отвечает за работу с процессами реального времени (kernel/sched_rt.c).Каждый процесс принадлежит только одному классу, который несет ответственность за управление этим процессом. Информация о том, какой класс управляет процессом хранится в виде указателя на класс в дескрипторе процесса:

include/linux/sched.h:
1
2
3
4
5
struct task_struct {
...
const struct sched_class *sched_class;
...
}


Структура класса определена в файле include/linux/sched.h и содержит в себе указатели на функции, такие как, например, включение и исключение из очереди выполнения:

1
2
3
4
5
6
7
8
struct sched_class { 
const struct sched_class *next;
void (*enqueue_task) (struct rq *rq, struct task_struct *p,
int wakeup);
void (*dequeue_task) (struct rq *rq, struct task_struct *p,
int sleep);
...
}


При создании нового процесса происходит вызов функции sched_fork() из copy_process() (описанной в прошлых статьях), в которой определяется к какому классу принадлежит процесс:

kernel/sched.c:
1
2
3
4
5
6
7
8
void sched_fork(struct task_struct *p, int clone_flags) 
{
...
p->prio = current->normal_prio;
if (!rt_prio(p->prio))
p->sched_class = &fair;_sched_class;
...
}


include/linux/sched.h:
1
2
3
4
5
6
7
8
#define MAX_USER_RT_PRIO     100
#define MAX_RT_PRIO MAX_USER_RT_PRIO
static inline int rt_prio(int prio)
{
if (unlikely(prio < MAX_RT_PRIO))
return 1;
return 0;
}


Если приоритет процесса больше 99, то устанавливается принадлежность процесса к классу CFS, который будет отвечать за управление этим процессом.
В зависимости от класса, к которому принадлежит процесс, он будет находиться в той или иной очереди выполнения — cfs_rq или rt_rq (см. рис. 2).


Рис.2. Схематичное представление очереди

Возвращаясь к функции schedule() было сказано, что выбирается наиболее подходящий процесс на выполнение:

kernel/sched.c (в функции schedule()):
1
2
3
...
next = pick_next_task(rq);
...


kernel/sched.c:
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
static inline struct task_struct *pick_next_task(struct rq *rq)
{
const struct sched_class *class;
struct task_struct *p;
if (likely(rq->nr_running == rq->cfs.nr_running)) {
p = fair_sched_class.pick_next_task(rq);
if (likely(p))
return p;
}
class = sched_class_highest;
for ( ; ; ) {
p = class->pick_next_task(rq);
if (p)
return p;
class = class->next;
}
}


Если количество процессов готовых к выполнению в общем равно количеству процессов принадлежащих к cfs_rq (rq->nr_running == rq->cfs.nr_running), то следовательно они все принадлежат к очереди cfs_rq и следующий процесс на выполнение будет выбираться по алгоритму CFS. В противном случае проходятся все классы, начиная с sched_class_highest (на самом деле это rt_sched_class), пока не будет выбран новый процесс на выполнение (см. рис. 3).


Рис. 3. Обход классов в поиске процесса

говоря о очереди выполнения cfs_rq, следует иметь ввиду, что на самом деле «очередь» представляет собой красно-черное дерево процессов, где самому левому листу дерева соответствует наибольший приоритет. Более подробно на сайте ibm

И последнее о чем хотелось бы еще сказать. Для многопроцессорных систем (SMP — Symmetric Multiprocessing) в планировщике реализована специальная функция load_balance() (kernel/sched.c), которая предназначена для того, чтобы процессор не только не «простаивал» (например, если его очередь пуста), но и как следствие, чтобы снизить нагрузку на другой процессор. Реализуется это за счет перемещения задач между очередями выполнения:


Рис. 4. Перемещение задачи из одной очереди в другую

P.S. Описано конечно же не все, а лишь малая часть, но как было сказано в самом начале преследовалась цель описать тему лишь в общих чертах.
P.P.S. И как всегда pdf'ка


Тэги: kernel processes scheduler
+ 25 -
Похожие Поделиться

warchief 13.03.2010 01:05 #
+ 0 -
Спасибо, жду следующую статью.
exelens 13.03.2010 09:06 #
+ 0 -
Присоединяюсь
Vzlom 13.03.2010 12:55 #
+ 1 -
Аналогично!!! Огромное спасибо =) очень полезная статейка
digiwhite 13.03.2010 11:59 #
+ 0 -
В мемориз :)
digiwhite 13.03.2010 12:20 #
+ 0 -
Структура класса определена в файле include/linux/sched.h и содержит в себе указатели на функции (методы класса), такие как, например, включение и исключение из очереди выполнения

Так-как разговор идет в контексте языка C, то я бы исключил упоминание таких понятий как "методы класса", дабы не вводить никого в заблуждение. Нету в C классов как таковых. Ну или используйте вместо этого "функции-члены" тогда.
dementiy 13.03.2010 19:23 #
+ 0 -
А я решил, что так может быть понятней будет, проведя некоторую аналогию с С++ (да и другими языками, в которых есть понятие класса), но раз может возникнуть некоторая неопределенность, то тогда убираю.
Vzlom 14.03.2010 00:45 #
+ 0 -
Отдельно данный вопрос освети для с++ Думаю будет полезно и правильно =)
dementiy 14.03.2010 02:09 #
+ 0 -
Я не совсем понял, что имелось ввиду. Я хотел сказать, что в С++ (как и в других объектно-ориентрированных языках) есть понятие класса, данные которого называют методами.
digiwhite 13.03.2010 12:24 #
+ 0 -
Было бы еще интересно для, так сказать, "самодостаточности" статьи добавить краткое описание функции likely :).
dementiy 13.03.2010 19:36 #
+ 0 -
В двух словах: likely означает вариант, который имеет большую вероятность для выполнения. В дальнейшем при компиляции будет проведена, некоторая оптимизация ассемблерного кода. Так же есть unlikely, то же самое, но наоборот, то есть менее вероятный вариант. likely и unlikely являются макросами, которые определены в файле inlude/linux/compiler.h
digiwhite 13.03.2010 20:54 #
+ 0 -
Посмотрел туда... жостко конечно. Что-то понять мне там особо не удалось :(
dementiy 13.03.2010 21:05 #
+ 1 -
На самом деле это рюшечки GCC. Здесь (правда на английском) в разделе "Optimization extensions" можно немного прочитать про них. Либо уже смотреть в документацию GCC.
digiwhite 13.03.2010 21:31 #
+ 0 -
Почитаю, спасибо :)
kstep 13.03.2010 13:45 #
+ 0 -
Спасибо за статью!
h0rr0rr_drag0n 13.03.2010 17:09 #
+ 0 -
Спасибо, было интересно! :-)

Смотреть видео онлайн

Онлайн видео бесплатно


Смотреть русское с разговорами видео

Online video HD

Видео скачать на телефон

Русские фильмы бесплатно

Full HD video online

Смотреть видео онлайн

Смотреть HD видео бесплатно

School смотреть онлайн