FrancisBFTC / KiddieOS_Development

O KiddieOS é um sistema operacional open-source básico em desenvolvimento pelo curso gratuito D.S.O.S [Desenvolvendo Sistemas Operacionais Simples]. A intenção deste sistema será: Criar, editar ou excluir arquivos, codificar em uma linguagem própria do sistema, criar objetos visuais e automatizados (desenhos) através desta linguagem, utilizar uma interface simples e intuitiva, criar novas interfaces gráficas, como: Janelas, botões, campos, etc... e estimular crianças, jovens e adultos a programar numa linguagem simples dentro do sistema operacional KiddieOS. A intenção do curso D.S.O.S é dá início ao desenvolvimento de sistemas operacionais utilizando a linguagem Assembly e entender a fundo sobre diversos conceitos internos deste tipo de sistema. Aqui neste repositório serão armazenados arquivos de APIs do KiddieOS, a imagem de disco para teste e futuramente - todo o sistema operacional completo. Visite o link abaixo para nos acompanhar no curso do Youtube, se inscreva neste canal para se manter atualizado e siga-me no GitHub. Vejo vocês lá:
MIT License
46 stars 5 forks source link

KiddieOS v1.3.8: Escrita, Renomeio e Atributo de Arquivos #8

Closed FrancisBFTC closed 7 months ago

FrancisBFTC commented 1 year ago

Funcionalidade/Alterações

Nesta versão, foi trabalhado algumas adaptações no comando Write de escrita/acréscimo de arquivos após adicionar novas funcionalidades no driver do FAT16, entre as funcionalidades temos a escrita de apenas entradas com atributos alterados, escrita de clusters e de dados de arquivos. Também foi implementado novos comandos: Como Attrib & Ren. Veja abaixo a descrição de cada comando e procedimentos:

Rotinas do Driver FAT16

Assim como na rotina de carregamento de arquivos LoadThisFile, uma busca inicial do arquivo deve ser feita antes de qualquer escrita ou leitura. Isto significa que é feita uma "cópia" da funcionalidade do LoadThisFile para procurar o arquivo para as rotinas WriteThisFile & WriteThisEntry, no entanto, quando elas encontram (ou não encontram) o arquivo, são executados novas rotinas diferentes.

Um exemplo é a rotina WriteThisFile que pode executar uma rotina mesmo se não encontrar o arquivo, que é o de criação de novos arquivos, deste modo, quando o arquivo é encontrado, uma rotina diferente é executada para realizar algumas configurações essenciais antes do "Acréscimo de dados" ou "Sobreescrita de Dados". Enquanto que na rotina WriteThisEntry, ela só executa uma nova rotina caso o arquivo é encontrado, caso não, ela finaliza a sua busca sem executar mais nada. O mesmo é feito na leitura de arquivos pelo LoadThisFile, porém com a diferença de que LoadThisFile contém tratamento de erros e retorno de código de erro.

Uma maneira comum de pensarmos o motivo desta busca ser quase a mesma do carregamento/leitura de arquivos, é pelo fato deste recurso se tratar do "Open" em operações de arquivos, ou seja, um arquivo primeiramente é aberto para depois efetuar alguma operação. A abertura de arquivo consiste exatamente nisso - buscar um arquivo no disco e caso encontrado, uma estrutura é criada para acessar o arquivo - isto significa que, a abertura de arquivos pode ser feita para o modo de escrita, leitura ou ambos. No entanto, atualmente a rotina de abertura de arquivos já é embutida em uma só chamada de operações de arquivos e ainda não pode criar a estrutura pois só retorna ao usuário após efetuar todas as operações. A rotina "OpenThisFile" será tratada futuramente de forma separada para gerenciamento por meio do usuário. Abaixo veremos a descrição das novas rotinas no qual esta busca executa:

A depender do que tiver em DX, um fluxo diferente é executado, como exemplo: Se DX for 0, significa que se trata do 1ª campo, que é o nome do arquivo, logo é feito uma cópia do nome apontado por BX para o campo em DI, mas se DX for 11, significa que é o campo do atributo, então é realizado uma cópia do atributo em bl para o campo em DI. Ambos como finalização, executará uma operação - SaveEntry. Esta label primeiro verifica se o segmento atual é o endereço inicial, caso for, concluímos que é o diretório raiz e como já conhecemos o setor lógico deste diretório, escrevemos setores lógicos do par apontado por ES:BX, a memória de diretório raiz. Porém, caso não for o endereço inicial, então é pesquisada a 1ª entrada do diretório "." que conterá o cluster inicial da pasta/diretório, onde este cluster será carregado em DX. Este fluxo de execução é determinado pelo endereço, porque sabemos que cada estrutura de diretório é carregado em um novo endereço.

A próxima operação é escrever a entrada apontada em memória para o disco, e para isto é necessário converter o cluster em DX para um LBA (Logic Block Address) que é o número de setor lógico e assim carregar no disco pelo par ES:BX. O endereço em BX é incrementado, e é calculado o próximo Cluster na cadeia, redefinindo o valor de DX para a próxima interação do loop converter para setor lógico, antes disso é verificado se o cluster é 0xFFFF, caso for, então o loop é finalizado e a entrada foi escrita, caso não for, o loop retorna ao início para escrita de setor lógico. Perceba que esta funcionalidade deve ser feita também para criação de arquivos, pois entradas de arquivos devem ser salvas antes de qualquer dado (As propriedades do arquivo). Então a próxima rotina veremos sobre criações de arquivos.

O que de fato acontece no Windows, por exemplo, ao editar arquivos existentes pelo FAT16 é zerar os clusters atuais porém escrever os mesmos (e novos) clusters em novas posições de memória, deixando o disco fragmentado, e como o FAT16 original não contém um sistema de desfragmentação de disco padrão, então cabe ao KiddieOS criar suas próprias alternativas. Outro fator é o tamanho de arquivos: O KiddieOS reaproveita os primeiros clusters zerados evitando fragmentação, porém quando é encontrado um cluster ocupado, mesmo que no meio do processo de leitura, o próximo cluster livre é utilizado, pois sabemos que a leitura/acesso do FAT é por meio do acesso encadeado, logo isto não interfere em questões de compatibilidade de leitura por sistemas modernos. Então para caso de arquivos maiores, o gerenciamento de espaço livre é feito, criando um encadeamento em posições distintas dos clusters, independente se o arquivo a ser editado for o primeiro e tiver dados maiores que o original, em casos de arquivos menores, os clusters que foram zerados pela rotina WriteFile são utilizados pelo CreateFile para novos arquivos, evitando desperdício.

Após a memória com dados definidos, a entrada é escrita no disco. Este processo de escrita da entrada no disco é o mesmo mencionado pelo 2ª parágrafo do item ChangeEntry - Se o segmento for o inicial, então é feito uma escrita estática do setor já conhecido (Diretório raiz), se não for inicial, então é buscado o cluster do diretório atual, convertido para setor lógico, escrito no disco e lido os próximos clusters na cadeia até que o último é encontrado. Após este procedimento, temos a escrita da entrada do arquivo (propriedades) no disco, o que poderia ser a área de dados, diferentemente de arquivos do diretório raiz, as entradas de arquivos dentro de pastas são armazenados na área de dados, pois pastas tecnicamente também são arquivos. Então a próxima fase é efetuar a escrita da tabela FAT da memória para o disco.

Através da rotina WriteFAT nós temos alguns cálculos fundamentais para determinar o setor inicial da tabela FAT onde a escrita irá começar, como também determinar a quantidade de setores do FAT que serão escritos. Também é calculado a partir da quantidade de dados do arquivo, a quantidade de setores de dados que serão escritos. Após isto, todos os clusters encadeados, baseados na quantidade de dados do arquivo e o gerenciamento de espaços livres (clusters vazios/zerados), são determinados e escritos na memória, antes mesmo de ir pro disco. Após isto terminamos a escrita do FAT para o disco, então o endereço correto de dados é calculado, para a próxima fase - a rotina WriteDataFile. A rotina de escrita de dados no disco, WriteDataFile, contém o mesmo procedimento da escrita de diretórios, realizando conversão de cluster físico para setor lógico, escrita do setor lógico a partir do endereço calculado ES:BX e leitura do próximo cluster na cadeia até encontrar o último, no entanto, os setores são da Área de Dados.

Todos estes procedimentos são realizados pelo Driver do FAT16. Nossos próximos passos é escrever campos de entradas relacionado com permissões, criando uma outra alternativa do FAT16 para gerenciamento de permissões de arquivos. Também utilizaremos as mesmas lógicas para criação do comando de Cópia de arquivos Copy, o comando de criação de pastas Mkdir, o comando de deleção de arquivos Del e o comando de atribuição de permissões Chmod.

TODO: Novos sistemas a ser implementados