Resposta esperada: No modo kernel é possível o acesso irrestrito ao conjunto de instruções da máquina. Um processo deixa de executar em modo usuário e passa a executar em modo kernel quando executa uma chamada de sistema.
Observações: Não bastava dizer que o modo kernel tem acesso irrestrito aos dados do sistema operacional. Para passar do modo usuário ao modo kernel, não é suficiente que um processo precise ou queira fazer acesso priveligiado ao hardware. É necessário que ele execute uma chamada de sistema.
#includeint v1[10]; void f() { int i; for (i = 0; i < 100; i++) v1[i] = i; } void g() { int v2[10]; int i; for (i = 0; i < 100; i++) v2[i] = i; } int main() { if (rand() % 2) f(); else g(); return 0; }
Resposta esperada: O acesso à posição v[11] está fora da área reservada para este vetor, podendo causar uma falha de segmentação (SEGMENTATION FAULT). O programa terminaria corretamente caso as posições v[11] a v[99] estivessem dentro do segmento de dados.
Resposta esperada: Após o acesso às posições mais altas do vetor, a pilha de execução, que contém o endereço de retorno da função, será corrompida. Desta forma, não há possibilidade do programa terminar corretamente.
Observações: Para responder esta questão, você deveria ter em mente o seguinte esquema para o espaço de endereçamento virtual do processo:
+-------------+ | Pilha | || | | \/ +-------------+ | Gap | | | +-------------+ | | | Dados | +-------------+ | Texto | +-------------+Note que o Gap é um espaço de endereçamento virtual não mapeado. Alguns alunos erraram ao dizer que o acesso a v1[99] poderia corromper memória de outros processos.
/* Tratador invocado quando um sinal tipo SIGUSR1 é recebido */ void trata_SIGUSR1(int signum) { pthread_mutex_lock(&mutex); /* Acesso a dados */ pthread_mutex_unlock(&mutex); } /* Função do programa */ void f() { pthread_mutex_lock(&mutex); /* Acesso a dados */ pthread_mutex_unlock(&mutex); }Resposta esperada: O tratador do sinal SIGUSR1 pode ser invocado dentro da região crítica da função f(). Neste caso, o programa entraria em deadlock.
Observações: O que ocorre é que o mesmo fluxo de execução é interrompido para a execução do tratador. Alguns alunos justificaram erros considerando vários fluxos de execução, inclusive de outros processos, o que não faz sentido, pois estes não teriam acesso ao mutex.
Resposta esperada: Sim, é possível criar um link simbólico para um arquivo que não existe, visto que este link é apenas um caminho, válido ou não, para outro arquivo.
Um hard link é uma referência para um i-node e não é possível criar uma referência para um i-node inválido.
Observações: Todas as referências para i-nodes no sistema são hard links. Desta forma, ao criarmos um arquivo, criamos o primeiro hard link para ele.
Resposta esperada: Na lista ligada, parte dos blocos de dados é utilizada para armazenar os apontadores, enquanto que com o uso da FAT os blocos dos arquivos são ocupados integralmente com dados.
Com a FAT, para se fazer acesso a um bloco específico de um arquivo, basta percorrer a lista em memória, que é mais rápido do que percorrer a lista no disco.
Observações: Muitos alunos responderam que a FAT permitia acesso direto aos blocos no disco, mas, em ambos os casos é necessário percorrer a lista.
Na FAT, a identificação de blocos livres também pode ser mais simples, pois basta percorrer a tabela e procurar por blocos que estejam marcados como livres.
Resposta esperada: Com o uso de i-nodes, não é necessário colocar informações sobre o disco como um todo na memória. Apenas quando um arquivo é aberto, é feita a leitura dos blocos que o compõem.
O acesso a um bloco específico de um arquivo é mais eficiente com o uso de i-nodes, pois não é necessário percorrer uma lista (no caso dos primeiros blocos, o acesso é direto e nos demais, pode-se ter de percorrer uma árvore de poucos níveis).
Observações: Para obter os pontos referentes a esta questão era importante fazer uma comparação entre os dois modelos; não bastava comentar características dos i-nodes.
Resposta esperada: Atribuindo funções específicas para as operações de escrita e leitura em um arquivo de um dado sistema de arquivos, é possível adicionar novas funcionalidades ao kernel ou modificar outras já existentes. Isto é mais vantajoso do que especificar uma nova chamada por razões de compatibilidade entre várias versões do sistema.
Observações: Alguns alunos falaram da possibilidade de se implementar otimizações em sistemas de arquivos via implementações específicas, o que não era o foco da questão.
No trabalho 2 do Linux, foi solicitada a implementação de chamadas modificadas de clone e fork via sistema de arquivos.
Resposta esperada: A principal vantagem é que a comunicação pode ser feita em memória, sem ser necessária a criação de um arquivo em disco. Além disso, o processo leitor do pipe (consumidor) poderá iniciar o seu processamento antes do escritor no pipe (produtor) terminar sua execução, sendo que a sincronização será feita automaticamente pelo sistema.