Mudanças entre as edições de "SOP-EngTel (página)"
Linha 204: | Linha 204: | ||
=Laboratórios= | =Laboratórios= | ||
− | {{collapse top| bg=lightyellow | expandir=true | | + | {{collapse top| bg=lightyellow | expandir=true | GCC/G++ no Linux}} |
− | == | + | == 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 | ||
− | |||
{{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
- Introdução a Sistemas Operacionais
- Escalonamento de Processos
- Comunicação entre Processos
- Coordenação de Processos (Programação Concorrente)
- Gerenciamento de Memória
- Gerenciamento de Arquivos
- Gerenciamento de Entrada e Saída
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çãoApresentaçã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: ProcessosGerê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óriaIntrodução ao Gerenciamento de Memória
Memória Principal
Memória Virtual
|
Unidade 04: Armazenamento |
---|
Unidade 04: ArmazenamentoInterface 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
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: 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;
}
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;
}
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.
|
Projetos
BOOOS - Basic Object Oriented Operating System |
---|
BOOOS - Basic Object Oriented Operating SystemEsta 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áticaVocê 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. 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. Para embasar seu trabalho, estude as seguintes man pages.
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 ConcorrenteA ser divulgado. |
Mapeamento de memória |
---|
Mapeamento de memóriaA ser divulgado. |
Implementação de driver Linux |
---|
Implementação de driver LinuxA ser divulgado. |