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
 
(81 revisões intermediárias por 5 usuários não estão sendo mostradas)
Linha 1: Linha 1:
= Sistemas Operacionais - 2015-2 =
+
= Sistemas Operacionais =
  
'''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
 
  
*[[SOP-EngTel_(Plano_de_Ensino)| Plano de Ensino]]
+
Turma 2019-1
*[[Cronograma de atividades (SOP-EngTel) | Cronograma]]
+
*'''Professor:''' [[Eraldo Silveira e Silva]]
 
+
*'''Encontros:''' Quartas às 9:40 (Lab.Redes) e sextas às 9:40 no Lab. Prog.
=Notas=
+
[[SOP29005-2019-1| Clique aqui]] Edição 2019-1
  
{| class="wikitable"
 
!scope="col"| Aluno
 
!scope="col"| P0
 
!scope="col"| P1
 
!scope="col"| T0
 
!scope="col"| T1
 
!scope="col"| Exs
 
!scope="col"| 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 ==
+
Turma 2018-2
 +
*'''Professor:''' [[André D'Amato]]
 +
*'''Encontros:''' Segundas às 15:40 e quintas às 13:30 no LabCad.
 +
[http://wiki.sj.ifsc.edu.br/index.php/SOP-EngTel_2018_2 Clique aqui] Edição 2018-2
  
{| class="wikitable"
 
!scope="col"| Aluno
 
!scope="col"| S0
 
!scope="col"| S1
 
!scope="col"| S2
 
!scope="col"| 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 ==
+
Turma 2018-1
 +
*'''Professor:''' [[André D'Amato]]
 +
*'''Encontros:''' Segundas às 7:30 e sextas às 9:40 no Laboratório de Redes II.
 +
[http://wiki.sj.ifsc.edu.br/index.php/SOP-EngTel_2018_1 Clique aqui] Edição 2018-1
  
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte1.pdf Introdução a Sistemas Operacionais]
 
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte2.pdf Escalonamento de Processos]
 
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte3.pdf Comunicação entre Processos]
 
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte4.pdf Coordenação de Processos (Programação Concorrente)]
 
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte5.pdf Gerenciamento de Memória]
 
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte6.pdf Gerenciamento de Arquivos]
 
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte7.pdf 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.
+
*'''Professor:''' [[Arliones Hoeller]]
 +
*'''Encontros:''' Quartas e sextas às 7:30 no Laboratório de Redes II.
 +
<!--*Inscreva-se neste [https://groups.google.com/forum/#!forum/sop29005 grupo de discussão].-->
  
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=
 
 
{{collapse top| bg=lightyellow | expandir=true | Unidade 01: Introdução}}
 
== Unidade 01: Introdução ==
 
 
=== Apresentação do Curso ===
 
 
*[[SOP-EngTel_(Plano_de_Ensino)| Plano de Ensino]]
 
*[[SOP-EngTel_(Plano_de_Ensino)| Plano de Ensino]]
*[[Cronograma de atividades (STE-EngTel) | Cronograma]]
+
*[[Cronograma de atividades (SOP-EngTel) | Cronograma]]
*Outros cursos de sistemas operacionais nos quais este curso se baseia:
+
*[http://moodlenovo.sj.ifsc.edu.br/course/view.php?id=153 Moodle]
**[http://www.lisha.ufsc.br/teaching/os/ Sistemas Operacionais - Ciências da Computação UFSC]
 
**[http://dainf.ct.utfpr.edu.br/~maziero/doku.php/so:start Sistemas Operacionais - Engenharia da Computação UTFPR]
 
*[[BOOOS - Basic Object Oriented Operating System]]
 
 
 
=== Visão geral de funções, responsabilidades e estruturas de um SO ===
 
* [https://www.youtube.com/watch?v=7LGKgdWtrqI Revolution OS]: documentário sobre Linux e software livre
 
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte1.pdf Apresentação sobre histórico visão geral e estruturas básicas de um SO]
 
* Capítulo 1 do livro do Silberschatz
 
 
 
=== Arquitetura de sistemas operacionais e modelos de programação ===
 
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte1.pdf Apresentação sobre histórico visão geral e estruturas básicas de um SO]
 
* Capítulo 2 do livro do Silberschatz
 
 
 
{{collapse bottom}}
 
 
 
{{collapse top| bg=lightyellow | expandir=true | Unidade 02: Processos}}
 
== Unidade 02: Processos ==
 
 
 
=== Gerência de tarefas; contextos, processos e threads ===
 
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte2.pdf Apresentação sobre Gerenciamento de Processos]
 
* Capítulo 3 do livro do Silberschatz
 
 
 
=== Escalonamento de tarefas ===
 
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte2.pdf Apresentação sobre Escalonamento de Processos]
 
* [http://courses.cs.vt.edu/csonline/OS/Lessons/Processes/index.html Animação de escalonamento de processos - Virginia Tech]
 
* Capítulo 5 do livro do Silberschatz.
 
 
 
=== Comunicação entre Processos ===
 
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte3.pdf Apresentação sobre Comunicação entre Processos]
 
* Capítulo 3 do livro do Silberschatz.
 
 
 
=== Coordenação de processos ===
 
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte4.pdf Apresentação sobre Coordenação de Processos]
 
* Capítulos 6 e 7 do livro do Silberschatz.
 
* Curiosidade: [http://research.microsoft.com/en-us/um/people/mbj/mars_pathfinder/authoritative_account.html A inversão de prioridades na Mars Pathfinder]
 
 
 
{{collapse bottom}}
 
 
 
{{collapse top| bg=lightyellow | expandir=true | Unidade 03: Memória}}
 
== Unidade 03: Memória==
 
 
 
=== Introdução ao Gerenciamento de Memória ===
 
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte5.pdf Apresentação sobre Gerenciamento de Memória]
 
* Capítulo 8 do livro do Silberschatz.
 
 
 
=== Memória Principal ===
 
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte5.pdf Apresentação sobre Gerenciamento de Memória]
 
* Capítulo 8 do livro do Silberschatz.
 
 
 
=== Memória Virtual ===
 
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte5.pdf Apresentação sobre Gerenciamento de Memória]
 
* Capítulo 9 do livro do Silberschatz.
 
 
 
 
 
{{collapse bottom}}
 
 
 
{{collapse top| bg=lightyellow | expandir=true | Unidade 04: Armazenamento}}
 
== Unidade 04: Armazenamento ==
 
 
 
=== Interface do Sistema de Arquivos ===
 
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte6.pdf Apresentação sobre Gerenciamento de Arquivos]
 
* Capítulo 10 do livro do Silberschatz.
 
 
 
=== Implementação do Sistema de Arquivos ===
 
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte6.pdf Apresentação sobre Gerenciamento de Arquivos]
 
* Capítulo 11 do livro do Silberschatz.
 
 
 
=== Estrutura de Armazenamento em Massa ===
 
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte6.pdf Apresentação sobre Gerenciamento de Arquivos]
 
* Capítulo 12 do livro do Silberschatz.
 
 
 
=== Gerenciamento de Entrada e Saída ===
 
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte7.pdf Apresentação sobre Gerenciamento de Entrada e Saída]
 
* Capítulo 13 do livro do Silberschatz.
 
 
 
{{collapse bottom}}
 
 
 
=Laboratórios=
 
 
 
{{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 top| bg=lightyellow | expandir=true | Processos no Linux}}
 
== Processos no Linux ==
 
 
 
 
 
;Syscall FORK
 
 
 
* Em um terminal, execute "man fork"
 
** A função da API POSIX '''fork()''' aciona uma chamada de sistema (system call - syscall) que cria um novo processo duplicando o processo que realiza a chamada. O novo processo, chamado de filho, é uma cópia exata do processo criador, chamado de pai, exceto por alguns detalhes listados na manpage. O principal destes detalhes para nós agora é o fato de terem '''PIDs diferentes'''.
 
** O '''código''' dos dois processos (pai e filho) são '''idênticos''';
 
** Os '''dados''' dos dois processos (pai e filho) são '''idênticos NO MOMENTO DA CRIAÇÃO''';
 
** Execução do processo filho inicia na próxima instrução do programa (no retorno da chamada FORK);
 
** Não é possível saber qual dos processos (pai ou filho) retormará a execução primeiro - isto fica a cargo do excalonador do SO;
 
** Valores de retorno da chamada FORK:
 
*** (-1): erro na criação do processo (ex.: memória insuficiente);
 
*** (0): em caso de sucesso, este é o valor de retorno recebido pelo processo filho;
 
*** (>0): em caso de sucesso, este é o valor de retorno recebido pelo processo pai;
 
 
 
;Syscall JOIN
 
 
 
* A syscall JOIN é implementada no POSIX pelo função '''wait()'''. Execute "man wait".
 
** Além da função '''wait()''', há também '''waitpid()''' e '''waitid()''';
 
** Todas estas syscalls são utilizadas para aguardar por mudanças no estado de um processo filho e obter informações sobre o processo filho cujo estado tenha mudado. São consideradas mudanças de estado: o filho terminou; o filho foi finalizado por um sinal (ex.: kill); o filho foi retomado por um sinal (ex.: alarme);
 
** A chamada wait também libera os recursos do processo filho que termina;
 
** '''wait()''': esta função suspende a execução do processo chamador até que UM DOS SEUS FILHOS finalize;
 
** '''waitpid()''': suspende a execução do processo chamador até que UM FILHO ESPECÍFICO finalize;
 
 
 
;Syscall EXEC
 
 
 
* A syscall EXEC é implementada no POSIX pela família de funções '''exec()'''. Execute "man exec".
 
** As principais funções da família são '''execl()''', '''execlp()''' e '''execvp()''';
 
** Todas estas funções são, na realidade, front-ends (abstrações) para a syscall '''execve'''. Esta syscall substitui a imagem do processo corrente (aquele que chama a syscall) pela a imagem de um novo processo;
 
** Os parâmetros passados a estas funções são, basicamente, o nome de um arquivo com a imagem do programa a ser executado (um binário de um programa), e uma lista de parâmetros a serem passados a este novo programa;
 
 
 
 
 
;Exemplos POSIX utilizando fork/wait/exec
 
 
 
*Exemplo 1: fork/wait básico
 
<syntaxhighlight lang=c>
 
// ex1: fork/wait básico
 
#include <sys/types.h>
 
#include <stdlib.h>
 
#include <stdio.h>
 
#include <unistd.h>
 
 
 
int main()
 
{
 
    int pid, status;
 
    pid = fork();
 
 
 
    if(pid == -1) // fork falhou
 
    {
 
        perror("fork falhou!");
 
        exit(-1);
 
    }
 
    else if(pid == 0) // Este é o processo filho
 
    {
 
        printf("processo filho\t pid: %d\t pid pai: %d\n", getpid(), getppid());
 
        exit(0);
 
    }
 
    else // Este é o processo pai
 
    {
 
        wait(&status);
 
        printf("processo pai\t pid: %d\t pid pai: %d\n", getpid(), getppid());
 
        exit(0);
 
    }
 
}
 
</syntaxhighlight>
 
 
 
<syntaxhighlight lang=bash>
 
arliones@socrates:~/tmp$ gcc ex1.c -o ex1
 
arliones@socrates:~/tmp$ ./ex1
 
processo filho pid: 27858 pid pai: 27857
 
processo pai pid: 27857 pid pai: 5337
 
arliones@socrates:~/tmp$
 
</syntaxhighlight>
 
 
 
* Exemplo 2: processos pai e filho compartilham código, mas não dados.
 
<syntaxhighlight lang=c>
 
// ex2: fork/wait "compartilhando" dados
 
#include <sys/types.h>
 
#include <stdlib.h>
 
#include <stdio.h>
 
 
 
int main()
 
{
 
    int pid, status, k=0;
 
    printf("processo %d\t antes do fork\n", getpid());
 
    pid = fork();
 
    printf("processo %d\t depois do fork\n", getpid());
 
 
 
    if(pid == -1) // fork falhou
 
    {
 
        perror("fork falhou!");
 
        exit(-1);
 
    }
 
    else if(pid == 0) // Este é o processo filho
 
    {
 
        k += 1000;
 
        printf("processo filho\t pid: %d\t K: %d\n", getpid(), k);
 
        exit(0);
 
    }
 
    else // Este é o processo pai
 
    {
 
        wait(&status);
 
        k += 10;
 
        printf("processo pai\t pid: %d\t K: %d\n", getpid(), k);
 
        exit(0);
 
    }
 
    k += 10;
 
    printf("processo %d\t K: %d\n", getpid(), k);
 
    exit(0);
 
}
 
</syntaxhighlight>
 
 
 
<syntaxhighlight lang=bash>
 
arliones@socrates:~/tmp$ gcc ex2.c -o ex2
 
arliones@socrates:~/tmp$ ./ex2
 
processo 18425 antes do fork
 
processo 18425 depois do fork
 
processo 18426 depois do fork
 
processo filho pid: 18426 K: 1000
 
processo pai pid: 18425 K: 10
 
arliones@socrates:~/tmp$
 
</syntaxhighlight>
 
 
 
* Modificação no código: comentar linhas 22 e 29
 
 
 
<syntaxhighlight lang=bash>
 
arliones@socrates:~/tmp$ gcc ex2.c -o ex2
 
arliones@socrates:~/tmp$ ./ex2
 
processo 32342 antes do fork
 
processo 32342 depois do fork
 
processo 32343 depois do fork
 
processo filho pid: 32343 K: 1000
 
processo 32343 K: 1010
 
processo pai pid: 32342 K: 10
 
processo 32342 K: 20
 
arliones@socrates:~/tmp$
 
</syntaxhighlight>
 
 
 
* Analise os resultados e busque entender a diferença.
 
 
 
 
 
;Exercício fork/wait
 
 
 
Excrever um programa C que cria uma árvore de 3 processos, onde o processo A faz um ''fork()'' criando um processo B, o processo B, por sua vez, faz um ''fork()'' criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o processo XXX, filho de YYY", onde XXX e YYY são PIDs de processos. Utilizar ''wait()'' para garantir que o processo C imprima sua resposta antes do B, e que o processo B imprima sua resposta antes do A. Utilizar ''sleep()'' (man 3 sleep) para haver um intervalo de 1 segundo entre cada mensagem impressa.
 
 
 
;Exercício status/wait
 
 
 
O ''status'' passado como parâmetro à função ''wait(&status)'' é, na verdade, o mecanismo de retorno de resultado do ''wait/waitpid''. Ao retornar, esta variável contém informações sobre o resultado da execução do processo filho. Por exemplo, se um processo terminou normalmente (i.e., chamou ''exit''), o comando ''WIFEXITED(status)'' retorna ''true''. Este comando retorna ''false'' se o processo foi abortado (e.g., ''segmentation fault'') ou morto (e.g., ''kill''). Investigue no manual do wait no Linux (''man wait'') o funcionamento do comando WEXITSTATUS(status), e use-o para modificar o exercício anterior para calcular o 5!, sendo que cada processo pode executar apenas uma multiplicação.
 
 
 
{{collapse bottom}}
 
 
 
{{collapse top| bg=lightyellow | expandir=true | Estrutura de processos}}
 
 
 
== Estrutura de processos ==
 
 
 
O Linux, através da API POSIX, oferece um conjunto de funções que permite às aplicações manipular contextos, facilitando a vida do programador que quer implementar tarefas "simultâneas" dentro de um único processo, ou seja, threads. As seguintes funções e tipos estão disponíveis:
 
*'''getcontext(&a)''': salva o contexto na variável '''a''';
 
*'''setcontext(&a)''': restaura um contexto salvo anteriormente na variável '''a''';
 
*'''swapcontext(&a,&b)''': salva o contexto atual na variável '''a''' e restaura o contexto salvo anteriormente na variável '''b''';
 
*'''makecontext(&a, ...)''': ajusta parâmetros internos do contexto salvo em '''a''';
 
*'''ucontext_t''':  as variáveis '''a''' e '''b''' são do tipo '''ucontext_t'''. Este tipo armazena um contexto.
 
 
 
Busque mais informações sobre estas funções utilizando o programa manpage do Linux (ex.: man getcontext).
 
 
 
Estude o código no arquivo pingpong.c abaixo e explique seu funcionamento.
 
<syntaxhighlight lang=c>
 
#include <stdio.h>
 
#include <stdlib.h>
 
#include <ucontext.h>
 
 
 
#define STACKSIZE 32768 /* tamanho de pilha das threads */
 
 
 
/* VARIÁVEIS GLOBAIS */
 
ucontext_t cPing, cPong, cMain;
 
 
 
/* Funções-comportamento das Tarefas */
 
void f_ping(void * arg) {
 
  int i;
 
 
 
  printf("%s iniciada\n", (char *) arg);
 
 
 
  for (i=0; i<4; i++) {
 
      printf("%s %d\n", (char *) arg, i);
 
      swapcontext(&cPing, &cPong);
 
  }
 
  printf("%s FIM\n", (char *) arg);
 
 
 
  swapcontext(&cPing, &cMain);
 
}
 
 
 
void f_pong(void * arg) {
 
  int i;
 
 
 
  printf("%s iniciada\n", (char *) arg);
 
 
 
  for (i=0; i<4; i++) {
 
      printf("%s %d\n", (char *) arg, i);
 
      swapcontext(&cPong, &cPing);
 
  }
 
  printf("%s FIM\n", (char *) arg);
 
 
 
  swapcontext(&cPong, &cMain);
 
}
 
 
 
/* MAIN */
 
int main(int argc, char *argv[]) {
 
  char *stack;
 
 
 
  printf ("Main INICIO\n");
 
 
 
  getcontext(&cPing);
 
  stack = malloc(STACKSIZE);
 
  if(stack) {
 
      cPing.uc_stack.ss_sp = stack ;
 
      cPing.uc_stack.ss_size = STACKSIZE;
 
      cPing.uc_stack.ss_flags = 0;
 
      cPing.uc_link = 0;
 
  }
 
  else {
 
      perror("Erro na criação da pilha: ");
 
      exit(1);
 
  }
 
 
 
  makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");
 
 
 
  getcontext(&cPong);
 
  stack = malloc(STACKSIZE);
 
  if(stack) {
 
      cPong.uc_stack.ss_sp = stack ;
 
      cPong.uc_stack.ss_size = STACKSIZE;
 
      cPong.uc_stack.ss_flags = 0;
 
      cPong.uc_link = 0;
 
  }
 
  else {
 
      perror("Erro na criação da pilha: ");
 
      exit(1);
 
  }
 
 
 
  makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");
 
 
 
  swapcontext(&cMain, &cPing);
 
  swapcontext(&cMain, &cPong);
 
 
 
  printf("Main FIM\n");
 
 
 
  exit(0);
 
}
 
</syntaxhighlight>
 
 
 
{{collapse bottom}}
 
 
 
{{collapse top| bg=lightyellow | expandir=true | Trocas de mensagens com pipes}}
 
== Trocas de mensagens com pipes ==
 
 
 
;Troca de mensagens
 
Um mecanismo disponibilizado por sistemas UNIX para troca de mensagens entre processos é o PIPE. Pipes são mecanismos de comunicação indireta onde mensagens são trocadas através de ''mailboxes''. Cada ''mailbox'' possui um identificador único, permitindo que processos identifiquem o canal de comunicação entre eles. O fluxo de mensagens em um Pipe é:
 
*'''unidirecional''': sobre um mesmo pipe, apenas um processo envia mensagens e um processo recebe mensagens;
 
*'''FIFO''': as mensagens são entregues na ordem de envio;
 
*'''não-estruturado''': não há estrutura pré-definida para o formato da mensagem.
 
No UNIX, pipes são inicializados através da '''SystemCall''' ''pipe'', que possui a seguinte sintaxe:
 
*''int pipe(int pipefd[2])'': ''pipe'' inicializa um novo pipe no sistema e retorna, no array pipefd, os descritores identificando cada uma das pontas do pipe. A primeira posição do array, i.e. pipefd[0], recebe o descritor que pode ser aberto apenas para leitura, enquanto a segunda posição do array, i.e. pipefd[1], recebe o descritor que pode ser aberto apenas para escrita. A função retorna zero no caso de sucesso, ou -1 se ocorrer erro.
 
As primitivas send/receive para uso de um pipe no UNIX são implementadas por '''SystemCalls''' read/write, conforme segue:
 
*''ssize_t read(int fd, void *buf, size_t count)'': “puxa” dados do pipe identificado pelo descritor fd. Os dados recebidos são os apontados pelo ponteiro buf, sendo count a quantidade máxima de bytes a serem recebidos. A função retorna o número de bytes recebidos.
 
*''ssize_t write(int fd, const void *buf, size_t count)'': “empurra” dados no pipe identificado pelo descritor fd. Os dados transmitidos são os apontados pelo ponteiro buf, sendo count a quantidade de bytes a serem transmitidos. A função retorna o número de bytes transmitidos.
 
Abaixo há um exemplo de programa criando um pipe e compartilhando os descritores entre dois processos (criados via ''fork()'').
 
<syntaxhighlight lang=c>
 
#include <unistd.h> 
 
#include <fcntl.h>
 
#include <stdio.h>
 
 
 
char *message = "This is a message!!!" ;
 
 
 
main()
 
{
 
    char buf[1024] ;
 
    int fd[2];
 
    pipe(fd);    /*create pipe*/
 
    if (fork() != 0) { /* I am the parent */
 
        write(fd[1], message, strlen (message) + 1) ;
 
    }
 
    else { /*Child code */
 
        read(fd[0], buf, 1024) ;
 
        printf("Got this from MaMa!!: %s\n", buf) ;
 
    }
 
}
 
</syntaxhighlight>
 
 
 
*'''Desafio 1: construa um “pipeline”'''. Crie um programa que conecta 4 processos através de 3 pipes. Utilize ''fork()'' para criar vários processos.
 
 
 
*'''Desafio 2: cópia de arquivo'''. Projete um programa de cópia de arquivos chamado FileCopy usando pipes comuns. Esse programa receberá dois parâmetros: o primeiro é o nome do arquivo a ser copiado e o segundo é o nome do arquivo copiado. Em seguida, o programa criará um pipe comum e gravará nele o conteúdo do arquivo a ser copiado. O processo filho lerá esse arquivo do pipe e o gravará no arquivo de destino. Por exemplo, se chamarmos o programa como descrito a seguir:
 
:<syntaxhighlight lang=bash>
 
$ FileCopy entrada.txt copia.txt
 
</syntaxhighlight>
 
:o arquivo ''entrada.txt'' será gravado no pipe. O processo filho lerá o conteúdo desse arquivo e o gravará no arquivo de destino ''copia.txt''. Escreva o programa usando os pipes da API POSIX no Linux.
 
 
 
{{collapse bottom}}
 
 
 
{{collapse top| bg=lightyellow | expandir=true | Memória compartilhada entre processos}}
 
 
 
== Memória compartilhada entre processos ==
 
 
 
Outra maneira de compartilhar dados entre processos é utilizando memória compartilhada. Nestes casos, o sistema operacional precisa ser utilizado para "mapear" blocos de memória no espaço de endereçamento de cada processo (veremos mais tarde como isto é feito). Sistemas UNIX diponibilizam uma série de '''SystemCalls''' para compartilhar memória entre processos:
 
*''int shmget(key_t key, size_t size, int shmflg)'': retorna o identificador de um segmento de memória compartilhado associado a uma chave de identificação (key). Caso a chave solicitada não exista e a flag IPC_CREAT está especificada, um novo segmento de memória compartilhada é criado, com o tamanho size.
 
*''void *shmat(int shmid, const void *shmaddr, int shmflg)'': anexa/mapeia o segmento de memória especificado por shmid (obtido através de um ''shmget'') no endereço shmaddr do espaço de endereçamento do processo.
 
*''int shmdt(const void *shmaddr)'': desfaz o mapeamento do segmento de memória compartilhada que está mapeado em shmaddr.
 
*''int shmctl(int shmid, int cmd, struct shmid_ds *buf)'': realiza a ação de controle indicada por cmd sobre o segmento de memória compartilhada identificado pelo shmid. Caso o cmd utilizado necessite de parâmetros, estes são passados em buf.
 
 
 
O programa abaixo cria um novo segmento de memória compartilhada em um sistema UNIX. A função ''ftok'' é utilizada para gerar uma chave única de identificação do segmento de memória (veja "man ftok"). O programa ipcs pode ser utilizado para verificar os segmentos de memória compartilhada disponíveis no sistema.
 
 
 
<syntaxhighlight lang=c>
 
#include <stdio.h>
 
#include <stdlib.h>
 
#include <string.h>
 
#include <sys/types.h>
 
#include <sys/ipc.h>
 
#include <sys/shm.h>
 
 
#define SHM_SIZE 1024  /* make it a 1K shared memory segment */
 
 
int main(void)
 
{
 
 
      key_t key;
 
      int shmid;
 
      char *data;
 
      int mode;
 
 
      /* make the key: */
 
      if ((key = ftok("/tmp", 'X')) == -1) {
 
            perror("ftok");
 
            exit(1);
 
      }
 
 
      /* create the shared memory segment: */
 
      if ((shmid = shmget(key, SHM_SIZE, 0644 | IPC_CREAT )) == -1) {
 
            perror("shmget");
 
            exit(1);
 
      }
 
 
      return(0);
 
}
 
</syntaxhighlight>
 
 
 
O programa abaixo manipula o segmento criado pelo programa anterior. Perceba que o programa utiliza a função ''ftok'' com os mesmos parâmetros passados na criação. O sistema operacional utiliza esta chava única para identificar o segmento de memória a ser utilizado. Se o programa abaixo é executado com um string como parâmetro (ex.: "./shm_test abc123"), ele escreve este parâmetro no segmento de memória. Caso seja executado sem parâmetros (ex.: "./shm_test"), o programa imprime o conteúdo da memória compartilhada.
 
 
 
<syntaxhighlight lang=c>
 
#include <stdio.h>
 
#include <stdlib.h>
 
#include <string.h>
 
#include <sys/types.h>
 
#include <sys/ipc.h>
 
#include <sys/shm.h>
 
 
#define SHM_SIZE 1024  /* make it a 1K shared memory segment */
 
 
int main(int argc, char *argv[])
 
{
 
 
      key_t key;
 
      int shmid;
 
      char *data;
 
      int mode;
 
 
 
      /* make the key: */
 
      if ((key = ftok("/tmp", 'X')) == -1) {
 
            perror("ftok");
 
            exit(1);
 
      }
 
 
 
      /* connect to the segment.
 
      NOTE: There's no IPC_CREATE. What happens if you place IPC_CREATE here? */
 
      if ((shmid = shmget(key, SHM_SIZE, 0644)) == -1) {
 
            perror("shmget");
 
            exit(1);
 
      }
 
 
 
    /* attach to the segment to get a pointer to it: */
 
        data = shmat(shmid, (void *)0, 0);
 
        if (data == (char *)(-1)) {
 
            perror("shmat");
 
            exit(1);
 
        }
 
 
 
        /* read or modify the segment, based on the command line: */
 
        if (argc == 2) {
 
            printf("writing to segment: \"%s\"\n", argv[1]);
 
            strncpy(data, argv[1], SHM_SIZE);
 
        } else
 
            printf("segment contains: \"%s\"\n", data);
 
 
 
        /* detach from the segment: */
 
        if (shmdt(data) == -1) {
 
            perror("shmdt");
 
            exit(1);
 
        }
 
 
      return(0);
 
}
 
</syntaxhighlight>
 
 
 
*'''Desafio1: destrua um shm.''' Crie um programa que destrua o shm utilizado nos programas anteriores. Para isso utilize ''shmctl'' com o parâmetro apropriado (veja "man shmctl").
 
 
 
<syntaxhighlight lang=c>
 
#include <stdio.h>
 
#include <stdlib.h>
 
#include <string.h>
 
#include <sys/types.h>
 
#include <sys/ipc.h>
 
#include <sys/shm.h>
 
 
#define SHM_SIZE 1024  /* make it a 1K shared memory segment */
 
 
int main(void)
 
{
 
      key_t key;
 
      int shmid;
 
      char *data;
 
      int mode;
 
 
      /* make the key: */
 
      if ((key = ftok("/tmp", 'X')) == -1) {
 
            perror("ftok");
 
            exit(1);
 
      }
 
 
      /* connect to memory segment: */
 
      if ((shmid = shmget(key, SHM_SIZE, 0644)) == -1) {
 
            perror("shmget");
 
            exit(1);
 
      }
 
 
    /* delete he segment */
 
      if( shmctl(shmid, IPC_RMID, NULL) == -1) {
 
            perror("shmctl");
 
            exit(1);
 
      }
 
 
      return(0);
 
}
 
</syntaxhighlight>
 
 
 
{{collapse bottom}}
 
 
 
{{collapse top| bg=lightyellow | expandir=true | POSIX Threads}}
 
 
 
== POSIX Threads ==
 
 
 
A biblioteca POSIX Threads, ou simplesmente ''pthreads'', é parte do padrão POSIX para programar utilizando threads. O padrão POSIX.1c define a API para criação e manipulação de threads. Esta API é encontrada na maioria dos sistemas baseados no Unix, como Linux, Mac OS X, Solaris, entre outros. Também existem alternativas adaptando a API para sistemas Windows, como a pthreads-w32.
 
 
 
A API da pthreads inclui métodos para criar, manipular e destruir threads, além de outras estruturas de dados para sincronizar as threads, incluindo implementações de mutexes e variáveis de condição.
 
 
 
A API POSIX ''semaphore'', utilizada para sincronização de processos ou threads, também funciona em conjunto com a ''pthreads'', embora sua implementação esteja definida em outro padrão, o POSIX.1b.
 
 
 
Programas em C/C++ que utilizarão a ''pthreads'' devem incluir o cabeçalho ''pthread.h'':
 
 
 
<syntaxhighlight lang=c>
 
#include <pthread.h>
 
</syntaxhighlight>
 
 
 
;Principais elementos da API
 
 
 
* pthread_t (struct)
 
:Estrutura que armazena dados/atributos de uma pthread.
 
 
 
* pthread_create
 
: Função que cria uma thread, incializando-a e deixando-a pronta para executar. O código abaixo apresenta um exemplo simples de um programa utilizando pthreads.
 
 
 
<syntaxhighlight lang=c>
 
 
 
#include <pthread.h>
 
 
 
pthread_t threads[2];
 
 
 
void *thread_func(void *arg) {
 
    // ...
 
}
 
 
 
int main(int argc, char **argv) {
 
    int i;
 
    for(i = 0; i < 2; i++) {
 
        pthread_create(&(threads[i]), NULL, thread_func,NULL);
 
    }
 
    for(i = 0; i < 2; i++) {
 
        pthread_join(threads[i], NULL);
 
    }
 
}
 
 
 
</syntaxhighlight>
 
 
 
 
 
* pthread_join
 
: Bloqueia execução de uma thread até que outra thread termine, implementando um comportamento similar à chamada de sistema ''wait'' usada em processos Unix.
 
 
 
* pthread_exit
 
: Encerra a execução de uma thread. A chamada a esta função por uma pthread gera a liberação de outras threads que estejam, eventualmente, bloqueadas nela por uma chamada ''pthread_join''.
 
 
 
O código abaixo apresenta um programa completo utilizando pthreads, onde threads recebem argumentos.
 
 
 
<syntaxhighlight lang=c>
 
 
 
#include <stdlib.h>
 
#include <stdio.h>
 
#include <pthread.h>
 
 
 
typedef struct {
 
    int idx, length;
 
} thread_arg, *ptr_thread_arg;
 
 
 
pthread_t threads[2];
 
 
 
void *thread_func(void *arg) {
 
    ptr_thread_arg targ = (ptr_thread_arg) arg;
 
    int i;
 
 
 
    for(i = targ->idx; i < (targ->idx + targ->length); i++)
 
        printf(“Thread %d – value %d\n”, pthread_self(), i);
 
}
 
 
 
int main(int argc, char **argv) {
 
    thread_arg arguments[2];
 
    int i;
 
    for(i = 0; i < 2; i++) {
 
        arguments[i].idx = i * 10;
 
        arguments[i].length = 10;
 
        pthread_create(&(threads[i]), NULL, thread_func, &(arguments[i]));
 
    }
 
    for(i = 0; i < 2; i++) {
 
        pthread_join(threads[i], NULL);
 
    }
 
}
 
 
 
</syntaxhighlight>
 
 
 
Ao compilar um programa com pthreads é necessário "linkar" com a biblioteca ''libpthread''. Para isso, deve ser usando a opção -lpthread com o gcc.
 
 
 
<syntaxhighlight lang=bash>
 
gcc ... -lpthread
 
</syntaxhighlight>
 
 
 
;Exercícios
 
 
 
* Implemente o exemplo do Ping e Pong utilizando pthreads.
 
 
 
{{collapse bottom}}
 
 
 
{{collapse top| bg=lightyellow | expandir=true | Problemas clássicos de coordenação de processos}}
 
 
 
== Problemas clássicos de coordenação de processos ==
 
 
 
A ser divulgado.
 
{{collapse bottom}}
 
 
 
{{collapse top| bg=lightyellow | expandir=true | Programação concorrente}}
 
== Programação concorrente ==
 
 
 
A ser divulgado.
 
{{collapse bottom}}
 
 
 
{{collapse top| bg=lightyellow | expandir=true | Tradução de endereços com paginação}}
 
== Tradução de endereços com paginação ==
 
 
 
A ser divulgado.
 
{{collapse bottom}}
 
 
 
{{collapse top| bg=lightyellow | expandir=true | Permissões de sistema de arquivos no Linux}}
 
== Permissões de sistema de arquivos no Linux ==
 
 
 
A ser divulgado.
 
{{collapse bottom}}
 
 
 
=Projetos=
 
 
 
{{collapse top| bg=lightyellow | expandir=true | 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]].
 
{{collapse bottom}}
 
 
 
{{collapse top| bg=lightyellow | expandir=true | 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.
 
 
 
[[Arquivo: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.
 
 
 
[[Arquivo: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 [http://docente.ifsc.edu.br/arliones.hoeller/sop/TerminALL-VAZIO.tgz aqui].
 
 
 
{{collapse bottom}}
 
 
 
{{collapse top| bg=lightyellow | expandir=true | Programação Concorrente}}
 
== Programação Concorrente ==
 
 
 
A ser divulgado.
 
{{collapse bottom}}
 
 
 
{{collapse top| bg=lightyellow | expandir=true | Mapeamento de memória}}
 
== Mapeamento de memória ==
 
 
 
A ser divulgado.
 
{{collapse bottom}}
 
  
{{collapse top| bg=lightyellow | expandir=true | Implementação de driver Linux}}
+
A partir de 2017, o conteúdo deste curso está sendo publicado aos alunos via Moodle.
== Implementação de driver Linux ==
 
  
A ser divulgado.
+
[http://wiki.sj.ifsc.edu.br/index.php?title=SOP-EngTel_(p%C3%A1gina)&oldid=123789 Clique aqui] para acessar as edições antigas desta disciplina.
{{collapse bottom}}
 

Edição atual tal como às 10h24min de 7 de fevereiro de 2019

Sistemas Operacionais

Turma 2019-1

Clique aqui Edição 2019-1


Turma 2018-2

  • Professor: André D'Amato
  • Encontros: Segundas às 15:40 e quintas às 13:30 no LabCad.

Clique aqui Edição 2018-2


Turma 2018-1

  • Professor: André D'Amato
  • Encontros: Segundas às 7:30 e sextas às 9:40 no Laboratório de Redes II.

Clique aqui Edição 2018-1



  • Professor: Arliones Hoeller
  • Encontros: Quartas e sextas às 7:30 no Laboratório de Redes II.

A partir de 2017, o conteúdo deste curso está sendo publicado aos alunos via Moodle.

Clique aqui para acessar as edições antigas desta disciplina.