PONTIFÍCIA UNIVERSIDADE CATÓLICA DE MINAS GERAIS Campus de Poços de Caldas Curso de Graduação em Ciência da Computação
LABORATÓRIO DE SISTEMAS OPERACIONAIS Escalonador
Dyego Henrique Melo Dias Professor: Dr. João Carlos de Moraes Morselli Junior
Poços de Caldas 11/06/2010
PONTIFÍCIA UNIVERSIDADE CATÓLICA DE MINAS GERAIS Campus de Poços de Caldas Curso de Graduação em Ciência da Computação
LABORATÓRIO DE SISTEMAS OPERACIONAIS: Escalonador
Trabalho apresentada à disciplina de Laboratório de Sistemas Operacionais, do Curso de Ciência da Computação como requisito parcial para obtenção do título de Bacharel em Ciência da Computação da Pontifícia Universidade Católica de Minas Gerais.
Dyego Henrique Melo Dias Professor: Dr. João Carlos de Moraes Morselli Junior
Poços de Caldas 11/06/201 2
Sumário 1. 2.
Introdução ......................................... ............................................................... ............................................ ............................................ ........................... ..... 5 Sistema Operacional ........................................... ................................................................. ............................................ ............................... ......... 6 2.1. System Calls .......................................... ................................................................ ............................................ ...................................... ................ 6 2.2. Processos ........................................... ................................................................. ............................................ .......................................... .................... 6 2.3. Arquivos ............................................ .................................................................. ............................................ .......................................... .................... 7 3. Escalonador de Processos ........................................... ................................................................. ............................................ ........................ 8 3.1. Objetivos do Escalonamento Escalonamento ........................................... ................................................................. .................................. ............ 8 3.2. Algoritmos Escalonadores Escalonadores ........................................... ................................................................. ...................................... ................ 8 3.2.1. FIFO ........................................... ................................................................. ............................................ .......................................... .................... 9 3.2.2. SJF ........................................... ................................................................. ............................................ ............................................ ........................ 9 3.2.3. SRT ............................................ .................................................................. ............................................ .......................................... .................... 9 3.2.4. Algoritmo Loteria ............................................ .................................................................. .......................................... .................... 9 3.2.5. Escalonamento Escalonamento garantido ............................................ .................................................................. ............................... ......... 9 3.2.6. RR ........................................... ................................................................. ............................................ ............................................ ........................ 9 3.2.7. Múltiplas Filas ........................................... ................................................................. ............................................ ........................... ..... 9 4. Simulação .......................................... ................................................................ ............................................ ............................................ ......................... ... 10 5. Funcionamento ......................................... ............................................................... ............................................ ........................................ .................. 11 6. FILAS ............................................ .................................................................. ............................................ ............................................ ............................. ....... 12 7. Simulações ............................................ .................................................................. ............................................ ........................................... ..................... 13 7.1. Simulação 1 ........................................... ................................................................. ............................................ .................................... .............. 13 7.2. Simulação 2 ........................................... ................................................................. ............................................ .................................... .............. 14 7.3. Simulação 3 ........................................... ................................................................. ............................................ .................................... .............. 15 7.4. Simulação 4 ........................................... ................................................................. ............................................ .................................... .............. 16 8. Comparando .......................................... ................................................................ ............................................ ........................................... ..................... 17 8.3. Quantidade total de starvation durante a simulação. ....................................... ....................................... 18 8.4. Conclusão das Simulações .......................................... ................................................................ .................................... .............. 19 9. Outras Simulações ............................................ .................................................................. ............................................ ................................ .......... 20 9.1. Simulação 5 ........................................... ................................................................. ............................................ .................................... .............. 20 9.2. Simulação 6 ........................................... ................................................................. ............................................ .................................... .............. 21 9.3. Simulação 7 ........................................... ................................................................. ............................................ .................................... .............. 22 9.4. Simulação 8 ........................................... ................................................................. ............................................ .................................... .............. 23 10. Média de Throughput ........................................... ................................................................. ............................................ ......................... ... 24 11. COMPARAÇÃO DAS SIMULAÇÕES 6, 7, 8 e 9 ......................................... ............................................ ... 27 11.1. Quantidade total de processos criados durante a simulação. ....................... ....................... 27 11.2. Quantidade total de processos executados executados durante a simulação. ................. 28 11.3. Quantidade total de starvation durante a simulação. ................................... ................................... 28
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
3
13. CONCLUSÃO SIMULAÇÃO 2 ........................................... ................................................................. ............................. ....... 29 14. Bibliografia ........................................... ................................................................. ............................................ ........................................ .................. 30 15. Anexos ........................................... ................................................................. ............................................ ............................................ ......................... ... 31 15.1. Escalonador.c ............................................ .................................................................. ............................................ ............................. ....... 31 15.2. Bibli.h ............................................ .................................................................. ............................................ ........................................ .................. 34 15.3. Estatistica.txt .......................................... ................................................................ ............................................ ................................ .......... 38
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
U
4
1. Introdução
Durante o percorrer do curso, estudamos na matéria de Sistemas Operacionais os Sistemas Operacionais em si e sua funcionalidades básicas, será apresentado neste documento uma explicação sobre escalonador (scheduler) e variáveis que fazem parte de sua implementação e execução. Também será apresentado apresentada a implementação de um escalonador básico, e os testes realizados em cada cenário no escalonador implementado.
5
2. Sistema Operacional
Segundo Tanenbaum & Woodhull em [Sistemas Operacionais, 2000], o programa de sistemas mais fundamental é o Sistema Operacional, que controla todos os recursos do computador e fornece a base sobre a qual os programas aplicativos podem ser escritos. São os sistemas operacionais que proporcionam uma interface de iteração para o usuário e o hardware, ele funciona como um intermediador entre usuário e hardware. Um Sistema Operacional é dividido em partes para seu funcionamento ser realizado com sucesso, estas partes são, as System Calls, os Processos, os Arquivos e o Shell.
2.1.
System Calls
System Calls são instruções estendidas que fazem a interface entre o Sistema Operacional e os Programas de Usuários. Tais Instruções variam de Sistema Operacional para Sistema Operacional.
2.2.
Processos
O conceito mais importante no estudo de sistemas operacionais, é o conceito de processo. Em um computador multiprogramado, que contem vários programas executando simultaneamente na memória, corresponde a um procedimento ou seqüência de instruções e um conjunto de dados variáveis utilizadas pelo programa. Além das instruções e dados, cada programa em execução possui uma área de memória correspondente para armazenar os valores dos registradores da UCP, quando o programa, por algum motivo, não estiver sendo executado. Essa área de memória é conhecida como registro
6
descritor e, além dos valores dos registradores da UCP, contém outras informações. Assim, em um determinado sistema, cada programa em execução constitui um processo. Portanto, podemos definir processo como sendo um programa em execução, o qual é constituído por uma seqüência de instruções, um conjunto de dados e um registro descritor.
2.3.
Arquivos
Arquivos são informações contidas em Disco ou dispositivos de I/O, segundo Tanenbaum & Woodhull em [Sistemas Operacionais, 2000], as chamadas de sistemas são necessárias para criar, para remover, para ler e para escrever arquivos. Antes de um arquivo poder ser lido, ele deve ser aberto e depois de lido deve ser fechado, assim chamadas são fornecidas para tais coisas. Tais chamadas são interpretadas e executadas pelo Sistema Operacional, que manipula o disco onde o arquivo e informações presentes nele estão contidas.
7
3. Escalonador de Processos
Quando um ou mais processos estão prontos para serem executados, o Sistema Operacional deve decidir qual deles vai ser executado primeiro. A parte do Sistema Operacional responsável por essa decisão é chamada de escalonador, e o algoritmo usado para tal é chamado de algoritmo de escalonamento. Em sistemas multiusuários e de tempo compartilhado o algoritmo de escalonamento é bem complexo. O Escalonador de Processos (scheduling ), ), é uma atividade exercida pelo escalonador, possibilitando assim que se execute mais processos de uma só vez, onde estes processos são divididos por prioridade, assim os processos com maior prioridade como os de I/O Bound e os Computacionalmente intensivos.
3.1.
Objetivos do Escalonamento
Justiça: fazer com que cada processo ganhe seu tempo justo, para usarem o mesmo tempo na CPU; Eficiência: manter a CPU ocupada a maior parte do tempo; Tempo de Reposta: minimizar o tempo de resposta para os usuários interativos; Tempo de Turnaround: minimizar o tempo que usuários devem esperar pelo resultado; Throughput: maximizar o número de tarefas executados por unidade de tempo.
3.2.
Algoritmos Escalonadores
Existem dois tipos de algoritmos de escalonamento os preemptivos e os não preemptivos, onde os algoritmos preemptivos permitem que os processos sejam interrompidos durante sua execução e os algoritmos não preemptivos, por serem utilizados exclusivamente em sistemas monoprocessados.
8
Alguns algoritmos de escalonamento mais utilizados são:
3.2.1. FIFO (First in, First Out) ou FCFS (First come, first served) que como seu próprio nome já diz, o primeiro que chega será o primeiro a ser executado; 3.2.2. SJF (Shortest Job First): Onde o menor processo ganhará a CPU e atrás do mesmo formar uma fila de processos por ordem crescente de tempo de execução; 3.2.3. SRT (Shortest Remaining Time): Neste algoritmo é escolhido o processo que possua o menor tempo restante, mesmo que esse processo chegue à metade de uma operação, se o processo novo for menor ele será executado primeiro; 3.2.4. Algoritmo Loteria: O Sistema Operacional distribui tokens (fichas), numerados entre os processos, para o escalonamento é sorteado um numero aleatório para que o processo ganhe a vez na CPU, processos com mais tokens têm mais chance de receber antes a CPU. 3.2.5. Escalonamento garantido : Este algoritmo busca cumprir promessas de alocação de CPU o mais preciso possível. 3.2.6. RR (Round-Robin): Nesse escalonamento o sistema operacional possui um timer, chamado de quantum, onde todos os processos ganham o mesmo valor de quantum para rodarem na CPU. Com exceção do algoritmo RR e escalonamento garantido, todos os outros sofrem do problema de Inanição ( starvation ). ). 3.2.7. Múltiplas Filas: São usadas várias filas de processos prontos para executar, cada processo e colocado em uma fila, e cada fila tem uma política de escalonamento própria e outra entre filas.
9
4. Simulação
Para que seja simulado um escalonador de processos de um sistema operacional foi desenvolvido um algoritmo em múltiplas filas que durante sua execução gera informações que são gravadas em um arquivo de estatísticas para que os resultados obtidos possam ser analisados. Neste algoritmo levamos em consideração alguns aspectos de funcionamento de um escalonador verdadeiro, como: tamanho dos processos, prioridades, quamtum (tempo que o processo recebe de CPU) e starvation (processos que demoram muito tempo para ganhar a CPU). Para obter alguns dados relativos ao escalonamento, usamos, neste mesmo algoritmo, uma estrutura com algumas variáveis que armazenavam informações para gerar uma estatística de desempenho. Com esses dados sabemos, por exemplo, quantos processos foram criados e executados por cada fila de prioridade, podendo assim saber o throughput. Abaixo mostraremos o funcionamento do algoritmo e o software utilizado para gerar os gráficos, e a seguir cada etapa da simulação e comentários a respeito dos testes.
10
5. Funcionamento
O algoritmo aqui comentado, implementa um simulador de um escalonador de processos, este algoritmo foi desenvolvido na linguagem C. Neste algoritmo foram implementados estruturas que simulam as propriedades e atributos de uma CPU e os Processos, filas com faixas crescentes de prioridade inclusive uma para processo de sistema em tempo real, e algumas outras funções. A cada iteração, é chamada uma função que verifica a necessidade de criar novos processos, esta função atribui um valor randômico a uma variável, que é comparada a fim de saber se deve ser criado um novo processo ou não. Caso um novo processo seja criado, é atribuído inicia-se uma nova instancia da estrutura processo com os atributos de ID, prioridade, tamanho e quantum, que após sua criação ele é inserido em uma fila de acordo com sua prioridade. Se não for criado um processo nessa iteração com a CPU, é chamado o escalonador. Este verifica as filas, para saber em qual fila há processo esperando por CPU, e executa o processo com prioridade maior. Nesta execução é dado um quantum, o tempo que o processo pode usar de CPU, e após a execução, é diminuído o tamanho do processo em relação a este quantum. Um processo é considerado como executado quando seu tamanho quantum é zero, isto significa que ele não precisa mais ser levado à CPU e pode ser retirado das filas de Processos e realocado de acordo com sua prioridade. No final das iterações estipuladas, o algoritmo gera um relatório com os dados colhidos ante sua execução, e os grava em um arquivo em disco chamado “estatísticas.txt”.
11
6. FILAS
Usamos a seguinte política para separar os processos por prioridade. Fila 1: esta fila é usada no caso de chegar algum processo de extrema importância, por exemplo, de tempo real. Somente é colocado nesta fila processos com prioridade 0 (zero). Estes processos são executados por inteiro, sem poder ser retirado da CPU antes de terminar. Fila 2: processos com prioridade de 1 até 19. Fila 3: processos com prioridade de 20 até 39. Fila 4: processos com prioridade de 40 até 59. Fila 5: processos com prioridade de 60 até 79. Fila 6: processos com prioridade de 80 até 99.
12
7. Simulações 7.1.
Simulação 1
Nesta primeira simulação utilizamos a função rand() para atribuir o quantum aleatoriamente aos novos processos gerados. Foi feita uma simulação com probabilidade de 20% de ser criado um processo, em 2000 iterações do sistema. Pegamos informações em 4 faixas de tempo que são: 0499, 500-999, 1000-1499 e 1500-1999 iterações.
100 90 80 70 60 Processos criados
50
processos executados
40
starvattion
30 20 10 0 0
500
1000
1500
2000
Verificamos que com esta probabilidade de criar novos processos, o escalonador executou todos processos gerados.
13
7.2.
Simulação 2
Nesta segunda simulação continuamos utilizando a função rand() para atribuir o quantum aleatoriamente aos novos processos gerados, mas alteramos a probabilidade de criar processos de 20 para 40% em 2000 iterações do sistema. Pegamos informações em 4 faixas de tempo que são: 0499, 500-999, 1000-1499 e 1500-1999 iterações.
100 90 80 70 60 Processos criados
50
processos executados
40
starvattion
30 20 10 0 0
500
1000
1500
2000
Com esta probabilidade de criar processos, o escalonador já não conseguiu executar a totalidade dos processos. Reparamos também que na última faixa de tempo, o escalonador executou mais processos, isso por que a criação de novos processos diminuiu, conseqüentemente diminuindo os processos em starvation e aumentado um pouco o throughput.
14
7.3.
Simulação 3
Nesta terceira simulação continuamos utilizando a função rand() para atribuir o quantum aleatoriamente aos novos processos gerados, mas alteramos a probabilidade de criar processos de 40 para 60% em 2000 iterações do sistema. Pegamos informações em 4 faixas de tempo que são: 0499, 500-999, 1000-1499 e 1500-1999 iterações.
100 90 80 70 60 Processos criados
50
processos executados
40
starvattion
30 20 10 0 0
500
1000
1500
2000
Com 60% de probabilidade de criar novos processos, o escalonador não conseguiu executar muitos processos, tendo uma queda considerável de rendimento. Até a terceira faixa de tempo percebemos que o starvation aumentou progressivamente e após passar das 1500 interações ocorreu uma queda acentuada do mesmo.
15
7.4.
Simulação 4
Nesta quarta simulação continuamos utilizando a função rand() para atribuir o quantum aleatoriamente aos novos processos gerados, mas alteramos a probabilidade de criar processos de 60 para 80% em 2000 iterações do sistema. Pegamos informações em 4 faixas de tempo que são: 0499, 500-999, 1000-1499 e 1500-1999 iterações.
100 90 80 70 60 Processos criados
50
processos executados
40
starvattion
30 20 10 0 0
500
1000
1500
2000
Ao aumentar a probabilidade de criar novos processos de 60% para 80%, ouve um aumento no numero de processos criados, mas, o desempenho continuou caindo, pois o numero de processos executados é quase desprezível. Em relação ao Starvation não tivemos muitas alterações. Até a terceira faixa de tempo percebemos que o starvation aumentou progressivamente e após passar das 1500 interações ocorreu uma queda acentuada do mesmo.
16
8. Comparando
Vamos mostrar alguns gráficos com as comparações de processos criados, executados, throughput, e starvation com a criação em quantidade baixa, média e grande de novos processos. Iterações = 2000 Quantum = randômico Probabilidade de criar novo processo = 20%, 40%, 60% 80%
8.1.
Quantidade total de processos criados durante a simulação:
100 90 80 70 60
Processos criados
50
processos executados
40
starvattion
30
#REF!
20 10 0 0
500
1000
1500
2000
17
8.2.
Quantidade total de processos executados durante a simulação.
800 700 600 500
Processos criados
400
processos executados
300
starvattion #REF!
200 100 0 0
8.3.
500
1000
1500
2000
Quantidade total de starvation durante a simulação.
800 700 600 500
Processos criados
400
processos executados
300
starvattion #REF!
200 100 0 0
500
1000
1500
2000
Como podemos observar no segundo gráfico, o número de processos executados não aumentou muito em relação a mudança de quantidade de processos novos, apesar do número de novos processos ter aumentado
18
significativamente, como observamos no primeiro gráfico. Em relação ao starvation, podemos ver que o aumento de starvation foi proporcional ao aumento de novos processos.
8.4.
Conclusão das Simulações
Analisando os gráficos, chegamos a conclusão que atribuindo um quantum aleatoriamente aos processos que serão executados, o desempenho do escalonador só é aceitável quando o número de novos processos chegando a CPU é baixo. Quanto mais processos chegam a CPU em um curto espaço de tempo, menos processos são executados, especialmente quando têm prioridade menor, já que os processos com prioridade maior, ainda tem uma boa porcentagem de execução.
19
9. Outras Simulações Nas próximas simulações (6, 7, 8 e 9) atribuímos o quantum aos novos processos de forma diferente. Pegamos o tamanho do processo que está chegando a CPU e dividimos por dois. O resultado será utilizado como quantum para a execução. Foram feitas simulações com probabilidades de 20%, 40%, 60% e 80% de ser criado um processo, em 2000 iterações do sistema. Pegamos informações em 4 faixas de tempo que são: 0-499, 500-999, 1000-1499 e 1500-1999 iterações.
9.1.
Simulação 5
Iterações = 2000 Quantum = tamanho / 2 Probabilidade de criar novo processo = 20% 100 90 80 70 60 Processos criados
50
processos executados
40
starvattion
30 20 10 0 0
500
1000
1500
2000
Verificamos que com esta probabilidade de criar novos processos, o escalonador executou todos. Somente na terceira faixa de tempo, ficaram alguns sem executar, o que foi compensado na parte final.
20
9.2.
Simulação 6
Iterações = 2000 Quantum = tamanho / 2 Probabilidade de criar novo processo = 40% 800 700 600 500 Processos criados
400
processos executados 300
starvattion
200 100 0 0
500
1000
1500
2000
Com esta probabilidade de criar processos, o escalonador continuou executando um bom número de processos. Na terceira faixa de tempo teve um aumento de processos novos, o que acarretou uma queda de throughput, e aumento do starvation. Como na parte final, a criação de processos foi maior, o escalonador diminuiu a execução de processos.
21
9.3.
Simulação 7
Iterações = 2000 Quantum = tamanho / 2 Probabilidade de criar novo processo = 60%
800 700 600 500 Processos criados
400
processos executados 300
starvattion
200 100 0 0
500
1000
1500
2000
Com muitos processos precisando utilizar a CPU, o escalonador não conseguiu executar muitas vezes. Pelo gráfico percebemos que a execução se manteve constante praticamente todo tempo, mesmo tendo uma pequena variação na quantidade de processos criados.
22
9.4.
Simulação 8
Iterações = 2000 Quantum = tamanho / 2 Probabilidade de criar novo processo = 80% 1400 1200 1000 800
Processos criados processos executados
600
starvattion
400 200 0 0
500
1000
1500
2000
Os gráficos indicam que com a criação de processos em 80% A CPU não modificou muito a sua forma de execução, ficando muito parecido com o gráfico de 60% de probabilidade, tendo apenas um aumento no starvation e uma queda dos processos executados.
23
10. Média de Throughput
As médias de throughput foram calculadas a partir de cada interação executada, visando assim mostrar em cada interação a quantidade de processos executados. Foram feitas quatro interações, onde sua duração é determinada por um loop de 500 voltas, de onde foram tirados os dados dos processos executados por fase de interação que seria a unidade de tempo necessária para calcular o throughput.
Fila 1 70 60 50 40 30
Fila 1
20 10 0 500
1000
1500
2000
Fila 2 25 20 15 10
Fila 2
5 0 500
1000
1500
2000
24
Fila 3 140 120 100 80 60
Fila 3
40 20 0 500
1000
1500
2000
Fila 4 140 120 100 80 60
Fila 4
40 20 0 500
1000
1500
2000
Fila 5 200 150 100 Fila 5 50 0 500
1000
1500
2000
25
Fila 6 160 140 120 100 80 60
Fila 6
40 20 0 500
1000
1500
2000
Para todas as médias de throughput calculadas, foram obtidos seis gráficos que demonstram o crescimento dos processos executados a cada faixa de tempo interações que foram realizados. Assim mostro abaixo um gráfico com um comparativo entre o crescimento do throughput para cada fila. 180 160 140 Fila 1
120
Fila 2
100
Fila 3
80
Fila 4 60 Fila 5 40
Fila 6
20 0 500
1000
1500
2000
Para cada fila tem-se um diferencial de crescimento devido à adição do tempo quantum para cada fila de acordo com sua prioridade, assim mostrando um crescimento variado para cada fila.
26
11. COMPARAÇÃO DAS SIMULAÇÕES 6, 7, 8 e 9 Iterações = 12000 Quantum = tamanho / 2 Probabilidade de criar novo processo = 20%, 40%, 60% e 80% Vamos mostrar alguns gráficos com as comparações de processos criados, executados e starvation com a criação em quantidade baixa, média e alta de novos processos.
11.1. Quantidade total de processos criados durante a simulação. 500 450 400 350 300
20%
250
40%
200
60%
150
80%
100 50 0 0
500
1000
1500
2000
27
11.2. Quantidade total de processos executados durante a simulação. 100 90 80 70 60
20%
50
40%
40
60%
30
80%
20 10 0 0
11.3.
500
1000
1500
2000
Quantidade total de starvation durante a simulação.
1400 1200 1000 20%
800
40% 600
60%
400
80%
200 0 0
500
1000
1500
2000
Como podemos observar pelos gráficos, o número de processos executados com probabilidade menor de criação de novos processos em relação ao tempo, é igual a quantidade de processos criados, gerando um bom throughput. Quando aumentamos a quantidade de processos, o número fica bem abaixo, o que gera um aumento no starvation. 28
12. CONCLUSÃO SIMULAÇÃO 2
Analisando os gráficos observamos que o número de processos executados que possuem uma prioridade maior foi satisfatória. Em compensação, processos com prioridades muito baixa, praticamente não foram a CPU. somente quando tem poucos processos chegando ao mesmo tempo, estes conseguem acesso a CPU para serem executados. Como a quantidade de processos utilizada na terceira fase da simulação foi elevada, é compreensível o escalonador ter agido desta maneira, por ter dado preferência à execução dos processos mais importantes. Nas simulações que geraram uma quantidade razoável de processos, tanto processos com prioridade maior, como processos com prioridade menor foram executados em bom número. Conseguimos um bom throughput.
13. CONCLUSÃO SIMULAÇÃO 2
Analisando os gráficos observamos que o número de processos executados que possuem uma prioridade maior foi satisfatória. Em compensação, processos com prioridades muito baixa, praticamente não foram a CPU. somente quando tem poucos processos chegando ao mesmo tempo, estes conseguem acesso a CPU para serem executados. Como a quantidade de processos utilizada na terceira fase da simulação foi elevada, é compreensível o escalonador ter agido desta maneira, por ter dado preferência à execução dos processos mais importantes. Nas simulações que geraram uma quantidade razoável de processos, tanto processos com prioridade maior, como processos com prioridade menor foram executados em bom número. Conseguimos um bom throughput.
29
14.
Bibliografia
TANENBAUM, ANDREW S. – Sistemas Operacionais: projeto e implementação / Andrew S. Tanenbaum e Albert S. Woodhull; trad: Edson Furmankiewicz. – 2ª Edição, Porto Alegre: Bookman, 2000. ISBN 85-7307-530-9. ESCALONAMENTO DE PROCESSOS, http://pt.wikipedia.org/wiki/ Escalonamento_de_processos - Esta página foi modificada pela última vez às 00h43min de 11 de maio de 2010. U
U
30
15. Anexos 15.1. #include #include #include #include
Escalonador.c "bibli.h"
main(){ int i, j, x, iteracao=0; lista Lista1Processos, Lista1Processos, Lista2Processos, Lista2Processos, Lista3Processos; Lista3Processos; lista Lista4Processos, Lista4Processos, Lista5Processos, Lista5Processos, Lista6Processos; Lista6Processos; c.tempo = 0; ARQ = fopen("estatisticas.tx fopen("estatisticas.txt","w"); t","w"); create(&Lista1Processos); create(&Lista2Processos); create(&Lista3Processos); create(&Lista4Processos); create(&Lista5Processos); create(&Lista6Processos); for (i=0; i<6; i++){ for (j=0; j<4; j++){ e[i][j].cont_proc_novos = 0; e[i][j].cont_proc_executados = 0; e[i][j].cont_proc = 0; e[i][j].cont_proc_starvation = 0; } } while (iteracao < 2000) { // verifica se foi criado um novo processo. caso criou, coloca na fila correta if (cria_processo(iteracao)) { if (p.prioridade == 0) { insert(&Lista1Processos, p); atualiza_estatistica(1 atualiza_estatistica(1, , 1, iteracao); } else if ((p.prioridade >= 1) && (p.prioridade <= 19)) { insert(&Lista2Processos,p); atualiza_estatistica(1 atualiza_estatistica(1, , 2, iteracao); } else if ((p.prioridade >= 20) && (p.prioridade <= 39)) { insert(&Lista3Processos, p); atualiza_estatistica(1 atualiza_estatistica(1, , 3, iteracao); } else if ((p.prioridade >= 40) && (p.prioridade <= 59)){ insert(&Lista4Processos, p); atualiza_estatistica(1 atualiza_estatistica(1, , 4, iteracao); }
31
else if ((p.prioridade >= 60) && (p.prioridade <= 79)){ insert(&Lista5Processos, p); atualiza_estatistica(1 atualiza_estatistica(1, , 5, iteracao); } else if ((p.prioridade >= 80) && (p.prioridade <= 99)){ insert(&Lista6Processos, p); atualiza_estatistica(1 atualiza_estatistica(1, , 6, iteracao); } } // caso não tenha sido criado novo processo, simula execução de um processo else { if (!isEmpty(Lista1Processos)){ if (executa_processo(&Lista1Processos)) insert(&Lista1Processos, p); else atualiza_estatistica(2, 1, iteracao); } else if (!isEmpty(Lista2Processos)){ if (executa_processo(&Lista2Processos)) insert(&Lista2Processos, p); else atualiza_estatistica(2, 2, iteracao); } else if (!isEmpty(Lista3Processos)){ if (executa_processo(&Lista3Processos)) insert(&Lista3Processos, p); else atualiza_estatistica(2, 3, iteracao); } else if (!isEmpty(Lista4Processos)){ if (executa_processo(&Lista4Processos)) insert(&Lista4Processos, p); else atualiza_estatistica(2, 4, iteracao); } else if (!isEmpty(Lista5Processos)){ if (executa_processo(&Lista5Processos)) insert(&Lista5Processos, p); else atualiza_estatistica(2, 5, iteracao); } else if (!isEmpty(Lista6Processos)){ if (executa_processo(&Lista6Processos)) insert(&Lista6Processos, p); else atualiza_estatistica(2, 6, iteracao); } } fprintf(ARQ,"Iteracoes: %d\t", iteracao); fprintf(ARQ,"Processos criados: %d\t", e[0][0].cont_proc_novos); fprintf(ARQ,"Processos executados: %d\n", e[0][0].cont_proc_executados); // verifica quantos processos tem em cada fila e se há starvation if (iteracao == 499){ verifica_starvation(Lista1Processos, verifica_starvation(Lista2Processos, verifica_starvation(Lista3Processos, verifica_starvation(Lista4Processos, verifica_starvation(Lista5Processos, verifica_starvation(Lista6Processos,
1, 2, 3, 4, 5, 6,
1); 1); 1); 1); 1); 1);
32
} else if (iteracao == 999){ verifica_starvation(Lista1Processos, verifica_starvation(Lista2Processos, verifica_starvation(Lista3Processos, verifica_starvation(Lista4Processos, verifica_starvation(Lista5Processos, verifica_starvation(Lista6Processos, } else if (iteracao == 1449){ verifica_starvation(Lista1Processos, verifica_starvation(Lista2Processos, verifica_starvation(Lista3Processos, verifica_starvation(Lista4Processos, verifica_starvation(Lista5Processos, verifica_starvation(Lista6Processos, } else if (iteracao == 2000){ verifica_starvation(Lista1Processos, verifica_starvation(Lista2Processos, verifica_starvation(Lista3Processos, verifica_starvation(Lista4Processos, verifica_starvation(Lista5Processos, verifica_starvation(Lista6Processos,
1, 2, 3, 4, 5, 6,
2); 2); 2); 2); 2); 2);
1, 2, 3, 4, 5, 6,
3); 3); 3); 3); 3); 3);
1, 2, 3, 4, 5, 6,
4); 4); 4); 4); 4); 4);
// para armazenar o total e[0][0].cont_proc = e[0][4].cont_proc; e[0][0].cont_proc_starvation = e[0][4].cont_proc_starvation; } iteracao++; } fprintf(ARQ,"::::::::: FILA 1 ::::::::::\n"); imprime(Lista1Processos); fprintf(ARQ,"::::::::: FILA 2 ::::::::::\n"); imprime(Lista2Processos); fprintf(ARQ,"::::::::: FILA 3 ::::::::::\n"); imprime(Lista3Processos); fprintf(ARQ,"::::::::: FILA 4 ::::::::::\n"); imprime(Lista4Processos); fprintf(ARQ,"::::::::: FILA 5 ::::::::::\n"); imprime(Lista5Processos); fprintf(ARQ,"::::::::: FILA 6 ::::::::::\n"); imprime(Lista6Processos); fprintf(ARQ,"Processos criados: %d", e[0][0].cont_proc_novos); fprintf(ARQ,"\nProcessos executados: %d", e[0][0].cont_proc_executados); mostra_estatistica(); printf("Arquivo com as informações de execução foi gravado em disco!\n");
33
fclose(ARQ); } // fim do main
15.2.
Bibli.h
#define TRUE #define FALSE
1 0
typedef struct{ int id; int prioridade; int tamanho; int tamanho_restante; tamanho_restante; int quantum; }processo; typedef struct{ int id; int tempo; }cpu; typedef struct{ int cont_proc_novos; cont_proc_novos; int cont_proc_executados; cont_proc_executados; int cont_proc; int cont_proc_starvation; cont_proc_starvation; }estatistica; processo p; cpu c; estatistica e[7][5]; FILE *ARQ; struct no{ processo dado; struct no *prox; }; typedef struct { struct no *inicio; } lista; void create(lista *q){ q->inicio=NULL; } int isEmpty(lista q){ if (q.inicio==NULL) return TRUE; else return FALSE; }
34
int cria_processo(int iteracoes){ int x; srand(time(NULL) * (e[0][0].cont_proc_novos + 1 * iteracoes + 1)); x = rand()%100; if (x < 80){ p.id = e[0][0].cont_proc_novos + 1; p.prioridade = rand()%100; p.tamanho = 1 + rand()%9; p.tamanho_restante p.tamanho_restante = p.tamanho; p.quantum = p.tamanho / 2; return(TRUE); } return(FALSE); } int insert(lista *q, processo d){ struct no *aux, *atual, *anterior; aux = (struct no *) malloc(sizeof(struct no)); if (aux!=NULL){ aux->dado=d; aux->prox=NULL; aux->prox=NULL; anterior = NULL; atual = q->inicio; while ((atual != NULL) && (d.prioridade (d.prioridade > atual>dado.prioridade)){ anterior = atual; atual = atual->prox; } if (anterior == NULL){ aux->prox = q->inicio; q->inicio = aux; } else { anterior->prox=aux; aux->prox = atual; } } } int executa_processo(lista *q){ struct no *aux, *atual, *anterior; srand(time(NULL) * (e[0][0].cont_proc_novos + 1 * (q->inicio)>dado.tamanho)); // atribui um quantum ao processo e diminui o tamanho restante if ((q->inicio)->dado.prioridade == 0) (q->inicio)->dado.quantum = (q->inicio)->dado.tamanho; else (q->inicio)->dado.quantum = 1 + rand()%(q->inicio)>dado.tamanho; (q->inicio)->dado.tamanho_restante = (q->inicio)>dado.tamanho_restante - (q->inicio)->dado.quantum; c.tempo = c.tempo + (q->inicio)->dado.quantum; if ((q->inicio)->dado.tamanho_restante <= 0){ aux = q->inicio; q->inicio = (q->inicio)->prox; free(aux); return(FALSE); } else{
35
// guarda os dados do processo atual p.id = (q->inicio)->dado.id; p.prioridade = (q->inicio)->dado.prioridade; p.tamanho = (q->inicio)->dado.tamanho; p.tamanho_restante = (q->inicio)->dado.tamanho_restante; p.quantum = (q->inicio)->dado.quantum; // deleta ele da lista para recolocá-lo aux = q->inicio; q->inicio = (q->inicio)->prox; (q->inicio)->prox; free(aux); return(TRUE); } } void verifica_starvation(lista q, int f, int i){ struct no *aux; aux = q.inicio; if (!isEmpty(q)){ while (aux != NULL){ e[0][i].cont_proc++; e[f][i].cont_proc++; if (aux->dado.tamanho == aux->dado.tamanho_restante){ e[0][i].cont_proc_starvation++; e[f][i].cont_proc_starvation++; } aux = aux->prox; } } } void imprime(lista q){ struct no *aux; int ContadorNos = 0; aux = q.inicio; if (!isEmpty(q)){ while (aux != NULL){ ContadorNos++; fprintf(ARQ,"ID: %d", aux->dado.id); fprintf(ARQ,"\tTamanho: %d", aux->dado.tamanho); fprintf(ARQ,"\tRestante: %d", aux>dado.tamanho_restante); fprintf(ARQ,"\tQuantum: %d", aux->dado.quantum); fprintf(ARQ,"\tPrioridade: %d\n", aux>dado.prioridade); aux = aux->prox; } fprintf(ARQ,"\n\nQuantidade de processos: %d", ContadorNos); } fprintf(ARQ,"\n\n\n"); } void atualiza_estatistica(int tipo, int fila, int interacoes){ if (tipo == 1){ e[0][0].cont_proc_novos++; e[fila][0].cont_proc_novos++;
36
if (interacoes <= 499){ e[0][1].cont_proc_novos++; e[fila][1].cont_proc_novos++; } else if ((interacoes >= 500) && (interacoes <= 999)){ e[0][2].cont_proc_novos++; e[fila][2].cont_proc_novos++; } else if ((interacoes >= 1000) && (interacoes <= 1499)){ e[0][3].cont_proc_novos++; e[fila][3].cont_proc_novos++; } else if ((interacoes >= 1500) && (interacoes <= 1999)){ e[0][4].cont_proc_novos++; e[fila][4].cont_proc_novos++; } } else if (tipo == 2){ e[0][0].cont_proc_executados++; - 42 e[fila][0].cont_proc_executados++; if (interacoes <= 499){ e[0][1].cont_proc_executados++; e[fila][1].cont_proc_executados++; } else if ((interacoes >= 500) && (interacoes <= 999)){ e[0][2].cont_proc_executados++; e[fila][2].cont_proc_executados++; } else if ((interacoes >= 1000) && (interacoes <= 1499)){ e[0][3].cont_proc_executados++; e[fila][3].cont_proc_executados++; } else if ((interacoes >= 1500) && (interacoes <= 1999)){ e[0][4].cont_proc_executados++; e[fila][4].cont_proc_executados++; } } } void mostra_estatistica(){ mostra_estatistica(){ int i; int j; int faixa = 499; fprintf(ARQ,"\n_________________________________________________ ______________\n\n"); fprintf(ARQ,"ESTATISTICAS"); fprintf(ARQ,"\n_________________________________________________ ______________\n\n"); for(i=0;i<5;i++){ if(i==0) fprintf(ARQ,"GERAL\n"); else fprintf(ARQ," FAIXA %d (%d a %d)\n",i,faixa499,faixa); fprintf(ARQ,"Fila\tProcessos Criados\tProcessos Executados\tQtd Processos\tStarvation\n");
37
for(j=1;j<7;j++){ fprintf(ARQ," %d\t\t%2d\t\t\t%2d\t\t %2d\t %2d\n",j, e[j][i].cont_proc_novos, e[j][i].cont_proc_executados, e[j][i].cont_proc, e[j][i].cont_proc_starvation); } if(j>6) fprintf(ARQ, " T\t\t%2d\t\t\t%2d\t\t %2d\t %2d\n", e[0][i].cont_proc_novos, e[0][i].cont_proc_executados, e[0][i].cont_proc, e[0][i].cont_proc_starvation); fprintf(ARQ,"\n_________________________________________________ _________________"); fprintf(ARQ,"\n\n"); faixa += 500; } }
15.3.
Estatistica.txt
Devido ao grande número de linhas geradas pelo escalonador, estarei disponibilizando o arquivo na URL seguinte: http:\\www.comp.pucpcaldas.br/~al550316968/estatísticas.txt
38