Sie sind auf Seite 1von 8

ESCOLA POLITCNICA DA UNIVERSIDADE DE SO PAULO

Departamento de Engenharia de Computao e Sistemas Digitais

PCS 2042 Sistemas Operacionais

Projeto 2
Tema D: Escalonamento de processos no
MINIX3

Autores:
Jun Miyazaki
Leonardo Elias de Souza Oliveira
Lucas Martins De Marchi
Lus Gustavo Ludescher
Lus Felipe Lu
Marcelo Trevizan Mazon
Objetivo
O objetivo deste projeto continuar o estudo do cdigo fonte do MINIX3 iniciado no Projeto
1, como complementao da disciplina terica PCS 2042 Sistemas Operacionais.

O estudo proposto referente ao mtodo de escalonamento (ou agendamento) de processos


implementado no MINIX 3, e resume-se a explic-lo, analisando o cdigo em que
implementado, e alter-lo, recompilando o kernel do sistema.

Os resultados sero apresentados no presente documento.


Estudo do cdigo
O arquivo em C com o cdigo do escalonador de processos /usr/src/kernel/proc.c (alm
do arquivo header proc.h). Nele, as funes schede pick_proc so as responsveis pela
implementao da poltica de escalonamento do sistema operacional. A anlise desses
cdigos levou concluso de que se trata de um agendamento por prioridade.

Os processos no MINIX3 so divididos em 16 (NR_SCHED_QUEUES) filas de prioridade,


sendo que a ltima (prioridade IDLE_Q) para os processos em IDLE, no sendo, portanto,
acessvel aos demais processos. Algumas constantes do escalonamento de processos de
definio das filas de prioridades so definidas no arquivo /usr/src/kernel/proc.h, como
segue:

#define NR_SCHED_QUEUES 16 /* MUST equal minimum priority + 1 */


#define TASK_Q 0 /* highest, used for kernel tasks */
#define MAX_USER_Q 0 /* highest priority for user processes */
#define USER_Q 7 /* default (should correspond to nice 0) */
#define MIN_USER_Q 14 /* minimum priority for user processes */
#define IDLE_Q 15 /* lowest, only IDLE process goes here */

Processos com maior prioridade tm menores ndices de prioridade. Os processos de tarefas


do Kernel so diferenciados dos processos do usurio, recebendo uma prioridade maior (0
contra 7). Alm de possurem prioridade mais elevada, as tarefas do Kernel recebem um
quantum (qs) maior, para que no sejam freqentemente interrompidas (por preempo).
Certos processos rodando em modo usurio tambm recebem prioridade maior que os
demais, como aqueles relativos ao gerenciamento do sistema de arquivo (FS) e ao
gerenciamento de memria (MM). Abaixo, o cdigo (/usr/src/kernel/table.c) das atribuies
iniciais de prioridades e quanta:

PUBLIC struct boot_image image[] = {


/* process nr, pc, flags, qs, queue, stack, traps, ipcto, call, name */
{ IDLE, idle_task, IDL_F, 8, IDLE_Q, IDL_S, 0, 0, 0, "IDLE" },
{ CLOCK,clock_task, TSK_F, 64, TASK_Q, TSK_S, TSK_T, 0, 0, "CLOCK" },
{ SYSTEM, sys_task, TSK_F, 64, TASK_Q, TSK_S, TSK_T, 0, 0, "SYSTEM"},
{ HARDWARE, 0, TSK_F, 64, TASK_Q, HRD_S, 0, 0, 0, "KERNEL"},
{ PM_PROC_NR, 0, SRV_F, 32, 3, 0, SRV_T, SRV_M, PM_C, "pm" },
{ FS_PROC_NR, 0, SRV_F, 32, 4, 0, SRV_T, SRV_M, FS_C, "fs" },
{ RS_PROC_NR, 0, SRV_F, 4, 3, 0, SRV_T, SYS_M, RS_C, "rs" },
{ TTY_PROC_NR, 0, SRV_F, 4, 1, 0, SRV_T, SYS_M, DRV_C, "tty" },
{ MEM_PROC_NR, 0, SRV_F, 4, 2, 0, SRV_T, DRV_M, MEM_C, "memory"},
{ LOG_PROC_NR, 0, SRV_F, 4, 2, 0, SRV_T, SYS_M, DRV_C, "log" },
{ DRVR_PROC_NR, 0, SRV_F, 4, 2, 0, SRV_T, SYS_M, DRV_C, "driver"},
{ INIT_PROC_NR, 0, USR_F, 8, USER_Q, 0, USR_T, USR_M, 0, "init" },
};
Processos com igual prioridade so colocados em filas. A funo enqueue a que aloca os
processos, chamando, para isso, a funo sched, que determina onde (qual fila e em que
posio: topo ou fim) o mesmo deve ser posicionado. Em seguida, aciona a funo
pick_proc, que escolhe o processo a ser executado de acordo com a situao das filas.

/* Determine where to insert to process. */


sched(rp, &q, &front);

/* Now add the process to the queue. */


if (rdy_head[q] == NIL_PROC) { /* add to empty queue */
rdy_head[q] = rdy_tail[q] = rp; /* create a new queue */
rp->p_nextready = NIL_PROC; /* mark new end */
}
else if (front) { /* add to head of queue */
rp->p_nextready = rdy_head[q]; /* chain head of queue */
rdy_head[q] = rp; /* set new queue head */
}
else { /* add to tail of queue */
rdy_tail[q]->p_nextready = rp; /* chain tail of queue */
rdy_tail[q] = rp; /* set new queue tail */
rp->p_nextready = NIL_PROC; /* mark new end */
}

/* Now select the next process to run. */


pick_proc();

Para a determinao da prioridade que deve ser atribuda a um processo, ou seja, em qual das
filas de prioridade o mesmo deve ser colocado, a funo sched verifica se o mesmo ainda
tem tempo de execuo, ou seja, se ele ainda no consumiu todo o quantum que lhe
atribudo. Caso no haja, ele recebe um novo quantum e uma menor prioridade (ou seja, um
ndice maior nas filas de prioridades). A varivel que guarda o tempo restante, time_left,
tambm usada para indicar se o processo deve ser posicionado no comeo ou no fim da fila,
de acordo com o parmetro de retorno front. Caso haja tempo sobrando, deve ir para o
incio da fila para ser executado primeiro. Se no, colocado no fim da fila de sua prioridade.
/*===========================================================================*
* sched *
*===========================================================================*/
PRIVATE void sched(rp, queue, front)
register struct proc *rp; /* process to be scheduled */
int *queue; /* return: queue to use */
int *front; /* return: front or back */
{
/* This function determines the scheduling policy. It is called whenever a
* process must be added to one of the scheduling queues to decide where to
* insert it. As a side-effect the process' priority may be updated.
*/
int time_left = (rp->p_ticks_left > 0); /* quantum fully consumed */

/* Check whether the process has time left. Otherwise give a new quantum
* and lower the process priority, unless the process already is in the
* lowest queue.
*/
if ( ! time_left) { /* quantum consumed ? */
rp->p_ticks_left = rp->p_quantum_size; /* give new quantum */
if (rp->p_priority < (IDLE_Q-1)) (
rp->p_priority += 1; /* lower priority */
}
}

/* If there is time left, the process is added to the front of its queue,
* so that it can immediately run. The queue to use simply is always the
* process' current priority.
*/
*queue = rp->p_priority;
*front = time_left;
}
Na funo pick_proc o processo no incio da fila de maior prioridade (menor ndice) no-
vazia escolhido. Trata-se de um iterador que comea pela fila de ndice 0, at que seja
encontrado um processo. Se no houver nenhum disponvel, entra-se na fila de IDLE.

/*===========================================================================*
* pick_proc *
*===========================================================================*/
PRIVATE void pick_proc()
{
/* Decide who to run now. A new process is selected by setting 'next_ptr'.
* When a billable process is selected, record it in 'bill_ptr', so that the
* clock task can tell who to bill for system time.
*/
register struct proc *rp; /* process to run */
int q; /* iterate over queues */

/* Check each of the scheduling queues for ready processes. The number of
* queues is defined in proc.h, and priorities are set in the image table.
* The lowest queue contains IDLE, which is always ready.
*/
for (q=0; q < NR_SCHED_QUEUES; q++) {
if ( (rp = rdy_head[q]) != NIL_PROC) {
next_ptr = rp; /* run process 'rp' next */
if (priv(rp)->s_flags & BILLABLE)
bill_ptr = rp; /* bill for system time */
return;
}
}
}
Alterao do cdigo
Props-se alterar o cdigo do MINIX3 a fim de mudar a sua poltica de escalonamento para o
agendamento por sorteio. Em linhas gerais, esse mtodo distribui bilhetes para os
processos em quantidades que variam de acordo com prioridades, tempos de execuo
conhecidos ou estimados, entre outros. Quando deve-se executar um processo, sorteia-se um
bilhete, sendo que processos com maior nmero de bilhetes tm maior probabilidade de
serem sorteados.

Para implementao de tal poltica no MINIX3, escolheu-se manter o mtodo de atribuio


de prioridades definido na funo sched, mas modificou-se a funo pick_proc para que
a mesma pudesse implementar o mtodo de sorteio baseado na distribuio de bilhetes.

Para a distribuio de bilhetes, ainda leva-se em conta a prioridade do processo, de modo que
processos com maior prioridade ganham maior nmero de bilhetes. definido o nmero de
bilhetes para cada fila de prioridade i (n_tickets_i = (16 - prioridade_i) * n_processos_i).
Somam-se os valores de todas as filas, e faz-se um sorteio de 1 at o resultado da soma.
Percorrem-se os nveis at encontrar a fila a que pertence o nmero sorteado (subtraindo o
nmero sorteado de n_tickets_i), e identifica-se o processo da fila que foi sorteado (dividindo
o nmero sorteado pelo nmero de bilhetes de cada processo da fila).

A ltima fila, a de IDLE, no entra no sorteio, pois s deve ser acionada quando no houver
outros processos nas filas.

Resumindo, processos com maior prioridade recebem mais bilhetes e tm maior


probabilidade de serem sorteados. A ordenao da fila serve apenas para identificao do
processo dentro de um mesmo nvel de prioridade, tais processos tm a mesma chance de
serem sorteados, pois recebem o mesmo nmero de bilhetes.

O cdigo da funo pick_proc, que foi a mais alterada est em anexo.


Anexo - pick_proc()
/*===========================================================================*
*pick_proc*
*===========================================================================*/
PRIVATEvoidpick_proc()
{
/*Decidewhotorunnow.Anewprocessisselectedbysetting'next_ptr'.
*Whenabillableprocessisselected,recorditin'bill_ptr',sothatthe
*clocktaskcantellwhotobillforsystemtime.
*/
registerstructproc*rp;/*processtorun*/
intq;/*iterateoverqueues*/

intnumrandom,tickets,i;

/*Checkeachoftheschedulingqueuesforreadyprocesses.Thenumberof
*queuesisdefinedinproc.h,andprioritiesaresetinthetasktable.
*ThelowestqueuecontainsIDLE,whichisalwaysready.
*/

/*Sumoftickets.Iterateintonumber_of_process_per_queuevector*/
for(q=0,tickets=0;q<NR_SCHED_QUEUES1;q++)
tickets+=(nr_procs_rdy[q]*(NR_SCHED_QUEUES1q));

/*Ifnoprocessesar*/
if(tickets==0)
rp=rdy_head[NR_SCHED_QUEUES1];
else{
numrandom=(rand()%(tickets1))+1;
/*numrandom=tickets/2;*/
for(q=0;q<NR_SCHED_QUEUES1;q++){
tickets=(nr_procs_rdy[q]*(NR_SCHED_QUEUES1q));
if(numrandom<=tickets){
rp=rdy_head[q];

if(numrandom%(NR_SCHED_QUEUES1q)==0)i=1;
elsei=0;
for(;(rp!=NIL_PROC)&&(i<((int)(numrandom/(NR_SCHED_QUEUES1q))));i++)
rp=rp>p_nextready;
}
else
numrandom=tickets;
}

}
if(rp!=NIL_PROC){
next_ptr=rp;
if(priv(rp)>s_flags&BILLABLE)
bill_ptr=rp;
return;
}
elsekprintf("erroinesperado....rp==NIL_PROC");
}

Das könnte Ihnen auch gefallen