Tempos de
DOS e
MSX, velhos tempos que não voltam mais, onde programadores se divertiam com o livros para DOS, e que hoje encontramos todos reeditados. Não pude desfrutar dessa época, mas para quem deve lembrar eram livros que ensinavam a fazer coisas fantásticas para a época, como criar relógios no canto da tela
Para todos aqueles que não puderam desfrutar de boas literaturas do tempo, hoje estão de volta. Sempre tive uma grande queda por linguagens antigas, como COBOL, BASIC,PASCAL, FORTRAN e claro o ASSEMBLY, mas dentre todas essas eu sempre achei que Assembly era coisa de doido, e ainda acho, sendo assim não tenho como garantir minha própria sanidade mental já que vi algumas coisas para doidos, digamos que pude provar do Elixir da loucura.
O
Unix,
Linux,
FreeBSD, e não apenas este mas outros também da família BSD, nos oferece igual e se não muito maior potencial para fuçadores natos como eu. Bem sabemos o quanto estas plataformas se tornaram famosas tanto em grandes servidores como em sistemas embutidos (embedded systems).
Digamos que neste artigo vamos fazer um paralelo do que encontrava-se nas antigas literaturas conforme citado acima, e como "portar" os mesmos raciocínio para o
Linux. Claro levando em consideração as características do sistema, não teremos como criar um exemplo do tipo relógio no canto da tela, não que não dê, mas é trabalhoso e teríamos que estender muito este artigo, vou tentar buscar a cabo com as explicações sobre como se comportam o que chamamos de interfaces disponíveis.
Modo Real e Modo protegido
Antes de mais nada lembremos das limitações que eram
encontradas nos processadores antigos, 640 Kb se quer
pareciam ser um problema já que para a época era o que
se tinha disponível. A grande maioria eram baseados em
processadores como o Z80 (Microprocessadores de 8 Bits
e com endereçamento máximo e direto de 64Kb).
Já nos 80286, existia um modo de trabalho do processador
que era chamado de modo protegido. Ou seja, quando o
processador era ligado, se comportava como um 8086, mas
após a entrada neste modo, novas características eram
habilitadas, como maior capacidade de endereçamento de
memória, permissões de acesso dessa memória etc.
A grosso modo podemos dizer que processadores em
modo real, eram por exemplo os 386 que se portavam como
um 8086, rodando diretamente programas, como o DOS em
16 Bits, com endereçamento de até 640 Kb, não importando o quanto
tivesse instalado na máquina. E o modo protegido eram aqueles
que apresentavam além de as vantagens citadas, a melhoria
de forma de entrada e saída deste modo para o modo real,
outra das vantagens do modo protegido eram as facilidades
de multitarefas e que com certeza revolucionaram os programas
da época.
A explicação sobre processadores de modo real e modo protegido se deu apenas para mostrar que o Linux no seu boot, inicia em "Modo real", mas muda para o "Modo protegido", em um dado momento. Portanto existem as regras deste modo, como o que chamamos de permissões de escrita, leitura e execução em trechos da memória. E com isso esclarecemos o por que não dá para dizer igual no DOS, alterar um endereço diretamente, sem levarmos em conta a quem pertence.
No caso do Linux, temos a memória que está protegida pelo Kernel, e que está disponível para os programas dos usuários (Kernel e User memories). Esta tentativa poderia causar um erro de segmentação (Segmentation Fault), uma exceção que é disparada pelo processador e sinalizada pelo Kernel, indicando que foi tentado uma operação não permitida.
Bem, agora sabemos que o Linux utiliza o máximo que pode de um processador e que é um sistema multitarefa, multiusuários e de 32 bits, que roda em "Modo protegido". Fazendo um paralelo sobre a BIOS, está claro que o software que roda nas BIOS de hoje em dia estão bem mais elaborados que antigamente até por que hoje em dia os Hardwares existente exigem isso, mas ainda temos a mesma limitação de interface como antigamente, inclusive se usa a mesma interface para os programas.
Mas estas interfaces não foram pensadas para um sistema multitarefa como o Linux, e portanto se fosse permitido usar as funções da BIOS, programando no Linux, teríamos um problema.
As rotinas não prevêem que mais de um processo pode tentar acessar o mesmo recurso e, portanto não implementam travas para isso, vamos ilustrar um pequeno exemplo em C, antes de mais nada vou dar uma explicadinha. A grosso modo o que faremos é, usar uma função que quando executada, checa se o flag busy é 0 (zero), se for significa que o recurso está livre, sendo assim é inicializado, flag setado para 1 e se procede o resto da função.
1 int Func (void) {
2 static char busy=0;
3 if (!busy){
4 init_stuff();
5 busy=1;
6 }
7 else {
8 fprintf(stderr,"Recurso ocupado\n");
9 return ERROR;
10 }
11 }
Na linha 2 criamos uma variável estática e inicializamos ela com o valor 0 para o flag, dessa forma sinalizamos o uso de um recurso, caso não esteja em uso linha 3, setamos na linha 5 o valor 1 do flag cimo 1 a fim de sinalizar o não uso de um recurso, caso o valor seja diferente de 1 então imprimimos na tela a mensagem de recurso ocupado que neste caso é um retorno de erro.
Enquanto este flag for 1, nenhum outro processo pode acessá-las, claro, existem as chamadas race-conditions, mas aqui estamos apenas demonstrando uma forma de checar o uso de um recurso em um ambiente multitarefa e que poderia com muita facilidade se transformar em algo caótico no meu ponto de vista como programador.