Home

br.kernelnewbies.org
[ Dicas | Download | Email | Exemplos | F.A.Q | Documentação | Links ]

Uma Visão Básica Sobre Processos no Kernel 2.6

 

 

 

Introdução

Escrevo este pequeno texto para mostrar o que é e como funcionam os processos no Kernel linux da família 2.6. Este não é nem de longe um tutorial de como se tornar um kernel hacker, nem mesmo de como compilá-lo, mas uma visão superficial de como é e como funciona os processos no kernel linux em especial o 2.6.

O kernel linux não é uma coisa das mais complicadas, porém a disponibilidade do código fonte, não permite que somente olhando você possa entende-lô, você precisa colocar a mão no código, ou mesmo trabalhar no código, procurar melhorias em seu sistema, como tudo na vida , a teoria dá um bom paramêtro de aprendizado, mas a prática te ensina a entender como as coisas funcionam.

Visão geral do Kernel 2.6

O kernel linux é o núcleo de todas as distibuíções GNU/linux como o Slackware e o Debian, para citar exemplos. Kernel é a camada mais baixa de comunicação com o hardware, gerênciando os recursos do computador. Embora o kernel linux esteja enraizado no UNIX, ele tem suas próprias características e vantagem distintas de um UNIX. Como o UNIX e até mesmo o MS-DOS o kernel do linux é monolítico, ou seja, possibilita uma interface de alto nível para chamadas do sistema específicas para a gestão de processos, memória e outros fatores. Mas o que acredito ser um dos sucessos do Kernel linux é a liberdade no sentido completo da palavra, todo o conjunto de soluções que são empregados no kernel linux é resultado da liberdade e modelo de desenvolvimento aberto.

O kernel 2.6 nada mais é que uma continuação do kernel 2.5, a nomenclatura por números do kernel é correspondente a seu processo de desenvolvimento, onde é sempre composto por 3 números:

versão . "versão de produção" . release

Exemplo: 2.6.10
2 => Versão do Kernel
6 => "versão de produção"
10 => Realease

O número correspondente a "versão de produção" atribuí ao kernel uma característica importante, ou seja, o estágio de desenvolvimento em que o mesmo se encontra. Versões que apresentam este campo em um número par é uma versão de produção ou estável, e quando apresenta um número ímpar significa uma versão em desenvolvimento ou de teste, como no caso do antecessor do 2.6, o 2.5.

Mas em sua atual versão, 2.6, o kernel traz muitas mudanças em relação as versões anteriores, como melhora no desempenho, sistemas de arquivos e suporte as novos dispositivos e plataformas. Alguns recursos foram quase que extintos do kernel, e outros melhorados, como o caso do schudler().

O schudler() basicamente é um algoritimo que controla os estados dos processos no sistema, ele seleciona qual processo deve ser inciado após o termino de um outro processo em andamento. Sendo o linux um sistema multitarefa, o schudler() trabalha controlando os processos no sistema.

No desenvolvimento do kernel 2.5 o schudler() rebecebeu uma revisão em seu código, recebendo até um novo nome schudler O(1). Esta revisão possibilita ao schudler O(1) novas características em relação as outras versões do Kernel linux. Esta melhora no schudler O(1), possibilita ao linux uma melhor performance em sistemas SMP (Symmetric Multi-Processing, multiprocessamento simétrico) . No antigo schudler(), para trabalhar em sistemas com multiprocessamento, os processos ficavam rodando ora em um processdor ora em outro processador, na versão atual do kernel isso não acontece mais, distribuíndo em forma de uma lista de execução os processos para cada processador.

Muitas outras mudanças também são significativas na família 2.6, como o fato de poder carregar gravadores de CD IDE sem a necessidade de emulação SCSI. Isso da-se a melhora ao suporte as placas Plug and Play, e a encorporação dos drivers ALSA ao kernel, permitindo que os aplicativos acessem o gravador diretamente. Mas não vou me estender comparando as mudanças das versões anteriores do kernel para atual, e sim passar um pouco da idéia de como funciona os processos no kernel 2.6

Os processos no Kernel linux 2.6

Um processo é um ambiente de execução que contempla um segmento de instruções, e dois segmentos de dados, no entanto um programa não é necessáriamente um processo, já que podemos ter vários processos compartilhando um mesmo programa.

O kernel atribuí a cada processo um espaço de tempo, função essa do schudler O(1), que permite que um processo entre e saia diversas vezes no processador em um único segundo, ou seja, ele pode não estar em um certo tempo no processador e mesmo assim continuar rodando pois o kernel fornece ao processo dois tipos de virtualização, um processador virtual e uma memória virtual, dando a ilusão ao processo de que ele esta sozinho no sistema. Cada processo tem sua indentificação, ou PID. PID é um valor númerico geralmente inteiro (int). Esse Intendificador é único, no caso dos usuários ele pode estar associado a um grupo, nesta situação o identificador do processo utilizado é o PGPR.

Veja um exemplo: pid.c

#include <stdio.h>
#include <unistd.h>

int main ()
{
/* indentificando o processo */
printf ("Processo número %d \n", getpid());

/* identificando o pai do processo */
printf ("Pai do processo %d \n", getppid());

/* identificando o grupo do processo */
printf ("Grupo do processo %d \n", getpgrp);

/* usei o sleep para que você possa executar o
* comando ps ax, e visualizar o processo em execução */

sleep(5);
}

OBS: ao executar este exemplo, execute em um outro terminal o comando ps ax para visualizar o processo.

Explicando o exemplo

Um processo é iniciado quando singelamente ele é criado, a criação de um processo é através da chamada de sistema fork() criando um novo processo duplicando um processo existente, a cópia de um processo já existente é feita de pai para filho. O processo que realiza a chamada do sistema fork() é o pai, em nosso exemplo utilizamos a função contida em unistd.h para identificarmos o processo pai, getppid (), ao observarmos o número do pid com o comando ps ax, podemos identificar que o pai do processo , no meu caso, é o bash, que originou o processo filho.

processo em execução:

:~>./pid
Processo número 5067
Pai do processo 4911
Grupo do processo 134513480

:-> ps ax
4911 pts/1 Ss 0:00 bash

O pai retorna a execução e o filho incia a execução. O segmento de dados do processo filho é uma cópia exata do processo pai, no entanto a cópia de segmento de dados do filho pode diferir do pai, como por exemplo o pid, tempo de execução, etc.

O primeiro processo do kernel, o processo de pid 0, é criado na inicialização do sistema, e responsável por criar a thread de inicialização, após carregados todos os dados para este processo, e finalmente iniciado o processo de pid 1(ou init), através da chamada do sistema execve(). Deve ficar claro, a interpretação de threads no Kernel linux, no linux não há nenhum conceito de thread, o linux implementa todas as threads como processos padrões, thread é meramente um recurso de compartilhamento de recursos do sistema, como recursos de espaço de endereço. As threads são criadas como processos normais com a exceção de que a chamada do sistema clone() é transmitida aos flags que corrrespondem aos recursos específicos a serem compartilhados. As threads do kernel se diferenciam das threads normais por não possuírem um espaço de endereço, como os processos normais.

Podemos dizer que um processo é como uma vida humana, é iniciado por "Deus", ou processo de pid 0, e tem um tempo de vida, tem seu trabalho e ser executado, seus filhos, compartilha alguns momentos, é depois morre. A morte de um processo acontece quando é realiza a chamada do sistema exit(), onde o kernel libera os recursos atribuídos ao processo e notifica ao pai. Um processo pode terminar também de forma inesperada, acontece quando um processo recebe um sinal ou execução na qual não sabe lidar.

Veja esse exemplo: processos.c

#include<stdio.h>
#include<unistd.h>

int main ()
{
printf ("Eu sou um processo filho de pid %d e de pai %d \n", getpid(), getppid());
printf ("Agora vou criar um processo filho e eu serei seu pai \n");

if(fork() == 0)
{
printf ("Este é um processo filho %d \n", getpid());

printf("Esse é meu pai %d \n", getppid());
}
exit(0);
}

O fork() é a chamada do sistema que realiza a criação de um novo processo, perceba que este programa estará criando um filho de pid diferente e poderá conter outras funções diferente de seu pai. Ao final da execução o processo filho é morto, mas não necessariamente o processo pai será morto com o filho, o processo pai pode estar criando novos filhos ou mesmo continuar suas tarefas.

O Kernel linux é preemptive, isso significa que cada processo tem uma prioridade, e o kernel checa se existe um processo com prioridade maior do processo corrente. Os processos são organizados no kernel através de uma lista de tarefas, cada elemento desta lista é um descritor do processo, que contém todas as informações sobre um determinado processo. A relação entre os processos é armazenada no descritor dos processos. Como visto, todos os processos tem um pai, processos pais podem ter vários filhos, e os filhos relacionados ao mesmo pai são chamados de irmãos, as informações entre estes processos é armazenada no descritor do processo.

Os processos de prioridades mais altas são processados antes dos processos de prioridade baixas, sendo que processos com prioridades idênticas seram executados em forma de rodízio. O usuário e o sistema pode influenciar a prioridade de um processo alterando o comportamento do sistema. O kernel divide em dois as prioridades dos processos, a primeira que varia entre os -20 a 19, carateriza a prioridade do processo. O default de um processo é 0, sendo que quanto maior for seu número de prioridade, menor será sua fatia de tempo, e quanto menor for sua prioridade maior será sua fatia de tempo, por exemplo um processo de prioridade -2, será executado primeiro que um processo de prioridade 10. A segunda parte da divisão é os processos em tempo real,variam entre 0 a 99, sendo que todos os processos em tempo real tem uma prioridade mais alta que os processos normais. Você pode alterar a prioridade de um processo com o comando :

nice -n <prioridade> comando

OBS: visualize com o comando top os processos atuais em execução e sua prioridade



Finalizando

Esse texto foi simplesmente para passar uma visão de como os processos trabalham no kernel linux. Peço que se encontrarem algum erro, ou mesmo tiverem alguma dúvida em relação ao texto que entre em contato comigo para corrigir ou mesmo solucionar dúvidas que referênte ao texto.

Autor
André Osti de Moura
andreoandre@gmail.com


© 2001-2002 by the people in #kernel-br - Webdesign by Caio Begotti (caio1982) & Fábio Minami (sussumo)