Sistemas Operacionais e Introdução a Programação (diário 2010-1) - Prof. Ederson Torresini
Revisão de 20h44min de 13 de março de 2010 por Etorresini (discussão | contribs) (→11/03: Controle de acesso e usuários)
- Endereço encurtado: http://bit.ly/sop20101
- Diário de acordo com o plano de ensino.
Sistemas Operacionais
18/02: Apresentação da disciplina
- Tópicos: plano de ensino, abordagem pedagógica.
24/02: História dos Sistemas Operacionais e das Linguagens de Programação
- Tópicos: história, evolução dos sistemas operacionais e das linguagens de programação.
- Referências externas:
25/02: Arquitetura de Sistemas Computacionais
- As linguagens de programação, sistemas operacionais e protocolos em rede mais comuns (C, UNIX e TCP/IP) existem desde os anos 1970. Àquela época, era comum organizar a informação em estruturas de dados simples: fila e árvore.
- Sistemas Operacionais modernos são desenvolvidos em linguagens de programação de alto nível (na maior parte do seu código). Esses sistemas transmitem e recebem dados através das redes de computadores.
<graphviz> digraph Triade { "Linguagens de Programação" -> "Sistemas Operacionais" "Sistemas Operacionais" -> "Redes de Computadores" "Linguagens de Programação" -> "Redes de Computadores" } </graphviz>
- Multiusuário, multiprocesso e multidados: usuários utilizam processos para manipular dados. Toda ação e arquivo deve possuir, portanto, um responsável ou dono para garantir o devido controle de acesso.
<graphviz> digraph SO { Usuários -> Kernel [label=1] Kernel -> Processos [label=2] Processos -> Kernel [label=3] Kernel -> Dados [label=4] } </graphviz>
03/03: Sistema de arquivos
- Tópicos: Estrutura de diretórios e arquivos organizados em árvore, visualização em modo gráfico e texto.
- Visualização em modo gráfico: no Linux, há vários programas que realizam uma mesma tarefa. Em aula, foi escolhido o sistema operacional Ubuntu Linux 9.10, que adota o navegador Nautilus (menu Locais -> Pasta Pessoal)para visualizar diretórios e arquivos - o equivalente ao Windows Explorer para o Windows.
- Visualização em modo texto: cada comando possui uma função. Cabe reforçar que no Linux as operações em modo gráfico possuem um equivalente em modo texto - sendo esse um instrumento bastante poderoso pela sua flexibilidade e agilidade para o administrador BEM acostumado :-)
- Alguns comandos utilizados: ls, cd, pwd, find, mkdir, mv e cp.
Atividades-problema
- Crie o diretório /var/tmp/0303, depois mova-o para o diretório /tmp.
- Copie o arquivo /etc/passwd para o diretório /tmp/a/b/c.
- Copie o arquivo /etc/shadow para o mesmo diretório do exercício anterior.
- Copie o diretório /tmp para /var/tmp (incluindo subdiretórios).
- O diretório /usr/../local/ existe? Por quê?
04/03: Gerência de memória e processos
- Tópicos: árvore de processos, filas de processos, comandos de manipulação dos processos.
- Alguns comandos utilizados para visualizar e operar sobre processos: ps, pstree, top e kill.
10/03: Processos e Controle de acesso
- Tópicos: a relação entre comandos, arquivos executáveis e processos, usuários e permissões e propriedades, números binários.
11/03: Controle de acesso e usuários
- Tópicos: usuários e grupos.
- Usuários são agrupados para facilitar a sua organização e manutenção. Assim pode-se utilizar grupos para ampliar ou restringir permissões de acesso a recursos do sistema, como CD-ROM, impressoras e outros.
- Todo arquivo está associado a um usuário (dono, responsável) e um grupo. As permissões, com isso, ficam estruturadas em 3 níveis:
- O próprio dono ou usuário do arquivo.
- Todos os usuários associados ao grupo do arquivo.
- Demais usuários do sistema.
- Cada usuário pode ler, modificar (escrever) e executar um arquivo (programa). Tem-se, assim, a combinação entre níveis de usuários e permissões:
Usuário | Grupo | Outros | ||||||
Ler | Escrever | Executar | Ler | Escrever | Executar | Ler | Escrever | Executar |
4 | 2 | 1 | 4 | 2 | 1 | 4 | 2 | 1 |
Código da permissão (octal) |
O comando
$ ls -l /etc/shadow
vai apresentar o seguinte resultado:
-rw-r----- 1 root shadow 796 Mar 13 20:27 /etc/shadow
Faz-se a seguinte leitura:
- -: O arquivo é regular (simples)
- rw-: o dono, root, pode ler e escrever no arquivo.
- r--: todos os usuários associados ao grupo shadow podem apenas ler o conteúdo do arquivo.
- ---: os demais usuários não têm qualquer acesso ao arquivo.
17/03: Usuários
18/03: Prova teórica
Lógica de Programação
Baseado no material Lógica de Programação, de Paulo Sérgio de Moraes - uma das referências bibliográficas da disciplina.
24/03: Introdução
25/03: Desenvolvendo algoritmos
31/03: Pseudocódigo e diagrama de blocos
01/04: Pseudocódigo e diagrama de blocos
07/04: Constantes e variáveis
08/04: Expressões lógicas e matemáticas e operadores
14/04: Estruturas de decisão
15/04: Estruturas de repetição
22/04: Prova prática
Linguagem de Programação C
Baseado no Guia Básico de C.
28/04: programas compilados e ambiente de desenvolvimento
29/04: Compilando o primeiro programa
- O clássico Hello World!
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("Alô mundo!\n");
}
05/05: Projeto Final da Disciplina
- Etapas de desenvolvimento:
- Desenha 1 onda
- Desenha 1 linha de ondas
- Desenha 1 matriz de tamanho fixo de ondas
- Desenha 1 matriz de tamanho variável de ondas (o usuário informa as dimensões)
- Mapeia 1 barco: latitude e longitude (vetor)
- Desenha o mar com 1 barco
- Mapeia 10 barcos: latitude e longitude (matriz)
- Desenha os 10 barcos
- Mapeia 10 barcos: latitude, longitude e se já foi atingido
- Pede ao usuário atirar
- Se o barco foi atingido, desenhar um X
- Ao final (todo os barcos atingidos): informar o usuário que venceu em 'n' movimentos
- Proposta de código que contempla:
- Bibliotecas e definições
- Declaração de constantes e variáveis
- Uso de variáveis com mesmo nome e diferentes escopos
- Vetor e matriz
- Operadores lógicos e matemáticos
- Expressões
- E/S
- Estruturas de decisão e repetição
- Funções
- Passagem de parâmetro por valor e por referência
- Acesso a uma matriz através de um vetor linear (função iniciaJogo)
- Ponteiros
#include <stdio.h>
#define QTDE_BARCOS 2
int iniciaJogo(int *barcos, int *tiros, int *atingidos)
{
int barco;
for(barco=0; barco<QTDE_BARCOS; barco++)
{
printf("\nBarco número %d:\n", barco + 1); // O primeiro barco é o de no. zero :-)
printf("Informe a latitude do barco: ");
scanf("%d", barcos + 3*barco); // end. inicial (barcos)
// + qtde. objetos por linha
// * linhas
// + coluna (1o. elemento)
printf("Informe a longitude do barco: ");
scanf("%d", barcos + 3*barco + 1); // end. inicial (barcos)
// + qtde. objetos por linha
// * linhas
// + coluna (2o. elemento)
*(barcos + 3*barco + 2) = 0; // endereço inicial (barcos)
// + qtde. objetos por linha
// * linhas
// + coluna (3o. elemento)
}
*tiros = 0;
*atingidos = 0;
}
char desenhaPonto(int linha, int coluna, int barcos[QTDE_BARCOS][3])
{
int barco;
for (barco=0; barco<QTDE_BARCOS; barco++)
{
if (linha==barcos[barco][0] & coluna==barcos[barco][1])
{
if (barcos[barco][2] == 1)
{
return 'X';
}
}
}
return '~';
}
desenhaMar(int linhas, int colunas, char onda, int barcos[QTDE_BARCOS][3])
{
int linha;
int coluna;
int barco;
int tinhaBarco;
for (linha=1; linha<linhas; linha++)
{
for (coluna=1; coluna<colunas; coluna++)
{
printf("%c", desenhaPonto(linha, coluna, barcos));
}
printf("\n");
}
}
int seVenceu(int barcos[QTDE_BARCOS][3])
{
int barco;
int atingidos = 0;
for (barco=0; barco<QTDE_BARCOS; barco++)
{
if (barcos[barco][2] == 1)
atingidos++;
}
return atingidos;
}
int main(int argc, char* argv[])
{
const char onda= '~';
int barcos[QTDE_BARCOS][3];
int latitude;
int longitude;
int barco;
int tiros;
int atingidos;
if (argc < 3)
{
printf("Use: %s (qtde. de linhas) (qtde. de colunas).\n", argv[0]);
return -1;
}
// Inicia o jogo
iniciaJogo(&barcos, &tiros, &atingidos);
// Estrutura principal de repetição: vai atirando sem parar... :-P
while (1)
{
// Limpa a tela
system("clear");
// Desenha o mar
desenhaMar(atoi(argv[1]), atoi(argv[2]), onda, barcos);
atingidos = seVenceu(barcos);
if (atingidos == QTDE_BARCOS)
{
printf("\nParabéns! Venceu o jogo com %d tiros!\n", tiros);
return 0;
}
else
{
printf("\nTiros: %d\n", tiros);
printf("Alvos atingidos: %d.\n", atingidos);
printf("\nDigite latitude e longitude:\n");
printf("- Latitude: ");
scanf("%d", &latitude);
printf("- Longitude: ");
scanf("%d", &longitude);
for (barco=0; barco<QTDE_BARCOS; barco++)
{
if (latitude == barcos[barco][0] & longitude == barcos[barco][1])
{
barcos[barco][2] = 1;
atingidos++;
}
}
tiros++;
}
}
}
06/05: Entrada e saída de dados e bibliotecas da linguagem
12/05: Constantes e variáveis
13/05: Vetores, matrizes e ponteiros
19/05: Expressões e operadores
20/05: Estruturas de decisão
26/05: Estruturas de repetição
27/05: Funções
- Tópicos: dividir para conquistar, escopo da função e suas constantes e variáveis.
02/06: Argumentos das funções
09/06: Passagem de parâmetro por valor e referência
10/06: O programa make
16/06: Desenvolvimento do Projeto Final
Expansões
- Limitar a quantidade de tiros e, caso o usuário não atinja todos os barcos, deve-se mostrá-los na tela.
- Tratar exceções de E/S, incluindo números fora dos limites - como por exemplo um barco fora do "mar".
- Alterar a interface para utilizar números para linhas e letras para colunas, além de permitir barcos de 3 tamanhos (sempre desenhados na horizontal).
- Utilizar apenas um vetor unidimensional ao invés de uma matriz em todo o código.
- MEGADESAFIO: utilizar a biblioteca ncurses, Tcl/Tk ou outra biblioteca gráfica para uma interface melhorada.
Dicas
- Entenda o problema, modele-o: utilize sempre que possível pseudocódigo / diagrama de bloco.
- Defina entradas, processamento e saídas do programa.
- Primeiro declare as variáveis, depois realize as expressões lógicas e matemáticas.
- Deixe claro (documente) o escopo de cada função (principalmente o fim) das estrutura de decisão e de repetição (quando não forem visíveis início e fim na mesma tela).