2. Autores
Eduardo Miranda Peloso da Silva
Franklin Rodriguez Tellez
Henrique Carvalho de Almeida Soares
José Luiz Machado Morais
William Wallace de Siqueira Ribeiro
Wilson Francisco Moreira de Souza Seron
2
3. Roteiro
• O Kernel
• Tipos de núcleo
• Kernel do Linux
• Sistemas de arquivo
• Processos no kernel
• Gerenciamento de Processos
o Prioridades
o Scheduler
• Preemptividade
• Gerenciamento de memória
• Multiprocessamento
• GRUB
• Compilação e instalação do Kernel
• Criação de uma System Call
• Módulos
• Device drivers
• Tempo Real 3
• Considerações Finais
• Referências
4. Definição de Kernel
• O kernel é o componente central, isto é, o núcleo
da maioria dos sistemas operacionais
• É a ligação entre as aplicações e o
processamento efetivo dos dados no nível de
hardware
• O desenvolvimento de um kernel é considerado
uma das atividades mais complexas na área de
programação
4
5. Definição de Kernel
Visão da arquitetura de um computador como camada de
abstração: hardware, firmware, assembler, kernel, sistema
5
operacional e aplicações
6. Responsabilidades do Kernel
• Gerenciar recursos de sistema
o Escalonamento de processos
o Gerenciamento de memória (paginação,
memória virtual)
o Gerenciamento de dispositivos (principalmente
drivers de periféricos, e E/S)
o Encapsular todo o acesso ao hardware
6
7. Como isto é feito?
• Para o “trabalho” ser feito, é necessário que um
processo acesse os serviços oferecidos pelo
kernel
• Isto é feito usando System Calls. Cada kernel
apresenta uma abordagem diferente para lidar
com o oferecimento de serviços
7
8. Tipos de Kernel
• Existem vários tipos de kernel:
o Monolítico
o Microkernel
o Híbridos
o Nanokernels
o Entre outros
• Entretanto, os mais usados são os monolíticos e
microkernel
8
10. Kernel Monolítico
• Projetados para ter todo o seu código no mesmo
espaço de endereços
• Define uma interface de alto nível sobre o
hardware
• Grupo de System Calls primitivas que
implementam todos os serviços do sistema
operacional
10
11. Kernel Monolítico
• Todos os serviços do sistema rodam junto à
thread principal do kernel
• Isto provê um acesso rico e poderoso ao
hardware
11
12. Kernel Monolítico
• Entretanto, há uma forte dependência entre
componentes do sistema
o Um bug num driver de dispositivo, por exemplo, pode derrubar o
sistema inteiro
• Exemplos de kernels monolíticos:
o Unix e Unix-like kernels (Linux, BSD, Solaris)
o Mac OS até o 8.6
o DOS e Windows até a série 9x (95, 98, Me)
12
14. Microkernel
• Consiste em definir uma abstração simples do
hardware
• Foco em desenvolvimento minimalista, resultando
em kernels menores
• Devido a isto, normalmente implementam
somente as funções mais básicas, separando-as
em módulos
• Alguns outros serviços, como networking, são
implementados em espaço de usuário
14
15. Microkernel
• Permite, portanto, que o restante do kernel seja
implementado como uma aplicação comum, em
linguagem de alto nível
• Mais fáceis de manter que os monolíticos
• O alto número de System Calls e de trocas de
contexto fazem com que o sistema seja mais
lento, pois geram grande overhead
15
16. Kernel Híbrido
• É uma combinação entre o monolítico e o
microkernel
• Roda serviços como o networking e o sistema de
arquivos no espaço de kernel
• Apenas módulos menores, como drivers de
dispositivos, são rodados como servers
16
17. O Kernel do Linux
• Em 03/Dez/2009, versão 2.6.32:
o 14.000 arquivos escritos em linguagem C e assembly
o 12,606,910 linhas de código
o 1000 diretórios e subdiretórios
o 230 Megabytes
• Site: www.kernel.org
17
18. O Kernel do Linux
• Unix-like
• Monolítico modularizado (possui suporte a
módulos)
• Threading (clone() system call)
• Preemptivo
o O kernel define o tempo de processamento de cada processo e
pode alterar essa estratégia a fim de maximizar o desempenho
do sistema
18
19. O Kernel do Linux
• Não permite acesso direto ao hardware
• Dois modos de execução
o User e Kernel Mode
• Sistema multiusuário
• Suporte a multiprocessamento
19
20. Vantagens do Kernel do Linux
• Gratuito
• Customizável
• Roda em máquinas antigas
• Estável
• Eficiente, mesmo em máquinas robustas
• Alta compatibilidade:
o Alpha, arm, i386, mips etc
o HTC, iPhone etc
20
22. Sistema de Arquivos
• Conjunto de estruturas lógicas e rotinas que permitem
ao sistema operacional controlar o acesso ao disco
rígido
• Em UNIX, os sistemas de arquivos mais utilizados são:
o Ext2
o Ext3
o ReiserFS
o XFS
o JFS
22
23. Journaling
• Journaling é uma característica do sistema de arquivos
que permite ao SO manter um log de todas as
mudanças no sistema antes de escrever os dados no
disco, tornando-o assim mais seguro
23
24. JFS e XFS
• JFS
o Sistema rápido com suporte a journaling e
redimensionamento de partições
o Perdeu muita credibilidade devido a inúmeros bugs
• XFS
o Sistema rápido na gravação, otimizado para escalabilidade
e que faz uso de journaling
o Sistema de alto custo em termos de recursos e de
gerenciamento complexo
24
25. Ext2 - Prós
• Sistema de arquivos rápido (não tem suporte para
journaling)
• Pré-alocação de blocos, com o intuito de diminuir a
fragmentação externa
• O uso de grupos de blocos diminui o número de buscas
em disco quando é realizada a leitura de uma grande
quantidade de dados subsequentes
25
26. Ext2 - Contras
• Não tem suporte para journaling, sendo assim pouco
confiável
• Pode causar fragmentação devido ao uso de blocos
• Apesar de possuir táticas para contornar o problema de
fragmentação, as mesmas podem causar perda de
desempenho no sistema, devido ao grande número de
blocos para gerenciar
26
27. Ext3 - Prós
• Utilização da árvore de diretórios para recuperação de
arquivos
• Permite atualização direta do Ext2, sem a necessidade
de realizar backup
• Baixo consumo de processamento
• Faz uso de journaling
27
28. Ext3 - Contras
• Não possui alocação dinâmica
• Não possui sistema de blocos de tamanhos variáveis
• Não permite a checagem do sistema enquanto ocorre
uma montagem para a escrita de um arquivo
• Dificuldade para a realização de desfragmentação
• Não possui um suporte à compressão transparente
28
29. ReiserFS - Prós
• Primeiro sistema de arquivos com suporte para
journaling
• Utiliza árvores balanceadas para otimizar as buscas de
arquivos
• Utiliza blocos de tamanhos variáveis para alocação
• Sistema capaz de recuperar a consistência
rapidamente após uma eventual finalização incorreta
• Suporte para arquivos maiores que 2GB 29
30. ReiserFS - Contras
• Consumo de CPU elevado
• Não funciona muito bem com softwares de RAID
• Exige algoritmos complexos devido ao modelo de
organização em árvores balanceadas
• Não possui bom desempenho em sistemas multicore
30
31. Quadro Comparativo
Prós Contras
ReiserFS - Journaling - Consumo de CPU elevado
- Utiliza árvores balanceadas - Não funciona muito bem com
- Blocos de tamanhos softwares de RAID
variáveis - Exige algoritmos complexos
- Recuperação da consistência - Não possui bom desempenho
- Suporte para arquivos em sistemas multicore
maiores que 2GB
Ext2 - Rapidez - Não possui journaling
- Pré alocação de blocos - Fragmentação de disco
Ext3 - Permite atualização direta - Não possui alocação dinâmica
do Ext2 - Não possui sistema de blocos
- Baixo consumo de de tamanhos variáveis
processamento - Desfragmentação difícil
- Faz uso de journaling - Não possui um suporte à
compressão transparente
JFS - Journaling - Perdeu muita credibilidade
- Partições redimensionáveis devido a inúmeros bugs
31
XFS - Journaling - Sistema de alto custo e de
- Escalabilidade gerenciamento complexo
32. Sistemas de Arquivos - Exercícios
• Considerando o quesito confiabilidade, qual sistema de
arquivos é o mais apropriado?
• Considerando o quesito velocidade, qual sistema de
arquivos é o mais indicado?
32
33. Processos no Kernel
• Cada programa executado é definido como um processo
• Cada um desses processos recebe um número de identificação
chamado PID (Process ID)
• Além do PID, cada processo tem um conjunto de informações
como: nome, uso da memória, usuário e grupo que o executou,
estado, entre outros
33
34. Estados de um Processo
• TASK_RUNNING
Em execução
• TASK_INTERRUPTIBLE
Suspenso até que uma condição se torne verdadeira
• TASK_UNINTERRUPTIBLE
Como o estado anterior, exceto pelo fato de que o seu estado
não será modificado quando receber um sinal. É importante para
os processos que necessitam executar determinada tarefa sem
serem interrompidos
34
35. Estados de um Processo
• TASK_STOPPED
Execução do processo foi parada
• TASK_ZOMBIE
O processo está terminado, mas o processo pai ainda não
executou uma chamada de sistema para retornar informações
sobre o processo morto - "wait'', as informações não são
descartadas pois ainda podem ser utilizadas
35
36. Gerenciamento de Processos
• Qualquer sistema operacional tem muitos processos rodando
"simultaneamente"
• São necessários meios para manipular e controlar a execução dos
diversos processos
• Os meios de realizar esse gerenciamento são:
o System Calls
o Scheduling e Prioridades
36
37. Gerenciamento de Processos
• System Calls específicas para manipulação de processos no kernel
Linux:
o fork()
o vfork()
o exit()
o clone()
o exec()
• Existem também alguns comandos para monitorar os processos em
execução:
o top
o ps
37
38. Gerenciamento de Processos
• A System Call fork():
o cria um novo processo a partir do orginal e idêntico a
ele
processo original: pai
processo(s) gerados por chamada(s) ao fork:
filho(s)
o ao ser chamada, no processo pai, retorna o PID do
processo filho
o ao ser chamada no filho, retorna 0
• Pode ser utilizada no contexto de programas com
tolerância a falhas
38
39. Gerenciamento de Processos
• A System Call vfork():
o tem a mesma funcionalidade da fork()
difere por bloquear o processo pai enquanto não há
uma chamada de _exit() ou da família exec()
o criada como uma versão com overhead menor do que a
fork(), onde pai e o(s) filho(s) compartilhavam tabela de
páginas
a fork() fazia a cópia na criação do processo filho,
atualmente é feito o Copy-on-Write (somente quando
filho modifica algum valor)
o segundo a man page, seu uso é desencorajado, exceto
em situações específicas
39
40. Gerenciamento de Processos
• A System Call clone():
o funciona similarmente a fork(), criando um novo
processo filho
o este novo processo na verdade é uma thread do
programa original
o recebe ao menos dois parâmetros, fn e arg
fn é a função a ser executada na thread
arg são os parâmetros a serem passados para a
função
40
41. Gerenciamento de Processos
• A System Call exec():
o cria e executa um novo processo
o recebe ao menos um parâmetro, o caminho do arquivo
a ser executado
o pode também receber uma lista de argumentos a serem
passados como parâmetros na execução do arquivo
o normalmente não retorna nenhum valor
caso tenha ocorrido algum erro, retorna -1
41
42. Gerenciamento de Processos
• A System Call exit():
o encerra o processo, com o código de status informado
como parâmetro
o após a saída, o código de status é passado para o
processo pai
• a chamada a exit() realiza uma série de etapas, antes de
chamar de fato a _exit(), que simplesmente termina o
processo
42
43. Gerenciamento de Processos
• Em qualquer sistema, processos tem prioridades
diferentes para execução
o quanto maior a prioridade, maior o tempo de
processamento que vai ser dedicado a ele
• No kernel Linux existe uma escala de números cada um
correspondendo a um maior ou menor nível de prioridade
o valores vão de -20 a 20, sendo que quanto menor o
valor, maior a prioridade
o processos do usuário tem prioridades de 0 a 20
o apenas processos do kernel podem ter o valor de
prioridade negativo
43
44. Gerenciamento de Processos
• Processos podem ter suas prioridades definidas no
momento da criação e também modificadas durante a
execução
• Existem dois comandos para isso:
o nice -n ## comando
executa comando com prioridade ##
o renice ## -p PID
modifica a prioridade do processo que tem id PID
para o valor ##
44
45. Gerenciamento de Processos
• Comandos nice e renice devem ser utilizados com
cuidado
o colocar processos demais em prioridade alta (nice
menor que 0) pode tornar o sistema lento
0 é o valor utilizado por padrão
o apenas o root pode colocar processo em nice menor
que 0
evita que processos de usuários, principalmente em
modo multi-usuário, interfiram na execução de
processos do sistema
processos usualmente com nice menor que 0 (-5 ou
mais) incluem comunicação com hardware (E/S...)
45
46. Gerenciamento de Processos
• Controle de execução de acordo com a prioridade é tarefa
do kernel, especificamente do Scheduler (Escalonador)
• No Linux, esse Escalonador é preemptivo, ou seja, destina
pequenas fatias de tempo para cada processo, trocando-
os de acordo com as prioridades definidas pelo usuário
'dono'
• O algoritmo atual de escalonamento passou a ser utilizado
apenas a partir da versão 2.6
o executada em tempo O(1), antiga implementação tinha
tempo O(n) em relação ao número de processos
o cada processador ou core tem uma fila independente de
processos
46
47. Gerenciamento de Processos
• Como funciona a política de escalonamento:
o tempo de processamento dividido em fatias de
tamanho fixo (quantum)
o cada nível de prioridade tem uma fila de processos que
pertencem a ela
processos tem suas prioridades modificadas
dinamicamente
o a cada processo que é selecionado é associado
um quantum de tempo para execução
quando o seu quantum acaba, ele é enviado para o
fim da fila de sua atual prioridade
47
48. Gerenciamento de Processos
• Como funciona a política de escalonamento (cont.):
o quando um processo é colocado no estado
TASK_RUNNING, o Kernel verifica as prioridades dinâmicas
do mesmo e do processo sendo executado
caso a prioridade do novo processo seja maior, é feita a
troca
o processo que saiu mantém-se no estado
TASK_RUNNING
o processos que interagem com o usuário tem prioridades
maiores
ficam sem processamento enquanto aguardam ação do
usuário, são escalonados rapidamente de volta quando
ela ocorre
o um processo batch tem baixa prioridade 48
executa usualmente enquanto um interativo aguarda
49. Gerenciamento de Processos
• Observações:
o apenas processos de usuário, não do kernel, são
preemptivos
complexidade de implementação, evita problemas de
sincronização no uso de estruturas de dados do
Kernel
o Kernel não diferencia de fato processo interativos
e batch, mas sim os que utilizam mais E/S ou mais CPU
algoritmos de escalonamento favorecem
implicitamente os de E/S - melhor tempo de resposta
de processos interativos
apenas processos de tempo-real são reconhecidos
como tal, tendo prioridade fixa na escala de 1 a 99 e
não tem execução interrompida por escalonamento 49
50. Gerenciamento de Processos
• Observações (cont.):
o o tamanho do quantum é um fator crítico para o
desempenho do sistema
se o quantum é muito pequeno, o overhead de troca de
processos pode tomar grande parte do tempo de
processamento
do contrário a responsividade é comprometida
o a função que implementa de fato o escalonador é a
schedule(), que pode ser invocada de dois modos
direto: quando recurso que o processo precisa está
indisponível, ele deve ser bloqueado
lazy: o valor do campo need_resched do processo foi
alterado para 1, em algum momento o kernel verifica
esse campo e escalona o processo 50
51. Gerenciamento de memória
• O Linux realiza o gerenciamento de memória a partir da
utilização de memória virtual. Funciona como uma camada
de abstração onde os endereços reais em hardware não
correspondem diretamente aos endereços vistos pelas
aplicações de usuário
• A utilização de memória virtual permite:
o Relocação: cada aplicação tem seu próprio espaço de
endereçamento
o Proteção e Compartilhamento: impede que um processo
utilize um endereço de memória que não lhe pertence
o Transparência: não é necessário que uma aplicação
tenha informações sobre o tamanho da memória, já que
ela não precisa limitar-se à memória física disponível 51
52. Gerenciamento de memória
• Segmentação
A memória é dividida em partes de tamanho variável e com
diferentes tipos de permissão. O endereço correspondente a
cada parte é calculado a partir de uma base e um limite
No Linux, a utilização ocorre de forma limitada, permitindo
maior simplificação e portabilidade
São utilizados 6 segmentos, os quais definem proteção em
nível de hardware para as determinadas áreas:
• código do kernel
• dados do kernel
• código de usuário
• dados de usuário 52
• TSS (segmento de estado da tarefa)
• LDT (descritores locais)
53. Gerenciamento de memória
• Paginação
A memória física é dividida em blocos de tamanho fixo,
(frames). Divide-se a memória lógica em blocos do mesmo
tamanho, chamados páginas (pages). Os frames livres são
registrados. Existe uma tabela de páginas onde é feita a
conversão dos endereços lógicos em endereços físicos
As páginas pouco utilizadas são movidas para o disco,
permitindo a utilização de mais memória do que a disponível
fisicamente
As páginas são divididas em tabelas hierárquicas, onde
podem ser acessadas a partir do page number (índice na
53
tabela que corresponde ao endereço base na memória
física) e do offset
54. Gerenciamento de memória
O Linux utiliza quatro níveis de tabelas hierárquicas: Page
Global Directory, Page Upper Directory, Page Middle
Directory e Page Table Entry
Dependendo da arquitetura, alguns dos níveis intermediários
são eliminados para obter maior eficiência
Cada processo possui suas próprias tabelas de páginas, as
quais contém apenas os endereços que o processo pode
utilizar
54
55. Gerenciamento de memória
O Linux utiliza tamanhos de páginas de acordo com a
arquitetura. Os processadores x86 utilizam páginas de 4
KiB (padrão), 2 MiB (caso seja utilizado o recurso de PAE
– Page Address Extension – da Intel) ou de 4 MiB. Nas
arquiteturas RISC o tamanho padrão é de 8 KiB, mas não
é o único
O uso de 32 bits permite o endereçamento de até 4GB,
sendo que o kernel divide esse espaço virtual em espaço
de usuário e espaço de kernel (usualmente 3GB e 1GB,
respectivamente)
55
56. Multiprocessamento
• Capacidade de um sistema operacional executar simultaneamente
dois ou mais processos
• Pressupõe a existência de dois ou mais núcleos de processamento
• A principal razão é executar multiprocessos de modo simultâneo
56
57. Multiprocessamento
Tipos de Sistemas Operacionais:
• Sistemas Simétricos (SMP – Symmetric MultiProcessing): cada
processador executa uma cópia idêntica do sistema operacional, que
comunicam-se entre si quando necessário e têm tempo uniforme de
acesso à memória
• Sistemas Assimétricos: cada processador recebe uma tarefa
específica. Um processador mestre controla o sistema e os outros,
escravos, recebem instruções dele. A distinção pode ser
implementada em hardware ou software
57
58. Multiprocessamento
• Objetivos no Linux:
o Ser eficiente em máquinas SMP
o Distribuir de maneira justa o tempo da CPU
o Possuir suporte para tempo real
o Apresentar boa performance em programas interativos,
mesmo com carga elevada
58
59. Multiprocessamento
• Problema nas versões anteriores a 2.6
o O escalonador usava uma ready list global em máquinas
SMP
o A necessidade de acesso mutuamente exclusivo à ready list
por parte dos processadores
Se um processador está acessando a ready list, os
demais necessitam esperar até que a mesma seja
liberada
Para um número elevado de processadores este bloqueio
dos processadores pode ocasionar uma queda
considerável no desempenho do sistema 59
60. Multiprocessamento
o Considere um processo bloqueado esperando uma
operação de E/S; quando termina a E/S, o processo é
recolocado na ready list global
pode ser executado por um processador diferente
daquele no qual estava rodando previamente.
Acontecendo isto, dados do processo porventura
existentes em caches não ficarão
inutilizados, influenciando negativamente a performance
60
61. Grub
• GRand Unified Bootloader
• É um multi-carregador de Sistemas
Operacionais (multi boot boot-loader)
o Boot Loader: é o primeiro software executado quando um
computador é iniciado
• Compatível com diversos sistemas de
arquivos e formatos de kernel
61
62. Processo de Boot
1.BIOS (Basic Input/Output System)
o Executa uma série de testes para localizar os dispositivos
presentes e verificar seu correto funcionamento
o Inicializa os dispositivos de hardware
o Busca um sistema operacional para dar o boot
Em geral no primeiro setor do HD ou drive de CD/DVD
o Copia o conteúdo do primeiro setor para a RAM e executa o
código carregado
62
63. Processo de Boot
2. Boot Loader – Grub
• Estágio 1: Cerca de 512 bytes, presente no
Master Boot Record (MBR)
o Apenas carrega o estágio 1.5 ou 2
• Estágio 1.5: Primeiros 30kB após MBR
o Carrega o estágio 2
• Estágio 2: Mostra a lista de sistemas
operacionais
o Carrega o kernel do S.O.
63
64. Grub
• Instalação
oEm geral é instalado automaticamente
oCaso não esteja presente:
sudo apt-get install grub
• Configuração Padrão
o update-grub
o Cria o arquivo menu.lst (em alguns sistemas menu.grub ou
menu.conf)
64
65. Grub
• Exemplo de arquivo menu.lst:
default 1
timeout 10
title Microsoft Windows XP Professional
root (hd0,1)
savedefault
makeactive
chainloader +1
title Ubuntu, kernel 2.6.17-10-generic
root (hd0,4)
kernel /boot/vmlinuz-2.6.17-10-generic root=/dev/sda5 ro quiet splash
initrd /boot/initrd.img-2.6.17-10-generic
quiet
savedefault
boot 65
66. Grub - Opções
• default n: Sistema padrão (0 é o primeiro)
• timeout t: tempo dado ao usuário para
escolher o sistema operacional. Após
esse tempo, o sistema default é escolhido
• title: nome mostrado no menu
• root: local aonde o sistema está instalado
• kernel e initrd: indica o kernel e possíveis
parâmetros
66
67. Grub – Exercício Proposto
• Analisar o arquivo menu.lst, e modificar o
tempo de timeout e o sistema operacional
padrão
67
68. Compilar o Kernel do Linux
• Mas por que compilar o Kernel?
o A atualização apresenta novos módulos, o que garante suporte a
novos dispositivos
o Tempo de inicialização mais rápido: é possível deixar somente
módulos que seu hardware utiliza
o Suporte a hardware adicional: permite a adição de suporte a
dispositivos, tais como placas de som, que não estão presentes
no kernel GENERIC
68
69. Passos para compilar o Kernel
1 - Baixar os fontes do kernel em www.kernel.org
2 - Definir uma configuração padrão
Descompatar o arquivo na pasta exemplo:
$cd linux2.6.30
(Neste exemplo foi utilizada a versão 2.6.30 do kernel. Esta
numeração não é fixa e será diferente de acordo com a versão a
ser utilizada)
$make defconfig (criar um config padrão)
Para escolher os itens que deseja habilitar/desabiltar, é necessário
usar menuconfig no lugar de defconfig
69
70. Passos para compilar o Kernel
3 - Compilar efetivamente o kernel
$make
Comando para a compilação do kernel. O tempo de execução
vai depender do hardware utilizado
$make modules
Comando para a compilação dos módulos
$sudo make modules_install
Comando para instalação dos módulos
$sudo make install
Comando para a instalação do kernel compilado
70
71. Passos para compilar o Kernel
4 - Instalar a imagem do kernel compilado
Entrar no diretório /boot
$cd /boot
Gerar a imagem
$sudo mkinitramfs -o initrd.img-2.6.30.6 2.6.30.6
(É preciso mudar o 2.6.30.6 para a versão personalizada do kernel)
5 - Após a imagem criada é preciso atualizar o grub (gerenciador de
boot)
$sudo update-grub
6 - Reiniciar o computador, escolhendo no grub a versão do kernel
desejada
71
72. Testando o Kernel compilado
1 - É preciso procurar a versão compilada no GRUB. Se ela não
estiver lá, aconteceu algo errado na instalação
2 - Escolher o kernel desejado no GRUB, teclando Enter
3 - Para verificar a versão, basta abrir o terminal e digitar:
$ uname -r
72
73. Compilando o Kernel - Exercícios
1 - Faça o download da versão mais nova do kernel e altere o nome
da versão da distribuição para: versão-seu-nome. Após compilar,
confira o resultado com o comando uname
2 - Quais os arquivos gerados pela compilação do kernel?
3 - Cite uma vantagem de manter seu kernel atualizado
73
74. Criação de uma System Call
• O que são System Calls?
São funções bem definidas que o sistema operacional provê
para que aplicações em nível de usuário solicitem serviços
do Kernel
• Lista de arquivos a serem criados/modificados
Assumindo que o código fonte do Kernel se encontra no
diretório /home/user/linux
Arquivos do Kernel que serão modificados:
1. /home/user/linux/arch/x86/kernel/syscall_table.S
2. /home/user/linux/arch/x86/include/asm/unistd_32.h
74
3. /home/user/linux/include/linux/syscalls.h
4. /home/user/linux/Makefile
75. Criação de uma System Call
Novos arquivos/diretórios do Kernel que serão criados
(considerando que o nome da nova System Call é “mycall”):
1. /home/user/linux/mycall – Diretório que conterá a nova
System Call, que deve ser criado manualmente
2. /home/user/linux/mycall/mycall.c – Código fonte da
System Call criada
3. /home/user/linux/mycall/Makefile
Novo arquivo em espaço de usuário criado para testar a
System Call:
1. testmycall.c – Código que chama a nova System Call 75
76. Criação de uma System Call
• syscall_table.S
É um arquivo assembly que contém os nomes das System
Calls
1. Adicionar uma linha no final do arquivo, no exemplo trata-se
da linha 337
2. Adicionar “.long sys_mycall” no final da lista de System Calls
76
Exemplo de modificação do arquivo syscall_table.S
77. Criação de uma System Call
• unistd_32.h
Este arquivo contém o número da System Call que é
passado ao Kernel através do registrador (EAX) quando a
System Call é chamada
1. Adicionar “#define __NR_mycall
<Número_Última_System_Call + 1>” ao final da lista
77
Exemplo de modificação do arquivo unistd_32.h
78. Criação de uma System Call
• syscalls.h
Este arquivo contém as declarações das System Calls
1. Adicionar a seguinte linha no final do arquivo:
“asmlinkage long sys_mycall(int i);”
Exemplo de modificação do arquivo syscalls.h 78
79. Criação de uma System Call
• Makefile
1. Adicionar “mycall/” ao core-y. Estará incluindo no Makefile
geral o diretório onde se encontram o código fonte da nova
System Call e o Makefile específico
Exemplo de modificação do arquivo Makefile
79
80. Criação de uma System Call
• mycall.c
1. Criar o arquivo fonte “mycall.c” no diretório “mycall”.
“mycall.c” conterá o código da nova System Call. A definição
da System Call no código fonte será “asmlinkage long
sys_mycall(...){...}” e deve incluir o arquivo “linux/linkage.h”.
Asmlinkage é usado para procurar os argumentos na pilha do
kernel
80
Exemplo de código fonte da nova System Call criada
81. Criação de uma System Call
• Makefile
1. O Makefile no diretório “mycall” conterá uma linha:
#####Makefile Start#####
obj-y := mycall.o
#####Makefile End#######
• Compilação e instalação do Kernel
Após esse ponto, é necessário compilar e instalar a nova
versão modificada do Kernel
81
82. Criação de uma System Call
• testmycall.c
1. “testmycall.c” é um arquivo que será utilizado como teste
da nova System Call criada. É necessária a inclusão da linha
“#define __NR_mycall XX”, onde XX é o número atribuído à
nova System Call. Em caso de erro, a chamada da System
Call retorna o valor -1
82
Exemplo de arquivo de teste da System Call criada
83. Criação de uma System Call
• Exercícios propostos
1. Crie uma System Call que recebe o PID de um processo
e retorna a prioridade do mesmo
2. Crie uma System Call que recebe dois PIDs de
processos diferentes e retorna qual dos dois processos
possui a maior prioridade
3. Crie uma System Call que recebe dois PIDs de
processos diferentes e troca a prioridade dos mesmos. Ou
seja, se o processo 1 tinha prioridade 10 e o processo 2
prioridade 15, ao final teremos 1 com prioridade 15 e 2
com prioridade 10 83
84. Módulos
• Linux permite adicionar ou remover
funcionalidades enquanto o sistema está
rodando
• Cada trecho de código que pode ser
adicionado ou removido é chamado “módulo”
• Os módulos podem ser ligados dinamicamente
ao kernel via comando insmod
• Podem ser desligados via comando rmmod
84
86. Módulos: Makefile
• Para Compilar:
omake
• Para instalar:
osudo insmod hello.ko
• Para desinstalar:
osudo rmmod hello.ko
86
87. Módulo “Hello World”
• Mensagens geradas pela função printk
ficam armazenadas geralmente em
/var/log/messages.
o Outros logs do Kernel: /var/log/kern.log e /var/log/syslog
• printk(): versão simplificada do printf
o Não imprime floats/doubles:
Troca de contexto padrão não salva o estado da FPU
É possível salvar o contexto da FPU com os comandos
kernel_fpu_begin() e kernel_fpu_end() porém essas funções
chamam preempt_disable() e preempt_enable(), o que
paralisa a preemptividade do kernel.
87
88. Passagem de Parâmetros
• Parâmetros podem ser passados para os
módulos no momento do carregamento:
• Trecho adicionado ao módulo:
88
• Ex.: insmod modulo.ko num=2 str=“abc”
89. Módulos - Funções Úteis
• Carga e descarga de módulos:
o insmod
o modprobe
o rmmod
• Inicialização (init) e término (exit):
o #include <linux/init.h>
o module_init(init_function);
o module_exit(cleanup_function)
89
90. Módulos - Funções Úteis
• Informações do processo atual:
o #include <linux/sched.h>
o struct task_struct *current;
current->pid : process id
current->comm: command name
• Header necessário:
o #include <linux/module.h>
90
91. Módulos - Funções Úteis
• Passagem de parâmetros:
o #include <linux/moduleparam.h>
o module_param(variável, tipo, permissões);
Permissões:
S_IRUGO: pode ser lido mas não modificado
S_IWUSR: pode ser alterado pelo root
• Log:
o #include <linux/kernel.h>
o int printk(const char *fmt, …);
Mesmos parâmetros do printf, exceto ponto
flutuante
91
92. Módulos – Exercício Proposto
• Modificar o módulo Hello World de
maneira que esse aceite um parâmetro N
do tipo int e um parâmetro S do tipo
String. Fazer com que o módulo ao ser
carregado mostre os parâmetros
recebidos, e na descarga repita N vezes a
String S
92
93. Device Drivers
• Permitem a interação do Kernel com
dispositivos de entrada e saída
• Consistem de estruturas de dados de
funções que controlam um ou mais
dispositivos
o Discos rígidos, teclados, mouses, monitores,
interfaces de rede
93
94. Device Drivers
• Cada driver interage com o kernel e com
outros drivers através de uma interface
específica:
o Código específico a um dispositivo pode ser encapsulado em
um módulo específico
o Novos dispositivos não precisam conhecer o código fonte do
kernel, apenas as interfaces
o O kernel acessa todos os dispositivos através da mesma
interface
o É possível escrever um driver como um módulo
dinamicamente carregável
94
95. Device Drivers
• Conjunto de rotinas que fazem um
dispositivo de hardware responder à
interface de programação definida pelas
operações canônicas:
o open, read, lseek, ioctl etc.
• Em geral são divididos em 3 classes:
o Caractere
o Bloco
o Interfaces de rede
95
96. Device Drivers
• Dispositivos podem ser conectados a
portas de Entrada/Saída ou terem suas
portas mapeadas em memória
• Portas de E/S:
o Kernel disponibiliza funções para acesso
inb(), inw(), inl()
outb(), outw(), outl()
o Funções request_resource(), allocate_resource()
e release_resource()
Garantem acesso às portas do dispositivo
96
97. Device Drivers
• E/S mapeado em memória
o Dispositivos são mapeados em endereços físicos
de 32 bits
o É necessário traduzir o endereço físico para um
endereço linear
Funções: ioremap() e ioremap_nocache()
o Acesso: readb(), readw(), readl(), writeb(),
writew(), writel(), memcpy_fromio(),
memcpy_toio()
97
103. Device Drivers - Exemplo
• Compilação igual a um módulo
• Passos adicionais:
o mknod /dev/memory c 60 0
o chmod 666 /dev/memory
• Para iniciar:
o insmod memory.ko
• Exemplo de uso:
o echo -n abcdef >/dev/memory
o cat /dev/memory
103
104. Device Drivers - Exercício
• Modificar o código do driver, adicionando
as seguintes funcionalidades:
o O tamanho do buffer deve ser definido via parâmetro
o O driver deve conseguir retornar o buffer completo, e
não somente o último caractere, como acontece no
exemplo
• Artigo original em:
http://www.freesoftwaremagazine.com/articles/drivers_linux
• Atenção: o código original mostrado no artigo foi
desenvolvido para versões antigas do kernel. Por isso o
código mostrado nos slides anteriores foi alterado para
104
possibilitar seu uso com um kernel atualizado
105. Tempo Real
• O que é um sistema em tempo real?
o Um sistema computacional em tempo real é um sistema cuja
correção depende não somente do resultado lógico dos
processamentos, mas também do instante em que os resultados
são produzidos
o O sistema deve ter a habilidade de executar um comando ou
instrução e disponibilizar a resposta em um tempo relativamente
previsível
105
106. Tempo Real
• Sistema:
o Um escalonador em tempo real substitui o escalonador original
o Executa qualquer código em tempo real, associado ao
escalonador em tempo real
o Executa todos os processos normais de tempo restante
106
107. Tempo Real
• Quando uma aplicação é executada em modo usuário, a mesma não
tem privilégios do modo kernel
• Qualquer grande aplicação executada em tempo real desejará obter
acesso privilegiado
• Os recursos são divididos em duas categorias
o Tempo Real
o Tempo não Real
• A comunicação entre esses duas categorias pode ser realizada das
seguintes formas:
o Memória compartilhada
o Lógica FIFO
107
108. Tempo Real
• Vantagem e desvantagem:
o No Linux, há uma divisão entre aplicações de Tempo Real
e de Tempo não Real
o Essa divisão torna as aplicações de Tempo Real mais
rápidas
o Contudo, ela dificulta a programação da aplicação em si se
for feito um comparativo com outros Sistemas Operacionais
que tratam todas aplicações como Tempo Real
108
109. Tempo Real
• O Kernel do Linux interage com três relógios de hardware diferentes:
o Real Time Clock (RTC)
o Time Stamp Counter (TSC)
o Programmable Interval Time (PIT)
• Os dois primeiros auxiliam o Kernel a obter a data e a hora atuais do
sistema, enquanto o último é programado para gerar interrupções
fixas em frequências determinadas pelo kernel
109
110. Tempo Real
• Utilização da Hora:
o Existem três chamadas de sistema, em nível de programação,
disponíveis para obtenção de horas no Linux:
time(), ftime() e gettimeofday()
o Além de funções de formatação das unidades de tempo, tais
como:
ctime(), asctime(), gmtime(), localtime(), mktime() e
strftime()
110
111. Tempo Real
• time(): retorna o número de segundos passados desde a primeira
hora do dia primeiro de janeiro de 1970
• Operações que exigem precisão não poderão ser feitas com a
função time(). A melhor resolução que consegue-se com ela é de
um segundo, com erro de meio segundo
111
113. Tempo Real
• ftime(): Possui uma estrutura de dados interna que fornece mais
informações sobre a hora atual. Bastante precisa, suas operações
internas demoram na ordem de centenas de nanosegundos o que é
mil vezes menor que sua menor unidade de medição
struct timeb {
time_t time;
short unsigned millitm;
short timezone;
short dstflag;
}
113
114. Tempo Real
• Modos de retorno de ftime():
o time - tem a mesma função do retorno da função time()
o millitm - dá os milisegundos trancorridos do mesmo momento
o timezone - o valor em minutos a oeste do meridiano de Greenwich
em que nos encontramos
o dstflag - será setado em 1 se estivermos no horário de verão ou 0
se não
o Biblioteca sys/timeb.h
114
116. Tempo Real
• gettimeofday(): é a função mais utilizada para a obtenção da hora
atual. Sua principal diferença em relação às anteriores é que possui
duas estruturas de dados internas:
struct timeval {
long tv_sec;
long tv_usec;
}
struct timezone {
int tz_minuteswest;
int tz_dsttime;
}
116
117. Tempo Real
• Modos de retorno de gettimeofday():
o tv_sec - guardará o valor em segundos que se passou desde a
primeira hora de primeiro de janeiro de 1970
o tv_usec - retorna o número de microssegundos transcorridos
após o último segundo
o tz_minuteswest - tem a mesma função que timezone de ftime()
o tz_dsttime - está em desuso (retorna erro no linux)
o Biblioteca sys/time.h
117
119. Considerações Finais
• O desenvolvimento do kernel não é uma tarefa simples
• O Linux possui um kernel monolítico modularizado
• A escolha de um Sistema de Arquivos deve ser feita levando em
consideração aspectos como confiabilidade e rapidez
• O gerenciamento de memória do Linux utiliza memória virtual com
técnicas como segmentação e paginação, propiciando transparência,
proteção e relocação
119
120. Considerações Finais
• Por possuir um bom escalonador, o Kernel permite que um certo
número de tarefas funcione aparentemente de modo simultâneo, de
acordo com suas prioridades
• O Linux implementa multiprocessamento em diversos pontos do
kernel, visto que essa tecnologia traz vantagens com relação ao
desempenho
• O Kernel oferece System Calls destinadas a manipulação de
processos, permitindo que as aplicações tenham controle sobre
suas execuções e de seus filhos
120
121. Considerações Finais
• Criar uma System Call com funcionalidades específicas que pode
interagir diretamente com o Kernel é uma grande vantagem em
sistemas de código aberto como o Linux
• Sistemas de tempo real diferenciam-se pelo fato do tempo de
resposta exigido ser rigoroso no processamento das informações, e
a não execução de determinada tarefa nesse tempo de resposta
pode ser catastrófica para a aplicação
121
122. Referências
• BOVET, Daniel; CESATI, Marco. Understading the Linux
Kernel. 3. ed. 2006. O’Reilly.
• MELLO, Alan Godoy S. Arquitetura do Kernel Linux. 7 mai.
2009. Instituto de Computação UNICAMP. Disponível em:
http://www.ic.unicamp.br/~islene/mc514/Kernel_Linux.pdf.
Acesso em 06 dez. 2009.
• Implementing a System Call on Linux 2.6 for i386.
Disponível em:
http://www.linux.org/docs/ldp/howto/Implement-Sys-Call-
Linux-2.6-i386/index.html. Acesso em 05 dez. 2009.
122
123. Referências
• Linux Man Pages. Disponível
em: http://www.linuxmanpages.com
• O gerenciador de boot GRUB. Disponível em:
http://www.infowester.com/lingrub.php
• GNU GRUB Manual 0.97. Disponível em:
http://www.gnu.org/software/grub/manual/grub.html
• GRUB. Disponível em: http://wiki.ubuntu-br.org/Grub
• CORBET, Jonathan; RUBINI, Alessandro; KROAH-
HARTMAN, Greg. Linux Device Drivers. 3. ed. O’Reilly.
123