A palestra que dei no Sétimo Encontro do Grupo de Usuários de C e C++ do Brasil apresentou meu resultado atual na pesquisa de um framework baseado em uma forma de orientação a aspectos em C++ descrita no "Modern C++ Design" do Alexandrescu.
Minha palestra não apresentou, porém, o que é exatamente o problema a resolver, assumindo que fosse razoavelmente conhecido. Seu foco foi apresentar todos os mecanismos disponíveis para se resolver o problema no Linux 2.6, suas peculiaridades e seus aspectos comuns.
Uma certa razão me motivou, após esta apresentação, a rebobinar meu raciocínio e considerar o problema original. [1] O que há exatamente de tão problemático na gestão de I/O em um programa?
A imagem inicial é a de um programa cujo objetivo é interagir com um dos dispositivos ligados ao computador. A forma básica dessa interação é a cópia de dados do dispositivo para a memória e da memória para o dispositivo, sendo que trabalho útil por parte do programa ocorre enquanto os dados estão na memória.
O trabalho de um tal programa pode, portanto, se manifestar por uma recorrente execução desta sequência exata: copiar do dispositivo para a memória, processar, copiar da memória para o dispositivo, reiniciar.
Agora, observamos um fato simples: enquanto o dispositivo copia, o processador está ocioso; enquanto o processador computa, o dispositivo está ocioso.
Esse fato pode ser um problema para você por duas razões altamente relacionadas: seu computador é tão caro que apenas se justifica quando trabalha a uma taxa máxima e sua fila de tarefas é tão grande que há uma tarefa que poderia processar ou copiar enquanto o processador ou o dispositivo estão ociosos.
Com o objetivo de solucionar esta questão, sistemas operacionais surgiram com a missão de coreografar tarefas de modo a obter a máxima utilização de todas as partes da máquina; i.e. levando uma tarefa ao processador e outra ao dispositivo simultaneamente, se possível.
Este sistema operacional não está conforme a nossa imagem inicial. Ele deve continuamente colocar e tirar tarefas do processador, colocar e tirar tarefas do dispositivo, em uma sequência complexa determinada por mutações indeterminadas em uma máquina de estados. Tais mutações são indeterminadas porque o sistema operacional não pode computar previamente por quanto tempo cada tarefa ocupará cada elemento. O sistema operacional deve agir e depois observar e esperar por alguma ocorrência significativa, então agir e voltar a observar e esperar. [2]
Esta é então nossa segunda imagem: a de um programa cujo objetivo é interagir com múltiplos dispositivos ligados ao computador. A forma básica dessa interação é a alternância entre um estado de paciência, enquanto se observa todos os dispositivos que se pressupõe estarem fazendo algo de útil, e um estado de atividade, iniciado por uma ocorrência significativa ao programa.
O trabalho de um tal programa pode, portanto, se manifestar por uma sequência que intercala atividade em cada um dos dispositivos, de modo que o programa se ocupa em fazer o que puder enquanto um dispositivo ou outro não demanda atenção.
Atividade, individualmente, será copiar ou processar; tomando uma execução do programa e evidenciando o que este programa faz com apenas um dispositivo, veremos a mesma sequência da imagem inicial arranjada no tempo na mesma ordem, separada por períodos em que o programa não se ocupou deste dispositivo.
Considerando com cuidado a imagem de um dispositivo podemos obter um conceito complexo e sofisticado. Um teclado e um monitor são dispositivos simples onde apenas se obtém ou enfia dados, e portanto a imagem desses dispositivos é simples. Uma controladora de vídeo com aceleração 3D é mais complexa, e possui evidentemente processador e memória próprios. Uma controladora de rede por si só não é um dispositivo complexo, mas a interação com ela é complexa, já que o recebimento de dados é algo totalmente imprevisível; além disso, a pilha de protocolos de rede que se constrói sobre ela possibilita o estabelecimento do que são efetivamente dispositivos virtuais, cujo exemplo contemporâneo obrigatório é a sessão TCP/IP.
Podemos nos convencer que a própria máquina é um dispositivo, e que um dispositivo é realmente uma máquina com processador e memória. O programa que dirige dispositivos se transforma em um elemento de um par que interage; o programa neste dispositivo e outro programa em outro dispositivo.
Um exemplo onde esta imagem ocorre claramente é o servidor típico da Internet: sua missão é coreografar atividade entre milhares de dispositivos virtuais TCP/IP onde o dispositivo é, exatamente, um outro programa que executa em uma outra máquina.
A presença de dados passíveis de serem obtidos, do ponto de vista de um dos programas, é determinada pelo fato de o outro programa ter enfiado algum dado do outro lado; estabelecem-se assim protocolos de comunicação que tornam possível a coreografia entre ambas as partes e a realização de trabalho útil.
Se um dos programas enfia dados na ligação virtual, esses dados ficarão em suspenso enquanto o outro programa não recuperá-los. Um tal dispositivo virtual, enquanto está ocioso, pode portanto está disponível ou indisponível. Considerando novamente as nossas exigências de desempenho, é imprescindível para o programa atuar rapidamente sobre o dispositivo quando ele estiver disponível, e é permitido ignorá-lo enquanto estiver indisponível.
Nossa imagem final é portanto a imagem de um programa operando milhares de dispositivos onde cada um desses dispositivos entende-se como sendo uma outra máquina executando um outro programa, potencialmente conforme a mesma imagem e também operando milhares de dispositivos.
Sua atividade envolve coreografar uma dança entre si mesmo e um outro programa de modo que ambos possam trocar dados: um copia para fora enquanto o outro copia para dentro. Além disso, sua atividade envolve agendar diversas danças entre si e todos os dipositivos: cuidando dos disponíveis e ignorando os indisponíveis.
Para atender a essa necessidade, o sistema operacional tem à disposição controladoras especiais na máquina, e o programa tem à disposição serviços especiais do sistema operacional.
[1] este problema está afirmado em todo bom material escolar sobre Sistemas Operacionais, como os do Tanembaum.
[2] o mecanismo básico da máquina que viabiliza esse comportamento é a controladora de interrupções.
Minha palestra não apresentou, porém, o que é exatamente o problema a resolver, assumindo que fosse razoavelmente conhecido. Seu foco foi apresentar todos os mecanismos disponíveis para se resolver o problema no Linux 2.6, suas peculiaridades e seus aspectos comuns.
Uma certa razão me motivou, após esta apresentação, a rebobinar meu raciocínio e considerar o problema original. [1] O que há exatamente de tão problemático na gestão de I/O em um programa?
A imagem inicial é a de um programa cujo objetivo é interagir com um dos dispositivos ligados ao computador. A forma básica dessa interação é a cópia de dados do dispositivo para a memória e da memória para o dispositivo, sendo que trabalho útil por parte do programa ocorre enquanto os dados estão na memória.
O trabalho de um tal programa pode, portanto, se manifestar por uma recorrente execução desta sequência exata: copiar do dispositivo para a memória, processar, copiar da memória para o dispositivo, reiniciar.
Agora, observamos um fato simples: enquanto o dispositivo copia, o processador está ocioso; enquanto o processador computa, o dispositivo está ocioso.
Esse fato pode ser um problema para você por duas razões altamente relacionadas: seu computador é tão caro que apenas se justifica quando trabalha a uma taxa máxima e sua fila de tarefas é tão grande que há uma tarefa que poderia processar ou copiar enquanto o processador ou o dispositivo estão ociosos.
Com o objetivo de solucionar esta questão, sistemas operacionais surgiram com a missão de coreografar tarefas de modo a obter a máxima utilização de todas as partes da máquina; i.e. levando uma tarefa ao processador e outra ao dispositivo simultaneamente, se possível.
Este sistema operacional não está conforme a nossa imagem inicial. Ele deve continuamente colocar e tirar tarefas do processador, colocar e tirar tarefas do dispositivo, em uma sequência complexa determinada por mutações indeterminadas em uma máquina de estados. Tais mutações são indeterminadas porque o sistema operacional não pode computar previamente por quanto tempo cada tarefa ocupará cada elemento. O sistema operacional deve agir e depois observar e esperar por alguma ocorrência significativa, então agir e voltar a observar e esperar. [2]
Esta é então nossa segunda imagem: a de um programa cujo objetivo é interagir com múltiplos dispositivos ligados ao computador. A forma básica dessa interação é a alternância entre um estado de paciência, enquanto se observa todos os dispositivos que se pressupõe estarem fazendo algo de útil, e um estado de atividade, iniciado por uma ocorrência significativa ao programa.
O trabalho de um tal programa pode, portanto, se manifestar por uma sequência que intercala atividade em cada um dos dispositivos, de modo que o programa se ocupa em fazer o que puder enquanto um dispositivo ou outro não demanda atenção.
Atividade, individualmente, será copiar ou processar; tomando uma execução do programa e evidenciando o que este programa faz com apenas um dispositivo, veremos a mesma sequência da imagem inicial arranjada no tempo na mesma ordem, separada por períodos em que o programa não se ocupou deste dispositivo.
Considerando com cuidado a imagem de um dispositivo podemos obter um conceito complexo e sofisticado. Um teclado e um monitor são dispositivos simples onde apenas se obtém ou enfia dados, e portanto a imagem desses dispositivos é simples. Uma controladora de vídeo com aceleração 3D é mais complexa, e possui evidentemente processador e memória próprios. Uma controladora de rede por si só não é um dispositivo complexo, mas a interação com ela é complexa, já que o recebimento de dados é algo totalmente imprevisível; além disso, a pilha de protocolos de rede que se constrói sobre ela possibilita o estabelecimento do que são efetivamente dispositivos virtuais, cujo exemplo contemporâneo obrigatório é a sessão TCP/IP.
Podemos nos convencer que a própria máquina é um dispositivo, e que um dispositivo é realmente uma máquina com processador e memória. O programa que dirige dispositivos se transforma em um elemento de um par que interage; o programa neste dispositivo e outro programa em outro dispositivo.
Um exemplo onde esta imagem ocorre claramente é o servidor típico da Internet: sua missão é coreografar atividade entre milhares de dispositivos virtuais TCP/IP onde o dispositivo é, exatamente, um outro programa que executa em uma outra máquina.
A presença de dados passíveis de serem obtidos, do ponto de vista de um dos programas, é determinada pelo fato de o outro programa ter enfiado algum dado do outro lado; estabelecem-se assim protocolos de comunicação que tornam possível a coreografia entre ambas as partes e a realização de trabalho útil.
Se um dos programas enfia dados na ligação virtual, esses dados ficarão em suspenso enquanto o outro programa não recuperá-los. Um tal dispositivo virtual, enquanto está ocioso, pode portanto está disponível ou indisponível. Considerando novamente as nossas exigências de desempenho, é imprescindível para o programa atuar rapidamente sobre o dispositivo quando ele estiver disponível, e é permitido ignorá-lo enquanto estiver indisponível.
Nossa imagem final é portanto a imagem de um programa operando milhares de dispositivos onde cada um desses dispositivos entende-se como sendo uma outra máquina executando um outro programa, potencialmente conforme a mesma imagem e também operando milhares de dispositivos.
Sua atividade envolve coreografar uma dança entre si mesmo e um outro programa de modo que ambos possam trocar dados: um copia para fora enquanto o outro copia para dentro. Além disso, sua atividade envolve agendar diversas danças entre si e todos os dipositivos: cuidando dos disponíveis e ignorando os indisponíveis.
Para atender a essa necessidade, o sistema operacional tem à disposição controladoras especiais na máquina, e o programa tem à disposição serviços especiais do sistema operacional.
[1] este problema está afirmado em todo bom material escolar sobre Sistemas Operacionais, como os do Tanembaum.
[2] o mecanismo básico da máquina que viabiliza esse comportamento é a controladora de interrupções.
Comentários
Postar um comentário