GERENCIA DE PROCESSOS EM LINUX
Death Knights Issue 0
by SaTaNfAcE
Y0z d00dz!!! Bem vamos ao q interressa!!!
Bem, nessa matehria eu irei falar um pouco da "parte logica" do linux, pra ser mais claro, nessa matehria escrevi sobre como o Linux gerencia seus processos, sobre o boot do sistema e sobre a gerencia de processos pelo Kernel!!! Eh iss0 aih espero q a matehria seja util!!!!
Consideracoes Iniciais
Para explicarmos como o Linux gerencia processos, faremos consideracoes iniciais sobre o codigo fonte do kernel do Linux (onde encontramos a implementacao da Gerencia de Processos) e a inicializacao "boot" do sistema.
Nos tentaremos explicar, de uma maneira ordenada o codigo fonte do Linux, tentando conseguir um bom entendimento sobre como o codigo fonte esta situado e como as caracteristicas mais relevantes do UNIX foram implementadas. O objetivo e ajuda-lo a se familiarizar com o projeto geral do Linux. Entao, vamos comecar por onde o Linux comeca: seu sistema de boot.
Um bom entendimento da linguagem C e necessario para entender este material, assim como familiaridade com conceitos de UNIX e arquitetura dos PCs. Porem, nenhum ccdigo C aparecera neste material, mas referencias de onde podem ser encontrados.
Qualquer referencia "pathname" a arquivos tem como ponto de partida a arvore principal de fontes, usualmente /usr/src/linux. A maioria das informacoes reportadas aqui tem como referencia o codigo fonte do Linux versao 1.0. Referencias a versoes posteriores conterao o simbolo.
Caso o simbolo nao estiver presente, significa que nao houveram modificacoes apos as versoes 1.0.9-1.1.76.
Ocasionalmente um paragrafo como este ocorrera no texto. Indicando onde poderam ser obtidas mais informacces sobre o assunto corrente (geralmente o codigo fonte).
Inicializacao ("boot" do sistema)
Quando o PC e ligado, o processador 80x86 encontra-se em modo real e executa o codigo contido no endereco 0xFFFF0, que corresponde a um endereco ROM-BIOS. O BIOS do PC realiza alguns testes no sistema e inicializa o vetor de interrupcoes no endereco fisico 0. Depois disto ele carrega o primeiro setor do device bootavel em 0x7C00, e passa a execucao para este endereco. O device e, usualmente, o disquete ou o disco rigido. A descricao anterior e um tanto simplificada, mas e tudo que se necessita para entender o trabalho inicial do kernel.
A primeirissima parte do kernel Linux esta escrito em linguagem assembly 8086 (boot/bootsect.S). Quando e executado, ele se move para o endereco absoluto 0x90000, carrega os proximos 2 kBytes de codigo do device de boot ate o endereco 0x90200, e o resto do kernel para o endereco 0x10000. A mensagem "Loading..." e apresentada durante o carregamento do sistema. O controle e, entao passado para o codigo contido em boot/Setup.S, outro codigo assembly de modo real.
A parte de "setup" identifica algumas caracteristicas do sistema (hardware) e o tipo da placa VGA. Se requerido, pede ao usuario para escolher o modo do video da console. E, entao, move todo o sistema do endereco 0x10000 para o endereco 0x1000, passa para o modo protegido e passa o controle para o resto do sistema (endereco 0x1000).
O proximo passo e a descompressso do kernel. O codigo em 0x1000 vem de zBoot/head.S que inicializa os registradores e invoca decompress_kernel(), o qual e composto por zBoot/inflate.c, zBoot/unzip.c e zBoot/misc.c. O dado "descompresso" vai para o endereco 0x100000 (1 Mega), e esta e a principal razao do por que o Linux nao pode rodar com menos de 2 Megas de RAM.
O encapsulamento do kernel em um arquivo gzip e realizado por Makefile e utilitarios no diretorio zBoot. Sao arquivos interessantes para se dar uma olhada.
O codigo "descompresso" e executado a partir do endereco 0x1010000 , onde todo o setup 32-bit esta lotado: IDT, GDT e LDT sao carregados, o processador e o co-processador sao identificados, a rotina start_kernel e invocada. Os arquivos fonte das operacoes acima estao em boot/head.S. Este, talvez, seja o codigo mais dificil em todo o kernel do Linux.
Note que se algum erro ocorrer durante alguns dos passos precedentes, o computador ira travar. O sistema operacional nao pode manipular erros enquanto nao estiver totalmente operante.
start_kernel() reside em init/main.c. Tode de agora em diante esta codificado em linguagem C, exceto gerencia de interrupcoes e chamadas de sistemas (Bem, a maior parte das macros possuem codigos assembly embutidos, tambem).
Depois dos procedimentos com todas as questoes iniciais, start_kernel() inicializa todas as partes do kernel, especificamente:
- Inicializa a memoria e chama paging_init().
- Inicializa os traps, canais IRQ e scheduling.
- Se requerido, aloja um profiling buffer.
- Inicializa todos device drives e buffers de discos, bem como outras partes menores.
- Regula o delay loop (calcula o numero "BogoMips").
Checa se a interrupcao 16 esta trabalhando com o co-processador.
Finalmente, o kernel esta pronto para move_to_user_mode(), em seguida fork (bifurca) o processo de inicializacao, cujos ccdigos estao no mesmo arquivo fonte. E o processo numero 0, tambem chamado idle task (tarefa preguicosa), se mantem rodando em um loop infinito. O processo de inicializacao tenta executar /etc/init, ou /bin/init, ou /sbin/init.
Se nenhum deles tem sucesso, o codigo se desvia para "/bin/sh /etc/rc" e cria um root shell no primeiro terminal (console). Este codigo e remanescente do Linux 0.01, quando o S.O. era feito para um kernel stand-alone, e nao havia processo de login.
Depois de exec() o programa de inicializacao de um dos lugares padrao (deve haver um deles), o kernel nao tem controle direto sobre o fluxo do programa. Sua funcao, de agora em diante, e prover processos atraves de chamadas ao sistema (system calls), assim como prover eventos para servicos assincronos (como uma interrupcao do hardware). A multitarefa esta inicializada, e inicializara o gerenciamento de acesso a multiusuarios, atraves do fork() e processos de login.
Estando o kernel carregado e provendo servico, vamos prosseguir dando uma olhada nesses servicos ("system calls").
Gerencia de processo pelo kernel
Do ponto de vista do kernel, um processo e uma entrada na tabela de processos. Nada mais.
A tabela de processos, entao, e uma das mais importantes estruturas de dados no sistema, conjuntamente com a tabela de gerenciamento de memoria e o buffer cache. O item individual na tabela de processos e a estrutura task_struct, definida em include/linux/sched.h. Com a task_struct, tanto informacoes de baixo quanto de alto nivel, sao mantidas * variando da copia de alguns registradores de hardware ate o inode do diretorio de trabalho para o processo.
A tabela de processos e tanto um array quanto uma lista duplamente ligada, como uma arvore. A implementacao fisica e um array estatico de ponteiros, cujo tamanho e NR_TASKS, uma constante definida em include/linux/tasks.h, e cada estrutura reside em uma pagina de memoria reservada. A estrutura da lista esta entre os ponteiros next_task e prev_task, a estrutura em arvore e um tanto complexa, e nao sera descrita aqui. Voce pode desejar mudar NR_TASKS do seu valor default (que e 128), mas esteja certo de que ha dependencias, e sera necessario recompilar todos os arquivos fonte envolvidos.
Depois do boot, o kernel esta sempre trabalhando em um dos processos, e a variavel global "current", um ponteiro para um item da task_struct, e usado para guardar o processo que esta rodando. A variavel "current" so e mudada pelo scheduler, em kernel/sch ed.c. Quando, porem, todos os processos necessitarem estar looked, a macro for_each_task e usada. Isto e consideravelmente mais rapido que uma procura seq¸encial no array.
Um processo esta sempre rodando em ou em "modo usuario" ou em "modo kernel". O corpo principal de um programa de usuario e executado em modo usuario e chamadas a sistema sao executados em modo kernel. A pilha usada pelos processos netes dois modos de execucao sao diferentes * um seguimento de pilha convencional e usado para o modo usuario, enquanto uma pilha de tamanho fixo (uma pagina, cujo processo e dono) e usada no modo kernel. A pagina de pilha para o modo kernel nunca e swapped out, porque ela pode estar disponivel sempre que um system call e introduzido.
Chamadas a sistema (System calls), no kernel do Linux, sao como funcoes da linguagem C, seu nome "oficial" esta prefixado por "sys_". Uma chamada a sistema de nome, por exemplo, burnout invoca a funcao de kernel sys_burnout().
O mecanismo de chamadas a sistema (System calls) esta descrito no capitulo 3 do Linux Kernel Hackers' Guide (http://www.redhat.com:8080/HyperNews/get/khg.html). Uma olhada em for_each_task e SET_LINKS, em include/linux/sched.h pode ajudar a entender a lista e a estrutura de arvore da tabela de processos.