Sistemas Operacionais e Introdução a Programação (diário 2010-1) - Prof. Ederson Torresini

De MediaWiki do Campus São José
Ir para navegação Ir para pesquisar

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

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

  1. Crie o diretório /var/tmp/0303, depois mova-o para o diretório /tmp.
  2. Copie o arquivo /etc/passwd para o diretório /tmp/a/b/c.
  3. Copie o arquivo /etc/shadow para o mesmo diretório do exercício anterior.
  4. Copie o diretório /tmp para /var/tmp (incluindo subdiretórios).
  5. 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, Usuários 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. Comandos novos: whoami, w, id, touch, rmdir (veja a lista completa).
    • 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.

11/03: Controle de acesso e usuários

  • Tópicos: usuários e grupos.
  • Em um interpretador de comandos, ou shell, é comum digitarmos uma série de comandos para resolver um único problema, como por exemplo criar um arquivo e depois atribuir permissões ao mesmo. Essa série de comandos podem ser organizados em um único arquivo, o qual poderá ser executado - realizando todos os comandos (uma por por, linha por linha) em sequência. A isso chama-se um roteiro de comandos interpretados, ou script shell. A estrutura é relativamente simples do arquivo: deve-se começar informando que o conteúdo é uma série de comandos a serem interpretados (#!) e, em seguida, o interpretador escolhido (no nosso caso, o /bin/bash, já trabalhado em sala):
#!/bin/bash
...
...
...

Assim, as atividades-problema abaixo, por necessitarem de uma série de comandos, pode ser criado um script shell que os resolvam. Lógico, o arquivo a ser executado deve permitir, para tal, permissão de execução a quem for executá-lo. Exemplo: se o usuário aluno quer executar o arquivo /home/aluno/Desktop/meuPrimeiroPrograma.txt, ele deve ativar a permissão de execução para, em seguida, fazê-lo:

$ chmod 744 /home/aluno/Desktop/meuPrimeiroPrograma.txt
$ /home/aluno/Desktop/meuPrimeiroPrograma.txt

Atividades-problema

  • Crie o arquivo /tmp/a/d/j/arquivo.txt. Apenas o dono poderá ler e escrever nesse arquivo - os demais não deverão possuir qualquer acesso. Quanto ao diretório /tmp/a, aplique as permissões 751 - e diga o que representam tais permissões (quem pode o quê).
  • Crie a seguinte estrutura de arquivos e diretórios:
<graphviz>

graph Dir { splines=false root [shape=Mrecord,label="/"] tmp [shape=Mrecord,label="tmp/"] l [shape=Mrecord,label="permissões: 755|grupo: aluno|<0>l/"] m [shape=Mrecord,label="<0>m/|grupo: vboxusers|permissões: 755"] n [shape=Mrecord,label="<0>n/|grupo: xboxusers|permissões: 570"] arq1 [shape=record,label="grupo: aluno|<0>arq1"] arq2 [shape=record,label="<0>arq2|grupo: xboxusers"]

root -- tmp tmp -- l:0 l:0 -- arq1:0 tmp -- m:0 m:0 -- n:0 n:0 -- arq2:0 }

</graphviz>

Os arquivos devem possuir as seguintes permissões: leitura e escrita para o dono, leitura para o grupo e nenhuma permissão aos demais.

17/03: Atividades pré-prova

  • A partir do diretório /usr/local/src, mova-se até o diretório /usr/src e depois ao diretório /var/tmp usando:
    • Endereço relativo:
      • 1 salto
      • 2 saltos
      • 3 saltos.
    • Endereço absoluto

Dicas:

  1. movimentar-se para o diretório acima: cd ..
  2. movimentar-se o diretório atual (para fins de entendimento): cd .
  • Crie a estrutura de diretório /home/aluno/a/b/c/d/e/f. Copie o diretório recém-criado c (e tudo que está abaixo dele) para o diretório /tmp. Tente remover o diretório /tmp/d - é possível?
  • Quantos e quais processos contêm a palavra gdm? Há alguma relação entre eles? Que usuário(s) executou(aram) cada um deles?
  • Quais usuários estão executando o processo chamado bash? Finalize todos os processos bash do usuário aluno:
    • Processo a processo: kill
    • Todos de uma só vez: killall
  • Na estrutura /home/aluno/a/b/c/d/e/f, apenas o usuário aluno pode modificar o diretório d e diretórios/arquivos-filhos (e/f), o grupo vboxusers pode ler e demais não têm acesso algum.

18/03: Prova prática

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

  • Tópicos: instrução, sequência, problemas do dia a dia.
  • Páginas da apostila: 4 a 7.

25/03: Desenvolvendo algoritmos

  • Tópicos: resolvendo problemas, linguagens e instrução disponíveis (vocabulário).
  • Ferramenta utilizada em aula: Kturtle e a linguagem Logo.
    • Para hoje, bastam as seguintes instruções:
      • reset
      • forward NÚMERO
      • turnright NÚMERO
      • turnleft NÚMERO
  • Páginas da apostila: 8 a 11.

Atividades-problema

Com esse conjunto de instruções, desenhe:

  • Um triângulo equilátero.
  • Um triângulo isósceles.
  • Um triângulo escaleno.
  • Um hexágono.
  • Um octógono.
  • 7 hexágonos interligados (um central e seis periféricos).
  • Uma espiral

Como atividade complementar: Light Bot

Respostas

  • O que este código abaixo faz?
reset
repeat 6
{
   forward 70
   turnleft 60
}
repeat 6
{
   forward 70
   turnright 60
}
turnleft 120
repeat 6
{
   forward 70
   turnleft 60
}
forward 70
turnright 60
repeat 6
{
   forward 70
   turnleft 60
}
forward 70
turnright 60
repeat 6
{
   forward 70
   turnleft 60
}
forward 70
turnright 60
repeat 6
{
   forward 70
   turnleft 60
}
forward 70
turnright 60
repeat 6
{
   forward 70
   turnleft 60
}

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

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

O jogo: Batalha Naval

  • Etapas de desenvolvimento:
  1. Desenha 1 onda
  2. Desenha 1 linha de ondas
  3. Desenha 1 matriz de tamanho fixo de ondas
  4. Desenha 1 matriz de tamanho variável de ondas (o usuário informa as dimensões)
  5. Mapeia 1 barco: latitude e longitude (vetor)
  6. Desenha o mar com 1 barco
  7. Mapeia 10 barcos: latitude e longitude (matriz)
  8. Desenha os 10 barcos
  9. Mapeia 10 barcos: latitude, longitude e se já foi atingido
  10. Pede ao usuário atirar
  11. Se o barco foi atingido, desenhar um X
  12. 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).

17/06: Desenvolvimento do Projeto Final

23/06: Desenvolvimento do Projeto Final

24/06: Desenvolvimento do Projeto Final

30/06: Desenvolvimento do Projeto Final

01/07: Entrega do Projeto Final

07/07: Recuperação

08/07: O futuro das linguagens de programação


Voltar para página principal da disciplina