# Exercícios MT1

Questões de exames antigos de Laboratório de Computadores, com resolução.

Página: https://resumos.rgo.pt/cadeiras/lc/exercicios-mt1/

## Hardware e I/O

Função principal dos dispositivos de I/O

Teste 1, 2024/25

Qual é a função principal dos dispositivos de entrada/saída (I/O) num sistema de computador?

Solução

Fornecer uma interface entre o computador e o seu ambiente exterior.

Os dispositivos de I/O são a ponte entre o sistema computacional e o utilizador ou outros sistemas, convertendo informação entre o mundo exterior e a representação interna do computador.

*   **Fornecer uma interface entre o computador e o seu ambiente..** Os periféricos de I/O ligam o processador ao mundo exterior: teclado, rato, ecrã, etc.
*   **Executar programas de software..** Quem executa programas é o CPU, não o dispositivo de I/O.
*   **Aumentar a velocidade de processamento do CPU..** A velocidade do CPU não depende dos periféricos de I/O.
*   **Armazenar dados de forma permanente..** O armazenamento permanente é papel da memória secundária, não da interface de I/O.

[Voltar à explicação](https://resumos.rgo.pt/cadeiras/lc/falar-com-hardware/#registos-e-espa%C3%A7os-de-endere%C3%A7amento)

O que é um device driver

Teste 1, 2024/25

O que é um device driver?

Solução

É um software que permite a interação com um componente de hardware.

O device driver esconde os detalhes do dispositivo atrás de uma interface uniforme e faz as operações privilegiadas (portas de I/O, interrupções) através de chamadas ao kernel.

*   **É um software que permite a interação com um componente de hardware..** O driver traduz pedidos do sistema operativo em operações sobre o dispositivo.
*   **É um componente de hardware de um dispositivo externo que recebe pedidos do processador..** O driver é software, não um componente de hardware.
*   **É uma classe de software específica para configurar o temporizador do processador..** O driver não se limita ao temporizador nem ao processador.
*   **É um componente de software que permite interagir diretamente com o hardware sem o sistema operativo..** Em Minix, o driver corre como processo e usa chamadas ao kernel; não dispensa o sistema operativo.

[Voltar à explicação](https://resumos.rgo.pt/cadeiras/lc/falar-com-hardware/#registos-e-espa%C3%A7os-de-endere%C3%A7amento)

Polling vs interrupções: chamadas ao kernel

Teste 1, 2024/25

Para ler scancodes do teclado pode escolher-se polling ou interrupções. Qual das duas alternativas espera que faça menos chamadas `sys_inb()` ao kernel?

Solução

Interrupções.

Em polling, o programa verifica o estado do dispositivo em ciclo, gastando uma chamada `sys_inb()` por consulta. Com interrupções, cada chamada ao kernel corresponde a um evento real, pelo que o número de chamadas é menor.

*   **Interrupções..** Com interrupções, o kernel só é chamado quando há um evento novo; em polling consulta-se o estado repetidamente.
*   **Polling..** Em polling é preciso consultar o registo de estado muitas vezes, mesmo sem teclas premidas.
*   **O número de chamadas é aleatório..** O número de chamadas não é aleatório; depende do mecanismo escolhido.
*   **Fazem sempre o mesmo número de chamadas..** Polling e interrupções não fazem o mesmo número de chamadas.

[Voltar à explicação](https://resumos.rgo.pt/cadeiras/lc/falar-com-hardware/#polling-e-timeout)

## Teclado

Combinação make code e break code válida

Teste 1, 2024/25

No protocolo PS/2 (set 1), o break code de uma tecla obtém-se poniendo o bit 7 do make code a 1. Qual é uma combinação make code / break code válida?

Solução

Make code `0x1E` e break code `0x9E`.

No set 1, o break code distingue-se do make code apenas no bit 7: `0x1E = 0001 1110` e `0x9E = 1001 1110 = 0x1E | 0x80`.

*   **Make code: `0xC2`, break code: `0xCA`.** `0xC2` já tem o bit 7 a 1; o break code não pode resultar dele.
*   **Make code: `0x9E`, break code: `0x1E`.** O break code tem sempre o bit 7 a 1, ao contrário do make code.
*   **Make code: `0x1E`, break code: `0x9E`.** `0x9E = 0x1E | 0x80`, ou seja, o bit 7 foi posto a 1.
*   **Make code: `0xCA`, break code: `0xC2`.** `0xCA` já tem o bit 7 a 1; o break code não pode resultar dele.

[Voltar à explicação](https://resumos.rgo.pt/cadeiras/lc/teclado/#make-break-e-prefixos)

Porque é que alguns scancodes têm dois bytes

Teste 1, 2024/25

No KBC, porque é que há scancodes com dois bytes?

Solução

Porque não era possível representar todo o conjunto de scancodes num só byte.

As teclas estendidas usam o prefixo `0xE0` seguido do código, como a seta direita (`E0 4D` no make). Com um só byte ficariam indisponíveis muitos códigos.

*   **Por retrocompatibilidade..** A retrocompatibilidade explica a conservação do set 1, não o facto de alguns scancodes usarem dois bytes.
*   **Porque não era possível representar todo o conjunto de scancodes num só byte..** Um byte só dá 256 códigos; o prefixo `0xE0` duplica o espaço disponível para teclas estendidas.
*   **Para permitir mapear os scancodes para diferentes idiomas de teclado..** O idioma do teclado é interpretado em software, não pelo número de bytes do scancode.
*   **Para mapear diretamente para ASCII..** Scancode não é ASCII; a tecla `0x1E` não produz o caráter `a` sem interpretação do layout.

[Voltar à explicação](https://resumos.rgo.pt/cadeiras/lc/teclado/#make-break-e-prefixos)

Função do registo de estado do KBC

Teste 1, 2024/25

Qual é o objetivo principal do registo de estado (status register) do KBC?

Solução

Guardar o estado do KBC.

O registo de estado (lido na porta `0x64`) tem bits como OBF (output buffer full) e IBF (input buffer full), que o programa testa antes de ler scancodes ou escrever comandos.

*   **Guardar o último caráter digitado dentro do KBC..** O caráter lido está no output buffer, não no registo de estado.
*   **Mostrar no ecrã o que se digita no teclado..** O KBC não gere o ecrã; isso é papel da placa de vídeo.
*   **Guardar o estado do KBC..** Bits como OBF e IBF indicam se há byte novo para ler ou se se pode escrever uma ordem.
*   **Guardar palavras-passe do utilizador..** O KBC não guarda palavras-passe.

[Voltar à explicação](https://resumos.rgo.pt/cadeiras/lc/teclado/#estado-do-i8042)

## Temporizador

Fórmula do divisor de frequência do timer

Teste 1, 2024/25

Na função `timer_set_frequency`, é necessário um divisor de frequência `d`. Qual fórmula exprime corretamente o seu cálculo? Neste contexto, `freq` é a frequência desejada, `TIMER_FREQ` é a frequência do relógio do timer no PC e `USHRT_MAX` é o valor máximo do contador.

Solução

`d = TIMER_FREQ / freq`.

O contador divide o relógio de entrada: para obter `freq` Hz a partir de `TIMER_FREQ` Hz, carrega-se `d = TIMER_FREQ / freq` (com a política de quociente inteiro usada no laboratório).

*   **`d = TIMER_FREQ / freq`.** A frequência de saída é a de entrada dividida pelo divisor: `freq = TIMER_FREQ / d`.
*   **`d = TIMER_FREQ / USHRT_MAX * freq`.** Esta expressão mistura o valor máximo do contador com a frequência desejada.
*   **`d = TIMER_FREQ * freq`.** Multiplicar as frequências não produz um divisor de contagem.
*   **`d = freq / USHRT_MAX`.** O divisor não depende da razão entre a frequência desejada e o valor máximo.

[Voltar à explicação](https://resumos.rgo.pt/cadeiras/lc/temporizador/#escolher-a-frequ%C3%AAncia)

Função do registo de controlo na porta 0x43

Teste 1, 2024/25

Qual é a função do registo de controlo na porta `0x43` do i8254?

Solução

Programa os timers e seleciona os modos de contagem.

A porta `0x43` recebe a palavra de controlo do i8254, que configura cada contador de 16 bits (portas `0x40` a `0x42`).

*   **Guarda a hora atual..** A hora é dada pelo relógio de tempo real, não pelo i8254.
*   **Controla a transferência de dados entre o CPU e a memória..** Isso é papel do controlador de memória/DMA, não do timer.
*   **Guarda definições de configuração do utilizador..** O registo de controlo programa o próprio contador, não preferências do utilizador.
*   **Programa os timers e seleciona os modos de contagem..** A palavra de controlo escolhe o contador, a ordem de bytes (LSB/MSB), o modo e o formato binário/BCD.

[Voltar à explicação](https://resumos.rgo.pt/cadeiras/lc/temporizador/#palavra-de-controlo)

O que permite o comando read-back do i8254

Teste 1, 2024/25

O que permite o comando read-back do i8254?

Solução

Ler o valor atual do contador e a configuração programada.

Sem o read-back, a porta de um contador só daria a contagem de forma pouco fiável; o comando permite ainda ler o estado (modo, formato) de um contador.

*   **Aumentar a velocidade de processamento do timer..** O read-back não altera a velocidade do relógio.
*   **Alterar o vetor de interrupção..** O vetor de interrupção é gerido pelo PIC, não pelo read-back.
*   **Ler o valor atual do contador e a configuração programada..** O comando read-back (escrito em `0x43` com os bits 7–6 a `11`) permite obter a contagem e/ou o estado do contador.
*   **Repor o timer nas definições de fábrica..** O read-back é apenas de leitura; não repõe nada.

[Voltar à explicação](https://resumos.rgo.pt/cadeiras/lc/temporizador/#read-back-e-estado)

Como se mediu o tempo no Lab 2

Teste 1, 2024/25

No Lab 2, como foi medido o tempo e impressa uma mensagem a cada segundo?

Solução

Subscrivendo as interrupções do timer com a definição de 60 Hz do Minix.

O Lab 2 configurava o contador 0 para gerar interrupções e o handler incrementava um contador de ticks; a cada 60 ticks (1 segundo a 60 Hz) se imprimia a mensagem.

*   **Usando o comando read-back a cada segundo..** O read-back lê o contador, mas não foi esse o mecanismo de temporização do Lab 2.
*   **Subscrivendo as interrupções do timer com a definição de 60 Hz do Minix..** O ciclo de eventos recebia notificações do timer (60 Hz) e contava ticks até perfazer um segundo.
*   **Configurando o timer com uma frequência de 120 Hz..** O Lab 2 usou a frequência de 60 Hz habitual do Minix, não 120 Hz.
*   **Subscrivendo as interrupções do timer com a definição de 120 Hz do Minix..** A definição usada foi a de 60 Hz, não 120 Hz.

[Voltar à explicação](https://resumos.rgo.pt/cadeiras/lc/interrupcoes/#ciclo-completo-com-timer)

## Interrupções

Comportamento de driver\_receive no Minix

Teste 1, 2024/25

Qual é o comportamento da chamada `driver_receive` no Minix?

Solução

Bloqueia até receber uma mensagem de pedido de serviço, permitindo comutação de contexto.

O ciclo de eventos do Lab 2 chama `driver_receive(ANY, &msg, &ipc_status)` e fica bloqueado até o kernel lhe entregar uma mensagem, incluindo as notificações de interrupção de hardware.

*   **Bloqueia até receber uma interrupção de software, permitindo comutação de contexto..** A `driver_receive` não espera por uma interrupção de software; espera por uma mensagem (que pode ser uma notificação de hardware).
*   **Dá erro se não houver notificações pendentes para o processo chamador..** Não dá erro; bloqueia à espera de mensagem.
*   **Faz polling do PIC à procura de interrupções dos periféricos relevantes..** Quem trata do PIC é o kernel, não a aplicação.
*   **Bloqueia até receber uma mensagem de pedido de serviço, permitindo comutação de contexto..** Enquanto não chega mensagem, o processo fica bloqueado e o CPU pode correr outro processo.

[Voltar à explicação](https://resumos.rgo.pt/cadeiras/lc/interrupcoes/#ciclo-completo-com-timer)

Valor de hook\_id para receber o bit 7 na notificação

Teste 1, 2024/25

Um device driver quer subscrever interrupções do timer para ser notificado pelo kernel com um payload em que o bit 7 está a 1. Que valor deve passar no argumento `hook_id` da função `sys_irqsetpolicy`?

Solução

`hook_id = 7`.

Guarda-se o número do bit antes da chamada: a máscara a testar na notificação é `1 << hook_id`, ou seja `BIT(7) = 0x80`. Passar o próprio `BIT(7)` como hook pediria o bit 128, que não existe no campo de notificações.

*   **`BIT(7)`.** `BIT(7)` vale 128 e seria a máscara a testar na notificação, não o valor do hook; como hook pediria um bit que não existe no campo de notificações.
*   **`0`.** Com `hook_id = 0`, o kernel poria a 1 o bit 0 da notificação, não o bit 7.
*   **`7`.** O `hook_id` é o número do bit: o kernel coloca a 1 esse bit no payload, e a máscara a testar na aplicação é `BIT(7) = 0x80`.
*   **`1`.** Com `hook_id = 1`, a notificação teria o bit 1 a 1.

[Voltar à explicação](https://resumos.rgo.pt/cadeiras/lc/interrupcoes/#hook-e-m%C3%A1scara-de-notifica%C3%A7%C3%A3o)

O que faz a política IRQ\_REENABLE

Teste 1, 2024/25

O que faz a flag `IRQ_REENABLE` no contexto das subscrições de notificações de interrupção no Minix?

Solução

Faz com que o kernel desmascare automaticamente as interrupções na linha IRQ associada ao `hook_id` indicado.

A `IRQ_REENABLE` autoriza a rotina genérica a reativar a linha de IRQ depois de cada interrupção, para que as seguintes possam chegar sem a aplicação ter de chamar `sys_irqenable`.

*   **Permite remover mais tarde a respetiva subscrição..** A remoção faz-se com `sys_irqrmpolicy`, independentemente desta flag.
*   **Aumenta a prioridade do handler instalado, impedindo o kernel de o tratar primeiro..** A política não altera prioridades de atendimento.
*   **Permite que o driver de dispositivo do próprio Minix trate das interrupções da respetiva linha IRQ depois de a subscrição ser removida..** A reativação automática da linha é o efeito da flag, não a devolução ao driver do sistema.
*   **Faz com que o kernel desmascare automaticamente as interrupções na linha IRQ associada ao `hook_id` indicado..** Sem esta política, o processo teria de chamar `sys_irqenable` quando ficasse pronto; com ela, a rotina genérica do kernel reativa a linha.

[Voltar à explicação](https://resumos.rgo.pt/cadeiras/lc/interrupcoes/#hook-e-m%C3%A1scara-de-notifica%C3%A7%C3%A3o)

Papel do PIC no mecanismo de interrupções

Teste 1, 2024/25

De que é responsável o PIC (Priority Interrupt Controller)?

Solução

Avisar o CPU de uma nova interrupção.

O PIC i8259 regista os pedidos de interrupção, aplica as máscaras e apresenta ao processador o pedido prioritário, que o CPU atende com o vetor associado.

*   **Avisar o CPU de uma nova interrupção..** O periférico pede IRQ ao PIC, o PIC escolhe o pedido a apresentar e sinaliza o processador com o vetor correspondente.
*   **Avisar o dispositivo de I/O das interrupções pela ordem correta..** O PIC comunica com o CPU, não com os dispositivos.
*   **Executar o handler respetivo de cada interrupção..** Quem executa o handler é o CPU, depois de o kernel despachar a notificação.
*   **Avisar o CPU de que o handler terminou..** O fim do atendimento é sinalizado com EOI, tratado pelo kernel.

[Voltar à explicação](https://resumos.rgo.pt/cadeiras/lc/interrupcoes/#irq-vetor-e-rotina)

## C e chamadas ao sistema

Semântica dos valores de retorno das chamadas POSIX

Teste 1, 2024/25

Nas chamadas ao sistema POSIX, qual é a semântica habitual dos valores de retorno?

Solução

`0` indica sucesso e os outros valores erro.

As chamadas ao sistema POSIX (e as do kernel do Minix usadas em LC) devolvem `0` quando a operação foi bem-sucedida e um código de erro diferente de zero quando falhou.

*   **`1` indica sucesso e os outros valores erro..** Não é `1` que indica sucesso nas chamadas POSIX.
*   **`0` indica erro e os outros valores sucesso..** É ao contrário: `0` é o valor de sucesso.
*   **`1` indica erro e os outros valores sucesso..** Nenhum valor positivo indica erro por convenção geral.
*   **`0` indica sucesso e os outros valores erro..** É a convenção habitual, também usada nas chamadas do Minix como `sys_inb` e `sys_irqsetpolicy`.

[Voltar à explicação](https://resumos.rgo.pt/cadeiras/lc/falar-com-hardware/#privil%C3%A9gios-e-minix)

Resultado da operação bit a bit 12 & 10

Teste 1, 2024/25

Qual é o resultado da expressão em C `(12 & 10)`?

Solução

`8`.

O operador `&` atua bit a bit: `12 = 1100b`, `10 = 1010b`, logo `12 & 10 = 1000b = 8`.

*   **`8`.** `12 = 1100b` e `10 = 1010b`; `1100 & 1010 = 1000 = 8`.
*   **`12`.** O resultado não é o primeiro operando.
*   **`2`.** `2 = 0010b` seria o resultado de `12 & 10` se só o bit 1 contasse, mas o bit 3 também é comum.
*   **`10`.** O resultado não é o segundo operando.

[Voltar à explicação](https://resumos.rgo.pt/cadeiras/lc/c-estruturado/#promo%C3%A7%C3%B5es-e-convers%C3%B5es-de-inteiros)

## O dispositivo L3223 (PP1)

Palavra de controlo do L3223: timer 1, alarme em milissegundos

PP1, 2020

No dispositivo fictício L3223 do PP1 de 2020, a escrita no porto `0x23` acede ao registo de controlo, cujos bits relevantes são: bits 7–6 selecionam o timer (`00`, `01`, `10` para os timers 0, 1, 2), o bit 4 seleciona o modo (`0` periódico, `1` alarme) e os bits 1–0 selecionam a unidade de tempo (`00` microssegundos, `01` milissegundos, `10` segundos). Indique a palavra de controlo, em hexadecimal, para configurar o timer 1 em modo alarme com unidade de milissegundos.

Solução

A palavra de controlo é `0x51`.

Timer 1 dá `01` nos bits 7–6 (`0x40`), o modo alarme liga o bit 4 (`0x10`) e milissegundos são `01` nos bits 1–0 (`0x01`). Somando: `0x40 | 0x10 | 0x01 = 0x51`. Depois de escrever a palavra de controlo em `0x23`, carrega-se o intervalo no porto do timer (`0x21`), primeiro o LSB e depois o MSB.

Confere a tua resposta:

*   A resposta indica a palavra de controlo `0x51` (binário `01010001`).
*   A justificação separa os campos: bits 7–6 = `01`, bit 4 = `1`, bits 1–0 = `01`.

Bit do registo de estado do L3223 para o timer 2

PP1, 2020

No L3223, a leitura do porto `0x23` acede ao registo de estado, em que o bit 2 (TIMER2-INT), o bit 1 (TIMER1-INT) e o bit 0 (TIMER0-INT) indicam, com valor 1, uma interrupção pendente do respetivo timer. Num atendimento de interrupção, para detetar o alarme do timer 2, que bit do registo de estado deve ser testado e com que valor?

Solução

Testa-se o bit 2 (TIMER2-INT) e o valor esperado é 1.

Cada timer tem o seu bit no registo de estado: o timer 0 usa o bit 0, o timer 1 o bit 1 e o timer 2 o bit 2. No handler lê-se `0x23` com `sys_inb` e verifica-se `(estado & TIMER2_INT) != 0` quando se espera o alarme do timer 2.

Confere a tua resposta:

*   A resposta indica que se testa o bit 2 (TIMER2-INT).
*   A resposta indica que o valor esperado é 1.
