Onde há um sistema operacional envolvido, os programas não falam com os drivers de dispositivo, pelo menos não diretamente. Os programas conversam com abstrações que, sem o conhecimento delas, acabam conversando com os drivers de dispositivo por meio de uma ou mais camadas de abstração.
Vou pular as complexidades dos sistemas operacionais modernos e usar o CP / M , um sistema operacional de microcomputador desenvolvido 45 anos atrás, como exemplo. CP / M foi um bolo de camadas com três camadas:
Programa. A camada superior é um programa que faz algo útil (processamento de texto, reprodução de Space Invaders) fazendo cálculos e E / S. Digamos que em algum momento o programa queira exibir a letra 'A' para o usuário ver. O CP / M fornece uma abstração conhecida como console , que é onde o usuário que interage com o programa deve procurar. A maneira convencional de enviar um personagem é com algumas instruções de montagem:
LD C,2 ; Load 2 into register C
LD E,65 ; Load the ASCII code for 'A' into register E
CALL 5 ; Call CP/M's routine for getting things done
(Se você não estiver familiarizado com eles, os registradores podem ser considerados variáveis que vivem no processador.) Vamos ver quais são os números mágicos 2e 5tudo sobre isso em um minuto. O ponto principal aqui é que tudo o que o programa sabe é que há um console e há uma maneira de escrever nele. Não sabe nem se importa com nada além disso. Essa é a primeira de duas abstrações que o CP / M usa para E / S.
BDOS . O endereço 5chamado pelo programa é o ponto de entrada para a próxima camada, o Sistema operacional de disco básico ou BDOS . O BDOS fornece uma série de funções numeradas que são como ordenar por número em um menu de restaurante. Você diz que deseja saída do console carregando o Cregistro com o número da função ( 2para saída do console) e o Eregistro com o caractere a ser enviado. A saída do console é uma operação muito simples, e o BDOS realmente não tem muito a ver com isso, a não ser chamar a próxima camada.
BIOS. O BIOS, ou sistema básico de entrada / saída, é a camada em que vive todo o código específico de hardware. Nos sistemas modernos, isso seria considerado um conjunto de drivers de dispositivo. Como o BDOS, o BIOS fornece chamadas para um conjunto padrão de operações muito primitivas que o BDOS usa para fazer seus negócios. Uma dessas operações é chamadaCONOUT, que cuida da obtenção do caractere que o programa solicitou para escrever duas camadas acima através de qualquer hardware que o faça. (Diferentemente dos PCs, as coisas não eram homogêneas naquela época. Todo mundo tinha maneiras diferentes de fazer isso acontecer.) A saída do console é uma passagem simples para o BDOS, mas fazer algo mais complexo como criar um arquivo em um disco pode exigir muitos Chamadas do BIOS para manipular a mídia. Novamente, como o BIOS possui uma interface abstrata padrão, o BDOS sempre sabe como obter o que deseja e não se importa com o que o BIOS faz.
Você provavelmente está se perguntando por que existem duas abstrações (programa para BDOS e BDOS para BIOS) em vez de apenas uma. A resposta é que o CP / M e seu BDOS podem ser fornecidos em formato binário aos fabricantes de computadores, eles escrevem um BIOS personalizado com drivers de dispositivo para o hardware, prendem os dois juntos e o enviam como sistema operacional para seus sistemas. Isso foi muito importante porque o BDOS foi mantido por uma organização e, portanto, sempre foi uma quantidade conhecida para os programas do usuário, possibilitando a execução dos mesmos aplicativos em uma variedade muito ampla (para a época) de hardware. É por isso que os sistemas operacionais existem e não apenas escrevemos programas que modificam o hardware diretamente .
Tudo o que descrevi aqui também se aplica aos sistemas operacionais modernos. O Unix, por exemplo, abstrai tudo como arquivos. Dá programas do mesmo conjunto de chamadas de sistema ( open(), write(), close(), etc.) para comunicar quer se trate de uma unidade de disco ou porta serial. O conjunto de decisões e abstrações é muito mais complexo, mas ainda se resume a escolher qual código de driver de dispositivo na camada inferior precisa ser executado para que a operação aconteça.