Mudanças entre as edições de "SOP29005-2020-1"

De MediaWiki do Campus São José
Ir para navegação Ir para pesquisar
 
(144 revisões intermediárias pelo mesmo usuário não estão sendo mostradas)
Linha 490: Linha 490:
 
*[https://www.dropbox.com/s/abutv2ajve7i04k/shared_mem_matrix.c?dl=0]
 
*[https://www.dropbox.com/s/abutv2ajve7i04k/shared_mem_matrix.c?dl=0]
  
=AULA 9 - Dia 10/03/2020=
+
=AULA 9 - Dia 13/03/2020=
  
 
==Objetivos/Conteúdos==
 
==Objetivos/Conteúdos==
Linha 552: Linha 552:
 
* Slides do Capítulo 4 do livro do Silberschatz
 
* Slides do Capítulo 4 do livro do Silberschatz
  
=AULA 10 ?? - REMOTA - Dia 20/03/2020=
+
=AULA 10 ?? - REMOTA - Dia 24/03/2020=
 
 
 
==Objetivos/Conteúdos==
 
==Objetivos/Conteúdos==
  
*Webconf
+
* Webconf
*Revisão de  Threads
+
* Revisão de  Threads
*Laboratório de Thread de Applicação
+
* Laboratório de Thread de Applicação
  
 
==Slides para esta aula==
 
==Slides para esta aula==
Linha 568: Linha 567:
 
{{collapse top| bg=lightyellow | expandir=true | Threads de aplicação}}
 
{{collapse top| bg=lightyellow | expandir=true | Threads de aplicação}}
  
== Threads de aplicação ==
+
==Threads de aplicação==
 
 
 
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:
 
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''';
+
* '''getcontext(&a)''': salva o contexto na variável '''a''';
*'''setcontext(&a)''': restaura um contexto salvo anteriormente 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''';
+
* '''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''';
+
* '''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.
+
* '''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).
 
Busque mais informações sobre estas funções utilizando o programa manpage do Linux (ex.: man getcontext).
Linha 664: Linha 662:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
*Exercício 1: Primeiramente compile e execute o código. Agora estude o código e entenda completamente o seu funcionamento. Explique em DETALHES o código, comentando todas as linhas. Na seção de diagrama do seu relatório, desenhe um diagrama de funcionamento do código para mostrar exatamente como acontece a troca de contexto entre as threads.
+
* Exercício 1: Primeiramente compile e execute o código. Agora estude o código e entenda completamente o seu funcionamento. Explique em DETALHES o código, comentando todas as linhas. Na seção de diagrama do seu relatório, desenhe um diagrama de funcionamento do código para mostrar exatamente como acontece a troca de contexto entre as threads.
*Exercício 2: Acrescente um procedimento '''f_new''' que receba 4 strings como parâmetros e imprima todas na tela. Antes do final da execução do main faça uma mudança de contexto para chamar o procedimento criado.
+
* Exercício 2: Acrescente um procedimento '''f_new''' que receba 4 strings como parâmetros e imprima todas na tela. Antes do final da execução do main faça uma mudança de contexto para chamar o procedimento criado.
  
<!--
+
<!--<syntaxhighlight lang=c>
<syntaxhighlight lang=c>
 
 
#include <stdio.h>
 
#include <stdio.h>
 
#include <stdlib.h>
 
#include <stdlib.h>
Linha 775: Linha 772:
 
   exit(0);
 
   exit(0);
 
}
 
}
</syntaxhighlight>
+
</syntaxhighlight>-->
-->
+
* Exercício 3: O que acontece se um dos threads é colocado para dormir? Todos os demais threads param a sua execução.
*Exercício 3: O que acontece se um dos threads é colocado para dormir? Todos os demais threads param a sua execução.
 
  
*Exercício 4: Note que um thread somente deixa a execução para outro thread de forma explícita. Será que é possível realizar um escalonamento de threads de forma similar ao que o kernel faz com os processos? Ver  http://www.cplusplus.com/forum/unices/6452/
+
* Exercício 4: Note que um thread somente deixa a execução para outro thread de forma explícita. Será que é possível realizar um escalonamento de threads de forma similar ao que o kernel faz com os processos? Ver  http://www.cplusplus.com/forum/unices/6452/
 
{{collapse bottom}}
 
{{collapse bottom}}
  
Linha 1 212: Linha 1 208:
 
{{collapse bottom}}
 
{{collapse bottom}}
  
=AULA 12 ?? - REMOTA - Dia 27/03/2020=
+
=AULA 12 ?? - REMOTA - Dia 3/04/2020=
 +
==Objetivos/Conteúdos==
 +
 
 +
** Conceito de Preempção
 +
** Critérios de Escalonamento
 +
* Algoritmos de Escalonamento
 +
** FCFS
 +
** Menor-Job-Primeiro
 +
** Prioridades
 +
** Round Robin
 +
 
 +
==Slides USados mna Aula==
 +
 
 +
** Slides do Livro do Professor Maziero e do Prof.Arliones
 +
 
 +
==Referências==
 +
 
 +
** Cap.51, 5.2 e 5.3 do Livro de Silberschatz
 +
** [https://www.os-book.com/OS9/slide-dir/ Slides Silberschatz]
 +
** [http://docente.ifsc.edu.br/andre.damato/sop2018/SOP2018-parte2.pdf Apresentação sobre Gerenciamento de Processos]
 +
** Cap.6 do Livro do Prof.Maziero (http://wiki.inf.ufpr.br/maziero/doku.php?id=socm:start)
 +
** https://www.geeksforgeeks.org/vector-in-cpp-stl/
 +
 
 +
=AULA 13 ?? - REMOTA - Dia 14/04/2020=
 +
 
 +
==Objetivos/Conteúdos==
 +
 
 +
*Exemplo do Escalonador RR
 +
 
 +
==Código de Exemplo==
 +
 
 +
*Criar um relógio global para as demonstraçoes de funcionamento da API que foi criada
 +
 
 +
<syntaxhighlight lang=c>
 +
 
 +
/**
 +
  User-level threads example.
 +
 +
  Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)
 +
*/
 +
#include <stdio.h>
 +
#include <stdlib.h>
 +
#include <ucontext.h> /* for makecontext/swapcontext routines */
 +
#include <queue> /* C++ STL queue structure */
 +
#include <vector>
 +
 +
#include<signal.h>
 +
#include<unistd.h>
 +
#include <ucontext.h>
 +
#include <sys/time.h>
 +
 +
#define TIME_SLICE 1
 +
 +
typedef void (*threadFn)(void);
 +
 +
class thread_cb { // bloco de controle do thread
 +
  int id_thread;
 +
  public:
 +
  ucontext_t contexto;
 +
  //metodos que manipulam o thread control block
 +
  thread_cb(threadFn p, int id) //construtor
 +
  {
 +
  int stackLen=4*1024;
 +
  char *stack=new char[stackLen];
 +
  getcontext(&contexto);
 +
  contexto.uc_stack.ss_sp=stack;
 +
  contexto.uc_stack.ss_size=stackLen;
 +
  contexto.uc_stack.ss_flags=0;
 +
  makecontext(&contexto,p,0);
 +
  id_thread = id;
 +
  };
 +
  ucontext_t *get_context() {
 +
    return &contexto;
 +
  };
 +
};
 +
 +
std::queue<class thread_cb *> ready_pool; // fila de pronto
 +
 +
int id_thread = 0;
 +
int id1,id2,id3;
 +
 
 +
class thread_cb *curr_thread=NULL;
 +
 +
int add_thread(threadFn func) //criar thread e retornar o id do thread criad
 +
{
 +
  class thread_cb *p = new thread_cb(func, ++id_thread);
 +
  ready_pool.push(p);
 +
  return id_thread;
 +
}
 +
 +
 +
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)
 +
{
 +
  if (old_task!=NULL)
 +
      swapcontext(old_task, new_task);
 +
  else
 +
      setcontext(new_task);
 +
}
 +
 +
void scheduler_rr()
 +
{
 +
    class thread_cb *next,*last;
 +
 +
 +
  if(curr_thread!=NULL) {
 +
      printf("Aqui\n");
 +
      ready_pool.push(curr_thread);
 +
      last=curr_thread;
 +
      next=ready_pool.front();
 +
      ready_pool.pop();
 +
      curr_thread=next;   
 +
      dispatcher(last->get_context(), curr_thread->get_context());
 +
  } else {
 +
      next=ready_pool.front();
 +
      ready_pool.pop();
 +
      curr_thread = next;
 +
      dispatcher(NULL, next->get_context());
 +
  }
 +
}
 +
 +
void sig_handler(int signo)
 +
{
 +
 +
  printf("SOP da Turma 2019-2: recebido SIGALRM\n");
 +
  alarm(TIME_SLICE); 
 +
 +
if (ready_pool.empty()) {
 +
printf("Nothing more to run!\n");
 +
exit(0);
 +
}
 +
  scheduler_rr();
 +
}
 +
 +
void preparar_handler()
 +
{
 +
  if (signal(SIGALRM, sig_handler) == SIG_ERR) {
 +
      printf("\nProblemas com SIGUSR1\n");
 +
      exit(-1);
 +
  }
 +
  alarm(TIME_SLICE);
 +
}
 +
 
 +
 
 +
 
 +
void runA(void)
 +
{
 +
  int x=1;
 +
  for (;;) {
 +
      x++;
 +
      printf("Thread A x=%d\n", x);
 +
  }
 +
}
 +
 +
void runB(void)
 +
{
 +
    int x=1;
 +
    for (;;) {
 +
        x++;
 +
        printf("Thread B x=%d\n", x);
 +
        if(x>90000000L)
 +
            yield_thread(); // abandonar a CPU
 +
    }
 +
}
 +
 
 +
void runC(void)
 +
{
 +
    int x=1;
 +
    for (;;) {
 +
        x++;
 +
        printf("Thread B x=%d\n", x);
 +
        if (x>1000000L) //consultar um timer global
 +
            del_thread(id2);
 +
    }
 +
}
 +
 
 +
main()
 +
{
 +
    id1 = add_thread(runA);
 +
    id2 = add_thread(runB);
 +
    id3 = add_thread(runC);
 +
    preparar_handler();
 +
    for(;;);
 +
}
 +
</syntaxhighlight>
 +
 
 +
=AULA 14 ?? - REMOTA - Dia 15/04/2020=
 +
 
 +
==Objetivos/Conteúdos==
 +
 
 +
*aula somte para dúvidas...
 +
 
 +
=AULA 15 ?? - REMOTA - Dia 17/04/2020=
 +
 
 +
==Objetivos/Conteúdos==
 +
 
 +
*Mecanismos de Sncronização
 +
 
 +
==Material de Referência==
 +
 
 +
*[http://professor.unisinos.br/barbosa/SO/ch6br.ppt Slides Silberschatz (tradução Prof.Cristiano Costa)]
 +
*[http://wiki.inf.ufpr.br/maziero/lib/exe/fetch.php?media=socm:socm-slides-10.pdf Slides Cap.10 Livro Prof.Maziero]
 +
*[http://wiki.inf.ufpr.br/maziero/lib/exe/fetch.php?media=socm:socm-texto-10.pdf Cap.10 Livro Prof.Maziero]
 +
 
 +
==Exemplo de remoção de itens de uma lista do stl==
 +
 
 +
<syntaxhighlight lang=c>
 +
 
 +
#include <list>
 +
#include <iostream>
 +
using namespace std;
 +
 
 +
int main()
 +
{
 +
    struct tcb{
 +
        int id;
 +
    }  *p1,*p2,*p3;
 +
    p1=new struct tcb;
 +
    p1->id=3;
 +
    p2=new struct tcb;
 +
    p2->id=4;
 +
    p3=new struct tcb;
 +
    p3->id=7;
 +
 
 +
    list<struct tcb *> minhalista{ p1,p2,p3 };
 +
    list<struct tcb *>::iterator it;
 +
 
 +
    it= minhalista.begin();
 +
    while(it != minhalista.end()) {
 +
        if ((*it)->id==4) {
 +
            it = minhalista.erase(it);
 +
        } else
 +
            it++;
 +
    }
 +
 
 +
    //imprimindo os ids de quem sobrou
 +
    it= minhalista.begin();
 +
    while(it != minhalista.end()) {
 +
        cout << "ID = " << (*it)->id << "\n";
 +
        it++;
 +
    }
 +
 
 +
    return 0;
 +
}
 +
 
 +
</syntaxhighlight>
 +
 
 +
=AULA 16 ?? - REMOTA - Dia 24/04/2020=
 +
 
 +
==Objetivos/Conteúdos==
 +
 
 +
*Mecanismos de Sncronização
 +
**Conceito de Condição de Corrida
 +
**Conceito de Exclusão Mútua e Seção Crítica
 +
 
 +
 
 +
==Material de Referência==
 +
 
 +
*[http://professor.unisinos.br/barbosa/SO/ch6br.ppt Slides Silberschatz (tradução Prof.Cristiano Costa)]
 +
*[http://wiki.inf.ufpr.br/maziero/lib/exe/fetch.php?media=socm:socm-slides-10.pdf Slides Cap.10 Livro Prof.Maziero]
 +
*[http://wiki.inf.ufpr.br/maziero/lib/exe/fetch.php?media=socm:socm-texto-10.pdf Cap.10 Livro Prof.Maziero]
 +
 
 +
=AULA 17 ?? - NÃO SÍNCRONA- Dia 28/04/2020=
 +
 
 +
==Objetivos/Conteúdos==
 +
 
 +
*Mecanismos de Sincronização
 +
**Race Condition
 +
**Exclusão Mútua
 +
**Soluções Triviais
 +
**Algoritmo de Peterson
 +
**Instruções Atômicas
 +
 
 +
==Material de Referência==
 +
 
 +
Vídeos elaborados pelo Prof.Eraldo usando os slides/Capítulo 10 do Livro Prof. Carlos Maziero
 +
 
 +
*[https://drive.google.com/file/d/1p5ZhP_n9IerGaGraX-XaVE2Mv9OQhSO7/view?usp=sharing  Race Condition]
 +
*[https://drive.google.com/file/d/1QDA6rcAEnWzvD-rWInAn_B-xTwTYp0ON/view?usp=sharing  Exclusão Mútua]
 +
*[https://drive.google.com/file/d/1uRpTjZKiVKMXKrbExLZ_Fu2hJ14_VjO4/view?usp=sharing  Algoritmo de Peterson e Instruções Atômicas]
 +
*[https://drive.google.com/file/d/1ctdQZknUDpsD-3doAkCAtFTBNSeg01Mf/view?usp=sharing  Exclusão Mútua usando Instrução Swap]
 +
 
 +
=REUNIÃO - Dia 19/05/2020=
 +
 
 +
*ANPs
 +
 
 +
=AULA - SÍNCRONA- Dia 22/5/2020=
 +
 
 +
==Objetivos==
 +
 
 +
* Revisão de Sistema Computacional (1.2 e 1.3 do Livro  do Silberchatz)
 +
* Revisão de Serviços do Sistema Operacional
 +
* Revisão: PARTE 2A: Gerenciamento de Processos (cap.3 Silberchatz ed.8)
 +
** 3.1.Conceito de Processo (seção do livro)
 +
** 3.2.Escalonamento de Processos  (seção do livro)
 +
** 3.3.Operações sobre Processos  (seção do livro)
 +
** 4.1.Visão Geral de Threads  (seção do livro)
 +
 
 +
=AULA - NÃO SÍNCRONA - Dia 22/5/2020=
 +
 
 +
==Objetivos==
 +
 
 +
* Revisão: PARTE 2A: Gerenciamento de Processos (cap.3 Silberchatz ed.8)
 +
 
 +
==Material Sugerido para Revisão==
 +
 
 +
*Aulas Prof.Isidro da Universidade do ABC:
 +
**[https://www.youtube.com/watch?v=V6BwPxmdmDI Gerenciamento de Processos]
 +
**[https://www.youtube.com/watch?v=lPLl-5Wk7GQ Processos parte 2 - Comunicação entre Processos]
 +
**[https://www.youtube.com/watch?v=x1eHjSOQiQE Threads]
 +
*Capítulos 3 e 4 do Silberschatz
 +
 
 +
=AULA SÍNCRONA - Dia 26/5/2020=
 +
==Objetivos==
 +
 
 +
* Uso da biblioteca libpthreads
 +
* Revisão de conceitos associados a threads
 +
 
 +
==Laboratório de libpthreads==
 +
==Parte 1==
 +
 
 +
;POSIX ThreadsA API POSIX disponibiliza uma biblioteca de threads chamada pthread. As threads são implementadas pela estrutura ''pthread_t'', e manipuladas pelas funções (acesse as man-pages das chamadas para maiores detalhes):
 +
* ''pthread_create'': cria uma thread;
 +
* ''pthread_kill'': força a terminação de uma thread;
 +
* ''pthread_join'': sincroniza o final de uma thread (qual a diferença/semelhança com o ''wait'' que usamos para processos?);
 +
* ''pthread_exit'': finaliza uma thread.
 +
Para utilizar estas funções é necessário linkar o programa à libpthread (''-lpthread'').
 +
 
 +
 
 +
==Parte 2==
 +
Exemplo básico de criação de threads do no [https://computing.llnl.gov/tutorials/pthreads/#Management POSIX Threads Programming]
 +
 
 +
# Implemente o programa em [https://computing.llnl.gov/tutorials/pthreads/samples/hello.c]
 +
# Compilar com:<br  />
 +
 
 +
  gcc -lpthread hello.c -o hello
 +
# Executar:<br  />
 +
 
 +
  ./hello
 +
 
 +
 
 +
 
 +
 
 +
==Parte 3==
 +
Como o Linux enxerga os pthreads
 +
 
 +
# Faça uma modificação da função associada aos threads colocando um loop infinito após o Hello World
 +
# O Linux "enxerga" estes threads? Confira com o comando htop
 +
 
 +
 
 +
==Parte 4==
 +
Observe o código abaixo.
 +
 
 +
<syntaxhighlight lang=cpp>
 +
 
 +
#include <stdio.h>
 +
 
 +
#define TAM 3
 +
 
 +
long double  vetor_A[TAM];
 +
 
 +
 
 +
void calcular_elemento(int i)
 +
{
 +
  double x;
 +
 
 +
  for (x=0;x<=100;x=x+0.0000001){
 +
    vetor_A[i] = vetor_A[i] + ((i+1)*x + (i+3))*0.0000001;
 +
  } 
 +
}
 +
 +
int main()
 +
{
 +
  int i;
 +
 
 +
  /* solução sequencial */
 +
  for (i=0;i<TAM;i++) {
 +
        calcular_elemento(i);
 +
  } 
 +
}
 +
</syntaxhighlight>
 +
 
 +
 
 +
# Execute o programa com o auxílio do programa time. Anote o tempo de execução.<br  />
 +
 
 +
  time a.out
 +
# Faça uma modificação para que o problema seja decomposto em threads explorando o número de cores físicos da sua máquina.
 +
# Execute o programa com o auxílio do programa time. Compare com o tempo de execução sequencial.<br  />
 +
 
 +
  time a.out
 +
# Faça uma variação do programa multithread para que o thread associado a função main aguarde os demais threads computando então a soma de todos os elementos do vetor. Veja exemplo em [https://computing.llnl.gov/tutorials/pthreads/#Joining]
 +
 
 +
 
 +
==Parte 5==
 +
Repita o procedimeto da parte 4 para explorar os cores lógicos. Existe ganho real? Discuta.
 +
 
 +
=AULA SÍNCRONA - Dia 5/6/2020=
  
 
==Objetivos/Conteúdos==
 
==Objetivos/Conteúdos==
  
**Conceito de Preempção
+
*Revisão de Mecanismos de Sincronização (já proposto em aula anterior)
**Critérios de Escalonamento
+
**Race Condition
*Algoritmos de Escalonamento
+
**Exclusão Mútua
**FCFS
+
**Soluções Triviais
**Menor-Job-Primeiro
+
**Algoritmo de Peterson
**Prioridades
+
**Instruções Atômicas
**Round Robin
+
*Laboratório
 +
 
 +
==Material de Referência==
 +
 
 +
Vídeos elaborados pelo Prof.Eraldo usando os slides/Capítulo 10 do Livro Prof. Carlos Maziero
 +
 
 +
*[https://drive.google.com/file/d/1p5ZhP_n9IerGaGraX-XaVE2Mv9OQhSO7/view?usp=sharing  Race Condition]
 +
*[https://drive.google.com/file/d/1QDA6rcAEnWzvD-rWInAn_B-xTwTYp0ON/view?usp=sharing  Exclusão Mútua]
 +
*[https://drive.google.com/file/d/1uRpTjZKiVKMXKrbExLZ_Fu2hJ14_VjO4/view?usp=sharing  Algoritmo de Peterson e Instruções Atômicas]
 +
*[https://drive.google.com/file/d/1ctdQZknUDpsD-3doAkCAtFTBNSeg01Mf/view?usp=sharing  Exclusão Mútua usando Instrução Swap]
 +
 
 +
Slides do Livro do Silberschatz
 +
 
 +
*[https://www.os-book.com/OS9/slide-dir/index.html]
 +
 
 +
==Laboratório de Race Condition, Algoritmo de Paterson e Mecanismos de Hardware (9/6?)==
 +
 
 +
# Implemente e execute várias o exemplo abaixo de 2 threads acessando uma área comum de dados (conta). Estime o valor final na variável conta.
 +
Compare os resultados obtidos.
 +
 
 +
<syntaxhighlight lang=cpp>
 +
 
 +
#include <pthread.h>
 +
#include <stdio.h>
 +
#include <stdlib.h>
 +
#define NUM_THREADS 2
 +
 
 +
/* based on https://computing.llnl.gov/tutorials/pthreads/samples/join.c */
 +
 
 +
double conta=0;
 +
 
 +
void *Thread1_DepositarConta(void *t)
 +
{
 +
  int i;
 +
  long tid;
 +
 
 +
  tid = (long)t;
 +
  printf("Thread %ld iniciando...\n",tid);
 +
  for (i=0; i<10000; i++){
 +
  conta = conta+1;
 +
  }
 +
  pthread_exit((void*) t);
 +
}
 +
 
 +
void *Thread2_DepositarConta(void *t)
 +
{
 +
  int i;
 +
  long tid;
 +
 
 +
  tid = (long)t;
 +
  printf("Thread %ld iniciando...\n",tid);
 +
  for (i=0; i<10000; i++){
 +
  conta = conta+1;
 +
  }
 +
  pthread_exit((void*) t);
 +
}
 +
 
 +
int main (int argc, char *argv[])
 +
{
 +
  pthread_t thread[NUM_THREADS];
 +
  pthread_attr_t attr;
 +
  int rc;
 +
  long t;
 +
  void *status;
 +
 
 +
  /* Initialize and set thread detached attribute */
 +
  pthread_attr_init(&attr);
 +
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
 +
 
 +
  for(t=0; t<NUM_THREADS; t++) {
 +
      printf("Main: criando threads %ld\n", t);
 +
      if(t==1)
 +
        rc = pthread_create(&thread[t], &attr, Thread1_DepositarConta, (void *)t);
 +
      else
 +
        rc = pthread_create(&thread[t], &attr, Thread2_DepositarConta, (void *)t);         
 +
      if (rc) {
 +
        printf("ERROR; return code from pthread_create() is %d\n", rc);
 +
        exit(-1);
 +
      }
 +
  }
 +
 
 +
  /* Free attribute and wait for the other threads */
 +
  pthread_attr_destroy(&attr);
 +
  for(t=0; t<NUM_THREADS; t++) {
 +
      rc = pthread_join(thread[t], &status);
 +
      if (rc) {
 +
        printf("ERROR; return code from pthread_join() is %d\n", rc);
 +
        exit(-1);
 +
      }
 +
      printf("Main: esperando thread %ld having a status of %ld\n",t,(long)status);
 +
  }
 +
 +
  printf("Main: Programa terminado - conta = %lf\n", conta);
 +
  pthread_exit(NULL);
 +
}
 +
</syntaxhighlight>
 +
 
 +
# Reimplemente o programa acima com controle da entrada e saída da região crítica usando o algoritmo de Paterson.
 +
# Reimplemente o programa acima com controle da entrada e saída da região crítica usando uma instrução simulada de TEST AND SET. Notar que neste caso
 +
a atomicidade da instrução não é garantida.
 +
 
 +
=AULA SÍNCRONA - Dia 19/06/2020=
 +
 
 +
==Objetivos==
 +
 
 +
*Laboratório: Race Condition e Mutex
 +
**Explorar o problema de Race Condition
 +
**Resolver o problema de Race Condition com o Mutex
 +
*Conceito de Semáforo
 +
 
 +
==Laboratório Parte 1==
 +
 
 +
Estude o código abaixo e infira qual o valor da conta ao final da execução do programa.
 +
 
 +
<syntaxhighlight lang=cpp>
 +
#include <pthread.h>
 +
#include <stdio.h>
 +
#include <stdlib.h>
 +
#define NUM_THREADS 2
 +
 
 +
double conta=0;
 +
 
 +
void *Thread1_DepositarConta(void *t)
 +
{
 +
  int i;
 +
  long tid;
 +
 
 +
  tid = (long)t;
 +
  printf("Thread %ld iniciando...\n",tid);
 +
  for (i=0; i<10000; i++){
 +
  conta = conta+1;
 +
  }
 +
  pthread_exit((void*) t);
 +
}
 +
 
 +
void *Thread2_DepositarConta(void *t)
 +
{
 +
  int i;
 +
  long tid;
 +
 
 +
  tid = (long)t;
 +
  printf("Thread %ld iniciando...\n",tid);
 +
  for (i=0; i<10000; i++){
 +
  conta = conta+1;
 +
  }
 +
  pthread_exit((void*) t);
 +
}
 +
 
 +
int main (int argc, char *argv[])
 +
{
 +
  pthread_t thread[NUM_THREADS];
 +
  pthread_attr_t attr;
 +
  int rc;
 +
  long t;
 +
  void *status;
 +
 
 +
  /* Initialize and set thread detached attribute */
 +
  pthread_attr_init(&attr);
 +
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
 +
 
 +
  for(t=0; t<NUM_THREADS; t++) {
 +
      printf("Main: criando threads %ld\n", t);
 +
      if(t==1)
 +
        rc = pthread_create(&thread[t], &attr, Thread1_DepositarConta, (void *)t);
 +
      else
 +
        rc = pthread_create(&thread[t], &attr, Thread2_DepositarConta, (void *)t);         
 +
      if (rc) {
 +
        printf("ERROR; return code from pthread_create() is %d\n", rc);
 +
        exit(-1);
 +
      }
 +
  }
 +
 
 +
  /* Free attribute and wait for the other threads */
 +
  pthread_attr_destroy(&attr);
 +
  for(t=0; t<NUM_THREADS; t++) {
 +
      rc = pthread_join(thread[t], &status);
 +
      if (rc) {
 +
        printf("ERROR; return code from pthread_join() is %d\n", rc);
 +
        exit(-1);
 +
      }
 +
      printf("Main: esperando thread %ld having a status of %ld\n",t,(long)status);
 +
  }
 +
  printf("Conta = %lf\n", conta);
 +
  return 0;
 +
}
 +
</syntaxhighlight>
 +
 
 +
==Laboratório Parte 2==
 +
 
 +
Proponha uma solução para o problema da Parte 1 usando uma solução trivial com BUSY WAIT. Quais os problemas de uma solução deste tipo?
 +
A ideia do busy wait seria algo do tipo:
 +
 
 +
<syntaxhighlight lang=cpp>
 +
      while(busy);  // entrada seção crítica
 +
      busy=1;      //
 +
      conta = conta+1;
 +
      busy=0;      // saída seção crítica
 +
</syntaxhighlight>
 +
 
 +
==Laboratório Parte 3 ==
 +
 
 +
Proponha uma solução para o problema da Parte 1 usando uma solução baseada em mutex. Estude o mutex em [https://computing.llnl.gov/tutorials/pthreads/#Mutexes]
 +
 
 +
==Laboratório Parte 4 ==
 +
 
 +
Teste a ideia do mutex servir como um lock para vários threads ou processos. Refaça o exercício da parte 3 para 10 threads =. Use uma única função de base para thread.
 +
 
 +
==Material de Referência==
 +
 
 +
*[http://wiki.inf.ufpr.br/maziero/lib/exe/fetch.php?media=socm:socm-slides-11.pdf Selides Cap.11 do Livro do Prof.Maziero]
 +
 
 +
=AULA SÍNCRONA - Dia 23/06/2020=
 +
==Objetivos==
 +
 
 +
* Conceito de Semáforo e Mutex
 +
* Uso de Semáforos intra processo
 +
 
 +
==Laboratório==
 +
Nos sistemas POSIX, semáforos são implementados pelo tipo ''sem_t'' e manipulado através das funções (acesse as man-pages das chamadas para maiores detalhes):
 +
* ''sem_init'': inicializa um semáforo;
 +
* ''sem_destroy'': destroy um semáforo;
 +
* ''sem_wait'': implementa a operação ''p'';
 +
* ''sem_post'': implementa a operação ''v''.
 +
Para utilizar estas funções é necessário linkar o programa à librt ou à libpthread (''-lrt'' ou ''-lpthread'').
 +
 
 +
Ver exemplo em [https://docs.oracle.com/cd/E19683-01/806-6867/6jfpgdcnj/index.html].
 +
 
 +
;PARTE 1
 +
Modifique o programa para usar um semáforo binário ao invés de um mutex em sua solução.
 +
 
 +
;PARTE 2
 +
Refaça o exercício da aula anterior criando dois tipos de  tarefas (i) tarefas escritoras (atualizando o saldo) e (ii) tarefas leitoras. Crie 10 tarefas leitoras mas limite o acesso a leitura para no máximo 3 tarefas por vez.
 +
 
 +
==Material de Referência==
 +
 
 +
* [http://wiki.inf.ufpr.br/maziero/lib/exe/fetch.php?media=socm:socm-slides-11.pdf Selides Cap.11 do Livro do Prof.Maziero]
 +
* Cap.sobre Semáforos do Silberschatz
 +
 
 +
==Avaliação 1 ==
 +
 
 +
Data: 3/Julho 2020
 +
 
 +
==Questionário - Processos==
 +
 
 +
#Conceitue processo. Descreva e explique cada uma das seções de um processo na memória.
 +
#Faça um diagrama e explique os possíveis estados de um processo no sistema. O que produz a transição entre estados?
 +
#O que é um Bloco de Controle de Processo? Quais informações ficam armazenadas neste bloco?
 +
#Faça um diagrama mostrando a alternância entre dois processos na CPU. Indique o procedimento de salvamento e restauração do estado do PCB.
 +
#Explique o que é multiprogramação e escalonamento de processos.
 +
#O que é a fila de processos prontos?
 +
#Diferencie um processo limitado por IO de um processo limitado por CPU.
 +
#Diferencie escalonamento de longo prazo de escalonamento de curto prazo.
 +
#Discuta o papel da interrupção na troca de contexto entre processos.
 +
#Explique como é o processo de criação de novos processos no UNIX/Linux através da chamada fork. O que acontece com a memória do novo processo?
 +
#Explique como funciona a chamada exec no UNIX/Linux
 +
#Explique como funciona a chamada wait no UNIX/Linux e como é possível retornar valores de um filho para o pai.
 +
#Faça um esqueleto de um programa UNIX/Linux que ao se tornar processo cria 3 filhos e espera pela execução dos mesmos.
 +
 
 +
==Questionário - Comunicação entre Processos==
 +
 
 +
#Diferenciar processos independentes de processos cooperantes.
 +
#Enumere e explique quatro razões para cooperação entre processos.
 +
#A velocidade de processamento é uma das razões da cooperação entre processos. Discuta se um hardware com apenas uma CPU pode usufruir desta característica.
 +
#Descreva os dois principais mecanismos de cooperação entre processos. Discuta a situação em que é possível usar a memória compartilhada e/ou a troca de mensagens.
 +
#A memória compartilhada requer chamada ao sistema na sua operação? Discuta.
 +
#Por que o processo de troca de mensagem deve ser mais lento que a memória compartilhada?
 +
#Apresente em pseudocódigo uma proposta de funcionamento do problema do produtor consumidor usando memória compartilhada.
 +
#A construção de uma solução para o problema produtor consumidor pode ser facilitado pelo uso da memória compartilhada? Discuta.
 +
#Quais as duas operações básicas ma troca de mensagens? O que poderia motivar o uso de mensagens do tamanho fixo? Esta abordagem torna mais complexa a vida dos programadores?
 +
#Enumere três métodos de implementação de uma lógica de ligação (link) entre processos.
 +
#Explique o que é a comunicação direta em troca de mensagens. Descreva como são as duas primitivas de comunicação direta para esta abordagem e quais as 3 propriedades seguidas por esta comunicação.
 +
#Descreva a variante assimétrica da troca direta de mensagens. O que muda em termos de primitiva de comunicação?
 +
#Descreva o problema de hard-coding associado a nomeação direta e como pode ser contornado através da nomeação/comunicação indireta?
 +
#O que é uma caixa postal? Como o Posix identifica uma caixa postal no caso de fila de mensagens?
 +
#Dois processos podem usar mais do que uma caixa postal para se comunicar? Qual a condição para que isto ocorra?
 +
#Descreva as duas operações básicas para a troca de mensagens com Caixa Postal.
 +
#Descreva na comunicação indireta via Caixa Postal as 3 propriedades básicas.
 +
#A questão do compartilhamento de caixas postais por múltiplos processos podem causar um problema na operação da recepção. Descreva quais as 3 possibilidades para contornar este problema.
 +
#De que forma a caixa postal estando no espaço de endereçamento de um processo (propriedade) afeta a recepção por mensagens? Descreva.
 +
#Quais as operações sobre uma caixa postal criada no espaço do sistema operacional deverão ser disponíveis? Descreva.
 +
#A transmissão de mensagem pode ser com e sem bloqueio. Descreva as 4 possibilidades (síncrona/assíncrona).
 +
#Discuta as 3 possibilidades de armazenamento de mensagens em buffer. Em que condições um remetente pode ser bloqueado?
 +
 
 +
 
 +
=AULA SÍNCRONA - Dia 26/06/2020=
 +
 
 +
==Objetivos==
 +
 
 +
* Revisão do Conceito de Semáforo e Mutex
 +
* Uso de Semáforos intra processo
 +
*Problema Produtor Consumidor
 +
 
 +
==Material de Referência==
 +
 
 +
*Livro Silberchatz: Cap.6 (versão 8)
 +
*Slides e Cap.11 do Livro do Prof.Maziero: Parte Semáforo e Mutex
 +
**[http://wiki.inf.ufpr.br/maziero/lib/exe/fetch.php?media=socm:socm-slides-11.pdf Selides Cap.11 do Livro do Prof.Maziero]
 +
 
 +
*[https://www.youtube.com/watch?v=ttfd43B9o04 Aula Sincronização de Processos - Prof.Isidro]
 +
 
 +
==Laboratório==
 +
Nos sistemas POSIX, semáforos são implementados pelo tipo ''sem_t'' e manipulado através das funções (acesse as man-pages das chamadas para maiores detalhes):
 +
* ''sem_init'': inicializa um semáforo;
 +
* ''sem_destroy'': destroy um semáforo;
 +
* ''sem_wait'': implementa a operação ''p'';
 +
* ''sem_post'': implementa a operação ''v''.
 +
Para utilizar estas funções é necessário linkar o programa à librt ou à libpthread (''-lrt'' ou ''-lpthread'').
 +
 
 +
Ver exemplo em [https://docs.oracle.com/cd/E19683-01/806-6867/6jfpgdcnj/index.html].
 +
 
 +
;PARTE 1
 +
;Modifique o programa do laboratório anterior para usar um semáforo binário ao invés de um mutex em sua solução.
 +
 
 +
;PARTE 2
 +
;Analise o código abaixo. Trata-se de uma implementação do problema produtor consumidor sem nenhum mecanismo de sincronização ou coordenação.
 +
Identifique a seção crítica.
 +
 
 +
<syntaxhighlight lang=cpp>
 +
#include <stdio.h>
 +
#include <pthread.h>
 +
#include <semaphore.h>
 +
#include <unistd.h>
 +
 
 +
 
 +
#define BUFFER_SIZE 50
 +
 
 +
sem_t mutex;
 +
volatile char fim=1;
 +
char buffer[BUFFER_SIZE];
 +
long disponivel=0; /* numero de itens ocupados no no buffer  */
 +
int in,out=0;
 +
int itens_prod=1;
 +
int soma_prod=0, soma_cons=0;
 +
 
 +
void* produtor(void* arg)
 +
{
 +
    char  prod=0;
 +
    volatile long aux;
 +
 
 +
    do {
 +
        while(disponivel == BUFFER_SIZE)
 +
          ;
 +
        buffer[in] = prod;
 +
        soma_prod = soma_prod + prod;
 +
        prod = (prod+1) % 5;
 +
        in = (in + 1) % BUFFER_SIZE;
 +
        //sem_wait(&mutex);
 +
        disponivel = disponivel + 1;
 +
        //sem_post(&mutex);
 +
        printf("produzidos = %d\n", itens_prod++);
 +
    } while (itens_prod!=900000);
 +
    sleep(5); //tempo para encerrar
 +
    fim=0;
 +
    printf("TOTAL produzido = %d\n", soma_prod);
 +
    pthread_exit(NULL);
 +
}
 +
 
 +
void* consumidor(void* arg)
 +
{
 +
    char consumo, consumo_ant='a';
 +
    volatile long aux;
 +
 
 +
    do {
 +
 
 +
        while(disponivel == 0 && fim)
 +
            ;
 +
        if (fim==0)
 +
                break;
 +
        consumo = buffer[out];
 +
        soma_cons = soma_cons + consumo;
 +
        out = (out + 1) % BUFFER_SIZE;
 +
        //sem_wait(&mutex);
 +
        disponivel = disponivel - 1;
 +
        //sem_post(&mutex);
 +
        printf("disponivel = %ld\n", disponivel);
 +
    } while (fim);
 +
    printf("TOTAL consumido = %d\n", soma_cons);
 +
    pthread_exit(NULL);
 +
}
 +
 
 +
int main()
 +
{
 +
    int x;
 +
    //sem_init(&mutex, 0, 1);
 +
    pthread_t t1,t2;
 +
    pthread_create(&t1,NULL,produtor,NULL);
 +
    pthread_create(&t2,NULL,consumidor,NULL);
 +
    printf("Tecle 1 e ENTER para FIM\n");
 +
    scanf("%d", &x);
 +
    fim = 0;
 +
    pthread_join(t1,NULL);
 +
    pthread_join(t2,NULL);
 +
    //sem_destroy(&mutex);
 +
    return 0;
 +
}
 +
</syntaxhighlight>
 +
 
 +
;PARTE 3
 +
;Usando semáforos e mutex (ou semáforo binário), faça uma proposta de solução do problema produtor consumidor.
 +
 
 +
;PARTE 4
 +
;Faça uma proposta para estender o problema para dois produtores e um consumidor.
 +
 
 +
=AULA SÍNCRONA - Dia 30/06/2020=
 +
==Objetivos==
 +
 
 +
* Conteúdos para avaliação
 +
* Problema Produtor Consumidor
  
 
==Referências==
 
==Referências==
  
*Cap.51, 5.2 e 5.3 do Livro de Silberschatz
+
* Livro Silberchatz: Cap.6 (versão 8)
*[https://www.os-book.com/OS9/slide-dir/ Slides Silberschatz]
+
* Slides e Cap.11 e 12 do Livro do Prof.Maziero: Parte Semáforo e Mutex
*[http://docente.ifsc.edu.br/andre.damato/sop2018/SOP2018-parte2.pdf Apresentação sobre Gerenciamento de Processos]
+
 
*Cap.6 do Livro do Prof.Maziero (http://wiki.inf.ufpr.br/maziero/doku.php?id=socm:start)
+
==Conteúdos para Avaliação==
 +
 
 +
{| class="wikitable" style="text-align:center;"
 +
|- style="text-align:left;"
 +
! Tópico
 +
! Referência
 +
! Comentário
 +
|-
 +
| Introdução e Estrutura do SIstema Operacional
 +
| 1.1 a 1.8 Silberchatz<br />2.1 a 2.7 + Laboratório System Call
 +
| style="text-align:left;"|*Papel da Interrupção e Timers para os SOPs;
 +
 
 +
 
 +
* Conceito de multiprogramação, multitarefa e multiprocessamento;
 +
|-
 +
| Processos: Conceitos e IPC
 +
| 3.1 a 3.5 + Laboratórios de Processos, Pipes e Memória Compartilhada Ver [https://www.geeksforgeeks.org/memory-layout-of-c-program/#:~:text=A%20text%20segment%20%2C%20also%20known,stack%20overflows%20from%20overwriting%20it.]
 +
| style="text-align:left;"| 
 +
|-
 +
| Threads
 +
| 4.1. a 4.4. + Laboratório de Threads: de aplicação e pthreads
 +
| style="text-align:left;"| 
 +
|-
 +
| Escalonamento do Processos
 +
| Cap.6 Livro Prof.Maziero (até 6.4.5)[http://wiki.inf.ufpr.br/maziero/doku.php?id=socm:start]
 +
| style="text-align:left;"|*Ver métricas/critérios para escalonamento;
 +
 
 +
 
 +
* ver como calcular os tempos de execução médio e tempo de espera;
 +
|}
 +
 
 +
=AULA SÍNCRONA - Dia 4/08/2020=
 +
==Objetivos==
 +
 
 +
* Introdução a Gerência de Meméoria
 +
** Vinculação de endereços lógicos aos físicos (8.1)
 +
** Swapping (8.2)
 +
 
 +
==Referência==
 +
[https://www.os-book.com/OS8/OLD/os8e/slide-dir/PDF-dir/ch7.pdf Slides Cap.7 Silberschatz]
 +
 
 +
=AULA SÍNCRONA - Dia 7/08/2020=
 +
 
 +
==Objetivos==
 +
 
 +
*Gerenciamento de Memória Contígua (8.2)
 +
*Paginação (8.4)
 +
*Agendar a nova (rec1) avaliação 1 - Sugestão: Disponibilizo na quarta que vem (dia 13/08) - Colocar ANPs complementares
 +
*Agendar a Avaliação 2 ?
 +
 
 +
==Referência==
 +
 
 +
[https://www.os-book.com/OS8/OLD/os8e/slide-dir/PDF-dir/ch7.pdf Slides Cap.7 Silberschatz]
 +
[http://wiki.inf.ufpr.br/maziero/lib/exe/fetch.php?media=socm:socm-slides-16.pdf]
 +
 
 +
=AULA SÍNCRONA - Dia 11/08/2020=
 +
 
 +
==Objetivos==
 +
 
 +
*Gerenciamento de Memória: Contígua, Paginação e Segmentação
 +
*Conceito de TLB
 +
*Hierarquia de Paginação
 +
 
 +
==Referência==
 +
 
 +
*[http://wiki.inf.ufpr.br/maziero/lib/exe/fetch.php?media=socm:socm-slides-15.pdf Slides Cap.15 MAziero]
 +
*[http://wiki.inf.ufpr.br/maziero/lib/exe/fetch.php?media=socm:socm-15.pdf Cap.15 Livro Maziero]
 +
 
 +
=AULA SÍNCRONA - Dia 14/08/2020=
 +
 
 +
==Objetivos==
 +
 
 +
*Técnicas para estender a memória RAM
 +
*Algoritmos de escolha de páginas vítima
 +
 
 +
==Referência==
 +
 
 +
*[http://wiki.inf.ufpr.br/maziero/lib/exe/fetch.php?media=socm:socm-slides-15.pdf Slides Cap.16 MAziero]
 +
*[http://wiki.inf.ufpr.br/maziero/lib/exe/fetch.php?media=socm:socm-15.pdf Cap.15 Livro Maziero]
 +
 
 +
 
 +
=AULA SÍNCRONA - Dia 18/08/2020=
 +
 
 +
==Objetivos==
 +
 
 +
*Técnicas para estender a memória RAM (continuação)
 +
*Algoritmos de escolha de páginas vítima
 +
*Ver ANP repassada na wiki
 +
 
 +
==Referência==
 +
 
 +
*[http://wiki.inf.ufpr.br/maziero/lib/exe/fetch.php?media=socm:socm-slides-17.pdf]
 +
*[http://wiki.inf.ufpr.br/maziero/lib/exe/fetch.php?media=socm:socm-slides-15.pdf Slides Cap.16 MAziero]
 +
*[http://wiki.inf.ufpr.br/maziero/lib/exe/fetch.php?media=socm:socm-15.pdf Cap.15 Livro Maziero]
 +
 
 +
==REcuperação A1==
 +
 
 +
*Dia 28/08/2020
 +
*ver conteúdo tabela acima
 +
 
 +
==A2==
 +
 
 +
*Coordenação de Processos
 +
*Memória Virtual
 +
*Data 04/Set
 +
*Sexta: revisamos PRoblemas Classicos
 +
 
 +
=AULA SÍNCRONA - Dia 21/08/2020=
 +
 
 +
*Revisão Mecanismos de Coordenação - Preparação para Avaliação 2
 +
*Problemas Clássicos de Sincronização
 +
 
 +
==Material de Referência==
 +
 
 +
*[http://wiki.inf.ufpr.br/maziero/lib/exe/fetch.php?media=socm:socm-12.pdf Cap.12 Livro Maziero]
 +
*[http://wiki.inf.ufpr.br/maziero/lib/exe/fetch.php?media=socm:socm-slides-12.pdf Slides Cap.12 Maziero]
 +
*[https://www.os-book.com/OS8/OLD/os8e/slide-dir/PDF-dir/ch6.pdf Slides Silbeschatz Cap. Problemas Clássicos]
 +
 
 +
=AULA - Dia 29/08/2020=
 +
 
 +
*AVALIAÇÂO 2
 +
 
 +
=AULA - Dia 1/09/2020=
 +
 
 +
==Objetivos==
 +
 
 +
*Conceituar Arquivos, DIretórios e Sistemas de Arquivos
 +
*Atributos de Arquivos
 +
*Operações sobre arquivos
 +
 
 +
==ASSISTIR VÍDEO==
 +
 
 +
*[http://wiki.inf.ufpr.br/maziero/lib/exe/fetch.php?media=socm:socm-video-22.mkv Vídeo Cap.22 do Livro do Prof.Maziero]
 +
 
 +
==Tarefa ==
 +
 
 +
*Ver questionário no SIGAA
 +
 
 +
=AULA - Dia 4/09/2020=
 +
 
 +
==Objetivos==
 +
 
 +
*Uso de Arquivos
 +
**Operações sobre arquivos
 +
**Formas de Acessos
 +
**Permissões
 +
**Travas
 +
 
 +
==ReferÊncias==
 +
 
 +
*[http://wiki.inf.ufpr.br/maziero/lib/exe/fetch.php?media=socm:socm-23.pdf Cap.23 - Livro Prof.Maziero]
 +
 
 +
*[http://wiki.inf.ufpr.br/maziero/lib/exe/fetch.php?media=socm:socm-slides-23.pdf Slides Cap.23]
 +
 
 +
*[http://wiki.inf.ufpr.br/maziero/lib/exe/fetch.php?media=socm:socm-video-23.mkv Vídeo Cap.23]
 +
 
 +
==TAREFA ANP==
 +
 
 +
VER NO SIGAA: TAREFA A3.1 - Permissionamento de Arquivos no Linux
 +
 
 +
==Adicional==
 +
 
 +
*[https://linux-audit.com/elf-binaries-on-linux-understanding-and-analysis/ Anatomia do ELF]
 +
 
 +
*[https://lwn.net/Articles/631631/ Como programas são executados no Linux]
 +
 
 +
*Ver Silberschatz:
 +
**Interface de Sistema de Arquivos (cap.10)
 +
**Conceito de Arquivo (10.1):
 +
**Atributo de Arquivos (10.1.1),
 +
**Operações sobre Arquivos (10.1.2),
 +
**Tipos de Arquivos (10.1.3) e
 +
**Estrutura de Arquivos (10.1.4)
 +
**Métodos de Acesso (10.2)
 +
**Acesso Sequencial (10.2.1)
 +
**Acesso Direto (10.2.2)
 +
**Outros métodos de acesso (10.2.3)
 +
 
 +
=AULA - Dia 8/09/2020=
 +
 
 +
==Objetivos==
 +
 
 +
*Implementação do Sistema de Arquivos
 +
 
 +
==Material de ReferÊncia==
 +
 
 +
*[http://wiki.inf.ufpr.br/maziero/lib/exe/fetch.php?media=socm:socm-24.pdf Cap.24 do Livro Prof.Maziero]
 +
*[http://wiki.inf.ufpr.br/maziero/lib/exe/fetch.php?media=socm:socm-slides-24.pdf Slides Ca.24]
 +
*[http://wiki.inf.ufpr.br/maziero/lib/exe/fetch.php?media=socm:socm-video-25.mkv Vídeo Cap.24]
 +
 
 +
=AULA - Dia 11/09/2020=
 +
 
 +
==Objetivos==
 +
 
 +
*Implementação do Sistema de Arquivos (Continuação)
 +
 
 +
==Material de ReferÊncia==
 +
 
 +
*[http://wiki.inf.ufpr.br/maziero/lib/exe/fetch.php?media=socm:socm-24.pdf Cap.24 do Livro Prof.Maziero]
 +
*[http://wiki.inf.ufpr.br/maziero/lib/exe/fetch.php?media=socm:socm-slides-24.pdf Slides Ca.24]
 +
*[http://wiki.inf.ufpr.br/maziero/lib/exe/fetch.php?media=socm:socm-video-25.mkv Vídeo Cap.24]
 +
 
 +
=AULA - Dia 15/09/2020=
 +
 
 +
==Objetivos==
 +
 
 +
*Subsistema de IO: Hardware de IO
 +
*Avaliação 3 - Dia 25/09/2020 - Prova Objetiva (diferente para cada aluno - 50% Tarefa ANP) 
 +
*Recuperação da Avaliação 1 - Dia 2/10
 +
 
 +
==Referências==
 +
 
 +
*[http://wiki.inf.ufpr.br/maziero/lib/exe/fetch.php?media=socm:socm-19.pdf Cap.19]
 +
*[http://wiki.inf.ufpr.br/maziero/lib/exe/fetch.php?media=socm:socm-slides-19.pdf Slides Cap.19]
 +
*[http://wiki.inf.ufpr.br/maziero/lib/exe/fetch.php?media=socm:socm-video-19.mkv Vídeo do Cap.19]
 +
*Cap.Subsistemas de IO do Silberschatz
 +
*[https://web.fe.up.pt/~pfs/aulas/so2020/proj/proj1.html proj1 2020 Universidade do Porto]
 +
*[https://web.fe.up.pt/~pfs/aulas/so2020/ Link Para SOP2020 Universidade do Porto]
 +
*[https://linux-kernel-labs.github.io/refs/heads/master/labs/device_drivers.html]
 +
 
 +
=AULA - Dia 18/09/2020=
 +
 
 +
==Objetivos==
 +
 
 +
*Projeto Final: Parte 1
 +
 
 +
 
 +
==Projeto Final==
 +
 
 +
Desenvolvimento do um Char Device Driver para Linux baseado em [https://web.fe.up.pt/~pfs/aulas/so2020/proj/proj1.html proj1 2020 Universidade do Porto]
 +
O objetivo final do projeto é um serial device driver a ser testado entre duas VMs.
 +
 
 +
==Etapa 1==
 +
 
 +
*Lab 1 - Instalação da VM com o CICA2
 +
*Lab 2
 +
**Driver Hello World Personalizado
 +
 
 +
=AULA - Dia 22/09/2020=
 +
 
 +
==Objetivos==
 +
 
 +
*Projeto Final: Parte 2
 +
*Lembrar que Sexta (25) será passada a AVAL.3 (questões objetivas)
 +
 
 +
==PARTE 2 - ECHO DEVICE==
 +
 
 +
Seguir instruções de [https://web.fe.up.pt/~pfs/aulas/so2020/proj/proj2.html proj1 2020 Universidade do Porto]
 +
 
 +
Fazer:
 +
-registro do major e minor number
 +
-criação do device echo_device
 +
-criação das funções open, read, write e close
 +
 
 +
=AULA - Dia 25/09/2020=
 +
 
 +
==Objetivos==
 +
 
 +
*Avaliação 3
 +
 
 +
=AULA - Dia 29/09/2020=
 +
 
 +
==Objetivos==
 +
 
 +
*Rec. Aval 1 - Dia 6/10/2020
 +
*Projeto: Visão Geral de onde podemos chegar...
 +
*Projeto Final: Parte 2 (continuação)
 +
 
 +
 
 +
=AULA - Dia 2/10/2020=
 +
 
 +
==Objetivos==
 +
 
 +
<syntaxhighlight lang=cpp>
 +
 
 +
 
 +
#include <stdio.h>
 +
 
 +
#define DIM_1 2
 +
#define DIM_2 3
 +
#define DIM_3 4
 +
 
 +
int main()
 +
{
 +
  int matA[DIM_1][DIM_2]={{2,5,7},
 +
                          {4,7,5}
 +
                        },
 +
      matB[DIM_2][DIM_3]={{7,5,6,4},
 +
                          {4,6,4,3},
 +
                          {9,2,2,1}
 +
                          },
 +
      matR[DIM_1][DIM_3] ={
 +
                          {0,0,0,0},
 +
                          {0,0,0,0}
 +
                          },
 +
      i,j,k;
 +
 
 +
 
 +
  for (i=0;i<DIM_1;i++)
 +
    for (j=0;j<DIM_3;j++) {
 +
        for (k=0;k<DIM_2;k++)
 +
            matR[i][j]=matR[i][j]+matA[i][k]*matB[k][j];
 +
        printf("MatR[%d][%d] => %d \n", i, j,  matR[i][j]);
 +
    }
 +
  return 0;   
 +
}
 +
</syntaxhighlight>
 +
 
 +
=AULA DIA  Dia 9/10/2020=
 +
 
 +
=Objetivos=
 +
 
 +
*Acompanhamento Projeto Final
 +
*Echo Driver
 +
 
 +
 
 +
 
 +
=AULA DIA  Dia 13/10/2020=
 +
 
 +
==Objetivos==
 +
 
 +
*Acompanhamento Projeto Final
 +
*Lab. 3 Univ.Porto (https://web.fe.up.pt/~pfs/aulas/so2020/proj/proj3.html)
 +
 
 +
=Reconfigurar teclado do CICA2=
 +
 
 +
sudo dpkg-reconfigure console-data
 +
 
 +
Escolher o teclado abnt2

Edição atual tal como às 09h20min de 27 de outubro de 2020

AULA 1 - Dia 11/02/2020

Objetivos/Conteúdos

  • Apresentação do Plano de Ensino
    • Objetivos e Conteúdo Programático da Disciplina (ver SIGAA)
    • Forma de Avaliação (ver SIGAA)
  • Introdução a Sistemas Operacionais (Cap1. do Silberschatz)
    • O que faz um sistema operacional (1.1)
    • Organização e Arquitetura de um Sistema Computacional (1.2 e 1.3)
      • Importância da Interrupção e Timers (1.2.1)
      • Estrutura de Armazenamento (1.2.2)
      • Estrutura de IO (1.2.3)
    • Estrutura e Operações de um Sistema Operacional (1.4 e 1.5)

Material de Referência

Arliones:

Leitura Recomendada

  • Cap.1 do Silberschatz principalmente:
    • 1.1 a 1.9

Exercícios Práticos de Apoio a Aula

Na sequência. com fins motivacionais, são apresentados alguns exercícios ilustrando conceitos de processos, arquivos e permissionamento.

  1. Comando para ver todos os processos no linux:
      $ ps aux
    
  2. Colocar 2 processos se executando no contexto de um terminal e verificar número dos processos e então "destruí-los":
    $ yes > /dev/null
    $ yes > /dev/null
    $ ps 
    $ kill -9 <pid_yes>
    $ kill -9 <pid_yes>
    

    Observe que dois processos foram criados a partir do programa "yes". Os processos associados ao terminal são visualizados e então destruídos. Tente destruir também o interpretador de comando (shell) associado ao terminal.

  3. Criar um terminal adicional
    $ xterm
    

    Ir no terminal criado e listar os processos que se executam associados a este terminal. Verificar qual o dispositivo de entrada e saída associado a ele. Voltar ao terminal original e enviar uma mensagem. Destruir o terminal criado:

    $ echo Alo Terminal > /dev/pts/2
    $ kill -9 <pid_terminal>
    
  4. Comunicação entre processos:
    $ cat /etc/passwd | grep home | wc -l
    
  5. Retirando a permissão de leitura de um arquivo em nível de usuário proprietário:
    $ echo Alo Mundo > alfa.txt
    $ ls -l alfa.txt
    $ cat alfa.txt
    $ chmod u-r alfa.txt
    $ cat alfa.txt
    $ chmod u+r alfa.txt
    $ cat  alfa.txt
    

AULA 2 - Dia 14/02/2020

Objetivos/Conteúdos

  • Estruturas do Sistema Operacional (cap.2)
    • Serviços do Sistema Operacional (2.1)
    • Interfaces com Usuários (2.2)
    • Chamadas do Sistema (2.3)
    • Tipos de Chamadas de Sistema (2.4) ver Fig.2.8
      • Chamadas de Controle de Processos


Material de Referência

Leitura Recomendada

  • Cap.2 do Silberschatz principalmente:
    • 2.1 a 2.8

Exercícios

  1. Estudar e executar o código em http://cs.lmu.edu/~ray/notes/gasexamples/ Detalhes das chamadas na arquitetura x86_64 ver em https://lwn.net/Articles/604287/
  2. Estudar e executar o código usando a função (em conformidade com a API POSIX) write() para o hello world:
    #include <unistd.h> 
    
    main()
    {
      write(1,"Alo Mundo\n",10);
    }
    
  3. Use o comando strace para verificar todas as chamadas de sistema dos programas acima.
  4. DESAFIO 1: Estude a seção "Mixing C and Assembly Language" da http://cs.lmu.edu/~ray/notes/gasexamples/ e construa uma função meu_hello_world() usando o código em assembly do exercício inicial. Estude como poderia disponibilizar esta e outras funções de interface (a sua API) em uma biblioteca. Note que esta função deve ser chamada da forma:
    main()
    {
      meu_hello_world();
    }
    
  5. Gere o assembly do código em C e discuta a diferença entre uma chamada de função e uma chamada de sistema.
  6. DESAFIO 2: Estude o link http://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/ e melhore a função meu_hello_world para suportar uma mensagem adicional da forma:
    #include <string.h>
    main()
    {
      char *p="Tudo bem com vocês?";
      meu_hello_world(p, strlen(p));
    }
    

    Solução:

    Solução
    modificado de http://cs.lmu.edu/~ray/notes/gasexamples/
            .global meu_hello_world
    
            .text
    meu_hello_world:
    
            push    %rdi                    # salva primeiro parâmetro
            push    %rsi                    # salva segundo parâmetro
            mov     $1, %rax                # system call 1 é write
            mov     $1, %rdi                # file handle 1 é stdout
            mov     $message, %rsi          # endereço da string
            mov     $13, %rdx               # número de bytes da string
            syscall                         # chamada ao sistema
    
            pop     %rdx                    # o que havia sido passado em rsi (número de bytes) é colocado em rdx
            pop     %rsi                    # o que havia sido colocado em rdi (endereço da string) é colocado em rsi
            mov     $1, %rax                # system call 1 is write
            mov     $1, %rdi                # file handle 1 é stdout
            syscall                         # nova chamada ao sistema
    
            ret
    
    message:
            .ascii  "Hello, World\n"
    

    AULA 3 - Dia 18/02/2020

    Objetivos/Conteúdos

      • Interfaces com Usuários (2.2)
      • Chamadas do Sistema (2.3)
      • Tipos de Chamadas de Sistema (2.4) ver Fig.2.8
        • Chamadas de Controle de Processos

    AULA 4 - Dia 21/08/2020

    Objetivos

    • PARTE 2A: Gerenciamento de Processos (cap.3)
    • 3.1.Conceito de Processo
    • 3.2.Escalonamento de Processos
    • 3.3.Operações sobre Processos (Laboratório Operações sobre Processos no Linux: Fork/Exec/Wait)

    Material de Referência

    • Slides do Cap.3 - Silberschatz
    • Laboratório Fork/Exec/Wait

    Exercícios de Demonstração

    1. Executar em um terminal o comando top. Em um outro terminal executar:
      yes > /dev/null &
      yes > /dev/null &
    
    1. Parar um dos processos yes
      kill -STOP <pid_yes>
    
    1. Continuar o processo
      kill -CONT <pid_yes>
    
    1. Destruir todos
      killall yes
    

    AULA 5 - Dia 28/02/2020

    Objetivos/Conteúdos

    • Gerenciamento de Processos
      • Conceito de Processo (3.1)
        • O processo (3.1.1)
        • Estado do Processo (3.1.2)
        • Bloco de Controle de Processo (3.1.3)
        • Threads (3.1.4)
      • Scheduling (3.2)
        • Filas de Scheduling (3.2.1)
        • Schedulers
        • Mudança de Contexto (3.2.3)
      • Operações Sobre Processos (3.3)

    Slides desta aula

    Laboratório em Sala

    https://wiki.sj.ifsc.edu.br/index.php/SOP29005-2019-1#Processos_no_Linux_-_Modificado_por_Eraldo

    Exercícios de Demonstração

    Processos no Linux

    Processos no Linux - Modificado por Eraldo

    Processos no Linux

    • Exercícios propostos pelo Prof.Arliones e Modificados por Eraldo


    DesenhoForkExec.png


    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 pela 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
    // ex1: fork/wait básico
    #include <sys/types.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <sys/wait.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);
        }
    }
    
    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$
    
    • Exemplo 2: processos pai e filho compartilham código, mas não dados.
    // ex2: fork/wait "compartilhando" dados
    // ex2: fork/wait "compartilhando" dados
    #include <sys/types.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <sys/wait.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 \t endereço K: %p\n", getpid(), k, &k);
            exit(0);
        }
        else // Este é o processo pai
        {
            wait(&status);  // espera o filho terminar
            k += 10;
            printf("processo pai\t pid: %d\t K: %d  \t endereço K:  %p\n", getpid(), k,  &k);
            exit(0);
        }
        k += 1000;
        printf("FIM processo %d\t K: %d\n", getpid(), k); 
        exit(0);
    }
    
    processo 17056   antes do fork
    processo 17056   depois do fork
    processo 17057   depois do fork
    processo filho   pid: 17057      K: 1000         endereço K: 0x7ffd8923e318
    processo pai     pid: 17056      K: 10           endereço K:  0x7ffd8923e318
    
    • Modificação no código: comentar linhas 23 e 30
    • Analise os resultados e busque entender a diferença.
    • Perguntas e desafios.:
    1. Analisando os valores impressos de k pode-se dizer que os dados são compartilhados entre os dois processos?
    2. O endereço de k impresso é o mesmo nos dois processos. ISto não contradiz a afirmação anterior?
    3. Substitua o k por uma área criada dinâmicamente com o malloc (área de HEAP). Verifique se esta área é ou não compartilhada pelos processos.


    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.

    • Use o comando pstree para verificar a árvore de processos criada.


    Solução

    /* ex3: Excrever um programa C que cria uma arvore 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 sao 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.

    • /
    1. include <sys/types.h>
    2. include <stdlib.h>
    3. include <stdio.h>
    4. include <unistd.h>
    5. include <sys/wait.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
       {
           pid = fork();
           if(pid == -1)
           {
               perror("fork falhou!");
               exit(-1);
           }
           else if(pid == 0) // Este é o filho do filho
           {
               sleep(1);
               printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());
               exit (0);
           }
           else
           {
               wait(&status);
               sleep(1);
               printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());
               exit(0);
           }
       }
       else // Este é o processo pai
       {
           wait(&status);
           sleep(1);
           printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());
           exit(0);
       }
    

    }

    </syntaxhighlight>


    AULA 6 - Dia 03/03/2020

    Objetivos/Conteúdos

    • Processos
    • Exercícios Fork/Exec

    AULA 7 - Dia 06/03/2020

    Objetivos/Conteúdos

    • Processos
    • Exercícios Fork/Exec
    • Memória Compartilhada

    Cap.3 - Seção 3.4 e 3.5

    AULA 8 - Dia 10/03/2020

    Objetivos/Conteúdos

    • Memória Compartilhada
    • Troca de Msgs
    • Laboratório de Pipes

    AULA 9 - Dia 13/03/2020

    Objetivos/Conteúdos

    • Questionário de REvisão
    • Conceito de Threads (cap.4)
    • Caracterização do contexto e chaveamento de contexto do thread
    • Laboratório de Thread de Applicação
    • Slides sobre Threads:


    Questionário - Processos

    1. Conceitue processo. Descreva e explique cada uma das seções de um processo na memória.
    2. Faça um diagrama e explique os possíveis estados de um processo no sistema. O que produz a transição entre estados?
    3. O que é um Bloco de Controle de Processo? Quais informações ficam armazenadas neste bloco?
    4. Faça um diagrama mostrando a alternância entre dois processos na CPU. Indique o procedimento de salvamento e restauração do estado do PCB.
    5. Explique o que é multiprogramação e escalonamento de processos.
    6. O que é a fila de processos prontos?
    7. Diferencie um processo limitado por IO de um processo limitado por CPU.
    8. Diferencie escalonamento de longo prazo de escalonamento de curto prazo.
    9. Discuta o papel da interrupção na troca de contexto entre processos.
    10. Explique como é o processo de criação de novos processos no UNIX/Linux através da chamada fork. O que acontece com a memória do novo processo?
    11. Explique como funciona a chamada exec no UNIX/Linux
    12. Explique como funciona a chamada wait no UNIX/Linux e como é possível retornar valores de um filho para o pai.
    13. Faça um esqueleto de um programa UNIX/Linux que ao se tornar processo cria 3 filhos e espera pela execução dos mesmos.

    Questionário - Comunicação entre Processos

    1. Diferenciar processos independentes de processos cooperantes.
    2. Enumere e explique quatro razões para cooperação entre processos.
    3. A velocidade de processamento é uma das razões da cooperação entre processos. Discuta se um hardware com apenas uma CPU pode usufruir desta característica.
    4. Descreva os dois principais mecanismos de cooperação entre processos. Discuta a situação em que é possível usar a memória compartilhada e/ou a troca de mensagens.
    5. A memória compartilhada requer chamada ao sistema na sua operação? Discuta.
    6. Por que o processo de troca de mensagem deve ser mais lento que a memória compartilhada?
    7. Apresente em pseudocódigo uma proposta de funcionamento do problema do produtor consumidor usando memória compartilhada.
    8. A construção de uma solução para o problema produtor consumidor pode ser facilitado pelo uso da memória compartilhada? Discuta.
    9. Quais as duas operações básicas ma troca de mensagens? O que poderia motivar o uso de mensagens do tamanho fixo? Esta abordagem torna mais complexa a vida dos programadores?
    10. Enumere três métodos de implementação de uma lógica de ligação (link) entre processos.
    11. Explique o que é a comunicação direta em troca de mensagens. Descreva como são as duas primitivas de comunicação direta para esta abordagem e quais as 3 propriedades seguidas por esta comunicação.
    12. Descreva a variante assimétrica da troca direta de mensagens. O que muda em termos de primitiva de comunicação?
    13. Descreva o problema de hard-coding associado a nomeação direta e como pode ser contornado através da nomeação/comunicação indireta?
    14. O que é uma caixa postal? Como o Posix identifica uma caixa postal no caso de fila de mensagens?
    15. Dois processos podem usar mais do que uma caixa postal para se comunicar? Qual a condição para que isto ocorra?
    16. Descreva as duas operações básicas para a troca de mensagens com Caixa Postal.
    17. Descreva na comunicação indireta via Caixa Postal as 3 propriedades básicas.
    18. A questão do compartilhamento de caixas postais por múltiplos processos podem causar um problema na operação da recepção. Descreva quais as 3 possibilidades para contornar este problema.
    19. De que forma a caixa postal estando no espaço de endereçamento de um processo (propriedade) afeta a recepção por mensagens? Descreva.
    20. Quais as operações sobre uma caixa postal criada no espaço do sistema operacional deverão ser disponíveis? Descreva.
    21. A transmissão de mensagem pode ser com e sem bloqueio. Descreva as 4 possibilidades (síncrona/assíncrona).
    22. Discuta as 3 possibilidades de armazenamento de mensagens em buffer. Em que condições um remetente pode ser bloqueado?


    Laboratório Threads Aplicação

    Ver https://wiki.sj.ifsc.edu.br/index.php/SOP29005-2019-1#Threads_de_aplica.C3.A7.C3.A3o

    Slides para esta aula

    AULA 10 ?? - REMOTA - Dia 24/03/2020

    Objetivos/Conteúdos

    • Webconf
    • Revisão de Threads
    • Laboratório de Thread de Applicação

    Slides para esta aula

    Threads de aplicação

    Threads de aplicação

    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.

    #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);
    }
    
    • Exercício 1: Primeiramente compile e execute o código. Agora estude o código e entenda completamente o seu funcionamento. Explique em DETALHES o código, comentando todas as linhas. Na seção de diagrama do seu relatório, desenhe um diagrama de funcionamento do código para mostrar exatamente como acontece a troca de contexto entre as threads.
    • Exercício 2: Acrescente um procedimento f_new que receba 4 strings como parâmetros e imprima todas na tela. Antes do final da execução do main faça uma mudança de contexto para chamar o procedimento criado.
    • Exercício 3: O que acontece se um dos threads é colocado para dormir? Todos os demais threads param a sua execução.
    • Exercício 4: Note que um thread somente deixa a execução para outro thread de forma explícita. Será que é possível realizar um escalonamento de threads de forma similar ao que o kernel faz com os processos? Ver http://www.cplusplus.com/forum/unices/6452/

    AULA 11 ?? - REMOTA - Dia 27/03/2020

    Objetivos/Conteúdos

    • Rever Threads em nível de Aplicação
    • Escalonamento de Threads de Aplicação
    • Exemplo: Escalalonador semi-automático
    Ainda Threads - Um escalonador semi-automático"

    Ainda Threads - Um escalonador semi-automático usando sinais

    Neste laboratório serão aprimorados os threads em nível de aplicação vistos na aula anterior. Usaremos sinais do Unix/Linux para escalonar os threads via handlers.

    Exemplo 1:

    No Linux/Unix o kernel ou um processo podem enviar sinais para outros processos. Trata-se de uma notificação de que um evento ocorreu. O processo pode ter tratadores (handlers) para estes sinais de forma a tratá-los de forma assíncrona. Pode-se fazer uma analogia com a interrupção por hardware de um programa em execução. Um tratador da interrupção trata a causa da mesma (evento) e no final do tratador (handler) é restaurado o contexto do programa interrompido. Por exemplo, quando um filho se encerra, o pai recebe do kernel o sinal SIGCHLD.

    No exemplo abaixo utilizamos o sinail USR1 de uso geral (disponível para o usuário). Associamos um handler a este sinal (sig_handler). O programa sendo executado, fica em loop no main(). Usando um outro terminal podemos enviar um sinal e verificar o efeito do mesmo.

    #include<stdio.h>
    #include <stdlib.h>
    #include<signal.h>
    #include<unistd.h>
    
    void sig_handler(int signo)
    {
      int x;
      printf("Turma de SOP: recebido SIGUSR1\n");
    }
    
    int main(void)
    {
      int x;
    
      if (signal(SIGUSR1, sig_handler) == SIG_ERR) {
          printf("\nProblemas com SIGUSR1\n");
          exit(-1);
      }
      // Loop  eterno dormindo 1s
      while(1) {
        sleep(1);
      }
      return 0;
    }
    

    Fazer no terminal:

     ps aux
    

    anotar o pid do processo e enviar o sinal:

     kill -USR1 pid
    

    Exemplo 2:

    O programa anterior é aprimorado para começar a executar um thread Ping similar a aula anterior. Ainda não existe escalonamento dos threads. Somente o thread ping é executado. O sinal USR1 pode ser enviado para o processo interrompendo a execução do thread.

    #include<stdio.h>
    #include <stdlib.h>
    #include<signal.h>
    #include<unistd.h>
    #include <ucontext.h>
     
    #define STACKSIZE 32768		/* tamanho de pilha das threads */
     
    #define PING_ID 1
     
    /* VARIÁVEIS GLOBAIS */
    ucontext_t cPing, cPong, cMain;
     
    int curr_thread;
     
    /* Handler para tratar o sinal */
    void sig_handler(int signo)
    {
      printf("Turma de SOP: recebido SIGUSR1\n");   
    }
     
    /* Funções-comportamento das Tarefas */
    void f_ping(void * arg) {
       int i=0;
     
       printf("%s iniciada\n", (char *) arg);
     
       for (;;) {
          printf("%s %d\n", (char *) arg, i++);
          sleep(1);
       }
       printf("%s FIM\n", (char *) arg);
     
     
    }
     
    void f_pong(void * arg) {
       int i=0;
     
       printf("%s iniciada\n", (char *) arg);
     
       for (;;) {
          printf("%s %d\n", (char *) arg, i++);
          sleep(1);
       }
       printf("%s FIM\n", (char *) arg);
    }
     
    void preparar_contexto_ping()
    {
       char *stack;
     
       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");
    }
     
    void preparar_contexto_pong()
    {
       char *stack;
     
       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");
    }
     
    int main(void)
    {
      int x;
     
      printf ("Main INICIO\n");
      preparar_contexto_ping();
      preparar_contexto_pong();
     
      if (signal(SIGUSR1, sig_handler) == SIG_ERR) {
          printf("\nProblemas com SIGUSR1\n");
          exit(-1);
      }
     
      curr_thread=PING_ID;
      swapcontext(&cMain, &cPing);
      // loop eterno que nunca é executado
      while(1) {
        sleep(1);
      }
      return 0;
    }
    

    Enviar o sinal USR1 para ver o efeito.

    Exemplo 3:

    Neste exemplo preparamos o handler para chavear o contexto de ping para pong e vice-versa. A cada USR1 recebido será realizada a troca de contexto.
    
    #include<stdio.h>
    #include <stdlib.h>
    #include<signal.h>
    #include<unistd.h>
    #include <ucontext.h>
    
    #define STACKSIZE 32768		/* tamanho de pilha das threads */
    
    #define PING_ID 1
    #define PONG_ID 2
    
    /* VARIÁVEIS GLOBAIS */
    ucontext_t cPing, cPong, cMain;
    
    int curr_thread;
    
    /* Handler para tratar o sinal */
    void sig_handler(int signo)
    {
      printf("Turma de SOP: recebido SIGUSR1\n");   
      if (curr_thread==PING_ID) {
         curr_thread=PONG_ID;
         swapcontext(&cPing, &cPong);    
      } else {
         curr_thread=PING_ID;
         swapcontext(&cPong, &cPing);
      }
    }
     
    /* Funções-comportamento das Tarefas */
    void f_ping(void * arg) {
       int i=0;
     
       printf("%s iniciada\n", (char *) arg);
     
       for (;;) {
          printf("%s %d\n", (char *) arg, i++);
          sleep(1);
       }
       printf("%s FIM\n", (char *) arg);
     
       
    }
     
    void f_pong(void * arg) {
       int i=0;
     
       printf("%s iniciada\n", (char *) arg);
     
       for (;;) {
          printf("%s %d\n", (char *) arg, i++);
          sleep(1);
       }
       printf("%s FIM\n", (char *) arg);
    }
    
    void prepara_contexto_ping()
    {
       char *stack;
     
       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");
    }
    
    void prepara_contexto_pong()
    {
       char *stack;
    
       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");
    }
    
    int main(void)
    {
      int x;
    
      printf ("Main INICIO\n");
      prepara_contexto_ping();
      prepara_contexto_pong();
      
      if (signal(SIGUSR1, sig_handler) == SIG_ERR) {
          printf("\nProblemas com SIGUSR1\n");
          exit(-1);
      }
    
      curr_thread=PING_ID;
      swapcontext(&cMain, &cPing);
      // A long long wait so that we can easily issue a signal to this process
      while(1) {
        sleep(1);
      }
      return 0;
    }
    

    Exercício: Use o comando htop para verificar como estes threads são vistos pelo SOP.

    Exercício: Tente analisar as pilhas dos threads e verificar sob qual pilha o handler se executa.

    Exercício 4:

    Neste ponto associamos um timer ao handler com o apoio do sinal ALRM. Agora os threads são escalonados automaticamente.

    #include<stdio.h>
    #include <stdlib.h>
    #include<signal.h>
    #include<unistd.h>
    #include <ucontext.h>
    #include <sys/time.h>
    
    #define STACKSIZE 32768		/* tamanho de pilha das threads */
    
    #define PING_ID 1
    #define PONG_ID 2
    #define TIME_SLICE 5
    
    /* VARIÁVEIS GLOBAIS */
    ucontext_t cPing, cPong, cMain;
    int curr_thread;
    
    /* Handler para tratar o sinal */
    void sig_handler(int signo)
    {
      printf("SOP da Turma 2020-1: recebido SIGALRM\n");
      alarm(TIME_SLICE);   
      if (curr_thread==PING_ID) {
         curr_thread=PONG_ID;
         swapcontext(&cPing, &cPong);    
      } else {
         curr_thread=PING_ID;
         swapcontext(&cPong, &cPing);
      }
    }
     
    /* Funções-comportamento das Tarefas */
    void f_ping(void * arg) {
       int i=0;
     
       printf("%s iniciada\n", (char *) arg);
     
       for (;;) {
          printf("%s %d\n", (char *) arg, i++);
          sleep(1);
       }
       printf("%s FIM\n", (char *) arg);
     
       
    }
     
    void f_pong(void * arg) {
       int i=0;
     
       printf("%s iniciada\n", (char *) arg);
     
       for (;;) {
          printf("%s %d\n", (char *) arg, i++);
          sleep(1);
       }
       printf("%s FIM\n", (char *) arg);
    }
    
    void preparar_contexto_ping()
    {
       char *stack;
     
       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");
    }
    
    void preparar_contexto_pong()
    {
       char *stack;
    
       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");
    }
    
    void preparar_handler()
    {
      if (signal(SIGALRM, sig_handler) == SIG_ERR) {
          printf("\nProblemas com SIGUSR1\n");
          exit(-1);
      }
      alarm(TIME_SLICE);
    }
    
    int main(void)
    {
      int x;
    
      printf ("Main INICIO\n");
      preparar_contexto_ping();
      preparar_contexto_pong();
      preparar_handler();
      curr_thread=PING_ID; //ajusta primeiro thread
      swapcontext(&cMain, &cPing); //nunca mais volta...
      return 0;
    }
    

    Exercício Proposto 5

    Refinar o handler de chaveamento de threads para que permita escalonar N f_pings, onde N será passado na linha de comando. Sugestão: criar uma fila ou vetor de identificadores de threads.


    AULA 12 ?? - REMOTA - Dia 3/04/2020

    Objetivos/Conteúdos

      • Conceito de Preempção
      • Critérios de Escalonamento
    • Algoritmos de Escalonamento
      • FCFS
      • Menor-Job-Primeiro
      • Prioridades
      • Round Robin

    Slides USados mna Aula

      • Slides do Livro do Professor Maziero e do Prof.Arliones

    Referências

    AULA 13 ?? - REMOTA - Dia 14/04/2020

    Objetivos/Conteúdos

    • Exemplo do Escalonador RR

    Código de Exemplo

    • Criar um relógio global para as demonstraçoes de funcionamento da API que foi criada
    /**
      User-level threads example.
     
      Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)
    */
    #include <stdio.h>
    #include <stdlib.h>
    #include <ucontext.h> /* for makecontext/swapcontext routines */
    #include <queue> /* C++ STL queue structure */
    #include <vector>
     
    #include<signal.h>
    #include<unistd.h>
    #include <ucontext.h>
    #include <sys/time.h>
     
    #define TIME_SLICE 1
     
    typedef void (*threadFn)(void);
     
    class thread_cb { // bloco de controle do thread
       int id_thread;
       public:
       ucontext_t contexto;
       //metodos que manipulam o thread control block
       thread_cb(threadFn p, int id) //construtor
       {
    	  int stackLen=4*1024;
    	  char *stack=new char[stackLen];
    	  getcontext(&contexto);
    	  contexto.uc_stack.ss_sp=stack;
    	  contexto.uc_stack.ss_size=stackLen;
    	  contexto.uc_stack.ss_flags=0;
    	  makecontext(&contexto,p,0);
    	  id_thread = id;
       };
       ucontext_t *get_context() {
         return &contexto;
       };
    };
     
    std::queue<class thread_cb *> ready_pool; // fila de pronto
     
    int id_thread = 0;
    int id1,id2,id3;
    
    class thread_cb *curr_thread=NULL;
     
    int add_thread(threadFn func) //criar thread e retornar o id do thread criad
    {
      class thread_cb *p = new thread_cb(func, ++id_thread);
      ready_pool.push(p);
      return id_thread;
    }
     
     
    void dispatcher(ucontext_t *old_task, ucontext_t *new_task)
    {
      if (old_task!=NULL)
          swapcontext(old_task, new_task);
      else
          setcontext(new_task);
    }
     
    void scheduler_rr()
    {
        class thread_cb *next,*last;
     
     
       if(curr_thread!=NULL) {
          printf("Aqui\n");
          ready_pool.push(curr_thread);
          last=curr_thread;
          next=ready_pool.front();
          ready_pool.pop();
          curr_thread=next;    
          dispatcher(last->get_context(), curr_thread->get_context()); 
       } else {
          next=ready_pool.front();
          ready_pool.pop();
          curr_thread = next;
          dispatcher(NULL, next->get_context());
       }
    }
     
    void sig_handler(int signo)
    {
     
      printf("SOP da Turma 2019-2: recebido SIGALRM\n");
      alarm(TIME_SLICE);   
     
    	if (ready_pool.empty()) {
    		printf("Nothing more to run!\n");
    		exit(0);
    	}
       scheduler_rr();
    }
     
    void preparar_handler()
    {
      if (signal(SIGALRM, sig_handler) == SIG_ERR) {
          printf("\nProblemas com SIGUSR1\n");
          exit(-1);
      }
      alarm(TIME_SLICE);
    }
    
    
    
    void runA(void)
    {
      int x=1;
      for (;;) {
           x++;
           printf("Thread A x=%d\n", x);
       }
    }
     
    void runB(void)
    {
        int x=1;
        for (;;) {
            x++;
            printf("Thread B x=%d\n", x);
            if(x>90000000L)
                yield_thread(); // abandonar a CPU
        }
    }
    
    void runC(void)
    {
        int x=1;
        for (;;) {
            x++;
            printf("Thread B x=%d\n", x);
            if (x>1000000L) //consultar um timer global 
                del_thread(id2);
        }
    }
    
    main()
    {
        id1 = add_thread(runA);
        id2 = add_thread(runB);
        id3 = add_thread(runC);
        preparar_handler();
        for(;;);
    }
    

    AULA 14 ?? - REMOTA - Dia 15/04/2020

    Objetivos/Conteúdos

    • aula somte para dúvidas...

    AULA 15 ?? - REMOTA - Dia 17/04/2020

    Objetivos/Conteúdos

    • Mecanismos de Sncronização

    Material de Referência

    Exemplo de remoção de itens de uma lista do stl

    #include <list>
    #include <iostream>
    using namespace std;
    
    int main()
    {
        struct tcb{
            int id;
        }  *p1,*p2,*p3;
        p1=new struct tcb;
        p1->id=3;
        p2=new struct tcb;
        p2->id=4;
        p3=new struct tcb;
        p3->id=7;
    
        list<struct tcb *> minhalista{ p1,p2,p3 };
        list<struct tcb *>::iterator it;
    
        it= minhalista.begin();
        while(it != minhalista.end()) {
            if ((*it)->id==4) {
                it = minhalista.erase(it);
            } else
                it++;
        }
    
        //imprimindo os ids de quem sobrou
        it= minhalista.begin();
        while(it != minhalista.end()) {
            cout << "ID = " << (*it)->id << "\n";
            it++;
        }
    
        return 0;
    }
    

    AULA 16 ?? - REMOTA - Dia 24/04/2020

    Objetivos/Conteúdos

    • Mecanismos de Sncronização
      • Conceito de Condição de Corrida
      • Conceito de Exclusão Mútua e Seção Crítica


    Material de Referência

    AULA 17 ?? - NÃO SÍNCRONA- Dia 28/04/2020

    Objetivos/Conteúdos

    • Mecanismos de Sincronização
      • Race Condition
      • Exclusão Mútua
      • Soluções Triviais
      • Algoritmo de Peterson
      • Instruções Atômicas

    Material de Referência

    Vídeos elaborados pelo Prof.Eraldo usando os slides/Capítulo 10 do Livro Prof. Carlos Maziero

    REUNIÃO - Dia 19/05/2020

    • ANPs

    AULA - SÍNCRONA- Dia 22/5/2020

    Objetivos

    • Revisão de Sistema Computacional (1.2 e 1.3 do Livro do Silberchatz)
    • Revisão de Serviços do Sistema Operacional
    • Revisão: PARTE 2A: Gerenciamento de Processos (cap.3 Silberchatz ed.8)
      • 3.1.Conceito de Processo (seção do livro)
      • 3.2.Escalonamento de Processos (seção do livro)
      • 3.3.Operações sobre Processos (seção do livro)
      • 4.1.Visão Geral de Threads (seção do livro)

    AULA - NÃO SÍNCRONA - Dia 22/5/2020

    Objetivos

    • Revisão: PARTE 2A: Gerenciamento de Processos (cap.3 Silberchatz ed.8)

    Material Sugerido para Revisão

    AULA SÍNCRONA - Dia 26/5/2020

    Objetivos

    • Uso da biblioteca libpthreads
    • Revisão de conceitos associados a threads

    Laboratório de libpthreads

    Parte 1

    POSIX ThreadsA API POSIX disponibiliza uma biblioteca de threads chamada pthread. As threads são implementadas pela estrutura pthread_t, e manipuladas pelas funções (acesse as man-pages das chamadas para maiores detalhes)
    • pthread_create: cria uma thread;
    • pthread_kill: força a terminação de uma thread;
    • pthread_join: sincroniza o final de uma thread (qual a diferença/semelhança com o wait que usamos para processos?);
    • pthread_exit: finaliza uma thread.

    Para utilizar estas funções é necessário linkar o programa à libpthread (-lpthread).


    Parte 2

    Exemplo básico de criação de threads do no POSIX Threads Programming

    1. Implemente o programa em [6]
    2. Compilar com:
     gcc -lpthread hello.c -o hello
    
    1. Executar:
     ./hello
    



    Parte 3

    Como o Linux enxerga os pthreads

    1. Faça uma modificação da função associada aos threads colocando um loop infinito após o Hello World
    2. O Linux "enxerga" estes threads? Confira com o comando htop


    Parte 4

    Observe o código abaixo.

    #include <stdio.h>
    
    #define TAM 3
    
    long double  vetor_A[TAM];
    
    
    void calcular_elemento(int i)
    {
      double x;
    
      for (x=0;x<=100;x=x+0.0000001){
         vetor_A[i] = vetor_A[i] + ((i+1)*x + (i+3))*0.0000001;
      }   
    }
     
    int main()
    {
      int i;
      
      /* solução sequencial */
      for (i=0;i<TAM;i++) {
             calcular_elemento(i);
      }   
    }
    


    1. Execute o programa com o auxílio do programa time. Anote o tempo de execução.
     time a.out
    
    1. Faça uma modificação para que o problema seja decomposto em threads explorando o número de cores físicos da sua máquina.
    2. Execute o programa com o auxílio do programa time. Compare com o tempo de execução sequencial.
     time a.out
    
    1. Faça uma variação do programa multithread para que o thread associado a função main aguarde os demais threads computando então a soma de todos os elementos do vetor. Veja exemplo em [7]


    Parte 5

    Repita o procedimeto da parte 4 para explorar os cores lógicos. Existe ganho real? Discuta.

    AULA SÍNCRONA - Dia 5/6/2020

    Objetivos/Conteúdos

    • Revisão de Mecanismos de Sincronização (já proposto em aula anterior)
      • Race Condition
      • Exclusão Mútua
      • Soluções Triviais
      • Algoritmo de Peterson
      • Instruções Atômicas
    • Laboratório

    Material de Referência

    Vídeos elaborados pelo Prof.Eraldo usando os slides/Capítulo 10 do Livro Prof. Carlos Maziero

    Slides do Livro do Silberschatz

    Laboratório de Race Condition, Algoritmo de Paterson e Mecanismos de Hardware (9/6?)

    1. Implemente e execute várias o exemplo abaixo de 2 threads acessando uma área comum de dados (conta). Estime o valor final na variável conta.

    Compare os resultados obtidos.

    #include <pthread.h>
    #include <stdio.h>
    #include <stdlib.h>
    #define NUM_THREADS	2
    
    /* based on https://computing.llnl.gov/tutorials/pthreads/samples/join.c */
    
    double conta=0;
    
    void *Thread1_DepositarConta(void *t)
    {
       int i;
       long tid;
      
       tid = (long)t;
       printf("Thread %ld iniciando...\n",tid);
       for (i=0; i<10000; i++){
    	   conta = conta+1;
       }
       pthread_exit((void*) t);
    }
    
    void *Thread2_DepositarConta(void *t)
    {
       int i;
       long tid;
      
       tid = (long)t;
       printf("Thread %ld iniciando...\n",tid);
       for (i=0; i<10000; i++){
    	   conta = conta+1;
       }
       pthread_exit((void*) t);
    }
    
    int main (int argc, char *argv[])
    {
       pthread_t thread[NUM_THREADS];
       pthread_attr_t attr;
       int rc;
       long t;
       void *status;
    
       /* Initialize and set thread detached attribute */
       pthread_attr_init(&attr);
       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
    
       for(t=0; t<NUM_THREADS; t++) {
          printf("Main: criando threads %ld\n", t);
          if(t==1)
             rc = pthread_create(&thread[t], &attr, Thread1_DepositarConta, (void *)t); 
          else
             rc = pthread_create(&thread[t], &attr, Thread2_DepositarConta, (void *)t);          
          if (rc) {
             printf("ERROR; return code from pthread_create() is %d\n", rc);
             exit(-1);
          }
       }
    
       /* Free attribute and wait for the other threads */
       pthread_attr_destroy(&attr);
       for(t=0; t<NUM_THREADS; t++) {
          rc = pthread_join(thread[t], &status);
          if (rc) {
             printf("ERROR; return code from pthread_join() is %d\n", rc);
             exit(-1);
          }
          printf("Main: esperando thread %ld having a status of %ld\n",t,(long)status);
       }
     
       printf("Main: Programa terminado - conta = %lf\n", conta);
       pthread_exit(NULL);
    }
    
    1. Reimplemente o programa acima com controle da entrada e saída da região crítica usando o algoritmo de Paterson.
    2. Reimplemente o programa acima com controle da entrada e saída da região crítica usando uma instrução simulada de TEST AND SET. Notar que neste caso

    a atomicidade da instrução não é garantida.

    AULA SÍNCRONA - Dia 19/06/2020

    Objetivos

    • Laboratório: Race Condition e Mutex
      • Explorar o problema de Race Condition
      • Resolver o problema de Race Condition com o Mutex
    • Conceito de Semáforo

    Laboratório Parte 1

    Estude o código abaixo e infira qual o valor da conta ao final da execução do programa.

    #include <pthread.h>
    #include <stdio.h>
    #include <stdlib.h>
    #define NUM_THREADS	2
    
    double conta=0;
    
    void *Thread1_DepositarConta(void *t)
    {
       int i;
       long tid;
      
       tid = (long)t;
       printf("Thread %ld iniciando...\n",tid);
       for (i=0; i<10000; i++){
    	   conta = conta+1;
       }
       pthread_exit((void*) t);
    }
    
    void *Thread2_DepositarConta(void *t)
    {
       int i;
       long tid;
      
       tid = (long)t;
       printf("Thread %ld iniciando...\n",tid);
       for (i=0; i<10000; i++){
    	   conta = conta+1;
       }
       pthread_exit((void*) t);
    }
    
    int main (int argc, char *argv[])
    {
       pthread_t thread[NUM_THREADS];
       pthread_attr_t attr;
       int rc;
       long t;
       void *status;
    
       /* Initialize and set thread detached attribute */
       pthread_attr_init(&attr);
       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
    
       for(t=0; t<NUM_THREADS; t++) {
          printf("Main: criando threads %ld\n", t);
          if(t==1)
             rc = pthread_create(&thread[t], &attr, Thread1_DepositarConta, (void *)t); 
          else
             rc = pthread_create(&thread[t], &attr, Thread2_DepositarConta, (void *)t);          
          if (rc) {
             printf("ERROR; return code from pthread_create() is %d\n", rc);
             exit(-1);
          }
       }
    
       /* Free attribute and wait for the other threads */
       pthread_attr_destroy(&attr);
       for(t=0; t<NUM_THREADS; t++) {
          rc = pthread_join(thread[t], &status);
          if (rc) {
             printf("ERROR; return code from pthread_join() is %d\n", rc);
             exit(-1);
          }
          printf("Main: esperando thread %ld having a status of %ld\n",t,(long)status);
       }
       printf("Conta = %lf\n", conta);
       return 0;
     }
    

    Laboratório Parte 2

    Proponha uma solução para o problema da Parte 1 usando uma solução trivial com BUSY WAIT. Quais os problemas de uma solução deste tipo? A ideia do busy wait seria algo do tipo:

          while(busy);  // entrada seção crítica
          busy=1;       //
          conta = conta+1;
          busy=0;       // saída seção crítica
    

    Laboratório Parte 3

    Proponha uma solução para o problema da Parte 1 usando uma solução baseada em mutex. Estude o mutex em [9]

    Laboratório Parte 4

    Teste a ideia do mutex servir como um lock para vários threads ou processos. Refaça o exercício da parte 3 para 10 threads =. Use uma única função de base para thread.

    Material de Referência

    AULA SÍNCRONA - Dia 23/06/2020

    Objetivos

    • Conceito de Semáforo e Mutex
    • Uso de Semáforos intra processo

    Laboratório

    Nos sistemas POSIX, semáforos são implementados pelo tipo sem_t e manipulado através das funções (acesse as man-pages das chamadas para maiores detalhes):

    • sem_init: inicializa um semáforo;
    • sem_destroy: destroy um semáforo;
    • sem_wait: implementa a operação p;
    • sem_post: implementa a operação v.

    Para utilizar estas funções é necessário linkar o programa à librt ou à libpthread (-lrt ou -lpthread).

    Ver exemplo em [10].

    PARTE 1

    Modifique o programa para usar um semáforo binário ao invés de um mutex em sua solução.

    PARTE 2

    Refaça o exercício da aula anterior criando dois tipos de tarefas (i) tarefas escritoras (atualizando o saldo) e (ii) tarefas leitoras. Crie 10 tarefas leitoras mas limite o acesso a leitura para no máximo 3 tarefas por vez.

    Material de Referência

    Avaliação 1

    Data: 3/Julho 2020

    Questionário - Processos

    1. Conceitue processo. Descreva e explique cada uma das seções de um processo na memória.
    2. Faça um diagrama e explique os possíveis estados de um processo no sistema. O que produz a transição entre estados?
    3. O que é um Bloco de Controle de Processo? Quais informações ficam armazenadas neste bloco?
    4. Faça um diagrama mostrando a alternância entre dois processos na CPU. Indique o procedimento de salvamento e restauração do estado do PCB.
    5. Explique o que é multiprogramação e escalonamento de processos.
    6. O que é a fila de processos prontos?
    7. Diferencie um processo limitado por IO de um processo limitado por CPU.
    8. Diferencie escalonamento de longo prazo de escalonamento de curto prazo.
    9. Discuta o papel da interrupção na troca de contexto entre processos.
    10. Explique como é o processo de criação de novos processos no UNIX/Linux através da chamada fork. O que acontece com a memória do novo processo?
    11. Explique como funciona a chamada exec no UNIX/Linux
    12. Explique como funciona a chamada wait no UNIX/Linux e como é possível retornar valores de um filho para o pai.
    13. Faça um esqueleto de um programa UNIX/Linux que ao se tornar processo cria 3 filhos e espera pela execução dos mesmos.

    Questionário - Comunicação entre Processos

    1. Diferenciar processos independentes de processos cooperantes.
    2. Enumere e explique quatro razões para cooperação entre processos.
    3. A velocidade de processamento é uma das razões da cooperação entre processos. Discuta se um hardware com apenas uma CPU pode usufruir desta característica.
    4. Descreva os dois principais mecanismos de cooperação entre processos. Discuta a situação em que é possível usar a memória compartilhada e/ou a troca de mensagens.
    5. A memória compartilhada requer chamada ao sistema na sua operação? Discuta.
    6. Por que o processo de troca de mensagem deve ser mais lento que a memória compartilhada?
    7. Apresente em pseudocódigo uma proposta de funcionamento do problema do produtor consumidor usando memória compartilhada.
    8. A construção de uma solução para o problema produtor consumidor pode ser facilitado pelo uso da memória compartilhada? Discuta.
    9. Quais as duas operações básicas ma troca de mensagens? O que poderia motivar o uso de mensagens do tamanho fixo? Esta abordagem torna mais complexa a vida dos programadores?
    10. Enumere três métodos de implementação de uma lógica de ligação (link) entre processos.
    11. Explique o que é a comunicação direta em troca de mensagens. Descreva como são as duas primitivas de comunicação direta para esta abordagem e quais as 3 propriedades seguidas por esta comunicação.
    12. Descreva a variante assimétrica da troca direta de mensagens. O que muda em termos de primitiva de comunicação?
    13. Descreva o problema de hard-coding associado a nomeação direta e como pode ser contornado através da nomeação/comunicação indireta?
    14. O que é uma caixa postal? Como o Posix identifica uma caixa postal no caso de fila de mensagens?
    15. Dois processos podem usar mais do que uma caixa postal para se comunicar? Qual a condição para que isto ocorra?
    16. Descreva as duas operações básicas para a troca de mensagens com Caixa Postal.
    17. Descreva na comunicação indireta via Caixa Postal as 3 propriedades básicas.
    18. A questão do compartilhamento de caixas postais por múltiplos processos podem causar um problema na operação da recepção. Descreva quais as 3 possibilidades para contornar este problema.
    19. De que forma a caixa postal estando no espaço de endereçamento de um processo (propriedade) afeta a recepção por mensagens? Descreva.
    20. Quais as operações sobre uma caixa postal criada no espaço do sistema operacional deverão ser disponíveis? Descreva.
    21. A transmissão de mensagem pode ser com e sem bloqueio. Descreva as 4 possibilidades (síncrona/assíncrona).
    22. Discuta as 3 possibilidades de armazenamento de mensagens em buffer. Em que condições um remetente pode ser bloqueado?


    AULA SÍNCRONA - Dia 26/06/2020

    Objetivos

    • Revisão do Conceito de Semáforo e Mutex
    • Uso de Semáforos intra processo
    • Problema Produtor Consumidor

    Material de Referência

    Laboratório

    Nos sistemas POSIX, semáforos são implementados pelo tipo sem_t e manipulado através das funções (acesse as man-pages das chamadas para maiores detalhes):

    • sem_init: inicializa um semáforo;
    • sem_destroy: destroy um semáforo;
    • sem_wait: implementa a operação p;
    • sem_post: implementa a operação v.

    Para utilizar estas funções é necessário linkar o programa à librt ou à libpthread (-lrt ou -lpthread).

    Ver exemplo em [11].

    PARTE 1
    Modifique o programa do laboratório anterior para usar um semáforo binário ao invés de um mutex em sua solução.
    PARTE 2
    Analise o código abaixo. Trata-se de uma implementação do problema produtor consumidor sem nenhum mecanismo de sincronização ou coordenação.

    Identifique a seção crítica.

    #include <stdio.h>
    #include <pthread.h>
    #include <semaphore.h>
    #include <unistd.h>
    
    
    #define BUFFER_SIZE 50
    
    sem_t mutex;
    volatile char fim=1;
    char buffer[BUFFER_SIZE];
    long disponivel=0; /* numero de itens ocupados no no buffer  */
    int in,out=0;
    int itens_prod=1;
    int soma_prod=0, soma_cons=0;
    
    void* produtor(void* arg)
    {
        char  prod=0;
        volatile long aux;
    
        do {
            while(disponivel == BUFFER_SIZE)
               ;
            buffer[in] = prod;
            soma_prod = soma_prod + prod;
            prod = (prod+1) % 5;
            in = (in + 1) % BUFFER_SIZE;
            //sem_wait(&mutex);
            disponivel = disponivel + 1;
            //sem_post(&mutex);
            printf("produzidos = %d\n", itens_prod++);
        } while (itens_prod!=900000);
        sleep(5); //tempo para encerrar
        fim=0;
        printf("TOTAL produzido = %d\n", soma_prod);
        pthread_exit(NULL);
    }
    
    void* consumidor(void* arg)
    {
        char consumo, consumo_ant='a';
        volatile long aux;
    
        do {
    
            while(disponivel == 0 && fim)
                ;
            if (fim==0)
                    break;
            consumo = buffer[out];
            soma_cons = soma_cons + consumo;
            out = (out + 1) % BUFFER_SIZE;
            //sem_wait(&mutex);
            disponivel = disponivel - 1;
            //sem_post(&mutex);
            printf("disponivel = %ld\n", disponivel);
        } while (fim);
        printf("TOTAL consumido = %d\n", soma_cons);
        pthread_exit(NULL);
    }
    
    int main()
    {
        int x;
        //sem_init(&mutex, 0, 1);
        pthread_t t1,t2;
        pthread_create(&t1,NULL,produtor,NULL);
        pthread_create(&t2,NULL,consumidor,NULL);
        printf("Tecle 1 e ENTER para FIM\n");
        scanf("%d", &x);
        fim = 0;
        pthread_join(t1,NULL);
        pthread_join(t2,NULL);
        //sem_destroy(&mutex);
        return 0;
    }
    
    PARTE 3
    Usando semáforos e mutex (ou semáforo binário), faça uma proposta de solução do problema produtor consumidor.
    PARTE 4
    Faça uma proposta para estender o problema para dois produtores e um consumidor.

    AULA SÍNCRONA - Dia 30/06/2020

    Objetivos

    • Conteúdos para avaliação
    • Problema Produtor Consumidor

    Referências

    • Livro Silberchatz: Cap.6 (versão 8)
    • Slides e Cap.11 e 12 do Livro do Prof.Maziero: Parte Semáforo e Mutex

    Conteúdos para Avaliação

    Tópico Referência Comentário
    Introdução e Estrutura do SIstema Operacional 1.1 a 1.8 Silberchatz
    2.1 a 2.7 + Laboratório System Call
    *Papel da Interrupção e Timers para os SOPs;


    • Conceito de multiprogramação, multitarefa e multiprocessamento;
    Processos: Conceitos e IPC 3.1 a 3.5 + Laboratórios de Processos, Pipes e Memória Compartilhada Ver [12]  
    Threads 4.1. a 4.4. + Laboratório de Threads: de aplicação e pthreads  
    Escalonamento do Processos Cap.6 Livro Prof.Maziero (até 6.4.5)[13] *Ver métricas/critérios para escalonamento;


    • ver como calcular os tempos de execução médio e tempo de espera;

    AULA SÍNCRONA - Dia 4/08/2020

    Objetivos

    • Introdução a Gerência de Meméoria
      • Vinculação de endereços lógicos aos físicos (8.1)
      • Swapping (8.2)

    Referência

    Slides Cap.7 Silberschatz

    AULA SÍNCRONA - Dia 7/08/2020

    Objetivos

    • Gerenciamento de Memória Contígua (8.2)
    • Paginação (8.4)
    • Agendar a nova (rec1) avaliação 1 - Sugestão: Disponibilizo na quarta que vem (dia 13/08) - Colocar ANPs complementares
    • Agendar a Avaliação 2 ?

    Referência

    Slides Cap.7 Silberschatz [14]

    AULA SÍNCRONA - Dia 11/08/2020

    Objetivos

    • Gerenciamento de Memória: Contígua, Paginação e Segmentação
    • Conceito de TLB
    • Hierarquia de Paginação

    Referência

    AULA SÍNCRONA - Dia 14/08/2020

    Objetivos

    • Técnicas para estender a memória RAM
    • Algoritmos de escolha de páginas vítima

    Referência


    AULA SÍNCRONA - Dia 18/08/2020

    Objetivos

    • Técnicas para estender a memória RAM (continuação)
    • Algoritmos de escolha de páginas vítima
    • Ver ANP repassada na wiki

    Referência

    REcuperação A1

    • Dia 28/08/2020
    • ver conteúdo tabela acima

    A2

    • Coordenação de Processos
    • Memória Virtual
    • Data 04/Set
    • Sexta: revisamos PRoblemas Classicos

    AULA SÍNCRONA - Dia 21/08/2020

    • Revisão Mecanismos de Coordenação - Preparação para Avaliação 2
    • Problemas Clássicos de Sincronização

    Material de Referência

    AULA - Dia 29/08/2020

    • AVALIAÇÂO 2

    AULA - Dia 1/09/2020

    Objetivos

    • Conceituar Arquivos, DIretórios e Sistemas de Arquivos
    • Atributos de Arquivos
    • Operações sobre arquivos

    ASSISTIR VÍDEO

    Tarefa

    • Ver questionário no SIGAA

    AULA - Dia 4/09/2020

    Objetivos

    • Uso de Arquivos
      • Operações sobre arquivos
      • Formas de Acessos
      • Permissões
      • Travas

    ReferÊncias

    TAREFA ANP

    VER NO SIGAA: TAREFA A3.1 - Permissionamento de Arquivos no Linux

    Adicional

    • Ver Silberschatz:
      • Interface de Sistema de Arquivos (cap.10)
      • Conceito de Arquivo (10.1):
      • Atributo de Arquivos (10.1.1),
      • Operações sobre Arquivos (10.1.2),
      • Tipos de Arquivos (10.1.3) e
      • Estrutura de Arquivos (10.1.4)
      • Métodos de Acesso (10.2)
      • Acesso Sequencial (10.2.1)
      • Acesso Direto (10.2.2)
      • Outros métodos de acesso (10.2.3)

    AULA - Dia 8/09/2020

    Objetivos

    • Implementação do Sistema de Arquivos

    Material de ReferÊncia

    AULA - Dia 11/09/2020

    Objetivos

    • Implementação do Sistema de Arquivos (Continuação)

    Material de ReferÊncia

    AULA - Dia 15/09/2020

    Objetivos

    • Subsistema de IO: Hardware de IO
    • Avaliação 3 - Dia 25/09/2020 - Prova Objetiva (diferente para cada aluno - 50% Tarefa ANP)
    • Recuperação da Avaliação 1 - Dia 2/10

    Referências

    AULA - Dia 18/09/2020

    Objetivos

    • Projeto Final: Parte 1


    Projeto Final

    Desenvolvimento do um Char Device Driver para Linux baseado em proj1 2020 Universidade do Porto O objetivo final do projeto é um serial device driver a ser testado entre duas VMs.

    Etapa 1

    • Lab 1 - Instalação da VM com o CICA2
    • Lab 2
      • Driver Hello World Personalizado

    AULA - Dia 22/09/2020

    Objetivos

    • Projeto Final: Parte 2
    • Lembrar que Sexta (25) será passada a AVAL.3 (questões objetivas)

    PARTE 2 - ECHO DEVICE

    Seguir instruções de proj1 2020 Universidade do Porto

    Fazer: -registro do major e minor number -criação do device echo_device -criação das funções open, read, write e close

    AULA - Dia 25/09/2020

    Objetivos

    • Avaliação 3

    AULA - Dia 29/09/2020

    Objetivos

    • Rec. Aval 1 - Dia 6/10/2020
    • Projeto: Visão Geral de onde podemos chegar...
    • Projeto Final: Parte 2 (continuação)


    AULA - Dia 2/10/2020

    Objetivos

    #include <stdio.h>
    
    #define DIM_1 2
    #define DIM_2 3
    #define DIM_3 4
    
    int main()
    {
      int matA[DIM_1][DIM_2]={{2,5,7},
                              {4,7,5}
                             },
          matB[DIM_2][DIM_3]={{7,5,6,4},
                              {4,6,4,3},
                              {9,2,2,1}
                              },
          matR[DIM_1][DIM_3] ={
                               {0,0,0,0},
                               {0,0,0,0}
                              },
          i,j,k;
    
    
      for (i=0;i<DIM_1;i++) 
         for (j=0;j<DIM_3;j++) {
            for (k=0;k<DIM_2;k++)
                 matR[i][j]=matR[i][j]+matA[i][k]*matB[k][j];
            printf("MatR[%d][%d] => %d \n", i, j,  matR[i][j]);
         } 
      return 0;     
    }
    

    AULA DIA Dia 9/10/2020

    Objetivos

    • Acompanhamento Projeto Final
    • Echo Driver


    AULA DIA Dia 13/10/2020

    Objetivos

    Reconfigurar teclado do CICA2

    sudo dpkg-reconfigure console-data

    Escolher o teclado abnt2