Основываясь на вашем новом коде [и теле функции pick_proc
], единственные возможные сбои — это те, которые я описал выше в своих главных комментариях.
То есть proc_ptr
должно быть допустимым (т. е. отличным от NULL), а proc_ptr->p_nr
должно находиться в диапазоне, чтобы предотвратить UB.
Каковы значения NR_TASKS
и NR_PROCS
? Может ли recent_time
поместиться в стеке? Размер стека в ядре обычно очень ограничен. Например, под Linux у вас может быть только около 4 КБ стека.
Таким образом, если NR_PROCS
было (например) 32767, то recent_time
нельзя было не помещать в стек.
И я не вижу причин иметь независимый массив для этого в стеке, поскольку он не будет сохраняться после вызова.
Итак, чтобы помочь в отладке, я бы добавил static
к определению recent_time
.
Вам нужно будет добавить код отладки, чтобы увидеть, в чем проблема.
Вот пример. Отрегулируйте printf
et. др. чтобы соответствовать механизму печати ядра minux
[при условии, что вы можете печатать в состоянии, в котором вызывается ваш код]:
#ifdef DEBUG
#define dbgprt(_fmt...) \
printf(_fmt)
#else
#define dbgprt(_fmt...) \
do { } while (0)
#endif
PRIVATE void
pick_proc()
{
register struct proc *rp; /* process to run */
int q; /* iterate over queues */
/* Modified Code here */
int realtime;
static clock_t recent_time[NR_TASKS + NR_PROCS];
clock_t stopwatch;
do {
// bad pointer
dbgprt("pick_proc: proc_ptr=%p\n",proc_ptr);
if (proc_ptr == NULL)
break;
// out of range process number
dbgprt("pick_proc: p_nr=%u\n",proc_ptr->p_nr);
if (proc_ptr->p_nr >= NR_PROCS)
break;
realtime = getuptime();
dbgprt("pick_proc: realtime=%d\n",realtime);
recent_time[proc_ptr->p_nr + NR_TASKS] = realtime - stopwatch;
stopwatch = realtime;
} while (0);
for (q = 0; q < NR_SCHED_QUEUES; q++) {
if ((rp = rdy_head[q]) != NIL_PROC) {
next_ptr = rp;
if (priv(rp)->s_flags & BILLABLE)
bill_ptr = rp;
return;
}
}
}
ОБНОВЛЕНИЕ:
Я не могу не подчеркнуть важность операторов assert
и/или if
для предварительной проверки всего, что вы делаете для предотвращения UB. И отладка printf
, например:
TRACE(VF_PICKPROC,printf("hello world\n"););
Кстати, я вытащил исходный код minix
из github:
git clone https://github.com/Stichting-MINIX-Research-Foundation/minix.git
Похоже, что у вас может быть устаревший исходный код, потому что pick_proc
в этом репозитории содержит больше кода, связанного с SMP.
NR_TASKS + NR_PROCS должны быть квантами времени, взятыми из таблицы процессов. Первоначально я объявил массив и секундомер в proc.h, но функция pic_proc не имела к ним доступа.
Вы действительно хотите либо использовать существующие поля в struct proc
, либо добавить свои собственные вместо создания отдельного массива [индексированного по номеру процесса].
Я добавил несколько скриншотов кода, вызывающего pic_proc. Я думаю, мне нужно изменить sched и оставить pic_proc в покое. Массив в pic_proc должен получать кванты времени от каждого процесса из таблицы процессов.
Да, надеюсь, истекшее процессорное время для каждого процесса находится в struct proc
. Если нет, вам придется добавить поле. Я подозреваю, что p_user_time
[и/или p_sys_time
] может быть тем, что вам нужно. И, может быть, p_cpu_time_left
. Другие возможности: p_accounting.time_in_queue
. Или p_cycles
pick_proc
просто просматривает начало заданной очереди выполнения. Таким образом, вам может потребоваться изменить код, который фактически вставляет данный процесс в эту очередь. Это может быть enqueue
и/или dequeue
. Похоже, что они учитывают приоритет процесса [p_priority
] и вытеснение.
Я пробежался глазами по коду ядра и предполагаю, что sched_proc
может представлять интерес.
Но я действительно думаю, что вам нужно более внимательно изучить код ядра, чтобы увидеть, какие функции на самом деле добавляют процесс в данную очередь выполнения. И как они выбирают процесс и из какой очереди.
При добавлении процесса он может просто добавляться в хвост. Этот код должен будет сканировать очередь и [при условии, что приоритет такой же], вставлять на основе минимальной загрузки ЦП.
person
Craig Estey
schedule
23.03.2021
proc_ptr
действительным при вызове вашего кода? Это может бытьNULL
. Находится лиproc_ptr->p_nr
в диапазоне от 0 доNR_PROC - 1
? Если нет, у вас есть UB [неопределенное поведение], и вы портите стек [я предполагаю, чтоrecent_time
находится в стеке], потому что вы индексируете за концомrecent_time
. Вы должны добавитьif
проверки операторов на достоверность и добавить [minux эквивалент]printk
для отображения значений. Возможно,realtime
должно бытьunsigned
[и/илиclock_t
, поскольку ваша настройкаstopwatch
соответствует его значению]. Может лиrecent_time
поместиться в стеке? - person Craig Estey   schedule 24.03.2021