Mudanças entre as edições de "SOP-EngTel (página)"

De MediaWiki do Campus São José
Ir para navegação Ir para pesquisar
Linha 204: Linha 204:
 
=Laboratórios=
 
=Laboratórios=
  
{{collapse top| bg=lightyellow | expandir=true | Lab1}}
+
{{collapse top| bg=lightyellow | expandir=true | GCC/G++ no Linux}}
== Lab1 ==
+
== GCC/G++ no Linux ==
 +
 
 +
;Referências
 +
* Referência sobre C++: http://www.cplusplus.com/
 +
* Livros sobre C++:
 +
** [http://www.stroustrup.com/4th.html The C++ Programming Language (4th Edition)]
 +
** [http://www.deitel.com/books/cpphtp5/ C++ How to Program, Fifth Edition]
 +
* Tutorial C++
 +
** [http://www.horstmann.com/ccj2/ccjapp3.html Moving from Java to C++]
 +
* Exercício-exemplo feito em aula. [[http://docente.ifsc.edu.br/arliones.hoeller/sop/my_first_cpp_program.tgz código-fonte]]
 +
 
 +
;Herança
 +
* http://www.cplusplus.com/doc/tutorial/inheritance/
 +
 
 +
Classes em C++ podem ser estendidas, criando novas classes que retêm as característica da classe-base. Este processo, conhecido como herança, envolve uma classe-base e uma classe derivada: a classe derivada '''herda''' os membros da classe-base, sobre os quais ela pode adicionar seus próprios membros.
 +
 
 +
Por exemplo, imaginemos uma série de classes para descrever dois tipos de polígonos: retângulos e triângulos. Estes dois polígonos têm certas propriedades em comum, como os valores necessários para calcular suas áreas: ambos podem ser descritos simplificadamente com uma altura e uma largura. (ou base).
 +
 
 +
Isto pode ser representado no formato de classes como uma classe Polygon (polígono) da qual podemos derivar duas outras classes: Rectangle e Triangle:
 +
 
 +
[[Arquivo:Inheritance.png]]
 +
 
 +
A classe Polygon poderia conter membros comuns a ambos os tipos de polígonos. Em nosso caso: largura e altura (width e height). E as classes Rectangle e Triangle poderiam ser as classes derivadas, com características específicas que diferenciam um tipo de polígono de outro.
 +
 
 +
Classes que são derivadas de outras herdam todos os membros '''acessíveis''' da classe-base. Isto significa que se a classe-base inclui um membro A e nós derivamos uma classe dela, e esta nova classe possui um membro B, a classe derivada conterá ambos os membros A e B.
 +
 
 +
No C++, a relação de herança de duas classes é declarada na classe derivada. A definição de classes derivadas usa a seguinte sintaxe:
 +
 
 +
<syntaxhighlight lang=cpp>
 +
class classe_derivada : public classe_base
 +
{ /*...*/ };
 +
</syntaxhighlight>
 +
 
 +
O código acima define uma classe com nome ''classe_derivada'', que herda '''publicamente''' a classe com nome ''classe_base''. A palavra reservada ''public'' pode ser substituído por ''protected'' ou ''private'', dependendo do tipo de herança desejado. Este delimitador de acesso limita o nível de acesso aos membros herdados da classe-base: os membros com um nível de acesso mais acessível são herdados com o nível declarado na herança, enquanto os membros com níveis de acesso iguais ou mais restritivos mantém, na classe derivada, os níveis de restrição declarados na classe-base.
 +
 
 +
<syntaxhighlight lang=cpp>
 +
#include <iostream>
 +
using namespace std;
 +
 
 +
class Polygon {
 +
  protected:
 +
    int width, height;
 +
  public:
 +
 
 +
    virtual int area() = 0;
 +
 
 +
    void set_values (int a, int b)
 +
      { width=a; height=b;}
 +
};
 +
 
 +
class Rectangle: public Polygon {
 +
  public:
 +
    int area ()
 +
      { return width * height; }
 +
};
 +
 
 +
class Triangle: public Polygon {
 +
  public:
 +
    int area ()
 +
      { return width * height / 2; }
 +
  };
 +
 
 +
int main () {
 +
  Rectangle rect;
 +
  Triangle trgl;
 +
  rect.set_values (4,5);
 +
  trgl.set_values (4,5);
 +
  cout << rect.area() << '\n';
 +
  cout << trgl.area() << '\n';
 +
  return 0;
 +
}
 +
</syntaxhighlight>
 +
 
 +
*'''Experimento 1:''' compile e execute o exemplo acima.
 +
*'''Experimento 2:''' substitua, no exemplo acima, uma herança pública por herança protegida ou privada e verifique o que acontece.
 +
 
 +
*'''Leitura extra - Polimorfismo:''' http://www.cplusplus.com/doc/tutorial/polymorphism/
 +
 
 +
;Espaços de nomes
 +
* http://www.cplusplus.com/doc/tutorial/namespaces/
 +
 
 +
Espaços de nome, ou ''namespaces'', permite agrupar entidades como classes, objetos e funções sob um mesmo nome. Deste modo o escopo global pode ser dividido em "sub-escopos", cada um com seu próprio nome.
 +
 
 +
A sintaxe para uso de um ''namespace'' em C++ é dada abaixo, onde ''identifier'' é o nome do sob o qual as entidades serão declaradas e, no local do comentário, seria registrado o conjunto de classes, objetos e funções incluídos no ''namespace'':
 +
 
 +
<syntaxhighlight lang=cpp>
 +
namespace identifier
 +
{
 +
  /* entities... */
 +
}
 +
</syntaxhighlight>
 +
 
 +
Por exemplo, o código abaixo as variáveis ''a'' e ''b'' são inteiros normais declarados dentro do ''namespace'' ''myNamespace''.
 +
 
 +
<syntaxhighlight lang=cpp>
 +
namespace myNamespace
 +
{
 +
  int a, b;
 +
}
 +
</syntaxhighlight>
 +
 
 +
Estas variáveis podem ser acessadas normalmente por classes ou funções declaradas dentro do mesmo ''namespace''. Para serem acessadas de fora do ''namespace'', contudo, elas precisam ser adequadamente qualificadas utilizando o operador de escopo (::). Por exemplo, para utilizar as variáveis acima de fora do ''myNamespace'', elas devem ser qualificadas como:
 +
 
 +
<syntaxhighlight lang=cpp>
 +
myNamespace::a
 +
myNamespace::b
 +
</syntaxhighlight>
 +
 
 +
Espaços de nomes podem ser bastante úteis para evitar colisão de identificadores:
 +
 
 +
<syntaxhighlight lang=cpp>
 +
// namespaces
 +
#include <iostream>
 +
using namespace std;
 +
 
 +
namespace foo
 +
{
 +
  int value() { return 5; }
 +
}
 +
 
 +
namespace bar
 +
{
 +
  const double pi = 3.1416;
 +
  double value() { return 2*pi; }
 +
}
 +
 
 +
int main () {
 +
  cout << foo::value() << '\n';
 +
  cout << bar::value() << '\n';
 +
  cout << bar::pi << '\n';
 +
  return 0;
 +
}
 +
</syntaxhighlight>
 +
 
 +
*'''Experimento 1:''' compile, execute, e entenda o código do exemplo acima.
 +
*'''Experimento 2:''' crie, dentro do ''namespace'' ''bar'', uma função que acesse a função ''value'' do ''namespace'' ''foo''.
 +
 
 +
*'''Leitura extra - Visibilidade de nomes em C++:''' http://www.cplusplus.com/doc/tutorial/namespaces/
 +
 
 +
;Criando bibliotecas
 +
* http://www.delorie.com/djgpp/doc/ug/larger/archives.html
 +
 
 +
Uma biblioteca é uma coleção de objetos, assim como uma biblioteca tradicional é uma coleção de livros. Quando construindo seu programa, você pode utilizar, no gcc, uma ou mais bibliotecas, de modo que o gcc utilizará os objetos nestas bibliotecas para completar seu programa. Por exemplo, todas as funções da biblioteca padrão C (como ''printf'' e ''exit'') estão em uma biblioteca C, geralmente na pasta lib/libc.a da sua instalação GCC. Quando você faz a ligação do seu programa, o GCC adiciona ao binário os objetos da biblioteca C necessários, baseando-se nas chamadas de funções do seu programa. Importante perceber que apenas as funções/objetos utilizados são ligados ao programa, não gerando desperdício de tempo e espaço.
 +
 
 +
Para fazer usa própria biblioteca, você precisa, primeiro, compilar cada um dos arquivos-fonte, gerando um conjunto de arquivos-objeto. Aqui utilizaremos, como exemplo, o código do [https://www.dropbox.com/s/nkiw7y4trrbixuy/my_first_cpp_program.zip exercício-exemplo da aula anterior].
 +
 
 +
<syntaxhighlight lang=bash>
 +
g++ -c pessoa.cc
 +
g++ -c aluno.cc
 +
</syntaxhighlight>
 +
 
 +
A seguir, você utilizará o comando ''ar'' para criar uma biblioteca contendo os arquivos-objeto criados.
 +
 
 +
<syntaxhighlight lang=bash>
 +
ar rvs mylib.a pessoa.o aluno.o
 +
</syntaxhighlight>
 +
 
 +
Cada uma das letras em ''rvs'' especifica um parâmetro para o ''ar''. ''r'' significa substituir objetos com mesmo nome na biblioteca pelos novos passados pela linha de comando. Como a biblioteca está inicialmente vazia, isto significa o mesmo que adicionar novos objetos à biblioteca. Há também opções para extrair e remover objetos da biblioteca. A opção ''v'' significa ''verbose'', ou seja, pede que o programa ''ar'' imprima na tela as ações sendo tomadas durante sua execução. Finalmente, a opção ''s'' diz ao ''ar'' para criar uma tabela de símbolos, que é um recurso extra que o GCC precisa para utilizar uma biblioteca.
 +
 
 +
Para utilizar a biblioteca, simplesmente adicione ela ao comando de ligação do gcc como se fosse outro objeto:
 +
 
 +
<syntaxhighlight lang=cpp>
 +
g++ main.cc mylib.a -o main
 +
</syntaxhighlight>
 +
 
 +
É importante listar as bibliotecas na ordem correta. Durante a ligação, o GCC "puxa" apenas os objetos que sabe necessitar até o momento. Isto que dizer que primeiro é necessário alimentar ao GCC os arquivos-objeto que dependem de uma biblioteca (no exemplo, o main.cc), e por fim as bibliotecas que completam esta dependência.
 +
 
 +
*'''Experimento 1:''' pegue o código-fonte da aula anterior e gere a biblioteca mylib.a utilizando os comandos acima.
 +
*'''Experimento 2:''' modifique o arquivo makefile da aula anterior para trabalhar com a biblioteca.
 +
*'''Experimento 3:''' modifique a assinatura de algum método das classes Pessoa ou Aluno e verifique o que acontece.
 +
 
 +
*'''Leitura extra - uso da C++ Standard Template Library:''' http://www.yolinux.com/TUTORIALS/LinuxTutorialC++STL.html
  
Lab1.
 
 
{{collapse bottom}}
 
{{collapse bottom}}
  

Edição das 14h18min de 26 de novembro de 2015

Sistemas Operacionais - 2015-2

Professor: Arliones Hoeller

  • Encontros: Quintas às 15:40 e sextas às 13:30 no Lab. de Programação.
  • Atendimento
    • Terças das 10:35 às 11:30
    • Quintas das 14:25 às 15:20

Notas

Aluno P0 P1 T0 T1 Exs Final
122005023-7
132002623-0
132002999-0
131004419-8
131005150-0
131001281-4
121000492-5
121000484-4
132004514-6
122001832-5
132002264-2
131005334-0
132004278-3

Entrega das Avaliações Secundárias

Aluno S0 S1 S2 S3
122005023-7 OK
132002623-0 OK
132002999-0 OK
131004419-8 OK
131005150-0 OK
131001281-4 OK
121000492-5 OK
121000484-4 OK
132004514-6 OK
122001832-5 OK
132002264-2 OK
131005334-0 OK
132004278-3 OK

Material de aula

Slides

Listas de exercícios

As listas de exercícios são compostas por exercícios selecionados do livro do Silberschatz, 8a edição. Há 10 volumes deste livro na biblioteca do campus.

SILBERSCHATZ, Abraham; GALVIN, Peter; GAGNE, Greg. Fundamentos de sistemas operacionais. 8. ed. Rio de Janeiro: LTC, 2011. 515 p., il. ISBN 9788521617471.

Exercícios selecionados:

  • Capítulo 1: 1-3, 6-8, 10, 13, 14, 17, 22, 23, 25.
  • Capítulo 2: 1-8, 12, 13, 15, 17, 22, 25.
  • Capítulo 3: 1, 3, 6-10, 13, 15
  • Capítulo 4: 1, 4, 7, 8, 10-13
  • Capítulo 5: 1-3, 5, 6, 9, 10, 13-15, 21
  • Capítulo 6: 1, 2 (utilizar semáforos POSIX), 6, 8, 11-15, 18, 20, 21, 25, 29, 39.
  • Capítulo 8: 1-6, 9-21, 23.
  • Capítulo 9: 1-8, 14-16, 19-23, 28.
  • Capítulo 10: 1-20
  • Capítulo 11: 1-7
  • Capítulo 12: 1-7, 13-14 (desafio).

Conteúdo

Unidade 01: Introdução

Unidade 01: Introdução

Apresentação do Curso

Visão geral de funções, responsabilidades e estruturas de um SO

Arquitetura de sistemas operacionais e modelos de programação

Unidade 02: Processos

Unidade 02: Processos

Gerência de tarefas; contextos, processos e threads

Escalonamento de tarefas

Comunicação entre Processos

Coordenação de processos

Unidade 03: Memória

Unidade 03: Memória

Introdução ao Gerenciamento de Memória

Memória Principal

Memória Virtual


Unidade 04: Armazenamento

Unidade 04: Armazenamento

Interface do Sistema de Arquivos

Implementação do Sistema de Arquivos

Estrutura de Armazenamento em Massa

Gerenciamento de Entrada e Saída

Laboratórios

GCC/G++ no Linux

GCC/G++ no Linux

Referências
Herança

Classes em C++ podem ser estendidas, criando novas classes que retêm as característica da classe-base. Este processo, conhecido como herança, envolve uma classe-base e uma classe derivada: a classe derivada herda os membros da classe-base, sobre os quais ela pode adicionar seus próprios membros.

Por exemplo, imaginemos uma série de classes para descrever dois tipos de polígonos: retângulos e triângulos. Estes dois polígonos têm certas propriedades em comum, como os valores necessários para calcular suas áreas: ambos podem ser descritos simplificadamente com uma altura e uma largura. (ou base).

Isto pode ser representado no formato de classes como uma classe Polygon (polígono) da qual podemos derivar duas outras classes: Rectangle e Triangle:

Inheritance.png

A classe Polygon poderia conter membros comuns a ambos os tipos de polígonos. Em nosso caso: largura e altura (width e height). E as classes Rectangle e Triangle poderiam ser as classes derivadas, com características específicas que diferenciam um tipo de polígono de outro.

Classes que são derivadas de outras herdam todos os membros acessíveis da classe-base. Isto significa que se a classe-base inclui um membro A e nós derivamos uma classe dela, e esta nova classe possui um membro B, a classe derivada conterá ambos os membros A e B.

No C++, a relação de herança de duas classes é declarada na classe derivada. A definição de classes derivadas usa a seguinte sintaxe:

class classe_derivada : public classe_base
{ /*...*/ };

O código acima define uma classe com nome classe_derivada, que herda publicamente a classe com nome classe_base. A palavra reservada public pode ser substituído por protected ou private, dependendo do tipo de herança desejado. Este delimitador de acesso limita o nível de acesso aos membros herdados da classe-base: os membros com um nível de acesso mais acessível são herdados com o nível declarado na herança, enquanto os membros com níveis de acesso iguais ou mais restritivos mantém, na classe derivada, os níveis de restrição declarados na classe-base.

#include <iostream>
using namespace std;

class Polygon {
  protected:
    int width, height;
  public:

    virtual int area() = 0;

    void set_values (int a, int b)
      { width=a; height=b;}
 };

class Rectangle: public Polygon {
  public:
    int area ()
      { return width * height; }
 };

class Triangle: public Polygon {
  public:
    int area ()
      { return width * height / 2; }
  };
  
int main () {
  Rectangle rect;
  Triangle trgl;
  rect.set_values (4,5);
  trgl.set_values (4,5);
  cout << rect.area() << '\n';
  cout << trgl.area() << '\n';
  return 0;
}
  • Experimento 1: compile e execute o exemplo acima.
  • Experimento 2: substitua, no exemplo acima, uma herança pública por herança protegida ou privada e verifique o que acontece.
Espaços de nomes

Espaços de nome, ou namespaces, permite agrupar entidades como classes, objetos e funções sob um mesmo nome. Deste modo o escopo global pode ser dividido em "sub-escopos", cada um com seu próprio nome.

A sintaxe para uso de um namespace em C++ é dada abaixo, onde identifier é o nome do sob o qual as entidades serão declaradas e, no local do comentário, seria registrado o conjunto de classes, objetos e funções incluídos no namespace:

namespace identifier
{
  /* entities... */
}

Por exemplo, o código abaixo as variáveis a e b são inteiros normais declarados dentro do namespace myNamespace.

namespace myNamespace
{
  int a, b;
}

Estas variáveis podem ser acessadas normalmente por classes ou funções declaradas dentro do mesmo namespace. Para serem acessadas de fora do namespace, contudo, elas precisam ser adequadamente qualificadas utilizando o operador de escopo (::). Por exemplo, para utilizar as variáveis acima de fora do myNamespace, elas devem ser qualificadas como:

myNamespace::a
myNamespace::b

Espaços de nomes podem ser bastante úteis para evitar colisão de identificadores:

// namespaces
#include <iostream>
using namespace std;

namespace foo
{
  int value() { return 5; }
}

namespace bar
{
  const double pi = 3.1416;
  double value() { return 2*pi; }
}

int main () {
  cout << foo::value() << '\n';
  cout << bar::value() << '\n';
  cout << bar::pi << '\n';
  return 0;
}
  • Experimento 1: compile, execute, e entenda o código do exemplo acima.
  • Experimento 2: crie, dentro do namespace bar, uma função que acesse a função value do namespace foo.
Criando bibliotecas

Uma biblioteca é uma coleção de objetos, assim como uma biblioteca tradicional é uma coleção de livros. Quando construindo seu programa, você pode utilizar, no gcc, uma ou mais bibliotecas, de modo que o gcc utilizará os objetos nestas bibliotecas para completar seu programa. Por exemplo, todas as funções da biblioteca padrão C (como printf e exit) estão em uma biblioteca C, geralmente na pasta lib/libc.a da sua instalação GCC. Quando você faz a ligação do seu programa, o GCC adiciona ao binário os objetos da biblioteca C necessários, baseando-se nas chamadas de funções do seu programa. Importante perceber que apenas as funções/objetos utilizados são ligados ao programa, não gerando desperdício de tempo e espaço.

Para fazer usa própria biblioteca, você precisa, primeiro, compilar cada um dos arquivos-fonte, gerando um conjunto de arquivos-objeto. Aqui utilizaremos, como exemplo, o código do exercício-exemplo da aula anterior.

g++ -c pessoa.cc
g++ -c aluno.cc

A seguir, você utilizará o comando ar para criar uma biblioteca contendo os arquivos-objeto criados.

ar rvs mylib.a pessoa.o aluno.o

Cada uma das letras em rvs especifica um parâmetro para o ar. r significa substituir objetos com mesmo nome na biblioteca pelos novos passados pela linha de comando. Como a biblioteca está inicialmente vazia, isto significa o mesmo que adicionar novos objetos à biblioteca. Há também opções para extrair e remover objetos da biblioteca. A opção v significa verbose, ou seja, pede que o programa ar imprima na tela as ações sendo tomadas durante sua execução. Finalmente, a opção s diz ao ar para criar uma tabela de símbolos, que é um recurso extra que o GCC precisa para utilizar uma biblioteca.

Para utilizar a biblioteca, simplesmente adicione ela ao comando de ligação do gcc como se fosse outro objeto:

g++ main.cc mylib.a -o main

É importante listar as bibliotecas na ordem correta. Durante a ligação, o GCC "puxa" apenas os objetos que sabe necessitar até o momento. Isto que dizer que primeiro é necessário alimentar ao GCC os arquivos-objeto que dependem de uma biblioteca (no exemplo, o main.cc), e por fim as bibliotecas que completam esta dependência.

  • Experimento 1: pegue o código-fonte da aula anterior e gere a biblioteca mylib.a utilizando os comandos acima.
  • Experimento 2: modifique o arquivo makefile da aula anterior para trabalhar com a biblioteca.
  • Experimento 3: modifique a assinatura de algum método das classes Pessoa ou Aluno e verifique o que acontece.

Projetos

BOOOS - Basic Object Oriented Operating System

BOOOS - Basic Object Oriented Operating System

Esta disciplina utiliza um projeto contínuo, no qual os alunos desenvolvem um aplicativo que emula um sistema operacional no espaço de usuário no Linux. Este projeto é chamado de BOOOS - Basic Object Oriented Operating System.

TerminALL - FORK/WAIT/EXEC na prática - Prazo: 12/11/2015

TerminALL - FORK/WAIT/EXEC na prática

Você deve utilizar as chamadas de sistema fork, wait e exec para implementar em C++ um interpretador de comandos. Os requisitos do projeto são apresentados na figura abaixo.

TerminALL-requisitos.png

Uma estrutura geral do sistema é dado pelo diagrama de classes abaixo. Este diagrama é uma versão inicial e, certamente, incompleto. O sistema final de vocês provavelmente terá novos métodos ou assinaturas diferentes para os métodos que estão ali.

TerminALL-classes.png

Para embasar seu trabalho, estude as seguintes man pages.

  • man fork
  • man wait
  • man exec
  • man gethostname
  • man getlogin
  • man getpid
  • man 2 kill

Entrega: Quinta, 12/11/2015, por email, em duplas. Entregar o código-fonte do projeto, acompanhado de relatório curto com o diagrama de classes atualizado (implementado) e uma descrição de como o sistema foi testado.

Um versão do projeto com classes VAZIAS E INCOMPLETAS pode ser baixada aqui.

Programação Concorrente

Programação Concorrente

A ser divulgado.

Mapeamento de memória

Mapeamento de memória

A ser divulgado.

Implementação de driver Linux

Implementação de driver Linux

A ser divulgado.