https://wiki.sj.ifsc.edu.br/api.php?action=feedcontributions&user=127.0.0.1&feedformat=atomMediaWiki do Campus São José - Contribuições do(a) usuário(a) [pt-br]2024-03-28T08:35:53ZContribuições do(a) usuário(a)MediaWiki 1.35.9https://wiki.sj.ifsc.edu.br/index.php?title=Arquivo:Exerc%C3%ADcios_PJI_preprova.odt&diff=162124Arquivo:Exercícios PJI preprova.odt2019-10-09T17:55:52Z<p>127.0.0.1: </p>
<hr />
<div></div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=INF-2019-2&diff=162120INF-2019-22019-10-09T17:01:07Z<p>127.0.0.1: </p>
<hr />
<div>=Informática Básica II= <br />
<br />
'''Professores:''' <br />
*Elen Macedo Lobato - elen@ifsc.edu.br <br />
*Volnei Velleda Rodrigues - volnei@ifsc.edu.br<br />
<br>'''Encontros:''' Quarta-feira / 20h40min-22 horas<br />
<br />
=31/07/2019: Apresentação da disciplina, introdução ao Libreoffice Writer=<br />
<font size="3"><br />
{{Collapse top | Aula 1}}<br />
===Apresentação da disciplina===<br />
<br />
Introdução ao componente curricular e Introdução ao Libreoffice.<br />
<br />
O LibreOffice é uma ferramenta do tipo “office” totalmente gratuita e de código aberto.<br />
<br />
Mas quais os motivos para usarmos o Libreoffice?<br />
<br />
* O LibreOffice é um conjunto de softwares de uso profissional ou doméstico ideal para quem quer uma suíte de escritório para o dia a dia e não deseja softwares desatualizadas e independentes.<br />
* Toda a interface do LibreOffice é padronizada, assim como acontece com o Microsoft Office. Conjuntos e ícones e funcionalidades são semelhantes em toda a interface do usuário. As teclas de atalho são diferentes dos utilizados em outras soluções, porém são bem simples de memorizar.<br />
* O LibreOffice pode ser instalado e utilizado de uma forma [https://pt-br.libreoffice.org/baixe-ja/portable-versions/ portátil], sem necessidade de instalação no computador de uso.<br />
* O LibreOffice é compatível com todos os formatos gerados pelos aplicativos Microsoft, inclusive os documentos mais antigos, tais como DOC, XLS e PPT.<br />
* O LibreOffice é um software de código aberto e grátis. Pode ser instalados em diversos computadores e ser utilizado para qualquer finalidade.<br />
<br />
No decorrer do curso iremos trabalhar com os seguintes softwares:<br />
<br />
'''LibreOffice Writer:'''<br />
<br />
O Writer é o processador de texto do LibreOffice e é um software similar ao Microsoft Word. Com o Writer é possível criar desde textos simples, até textos com padrões complexos, com imagens, tabelas, anotações, estilos e numeração de páginas. Sua interface lembra o Word na versão 2000 e as barras de ferramentas são personalizáveis assim como todos os outros softwares que acompanham o pacote LibreOffice.<br />
<br />
<br />
'''LibreOffice Calc:'''<br />
<br />
O Calc é o editor de planilhas eletrônicas do LibreOffice e é um software similar ao Microsoft Excel. Com o Calc é possível criar planilhas e gráficos de todos os tipos, com imagens, formatação de texto e bordas. Sua interface lembra o Excel 2000 e as barras de ferramentas são personalizáveis assim como todos os outros softwares que acompanham o pacote LibreOffice.<br />
<br />
<br />
'''LibreOffice Impress:'''<br />
<br />
O Impress é o criador de apresentações do LibreOffice e é um software similar ao Microsoft Power Point. Com o Impress é possível criar apresentações de todos tipos, com diversos slides, imagens, formas, animações e transições. Sua interface lembra o Power Point 2000 e as barras de ferramentas são personalizáveis assim como todos os outros softwares que acompanham o pacote LibreOffice.<br />
<br />
<br />
<br />
===LibreOffice Writer===<br />
<br />
<br />
Para a maioria das nossas atividades no software Writer, nós faremos uso de textos.<br />
<br />
Vamos conhecer um pouco de sua interface:<br />
<br />
<div style="text-align: center;">[[Arquivo:writerinterface.jpg|900px]]</div><br />
bit.ly/inf-2018-2<br />
As barras de ferramentas podem ser movidas, de acordo com a necessidade ou preferência:<br />
<br />
<div style="text-align: center;">[[Arquivo:moverbarra.jpg|900px]]</div><br />
<br />
<br />
As funções dos botões também podem ser acessadas via teclas de atalho:<br />
<br />
Teclas de função para o LibreOffice Writer<br />
<br />
<div style="text-align: center;">[[Arquivo:atalho1.jpg]]</div><br />
<br />
<br />
Teclas de atalho para controlar documentos e janelas<br />
<br />
<div style="text-align: center;">[[Arquivo:atalho2.jpg]]</div><br />
<br />
<br />
Teclas de atalho para editar ou formatar documentos<br />
<br />
<div style="text-align: center;">[[Arquivo:atalho3.jpg]]</div><br />
<br />
<br />
A extensão padrão do arquivo é '''ODT'''. Se salvarmos um arquivo com o nome '''Exemplo''', o mesmo se chamará '''Exemplo.odt'''.<br />
<br />
Para selecionarmos o texto, podemos utilizar o mouse ou o teclado, através da tecla '''SHIFT''' + '''SETA DIRECIONAL'''.<br />
</font><br />
{{Collapse bottom | Aula 1}}<br />
<br />
=07/08/2019: Formatação e alinhamento=<br />
<font size="3"><br />
{{Collapse top | Aula 2}}<br />
<br />
===Barra de ferramentas Formatação===<br />
<br />
A barra de Formatação permite alterar as configurações relacionadas ao texto em si, como fonte, tamanho de fonte, estilos, negrito, sublinhado, etc.<br />
<br />
<div style="text-align: left;">[[Arquivo:barraformatacao.jpg]]</div><br />
<br />
Estilos e Formatação (F11): Exibe a janela Estilos e Formatação (abaixo) que exibe os estilos pré-definidos e também permite salvar configurações relativas ao tamanho e cor da fonte, espaçamento entre linhas do parágrafo. É possível alterar os estilos existentes ou mesmo criar novos.<br />
<br />
<div style="text-align: left;">[[Arquivo:estilowriter.jpg]]</div><br />
<br />
<br />
Nesta caixa de seleção escolhemos a fonte:<br />
<br />
<div style="text-align: left;">[[Arquivo:fontewriter.jpg]]</div><br />
<br />
<br />
Permite definir o tamanho da fonte, entre 2 e 999,9:<br />
<br />
<div style="text-align: left;">[[Arquivo:tamanhofontewriter.jpg]]</div><br />
<br />
<br />
Aplicam negrito, itálico e sublinhado respectivamente. Atalhos CTRL+B, CTRL+I e CTRL+U:<br />
<br />
<div style="text-align: left;">[[Arquivo:niswriter.jpg]]</div><br />
<br />
<br />
Aqui estão os possíveis alinhamentos para os parágrafos e são extremamente cobrados em concursos. <br />
<br />
<div style="text-align: left;">[[Arquivo:alinhamentowriter.jpg]]</div><br />
<br />
<br />
Alinhamento à esquerda. Atalho CTRL + L.<br />
<br />
Obs.: Quando o parágrafo está alinhado a esquerda fica desalinhado a direita.<br />
<br />
Alinhamento Centralizado. Atalho CTRL + E.<br />
<br />
Obs.: Quando o parágrafo está centralizado fica desalinhado a esquerda e a direita.<br />
<br />
Alinhamento à Direita. Atalho CTRL + R.<br />
<br />
Obs.: Quando o parágrafo está alinhado a direita fica desalinhado a esquerda.<br />
<br />
Alinhamento Justificado. Atalho CTRL + J.<br />
<br />
Obs.: Quando o parágrafo está justificado fica alinhado a direita e a esquerda.<br />
<br />
Dica: Para aplicar qualquer alinhamento a um parágrafo não é preciso selecionar o parágrafo, basta que o cursor esteja dentro do parágrafo.<br />
<br />
<br />
Cor da Fonte. Permite alterar a cor da fonte.<br />
<br />
<div style="text-align: left;">[[Arquivo:corfontewriter.jpg]]</div><br />
<br />
<br />
Dica: Não é preciso selecionar a palavra que se deseja alterar a cor da fonte, basta que o cursor esteja posicionado dentro da palavra.<br />
<br />
<br />
Realçar. Permite realçar um texto com várias cores.<br />
<br />
<div style="text-align: left;">[[Arquivo:realcewriter.jpg]]</div><br />
<br />
<br />
Cor do Plano de Fundo. Permite alterar a cor do plano de fundo da posição onde o cursor está ou no trecho selecionado.<br />
<br />
<div style="text-align: left;">[[Arquivo:corfundowriter.jpg]]</div><br />
<br />
<br />
'''Exercício'''<br />
<br />
<br />
<div style="text-align: center;">'''O Conceito de Mercado'''</div><br />
<br />
<br />
O conceito de <u>mercado</u> continua intimamente associado à idéia de <u>local</u> onde se efetuam transações entre produtores e consumidores. Consideramos essa noção restritiva, pelos seguintes aspectos:<br />
O mercado é hoje um espaço de realização de operações econômicas de compra e venda que vai para além dos seus contornos <u>físicos</u> e mesmo <u>temporais</u>.<br />
De fato, estão a surgir com grande freqüência <u>formas imateriais de mercado</u> (…).<br />
Essas formas de mercado lançam mão dos meios proporcionados pela sociedade de informação, possibilitando a realização de compras e vendas em casa, pela simples manutenção interativa de um ecrã de televisão ou, mais simplesmente, através de um telefonema para um número fornecido por aquele ecrã, com entrega imediata no domicilio ou pelo correio, como é uso da chamada televisão comercial.<br />
Existem operações de compra e venda que se contratam hoje e se realizam apenas daqui a alguns meses (como por exemplo, nos mercados de futuros, caso dos mercados de cereais nos Estados Unidos da América,...).<br />
Por outro lado existe uma diversidade de mercados, que vai desde os mercados de produtos finais ou de consumo final aos mercados de produtos intermédios e de fatores produtivos, bem como ao mercado de trabalho ou à bolsa ou <u>mercado de valores imobiliários</u>. Aos mercados nacionais sobrepõem-se os <u>mercados transnacionais</u>, de natureza informal, ou de diversos acordos de comércio livre, uniões aduaneiras ou comunidades econômicas.<br />
Tudo são razões para que se considere a noção de mercado como relativa e circunstancial, além de mutável no tempo.<br />
Uma coisa é certa: num mercado existem sempre intenções de compra (compra), intenções de venda (<u>oferta</u>), um preço e uma situação de equilíbrio mais ou menos estável fornecida por esse preço e pela quantidade correspondente.<br />
<br />
<br />
<div style="text-align: right;">Extraído de: Tinto, G., Introdução à Economia, 1995.</div><br />
<br />
<br />
# Grave o documento com o nome '''Exercicio1_Writer_Nome_Aluno'''.<br />
# Centralize o título “O Conceito de Mercado” no texto.<br />
# Formate o título como: '''negrito, tamanho 16''', tipo de letra '''Dejavu Sans'''.<br />
# Efetue o '''alinhamento justificado''' do texto.<br />
# Formate o texto com a fonte '''Nimbus Sans L''' e tamanho '''11'''<br />
# '''Alinhe à direita''' a fonte de onde foi extraído o texto (última linha) e coloque o texto em '''itálico'''<br />
# Marque a '''bold''' (negrito) os termos/expressões sublinhados acima<br />
# Anule os sublinhados e mantenha o negrito dos mesmos termos expressões<br />
# Coloque a '''negrito, itálico e sublinhada''' todas as ocorrências das palavras compra e compras.<br />
<br />
<br />
Envie este arquivo editado para o e-mail de seu(sua) professor(a).<br />
<br />
</font><br />
{{Collapse bottom | Aula 2}}<br />
<br />
=14/08/2019: Formatações de parágrafo, localizar e substituir=<br />
<font size="3"><br />
{{Collapse top | Aula 3}}<br />
<br />
===Comando Localizar e Substituir===<br />
Para se localizar palavras em um texto qualquer, basta que você acesse o menu '''Editar, Localizar''' ou por meio do atalho '''Ctrl + F'''. Logo será aberto, no canto inferior esquerdo do aplicativo, um campo para digitação da palavra a ser procurada.<br />
<br />
<div style="text-align: left;">[[Arquivo:localizarwriter.jpg]]</div><br />
<br />
O recurso para “localizar e substituir” também é muito importante pois nos auxilia a corrigir erros espalhados pelo texto ou mesmo a mudança de uma palavra por outra de mesmo significado. Para usarmos o recurso de “localizar e substituir” basta acessarmos o menu '''Editar, Localizar e substituir''' ou diretamente pelo atalho '''Ctrl + H'''.<br />
<br />
<div style="text-align: left;">[[Arquivo:localizarsubstituirwriter.jpg]]</div><br />
<br />
<br />
===Ferramenta Pincel===<br />
Esse comando copia toda a formatação de um objeto ou texto e aplica ao objeto que será clicado ou marcado a seguir. O Pincel não se encontra em um item de menu específico, porém, possui um botão na barra de ferramentas padrão, conforme Figura a seguir.<br />
<br />
<div style="text-align: left;">[[Arquivo:pincelwriter.jpg]]</div><br />
<br />
Como utilizar o Pincel:<br />
* Primeiro clique na palavra ou objeto que você deseja copiar os formatos nele aplicados (por exemplo tipo da fonte, tamanho e etc.);<br />
* Em seguida, clique na palavra a qual você deseja que possua os mesmos formatos da palavra anterior (a que você copiou os formatos).<br />
<br />
===Recuos e espaçamentos===<br />
Este recurso permite alterar a posição inicial, final e primeira linha do texto.<br />
<br />
Escolha a guia Formatar - Parágrafo - Recuos e espaçamento<br />
<br />
<div style="text-align: left;">[[Arquivo:recuoespacamentowriter.jpg]]</div><br />
<br />
A opção '''Antes do texto''' permite indicar onde o texto irá iniciar.<br />
<br />
A opção '''Depois do texto''' indica onde ele irá terminar.<br />
<br />
Já a opção '''Primeira linha''' indica onde a primeira linha do parágrafo irá iniciar.<br />
<br />
As opções '''Acima do parágrafo''' e '''Abaixo do parágrafo''' indicam o espaçamento entre as linhas antes e depois de um parágrafo, respectivamente.<br />
<br />
A opção '''Entre linhas''' define o espaço entre cada linha do texto.<br />
<br />
<br />
===Exercício 2===<br />
# Copie e cole o texto abaixo em um novo documento do '''LibreOffice Writer'''.<br />
# Grave o documento com o nome "Ex2_Writer_seu nome.odt". <br />
# O título do texto deve estar em '''Arial, tamanho 22, negrito e centralizado'''.<br />
# O corpo do texto deve estar em '''Arial, tamanho 12'''.<br />
# Vá na opção '''formatar parágrafo, Recuos e espaçamentos'''. O parágrafo do corpo do texto deve estar '''justificado, primeira linha 1,5 cm, espaço embaixo do parágrafo 0,5 cm'''.<br />
# Deixe todas as demais opções de medidas do parágrafo com valor '''0 cm''' e '''espaçamento de linha simples'''<br />
# Use a ferramenta '''Localizar e substituir''' para localizar a palavra Haiti e substituir por '''Haiti'''.<br />
# As palavras '''Ayiti''' e '''La Perle des Antilles ''' devem estar em itálico.<br />
# A referência do texto deve ser formatada da seguinte forma:'''letra estilo Arial, tamanho 10, parágrafo alinhado à direita'''.<br />
<br />
<br />
<br />
<div style="text-align: center;">'''Haiti'''</div><br />
<br />
:O Haiti, oficialmente República do Haiti, é um país do Caribe. Ocupa uma pequena porção ocidental da ilha de Hispaniola, no arquipélago das Grandes Antilhas, que partilha com a República Dominicana. Ayiti ("terra de altas montanhas") era o nome indígena dos taínos para a ilha.<br />
:Em francês o país é chamado de La Perle des Antilles (A Pérola das Antilhas), por conta de sua beleza natural. O ponto mais alto do país é Pic la Selle, com 2.680 metros de altitude. Tanto em área quanto em população, o Haiti é o terceiro maior país do Caribe (depois de Cuba e da República Dominicana), com 27.750 quilômetros quadrados e cerca de 10,4 milhões de habitantes, sendo que pouco menos de um milhão deles vivem na capital, Porto Príncipe. O francês e o crioulo Haitiano são as línguas oficiais do país.<br />
:A posição histórica e etno-linguística do Haiti é única por várias razões. Quando conquistou a independência em 1804, se tornou a primeira nação independente da América Latina e do Caribe, sendo o único país do mundo estabelecido como resultado de uma revolta de escravos bem-sucedida e a segunda república da América. A Revolução Haitiana, feita por escravos e negros libertos, durou quase uma década; todos os primeiros líderes do governo foram antigos escravos. O país é uma das duas nações independentes do continente americano (junto com o Canadá) que designa o francês como língua oficial; as outras áreas de língua francesa no continente são todos departamentos ou coletividades ultramarinas da França.<br />
:O Haiti é o mais populoso membro pleno da Comunidade do Caribe (CARICOM). O país também é um membro da União Latina. Em 2012, o Haiti anunciou sua intenção de obter o estatuto de membro associado da União Africana. É o país mais pobre da América, medido pelo Índice de Desenvolvimento Humano (IDH). A violência política tem ocorrido regularmente ao longo da história do país, o que levou a instabilidade no governo. Mais recentemente, em fevereiro de 2004, um golpe de Estado originário do norte do país forçou a renúncia e o exílio do presidente Jean-Bertrand Aristide. Um governo provisório assumiu o controle com a segurança proporcionada pela Missão das Nações Unidas para a estabilização no Haiti.<br />
<div style="text-align: right;">Texto adaptado de: https://pt.wikipedia.org/wiki/Haiti</div> <br />
<div style="text-align: right;">Acessado em 12/08/2019</div> <br />
<br />
<br />
'''Como o texto deve ficar ao final do exercício:'''<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:exercicio2_write_2019.jpg]]</div><br />
<br />
<br />
'''Salve o arquivo e envie para o e-mail: elen@ifsc.edu.br ou pedroarmando@ifsc.edu.br.'''<br />
<br />
<br />
<br />
</font><br />
{{Collapse bottom | Aula 3}}<br />
<br />
=21/08/2019: Formatações de parágrafo (exercício extra)=<br />
<font size="3"><br />
{{Collapse top | Aula 4}}<br />
<br />
<br />
===Exercício 3===<br />
# Copie e cole o texto abaixo em um novo documento do '''LibreOffice Writer'''.<br />
# Grave o documento com o nome "Ex3_Writer_seu nome.odt". <br />
# O título do texto deve estar em '''Avdira, tamanho 16 e negrito'''.<br />
# Vá na opção '''formatar parágrafo, Recuos e espaçamentos'''. O parágrafo do título do texto deve estar '''centralizado e espaço depois do parágrafo 0,5 cm'''. Deixe todas as demais opções com valor '''0 cm''' e '''espaçamento de linha simples'''.<br />
# O corpo do texto introdutório deve estar em '''Avdira, tamanho 9'''.<br />
# Vá na opção '''formatar parágrafo, Recuos e espaçamentos'''. O parágrafo do corpo do texto deve estar '''justificado, primeira linha 1,5 cm, espaço depois do parágrafo 0,3 cm'''. Deixe todas as demais opções de medidas com valor '''0 cm''' e '''espaçamento de linha simples'''<br />
# O título do poema deve estar em '''Anaktoria, tamanho 14, negrito'''.<br />
# O parágrafo do título do poema deve estar '''alinhado à esquerda, recuo antes do texto 2 cm, acima do parágrafo 0,5 cm e Abaixo do parágrafo 0,5 cm''', todas as demais medidas do parágrafo devem ser 0 cm.<br />
# O texto do poema deve estar em '''Anaktoria, tamanho 11'''.<br />
# Os parágrafos dos versos do poema devem estar '''alinhado à esquerda, recuo antes do texto de 1 cm para os versos ímpares e de 3 cm para os versos pares,''', todas as demais medidas do parágrafo devem ser 0 cm.<br />
# Somente os parágrafos da última linha de cada verso devem ser formatado com "espaçamento depois do parágrafo de 0,5 cm"<br />
# A referência do texto deve ser formatada da seguinte forma:'''letra estilo Courier, tamanho 9, parágrafo alinhado à direita'''.<br />
# Salve o arquivo e envie para o e-mail: "elen@ifsc.edu.br" ou "pedroarmando@ifsc.edu.br."<br />
<br />
<br />
<div style="text-align: center;">'''Canção do Exílio de Gonçalves Dias'''</div><br />
<br />
:"Canção do Exílio" é uma poesia romântica de Gonçalves Dias escrita em 1843 e introduzida na obra lírica Primeiros Cantos, de 1846. Foi produzida no primeiro momento do Romantismo no Brasil, época na qual se vivia uma forte onda de nacionalismo, que se devia ao recente rompimento do Brasil colônia com Portugal. O poeta trata, neste sentido, de demonstrar aversão aos valores portugueses e ressaltar os valores naturais do Brasil. <br />
:Apesar de ser um texto de profunda glorificação à pátria, o poema possui total ausência de adjetivos qualificativos. São os advérbios “lá, cá, aqui” que nos localizam geograficamente no poema. Formalmente, o poema apresenta redondilhas maiores (sete sílabas em cada verso) e rimas oxítonas (lá, cá, sabiá), com a exceção da segunda estrofe. <br />
:Quando Gonçalves Dias escreveu este poema, cursava a Faculdade de Direito de Coimbra, em julho de 1843. Vivia, desta forma, um exílio físico e geográfico. Tradicionalmente, esta é a situação do exílio.<br />
<br />
<br />
<br />
:'''Canção do Exílio'''<br />
<br />
<br />
<div style="text-align: left;">Minha terra tem palmeiras,</div><br />
<div style="text-align: left;">Onde canta o Sabiá;</div><br />
<div style="text-align: left;">As aves, que aqui gorjeiam,</div><br />
<div style="text-align: left;">Não gorjeiam como lá.</div><br />
<br />
:Nosso céu tem mais estrelas, <br />
:Nossas várzeas têm mais flores, <br />
:Nossos bosques têm mais vida, <br />
:Nossa vida mais amores.<br />
<br />
<div style="text-align: left;">Em cismar – sozinho – à noite –</div><br />
<div style="text-align: left;">Mais prazer encontro eu lá;</div><br />
<div style="text-align: left;">Minha terra tem palmeiras; </div><br />
<div style="text-align: left;">Onde canta o Sabiá.</div><br />
<br />
:Minha terra tem primores, <br />
:Que tais não encontro eu cá; <br />
:Em cismar – sozinho – à noite – <br />
:Mais prazer encontro eu lá; <br />
:Minha terra tem palmeiras,<br />
:Onde canta o Sabiá.<br />
<br />
<div style="text-align: left;">Não permita Deus que eu morra, </div><br />
<div style="text-align: left;">Sem que eu volte para lá;</div><br />
<div style="text-align: left;">Sem que eu desfrute os primores </div><br />
<div style="text-align: left;">Que não encontro por cá;</div><br />
<div style="text-align: left;">Sem qu'inda aviste as palmeiras,</div><br />
<div style="text-align: left;">Onde canta o Sabiá.</div><br />
<br />
<br />
:Texto adaptado de: https://pt.wikipedia.org/wiki/Canção_do_Exílio <br />
:Acessado em 13/08/2019 <br />
<br />
<br />
'''Como o texto deve ficar ao final do exercício:'''<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:exercicio3_write_2019_CExilio.jpg]]</div><br />
<br />
<br />
<br />
</font><br />
{{Collapse bottom | Aula 4}}<br />
<br />
=28/08/2019: Colunas, capitular e hifenização=<br />
<font size="3"><br />
{{Collapse top | Aula 5}}<br />
<br />
===Criando colunas===<br />
<br />
<br />
O Writer permite criar colunas em seus documentos de texto. É possível inserir colunas em um estilo de página ou em um bloco individual de texto, sendo possível ainda formatar o layout da coluna de acordo com suas preferências:<br />
<br />
* Inserir colunas em um estilo de página;<br />
* Inserir colunas a um bloco de texto individual;<br />
* Formatar um layout de coluna;<br />
* Reverter para um layout de coluna simples.<br />
<br />
<br />
====Inserindo colunas em um estilo de página====<br />
<br />
<br />
Para inserir uma coluna em um estilo de página, clique em qualquer lugar da página e escolha Formatar > Colunas... no menu principal. Abre-se a janela Colunas:<br />
<br />
<div style="text-align: left;">[[Arquivo:colunaswriter.jpg]]</div><br />
<br />
<br />
====Inserindo colunas em um bloco de texto====<br />
<br />
<br />
Também é possível inserir colunas em um bloco de texto individual. Isso é útil caso não se queira modificar o estilo da página, ou se você quiser inserir colunas dentro de colunas. Observe que o Writer criará automaticamente uma seção a partir do bloco de texto selecionado. Uma seção é simplesmente um bloco de texto que tem uma formatação especial.<br />
<br />
Para inserir uma coluna em um bloco individual de texto, selecione o texto desejado, escolhendo em seguida Formatar > Colunas... a partir do menu principal. Abre-se a janela Colunas.<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:colunaswriter2.jpg]]</div><br />
<br />
Se você inserir colunas em um bloco de texto, é possível escolher como você deseja distribuir o texto pela coluna. È possível distribuir o texto de uma ou duas maneiras:<br />
<br />
* Uniformemente. Se você escolher distribuir o texto uniformemente, o Writer preencherá a primeira linha de cada coluna, seguindo para a segunda linha de cada coluna, e assim por diante.<br />
* Estilo Jornal. Se você escolher distribuir o texto em Estilo Jornal, o Writer preencherá as colunas uma por vez, começando pela primeira coluna.<br />
<br />
Para distribuir o texto uniformemente, marque a caixa de seleção Distribuir conteúdo uniformemente em todas todas as colunas na área Configurações. Desmarque esta caixa de seleção se você quiser distribuir o texto no estilo jornal.<br />
<br />
<br />
====Especificando o número de colunas====<br />
<br />
<br />
Se preferir criar um layout de coluna personalizado, você deverá especifcar o número de colunas desejado. Insira o número desejado na caixa Colunas da área Configurações.<br />
<br />
<br />
====Formatando a largura e o espaçamento da coluna====<br />
<br />
<br />
Para criar colunas com espaçamento uniforme com a mesma largura, marque a caixa de seleção AutoLargura na área Largura e espaçamento.<br />
<br />
Para personalizar a largura e o espaçamento das colunas, siga as seguintes etapas:<br />
<br />
* Na área de Largura e espaçamento, desmarque a caixa de seleção AutoLargura.<br />
* Na linha Largura, insira uma largura para cada coluna.<br />
* Na linha Espaçamento, insira o valor de espaçamento desejado entre cada par de coluna.<br />
<br />
Utilize as teclas direcionais na linha Coluna para rolar pelas colunas.<br />
<br />
<br />
====Formatando as linhas separadoras====<br />
<br />
<br />
Para exibir as linhas separadoras entre as colunas, siga as seguintes etapas:<br />
<br />
* A partir da lista suspensa Linha na área Linha separadora, selecione o tipo de linha desejado.<br />
* Por padrão, as linhas separadoras têm o mesmo tamanho das colunas. Caso deseje que as linhas separadoras sejam mais curtas do que a coluna, utilize a caixa Altura para inserir a altura das linhas separadoras como uma porcentagem do tamanho das colunas. Por exemplo, se você inserir 50%, as linhas separadoras terão metade do tamanho das colunas.<br />
* Se você inseriu uma altura menor do que 100%, use a lista suspensa Posição para selecionar um alinhamento vertical para as linhas do separador.<br />
<br />
<br />
====Revertendo o layout de uma coluna simples====<br />
<br />
<br />
Para reverter o layout de uma coluna simples em um estilo de página ou em um bloco de texto:<br />
<br />
* Clique em qualquer local no layout da coluna.<br />
* A partir do menu principal, escolha Formatar > Colunas... A janela Colunas aparece. <br />
* Na área Configurações, clique no layout de coluna simples localizado no lado esquerdo da caixa Colunas . Ou, volte a caixa Colunas para 1.<br />
* Clique em OK. A janela Colunas se fecha e o layout é revertido para uma coluna simples.<br />
<br />
<br />
===Capitulares===<br />
<br />
<br />
Basta somente você deixar o cursor no parágrafo que você deseja a primeira letra capitulada. Vá no meu Parágrafo e escolha a guia Capitulares. Na parte de Configurações, ative a caixa Exibir capitulares. Também pode escolher o número de caracteres, se vai utilizar a palavra inteira, quantidade de linhas a serem utilizadas, espaçamento até o texto e estilo do caractere. Após efetuar as configurações, clique em Ok.<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:capitulareswriter.jpg]]</div><br />
<br />
<br />
===Hifenização===<br />
<br />
<br />
Insere hifens nas palavras grandes demais para caber no fim da linha. O LibreOffice procura no documento e sugere uma hifenização que possa ser aceita ou rejeitada. Se o texto estiver selecionado, a caixa de diálogo Hifenização atuará somente no texto selecionado. Se não houver texto selecionado, a caixa de diálogo Hifenização atuará em todo o documento.<br />
<br />
<br />
Agora, para colocar Hifenização, é bem simples, pressione Ctrl + A, para selecionar tudo ou selecione a parte do texto que deseja hifenizar e depois justifique o texto. Logo em seguida, clique em Ferramentas > Idioma > Hifenização. Depois, é só confirmar quais palavras que deseja hifenizar ou clicar em hifenizar tudo e pressione OK.<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:hifenizacaowriter.jpg]]</div><br />
<br />
===Exercício 4===<br />
<br />
<br />
Copie o texto abaixo e posteriormente efetue os ajustes pedidos:<br />
<br />
<br />
----<br />
<br />
* Copie e cole o texto da wiki em um novo documento do LibreOffice Writer. <br />
* Grave o documento com o nome'''Ex4_Writer_seu nome.od'''. <br />
* O título do texto deve estar em fonte '''Dejavu Sans''', tamanho '''14''' e '''negrito'''<br />
* O parágrafo do título deve estar com alinhamento '''centralizado''', espaçamento embaixo do parágrafo '''0,70 cm''', entrelinhas simples e demais opções em 0,00 cm.<br />
* Selecione o texto (sem selecionar o título e nem a fonte do texto) e aplique o alinhamento '''justificado''', fonte '''Dejavu Sans''', tamanho '''12'''.<br />
* Ainda com o texto selecionado, vá em Inserir > Seção > Colunas, selecione '''2 colunas''', espaçamento de '''0,50 cm''', Largura '''Automática, linha separadora estilo linha '''contínua''' e largura '''0,50 cm'''. <br />
* No texto selecionado aplique formatação '''justificado''' no parágrafo e '''hifenização''' em todas as palavras. Vá em Ferramentas > Idioma > Hifenização > Hifenizar tudo.<br />
* Insira a opção '''Capitulares''' através do menu Formatar > Parágrafo > Capitulares, selecione '''Exibir capitulares''', Número de caracteres '''1''', Linhas '''3''' (tamanho de 3 linhas no início do texto) e demais opções em 0 ou Nenhum. <br />
* Alinhe a última linha (fonte do texto) à '''direita''', '''itálico''', fonte '''Dejavu Sans e tamanho '''10'''. Este parágrafo deve estar espaçamento acima do parágrafo '''1,00 cm''', entrelinhas simples e demais opções em 0,00 cm.<br />
* Salve o arquivo e envie para o e-mail: '''elen@ifsc.edu.br''' ou '''pedroarmando@ifsc.edu.br'''.<br />
<br />
<br />
<br />
Das Vantagens de Ser Bobo<br />
<br />
<br />
O bobo, por não se ocupar com ambições, tem tempo para ver, ouvir e tocar o mundo. O bobo é capaz de ficar sentado quase sem se mexer por duas horas. Se perguntado por que não faz alguma coisa, responde: "Estou fazendo. Estou pensando." <br />
Ser bobo às vezes oferece um mundo de saída porque os espertos só se lembram de sair por meio da esperteza, e o bobo tem originalidade, espontaneamente lhe vem a idéia. <br />
O bobo tem oportunidade de ver coisas que os espertos não vêem. Os espertos estão sempre tão atentos às espertezas alheias que se descontraem diante dos bobos, e estes os vêem como simples pessoas humanas. O bobo ganha utilidade e sabedoria para viver. O bobo nunca parece ter tido vez. No entanto, muitas vezes, o bobo é um Dostoievski. <br />
Há desvantagem, obviamente. Uma boba, por exemplo, confiou na palavra de um desconhecido para a compra de um ar refrigerado de segunda mão: ele disse que o aparelho era novo, praticamente sem uso porque se mudara para a Gávea onde é fresco. Vai a boba e compra o aparelho sem vê-lo sequer. Resultado: não funciona. Chamado um técnico, a opinião deste era de que o aparelho estava tão estragado que o conserto seria caríssimo: mais valia comprar outro. Mas, em contrapartida, a vantagem de ser bobo é ter boa-fé, não desconfiar, e portanto estar tranqüilo. Enquanto o esperto não dorme à noite com medo de ser ludibriado. O esperto vence com úlcera no estômago. O bobo não percebe que venceu. <br />
Aviso: não confundir bobos com burros. Desvantagem: pode receber uma punhalada de quem menos espera. É uma das tristezas que o bobo não prevê. César terminou dizendo a célebre frase: "Até tu, Brutus?" <br />
Bobo não reclama. Em compensação, como exclama! <br />
Os bobos, com todas as suas palhaçadas, devem estar todos no céu. Se Cristo tivesse sido esperto não teria morrido na cruz. <br />
O bobo é sempre tão simpático que há espertos que se fazem passar por bobos. Ser bobo é uma criatividade e, como toda criação, é difícil. Por isso é que os espertos não conseguem passar por bobos. Os espertos ganham dos outros. Em compensação os bobos ganham a vida. Bem-aventurados os bobos porque sabem sem que ninguém desconfie. Aliás não se importam que saibam que eles sabem. <br />
Há lugares que facilitam mais as pessoas serem bobas (não confundir bobo com burro, com tolo, com fútil). Minas Gerais, por exemplo, facilita ser bobo. Ah, quantos perdem por não nascer em Minas! <br />
Bobo é Chagall, que põe vaca no espaço, voando por cima das casas. É quase impossível evitar excesso de amor que o bobo provoca. É que só o bobo é capaz de excesso de amor. E só o amor faz o bobo.<br />
<br />
<br />
Clarice Lispector<br />
<br />
<br />
<br />
<br />
<br />
O texto deve ficar neste formato:<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:texto2writer.jpg]]</div><br />
<br />
<br />
</font><br />
{{Collapse bottom | Aula 5}}<br />
<br />
=04/09/2019: Exercício de fixação=<br />
<font size="3"><br />
{{Collapse top | Aula 6}}<br />
<br />
<br />
===Exercício 5===<br />
<br />
<br />
Copie o texto abaixo e posteriormente efetue os ajustes pedidos:<br />
<br />
<br />
<br />
<br />
<br />
A vida é a maior oportunidade de sua existência para conseguir alcançar todos os seus sonhos. Não existe legitimidade maior que lutar por tudo que você anseia, seus desejos são como um doce que você tem de comprar para saborear, para apreciar devidamente, sem medo de ser feliz. Vá em frente e nunca olhe para trás! Não desista nunca deste ringue que é o mundo, porque é nele que vive tudo aquilo que você merece. O segredo? Lutar! Lutar! Lutar!<br />
<br />
Autor desconhecido<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
* Copie e cole o texto da wiki em um novo documento do LibreOffice Writer. <br />
* Grave o documento com o nome'''Ex5_Writer_seu nome.od'''. <br />
<br />
Formatação 01:<br />
* O texto deve estar em fonte '''Dejavu Sans''', tamanho '''8''' e '''negrito''', na cor '''azul''', alinhamento '''justificado''', espaçamento entrelinhas '''simples''' e recuo da primeira linha '''2 cm''' .<br />
* A última linha (fonte do texto) à '''direita''', '''itálico''', fonte '''Dejavu Sans e tamanho '''6'''.<br />
<br />
Formatação 02:<br />
* O texto deve estar em fonte '''Chilanka''', tamanho '''10''', '''negrito''','''itálico''', na cor '''amarelo''', alinhamento '''à esquerda''' e o espaçamento entrelinhas '''duplo'''.<br />
* A última linha (fonte do texto) à '''centralizado''', '''negrito''', fonte '''Dejavu Sans e tamanho '''8'''.<br />
<br />
Formatação 03:<br />
* O texto deve estar em fonte '''Chandas''', tamanho '''10''', '''itálico''', na cor '''verde''', alinhamento '''à direita''' e o espaçamento entrelinhas '''simples'''.<br />
* A última linha (fonte do texto) à '''direita''', '''negrito e itálico''', fonte '''Dejavu Sans e tamanho '''8'''.<br />
<br />
Formatação 04:<br />
* O texto deve estar em fonte '''Garuda''', tamanho '''10''', '''sublinado''','''itálico''', na cor '''preto''', alinhamento '''centralizado''' e o espaçamento entrelinhas '''simples'''.<br />
* A última linha (fonte do texto) à '''direita''', '''itálico''', fonte '''Dejavu Sans e tamanho '''8'''.<br />
<br />
Formatação 05:<br />
* O texto deve estar em fonte '''Gubbi''', tamanho '''10''', na cor '''vermelho''', alinhamento '''justificado''' e o espaçamento entrelinhas '''simples'''.<br />
* A última linha (fonte do texto) à '''direita''', '''negrito''', fonte '''Dejavu Sans e tamanho '''8'''.<br />
<br />
<br />
<br />
* Salve o arquivo.<br />
* Enviar para o e-mail: '''elen@ifsc.edu.br'''.<br />
<br />
<br />
<br />
<br />
<br />
<br />
O texto deve ficar neste formato:<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:Exer5_LibreOfficeInf2.jpg]]</div><br />
<br />
<br />
</font><br />
{{Collapse bottom | Aula 7}}<br />
<br />
=11/09/2019: Tabelas, Cabeçalho, Rodapé e Campos no Libreoffice Writer=<br />
<font size="3"><br />
{{Collapse top | Aula 7}}<br />
<br />
===Tabelas===<br />
<br />
Sabemos que uma tabela nada mais é do que um conjunto de dados disponibilizados em uma grade que possui diversas linhas e colunas.<br />
<br />
Para criar uma tabela no Writer basta acessarmos o menu Tabela, Inserir, Tabela, pelo atalho Ctrl + F12 ou ainda pelo botão disponibilizado na barra de Ferramentas Padrão. Ao acessar uma das opções acima, será mostrada a tela de configuração da tabela.<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:tabelawriter.jpg]]</div><br />
<br />
<br />
Na Figura acima podemos ver claramente que há a possibilidade de darmos um nome para a tabela por meio do campo “Nome” e de determinarmos quantas linhas e colunas nossa tabela terá, por meio dos campos “Colunas” e “Linhas”.<br />
<br />
Logo a seguir, abaixo do campo “Linhas” podemos ver um campo “Título”, onde se o marcarmos, nossa tabela terá N linhas com formatação de título (e. g. Negrito). A quantidade de linhas será definida no campo “As primeiras ... linhas”.<br />
<br />
O Campo “Borda” indica a existência ou não de uma linha separando cada célula que comporá a tabela criada.<br />
<br />
O botão “Autoformatar...” nos dá a possibilidade de darmos uma formatação para a tabela que será criada (e. g. Cores, fonte, bordas, alinhamento e etc).<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:tabela2writer.jpg]]</div><br />
<br />
<br />
Após a criação da tabela, podemos alterar suas propriedades ou parte dela, selecionando a parte que queremos alterar e indo até o menu Tabela, Propriedades da tabela. <br />
<br />
Nesta janela podemos alterar O nome, espaçamento, tamanho de coluna e linha, estilos de borda e cores de fundo.<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:tabela3writer.jpg]]</div><br />
<br />
<br />
===Cabeçalho===<br />
<br />
<br />
Para colocar um cabeçalho em um documento basta acessarmos o menu Inserir, Cabeçalho, Padrão. Então abrir-se-á uma área para digitação do texto do cabeçalho.<br />
<br />
Você poderá digitar o texto do cabeçalho em qualquer página do documento, que este será automaticamente replicado para as demais páginas existentes.<br />
<br />
Você poderá ainda, aplicar formatação ao cabeçalho, incluir borda e plano de fundo e também excluir o cabeçalho por meio da aba azul “Cabeçalho (Padrão)”. Para isto, basta clicar na setinha apontada para baixo existente na aba que as opções surgirão na forma de um menu pop-up.<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:cabecalhowriter.jpg]]</div><br />
<br />
<br />
===Rodapé===<br />
<br />
<br />
Para inserir um rodapé, o procedimento é idêntico ao do cabeçalho, porém deve-se acessar o menu Inserir, Rodapé, Padrão]. Abrir-se-á uma área para digitação do texto do rodapé. Nesta área, pode-se colocar o que for necessário. No entanto, o mais comum de ser colocado nos rodapés de documentos são: número da página, data/hora da impressão, autor, quantidade total de páginas existentes no documento, dentre outros.<br />
<br />
Você poderá ainda, da mesma forma que no cabeçalho, aplicar formatação ao rodapé, incluir borda, plano de fundo e também o excluir. Tudo isto poderá ser realizado por meio da aba azul “Rodapé (Padrão)”.<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:rodapewriter.jpg]]</div><br />
<br />
===Campos===<br />
<br />
<br />
Este é mais um recurso muito útil existente no LibreOffice. Com ele você poderá fazer seu documento mostrar informações automaticamente e sem muito esforço, disponibilizado no menu Inserir, Campos.<br />
<br />
Os campos preexistentes no LibreOffice. são:<br />
<br />
* Data: coloca a data atual (do sistema operacional) no documento toda vez que o mesmo for aberto;<br />
* Hora: coloca a hora atual (do sistema operacional) no documento toda vez que o mesmo for aberto;<br />
* Número da página: exibe o número da página atual;<br />
* Total de páginas: exibe a quantidade de páginas existentes no documento;<br />
* Assunto: mostra o que foi registrado no campo “Assunto”, descrito nas “Propriedades” do documento;<br />
* Título: mostra o que foi registrado no campo “Título”, descrito nas “Propriedades” do documento;<br />
* Autor: mostra o primeiro e último nome listados em “Dados do Usuário” do LibreOffice no menu Ferramentas, Opções;<br />
* Outros: [Ctrl + F2] que dá a possibilidade de escolha de diversos campos, com diversas informações sobre o documento. Estes outros campos poderão ser escolhidos na tela “Campos” em suas diversas abas.<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:camposwriter.jpg]]</div><br />
<br />
<br />
===Exercícios===<br />
<br />
<br />
Crie uma tabela no documento em branco com os dados da imagem abaixo:<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:exerciciotabelawriter.jpg]]</div><br />
<br />
<br />
Formate a tabela com as seguintes configurações:<br />
<br />
<br />
* Linha de título mesclada, fonte Rekha, tamanho 14, cor vermelha, negrito e centralizado;<br />
* Linha de subtítulo com fonte Loma, tamanho 12, itálico e centralizado;<br />
* Demais linhas com fonte Garuda, tamanho 12 alinhamento justificado;<br />
* Insira cor de fundo de acordo com a imagem acima.<br />
<br />
No cabeçalho, insira o texto Proeja - Informática básica II em fonte Liberation Serif, tamanho 12 e negrito.<br />
<br />
No rodapé insira o número da página alinhado a direita.<br />
<br />
Ao final, o documento deve ter essa aparência:<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:exerciciotabela2writer.jpg]]</div><br />
<br />
<br />
<br />
* Salve o arquivo.<br />
* Enviar para o e-mail: '''elen@ifsc.edu.br''' ou '''volnei@ifsc.edu.br'''<br />
<br />
</font><br />
{{Collapse bottom | Aula 7}}<br />
<br />
=18/09/2019: Corretor ortográfico, impressão e Figuras=<br />
<font size="3"><br />
{{Collapse top | Aula 8}}<br />
<br />
===Corretor ortográfico===<br />
<br />
Você pode verificar a ortografia de uma seleção de texto ou do documento por inteiro manualmente.<br />
<br />
A verificação ortográfica começa na posição atual do cursor ou no início da seleção de texto.<br />
<br />
Clique no documento ou selecione o texto que deseja verificar. Escolha Ferramentas - Ortografia e gramática.<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:corretorwriter.jpg]]</div><br />
<br />
<br />
Sempre que é encontrado um erro de ortografia, surge a caixa de diálogo Verificação ortográfica e o LibreOffice oferece algumas sugestões de correção.<br />
Adote um dos seguintes procedimentos:<br />
<br />
Para aceitar a correção, clique na sugestão e, em seguida, em Corrigir.<br />
<br />
Edite a frase na caixa de texto superior e, em seguida, clique em Corrigir.<br />
<br />
Para adicionar a palavra desconhecida ao dicionário definido pelo usuário, clique em Adicionar ao dicionário.<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:corretor2writer.jpg]]</div><br />
<br />
<br />
===Impressão===<br />
<br />
<br />
Para imprimir documentos no Libreoffice Writer, podemos clicar diretamente no botão imprimir ou ir no menu Arquivo, imprimir:<br />
<br />
Na janela que se abre, podemos escolher diversas configurações adicionais.<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:imprimir2writer.jpg]]</div><br />
<br />
<br />
Na aba Geral, podemos escolher a impressora, quantidade de cópias, se serão agrupadas, quais páginas serão impressas (todas, somente uma ou uma parte).<br />
<br />
Na aba Libreoffice Writer podemos escolher se o plano de fundo será impresso, as figuras e objetos, texto oculto, cor do texto e páginas em branco.<br />
<br />
Em Layout escolhemos a quantidade de páginas por folha, a ordem e lados da página.<br />
<br />
E na aba Opções escolhemos se irá para uma impressora física ou um arquivo, agrupamento, bandejas definidas na impressora e tamanho definido na impressora.<br />
<br />
<br />
===Visualizar impressão===<br />
<br />
Antes de imprimir algum trabalho, convém observar como ficará o layout no papel, para evitar alguns acidentes, tais como quebras de páginas em locais indesejados, ajustes de parágrafos, entre outros. Para tanto, o auxílio da função Visualizar Impressão é fundamental.<br />
<br />
Acesse o menu Arquivo > Visualização de Página, no ícone na barra de ferramentas ou através do atalho Ctrl + Shift + O.<br />
<br />
Na tela aparecerá uma projeção exata de como ficará a impressão. Serão apresentadas algumas ferramentas, se quisermos analisar com mais detalhes:<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:visualizarimpressaowriter.jpg]]</div><br />
<br />
<br />
'''Uma página<br/>'''<br />
Mostra uma página na janela de visualização.<br />
<br />
<br />
'''Duas páginas<br/>'''<br />
Mostra duas páginas na janela de visualização. As páginas ímpares aparecerão no lado direito e as páginas pares no lado esquerdo.<br />
<br />
<br />
'''Visualização de livro<br/>'''<br />
Selecione esta opção para ver a primeira página no lado direito da visualização. Se não a selecionar, a primeira página é mostrada no lado esquerdo da visualização.<br />
<br />
<br />
'''Várias páginas<br/>'''<br />
Define o número de páginas exibidas na tela. Clique na seta ao lado do ícone para abrir uma grade e selecionar o número de páginas a serem exibidas como linhas e colunas na visualização.<br />
<br />
<br />
'''Para o início do documento<br/>'''<br />
Vai para a primeira página do documento. Essa função somente estará ativa quando você selecionar a função Visualizar impressão no menu Arquivo.<br />
<br />
<br />
'''Página anterior<br/>'''<br />
Vai para a página anterior do documento. Essa função só estará ativa quando você selecionar a função Visualizar impressão no menu Arquivo.<br />
<br />
<br />
'''Próxima página<br/>'''<br />
Vai para a próxima página do documento. Essa função só estará ativa quando você selecionar a função Visualizar impressão no menu Arquivo.<br />
<br />
<br />
'''Para o fim do documento<br/>'''<br />
Vai para a última página do documento. Essa função somente estará ativa quando você selecionar a função Visualizar impressão no menu Arquivo.<br />
<br />
<br />
'''Menos zoom<br/>'''<br />
Diminui o zoom para ver mais do documento em um tamanho reduzido.<br />
<br />
<br />
'''Zoom de visualização<br/>'''<br />
Determina o nível de zoom da visualização de impressão.<br />
<br />
<br />
'''Mais zoom<br/>'''<br />
Aumenta o zoom para obter um close do documento.<br />
<br />
<br />
'''Imprimir<br/>'''<br />
Imprime o documento.<br />
<br />
<br />
'''Tela inteira<br/>'''<br />
Exibe ou oculta os menus e as barras de ferramentas no Writer ou no Calc. Para sair do modo de tela inteira, clique no botão Tela inteira ou pressione a tecla Esc.<br />
<br />
<br />
'''Fechar visualização<br/>'''<br />
Fecha a visualização e volta na edição do documento.<br />
<br />
<br />
===Figuras===<br />
<br />
<br />
A inserção de figura em um texto e sua manipulação é simples no Writer.<br />
<br />
Vamos passo a passo mostrar como se dá essa inserção. <br />
<br />
Primeiro abra o documento em que deseja inserir a figura e posicione o cursor no local desejado que ela apareça. Depois escolha Inserir - Figura. Localize o arquivo gráfico que você deseja inserir e, em seguida, clique em Abrir. <br />
<br />
Por padrão, a figura inserida é centralizada acima do parágrafo no qual você clicou. <br />
<br />
<br />
Veja que é criada uma barra de ferramenta flutuante chamada figura. Nela você modifica os aspectos de cor e padrão da figura e também inverte vertical ou horizontalmente a figura. <br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:figurawriter.jpg]]</div><br />
<br />
<br />
Quando é inserida uma figura a barra de ferramenta quadro é mostrada para configurar com mais facilidade a figura. <br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:figura2writer.jpg]]</div><br />
<br />
<br />
Também temos a opção de formatar figura. Para isso, selecione a figura e vá no menu Formatar - Figura.<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:figura3writer.jpg]]</div><br />
<br />
<br />
Nesta janela teremos várias opções de configuração, tais como ajuste de tamanho, ajuste no texto, posicionamento. hiperlink, recorte, bordas, transparência, etc.<br />
<br />
<br />
</font><br />
{{Collapse bottom | Aula 8}}<br />
<br />
=25/09/2019: Atividade=<br />
<font size="3"><br />
{{Collapse top | Aula 9}}<br />
<br />
===Tarefa===<br />
<br />
Você deve pesquisar na internet quais os componentes de um computador e qual a função de cada um, depois crie um pequeno texto/parágrafo no LibreOffice Writer explicando para o que serve cada desses componentes. Após isto encontre na internet uma foto de cada material pesquisado e insira no texto.<br />
<br />
Depois de criar o texto e inserir as figuras, pesquise novamente na internet, em lojas de computadores, o valor destes componentes. E crie uma tabela informando estes valores.<br />
<br />
Utilize também o Corretor Ortográfico para não ter nenhum erro de ortografia no seu texto.<br />
<br />
A formatação do arquivo segue abaixo:<br />
<br />
Texto:<br />
<br />
• Fonte Arial<br />
<br />
• Tamanho 12<br />
<br />
• Justificado<br />
<br />
• Recuo da Primeira Linha do Parágrafo: 1,25 cm<br />
<br />
• Espaçamento de Linhas (Espaçamento Entre Linhas): 1,5<br />
<br />
• Marcadores e Numeração em forma de círculo pequeno<br />
<br />
<br />
Página:<br />
<br />
• Margem Esquerda: 3,00 cm<br />
<br />
• Margem Superior: 3,00 cm<br />
<br />
• Margem Inferior: 2,00 cm<br />
<br />
• Margem Direita: 2,00 cm<br />
<br />
• Orientação da página: Retrato<br />
<br />
<br />
Exporte o arquivo para PDF e salve o arquivo com o seguinte nome: Seu Nome Completo – Informática II PROEJA – Tarefa 01<br />
e envie para o e-mail elen@ifsc.edu.br ou volnei@ifsc.edu.br informando no assunto do e-mail seu<br />
nome completo, curso e turma.<br />
<br />
<br />
</font><br />
{{Collapse bottom | Aula 9}}<br />
<br />
=02/10/2019: Atividade Avaliativa=<br />
<font size="3"><br />
{{Collapse top | Aula 10}}<br />
<br />
===Tarefa===<br />
<br />
Concluir a atividade proposta da aula passada.<br />
<br />
</font><br />
{{Collapse bottom | Aula 10}}<br />
<br />
=09/10/2019: Introdução ao Libreoffice Calc=<br />
<font size="3"><br />
{{Collapse top | Aula 11}}<br />
<br />
===Libreoffice Calc===<br />
<br />
Calc é um software de planilha eletrônica multiplataforma de código aberto, desenvolvido originalmente pela Star Division, posteriormente pela Sun Microsystems (como parte da suíte StarOffice) e atualmente pela The Document Foundation, como parte da suíte LibreOffice. Também é distribuído gratuitamente com as suítes OpenOffice.org e NeoOffice.<br />
<br />
Nessa planilha, o número limite de linhas é de pouco mais de 1 milhão por planilha e o número limite de colunas é de 1024 por planilha.<br />
<br />
Na imagem abaixo podemos conhecer um pouco melhor a interface do Calc:<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:interfacecalc.jpg]]</div><br />
<br />
<br />
As células do Calc possuem endereçamento, onde as colunas são definidas por letras e as linhas por números. Para identificar o endereço da célula, basta indicar primeiramente o endereçamento da coluna e depois da linha. Ex: '''A1'''.<br />
<br />
<br />
====Operadores====<br />
<br />
<br />
Devemos conhecer alguns símbolos que são muito utilizados, juntamente com a ordem dos cálculos efetuados:<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:interface2calc.jpg]]</div><br />
<br />
<br />
====Realce de valor====<br />
<br />
<br />
A função Realce de valor destaca os conteúdos das células através da diferenciação da cor da fonte. Para acioná-la, vá até o menu Exibir > Realce de valor ou clique na combinação de teclas Ctrl+F8.<br />
<br />
Textos são apresentados em preto, números em azul e fórmulas em verde. Essa configuração de cores é padrão para qualquer instalação do LibreOffice. Na figura abaixo, é possível identificar as três categorias. No exemplo, o conteúdo da célula B30 é a fórmula =1+1. <br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:interface3calc.jpg]]</div><br />
<br />
<br />
====Séries de preenchimento====<br />
<br />
<br />
Uma Série de preenchimento é uma forma fácil de fazer um preenchimento automático em uma área da planilha a partir de um valor inicial.<br />
<br />
Inicialmente, digite o valor inicial em uma célula. Com a célula selecionada, coloque o ponteiro do mouse sobre o ponto preto no canto inferior direito, chamado Alça de preenchimento, até que este se transforme em uma pequena cruz.<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:interface4calc.jpg]]</div><br />
<br />
<br />
Arraste com o botão do mouse pressionado até a última célula da sequência desejada, como no passo 1 apresentado na tabela abaixo. Solte o botão do mouse e a área selecionada será preenchida com a sequência numérica correspondente (passo 2).<br />
<br />
Se a direção da sua seleção for horizontal para a esquerda ou vertical para cima, o Calc fará o preenchimento com decremento 1. Se a direção da sua seleção for horizontal para a direita ou vertical para baixo, o Calc fará o preenchimento com incremento 1.<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:interface5calc.jpg]]</div><br />
<br />
<br />
Se você desejar criar uma sequência de preenchimento sem incremento algum, faça o mesmo procedimento, no entanto, ao clicar e arrastar com a alça de preenchimento, mantenha a tecla Ctrl pressionada.<br />
<br />
====Formatar Células====<br />
<br />
<br />
Permite que você especifique diversas opções de formatação e aplique atributos às células selecionadas.<br />
<br />
Escolha Formatar - Células<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:formatcelcalc.jpg]]</div><br />
<br />
<br />
Números<br />
Especifica as opções de formatação para a(s) célula(s) selecionada(s).<br />
<br />
<br />
Fonte<br />
Especifique a formatação e a fonte que deseja aplicar.<br />
<br />
<br />
Alinhamento<br />
Define ao opções de alinhamento para o conteúdo da célula atual, ou das células selecionadas.<br />
<br />
<br />
Bordas<br />
Define opções de borda para os objetos selecionados em Writer ou Calc.<br />
<br />
<br />
Plano de fundo<br />
Define a cor ou a figura do plano de fundo.<br />
<br />
<br />
Proteção de célula<br />
Define as opções de proteção para as células selecionadas.<br />
<br />
</font><br />
{{Collapse bottom | Aula 11}}<br />
<br />
=16/10/2019: Fórmulas simples Libreoffice Calc=<br />
<font size="3"><br />
{{Collapse top | Aula 12}}<br />
<br />
===Funções===<br />
<br />
Funções são procedimentos baseados em operações e operandos que, manipulados, retornam um determinado resultado. Funções podem simplesmente representar a implementação de operadores, como a função Soma, que veremos adiante, ou, de forma mais complexa, realizar cálculos de nível avançado.<br />
<br />
<br />
Para inserir uma função através do assistente, siga os seguintes passos:<br />
<br />
Selecione a célula onde será inserida a função;<br />
<br />
Selecione uma das opções abaixo:<br />
<br />
* vá até o menu Inserir > Função ou<br />
* teclar Ctrl + F2 ou<br />
* clique sobre o botão Assistente de funções, na Barra de fórmulas.<br />
<br />
Será aberta a tela do Assistente de funções. Selecione, então, uma categoria de função na caixa Categoria;<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:funcaocalc.jpg]]</div><br />
<br />
<br />
Selecione o nome da função e clique no botão Próximo;<br />
<br />
Preencha os argumentos solicitados para a função;<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:funcao2calc.jpg]]</div><br />
<br />
<br />
Clique OK. A fórmula será inserida na célula e o resultado será contabilizado.<br />
<br />
A função também pode ser digitada. Para isto, basta iniciar coma digitação do símbolo de = e posteriormente digitar o nome da fórmula desejada, juntamente com seu parâmetros.<br />
<br />
<br />
====Funções simples====<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:funcaosomacalc.jpg]]</div><br />
<br />
<br />
No exemplo acima, a função é SOMA, o argumento é B2:B6 (leia-se de B2 até B6) e o resultado ( a soma dos valores) é 20. <br />
<br />
Como digitar<br />
<br />
Se as células são adjacentes: =SOMA(C2:C8) <br />
<br />
Essa função soma o conteúdo de células adjacentes (sequência C2 até C8)<br />
<br />
Se as células não são adjacentes: =SOMA(B2;C3;D1).<br />
<br />
A função Média calcula o valor médio de um intervalo, adjacente ou não.<br />
<br />
=MEDIA(C2:C8)<br />
<br />
A função Mínimo retorna o menor valor de um intervalo analisado<br />
<br />
=MINIMO(C2:C8)<br />
<br />
A função Máximo retorna o maior valor de um intervalo analisado<br />
<br />
=MAXIMO(C2:C8)<br />
<br />
A função Mediana de um intervalo é o seu valor central, ou seja, que divide o intervalo em duas partes iguais<br />
<br />
=MED(C2:C8)<br />
<br />
A função Moda retorna o valor que mais se repete em um intervalo. Caso dois números ou mais tenham a mesma quantidade de repetições, o menor valor será mostrado.<br />
<br />
=MODO(C2:C8)<br />
<br />
A função Concatenar agrupa valores indicados. Esta função aceita somente ;<br />
<br />
=CONCATENAR(C2;C5;C8)<br />
<br />
<br />
</font><br />
{{Collapse bottom | Aula 12}}<br />
<br />
=23/10/2019: Fórmulas Compostas Libreoffice Calc=<br />
<font size="3"><br />
{{Collapse top | Aula 13}}<br />
<br />
===Funções Lógicas===<br />
<br />
<br />
'''SE'''<br />
<br />
<br />
Esta é uma função bastante interessante pois permite ao usuário da planilha construir expressões condicionais, avaliando e apresentando diferentes resultados conforme uma cláusula avaliada.<br />
<br />
A estrutura da função SE é:<br />
<br />
=SE (CONDIÇÃO; VALOR_SE_CONDIÇÃO_VERDADEIRA; VALOR_SE_CONDIÇÃO_FALSA)<br />
<br />
O primeiro argumento é a condição. Normalmente, avaliamos o conteúdo de uma célula em relação a um dado parâmetro, como, por exemplo C4<100 ou A1=”APROVADO”.<br />
<br />
Caso a condição seja verdadeira, o segundo argumento é apresentado como resultado da função.<br />
<br />
Caso a condição seja falsa, o terceiro argumento é apresentado como resultado.<br />
<br />
No exemplo abaixo, avaliamos o valor da nota do aluno e, caso esteja acima da média, apresentamos o resultado “Aprovado”. Senão, apresentamos o resultado “Recuperação”.<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:funcaocalcse.jpg]]</div><br />
<br />
<br />
<br />
'''CONT.NUM'''<br />
<br />
<br />
<br />
A função CONT.NÚM conta quantos valores numéricos estão entre os ARGUMENTOS da função.<br />
<br />
Entende-se como valores numéricos: números, datas e fórmulas cujo resultado seja um número. Células vazias ou células com conteúdo de texto não são contadas na função CONT.NÚM.<br />
<br />
O formato da função é:<br />
<br />
=CONT.NÚM(ARGUMENTOS)<br />
<br />
Observe no exemplo abaixo que nem todos os alunos fizeram a primeira avaliação. Podemos usar a função CONT.NÚM para contar as notas do intervalo B11:B19 e identificar quantos alunos de fato fizeram a prova.<br />
<br />
O resultado da função =CONT.NÚM(B11:B19) será 7 pois, as duas células, correspondentes aos alunos que não fizeram a prova, estão vazias.<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:funcaocalccontnum.jpg]]</div><br />
<br />
<br />
<br />
'''CONT.SE'''<br />
<br />
<br />
<br />
A função CONT.SE tem como objetivo contar quantos valores obedecem a um determinado critério. A estrutura é bastante simples:<br />
<br />
=CONT.SE (INTERVALO; CONDIÇÃO)<br />
<br />
Os valores dentro do intervalo são avaliados um a um de acordo com a condição. O valor é contado somente se a condição for verdadeira.<br />
<br />
No exemplo abaixo, contamos quantos alunos estão com notas acima da média estabelecida.<br />
<br />
Note que usamos uma concatenação de texto para expressar adequadamente o critério, indicado no segundo argumento com a expressão “>”&B6. Ou seja, concatenamos o sinal de > com o conteúdo da célula B5.<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:funcaocalccontse.jpg]]</div><br />
<br />
<br />
O resultado da função CONT.SE acima é de 7 alunos.<br />
<br />
Quando o critério ou condição for de igualdade, não precisamos usar a concatenação de texto, por exemplo:<br />
<br />
=CONT.SE(B10:B18;B6)<br />
<br />
Em sua construção mais comum, a função CONT.SE permite apenas um argumento como critério de contagem. No entanto, em casos específicos, é possível utilizar mais de um argumento através do uso de expressões regulares em fórmulas.<br />
<br />
O exemplo abaixo ilustra essa situação. A partir da tabela abaixo, desejamos obter a quantidade de cadastros de pessoas que são dos estados do Rio Grande do Sul e Santa Catarina.<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:funcaocalccontse2.jpg]]</div><br />
<br />
<br />
Uma abordagem óbvia e simples seria a soma de CONT.SE:<br />
<br />
=CONT.SE(F3:F8;"RS")+CONT.SE(F3:F8;"SC")<br />
<br />
Uma abordagem elegante poderia utilizar expressões regulares:<br />
<br />
=CONT.SE(F3:F8;"RS|SC")<br />
<br />
Onde o símbolo | (pipe) entre as siglas RS e SC representa a operação OU lógica. Logo, estamos contando apenas os valores do intervalo de F3 até F8 que são iguais a RS ou a SC.<br />
<br />
<br />
'''CONT.VALORES'''<br />
<br />
<br />
A função CONT.VALORES permite contar células preenchidas com valores de texto, número ou fórmula dentro de um intervalo.<br />
<br />
O formato da função CONT.VALORES é:<br />
<br />
=CONT.VALORES(ARGUMENTOS)<br />
<br />
No exemplo abaixo, o usuário deverá preencher o espaço amarelo com cinco códigos de produto.<br />
<br />
Para contar quantas células já foram preenchidas, utilizamos a função CONT.VALORES e o intervalo de G5:G9.<br />
<br />
O resultado da função, no exemplo abaixo, será 3.<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:funcaocalccontvalores.jpg]]</div><br />
<br />
<br />
<br />
'''CONTAR.VAZIO'''<br />
<br />
<br />
CONTAR.VAZIO conta quantas células do intervalo indicado em ARGUMENTOS estão vazias, isto é, sem conteúdo algum.<br />
<br />
=CONTAR.VAZIO(ARGUMENTOS)<br />
<br />
No nosso exemplo anterior, da função CONT.VALORES, calculamos quantas células do intervalo amarelo já haviam sido preenchidas. Podemos encontrar a informação complementar (quantas células faltam ser preenchidas) através da função CONTAR.VAZIO.<br />
<br />
No exemplo, a função CONTAR.VAZIO pode ser utilizada sobre o intervalo de G5:G9. O resultado da função na célula H15 será de 2.<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:funcaocalccontvazio.jpg]]</div><br />
<br />
<br />
<br />
'''SOMASE'''<br />
<br />
<br />
A função SOMASE é útil para cálculos que envolvam valores totais a partir de um determinado critério. O formato da função é:<br />
<br />
=SOMASE(INTERVALO_DE_AVALIAÇÃO; CRITÉRIO; INTERVALO_DE_SOMA)<br />
<br />
Os valores do intervalo de avaliação são avaliados conforme o critério. Caso estejam de acordo com o critério indicado, o valor correspondente no intervalo de soma é somado ao resultado.<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:funcaocalcsomase.jpg]]</div><br />
<br />
</font><br />
{{Collapse bottom | Aula 13}}<br />
<br />
=30/10/2019: Revisão=<br />
<font size="3"><br />
{{Collapse top | Aula 14}}<br />
<br />
</font><br />
{{Collapse bottom | Aula 14}}<br />
<br />
=06/11/2019: Avaliação=<br />
<font size="3"><br />
{{Collapse top | Aula 15}}<br />
<br />
* Copie o conteúdo abaixo:<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:avaliacaocalc.jpg]]</div><br />
<br />
<br />
* Efetue os cálculos solicitados (Total dos produtos por trimestre, Valor máximo, Valor mínimo, Média e Total por mês).<br />
<br />
* Salve o arquivo com o seu nome e envia para o seguinte e-mail:<br />
<br />
elen@ifsc.edu.br ou volnei@ifsc.edu.br<br />
<br />
</font><br />
{{Collapse bottom | Aula 15}}<br />
<br />
=13/11/2019: Vínculo entre planilhas, Gráficos, Classificação e Filtros=<br />
<font size="3"><br />
{{Collapse top | Aula 16}}<br />
<br />
===Classificação===<br />
<br />
<br />
No Libreoffice Calc, podemos efetuar a classificação de conteúdos, em ordem alfabética, de forma crescente ou decrescente.<br />
<br />
Para tanto, devemos clicar em um intervalo de banco de dados:<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:classificacaocalc.jpg]]</div><br />
<br />
<br />
Ao selecionar um intervalo de células, somente estas células serão classificadas. <br />
<br />
Se você clicar somente em uma célula sem selecionar, então todo o intervalo de banco de dados será classificado.<br />
<br />
Escolha Dados - Classificar.<br />
<br />
O intervalo de células que será classificado é mostrado em cores invertidas.<br />
<br />
Selecione as opções de classificação desejadas.<br />
<br />
<div style="text-align: left;">[[Arquivo:classificacaocalc2.jpg]]</div><br />
<br />
Clique em OK.<br />
<br />
<div style="text-align: left;">[[Arquivo:classificacaocalc3.jpg]]</div><br />
<br />
<br />
===Filtro===<br />
<br />
<br />
Os filtros e filtros avançados permitem que você assegure que somente certas linhas (registros) de um intervalo de dados fiquem visíveis. Nos documentos de planilhas do LibreOffice, há várias possibilidades para a aplicação de filtros.<br />
<br />
Uma das utilizações para a função Autofiltro, que se encontra em Dados, Filtro, Autofiltro, é a de rapidamente restringir a exibição de registros com entradas idênticas em um campo de dados.<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:autofiltrocalc.jpg|900px]]</div><br />
<br />
<br />
Na caixa de diálogo Filtro padrão, você também pode definir intervalos que contenham os valores em determinados campos de dados. É possível utilizar o filtro padrão para conectar até três condições com um operador lógico E ou OU.<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:filtropadraocalc.jpg]]</div><br />
<br />
<br />
O Filtro avançado excede a restrição de três condições e permite até oito condições de filtro. Com os filtros avançados, você insere as condições diretamente na planilha.<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:filtroavancadocalc.jpg]]</div><br />
<br />
<br />
Para remover um filtro, de forma a ver todas as células, clique dentro da área onde o filtro estiver aplicado e escolha Dados - Filtro - Redefinir filtro.<br />
<br />
Ao selecionar várias linhas de uma área onde um filtro foi aplicado, a seleção pode incluir linhas visíveis e linhas ocultas pelo filtro. Se depois você aplicar formatação, ou excluir as linhas selecionadas, esta ação só afetará as linhas visíveis. As linhas ocultas não serão afetadas.<br />
<br />
Isto é o oposto das linhas que foram ocultas manualmente pelo comando Formatar - Linhas - Ocultar linhas. Linhas ocultas manualmente são excluídas ao excluir uma seleção que as contenha.<br />
<br />
<br />
===Vínculo entre planilhas===<br />
<br />
Podemos utilizar conteúdos que se encontram em outras planilhas do documento.<br />
<br />
Para que isso ocorra, devemos utilizar como no exemplo abaixo:<br />
<br />
=Planilha2.A1<br />
<br />
Neste caso, o conteúdo da Planilha2, célula A1 será exibido onde esta fórmula for empregada.<br />
<br />
<br />
===Gráficos===<br />
<br />
<br />
No Calc, é fácil gerar gráficos a partir de qualquer planilha. <br />
<br />
Pode-se chamar o assistente de gráficos a partir do seu ícone ou do menu Inserir ... gráfico.<br />
<br />
Os gráficos no Calc estão muito fáceis e muito intuitivos e prometem-se ainda muitas melhorias para este recurso. <br />
<br />
Ao se invocar o comando Inserir Gráfico, tem-se uma tela como a seguir (previsão do gráfico e seu assistente):<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:graficocalc.jpg]]</div><br />
<br />
<br />
Logo na Etapa 1 você terá vários tipos e subtipos de gráficos a escolher: barras, pizza, rede, dispersão, etc.<br />
<br />
Etapa 2 – Intervalo de Dados – aqui se informa ao Calc a área a ser computada e plotada.<br />
<br />
Etapa 3 – Série de Dados – Aqui se definem nomes e rótulos para as séries dos dados.<br />
<br />
Etapa 4 – É nesta etapa que se fazem as legendas do gráfico.<br />
<br />
A seguir, vemos um gráfico de Pizza gerado no LibreOffice Calc:<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:graficocalc2.jpg]]</div><br />
<br />
<br />
</font><br />
{{Collapse bottom | Aula 16}}<br />
<br />
=20/11/2019: Introdução ao Libreoffice Impress=<br />
<font size="3"><br />
{{Collapse top | Aula 17}}<br />
<br />
===Tela Principal===<br />
<br />
O Impress é software para desenvolvimento de apresentações. Por meio deste software pode-se preparar as apresentações textuais, adicionar imagens, sons e até mesmo animação.<br />
<br />
<div style="text-align: left;">[[Arquivo:impressprincipal.jpg]]</div><br />
<br />
<br />
===Slide Mestre===<br />
<br />
Toda apresentação possui no mínimo um slide mestre. Este slide em especial leva este nome não é à toa e veremos o por quê.<br />
<br />
No slide mestre pode-se configurar e/ou alterar as formatações de uma apresentação inteira.<br />
<br />
Nem sempre as pessoas que trabalham com este tipo de ferramenta o utilizam. Na maioria das vezes por pura falta de conhecimento.<br />
<br />
Vamos começar a desenvolver nossa apresentação exatamente pelo slide mestre. Mas antes disso vamos acessar o menu [Exibir | Régua], para que a régua seja mostrada da mesma forma como é mostrada no Writer.<br />
<br />
Agora então vamos acessar o menu [Exibir | Mestre | Slide Mestre]. Após este passo, podemos observar que a interface mudou bastante:<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:impressmestre.jpg]]</div><br />
<br />
<br />
Tudo que fizermos neste slide será replicado para todos os slides que tenham este mesmo layout em nossa apresentação.<br />
<br />
<br />
Para fazer uma apresentação, não é pré-requisito configurar o slide mestre. No entanto, há alguns bons motivos para você fazê-lo:<br />
<br />
* Configurando o slide mestre, você não precisará fazer isto de novo em nenhum outro slide, pois, isto acontecerá automaticamente;<br />
* Hoje esta apresentação vai ter um fundo de tela voltado para este curso, amanhã se o autor não ficar satisfeito ou se for usá-la em outro curso, bastará fazer a alteração no slide mestre e tudo estará resolvido.<br />
<br />
<br />
===Segundo Slide===<br />
<br />
<br />
Para criar o segundo slide vamos dar um clique com o botão direito do mouse na área sob as miniaturas de slides. <br />
<br />
No menu pop-up que aparecer acesse a opção “Novo slide”.<br />
<br />
Muito provavelmente o slide que foi criado veio com o mesmo layout do anterior a ele. Então, vá até a área de layout de slides e clique no layout que gostaria de utilizar.<br />
<br />
<br />
===Slide com imagem===<br />
<br />
<br />
Mais uma vez vamos repetir o processo de criar um novo slide, ou seja, clique com o botão direito do mouse sobre a área limpa sob as miniaturas de slides. Então escolha a opção “Novo slide”.<br />
<br />
Será criado um slide com layout padrão. Vamos alterar o layout para um que comporte texto e objetos.<br />
<br />
Agora, no quadro do lado direito é apresentada uma imagem central que na verdade são quatro botões:<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:impressslideimagem.jpg]]</div><br />
<br />
<br />
Clique no botão para inserir “Imagem”. Será aberta uma caixa de diálogo do sistema operacional que você estiver usando, então, vá até a pasta onde está o arquivo, selecione-o e aperte o botão “Abrir” (Open em inglês).<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:impressslideimagem2.jpg]]</div><br />
<br />
<br />
O slide apresentará a imagem selecionada. Clique na figura e ajuste-a para que fique num tamanho adequado. E está pronto o terceiro slide.<br />
<br />
<br />
===Exercício===<br />
<br />
Desenvolva a apresentação abaixo de forma que fique o mais parecida possível.<br />
<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:impresssexerciciopag1.jpg]]</div><br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:impresssexerciciopag2.jpg]]</div><br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:impresssexerciciopag3.jpg]]</div><br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:impresssexerciciopag4.jpg]]</div><br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:impresssexerciciopag5.jpg]]</div><br />
<br />
</font><br />
{{Collapse bottom | Aula 17}}<br />
<br />
=27/11/2019: Libreoffice Impress - Efeitos, aparência e demais configurações=<br />
<font size="3"><br />
{{Collapse top | Aula 18}}<br />
<br />
===Modificando a aparência de todos os slides===<br />
<br />
Para modificar a aparência de um slide, devemos alterar o slide mestre. Vimos anteriormente a criação de um silde mestre do zero, mas nesse momento iremos usar modelos prontos. Para tanto, clique no botão Páginas mestre no painel lateral, como mostra a imagem abaixo:<br />
<br />
<br />
<div style="text-align: left;">[[Arquivo:impresssslidemestrepronto.jpg]]</div><br />
<br />
<br />
Basta escolher o modelo desejado que automaticamente será aplicado em todos os slides.<br />
<br />
<br />
===Avançar slides automaticamente===<br />
<br />
<br />
Pode-se configurar a apresentação para avançar automaticamente para o próximo slide após um determinado período de tempo (por exemplo na forma de quiosque ou carrocel) a partir do menu Apresentação de slide → Configurações da apresentação de slides ou para avançar automaticamente após um período preestabelecido de tempo diferente para cada slide.<br />
<br />
<div style="text-align: left;">[[Arquivo:impresssstransicaoslides.jpg]]</div><br />
<br />
Para configurar este último, escolha Apresentação de slide → Cronometrar. Quando usamos esta ferramenta, um temporizador de pequeno porte é exibido no canto inferior esquerdo. Quando estiver pronto para avançar para o próximo slide, clique no temporizador. O Impress vai memorizar os intervalos e na próxima apresentação dos slides, estes irão avançar automaticamente após o tempo expirar.<br />
<br />
<br />
===Transições de slide===<br />
<br />
<br />
Transição de slide é a animação que é reproduzida quando um slide for alterado. Pode-se configurar a transição de slide a partir da aba Transição de slides no painel de Tarefas. Selecione a transição desejada, a velocidade da animação, e se a transição deve acontecer quando se clica com o mouse (de preferência) ou automaticamente depois de um determinado número de segundos. Clique Aplicar a todos os slides, a menos que prefira ter diferentes transições na apresentação.<br />
<br />
<div style="text-align: left;">[[Arquivo:impresssstransicaoslides2.jpg]]</div><br />
<br />
</font><br />
{{Collapse bottom | Aula 18}}</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=SOP29005-2019-2&diff=162119SOP29005-2019-22019-10-09T16:30:07Z<p>127.0.0.1: /* AULA 19 - Dia 04/10/2019 */</p>
<hr />
<div>=AULA 1 - Dia 30/07/2019=<br />
<br />
===Objetivos/Conteúdos===<br />
<br />
*Apresentação do Plano de Ensino<br />
**Objetivos e Conteúdo Programático da Disciplina (ver SIGAA)<br />
**Forma de Avaliação (ver SIGAA)<br />
<br />
*Introdução a Sistemas Operacionais (Cap1. do Silberschatz)<br />
**O que faz um sistema operacional (1.1)<br />
**Organização e Arquitetura de um Sistema Computacional (1.2 e 1.3)<br />
***Importância da Interrupção e Timers (1.2.1)<br />
***Estrutura de Armazenamento (1.2.2)<br />
***Estrutura de IO (1.2.3)<br />
**Estrutura e Operações de um Sistema Operacional (1.4 e 1.5)<br />
<br />
===Material de Referência===<br />
<br />
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte1.pdf Apresentação sobre histórico visão geral e estruturas básicas de um SO]<br />
* [http://codex.cs.yale.edu/avi/os-book/OSE1/slide-dir/index.html Slides Silberschatz Oitava Edição]<br />
* [http://professor.unisinos.br/barbosa/SO/ch1br.ppt Tradução Slides Silberschatz Cap1]<br />
* [http://professor.unisinos.br/barbosa/SO/ch2br.ppt Tradução Slides Silberschatz Cap2]<br />
* [http://professor.unisinos.br/barbosa/SO/ch3br.ppt Tradução Slides Silberschatz Cap3]<br />
* [http://professor.unisinos.br/barbosa/SO/ch4br.ppt Tradução Slides Silberschatz Cap4]<br />
* [http://wiki.inf.ufpr.br/maziero/doku.php?id=so:livro_de_sistemas_operacionais Livro do Prof.Maziero]<br />
* [http://deptinfo.unice.fr/~rr/l3systres/ Université Nice Sophia Antipolis]<br />
<br />
Arliones:<br />
<br />
*[https://www.dropbox.com/s/dt80g3tml65rpmg/SOP29005-parte6.odp?dl=0]<br />
*[https://www.dropbox.com/s/7lneavq0go9kz2t/SOP29005-parte7.odp?dl=0]<br />
<br />
===Leitura Recomendada===<br />
<br />
*Cap.1 do Silberschatz principalmente:<br />
**1.1 a 1.9<br />
<br />
===Exercícios Práticos de Apoio a Aula===<br />
<br />
Na sequência. com fins motivacionais, são apresentados alguns exercícios ilustrando conceitos de processos, arquivos e permissionamento.<br />
<br />
<ol><br />
<li><br />
Comando para ver todos os processos no linux:<br />
<code><br />
$ ps aux<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Colocar 2 processos se executando no contexto de um terminal e verificar número dos processos e então "destruí-los":<br />
<code><br />
$ yes > /dev/null<br />
$ yes > /dev/null<br />
$ ps <br />
$ kill -9 <pid_yes><br />
$ kill -9 <pid_yes><br />
</syntaxhighlight><br />
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.<br />
</li><br />
<li><br />
Criar um terminal adicional<br />
<code><br />
$ xterm<br />
</syntaxhighlight><br />
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:<br />
<code><br />
$ echo Alo Terminal > /dev/pts/2<br />
$ kill -9 <pid_terminal><br />
</syntaxhighlight><br />
</li><br />
<li><br />
Comunicação entre processos:<br />
<code><br />
$ cat /etc/passwd | grep home | wc -l<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Retirando a permissão de leitura de um arquivo em nível de usuário proprietário:<br />
<code><br />
$ echo Alo Mundo > alfa.txt<br />
$ ls -l alfa.txt<br />
$ cat alfa.txt<br />
$ chmod u-r alfa.txt<br />
$ cat alfa.txt<br />
$ chmod u+r alfa.txt<br />
$ cat alfa.txt <br />
</syntaxhighlight><br />
</li><br />
</ol><br />
<br />
=AULA 2 - Dia 2/08/2019=<br />
<br />
===Objetivos/Conteúdos===<br />
<br />
*Continuação da Aula<br />
*Estruturas do Sistema Operacional (cap.2)<br />
**Serviços do Sistema Operacional (2.1)<br />
**Interfaces com Usuários (2.2)<br />
**Chamadas do Sistema (2.3)<br />
**Tipos de Chamadas de Sistema (2.4) ver Fig.2.8<br />
***Chamadas de Controle de Processos<br />
**Arquiteturas e Estruturas de Sistemas Operacionais (2.7)<br />
**Máquinas Virtuais (2.8)<br />
<br />
===Material de Referência===<br />
<br />
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte1.pdf Apresentação sobre histórico visão geral<br />
* [http://www.fil.univ-lille1.fr/~sedoglav/OS/TP.html ]<br />
<br />
===Leitura Recomendada===<br />
<br />
*Cap.2 do Silberschatz principalmente:<br />
**2.1 a 2.8<br />
<br />
===Exercícios===<br />
<br />
=AULA 3 - Dia 7/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*Continuação da aula anterior<br />
**Chamadas do Sistema (2.3)<br />
**Tipos de Chamadas de Sistema (2.4) ver Fig.2.8<br />
***Chamadas de Controle de Processos<br />
**Arquiteturas e Estruturas de Sistemas Operacionais (2.7)<br />
**Máquinas Virtuais (2.8)<br />
<br />
===Exercícios===<br />
<br />
<ol><br />
<li> Estudar e executar o código em http://cs.lmu.edu/~ray/notes/gasexamples/ <br />
Detalhes das chamadas na arquitetura x86_64 ver em https://lwn.net/Articles/604287/ <br />
<li>Estudar (usar o man) e executar o código usando a função (em conformidade com a API POSIX) write() para o ''hello world'':<br />
<code><br />
#include <unistd.h> <br />
<br />
main()<br />
{<br />
write(1,"Alo Mundo\n",10);<br />
}<br />
</syntaxhighlight><br />
</li><br />
<li> Use o comando strace para verificar todas as chamadas de sistema dos programas acima.<br />
</li><br />
<li><br />
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() 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:<br />
<code><br />
void meu_hello();<br />
<br />
int main()<br />
{<br />
meu_hello();<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
</li><br />
Gere o assembly do código em C e discuta a diferença entre uma chamada de função e uma chamada de sistema.<br />
<li><br />
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:<br />
<code><br />
#include <string.h><br />
main()<br />
{<br />
char *p="Tudo bem com vocês?";<br />
meu_hello_world(p, strlen(p));<br />
}<br />
</syntaxhighlight><br />
Solução:<br />
{{collapse top|Solução}}<br />
<code><br />
modificado de http://cs.lmu.edu/~ray/notes/gasexamples/<br />
.global meu_hello_world<br />
<br />
.text<br />
meu_hello_world:<br />
<br />
push %rdi # salva primeiro parâmetro<br />
push %rsi # salva segundo parâmetro<br />
mov $1, %rax # system call 1 é write<br />
mov $1, %rdi # file handle 1 é stdout<br />
mov $message, %rsi # endereço da string<br />
mov $13, %rdx # número de bytes da string<br />
syscall # chamada ao sistema<br />
<br />
pop %rdx # o que havia sido passado em rsi (número de bytes) é colocado em rdx<br />
pop %rsi # o que havia sido colocado em rdi (endereço da string) é colocado em rsi<br />
mov $1, %rax # system call 1 is write<br />
mov $1, %rdi # file handle 1 é stdout<br />
syscall # nova chamada ao sistema<br />
<br />
ret<br />
<br />
message:<br />
.ascii "Hello, World\n"<br />
</syntaxhighlight><br />
</li><br />
</ol><br />
{{collapse bottom}}<br />
<br />
=AULA 4 - Dia 9/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*PARTE 2A: Gerenciamento de Processos (cap.3)<br />
*3.1.Conceito de Processo<br />
*3.2.Escalonamento de Processos<br />
*3.3.Operações sobre Processos (Laboratório Operações sobre Processos no Linux: Fork/Exec/Wait)<br />
<br />
===Material de Referência===<br />
<br />
*Slides do Cap.3 - Silberschatz<br />
*Laboratório Fork/Exec/Wait<br />
<br />
=== Exercícios de Demonstração===<br />
<br />
#Executar em um terminal o comando top. Em um outro terminal executar:<br />
yes > /dev/null &<br />
yes > /dev/null &<br />
#Parar um dos processos yes<br />
kill -STOP <pid_yes><br />
#Continuar o processo<br />
kill -CONT <pid_yes><br />
#Destruir todos<br />
killall yes<br />
<br />
=AULA 5 - Dia 14/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*Ainda Processos<br />
*Cap.3.2..Escalonamento de Processos<br />
*Cap.2.3.Operaçṍes sobre processos<br />
*Finalização do Laboratório Fork/Exec/Wait<br />
<br />
===Adendo===<br />
<br />
*Estudar e comentar [https://www.geeksforgeeks.org/wait-system-call-c/]<br />
<br />
=AULA 6 - Dia 16/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*Comunicação Interprocessos (3.4 e 3.5)<br />
*Laboratório de Memória Compartilhada<br />
<br />
=AULA 7 - Dia 21/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Comunicação Interprocessos: Troca de Mensagens (3.6)<br />
*Laboratório de Pipes<br />
<br />
=AULA 8 - Dia 23/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Finalização Lab. pipes nomeados.<br />
*Threads ((cap.4.1, 4.2)<br />
*Lab.Threads de Aplicação<br />
<br />
=AULA 9 - Dia 28/08/2019=<br />
<br />
*Laboratório: Ainda Threads - Um escalonador semi-automático<br />
<br />
<br />
=AULA 10 - Dia 30/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Repassar um primeiro estudo sobre o RTOS<br />
*Revisar Processos e Threads<br />
<br />
==Questionário - Processos==<br />
<br />
#Conceitue processo. Descreva e explique cada uma das seções de um processo na memória.<br />
#Faça um diagrama e explique os possíveis estados de um processo no sistema. O que produz a transição entre estados?<br />
#O que é um Bloco de Controle de Processo? Quais informações ficam armazenadas neste bloco?<br />
#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.<br />
#Explique o que é multiprogramação e escalonamento de processos.<br />
#O que é a fila de processos prontos?<br />
#Diferencie um processo limitado por IO de um processo limitado por CPU.<br />
#Diferencie escalonamento de longo prazo de escalonamento de curto prazo.<br />
#Discuta o papel da interrupção na troca de contexto entre processos.<br />
#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?<br />
#Explique como funciona a chamada exec no UNIX/Linux<br />
#Explique como funciona a chamada wait no UNIX/Linux e como é possível retornar valores de um filho para o pai.<br />
#Faça um esqueleto de um programa UNIX/Linux que ao se tornar processo cria 3 filhos e espera pela execução dos mesmos.<br />
<br />
==Questionário - Comunicação entre Processos==<br />
<br />
#Diferenciar processos independentes de processos cooperantes.<br />
#Enumere e explique quatro razões para cooperação entre processos.<br />
#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.<br />
#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.<br />
#A memória compartilhada requer chamada ao sistema na sua operação? Discuta.<br />
#Por que o processo de troca de mensagem deve ser mais lento que a memória compartilhada?<br />
#Apresente em pseudocódigo uma proposta de funcionamento do problema do produtor consumidor usando memória compartilhada.<br />
#A construção de uma solução para o problema produtor consumidor pode ser facilitado pelo uso da memória compartilhada? Discuta.<br />
#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?<br />
#Enumere três métodos de implementação de uma lógica de ligação (link) entre processos.<br />
#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.<br />
#Descreva a variante assimétrica da troca direta de mensagens. O que muda em termos de primitiva de comunicação?<br />
#Descreva o problema de hard-coding associado a nomeação direta e como pode ser contornado através da nomeação/comunicação indireta?<br />
#O que é uma caixa postal? Como o Posix identifica uma caixa postal no caso de fila de mensagens?<br />
#Dois processos podem usar mais do que uma caixa postal para se comunicar? Qual a condição para que isto ocorra?<br />
#Descreva as duas operações básicas para a troca de mensagens com Caixa Postal.<br />
#Descreva na comunicação indireta via Caixa Postal as 3 propriedades básicas.<br />
#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.<br />
#De que forma a caixa postal estando no espaço de endereçamento de um processo (propriedade) afeta a recepção por mensagens? Descreva.<br />
#Quais as operações sobre uma caixa postal criada no espaço do sistema operacional deverão ser disponíveis? Descreva.<br />
#A transmissão de mensagem pode ser com e sem bloqueio. Descreva as 4 possibilidades (síncrona/assíncrona).<br />
#Discuta as 3 possibilidades de armazenamento de mensagens em buffer. Em que condições um remetente pode ser bloqueado?<br />
<br />
==ETAPA 1 - Projeto Final==<br />
<br />
*Apresentação (slides) sobre a parte de gerenciamento de tarefas no RTOS;<br />
*apresentação dia 18/09/2019<br />
<br />
==Referências==<br />
<br />
*[https://www.freertos.org/RTOS.html Site do FreeRTOS] ver Mastering the FreeRTOS Real Time Kernel - a Hands On Tutorial Guide <br />
*[https://www.embarcados.com.br/rtos-sistema-operacional-de-tempo-real/]<br />
*[https://github.com/feilipu/avrfreertos]<br />
<br />
=AULA 11 - Dia 4/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Pico de CPU X Pico de IO <br />
*Preempção X Não Preempção<br />
*Escalonamento de Processos: Escalonamento FCFS<br />
<br />
<br />
=AULA 12 - Dia 6/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Escalonamento de Processos: <br />
**Shortest Job First (preemptivo e não preemptivo)<br />
**Prioridade (preemptivo e não preemptivo)<br />
**Round-Robin: Preemptivo<br />
*Lab.Round Robin<br />
<br />
==Material de Referência==<br />
<br />
http://docente.ifsc.edu.br/andre.damato/sop2018/SOP2018-parte2.pdf<br />
<br />
<br />
=AULA 13 - Dia 13/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Sincronização entre Processos<br />
*Laboratório do Esquema de Peterson<br />
<br />
==Material de Referência==<br />
<br />
*Livro Silberchatz<br />
*https://www.os-book.com/OSE1/slide-dir/PPT-dir/ch6.ppt<br />
<br />
=AULA 14 - Dia 18/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Sincronização entre Processos<br />
*Lock de Hardware<br />
*Laboratório do TSL<br />
<br />
==Laboratório Proposto==<br />
<br />
*Refazer o problema proposto usando uma instrução simualada de test and set. Prever um liite superior para entrada de um processo na região crítica.<br />
<br />
==Material de Referência==<br />
<br />
*Livro Silberchatz<br />
*https://www.os-book.com/OSE1/slide-dir/PPT-dir/ch6.ppt<br />
<br />
<br />
=AULA 15 - Dia 20/08/2019=<br />
<br />
==O ATmega238 usado no Arduino UNO==<br />
<br />
Ver [https://pt.wikipedia.org/wiki/ATmega328]<br />
<br />
==O Arduino UNO==<br />
<br />
Ver [https://pt.wikipedia.org/wiki/Arduino]<br />
Ver [https://github.com/feilipu/Arduino_FreeRTOS_Library]<br />
<br />
==O FreeRtos para o Arduino==<br />
<br />
Ver [https://github.com/feilipu/Arduino_FreeRTOS_Library]<br />
<br />
Para instalar no IDE:<br />
*Baixar o ZIP do link acima<br />
*No IDE importar a biblioteca:<br />
**sketch->IncluirBiblioteca->Adicionar do arquivo ZIP<br />
<br />
<br />
==Código Experimental==<br />
<br />
Este código demonstra a ocorrência de "race condition".<br />
<br />
<syntaxhighlight lang=c><br />
// Code based on Examples of Arduino and examples <br />
// from https://github.com/feilipu/Arduino_FreeRTOS_Library<br />
<br />
#include <Arduino_FreeRTOS.h><br />
#include <FreeRTOSVariant.h><br />
#include <task.h><br />
#include <semphr.h><br />
<br />
#define TAM_BUFF 10<br />
<br />
volatile unsigned long race_flag=0xFFEEDDCC;<br />
volatile unsigned long int cont;<br />
int task_cont=0;<br />
<br />
void PrintSerial( void *pvParameters ); // Task para imprimir valor de race_flag<br />
void TaskBlink( void *pvParameters );<br />
void TaskSetarace_flag(void *pvParameters); //Task que atribui race_flag=0xFFEEDDCC<br />
void TaskZerarace_flag(void *pvParameters); //Task que atribui race_flag=0xAA0000AA<br />
<br />
// função de setup<br />
<br />
void setup() {<br />
<br />
Serial.begin(9600);<br />
<br />
while (!Serial) {<br />
; // wait for serial port to connect. Needed for native USB, on LEONARDO, MICRO, YUN, and other 32u4 based boards.<br />
}<br />
<br />
<br />
// criar as 2 tarefas<br />
<br />
xTaskCreate(<br />
TaskBlink<br />
, (const portCHAR *)"Blink" // A name just for humans<br />
, 128 // This stack size can be checked & adjusted by reading the Stack Highwater<br />
, NULL<br />
, 1 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.<br />
, NULL );<br />
<br />
xTaskCreate(<br />
TaskPrintSerial<br />
, (const portCHAR *) "PrintSerial"<br />
, 128 // Stack size<br />
, NULL<br />
, 1 // Priority<br />
, NULL );<br />
<br />
xTaskCreate(<br />
TaskSetarace_flag<br />
, (const portCHAR *) "Setarace_flag"<br />
, 128 // Stack size<br />
, NULL<br />
, 1 // Priority<br />
, NULL );<br />
<br />
xTaskCreate(<br />
TaskZerarace_flag<br />
, (const portCHAR *) "Zerarace_flag"<br />
, 128 // Stack size<br />
, NULL<br />
, 1 // Priority<br />
, NULL );<br />
<br />
cont = race_flag;<br />
<br />
// escalonador toma conta a partir daqui<br />
<br />
}<br />
<br />
void loop()<br />
{<br />
// nada a fazer aqui<br />
}<br />
<br />
/*--------------------------------------------------*/<br />
/*---------------------- Tasks ---------------------*/<br />
/*--------------------------------------------------*/<br />
<br />
void TaskBlink(void *pvParameters) // This is a task.<br />
{<br />
(void) pvParameters;<br />
<br />
/*<br />
Blink<br />
Turns on an LED on for one second, then off for one second, repeatedly.<br />
<br />
Most Arduinos have an on-board LED you can control. On the UNO, LEONARDO, MEGA, and ZERO <br />
it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN takes care <br />
of use the correct LED pin whatever is the board used.<br />
<br />
The MICRO does not have a LED_BUILTIN available. For the MICRO board please substitute<br />
the LED_BUILTIN definition with either LED_BUILTIN_RX or LED_BUILTIN_TX.<br />
e.g. pinMode(LED_BUILTIN_RX, OUTPUT); etc.<br />
<br />
If you want to know what pin the on-board LED is connected to on your Arduino model, check<br />
the Technical Specs of your board at https://www.arduino.cc/en/Main/Products<br />
<br />
This example code is in the public domain.<br />
<br />
modified 8 May 2014<br />
by Scott Fitzgerald<br />
<br />
modified 2 Sep 2016<br />
by Arturo Guadalupi<br />
*/<br />
<br />
// initialize digital LED_BUILTIN on pin 13 as an output.<br />
pinMode(LED_BUILTIN, OUTPUT);<br />
<br />
for (;;) // A Task shall never return or exit.<br />
{<br />
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)<br />
vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second<br />
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW<br />
vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second<br />
}<br />
}<br />
<br />
<br />
<br />
<br />
void TaskPrintSerial(void *pvParameters) // Task que imprime na serial - must be improved...<br />
{<br />
(void) pvParameters;<br />
/*<br />
<br />
*/<br />
<br />
<br />
for (;;)<br />
{ <br />
while (cont==0xAA0000AA || cont==0xFFEEDDCC)<br />
cont = race_flag;<br />
;<br />
<br />
Serial.println("Problemas: valor race_flag é");<br />
Serial.println(cont, HEX);<br />
<br />
vTaskDelay(5); // one tick delay (15ms) in between reads for stability - b<br />
cont = race_flag;<br />
}<br />
}<br />
<br />
void TaskSetarace_flag(void *pvParameters) <br />
{<br />
(void) pvParameters;<br />
const TickType_t xMaxBlockTimeTicks = 0x20;<br />
/*<br />
<br />
*/<br />
<br />
race_flag=0xAA0000AA;<br />
for (;;)<br />
{<br />
race_flag=0xAA0000AA;<br />
//Serial.println("Produtor");<br />
vTaskDelay( ( rand() %xMaxBlockTimeTicks) ); <br />
} <br />
<br />
}<br />
<br />
void TaskZerarace_flag(void *pvParameters) <br />
{<br />
(void) pvParameters;<br />
const TickType_t xMaxBlockTimeTicks = 0x20;<br />
/*<br />
<br />
*/<br />
race_flag=0xFFEEDDCC;<br />
<br />
for (;;)<br />
{<br />
race_flag=0xFFEEDDCC;<br />
vTaskDelay( ( rand() %xMaxBlockTimeTicks) ); <br />
if(task_cont++==100) {<br />
delay(1);<br />
Serial.println("Fim TaskZera - valor race_flag ");<br />
Serial.println(race_flag, HEX);<br />
for(;;);<br />
} <br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=AULA 16 - Dia 25/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Preparação de exemplos de RTOS sobre Arduíno para apresentação na sexta;<br />
<br />
=Laboratórios Propostos= <br />
<br />
Considere o código abaixo. Observe que a região de dados compartilhada shared_data é zerada pelo pai e setada pelo processo filho. O pai detecta inconsistências nos dados que operou. Tente corrigir usando o esquema de Peterson para acesso a região crítica. Crie uma função de entrada e de saída da região crítica.<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
<br />
<br />
#define BUFFER_SIZE 4096<br />
char *shared_data;<br />
char reference_data[BUFFER_SIZE];<br />
<br />
main()<br />
{ <br />
key_t key;<br />
int shmid;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, BUFFER_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
shared_data = shmat(shmid, (void *)0, 0);<br />
<br />
if (shared_data == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int count=0; <br />
memset(reference_data,0,BUFFER_SIZE); <br />
for(;;){ <br />
memset(shared_data,0,BUFFER_SIZE);<br />
if (memcmp(shared_data, reference_data, BUFFER_SIZE)!=0) {<br />
count++;<br />
if (count%1000000==0)<br />
printf("Processo pai detectou algo errado nos dados %d\n", count); <br />
} <br />
} <br />
<br />
<br />
}<br />
else { /*Child code */<br />
<br />
for(;;){ <br />
memset(shared_data,1,BUFFER_SIZE); <br />
}<br />
<br />
}<br />
<br />
if (shmdt(shared_data) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
Possível solução:<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
#include <unistd.h><br />
<br />
#define BUFFER_SIZE 4096<br />
#define ID_PAI 0<br />
#define ID_FILHO 1<br />
#define FALSE 0<br />
#define TRUE 1<br />
<br />
char *shared_data;<br />
char reference_data[BUFFER_SIZE];<br />
<br />
struct tipo_peterson{<br />
char flag[2];<br />
char turn;<br />
} *pet_struct;<br />
<br />
void ent_sec_crit(int id)<br />
{<br />
char id_outro = (id+1)%2;<br />
<br />
pet_struct->flag[id] = TRUE; // indica que o processo deseja entrar na região crítica<br />
pet_struct->turn = id_outro; // o processo sinaliza para o outrao entrar, <br />
// caso o outro esteja entrando<br />
// este ponto é uma race condition: turn pode ser 0 ou 1 <br />
while ( (pet_struct->flag[id_outro]==TRUE) && (pet_struct->turn == id_outro) )<br />
;<br />
}<br />
<br />
void sai_sec_crit(int id)<br />
{<br />
pet_struct->flag[id] = FALSE;<br />
}<br />
<br />
int main()<br />
{ <br />
key_t key;<br />
int shmid;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, BUFFER_SIZE+sizeof(struct tipo_peterson), S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
shared_data = shmat(shmid, (void *)0, 0);<br />
pet_struct = (struct tipo_peterson *) (shared_data + BUFFER_SIZE); <br />
<br />
if (shared_data == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int count=0; <br />
memset(reference_data,0,BUFFER_SIZE); <br />
for(;;){ <br />
ent_sec_crit(ID_PAI);<br />
memset(shared_data,0,BUFFER_SIZE);<br />
if (memcmp(shared_data, reference_data, BUFFER_SIZE)!=0) {<br />
count++;<br />
if (count%1000000==0)<br />
printf("Processo pai detectou algo errado nos dados %d\n", count); <br />
} <br />
sai_sec_crit(ID_PAI);<br />
} <br />
<br />
<br />
}<br />
else { /*Child code */<br />
<br />
for(;;){<br />
ent_sec_crit(ID_FILHO); <br />
memset(shared_data,1,BUFFER_SIZE);<br />
sai_sec_crit(ID_FILHO); <br />
}<br />
<br />
}<br />
<br />
if (shmdt(shared_data) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
=AULA 17 - Dia 27/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Apresentação dos Trabalhos<br />
*Definição da próxima etapa<br />
<br />
=AULA 18 - Dia 02/10/2019=<br />
<br />
==Objetivos==<br />
<br />
*Semáforos, Deadlock e o Problema da Inversão de Prioridade<br />
*Laboratório de Pthreads e Mutex;<br />
<br />
==Laboratório Proposto==<br />
<br />
*Lab. Programação concorrente - Parte 1<br />
<br />
==Materia de Referência==<br />
<br />
*[https://www.os-book.com/OSE1/slide-dir/PDF-dir/ch6.pdf]<br />
<br />
==Desafio==<br />
<br />
Usar <br />
ps -T aux | grep ex1vA<br />
<br />
Para ver os threads dormindo...<br />
<br />
Otimizar o programa abaixo<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <pthread.h><br />
#include <stdlib.h><br />
#include <unistd.h><br />
#include <time.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
pthread_mutex_t mut;<br />
<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
<br />
<br />
long long i;<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
usleep(5000000);<br />
printf("Novo saldo = %d\n",novo_saldo);<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d\n", (i+1));<br />
exit(-1);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
printf("Saldo final é %d\n", saldo);<br />
}<br />
</syntaxhighlight><br />
<br />
=AULA 19 - Dia 04/10/2019=<br />
<br />
==Objetivos==<br />
<br />
*Ainda Semáforos, Deadlock e o Problema da Inversão de Prioridade<br />
*Laboratório de Pthreads com semáforo binário;<br />
*Laboratório de Pthreads com semáforos contador como solução do problema do produtor e consumidor.<br />
<br />
<br />
==Material de Referência==<br />
<br />
*ver laboratório de Programação concorrente<br />
<br />
==Laboratório Proposto==<br />
<br />
=AULA 20 - Dia 9/10/2019=<br />
<br />
==Objetivos==<br />
<br />
*Problemas clássicos de sincronização;<br />
<br />
==Material de Referência==<br />
<br />
<br />
https://www.os-book.com/OSE1/slide-dir/PDF-dir/ch6.pdf<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Programação concorrente}}<br />
<br />
== Programação concorrente ==<br />
<br />
<br />
===PARTE 1 - Mutex e Biblioteca libpthreads===<br />
<br />
;POSIX Threads<br />
A 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):<br />
*''pthread_create'': cria uma thread;<br />
*''pthread_kill'': força a terminação de uma thread;<br />
*''pthread_join'': sincroniza o final de uma thread (qual a diferença/semelhança com o ''wait'' que usamos para processos?);<br />
*''pthread_exit'': finaliza uma thread.<br />
Para utilizar estas funções é necessário linkar o programa à libpthread (''-lpthread''). <br />
<br />
<br />
;POSIX pthread mutex<br />
<br />
A biblioteca pthread implementa um tipo ''pthread_mutex_t'', que garante a exclusão mútua entre threads. Estes mutex são manipulados através das funções (acesse as man-pages das chamadas para maiores detalhes):<br />
*''pthread_mutex_lock'': acessa um mutex.<br />
*''pthread_mutex_trylock'': tenta acessar um mutex (retorna valor indicando sucesso ou falha no lock).<br />
*''pthread_mutex_unlock'': libera um mutex.<br />
<br />
<br />
<br />
;Exercício 1<br />
<br />
O programa abaixo cria 5 threads, e cada uma destas threads atualiza uma variável global (memória compartilhada).<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
#include <pthread.h><br />
#include <stdlib.h><br />
#include <unistd.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
pthread_mutex_t mut;<br />
<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
long long i;<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
sleep(1);<br />
printf("Novo saldo = %d\n",novo_saldo);<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d\n", (i+1));<br />
exit(-1);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
printf("Saldo final é %d\n", saldo);<br />
}<br />
</syntaxhighlight><br />
<br />
# Compile este programa. <br />
# Execute este programa várias vezes. Ele funciona? Será que ele gera as saídas esperadas?<br />
# Identifique as '''seções críticas''' do programa.<br />
# Corrija o programa utilizando '''mutex'''. <br />
# Analise a função ''AtualizaSaldo()'' com a sua solução. Lembre-se que o uso do mutex implica em apenas uma thread acessar a seção crítica por vez, enquanto outras threads ficam bloqueadas, esperando. Disso vem que, quanto menor o trecho de código entre um ''lock'' e um ''unlock'', menos tempo uma thread necessita ficar esperando.<br />
<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <cstring><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
<br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
sem_t sem;<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
int value;<br />
sem_wait(&sem);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
sem_getvalue(&sem, &value);<br />
printf("valor sem = %d\n", value);<br />
sem_post(&sem);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
sem_init(&sem,0,1);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
sem_destroy(&sem);<br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
===PARTE 2 - POSIX Semaphores Binários===<br />
<br />
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):<br />
*''sem_init'': inicializa um semáforo;<br />
*''sem_destroy'': destroy um semáforo;<br />
*''sem_wait'': implementa a operação ''p'';<br />
*''sem_post'': implementa a operação ''v''.<br />
Para utilizar estas funções é necessário linkar o programa à librt ou à libpthread (''-lrt'' ou ''-lpthread'').<br />
<br />
;Exercício 1<br />
Modifique o programa para usar um semáforo binário ao invés de um mutex em sua solução.<br />
<br />
;Exercício 2 - Fazer em casa<br />
Refaça o exercício 3 usando processos criados com fork e exec. O semáforo deve ser criado em uma região de memória compartilhada.<br />
<br />
===PARTE 3 - POSIX Semaphores===<br />
<br />
;Exercício 3<br />
Implemente com pthreads e semáforos/mutex a solução do produtor/comsumidor conforme sugerido no livro do Silberchatz. USe dois semáforos: (i) um para controlar o numero de itens vazios no buffer (semáforo empty - quando zero o thread produtor deve parar de produzir). (ii) um semáforo para controlar o numero de itens ocupados no buffer (semáforo full - quando zero o consumidor deve parar de consumir).<br />
<br />
<!--<br />
<code><br />
#include <stdio.h><br />
#include <pthread.h><br />
#include <stdlib.h><br />
#include <unistd.h><br />
#include <time.h><br />
#include <semaphore.h> <br />
<br />
#define NUM_THREADS 5<br />
<br />
#define NUM_MAX 1000<br />
#define TAM_BUFF 100<br />
<br />
pthread_mutex_t mut;<br />
sem_t full,empty; <br />
<br />
int buffer[TAM_BUFF];<br />
<br />
<br />
void *Produtor(void* arg)<br />
{<br />
int i;<br />
int in=0;<br />
for(i=0;i<NUM_MAX;i++) {<br />
sem_wait(&empty);<br />
pthread_mutex_lock(&mut);<br />
buffer[in]=i;<br />
pthread_mutex_unlock(&mut);<br />
sem_post(&full); <br />
in=(in+1)%TAM_BUFF;<br />
printf("Produtor: produzi um item...\n");<br />
if(i%20==0)<br />
usleep(500000); <br />
}<br />
}<br />
<br />
void *Consumidor(void* arg)<br />
{<br />
int i;<br />
int dado;<br />
int out=0;<br />
for(i=0;i<NUM_MAX;i++) {<br />
//usleep(100000);<br />
sem_wait(&full);<br />
pthread_mutex_lock(&mut);<br />
dado=buffer[out];<br />
pthread_mutex_unlock(&mut);<br />
printf("item consumido = %d\n", dado);<br />
out=(out+1)%TAM_BUFF;<br />
sem_post(&empty);<br />
}<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[2];<br />
<br />
sem_init(&full, 0, 0);<br />
sem_init(&empty, 0, TAM_BUFF);<br />
pthread_mutex_init(&mut, NULL);<br />
pthread_create(&threads[0], NULL, Produtor,NULL);<br />
pthread_create(&threads[1], NULL, Consumidor,NULL);<br />
<br />
pthread_join(threads[0], NULL);<br />
pthread_join(threads[1], NULL);<br />
}<br />
</syntaxhighlight><br />
<br />
--><br />
<br />
===PARTE 4 - POSIX Semaphores===<br />
<br />
;Exercício 4<br />
<br />
O programa abaixo manipula uma matriz de tamanho MxN (veja os defines para o tamanho da matriz). A função ''SumValues'' soma todos os valores em uma linha da matriz. A linha a ser somada é identificada pela variável ''i''. Modifique o programa principal (''main'') nos locais indicados para:<br />
# Criar N threads, uma para somar os valores de cada linha.<br />
# Receber o resultado do somatório de cada linha e gerar o somatório total da matriz.<br />
# Analise o programa: há problemas de sincronização que precisam ser resolvidos? Se sim, resolva-os.<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include "thread.h"<br />
<br />
/* number of matrix columns and rows */<br />
#define M 5<br />
#define N 10<br />
<br />
using namespace std;<br />
<br />
int matrix[N][M];<br />
Thread *threads[N];<br />
<br />
<br />
/* thread function; it sums the values of the matrix in the row */<br />
int SumValues(int i)<br />
{<br />
int n = i; /* number of row */<br />
int total = 0; /* the total of the values in the row */<br />
int j;<br />
for (j = 0; j < M; j++) /* sum values in the "n" row */<br />
total += matrix[n][j];<br />
cout << "The total in row" << n << " is " << total << "." << endl;<br />
/* terminate a thread and return a total in the row */<br />
exit(total);<br />
}<br />
<br />
int main(int argc, char *argv[])<br />
{<br />
int i, j;<br />
int total = 0; /* the total of the values in the matrix */<br />
<br />
/* initialize the matrix */<br />
for (i = 0; i < N; i++)<br />
for (j = 0; j < M; j++)<br />
matrix[i][j] = i * M + j;<br />
<br />
/* create threads */<br />
/* COLOQUE SEU CÓDIGO PARA CRIAR AS THREADS AQUI! */<br />
<br />
/* wait for terminate a threads */<br />
/* COLOQUE SEU CÓDIGO PARA PEGAR O SOMATÓRIO DE LINHAS E TOTALIZAR A SOMA DA MATRIZ AQUI! */<br />
<br />
cout << "The total values in the matrix is " << total << endl;<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
{{collapse bottom}}<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Escalonamento Round Robin e FCFS para Threads"}}<br />
<br />
== Escalonamento Round-Robin ==<br />
<br />
OBS: ver https://www.quora.com/What-exactly-does-typedef-do-in-C<br />
<br />
O Exemplo abaixo mostra a implementação de um esquema de escalonamento Round Robin do exercício anterior.<br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
Modificado por Eraldo <br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 5<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
void runA(void) {<br />
for (;;) {<br />
printf("running A\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runB(void) {<br />
for (;;) {<br />
printf("running B\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 1<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
<br />
void scheduler_rr();<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void yield_thread()<br />
{<br />
scheduler_rr();<br />
}<br />
<br />
void delete_thread()<br />
{<br />
delete curr_thread;<br />
curr_thread=NULL;<br />
scheduler_rr();<br />
}<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
struct delta{<br />
long alfa;<br />
char epson[1000];<br />
long beta;<br />
} shar;<br />
<br />
int turn;<br />
int flag[2];<br />
<br />
#define TRUE 1<br />
#define FALSE 0<br />
<br />
void ent_rc(int p, int vt)<br />
{<br />
flag[p]=TRUE;<br />
turn = vt;<br />
if(p) p=0; else p=1;<br />
while (flag[p] && turn == vt);<br />
//printf("Thread %d: esperando para acessar a região crítica\n", p);<br />
}<br />
<br />
void sai_rc(int p)<br />
{<br />
flag[p]=FALSE;<br />
}<br />
<br />
void runA(void) {<br />
struct delta x = {0, 100};<br />
<br />
for (;;) {<br />
x.alfa=0;x.beta=0;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0);<br />
x.alfa=100;x.beta=100;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0); <br />
}<br />
}<br />
<br />
void runB(void) {<br />
<br />
for (;;) {<br />
ent_rc(1,0);<br />
printf("shar alfa = %ld shar beta = %ld \n",shar.alfa, shar.beta); // regiao crítica<br />
sai_rc(1);<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runC(void) {<br />
int i;<br />
for (i=0;i<10;i++) {<br />
printf("Thread C - parte 1\n");<br />
yield_thread();<br />
printf("Thread C - parte 2\n");<br />
yield_thread();<br />
}<br />
delete_thread();<br />
}<br />
<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
add_thread(runC);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
{{collapse bottom}}<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Um escalonador semi-automático"}}<br />
<br />
== Ainda Threads - Um escalonador semi-automático usando sinais ==<br />
<br />
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.<br />
<br />
===Exemplo 1:===<br />
<br />
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. <br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
<br />
void sig_handler(int signo)<br />
{<br />
int x;<br />
printf("Turma de SOP: recebido SIGUSR1\n");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
// Loop eterno dormindo 1s<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Fazer no terminal:<br />
ps aux<br />
anotar o pid do processo e enviar o sinal:<br />
kill -USR1 pid<br />
<br />
===Exemplo 2:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// loop eterno que nunca é executado<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Enviar o sinal USR1 para ver o efeito. <br />
<br />
===Exemplo 3:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void prepara_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void prepara_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
prepara_contexto_ping();<br />
prepara_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// A long long wait so that we can easily issue a signal to this process<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Exercício: Use o comando htop para verificar como estes threads são vistos pelo SOP.<br />
<br />
Exercício: Tente analisar as pilhas dos threads e verificar sob qual pilha o handler se executa.<br />
<br />
<br />
===Exercício 4:===<br />
<br />
Neste ponto associamos um timer ao handler com o apoio do sinal ALRM. Agora os threads são escalonados automaticamente.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
===Exercício Proposto 5===<br />
<br />
Colocar 3 threads rodando.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void preparar_contexto_ping(ucontext_t *pContext, char *p)<br />
{<br />
char *stack;<br />
<br />
getcontext(pContext);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
(*pContext).uc_stack.ss_sp = stack ;<br />
(*pContext).uc_stack.ss_size = STACKSIZE;<br />
(*pContext).uc_stack.ss_flags = 0;<br />
(*pContext).uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(pContext, (void*)(*f_ping), 1, p);<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping(&cPing, "ping");<br />
preparar_contexto_ping(&cPong, "pong");<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Threads de aplicação}}<br />
<br />
== Threads de aplicação ==<br />
<br />
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:<br />
*'''getcontext(&a)''': salva o contexto na variável '''a''';<br />
*'''setcontext(&a)''': restaura um contexto salvo anteriormente na variável '''a''';<br />
*'''swapcontext(&a,&b)''': salva o contexto atual na variável '''a''' e restaura o contexto salvo anteriormente na variável '''b''';<br />
*'''makecontext(&a, ...)''': ajusta parâmetros internos do contexto salvo em '''a''';<br />
*'''ucontext_t''': as variáveis '''a''' e '''b''' são do tipo '''ucontext_t'''. Este tipo armazena um contexto.<br />
<br />
Busque mais informações sobre estas funções utilizando o programa manpage do Linux (ex.: man getcontext).<br />
<br />
Estude o código no arquivo pingpong.c abaixo e explique seu funcionamento.<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
*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.<br />
*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.<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain, cFnew;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_new(void * arg1, void * arg2,void * arg3,void * arg4) <br />
{<br />
printf ("%s: Primeira string %s %s %s\n",(char*) arg1,(char*) arg2,(char*) arg3, (char*) arg4);<br />
swapcontext(&cFnew, &cMain); <br />
}<br />
<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
<br />
getcontext(&cFnew);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cFnew.uc_stack.ss_sp = stack ;<br />
cFnew.uc_stack.ss_size = STACKSIZE;<br />
cFnew.uc_stack.ss_flags = 0;<br />
cFnew.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cFnew, (void*)(*f_new), 4, "\tF_new", "\tAlo", "\tMundo","\tReal");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
swapcontext(&cMain, &cFnew);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
--><br />
Exercício 3: O que acontece se um dos threads é colocado para dormir? Todos os demais threads param a sua execução.<br />
<br />
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/<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Processos no Linux}}<br />
<br />
== Processos no Linux - Modificado por Eraldo ==<br />
<br />
<blockquote style="background: lime; border: 1px solid black; padding: 1em;"><br />
Processos no Linux<br />
</blockquote><br />
<br />
*Exercícios propostos pelo Prof.Arliones e Modificados por Eraldo<br />
<br />
<br />
[[imagem:DesenhoForkExec.png|border|650px]]<br />
<br />
<br />
;Syscall FORK<br />
<br />
* Em um terminal, execute "man fork"<br />
** 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'''.<br />
** O '''código''' dos dois processos (pai e filho) são '''idênticos''';<br />
** Os '''dados''' dos dois processos (pai e filho) são '''idênticos NO MOMENTO DA CRIAÇÃO''';<br />
** Execução do processo filho inicia na próxima instrução do programa (no retorno da chamada FORK);<br />
** Não é possível saber qual dos processos (pai ou filho) retormará a execução primeiro - isto fica a cargo do excalonador do SO;<br />
** Valores de retorno da chamada FORK:<br />
*** (-1): erro na criação do processo (ex.: memória insuficiente);<br />
*** (0): em caso de sucesso, este é o valor de retorno recebido pelo processo filho;<br />
*** (>0): em caso de sucesso, este é o valor de retorno recebido pelo processo pai;<br />
<br />
;Syscall JOIN<br />
<br />
* A syscall JOIN é implementada no POSIX pela função '''wait()'''. Execute "man wait".<br />
** Além da função '''wait()''', há também '''waitpid()''' e '''waitid()''';<br />
** 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);<br />
** A chamada wait também libera os recursos do processo filho que termina;<br />
** '''wait()''': esta função suspende a execução do processo chamador até que UM DOS SEUS FILHOS finalize;<br />
** '''waitpid()''': suspende a execução do processo chamador até que UM FILHO ESPECÍFICO finalize;<br />
<br />
;Syscall EXEC<br />
<br />
* A syscall EXEC é implementada no POSIX pela família de funções '''exec()'''. Execute "man exec".<br />
** As principais funções da família são '''execl()''', '''execlp()''' e '''execvp()''';<br />
** 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;<br />
** 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;<br />
<br />
<br />
;Exemplos POSIX utilizando fork/wait/exec<br />
<br />
*Exemplo 1: fork/wait básico<br />
<syntaxhighlight lang=c><br />
// ex1: fork/wait básico<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
printf("processo filho\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
printf("processo pai\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
arliones@socrates:~/tmp$ gcc ex1.c -o ex1 <br />
arliones@socrates:~/tmp$ ./ex1 <br />
processo filho pid: 27858 pid pai: 27857<br />
processo pai pid: 27857 pid pai: 5337<br />
arliones@socrates:~/tmp$ <br />
</syntaxhighlight><br />
<br />
* Exemplo 2: processos pai e filho compartilham código, mas não dados.<br />
<syntaxhighlight lang=c><br />
// ex2: fork/wait "compartilhando" dados<br />
// ex2: fork/wait "compartilhando" dados<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status, k=0;<br />
printf("processo %d\t antes do fork\n", getpid());<br />
pid = fork();<br />
printf("processo %d\t depois do fork\n", getpid());<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
k += 1000;<br />
printf("processo filho\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status); // espera o filho terminar<br />
k += 10;<br />
printf("processo pai\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
k += 1000;<br />
printf("FIM processo %d\t K: %d\n", getpid(), k); <br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
processo 17056 antes do fork<br />
processo 17056 depois do fork<br />
processo 17057 depois do fork<br />
processo filho pid: 17057 K: 1000 endereço K: 0x7ffd8923e318<br />
processo pai pid: 17056 K: 10 endereço K: 0x7ffd8923e318<br />
</syntaxhighlight><br />
<br />
* Modificação no código: comentar linhas 23 e 30<br />
<br />
<syntaxhighlight lang=bash><br />
<br />
</syntaxhighlight><br />
<br />
* Analise os resultados e busque entender a diferença.<br />
*Perguntas e desafios.:<br />
#Analisando os valores impressos de k pode-se dizer que os dados são compartilhados entre os dois processos?<br />
#O endereço de k impresso é o mesmo nos dois processos. ISto não contradiz a afirmação anterior?<br />
#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.<br />
<br />
<br />
;Exercício fork/wait<br />
<br />
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.<br />
<br />
*Use o comando pstree para verificar a árvore de processos criada.<br />
<br />
{{collapse top|Solução}}<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
<!--<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
--><br />
<br />
;DESAFIO: fork/wait<br />
<br />
Reimplementar o exercício anterior de criação de uma árvore de 3 processos, generalizando a criação de N processos onde N é repassado na linha de comando do programa. SUGESTÃO: usar um comando for, mas lembrar que se existe um fork dentro do for, então cada filho gerado dará continuidade a execução do for. É necessário que o processo faça um exit ou retorne neste momento.<br />
<br />
;DESAFIO: Exercício status/wait<br />
<br />
O ''status'' passado como parâmetro à função ''wait(&status)'' é, na verdade, o mecanismo de retorno de resultado do ''wait/waitpid''. Ao retornar, esta variável contém informações sobre o resultado da execução do processo filho. Por exemplo, se um processo terminou normalmente (i.e., chamou ''exit''), o comando ''WIFEXITED(status)'' retorna ''true''. Este comando retorna ''false'' se o processo foi abortado (e.g., ''segmentation fault'') ou morto (e.g., ''kill''). Investigue no manual do wait no Linux (''man wait'') o funcionamento do comando WEXITSTATUS(status). <br />
Imagine um problema de busca de dados armazenados na forma de uma matriz de inteiros 4x30. Você está interessado em saber quantas ocorrências de um determinado número existe em cada linha da matriz. Note que que são tarefas que podem ser paralelizadas e usufruir de um sistema capaz de executá-las em paralelo. Faça uma implementação paralelizando 4 processos filhos a partir de um pai, onde cada processo é responsável por uma busca. A quantidade de ocorrências do número buscado é retornada e capturada através de WEXITSTATUS.<br />
<br />
;Syscall EXEC<br />
<br />
*Exemplo exec()<br />
<br />
<syntaxhighlight lang=c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
execl("/bin/ls","ls","-l", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 1: Modificar o código para mostrar que o exec() não retorna (colocar um printf após o exec).<br />
<br />
*Exercício 2: Criar um exemplo (dois programas ) para demonstrar que o exec não cria novo processo. <br />
**Crie um primeiro programa (prog1) que imprime o seu pid e depois faz um exec do segundo programa.<br />
**Crie o segundo programa que simplesmente imprime o pid.<br />
<br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU ANTES DO EXEC: Meu pid é %d\n", getpid());<br />
execl("./prog2","prog2", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU DEPOIS DO EXEC:Meu pid é %d\n", getpid());<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 3: Criar um exemplo usando fork/exec mostrando que um processo pai cria um filho e espera por sua execução. O filho executa o comando "ps aux". Ambos devem mostrar seus pids.<br />
<br />
{{collapse bottom}} <br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Laboratório Memória Compartilhada entre Pai e Filho - Produtor Consumidor}}<br />
<br />
Baseado no Lab. do Prof.Arliones<br />
<br />
=== Objetivo ===<br />
<br />
*Familiarizar o aluno com o conceito de Memória Compartilhada entre Processos Pai e Filho<br />
*Familizarizar o aluno com o conceito de Produtor Consumidor<br />
<br />
=== Referencial Teórico-Prático ===<br />
<br />
* Silberchatz - 3.4 e 3.5<br />
* man nos comandos shmat e shmget<br />
<br />
=== Exemplo de Funcionamento ===<br />
<br />
No exemplo abaixo um processo pai compartilha uma área de memória com o processo filho. O processo filho escreve uma mensagem para o pai na área de memória compartilhada e termina. O processo pai é desbloqueado no wait e imprime a mensagem escrita.<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
char *ptr_msg = "alo pai, tudo bem?"; <br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
strcpy(segmento, ptr_msg);<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(&filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
=== Desafio a ser Implementado em Sala ===<br />
<br />
Construir um programa em que um processo pai atua como produtor e o processo filho atua como consumidor. O buffer circular compartilhado é um buffer de inteiro de tamanho 5. O pai alimentará o buffer com 50 itens gerados aleatóriamente entre 1 e 100. A cada escrita/leitura no buffer o produtor/consumidor deve esperar alguns milisegundos de forma a acontecer situações de buffer cheio e vazio. <br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
#include <unistd.h><br />
#include <time.h><br />
#include <sys/types.h><br />
#include <sys/wait.h><br />
<br />
<br />
<br />
#define SHM_SIZE 1024 <br />
<br />
#define BUFF_COMP_SIZE 5<br />
<br />
struct buff_comp {<br />
int buffer[BUFF_COMP_SIZE];<br />
int in,out;<br />
};<br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
struct buff_comp *p; <br />
<br />
/* initialize random seed: */<br />
srand ( time(NULL) );<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
p = (struct buff_comp *) shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
p->out = p->in = 0;<br />
<br />
if((filho = fork()) == -1)<br />
{<br />
<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
int i;<br />
for(i=0;i<50;i++) {<br />
while (p->in==p->out) {<br />
printf("FILHO: BUFFER VAZIO !!!!!!!\n");<br />
usleep(rand() % 10000 + 1);<br />
}<br />
printf("FILHO: item lido = %d\n", p->buffer[p->out]);<br />
p->out = (p->out+1)%BUFF_COMP_SIZE;<br />
}<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
int i; <br />
<br />
for(i=0;i<50;i++) {<br />
while (((p->in+1)%BUFF_COMP_SIZE) == p->out) {<br />
printf("PAI: BUFFER CHEIO !!!!!!!\n");<br />
usleep(rand() % 10000 + 1);<br />
}<br />
p->buffer[p->in] = rand() % 100 + 1;<br />
printf("PAI: item produzido = %d\n", p->buffer[p->in]);<br />
p->in = (p->in+1)%BUFF_COMP_SIZE;<br />
<br />
}<br />
wait(&filho); <br />
<br />
}<br />
<br />
<br />
if (shmdt(p) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Trocas de mensagens com pipes}}<br />
<br />
= Trocas de mensagens com pipes =<br />
<br />
;Troca de mensagens<br />
Um mecanismo disponibilizado por sistemas UNIX para troca de mensagens entre processos é o PIPE. Pipes são mecanismos de comunicação indireta onde mensagens são trocadas através de ''mailboxes''. Cada ''mailbox'' possui um identificador único, permitindo que processos identifiquem o canal de comunicação entre eles. O fluxo de mensagens em um Pipe é:<br />
*'''unidirecional''': sobre um mesmo pipe, apenas um processo envia mensagens e um processo recebe mensagens;<br />
*'''FIFO''': as mensagens são entregues na ordem de envio;<br />
*'''não-estruturado''': não há estrutura pré-definida para o formato da mensagem.<br />
No UNIX, pipes são inicializados através da '''SystemCall''' ''pipe'', que possui a seguinte sintaxe:<br />
*''int pipe(int pipefd[2])'': ''pipe'' inicializa um novo pipe no sistema e retorna, no array pipefd, os descritores identificando cada uma das pontas do pipe. A primeira posição do array, i.e. pipefd[0], recebe o descritor que pode ser aberto apenas para leitura, enquanto a segunda posição do array, i.e. pipefd[1], recebe o descritor que pode ser aberto apenas para escrita. A função retorna zero no caso de sucesso, ou -1 se ocorrer erro.<br />
As primitivas send/receive para uso de um pipe no UNIX são implementadas por '''SystemCalls''' read/write, conforme segue:<br />
*''ssize_t read(int fd, void *buf, size_t count)'': “puxa” dados do pipe identificado pelo descritor fd. Os dados recebidos são os apontados pelo ponteiro buf, sendo count a quantidade máxima de bytes a serem recebidos. A função retorna o número de bytes recebidos.<br />
*''ssize_t write(int fd, const void *buf, size_t count)'': “empurra” dados no pipe identificado pelo descritor fd. Os dados transmitidos são os apontados pelo ponteiro buf, sendo count a quantidade de bytes a serem transmitidos. A função retorna o número de bytes transmitidos.<br />
<br />
*Exemplo 1: Transmitindo e recebendo pelo próprio processo<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main()<br />
{<br />
int fd[2];<br />
char *ptr = "Alo eu mesmo";<br />
char *ptr_alvo;<br />
int tamanho_dados, ret;<br />
<br />
tamanho_dados = strlen(ptr)+1;<br />
<br />
if (pipe(fd)==-1){<br />
printf ("erro criação pipe\n");<br />
exit(-1);<br />
}<br />
printf("Transmitido %d bytes\n", tamanho_dados);<br />
write (fd[1], ptr, tamanho_dados);<br />
<br />
ptr_alvo = malloc(tamanho_dados);<br />
<br />
ret=read(fd[0],ptr_alvo,tamanho_dados);<br />
<br />
printf("ret = %d dados => %s\n", ret, ptr_alvo); <br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
*Exemplo 2: Abaixo há um exemplo de programa criando um pipe e compartilhando os descritores entre dois processos (criados via ''fork()'').<br />
<syntaxhighlight lang=c><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
<br />
char *message = "This is a message!!!" ;<br />
<br />
main()<br />
{<br />
char buf[1024] ;<br />
int fd[2];<br />
pipe(fd); /*create pipe*/<br />
if (fork() != 0) { /* I am the parent */<br />
write(fd[1], message, strlen (message) + 1) ;<br />
}<br />
else { /*Child code */<br />
read(fd[0], buf, 1024) ;<br />
printf("Got this from MaMa!!: %s\n", buf) ;<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
*'''Exercício 1: construa um “pipeline”'''. Crie um programa que conecta 4 processos através de 3 pipes. Utilize ''fork()'' para criar vários processos.<br />
<br />
<syntaxhighlight lang=cpp><br />
<br />
//Solução possível<br />
<br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
pipe(fd);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
<br />
</syntaxhighlight><br />
<br />
*'''Exercício 2: Modifique o exercício anterior para que o processo D, através de um novo pipe, mande uma mensagem diretamente para o pai de todos.<br />
<br />
<!--<br />
<code><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
int fd_retorno[2];<br />
<br />
pipe(fd);<br />
pipe(fd_retorno);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size);<br />
read(fd_retorno[0], buf, size);<br />
printf("PAI:%s\n", buf); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
char *ptr_msg_ret="Ok msg de D para o pai";<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
write(fd_retorno[1],ptr_msg_ret,strlen(ptr_msg_ret)+1);<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
*'''Exercício 3: Consultor de Login de Acesso:'''. Estude o link https://www.geeksforgeeks.org/named-pipe-fifo-example-c-program/ e projete um programa cliente servidor da seguinte forma: (i) O servidor possui uma tabela de usuários (userid). O user_id é de tamanho fixo de 7 caracteres. O servidor espera por consultas para verificar se um usuário está na tabela. Se estiver responde com o caracter 'S' senão com 'N'. (ii) O cliente espera por user_id no teclado e consulta o servidor sobre sua existência na tabela. O cliente imprime na tabela a existência ou não do usuário.<br />
<br />
*'''Exercício 4: cópia de arquivo'''. Projete um programa de cópia de arquivos chamado FileCopy usando pipes comuns. Esse programa receberá dois parâmetros: o primeiro é o nome do arquivo a ser copiado e o segundo é o nome do arquivo copiado. Em seguida, o programa criará um pipe comum e gravará nele o conteúdo do arquivo a ser copiado. O processo filho lerá esse arquivo do pipe e o gravará no arquivo de destino. Por exemplo, se chamarmos o programa como descrito a seguir:<br />
:<syntaxhighlight lang=bash><br />
$ FileCopy entrada.txt copia.txt<br />
</syntaxhighlight><br />
:o arquivo ''entrada.txt'' será gravado no pipe. O processo filho lerá o conteúdo desse arquivo e o gravará no arquivo de destino ''copia.txt''. Escreva o programa usando os pipes da API POSIX no Linux.<br />
<br />
<br />
{{collapse bottom}}<br />
<br />
=Laboratórios Disponíveis= <br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Escalonamento Round Robin e FCFS para Threads"}}<br />
<br />
<br />
== Escalonamento Round-Robin preemptivo ==<br />
<br />
OBS: ver https://www.quora.com/What-exactly-does-typedef-do-in-C<br />
<br />
A fazer: <br />
<br />
*primitiva de término de processo (destrutor do objeto); <br />
*primitiva de yield<br />
*isolar o escalonador em uma função;<br />
*isolar o dispatcher em uma função; <br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
Modificado por Eraldo <br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 5<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
void runA(void) {<br />
for (;;) {<br />
printf("running A\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runB(void) {<br />
for (;;) {<br />
printf("running B\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 1<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
<br />
void scheduler_rr();<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void yield_thread()<br />
{<br />
scheduler_rr();<br />
}<br />
<br />
void delete_thread()<br />
{<br />
delete curr_thread;<br />
curr_thread=NULL;<br />
scheduler_rr();<br />
}<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
struct delta{<br />
long alfa;<br />
char epson[1000];<br />
long beta;<br />
} shar;<br />
<br />
int turn;<br />
int flag[2];<br />
<br />
#define TRUE 1<br />
#define FALSE 0<br />
<br />
void ent_rc(int p, int vt)<br />
{<br />
flag[p]=TRUE;<br />
turn = vt;<br />
if(p) p=0; else p=1;<br />
while (flag[p] && turn == vt);<br />
//printf("Thread %d: esperando para acessar a região crítica\n", p);<br />
}<br />
<br />
void sai_rc(int p)<br />
{<br />
flag[p]=FALSE;<br />
}<br />
<br />
void runA(void) {<br />
struct delta x = {0, 100};<br />
<br />
for (;;) {<br />
x.alfa=0;x.beta=0;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0);<br />
x.alfa=100;x.beta=100;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0); <br />
}<br />
}<br />
<br />
void runB(void) {<br />
<br />
for (;;) {<br />
ent_rc(1,0);<br />
printf("shar alfa = %ld shar beta = %ld \n",shar.alfa, shar.beta); // regiao crítica<br />
sai_rc(1);<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runC(void) {<br />
int i;<br />
for (i=0;i<10;i++) {<br />
printf("Thread C - parte 1\n");<br />
yield_thread();<br />
printf("Thread C - parte 2\n");<br />
yield_thread();<br />
}<br />
delete_thread();<br />
}<br />
<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
add_thread(runC);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Um escalonador semi-automático"}}<br />
<br />
== Ainda Threads - Um escalonador semi-automático usando sinais ==<br />
<br />
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.<br />
<br />
===Exemplo 1:===<br />
<br />
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. <br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
<br />
void sig_handler(int signo)<br />
{<br />
int x;<br />
printf("Turma de SOP: recebido SIGUSR1\n");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
// Loop eterno dormindo 1s<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Fazer no terminal:<br />
ps aux<br />
anotar o pid do processo e enviar o sinal:<br />
kill -USR1 pid<br />
<br />
===Exemplo 2:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// loop eterno que nunca é executado<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Enviar o sinal USR1 para ver o efeito. <br />
<br />
===Exemplo 3:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void prepara_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void prepara_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
prepara_contexto_ping();<br />
prepara_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// A long long wait so that we can easily issue a signal to this process<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
Exercício: Tente analisar as pilhas dos threads e verificar sob qual pilha o handler se executa.<br />
<br />
===Exercício 4:===<br />
<br />
Neste ponto associamos um timer ao handler com o apoio do sinal ALRM. Agora os threads são escalonados automaticamente.<br />
<br />
<code><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void preparar_contexto_ping(ucontext_t *pContext, char *p)<br />
{<br />
char *stack;<br />
<br />
getcontext(pContext);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
(*pContext).uc_stack.ss_sp = stack ;<br />
(*pContext).uc_stack.ss_size = STACKSIZE;<br />
(*pContext).uc_stack.ss_flags = 0;<br />
(*pContext).uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(pContext, (void*)(*f_ping), 1, p);<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping(&cPing, "ping");<br />
preparar_contexto_ping(&cPong, "pong");<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Um Exemplo de Uso "API Padrão POSIX"}}<br />
<br />
== Um Exemplo de Uso "API Padrão POSIX" ==<br />
<br />
;Referências<br />
* Referência http://man7.org/linux/man-pages/man2/mmap.2.html<br />
<br />
<br />
Crie uma função soma que receba 2 ponteiros referenciando posições na memória, criadas utilizando nmap(), de maneira que estas posições armazenem números inteiros. A função soma deverá retornar a soma dos números apontados em regiões da memória sem a utilização de nenhuma rotina da biblioteca do C, que não sejam definidas por APIs posix, para criação destas <br />
regiões na memória (malloc, alloc, calloc). Após retornar o resultado da soma os devidos ponteiros deverão ser extintos da memória.<br />
<br />
<br />
*'''Experimento 1:''' Aumente o tamanho da memória alocada até quando for possível.<br />
<br />
Qual o tamanho limite da memória que você conseguiu alocar?<br />
<br />
*'''Experimento 2:''' Mude o escopo para PROT_NONE, após executar e depurar o código explique o que aconteceu.<br />
<br />
Em sua opinião NMAP trata-se de uma syscall ou de uma API? Afinal API e syscall são a mesma coisa? Explique.<br />
<br />
<syntaxhighlight lang=cpp><br />
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);<br />
int munmap(void *addr, size_t length);<br />
<br />
addr = Valor do início do mapeamento.<br />
length = valor do tamanho da região a ser alocada.<br />
prot = especificações de proteção da região alocada (consultar http://man7.org/linux/man-pages/man2/mmap.2.html).<br />
flags = especificação do escopo e do tipo da região criada (exemplo publica ou privada, se é anônima ou não). <br />
</syntaxhighlight><br />
<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
void* meu_malloc(size_t tamanho) {<br />
void* addr = mmap(0, // addr<br />
tamanho, // len<br />
PROT_READ | PROT_WRITE, // prot<br />
MAP_ANON | MAP_PRIVATE, // flags<br />
-1, // filedes<br />
0); // off<br />
*(size_t*)addr = tamanho;<br />
return addr;<br />
}<br />
<br />
int meu_free(void* addr) {<br />
return munmap(addr - sizeof(size_t), (size_t) addr);<br />
}<br />
<br />
<br />
int soma(int *N1, int *N2){<br />
<br />
return (*N1+*N2);<br />
<br />
}<br />
<br />
<br />
int main(int argc, char* argv[]) {<br />
<br />
int* numero1 = meu_malloc(sizeof(int));<br />
int* numero2 = meu_malloc(sizeof(int)); <br />
<br />
<br />
*numero1 = 10;<br />
*numero2 = 20; <br />
<br />
int resultado = soma(numero1, numero2);<br />
<br />
printf("\n\n O resultado da soma é %d \n\n",resultado); <br />
<br />
meu_free(numero1);<br />
meu_free(numero2);<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Processos no Linux}}<br />
<br />
== Processos no Linux - Modificado por Eraldo ==<br />
<br />
<blockquote style="background: lime; border: 1px solid black; padding: 1em;"><br />
Processos no Linux<br />
</blockquote><br />
<br />
*Exercícios propostos pelo Prof.Arliones e Modificados por Eraldo<br />
<br />
<br />
[[imagem:DesenhoForkExec.png|border|650px]]<br />
<br />
<br />
;Syscall FORK<br />
<br />
* Em um terminal, execute "man fork"<br />
** 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'''.<br />
** O '''código''' dos dois processos (pai e filho) são '''idênticos''';<br />
** Os '''dados''' dos dois processos (pai e filho) são '''idênticos NO MOMENTO DA CRIAÇÃO''';<br />
** Execução do processo filho inicia na próxima instrução do programa (no retorno da chamada FORK);<br />
** Não é possível saber qual dos processos (pai ou filho) retormará a execução primeiro - isto fica a cargo do excalonador do SO;<br />
** Valores de retorno da chamada FORK:<br />
*** (-1): erro na criação do processo (ex.: memória insuficiente);<br />
*** (0): em caso de sucesso, este é o valor de retorno recebido pelo processo filho;<br />
*** (>0): em caso de sucesso, este é o valor de retorno recebido pelo processo pai;<br />
<br />
;Syscall JOIN<br />
<br />
* A syscall JOIN é implementada no POSIX pela função '''wait()'''. Execute "man wait".<br />
** Além da função '''wait()''', há também '''waitpid()''' e '''waitid()''';<br />
** 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);<br />
** A chamada wait também libera os recursos do processo filho que termina;<br />
** '''wait()''': esta função suspende a execução do processo chamador até que UM DOS SEUS FILHOS finalize;<br />
** '''waitpid()''': suspende a execução do processo chamador até que UM FILHO ESPECÍFICO finalize;<br />
<br />
;Syscall EXEC<br />
<br />
* A syscall EXEC é implementada no POSIX pela família de funções '''exec()'''. Execute "man exec".<br />
** As principais funções da família são '''execl()''', '''execlp()''' e '''execvp()''';<br />
** 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;<br />
** 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;<br />
<br />
<br />
;Exemplos POSIX utilizando fork/wait/exec<br />
<br />
*Exemplo 1: fork/wait básico<br />
<syntaxhighlight lang=c><br />
// ex1: fork/wait básico<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
printf("processo filho\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
printf("processo pai\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
arliones@socrates:~/tmp$ gcc ex1.c -o ex1 <br />
arliones@socrates:~/tmp$ ./ex1 <br />
processo filho pid: 27858 pid pai: 27857<br />
processo pai pid: 27857 pid pai: 5337<br />
arliones@socrates:~/tmp$ <br />
</syntaxhighlight><br />
<br />
* Exemplo 2: processos pai e filho compartilham código, mas não dados.<br />
<syntaxhighlight lang=c><br />
// ex2: fork/wait "compartilhando" dados<br />
// ex2: fork/wait "compartilhando" dados<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status, k=0;<br />
printf("processo %d\t antes do fork\n", getpid());<br />
pid = fork();<br />
printf("processo %d\t depois do fork\n", getpid());<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
k += 1000;<br />
printf("processo filho\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status); // espera o filho terminar<br />
k += 10;<br />
printf("processo pai\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
k += 1000;<br />
printf("FIM processo %d\t K: %d\n", getpid(), k); <br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
processo 17056 antes do fork<br />
processo 17056 depois do fork<br />
processo 17057 depois do fork<br />
processo filho pid: 17057 K: 1000 endereço K: 0x7ffd8923e318<br />
processo pai pid: 17056 K: 10 endereço K: 0x7ffd8923e318<br />
</syntaxhighlight><br />
<br />
* Modificação no código: comentar linhas 23 e 30<br />
<br />
<syntaxhighlight lang=bash><br />
<br />
</syntaxhighlight><br />
<br />
* Analise os resultados e busque entender a diferença.<br />
*Perguntas e desafios.:<br />
#Analisando os valores impressos de k pode-se dizer que os dados são compartilhados entre os dois processos?<br />
#O endereço de k impresso é o mesmo nos dois processos. ISto não contradiz a afirmação anterior?<br />
#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.<br />
<br />
<br />
;Exercício fork/wait<br />
<br />
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.<br />
<br />
*Use o comando pstree para verificar a árvore de processos criada.<br />
<br />
{{collapse top|Solução}}<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
<!--<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
--><br />
<br />
;DESAFIO: fork/wait<br />
<br />
Reimplementar o exercício anterior de criação de uma árvore de 3 processos, generalizando a criação de N processos onde N é repassado na linha de comando do programa. SUGESTÃO: usar um comando for, mas lembrar que se existe um fork dentro do for, então cada filho gerado dará continuidade a execução do for. É necessário que o processo faça um exit ou retorne neste momento.<br />
<br />
;DESAFIO: Exercício status/wait<br />
<br />
O ''status'' passado como parâmetro à função ''wait(&status)'' é, na verdade, o mecanismo de retorno de resultado do ''wait/waitpid''. Ao retornar, esta variável contém informações sobre o resultado da execução do processo filho. Por exemplo, se um processo terminou normalmente (i.e., chamou ''exit''), o comando ''WIFEXITED(status)'' retorna ''true''. Este comando retorna ''false'' se o processo foi abortado (e.g., ''segmentation fault'') ou morto (e.g., ''kill''). Investigue no manual do wait no Linux (''man wait'') o funcionamento do comando WEXITSTATUS(status). <br />
Imagine um problema de busca de dados armazenados na forma de uma matriz de inteiros 4x30. Você está interessado em saber quantas ocorrências de um determinado número existe em cada linha da matriz. Note que que são tarefas que podem ser paralelizadas e usufruir de um sistema capaz de executá-las em paralelo. Faça uma implementação paralelizando 4 processos filhos a partir de um pai, onde cada processo é responsável por uma busca. A quantidade de ocorrências do número buscado é retornada e capturada através de WEXITSTATUS.<br />
<br />
;Syscall EXEC<br />
<br />
*Exemplo exec()<br />
<br />
<syntaxhighlight lang=c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
execl("/bin/ls","ls","-l", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 1: Modificar o código para mostrar que o exec() não retorna (colocar um printf após o exec).<br />
<br />
*Exercício 2: Criar um exemplo (dois programas ) para demonstrar que o exec não cria novo processo. <br />
**Crie um primeiro programa (prog1) que imprime o seu pid e depois faz um exec do segundo programa.<br />
**Crie o segundo programa que simplesmente imprime o pid.<br />
<br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU ANTES DO EXEC: Meu pid é %d\n", getpid());<br />
execl("./prog2","prog2", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU DEPOIS DO EXEC:Meu pid é %d\n", getpid());<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 3: Criar um exemplo usando fork/exec mostrando que um processo pai cria um filho e espera por sua execução. O filho executa o comando "ps aux". Ambos devem mostrar seus pids.<br />
<br />
{{collapse bottom}} <br />
{{collapse top| bg=lightyellow | expandir=true | Threads de aplicação}}<br />
<br />
== Threads de aplicação ==<br />
<br />
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:<br />
*'''getcontext(&a)''': salva o contexto na variável '''a''';<br />
*'''setcontext(&a)''': restaura um contexto salvo anteriormente na variável '''a''';<br />
*'''swapcontext(&a,&b)''': salva o contexto atual na variável '''a''' e restaura o contexto salvo anteriormente na variável '''b''';<br />
*'''makecontext(&a, ...)''': ajusta parâmetros internos do contexto salvo em '''a''';<br />
*'''ucontext_t''': as variáveis '''a''' e '''b''' são do tipo '''ucontext_t'''. Este tipo armazena um contexto.<br />
<br />
Busque mais informações sobre estas funções utilizando o programa manpage do Linux (ex.: man getcontext).<br />
<br />
Estude o código no arquivo pingpong.c abaixo e explique seu funcionamento.<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
*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.<br />
*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.<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain, cFnew;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_new(void * arg1, void * arg2,void * arg3,void * arg4) <br />
{<br />
printf ("%s: Primeira string %s %s %s\n",(char*) arg1,(char*) arg2,(char*) arg3, (char*) arg4);<br />
swapcontext(&cFnew, &cMain); <br />
}<br />
<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
<br />
getcontext(&cFnew);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cFnew.uc_stack.ss_sp = stack ;<br />
cFnew.uc_stack.ss_size = STACKSIZE;<br />
cFnew.uc_stack.ss_flags = 0;<br />
cFnew.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cFnew, (void*)(*f_new), 4, "\tF_new", "\tAlo", "\tMundo","\tReal");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
swapcontext(&cMain, &cFnew);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
--><br />
Exercício 3: O que acontece se um dos threads é colocado para dormir? Todos os demais threads param a sua execução.<br />
<br />
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/<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Trocas de mensagens com pipes}}<br />
<br />
== Trocas de mensagens com pipes ==<br />
<br />
;Troca de mensagens<br />
Um mecanismo disponibilizado por sistemas UNIX para troca de mensagens entre processos é o PIPE. Pipes são mecanismos de comunicação indireta onde mensagens são trocadas através de ''mailboxes''. Cada ''mailbox'' possui um identificador único, permitindo que processos identifiquem o canal de comunicação entre eles. O fluxo de mensagens em um Pipe é:<br />
*'''unidirecional''': sobre um mesmo pipe, apenas um processo envia mensagens e um processo recebe mensagens;<br />
*'''FIFO''': as mensagens são entregues na ordem de envio;<br />
*'''não-estruturado''': não há estrutura pré-definida para o formato da mensagem.<br />
No UNIX, pipes são inicializados através da '''SystemCall''' ''pipe'', que possui a seguinte sintaxe:<br />
*''int pipe(int pipefd[2])'': ''pipe'' inicializa um novo pipe no sistema e retorna, no array pipefd, os descritores identificando cada uma das pontas do pipe. A primeira posição do array, i.e. pipefd[0], recebe o descritor que pode ser aberto apenas para leitura, enquanto a segunda posição do array, i.e. pipefd[1], recebe o descritor que pode ser aberto apenas para escrita. A função retorna zero no caso de sucesso, ou -1 se ocorrer erro.<br />
As primitivas send/receive para uso de um pipe no UNIX são implementadas por '''SystemCalls''' read/write, conforme segue:<br />
*''ssize_t read(int fd, void *buf, size_t count)'': “puxa” dados do pipe identificado pelo descritor fd. Os dados recebidos são os apontados pelo ponteiro buf, sendo count a quantidade máxima de bytes a serem recebidos. A função retorna o número de bytes recebidos.<br />
*''ssize_t write(int fd, const void *buf, size_t count)'': “empurra” dados no pipe identificado pelo descritor fd. Os dados transmitidos são os apontados pelo ponteiro buf, sendo count a quantidade de bytes a serem transmitidos. A função retorna o número de bytes transmitidos.<br />
<br />
*Exemplo 1: Transmitindo e recebendo pelo próprio processo<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main()<br />
{<br />
int fd[2];<br />
char *ptr = "Alo eu mesmo";<br />
char *ptr_alvo;<br />
int tamanho_dados, ret;<br />
<br />
tamanho_dados = strlen(ptr)+1;<br />
<br />
if (pipe(fd)==-1){<br />
printf ("erro criação pipe\n");<br />
exit(-1);<br />
}<br />
printf("Transmitido %d bytes\n", tamanho_dados);<br />
write (fd[1], ptr, tamanho_dados);<br />
<br />
ptr_alvo = malloc(tamanho_dados);<br />
<br />
ret=read(fd[0],ptr_alvo,tamanho_dados);<br />
<br />
printf("ret = %d dados => %s\n", ret, ptr_alvo); <br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
*Exemplo 2: Abaixo há um exemplo de programa criando um pipe e compartilhando os descritores entre dois processos (criados via ''fork()'').<br />
<syntaxhighlight lang=c><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
<br />
char *message = "This is a message!!!" ;<br />
<br />
main()<br />
{<br />
char buf[1024] ;<br />
int fd[2];<br />
pipe(fd); /*create pipe*/<br />
if (fork() != 0) { /* I am the parent */<br />
write(fd[1], message, strlen (message) + 1) ;<br />
}<br />
else { /*Child code */<br />
read(fd[0], buf, 1024) ;<br />
printf("Got this from MaMa!!: %s\n", buf) ;<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
*'''Exercício 1: construa um “pipeline”'''. Crie um programa que conecta 4 processos através de 3 pipes. Utilize ''fork()'' para criar vários processos.<br />
<br />
<syntaxhighlight lang=cpp><br />
<br />
//Solução possível<br />
<br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
pipe(fd);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
<br />
</syntaxhighlight><br />
<br />
*'''Exercício 3: Modifique o exercício anterior para que o processo D, através de um novo pipe, mande uma mensagem diretamente para o pai de todos.<br />
<br />
<!--<br />
<code><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
int fd_retorno[2];<br />
<br />
pipe(fd);<br />
pipe(fd_retorno);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size);<br />
read(fd_retorno[0], buf, size);<br />
printf("PAI:%s\n", buf); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
char *ptr_msg_ret="Ok msg de D para o pai";<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
write(fd_retorno[1],ptr_msg_ret,strlen(ptr_msg_ret)+1);<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
*'''Exercício 3: Consultor de Login de Acesso:'''. Estude o link https://www.geeksforgeeks.org/named-pipe-fifo-example-c-program/ e projete um programa cliente servidor da seguinte forma: (i) O servidor possui uma tabela de usuários (userid). O user_id é de tamanho fixo de 7 caracteres. O servidor espera por consultas para verificar se um usuário está na tabela. Se estiver responde com o caracter 'S' senão com 'N'. (ii) O cliente espera por user_id no teclado e consulta o servidor sobre sua existência na tabela. O cliente imprime na tabela a existência ou não do usuário.<br />
<br />
*'''Exercício 4: cópia de arquivo'''. Projete um programa de cópia de arquivos chamado FileCopy usando pipes comuns. Esse programa receberá dois parâmetros: o primeiro é o nome do arquivo a ser copiado e o segundo é o nome do arquivo copiado. Em seguida, o programa criará um pipe comum e gravará nele o conteúdo do arquivo a ser copiado. O processo filho lerá esse arquivo do pipe e o gravará no arquivo de destino. Por exemplo, se chamarmos o programa como descrito a seguir:<br />
:<syntaxhighlight lang=bash><br />
$ FileCopy entrada.txt copia.txt<br />
</syntaxhighlight><br />
:o arquivo ''entrada.txt'' será gravado no pipe. O processo filho lerá o conteúdo desse arquivo e o gravará no arquivo de destino ''copia.txt''. Escreva o programa usando os pipes da API POSIX no Linux.<br />
<br />
<br />
{{collapse bottom}}<br />
<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Exercícios sobre Memória Compartilhada}}<br />
<br />
==SHARED MEMORY: Produtor (pai) - Consumidor (filho) - ==<br />
<br />
<!-- Parou aki 20/08<br />
<br />
<br />
*'''Experimento 2:''' Complete o código a seguir para que os processos pai e filho possam compartilhar um segmento de memória. O filho escreve no segmento e o pai imprime na tela o conteúdo da mensagem.<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
char *ptr_msg = "alo pai, tudo bem?"; <br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
//completar aqui<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
<!--<br />
<code><br />
<br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/types.h><br />
#include <string.h><br />
#include <stdlib.h><br />
<br />
int main(void)<br />
{<br />
int fd[2], pipe_ret, filho;<br />
char string[] = "Hello, pipe!\n";<br />
char buffer[20];<br />
<br />
pipe(fd);<br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
/*Mandar string para a extremidade do pipe*/<br />
write(fd[1], string, (strlen(string)+1));<br />
exit(0);<br />
}<br />
else<br />
{<br />
<br />
/* Read in a string from the pipe */<br />
pipe_ret = read(fd[0], buffer, (20*sizeof(char)));<br />
printf("Recebi este texto %s", buffer);<br />
}<br />
<br />
return(0);<br />
}<br />
<br />
<br />
<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
key = ftok("teste_sh.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644 | IPC_CREAT));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
<br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
strncpy(segmento, "mensagem compartilhada", SHM_SIZE); <br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
--><br />
<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Memória Compartilhada}}<br />
*'''Experimento Shared Memory:''' Complete o código a seguir para que os processos pai e filho possam compartilhar um segmento de memória. O filho escreve no segmento e o pai imprime na tela o conteúdo da mensagem.<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
char *ptr_msg = "alo pai, tudo bem?"; <br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
//completar aqui strcpy(segmento, ptr_msg); //aqui deveria testar a cpacidade da área...<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exemplo com ftok:<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
key = ftok("./teste.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644 | IPC_CREAT));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
<br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
strncpy(segmento, "mensagem compartilhada", SHM_SIZE); <br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exemplo com ftok entre processos sem parentesco:<br />
<br />
Criar um arquivo teste.txt e em um terminal executar:<br />
<br />
<syntaxhighlight lang=c><br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
int modo,filho;<br />
<br />
struct minha_struct {<br />
char flag;<br />
int numero;<br />
} *ptr;<br />
<br />
<br />
key = ftok("./teste.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644 | IPC_CREAT));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
ptr = (struct minha_struct *) shmat(shmid, (void *)0, 0);<br />
if ((char *)ptr == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
ptr->flag =0;<br />
ptr->numero = 0;<br />
while (ptr->flag==0) { <br />
printf("%d\n", ptr->numero);<br />
sleep(1);<br />
} <br />
<br />
if (shmdt(ptr) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Em outro terminal executar:<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
struct minha_struct {<br />
char flag;<br />
int numero;<br />
} *ptr;<br />
<br />
<br />
key = ftok("./teste.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
ptr = (struct minha_struct *) shmat(shmid, (void *)0, 0);<br />
if ((char *)ptr == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
<br />
<br />
while (ptr->numero++<10)<br />
sleep(1);<br />
<br />
ptr->flag = 1;<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Exercício Desafio: Implementar o problema do buffer circular usando memória compartilhada.<br />
<br />
{{collapse bottom}}<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Exercício (Algoritmo de Peterson)}}<br />
<br />
== Exercício (Algoritmo de Peterson) ==<br />
<br />
<br />
'''Exercício 1''': Sincronize o código a seguir, de maneira que o processo pai imprima apenas os números impares e o processo filho os números pares. Para isso utilize o algoritmo de '''Peterson''' visto em aula. '''Utilize memória compartilhada''' para comunicação entre os processos.<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
main()<br />
{ <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int i; <br />
<br />
for(i = 0;i < 10;i=i+2){ <br />
printf("Processo pai %d \n", i); <br />
<br />
} <br />
<br />
<br />
}<br />
<br />
else { /*Child code */<br />
int i; <br />
for(i = 1;i < 10;i=i+2){ <br />
printf("Processo filho %d \n", i); <br />
<br />
}<br />
<br />
<br />
}<br />
<br />
exit(0);<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
'''Exercício 2''': Considerando o exercício anterior faça a mesma sincronização, no entanto desta vez utilize a modelagem em software do TSL. <br />
* Em sua experiência, depois de testar diversas vezes as execuções de suas soluções baseadas no algoritmo de '''Peterson''' e '''Tsl''', qual sua opinião sobre as abordagens?<br />
Explique seu raciocínio. <br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Exercício (Semáforos)}}<br />
== Exercício (Semáforos) ==<br />
<br />
<br />
'''Exercício 1''': Sincronize o código a seguir, de maneira que o processo pai imprima apenas os números impares e o processo filho os números pares. Para isso utilize '''Semáforos''' de acordo com a implementação em '''semaforo.h'''. '''Utilize memória compartilhada''' para comunicação entre os processos.<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
main()<br />
{ <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int i; <br />
<br />
for(i = 0;i < 10;i=i+2){ <br />
printf("Processo pai %d \n", i); <br />
sleep(1);<br />
<br />
} <br />
<br />
<br />
}<br />
<br />
else { /*Child code */<br />
int i; <br />
for(i = 1;i < 10;i=i+2){ <br />
printf("Processo filho %d \n", i); <br />
<br />
}<br />
<br />
<br />
}<br />
<br />
exit(0);<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
SEMAFORO.H<br />
<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <sys/sem.h><br />
<br />
<br />
int criar_semaforo(int val, int chave) <br />
{<br />
int semid ;<br />
<br />
union semun {<br />
int val;<br />
struct semid_ds *buf ;<br />
ushort array[1];<br />
} arg_ctl ;<br />
<br />
key_t ft = ftok("/tmp", chave);<br />
<br />
semid = semget(ft,1,IPC_CREAT|IPC_EXCL|0666);<br />
if (semid == -1) {<br />
semid = semget(ft,1,0666); <br />
if (semid == -1) {<br />
perror("Erro semget()");<br />
exit(1) ;<br />
}<br />
}<br />
<br />
arg_ctl.val = val; //valor de início<br />
if (semctl(semid,0,SETVAL,arg_ctl) == -1) {<br />
perror("Erro inicializacao semaforo");<br />
exit(1);<br />
}<br />
return(semid) ;<br />
}<br />
<br />
void P(int semid){<br />
<br />
struct sembuf *sops = malloc(10*sizeof(int));<br />
sops->sem_num = 0;<br />
sops->sem_op = -1;<br />
sops->sem_flg = 0;<br />
semop(semid, sops, 1); <br />
free(sops);<br />
<br />
}<br />
<br />
<br />
void V(int semid){<br />
<br />
struct sembuf *sops = malloc(10*sizeof(int));<br />
sops->sem_num = 0;<br />
sops->sem_op = 1;<br />
sops->sem_flg = 0; <br />
semop(semid, sops, 1); <br />
free(sops);<br />
<br />
} <br />
<br />
<br />
<br />
void sem_delete(int semid) <br />
{<br />
<br />
if (semctl(semid,0,IPC_RMID,0) == -1)<br />
perror("Erro na destruicao do semaforo");<br />
}<br />
<br />
<br />
<br />
<br />
</syntaxhighlight><br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Programação concorrente}}<br />
<br />
== Programação concorrente ==<br />
<br />
;POSIX Threads<br />
A 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):<br />
*''pthread_create'': cria uma thread;<br />
*''pthread_kill'': força a terminação de uma thread;<br />
*''pthread_join'': sincroniza o final de uma thread (qual a diferença/semelhança com o ''wait'' que usamos para processos?);<br />
*''pthread_exit'': finaliza uma thread.<br />
Para utilizar estas funções é necessário linkar o programa à libpthread (''-lpthread''). <br />
<br />
<br />
;POSIX pthread mutex<br />
<br />
A biblioteca pthread implementa um tipo ''pthread_mutex_t'', que garante a exclusão mútua entre threads. Estes mutex são manipulados através das funções (acesse as man-pages das chamadas para maiores detalhes):<br />
*''pthread_mutex_lock'': acessa um mutex.<br />
*''pthread_mutex_trylock'': tenta acessar um mutex (retorna valor indicando sucesso ou falha no lock).<br />
*''pthread_mutex_unlock'': libera um mutex.<br />
<br />
<br />
<br />
<br />
;POSIX Semaphores<br />
<br />
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):<br />
*''sem_init'': inicializa um semáforo;<br />
*''sem_destroy'': destroy um semáforo;<br />
*''sem_wait'': implementa a operação ''p'';<br />
*''sem_post'': implementa a operação ''v''.<br />
Para utilizar estas funções é necessário linkar o programa à librt ou à libpthread (''-lrt'' ou ''-lpthread'').<br />
<br />
;Exercício 1<br />
<br />
O programa abaixo cria 5 threads, e cada uma destas threads atualiza uma variável global (memória compartilhada).<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include <pthread.h><br />
#include <signal.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
pthread_mutex_t mut;<br />
<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
}<br />
</syntaxhighlight><br />
<br />
# Compile este programa. <br />
# Execute este programa várias vezes. Ele funciona? Será que ele gera as saídas esperadas?<br />
# Identifique as '''seções críticas''' do programa.<br />
# Corrija o programa utilizando '''mutex'''. <br />
# Analise a função ''AtualizaSaldo()'' com a sua solução. Lembre-se que o uso do mutex implica em apenas uma thread acessar a seção crítica por vez, enquanto outras threads ficam bloqueadas, esperando. Disso vem que, quanto menor o trecho de código entre um ''lock'' e um ''unlock'', menos tempo uma thread necessita ficar esperando.<br />
# Modifique o programa para usar um semáforo binário ao invés de um mutex em sua solução.<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <cstring><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
<br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
sem_t sem;<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
int value;<br />
sem_wait(&sem);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
sem_getvalue(&sem, &value);<br />
printf("valor sem = %d\n", value);<br />
sem_post(&sem);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
sem_init(&sem,0,1);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
sem_destroy(&sem);<br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
<br />
;Exercício 2<br />
Refaça o exercício 3 usando processos criados com fork e exec. O semáforo deve ser criado em uma região de memória compartilhada.<br />
<br />
;Exercício 3<br />
Implemente com pthreads e semáforos/mutex a solução do produtor/comsumidor.<br />
<br />
;Exercício 4<br />
<br />
O programa abaixo manipula uma matriz de tamanho MxN (veja os defines para o tamanho da matriz). A função ''SumValues'' soma todos os valores em uma linha da matriz. A linha a ser somada é identificada pela variável ''i''. Modifique o programa principal (''main'') nos locais indicados para:<br />
# Criar N threads, uma para somar os valores de cada linha.<br />
# Receber o resultado do somatório de cada linha e gerar o somatório total da matriz.<br />
# Analise o programa: há problemas de sincronização que precisam ser resolvidos? Se sim, resolva-os.<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include "thread.h"<br />
<br />
/* number of matrix columns and rows */<br />
#define M 5<br />
#define N 10<br />
<br />
using namespace std;<br />
<br />
int matrix[N][M];<br />
Thread *threads[N];<br />
<br />
<br />
/* thread function; it sums the values of the matrix in the row */<br />
int SumValues(int i)<br />
{<br />
int n = i; /* number of row */<br />
int total = 0; /* the total of the values in the row */<br />
int j;<br />
for (j = 0; j < M; j++) /* sum values in the "n" row */<br />
total += matrix[n][j];<br />
cout << "The total in row" << n << " is " << total << "." << endl;<br />
/* terminate a thread and return a total in the row */<br />
exit(total);<br />
}<br />
<br />
int main(int argc, char *argv[])<br />
{<br />
int i, j;<br />
int total = 0; /* the total of the values in the matrix */<br />
<br />
/* initialize the matrix */<br />
for (i = 0; i < N; i++)<br />
for (j = 0; j < M; j++)<br />
matrix[i][j] = i * M + j;<br />
<br />
/* create threads */<br />
/* COLOQUE SEU CÓDIGO PARA CRIAR AS THREADS AQUI! */<br />
<br />
/* wait for terminate a threads */<br />
/* COLOQUE SEU CÓDIGO PARA PEGAR O SOMATÓRIO DE LINHAS E TOTALIZAR A SOMA DA MATRIZ AQUI! */<br />
<br />
cout << "The total values in the matrix is " << total << endl;<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Lista de exercícios "Revisão para Prova" }}<br />
<br />
== Lista de exercícios/Revisão para Prova ==<br />
<br />
A lista de exercícios referente a primeira prova (Parte introdutória + Processos) segue neste LINK [http://docente.ifsc.edu.br/andre.damato/sop2018/lista_rev1.pdf | Lista de exercícios]. <br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Primeiro trabalho}}<br />
== JOGO DA VIDA DE CONWAY e JANTAR DOS FILÓSOFOS==<br />
<br />
;Referências<br />
<br />
* [https://www.open-mpi.org/doc/current/ MPI]<br />
<br />
* [https://quark.phy.bnl.gov/~creutz/qcdoc/mpi/mpi.h Tipos de dados MPI]<br />
<br />
* [https://pt.wikipedia.org/wiki/Jogo_da_vida Jogo da Vida]<br />
<br />
<br />
<br />
<br />
A partir da implementação sequencial do Game of Life apresentada a seguir, estude o código e transforme esta implementação em uma implementação paralela utilizando o protocolo de passagem de mensagens MPI.<br />
Perceba que a impĺementação mencionada utiliza como parâmetros de entrada um aquivo contendo o estado inicial do jogo, e o número de gerações que o usuário deseja rodar. A evolução do estado inicial <br />
é impressa na tela passo a passo. Sendo assim, a partir disso:<br />
<br />
*'''1: Elabore uma implementação com 2 processos para o jogo da vida utilizando o protocolo MPI, de maneira que um processo execute uma geração i qualquer e o outro execute a geração seguinte i+1''' <br />
<br />
*'''2: (0,7) Os processos deverão se comunicar utilizando as funções do protocolo MPI.''' <br />
<br />
*'''3: (0,3) Relatório simplificado explicando a sua solução. Utilize diagramas para representar a comunicação entre os processos, explicando como a matriz do jogo é transferida entre os processos. ''' <br />
<br />
*'''4: Entregue o Relatório e o código fonte do trabalho em um pacote compactado via e-mail (PRAZO 19/10). <br />
<br />
<br />
<br />
* ''' Compilar o código com MPI '''<br />
<code><br />
mpicc -o nomeApp arquivo.c<br />
</syntaxhighlight><br />
<br />
* ''' Rodar rodar programa utilizando MPI '''<br />
<code><br />
mpirun -np numeroDeProcessos ./nomeApp entrada.txt gerações<br />
</syntaxhighlight><br />
<br />
* (int) -np: Quantidade de processos que você deseja executar <br />
<br />
* entrada.txt: Arquivo de entrada com estado inicial do jogo <br />
<br />
* (int) gerações: número de gerações que você deseja rodar<br />
<br />
* [http://docente.ifsc.edu.br/andre.damato/sop2018/entrada.txt Arquivo de entrada para Testes]<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
<br />
<br />
<br />
/*<br />
<br />
Conway's Game of Life<br />
<br />
Compilar código com MPI<br />
mpicc -o nomeApp arquivo.c<br />
<br />
<br />
Rodar rodar programa utilizando MPI<br />
<br />
mpirun -np numeroDeProcessos ./nomeApp entrada.txt gerações<br />
<br />
(int) -np: Quantidade de processos que você deseja executar <br />
entrada.txt: Arquivo de entrada com estado inicial do jogo <br />
(int) gerações: número de gerações que você deseja rodar<br />
<br />
<br />
*/<br />
<br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h><br />
#include "mpi.h"<br />
<br />
<br />
//Numero de linhas e colunas<br />
#define nLinhas 32<br />
#define nColunas 82 <br />
<br />
char *matriz[nLinhas];<br />
char *entrada[nLinhas];<br />
<br />
<br />
void iniciar() {<br />
<br />
int i;<br />
<br />
//Alocar espaço em memória para as matrizes<br />
for (i = 0; i < nLinhas; i++ ) <br />
matriz[i] = (char *) malloc((nColunas) * sizeof( char )); <br />
<br />
<br />
}<br />
<br />
int adjacente(char **matriz, int i, int j){<br />
<br />
int x,y, initX, initY, limitX, limitY;<br />
int vizinhos = 0;<br />
<br />
if(i == 0)<br />
initX = 0;<br />
else <br />
initX = -1;<br />
<br />
if(i == (nLinhas-1)) <br />
limitX = 1;<br />
else<br />
limitX = 2;<br />
<br />
<br />
if(y == 0)<br />
initY = 0;<br />
else <br />
initY = -1;<br />
<br />
if(y == (nColunas-3)) <br />
limitY = 1;<br />
else<br />
limitY = 2;<br />
<br />
for(x = initX ; x < limitX; x++){<br />
for(y = initY; y < limitY; y++){<br />
if(matriz[i+x][j+y] == '#') <br />
vizinhos++; <br />
} <br />
}<br />
<br />
<br />
if(matriz[i][j] == '#') <br />
return (vizinhos-1);<br />
else <br />
return vizinhos;<br />
<br />
}<br />
<br />
<br />
void calculoGeracao(char **matriz, int ger) {<br />
<br />
int i, j, a;<br />
char novaGeracao[nLinhas][nColunas];<br />
<br />
/* Aplicando as regras do jogo da vida */<br />
for (i=0; i < nLinhas; i++){ <br />
for (j=0; j < nColunas; j++) {<br />
<br />
a = adjacente(matriz, i, j);<br />
<br />
if (a == 2) novaGeracao[i][j] = matriz[i][j];<br />
if (a == 3) novaGeracao[i][j] = '#';<br />
if (a < 2) novaGeracao[i][j] = ' ';<br />
if (a > 3) novaGeracao[i][j] = ' ';<br />
<br />
if (j == 0)<br />
novaGeracao[i][j] = '"';<br />
} <br />
<br />
novaGeracao[i][79] = '"';<br />
novaGeracao[i][80] = '\n';<br />
<br />
<br />
}<br />
<br />
/* Passando o resultado da nova geração para a matriz de entrada */<br />
for (i=0; i < nLinhas; i++){ <br />
for (j=0; j < nColunas; j++) <br />
matriz[i][j] = novaGeracao[i][j];<br />
}<br />
}<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
main(int argc, char *argv[2]){<br />
<br />
/* Para uso com MPI<br />
<br />
<br />
//Variáveis para uso com MPI<br />
int numeroDeProcessos = 0;<br />
int rank = 0;<br />
MPI_Status status; <br />
<br />
//Iniciar MPI---<br />
MPI_Init( &argc, &argv );<br />
<br />
//Atribui a variável numeroDeProcessos o número de processos passado como parâmetro em -np <br />
MPI_Comm_size( MPI_COMM_WORLD, &numeroDeProcessos );<br />
<br />
//Pega o valor do rank (processo)<br />
MPI_Comm_rank( MPI_COMM_WORLD, &rank );<br />
*/<br />
<br />
<br />
FILE *matrizEntrada;<br />
matrizEntrada = fopen(argv[1], "r");<br />
iniciar();<br />
<br />
<br />
if (matrizEntrada == NULL)<br />
printf ("Não posso abrir o arquivo \"%s\"\n", argv[1]);<br />
<br />
<br />
char str[nColunas];<br />
int linha = 0;<br />
<br />
<br />
<br />
//Lendo o estado inicial do jogo a partir do arquivo<br />
while((fgets(str, nColunas, matrizEntrada) != NULL)&&(linha < nLinhas)){<br />
strcat(matriz[linha], str);<br />
linha++;<br />
}<br />
<br />
int i,gens; <br />
<br />
<br />
for(gens = 0; gens < atoi(argv[2]); gens++){ //Gens é o número de gerações especificado no segundo parâmetro <br />
<br />
calculoGeracao(matriz, gens);<br />
printf("%c[2J",27); // Esta linha serve para limpar a tela antes de imprimir o resultado de uma geração <br />
<br />
//Lendo o estado do jogo e imprime na tela <br />
for(i = 0; i < nLinhas; i++)<br />
printf("%s", matriz[i]); <br />
<br />
sleep(1);<br />
<br />
}<br />
<br />
<br />
for(i = 0; i < nLinhas; i++) <br />
free(matriz[i]); <br />
<br />
<br />
<br />
/* Finaliza o MPI */ <br />
//MPI_Finalize();<br />
<br />
exit(0);<br />
} <br />
<br />
<br />
</syntaxhighlight><br />
<br />
<br />
;Jantar dos Filósofos<br />
O problema clássico Jantar dos Filósofos consiste em que n fluxos (n filósofos) disputam n recursos (n talheres). No problema, para conseguir "jantar" (ou executar), cada filósofo precisa pegar dois talheres adjascentes a ele. Cada recurso é compartilhado por dois filósofos.<br />
*[http://www.doc.ic.ac.uk/~jnm/concurrency/classes/Diners/Diners.html Veja esta simulação]<br />
*[http://en.wikipedia.org/wiki/Dining_philosophers_problem Veja esta descrição do problema]<br />
<br />
<br />
* ''' (0,7) programa abaixo implementa um Jantar dos Filósofos utilizando semáforos para sincronização. Contudo, as chamadas para as operações ''v'' e ''p'' foram removidas, conforme comentários no código. Re-insira as operações no código e analise a solução. Esta modificação é suficiente para garantir que não haverá deadlock? Se sim, mostre o porque. Se não, proponha uma solução completa. '''<br />
<br />
<br />
*''' (0,3) Relatório simplificado explicando a sua solução. ''' <br />
<br />
*''' Entregue o Relatório e o código fonte do trabalho em um pacote compactado via e-mail (PRAZO 19/10). <br />
<br />
<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include "thread.h"<br />
#include "semaphore.h"<br />
<br />
using namespace std;<br />
<br />
const int DELAY = 10000000;<br />
const int ITERATIONS = 5;<br />
<br />
Semaphore chopstick[5];<br />
<br />
int philosopher(int n)<br />
{<br />
cout << "Philosopher " << n << " was born!\n";<br />
<br />
int first = (n < 4)? n : 0; // left for phil 0 .. 3, right for phil 4<br />
int second = (n < 4)? n + 1 : 4; // right for phil 0 .. 3, left for phil 4<br />
<br />
// Foram removidos do laço abaixo:<br />
// - uma chamada para chopstick[first].p()<br />
// - uma chamada para chopstick[second].p()<br />
// - uma chamada para chopstick[first].v()<br />
// - uma chamada para chopstick[second].v()<br />
for(int i = 0; i < ITERATIONS; i++) {<br />
cout << "Philosopher " << n << " thinking ...\n";<br />
for(int i = 0; i < DELAY * 10; i++);<br />
<br />
cout << "Philosopher " << n << " eating ...\n";<br />
for(int i = 0; i < DELAY; i++);<br />
}<br />
<br />
return n;<br />
}<br />
<br />
int main()<br />
{<br />
cout << "The Dining-Philosophers Problem\n";<br />
<br />
Thread * phil[5];<br />
for(int i = 0; i < 5; i++)<br />
phil[i] = new Thread(&philosopher, i);<br />
<br />
int status;<br />
for(int i = 0; i < 5; i++) {<br />
phil[i]->join(&status);<br />
if(status == i)<br />
cout << "Philosopher " << i << " went to heaven!\n";<br />
else<br />
cout << "Philosopher " << i << " went to hell!\n";<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Softwares básicos, caso Hello Word! (Trabalho 2) Entrega dia 09/11}}<br />
<br />
== Softwares básicos, caso Hello Word! ==<br />
<br />
O objetivo do experimento de hoje é pesquisar e entender os processos de atribuição de endereços de programas realizados em tempo de compilação pelos softwares básicos como: compilador, linker, e assembler. Sendo assim, neste experimento vamos utilizar os seguintes softwares para criação e análise de código:<br />
<br />
*'''GCC''': compilador para gerar código objeto a partir de um código de programa escrito na linguagem c;<br />
*'''GNU Linker (LD)''': Para vincular os códigos (módulos) objetos do programa;<br />
*[https://linux.die.net/man/1/ld| Linker ] <br />
*'''GNU Assembler''': Para gerar o código executável a partir do código objeto;<br />
*[https://linux.die.net/man/1/as | assembler]<br />
* '''OBJDUMP''': Para mostrar informações do código;<br />
*[https://linux.die.net/man/1/objdump | Objdump ]<br />
<br />
<br />
A seguir segue descrito o programa a ser utilizado no exercício 1:<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
int main()<br />
{<br />
printf("Hello, World!");<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
Trata-se do programa hello word, este programa apenas exibe uma mensagem na tela. No entanto, vamos analisar como são as etapas confecção do executável a partir deste código ''simples''. <br />
<br />
Exercício 1: <br />
* Compile o programa hello word, e o transforme em código objeto utilizando o programa GCC. Para esta tarefa execute o seguinte comando:<br />
<code><br />
gcc -o hello hello.c <br />
</syntaxhighlight><br />
* Agora abra o código objeto utilizando o programa OBJDUMP.<br />
<code><br />
objdump -D hello<br />
</syntaxhighlight><br />
* Identifique quais são as seções de código obtidas a partir do '''hello.c'''.<br />
* Pesquise e entenda o significado das seções de código: .bss, .txt, .data, .init.<br />
* Faça uma análise e identifique o endereço de memória que o programa ''hello world'' vai ser carregado. <br />
* Este código objeto é relocável? Justifique sua resposta.<br />
* Agora gere o código assembly do hello world.<br />
<code><br />
gcc -S hello.c<br />
</syntaxhighlight> <br />
*Agora gere o código executável utilizando o programa '''AS''' e o programa '''LD'''.<br />
<code><br />
as -o hello.o hello.s<br />
</syntaxhighlight><br />
* Como a etapa de linkagem para a construção do código executável está sendo executada sem o auxílio do '''GCC''', necessitamos vincular manualmente as bibliotecas necessárias. Para criar apropriadamente o executável vamos precisar das bibliotecas '''ld-linux-x86-64.so.2''', '''crt1.o''', '''crti.o''', '''crtn.o'''.<br />
* Para descobrir suas respectivas localizações use o comando '''LOCATE'''. Por exemplo:<br />
<code><br />
<br />
locate crti.o <br />
<br />
</syntaxhighlight><br />
<br />
ou <br />
<br />
<code><br />
<br />
find /usr/ -name crti*<br />
<br />
</syntaxhighlight><br />
<br />
* Agora que já sabemos a localização das bibliotecas necessárias vamos vincular essas a nossa aplicação.<br />
<code><br />
ld --dynamic-linker /caminho/ld-linux-x86-64.so.2 /caminho/crt1.o /caminho/crti.o /caminho/crtn.o hello.o -lc -o hello.exe<br />
</syntaxhighlight><br />
<br />
* Agora abra o código objeto utilizando o programa OBJDUMP.<br />
* Faça uma análise e identifique o endereço de memória em que o programa ''hello world'' inicializa suas estruturas na memória.<br />
* Dica!<br />
<code><br />
objdump -D -s -j .init hello.exe<br />
</syntaxhighlight><br />
* Houve diferença entre os endereços do programa executável em relação ao código objeto? Explique.<br />
* Explique as principais diferenças entre o arquivo objeto .o e o executável final. (dica utilize o objdump para fazer essa análise)<br />
{{collapse bottom}}<br />
<ol><br />
<li> Estudar e executar o código em http://cs.lmu.edu/~ray/notes/gasexamples/ <br />
Detalhes das chamadas na arquitetura x86_64 ver em https://lwn.net/Articles/604287/ <br />
<li>Estudar e executar o código usando a função (em conformidade com a API POSIX) write() para o ''hello world'':<br />
<code><br />
#include <unistd.h> <br />
<br />
main()<br />
{<br />
write(1,"Alo Mundo\n",10);<br />
}<br />
</syntaxhighlight><br />
</li><br />
<li> Use o comando strace para verificar todas as chamadas de sistema dos programas acima.<br />
</li><br />
<li><br />
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:<br />
<code><br />
main()<br />
{<br />
meu_hello_world();<br />
}<br />
</syntaxhighlight><br />
</li><br />
Gere o assembly do código em C e discuta a diferença entre uma chamada de função e uma chamada de sistema.<br />
<li><br />
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:<br />
<code><br />
#include <string.h><br />
main()<br />
{<br />
char *p="Tudo bem com vocês?";<br />
meu_hello_world(p, strlen(p));<br />
}<br />
</syntaxhighlight><br />
Solução:<br />
{{collapse top|Solução}}<br />
<code><br />
modificado de http://cs.lmu.edu/~ray/notes/gasexamples/<br />
.global meu_hello_world<br />
<br />
.text<br />
meu_hello_world:<br />
<br />
push %rdi # salva primeiro parâmetro<br />
push %rsi # salva segundo parâmetro<br />
mov $1, %rax # system call 1 é write<br />
mov $1, %rdi # file handle 1 é stdout<br />
mov $message, %rsi # endereço da string<br />
mov $13, %rdx # número de bytes da string<br />
syscall # chamada ao sistema<br />
<br />
pop %rdx # o que havia sido passado em rsi (número de bytes) é colocado em rdx<br />
pop %rsi # o que havia sido colocado em rdi (endereço da string) é colocado em rsi<br />
mov $1, %rax # system call 1 is write<br />
mov $1, %rdi # file handle 1 é stdout<br />
syscall # nova chamada ao sistema<br />
<br />
ret<br />
<br />
message:<br />
.ascii "Hello, World\n"<br />
</syntaxhighlight><br />
</li><br />
</ol><br />
{{collapse bottom}}</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=STE29008-2019-2&diff=162111STE29008-2019-22019-10-09T10:54:38Z<p>127.0.0.1: /* (07/10/2018) – Correção A3 e Interrupção */</p>
<hr />
<div>= Sistemas Embarcados: Diário de Aula 2019-2 =<br />
<br />
*'''Professor:''' [[Roberto de Matos]]<br />
*'''Encontros:''' 2ª e 4ª às 07:30h <br />
*'''Atendimento Paralelo:''' 4ª às 10h e 14h (1h cada)<br />
*[[STE-EngTel_(Plano_de_Ensino)| Plano de Ensino]].<br />
* [http://sigaa.ifsc.edu.br/ Cronograma de Aulas]: Conteúdo Programado no Portal SIGAA<br />
<br />
*[http://docente.ifsc.edu.br/roberto.matos/ste_public/adm/STE2019-2_notas.pdf Notas]<br />
<br />
= 29/07/2019 – Apresentação=<br />
<br />
* Apresentação do professor.<br />
* Apresentação da disciplina.<br />
* [https://m.eet.com/media/1246048/2017-embedded-market-study.pdf 2017 Embedded Markets Study]<br />
<br />
= 31/07/2019 – Introdução=<br />
*Notas de Aula:<br />
**[http://www.lisha.ufsc.br/teaching/esl/intro.pdf Introdução]<br />
**[http://www.lisha.ufsc.br/teaching/esl/esd.pdf Embedded Systems Development: Design Principles]<br />
<br />
= 05/08/2019 – GPIO=<br />
<br />
*Notas de Aula:<br />
**[http://www.lisha.ufsc.br/teaching/esl/esd.pdf Embedded Systems Development: Design Principles]<br />
<br />
*Experimento:<br />
**[[ESTE: General Purpose Input and Output (GPIO) | Lab 01: GPIO - Hello LED]]<br />
**[https://www.arduino.cc/en/Tutorial/DigitalPins Arduino - Digital Pins]<br />
<br />
<br />
*Definição das Duplas:<br />
** Daniel e Anderson<br />
** Ameliza e Natalia<br />
** Guilherme e Marcone<br />
** Allex e Douglas<br />
** Fabiano e Filipe Kuhnen<br />
** Felipe Cardoso e Luiza<br />
** Gustavo e Gabriel<br />
<br />
= 07/08/2019 – Experimento UART=<br />
*[https://www.arduino.cc/reference/en/language/functions/communication/serial/ Serial Arduino]<br />
<br />
*Experimentos:<br />
**[[ESTE:_Universal_Assynchronous_Receiver_and_Transmitter_(UART) | Lab 02: UART - Serial Communication]]<br />
**[[ESTE:_UART_-_Serial_Communication | Lab 03: UART - Master/Slave]]<br />
<br />
= 12/08/2019 – Projeto 1: Sensor de Temperatura - Arduino =<br />
<br />
* Notas de Aula:<br />
** https://www.arduino.cc/en/tutorial/AnalogInput<br />
** https://www.arduino.cc/reference/en/language/functions/analog-io/analogread/<br />
<br />
==Atividade==<br />
O objetivo deste experimento é apresentar um exemplo básico de programação de sistema embarcado com microcontrolador. Para isto, será desenvolvido um sensor de temperatura com comunicação serial utilizando a plataforma Arduino.<br />
<br />
*Material necessário:<br />
**Arduino Uno;<br />
**Termistor NTC 10KOhm;<br />
**Resistor 10KOhm;<br />
**Matriz de contato;<br />
**Computador com IDE do Arduino instalada.<br />
<br />
*Para completar o desafio, utilize o site arduino.cc como referência, e construa um sketch (programa na IDE do Arduino) que, a cada 1 segundo, pisque um LED (veja o LED já na placa do Arduino no pino 13), e leia um valor do sensor de temperatura e escreva, em graus celcius, na tela. Um pseudo-código da sua aplicação seria:<br />
<br />
<syntaxhighlight lang=c><br />
loop() {<br />
ligaLED();<br />
AdquireTemperatura(); // lê do ADC e converte para Celcius<br />
desligaLED();<br />
ImprimeResultado(); // pela serial<br />
dorme1segundo();<br />
}<br />
</syntaxhighlight><br />
<br />
*Para completar esta atividade, você precisará:<br />
**Montar um circuito com divisor de tensão utilizando o NTC e o resistor para aquisição do sinal através de uma porta analógica do Arduino<br />
**Especificar um modelo (equação) para obter o valor da resistência do NTC a partir do valor de tensão lido no canal analógico do Arduino;<br />
**Utilizar o modelo de [https://en.wikipedia.org/wiki/Steinhart–Hart_equation Steinhart-Hart] para obter a temperatura a partir da resistência;<br />
**Calibrar o seu sistema para temperaturas entre 0 e 50 graus celcius ([https://www.thinksrs.com/downloads/programs/Therm%20Calc/NTCCalibrator/NTCcalculator.htm utilize esta calculadora] e a tabela de resistência-temperatura do seu NTC abaixo);<br />
**No programa arduino, implemente duas versões do software: uma utilizando apenas "float" e outra utilizando apenas "int 32-bits" (compare as versões).<br />
<br />
*Entregue um relatório curto (1 página), comparando os resultados obtidos em termos de:<br />
**Uso de memória de programa (flash - código-fonte);<br />
**Uso de memória de dados (RAM);<br />
**Tempo necessário para o cálculo (conecte o pino do LED a um osciloscópio - o tempo que o LED fica acesso é o tempo que leva para fazer o cálculo).<br />
<br />
*Observações:<br />
** O trabalho deve ser executado em dupla.<br />
** Entrega até 18/08 via Sigaa<br />
<br />
<br />
http://docente.ifsc.edu.br/roberto.matos/ste_public/fig/NTC-10Kohm-tabela.jpg<br />
<br />
= 14/08/2019 – Projeto 1: Sensor de Temperatura - Arduino (cont.)=<br />
<br />
*Verificar "β parameter equation":<br />
** https://en.wikipedia.org/wiki/Thermistor<br />
<br />
= 19/08/2019 – Correção Projeto 1=<br />
* Implementado em conjunto a versão long e float.<br />
<br />
<br />
= 21/08/2019 – Usando C++=<br />
<br />
==Mudança de nível de abstração==<br />
*Arduino Mega --> ATmega2560 (Ex.: I/O Ports)<br />
*[http://docente.ifsc.edu.br/roberto.matos/ste_public/doc/sch_mega2560-original.pdf Esquemático Arduino Mega]<br />
*[http://docente.ifsc.edu.br/roberto.matos/ste_public/doc/sch_mega2560-clone_CH340G.pdf Esquemático Arduino Mega - CLONE]<br />
<br />
<!--<br />
*[https://www.arduino.cc/en/uploads/Main/arduino-mega2560-schematic.pdf Esquemático Arduino Mega]<br />
*[https://robotdyn.com/pub/media/0G-00005641==MEGA-PRO-CH340GATmega2560/DOCS/Schematic==0G-00005641==MEGA-PRO-CH340GATmega2560.pdf Esquemático Arduino Mega - CLONE]<br />
<br />
<br />
<br />
--><br />
<br />
[[Arquivo: portas_arduino_MEGA.png|800px]]<br />
<br />
<br />
Fonte: https://www.arduino.cc/en/Hacking/PinMapping2560<br />
<br />
<br />
<br />
[[Arquivo:megapdf.jpg|800px]]<br />
<br />
== ATmega2560: I/O Ports==<br />
*[http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2549-8-bit-AVR-Microcontroller-ATmega640-1280-1281-2560-2561_datasheet.pdf Datasheet ATmega2560]<br />
*[http://docente.ifsc.edu.br/roberto.matos/ste_public/doc/datasheet_ATmega2560.pdf Datasheet ATmega2560 (local)]<br />
<br />
*[http://www.avr-tutorials.com/digital/about-avr-8-bit-microcontrollers-digital-io-ports Resumo Portas]<br />
<br />
<br />
*Tabela verdade de configuração das portas:<br />
[[Arquivo:Port_Pin_Configurations.png|600px]]<br />
<br />
<br />
*Endereços registradores de I/O:<br />
[[Arquivo:io_registers_address_2560.png|800px]]<br />
<br />
==GCC, avr-libc==<br />
<br />
===Fluxo Ferramentas:===<br />
<br />
[[Arquivo:Avr-gcc.png|800px]]<br />
<br />
<br />
===AVR-LIBC:===<br />
*[https://www.nongnu.org/avr-libc/ avr-libc]<br />
*[https://www.nongnu.org/avr-libc/user-manual/group__demo__project.html A simple Project]<br />
<br />
===Desenvolvimento:===<br />
* É obrigatório a instalação das ferramentas (Toolchain e AVR-Libc).<br />
* O aluno pode escolher usar o MPLAB X ou montar seu próprio Makefile.<br />
<br />
* MPLAB X:<br />
** [https://www.microchip.com/mplab/mplab-x-ide MPLAB® X IDE v5.20]<br />
** [https://www.microchip.com/mplab/avr-support/avr-and-arm-toolchains-c-compilers AVR 8-bit Toolchain]<br />
<br />
*Makefile:<br />
** Tools: '''sudo apt-get install gcc-avr binutils-avr avr-libc gdb-avr avrdude'''<br />
**[http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/ Guia]<br />
**[http://docente.ifsc.edu.br/roberto.matos/ste_public/src/Makefile Exemplo Simples]<br />
**[https://gist.github.com/rynr/72734da4b8c7b962aa65 Exemplo Complexo]<br />
<br />
* Gravação:<br />
** [https://www.nongnu.org/avrdude/ avrdude]<br />
** MPLAB X: '''avrdude -c avrispmkII -P /dev/ttyUSB0 -D -p ${Device} -U flash:w:${ImagePath}:i''' <br />
** Terminal: '''avrdude -c avrispmkII -P<PORTA> -D -p ATmega2560 -U flash:w:<HEX>:i'''<br />
<br />
==Prática==<br />
*Implemente um programa usando GCC e avr-libc para ligar um led (D13) quando um botão (A0) for pressionado ([[ESTE:_General_Purpose_Input_and_Output_(GPIO)|exemplo]])<br />
*[https://www.geeksforgeeks.org/bitwise-hacks-for-competitive-programming/ Operação de Bits em C/C++]<br />
*[http://www.cplusplus.com/doc/boolean/ Operações Booleanas em C/C++]<br />
*[https://www.avrfreaks.net/forum/tut-c-bit-manipulation-aka-programming-101?name=PNphpBB2&file=viewtopic&t=37871 Programming 101 - By Eric Weddington]<br />
<br />
= 26/08/2019 – Usando C++ (cont.)=<br />
<br />
==Prática==<br />
*Configuração da ferramenta:<br />
** Tools -> Options -> Embedded -> Build Tools-> Add<br />
** Base Directory: '''/opt/microchip/avr8-gnu-toolchain/bin<br />
<br />
*Implemente um programa usando GCC e avr-libc para ligar um led (D13) quando um botão (A0) for pressionado ([[ESTE:_General_Purpose_Input_and_Output_(GPIO)|exemplo]])<br />
<br />
==Notas==<br />
*[https://www.geeksforgeeks.org/bitwise-hacks-for-competitive-programming/ Operação de Bits em C/C++]<br />
*[http://www.cplusplus.com/doc/boolean/ Operações Booleanas em C/C++]<br />
*[https://www.avrfreaks.net/forum/tut-c-bit-manipulation-aka-programming-101?name=PNphpBB2&file=viewtopic&t=37871 Programming 101 - By Eric Weddington]<br />
<br />
<br />
= 28/08/2019 – Usando C++ Serial =<br />
==Objetivos==<br />
* Entender o periférico Serial e implementar métodos de configuração, envio e recepção. <br />
*[http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2549-8-bit-AVR-Microcontroller-ATmega640-1280-1281-2560-2561_datasheet.pdf Datasheet ATmega2560]<br />
<br />
==Experimento==<br />
* Implementar comunicação serial 9600bps 8N1<br />
<br />
<br />
= 02/09/2019 – Usando C++ ADC =<br />
==Objetivos==<br />
* Entender o periférico ADC e implementar métodos de configuração e leitura do ADC.<br />
*[http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2549-8-bit-AVR-Microcontroller-ATmega640-1280-1281-2560-2561_datasheet.pdf Datasheet ATmega2560]<br />
<br />
==Experimento==<br />
* Implementar leitura do ADC<br />
<br />
==Exercício==<br />
* Implementar o "sensor de temperatura" com C++ e AVR-LIBC<br />
* Comparar o tamanho do código gerado<br />
* Entrega: 08/09<br />
<br />
<br />
= 04/09/2019 – Interrupção =<br />
*Desafio:<br />
**Usando Round Robin sem interrupções implementar um sistema com um LED e um botão. O sistema deve piscar o LED (D13) a cada 1 segundos e ao botão (D2) ser pressionado envia uma mensagem pela serial.<br />
<br />
*Notas de Aula:<br />
**[http://www.lisha.ufsc.br/teaching/esl/esd.pdf Embedded Systems Development: Design Principles]<br />
<br />
*Experimentos:<br />
**[[ESTE:_GPIO_and_External_Interrupts_-_part_1 | Lab 04: GPIO and External Interrupts - part 1]]<br />
**[[ESTE:_GPIO_and_External_Interrupts_-_part_2 | Lab 05: GPIO and External Interrupts - part 2]]<br />
<br />
*Referências:<br />
**[https://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html Interrupções AVR-Libc]<br />
<br />
<br />
= 09/09/2019 – Classe GPIO =<br />
* Análise GPIO:<br />
** avr-objdump -h -S <PROJECT_NAME>.elf > <PROJECT_NAME>.lst<br />
*[https://drive.google.com/open?id=1-Duj1Ofn1B4K1mi_MfhXVml8XcJv0AOhAhWjeak-Qf8 Mapeamento de Pinos Arduino Mega]<br />
<br />
* Classe GPIO_v1 discutida em sala de aula.<br />
** [http://docente.ifsc.edu.br/roberto.matos/ste_public/src/gpio_v1.zip GPIO v1 ]<br />
<br />
*Exercício:<br />
** Implementar classe GPIO com ponteiros para as portas.<br />
** Verificar tamanho do "set" e da ocupação da memória de dados<br />
** Comparar com a primeira versão.<br />
<br />
<br />
<syntaxhighlight lang=c><br />
#include <avr/io.h><br />
#include <util/delay.h><br />
#include "GPIO.h"<br />
<br />
<br />
//LEDS PLACA (acende com '0')<br />
GPIO led0(0, GPIO::OUTPUT); //PE0<br />
GPIO led1(1, GPIO::OUTPUT); //PE1<br />
<br />
//LEDS PLACA (acende com '1')<br />
GPIO led13(13, GPIO::OUTPUT); //PB7<br />
<br />
//Adicionar LED<br />
GPIO led4(4, GPIO::OUTPUT); //PG5<br />
GPIO led6(6, GPIO::OUTPUT); //PH0<br />
<br />
int main(void){<br />
<br />
UCSR0B = 0;<br />
<br />
led0.set(1);<br />
led1.set(1);<br />
led6.clear();<br />
led4.clear();<br />
led13.clear();<br />
_delay_ms(1000);<br />
led0.clear();<br />
led1.clear();<br />
led6.set(1);<br />
led4.set(1);<br />
led13.set(1);<br />
_delay_ms(1000);<br />
<br />
while (1){<br />
led0.toggle();<br />
led1.toggle();<br />
led6.toggle();<br />
led4.toggle();<br />
led13.toggle();<br />
_delay_ms(1000);<br />
}<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
[[Arquivo:megapdf.jpg|800px]]<br />
<br />
= 10/09/2019 – Classe GPIO (cont.) =<br />
* Re-fatoração da classe GPIO<br />
** [http://docente.ifsc.edu.br/roberto.matos/ste_public/src/GPIO_Port.zip GPIO Port]<br />
<br />
* Experimento:<br />
** Implementar a classe GPIO_v1.3 com o GPIO_Port.<br />
** Verificar o consumo da memória de dados e programa? Por que o consumo da memória de dados foi 23 bytes?<br />
<br />
* Exercício (fora da sala de aula):<br />
** Implementar todas as versões compreendendo os conceitos de modelagem (v1.2 e v1.3).<br />
** Implementar a v2.0 com o construtor indexado (informações abaixo) entendendo o conceito da indexação dos pinos a partir do id.<br />
** Implementar a v3.0 com todos os pinos do Arduino Mega. Apoio: [https://drive.google.com/open?id=1-Duj1Ofn1B4K1mi_MfhXVml8XcJv0AOhAhWjeak-Qf8 Mapeamento de Pinos Arduino Mega]<br />
<br />
<br />
<br />
* Modificação GPIO.cpp (uso)<br />
<syntaxhighlight lang=c><br />
GPIO::GPIO(uint8_t id, PortDirection_t dir)<br />
{<br />
_bit = GPIO_PORT::id_to_bit[id];<br />
_port = GPIO_PORT::AllPorts[GPIO_PORT::id_to_port[id]];<br />
_port->dir(_bit, dir);<br />
}<br />
</syntaxhighlight><br />
<br />
*Modificação GPIO_Port.h (dentro do namespace GPIO_PORT)<br />
<syntaxhighlight lang=c><br />
extern GPIO_Port * AllPorts[4];<br />
extern const uint8_t id_to_port[14];<br />
extern const uint8_t id_to_bit[14];<br />
</syntaxhighlight><br />
<br />
<br />
*Modificação GPIO_Port.cpp (dentro do namespace GPIO_PORT)<br />
<syntaxhighlight lang=c><br />
GPIO_Port * AllPorts[4] = {<br />
reinterpret_cast<GPIO_Port*>(AVR_PB),<br />
reinterpret_cast<GPIO_Port*>(AVR_PE),<br />
reinterpret_cast<GPIO_Port*>(AVR_PG),<br />
reinterpret_cast<GPIO_Port*>(AVR_PH)<br />
};<br />
<br />
<br />
enum Ports_index {<br />
PB_i = 0,<br />
PE_i = 1,<br />
PG_i = 2,<br />
PH_i = 3<br />
};<br />
<br />
const uint8_t id_to_port[14] = {<br />
PE_i ,<br />
PE_i ,<br />
PE_i ,<br />
PE_i ,<br />
PG_i ,<br />
PE_i ,<br />
PH_i ,<br />
PH_i ,<br />
PH_i ,<br />
PH_i ,<br />
PB_i ,<br />
PB_i ,<br />
PB_i ,<br />
PB_i<br />
};<br />
<br />
const uint8_t id_to_bit[14] = {<br />
(1 << (0)) ,<br />
(1 << (1)) ,<br />
_BV( 4 ) ,<br />
_BV( 5 ) ,<br />
_BV( 5 ) ,<br />
_BV( 3 ) ,<br />
_BV( 3 ) ,<br />
_BV( 4 ) ,<br />
_BV( 5 ) ,<br />
_BV( 6 ) ,<br />
_BV( 4 ) ,<br />
_BV( 5 ) ,<br />
_BV( 6 ) ,<br />
_BV( 7 )<br />
};<br />
</syntaxhighlight><br />
<br />
= (16/09/2019) – Classe UART Bloqueante =<br />
<br />
Proposta e implementação da UART Bloqueante<br />
* Usar a implementação feita em sala de aula e encapsular na classe abaixo. <br />
*Dúvidas: Ler o capítulo 22 do datasheet (USART). Atenção especial as seguintes seções<br />
**"Clock Generation"<br />
**"USART Initialization"<br />
**"Sending Frames with 5 to 8 Data Bit"<br />
**"Receiving Frames with 5 to 8 Data Bits"<br />
**"Register Description"<br />
<br />
*Diagrama de Classe:<br />
http://docente.ifsc.edu.br/roberto.matos/ste_public/uml/UART_bloqueante.png<br />
<br />
<br />
<syntaxhighlight lang=c><br />
#include <avr/io.h><br />
#include <util/delay.h><br />
#include "UART.h"<br />
<br />
UART uart(115200, UART::DATABITS_8, UART::NONE, UART::STOPBIT_1);<br />
<br />
int main(){<br />
uint8_t echo;<br />
char msg[] = "Byte Received: ";<br />
<br />
while(1){<br />
echo = uart.get();<br />
uart.puts(msg);<br />
uart.put(echo);<br />
uart.put('\n');<br />
}<br />
<br />
return 1;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
= (18/09/2019) – Classe UART com interrupção =<br />
<br />
* Dúvidas: Ler manuais da AVR-LIBC<br />
** https://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html<br />
** https://www.microchip.com/webdoc/AVRLibcReferenceManual/group__avr__interrupts.html<br />
** Ler o capítulo 14 do datasheet (Interrupts).<br />
** Ler Seção "7.8 Reset and Interrupt Handling"<br />
** Ler o capítulo 22 do datasheet (USART). Atenção especial as seguintes seções:<br />
***"Transmitter Flags and Interrupts" <br />
***"Receive Compete Flag and Interrupt"<br />
***"Register Description"<br />
*Atenção, a interrupção TXCIEn não deve ser usada - normalmente ela é utilizada apenas para implementar protocolos com reconhecimento/ack;<br />
*Diagrama de Classe:<br />
http://docente.ifsc.edu.br/roberto.matos/ste_public/uml/UART_interrupt.png<br />
<br />
<br />
== Exercício ==<br />
* Implementar Fila e adicionar na Classe UART com interrupção.<br />
http://docente.ifsc.edu.br/roberto.matos/ste_public/uml/UART_interrupt_queue.png<br />
<br />
= (23/09/2018) – Análise do Andamento dos Exercícios =<br />
* Verificação dos alunos com relação as dúvidas<br />
* Análise das implementações executadas até o momento<br />
<br />
<br />
<br />
= (24/09/2018) – Timer e Timeouts =<br />
<br />
* Leitura capítulo 16 ("8-bit Timer/Counter0 with PWM").<br />
*Adaptar e testar a classe timer fornecida para o Atmega2560:<br />
**[http://docente.ifsc.edu.br/roberto.matos/ste_public/src/Timer.zip Classe Timer]<br />
**[https://pt.wikipedia.org/wiki/Singleton Singleton]<br />
<br />
*Implementar a classe Timeout e e inserir os métodos "TimeoutManager" e "addTimeout" na classe Timer:<br />
http://docente.ifsc.edu.br/roberto.matos/ste_public/uml/timeouts.png<br />
<br />
<syntaxhighlight lang=c><br />
#include <avr/io.h><br />
#include <avr/interrupt.h><br />
#include "GPIO.h"<br />
#include "Timer.h"<br />
<br />
<br />
GPIO p2(2, GPIO::OUTPUT);<br />
GPIO p3(3, GPIO::OUTPUT);<br />
GPIO p4(4, GPIO::OUTPUT);<br />
GPIO p5(5, GPIO::OUTPUT);<br />
<br />
void timeout2_handler(void){<br />
p2.toggle();<br />
}<br />
<br />
void timeout3_handler(void){<br />
p3.toggle();<br />
}<br />
<br />
void timeout4_handler(void){<br />
p4.toggle();<br />
}<br />
<br />
void timeout5_handler(void){<br />
p5.toggle();<br />
}<br />
<br />
<br />
Timer t = Timer(1000);<br />
<br />
int main(){<br />
<br />
sei();<br />
t.addTimeout(1000, &timeout2_handler);<br />
t.addTimeout(2000, &timeout3_handler);<br />
t.addTimeout(3000, &timeout4_handler);<br />
t.addTimeout(4000, &timeout5_handler);<br />
while(true){<br />
t.timeoutManager();<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
= (30/09/2018) – Timer e Timeouts (cont.)=<br />
* Finalizar a implementação da classe Timeouts.<br />
<br />
* Desenvolvimento C++<br />
** 21/08 e 26/08: Botão LED<br />
** 28/08: Transmissão Serial Bloqueante<br />
* ISR com a AVR-LIBC<br />
** 04/09: Desafio e Interrupção Externa<br />
*Consumo Memória (Dados e Programa), LSS<br />
** 09/09: GPIO_v1 ("case")<br />
** 10/09: GPIO_v1.2 (ponteiros DDR, PORT, PIN)<br />
*Refatoração Classe <br />
** 10/09: GPIO_v1.3 (GPIO_Port)<br />
*Indexação do Construtor<br />
** 16/09: GPIO_v2 (wiki) e GPIO_v3 (todos os pinos do Mega)<br />
<br />
*Modelando Classes:<br />
**16/09: Classe UART Bloqueante<br />
**18/09: Classe UART com interrupção (tarefa: adicionar FIFO)<br />
**24/09: Classe Timer/Timeout<br />
<br />
<br />
= (02/10/2018) – A3 =<br />
* Avaliação individual prática em sala de aula.<br />
<br />
<br />
= (07/10/2018) – Correção A3 =<br />
* Correção da A3<br />
<br />
<br />
= (07/10/2018) – Interrupção Externa =<br />
<br />
==Classe de Interrupção Externa: ==<br />
* A [http://docente.ifsc.edu.br/roberto.matos/ste_public/src/extint.zip Classe extint] funciona para as 8 interrupções externas (INTn). Não confundir com a PCINTn.<br />
<br />
* Ler manuais da AVR-LIBC:<br />
** https://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html<br />
** https://www.microchip.com/webdoc/AVRLibcReferenceManual/group__avr__interrupts.html<br />
<br />
* Ler o capítulo 14 do datasheet (Interrupts).<br />
* Ler Seção "7.8 Reset and Interrupt Handling"<br />
* Ler o capítulo 15 do datasheet (External Interrupts). Atenção especial as seguintes seções:<br />
**"Register Description" (EICRA, EICRB, EIMSK e EIFR)<br />
<br />
*Diagrama de Classe:<br />
http://docente.ifsc.edu.br/roberto.matos/ste_public/uml/ExtInt.png<br />
<br />
*Atividade<br />
** Fazer proposta de integração com a GPIO<br />
** Codificar e fazer teste</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=FIC_MATLAB_2019-2/Aula-13&diff=162110FIC MATLAB 2019-2/Aula-132019-10-09T01:02:31Z<p>127.0.0.1: </p>
<hr />
<div><syntaxhighlight lang=matlab class="mw-collapsible"><br />
%% Programa principal<br />
clear<br />
close all<br />
<br />
num1 = input('Qual o primeiro número? \n');<br />
num2 = input('E o segundo número? \n');<br />
operacao = input('Escolha a operação\n','s');<br />
[result, sinal] = calc(num1, num2, operacao);<br />
disp(['Seu resultado é ' num2str(result) ' e o sinal dele é ' num2str(sinal)]);<br />
<br />
[media_ar, media_geo] = medias(num1,num2);<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=matlab class="mw-collapsible"><br />
%% Função calculadora<br />
function [resultado, sinal] = calc(num1, num2, op) % Primeria saída é resultado e segunda saída é o sinal do resultado<br />
switch op<br />
case '/'<br />
resultado = num1 / num2; % caso de divisão<br />
case '*'<br />
resultado = num1 * num2; % caso de multiplicação<br />
case '-'<br />
resultado = num1 - num2; % caso de subtração<br />
case '+'<br />
resultado = num1 + num2; % caso de soma<br />
end<br />
sinal = sign(resultado); % sinal do resultado final.<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=matlab class="mw-collapsible"><br />
%% função média aritmética e geométrica<br />
function [m_aritmetica, m_geometrica] = medias(num1, num2)<br />
% média aritmética<br />
m_aritmetica = (num1 + num2)/2;<br />
<br />
% média geométrica<br />
m_geometrica = sqrt(num1 * num2);<br />
<br />
end<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=matlab class="mw-collapsible"><br />
% questão 1.c<br />
function PalavraFinal = retiraCaracter(palavraInicial,posicao)<br />
palavraInicial(posicao) = [];<br />
PalavraFinal = palavraInicial;<br />
end<br />
</syntaxhighlight></div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=FIC_MATLAB_2019-2/Aula-13&diff=162109FIC MATLAB 2019-2/Aula-132019-10-09T00:57:42Z<p>127.0.0.1: </p>
<hr />
<div><syntaxhighlight lang=matlab class="mw-collapsible"><br />
%% Função principal<br />
clear<br />
close all<br />
<br />
num1 = input('Qual o primeiro número? \n');<br />
num2 = input('E o segundo número? \n');<br />
operacao = input('Escolha a operação\n','s');<br />
[result, sinal] = calc(num1, num2, operacao);<br />
disp(['Seu resultado é ' num2str(result) ' e o sinal dele é ' num2str(sinal)]);<br />
<br />
[media_ar, media_geo] = medias(num1,num2);<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=matlab class="mw-collapsible"><br />
%% Função calculadora<br />
function [resultado, sinal] = calc(num1, num2, op) % Primeria saída é resultado e segunda saída é o sinal do resultado<br />
switch op<br />
case '/'<br />
resultado = num1 / num2; % caso de divisão<br />
case '*'<br />
resultado = num1 * num2; % caso de multiplicação<br />
case '-'<br />
resultado = num1 - num2; % caso de subtração<br />
case '+'<br />
resultado = num1 + num2; % caso de soma<br />
end<br />
sinal = sign(resultado); % sinal do resultado final.<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=matlab class="mw-collapsible"><br />
%% função média aritmética e geométrica<br />
function [m_aritmetica, m_geometrica] = medias(num1, num2)<br />
% média aritmética<br />
m_aritmetica = (num1 + num2)/2;<br />
<br />
% média geométrica<br />
m_geometrica = sqrt(num1 * num2);<br />
<br />
end<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=matlab class="mw-collapsible"><br />
% questão 1.c<br />
function PalavraFinal = retiraCaracter(palavraInicial,posicao)<br />
palavraInicial(posicao) = [];<br />
PalavraFinal = palavraInicial;<br />
end<br />
</syntaxhighlight></div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=ISL-FicLinux_(p%C3%A1gina)&diff=162098ISL-FicLinux (página)2019-10-08T19:59:35Z<p>127.0.0.1: /* TCP e UDP */</p>
<hr />
<div>__NOTOC__<br />
= Introdução ao Sistema Operacional Linux / Redes com Linux =<br />
<br />
*'''Encontros:''' Terças e Quintas das 19:00 às 22:00.<br />
*'''Local:''' Laboratório de Redes de Computadores (Redes 1).<br />
<br />
*[[ISL-FicLinux_(Plano_de_Ensino)| Plano de Ensino]]<br />
<br />
==Curso FIC Linux 2019==<br />
<br />
{{collapse top | Semestre 2019-2 - Prof. Eraldo Silveira e Silva}}<br />
<br />
==Cronograma Tentativa==<br />
<br />
Horários: 19h às 22h.<br />
<br />
{| class="wikitable"|<br />
| AULA || DATA || Professor || Conteúdo<br />
|-<br />
| 1 || 27/09/2019 || ERALDO || Programa da Disciplina.Forma de Avaliação. O computador: hardware e software. SO Linux: histórico e distribuições. Ligando/Logando/Desligando a Máquina. Conceitos básico de Sistema de Arquivos e Processos.<br />
|-<br />
| 2 || 29/09/2019 || ERALDO || Gerenciamento de Arquivos I: Operações sobre arquivos e diretórios usando o terminale o Nautilus.<br />
|-<br />
| 3 || 3/09/2019 || ERALDO || Gerenciamento de Arquivos II: continuação Operações sobre arquivos e diretórios. Links Simbólicos, Criação de Arquivo com vi e outros editores.<br />
|-<br />
| 4 || 5/09/2019 || ERALDO || Interfaces Gráficas: X11, Gnome. KDE e outras. Instalação de Programas via Gerenciador de Pacotes.<br />
|-<br />
| 5 || 10/09/2019 || ERALDO || Administração de contas de usuários I<br />
|-<br />
| 6 || 12/09/2019 || ERALDO || Administração de contas de usuários II<br />
|-<br />
| 7 || 17/09/2019 || ERALDO || Permissionamento de Arquivos<br />
|-<br />
| 8 || 19/09/2019 || ERALDO || Gerenciamento de Processos<br />
|-<br />
| 9 || 24/09/2019 || ERALDO || Introdução ao Shell Script<br />
|-<br />
| 10 || 26/09/2019 || ERALDO || Introdução ao Shell Script<br />
|-<br />
| 11 || 1/10/2019 || ERALDO || Introdução a Redes. Conceito de Protocolos. Ferramentas de Rede no Linux.<br />
|-<br />
| 12 || 3/10/2019 || ERALDO || Conceito de Protocolos. Protocolos de Aplicação: exemplo http. Protocolo DNS<br />
|-<br />
| 13 || 8/10/2019 || ERALDO || Camada de Transporte: protocolo UDP. Protocolo TCP. Diferenças dos protocolos de Transporte TCP/UDP. <br />
|-<br />
| 14 || 10/10/2019 || ERALDO || Camada IP e aspectos da configuração da mesma sob o Linux<br />
|-<br />
| 15 || 15/10/2019 || ERALDO || Camada de Enlace/Física. Hubs X Switches. O Papel do Protocolo ARP. Outros serviços/protocolos: Serviço DHCP e NAT<br />
|-<br />
| 16 || 17/10/2019 || ERALDO|| Segmentação Redes IP. Cálculo de subredes. <br />
|-<br />
| 17 || 22/10/2019 || ERALDO || Introdução ao IPV6. Introdução ao Access Point TPLINK N750: configuração da LAN e WAN<br />
|-<br />
| 18 || 24/10/2019 || ERALDO || Serviço SSH no Linux. Acesso a rede WIFI. Conceitos básicos de redes sem fio.<br />
|-<br />
| 19 || 29/10/2009 || ERALDO || Tópicos Adicionais sobre redes no Linux: Configuração Manual X NetworkManager. Relatório Avaliativo 1.<br />
|-<br />
| 20 || 31/10/2019 || ERALDO || Relatório Avaliativo 2<br />
|}<br />
<br />
=Curso FIC Linux 2019-2=<br />
<br />
==Professor==<br />
<br />
:*Prof. [[Eraldo Silveira e Silva]]<br />
:*email: eraldo@ifsc.edu.br<br />
:*sala: Sala de I de Professores da Área de Telecomunicações (primeira sala lado da Biblioteca - direção esquerda)<br />
<br />
=27/08/2019=<br />
<br />
==Objetivos==<br />
<br />
===Parte 1===<br />
<br />
*Apresentar o IFSC: estrutura, câmpus e serviços<br />
*Apresentar o curso: perfil do egresso, competências gerais, áreas de atuação do egresso e conteúdos previstos<br />
*Apresentar o Cronograma Tentativa (ver SIGA A)<br />
*Apresentar metodologia e forma de avaliação<br />
<br />
===Parte 2===<br />
<br />
*Conceitos de Hardware, Software e Firmware<br />
*Arquiteturas de processadores<br />
*Classificação de softwares<br />
*Conceitos de Sistemas Operacionais e exemplos<br />
<br />
===Parte 3===<br />
<br />
*Histórico do Linux<br />
*Linux e GNU/Linux<br />
*Instalando o Linux<br />
*Arquitetura do Linux<br />
*Distribuições<br />
*Distribuições usadas no IFSC/SJ<br />
*Ligando e Desligando o Sistema<br />
*Primeiros contatos.<br />
<br />
==Professores do FIC Linux Edição 2019-2==<br />
<br />
*Prof. [[Eraldo Silveira e Silva]] (Introdução ao Linux e Redes com Linux)<br />
<br />
==Apresentação do IFSC==<br />
<br />
*[http://www.ifsc.edu.br/estrutura-organizacional-inicio Página do IFSC]<br />
*[https://www.sj.ifsc.edu.br/index.php Página do Câmpus]<br />
<br />
==Apresentação do Curso==<br />
<br />
*[[ISL-FicLinux_(Plano_de_Ensino) | Introdução ao Linux]]<br />
*[https://wiki.sj.ifsc.edu.br/index.php/PRL-FicLinux_(Plano_de_Ensino) Projeto de Rede Residencial com o Linux]<br />
*[[Curso_de_Formação_Continuada_de_Configuração_de_Redes_de_Computadores_Linux | PPC do Curso e Outras Regulamentações]]<br />
<br />
==Cronograma Tentativa==<br />
<br />
Horários: 19h às 22h.<br />
<br />
VER SIGA A [https://sig.ifsc.edu.br/sigaa/verTelaLogin.do]<br />
<br />
==Metodologia, Avaliação e Critérios de Aprovação==<br />
<br />
*Aulas expositivas e aulas práticas no laboratório. Nas aulas práticas serão desenvolvidos exercícios e trabalhos individuais.<br />
*Avaliações individuais: Listas de exercícios com aproveitamento e entregues no prazo. <br />
*Critérios para aprovação: Serão considerados aprovados os alunos que obtiverem conceito final 6 ou superior em cada componente curricular. ATENÇÃO: Possuir no mínimo 75% de presença<br />
<br />
==Bibliografia==<br />
<br />
#Odilson Tadeu Valle<br />
##Administração de redes com Linux: fundamentos e práticas<br />
##Editora IFSC, 2010<br />
#Gleydson Mazioli da Silva<br />
##Guia Foca Linux<br />
##http://www.guiafoca.org/<br />
#Luiz Carlos Lobato Lobo de Medeiros e Wendel Soares<br />
##Formação de suporte técnico PROINFO<br />
##https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo<br />
#Ari Frazão Jr e Marcelo Braga<br />
##Administração de Sistemas Linux<br />
##https://pt.scribd.com/doc/128912228/Administracao-de-Sistemas-Linux<br />
<br />
==Conceitos de Hardware, Software e Firmware==<br />
<br />
*Em informática, o hardware consiste nos equipamentos<br />
**Ex: Computador, teclado, mouse, monitor<br />
*Software é um aplicativo, desenvolvido em uma linguagem de programação<br />
**Ex: Windows, Linux, Mozilla Firefox, Google Chrome<br />
*Firmware é um conjunto de instruções básicas e específicas para um hardware<br />
**Ex: BIOS nos computadores, sistemas de controle das máquinas de lavar, etc.<br />
<br />
==Estrutura de um Computador e Arquitetura de Processadores==<br />
<br />
*Material de Referência: https://www.dropbox.com/s/fn3l9os4l7gh9o5/AULA%201.odp?dl=0<br />
<br />
===Outros Links Interessantes===<br />
<br />
*Bits, [https://pt.wikipedia.org/wiki/Byte Bytes] e tamanho de memória;<br />
*Representação de Caracteres: [https://pt.wikipedia.org/wiki/ASCII Tabela ASCII];<br />
*O [https://pt.wikipedia.org/wiki/Microprocessador microprocessador], barramentos e memórias semicondutoras: RAM,ROM, E2PROM, FLASH;<br />
*Memórias cache e memórias secundárias;<br />
*[https://pt.wikipedia.org/wiki/Mem%C3%B3ria_virtual Memória Virtual] e Swapping;<br />
*Registradores de 32bits ou 64bits<br />
*Arquitetura [https://pt.wikipedia.org/wiki/X86 x86] / [https://pt.wikipedia.org/wiki/AMD64 x86-64] – presente nos computadores pessoais<br />
*Arquitetura ARM – presente em sistemas embarcados e dispositivos móveis<br />
*Múltiplos núcleos (core)<br />
*Máquinas Virtuas: VirtualBox, UML (User Mode Linux).<br />
<br />
==O papel do Sistema Operacional==<br />
<br />
*O [https://pt.wikipedia.org/wiki/Sistema_operativo SO] é um programa (software) que controla a máquina e a torna utilizável para o usuário;<br />
*Abstrações do Sistema: arquivos e processos;<br />
*Pode ser multitarefa e multiusuário;<br />
*[https://en.wikipedia.org/wiki/Device_driver Driver] de dispositivo<br />
*[https://pt.wikipedia.org/wiki/Multi_boot Múltiplos OS instalados] em um computador. É possível??<br />
<br />
==Sistema de Arquivos==<br />
<br />
*Forma como estão estruturados/organizados os arquivos/dados em uma determinada mídia [https://pt.wikipedia.org/wiki/Sistema_de_ficheiros];<br />
*Um sistema operacional deve saber como acessar e operar sobre este sistema;<br />
*Tipos de sistemas: ext4, NTFS, VFAT32<br />
<br />
==Exemplos de SO==<br />
<br />
*Unix<br />
*Microsoft DOS<br />
*IBM<br />
*Microsoft Windows<br />
*netBSD, freeBSD, openBSD<br />
*Linux<br />
*macOS<br />
*Android<br />
*iOS<br />
<br />
==Histórico do Linux==<br />
<br />
*O início de tudo: UNIX;<br />
*Surgiu em 1991 quando Linus Torvalds, um estudante finlandês, resolveu desenvolver um sistema operacional compatível com a POSIX, por em que pudesse ser executado em arquitetura x86;<br />
*Linux está sob uma licença de software livre e diversas pessoas e empresas contribuem para o desenvolvimento do mesmo.<br />
*E o que é [https://pt.wikipedia.org/wiki/POSIX POSIX]? Define padrões para a interface de programação de aplicações (API) de um OS de forma a manter compatibilidade com o UNIX;<br />
<br />
==Arquitetura do Linux==<br />
<br />
===Material de Referência===<br />
<br />
*[https://www.dropbox.com/s/zvpo7zw19ns7rmk/AULA%202.odp?dl=0 Slides Introdução ao SO Linux]<br />
*Ver pg.16 a 19 de [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo]<br />
<br />
==Distribuições==<br />
<br />
Uma distribuição Linux consiste de um kernel Linux e uma coleção de software utilitários e aplicativos de usuário (baseado slides Prof. Emerson)<br />
**Redhat<br />
**Slackware<br />
**Debian<br />
**Ubuntu<br />
**OpenSuse<br />
**Fedora<br />
**CentOS<br />
**Kali<br />
<br />
<br />
Algumas distribuições podem ser executadas diretamente no CD/pendrive<br />
sem a necessidade de fazer sua instalação no disco rígido do computador<br />
<br />
==Distribuições aqui no IFSC SJ==<br />
<br />
*Ubuntu<br />
*Ubuntu Mate (fork do Ubuntu)<br />
*Debian<br />
<br />
==Instalando o Linux==<br />
<br />
*Fazer Download do arquivo ISO em [http://mirror.pop-sc.rnp.br/mirror/ubuntu-releases/18.04/] versão Ubuntu 18.04.3 LTS;<br />
*Instalar a VirtualBox (já está instalada no nosso Lab). Baixar de [https://www.virtualbox.org/wiki/Downloads] e selecionar para a máquina hospedeira alvo;<br />
*Seguir o procedimento colocado pelo professor.<br />
<br />
*[Ver https://www.dropbox.com/s/4xfdhqq8lruvq8m/LinuxSobreVM.odp?dl=0 Slides de Instalação]<br />
<br />
==Ligando e Desligando o Sistema Linux==<br />
<br />
*Cuidado ao desligar um OS como o Linux!!! Dados podem ser perdidos.<br />
*Ver [https://pt.wikibooks.org/wiki/Guia_do_Linux/Iniciante%2BIntermedi%C3%A1rio/Introdu%C3%A7%C3%A3o/Ligando_o_computador]<br />
<br />
==O Desktop do Ubuntu - Primeiras Considerações==<br />
<br />
*O Desktop no Ubuntu ver[https://help.ubuntu.com/stable/ubuntu-help/shell-overview.html]<br />
<br />
=AULA 2 - Dia 29/08/2019=<br />
<br />
==Objetivos==<br />
<br />
===PARTE 1===<br />
<br />
*Revisão da aula passada;<br />
*repassar itens não mencionados na aula passada;<br />
**Paginação e Memória [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo pg.19]<br />
**Estrutura do Linux [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo pg.18]<br />
<br />
===PARTE 2===<br />
<br />
*Operações com arquivos e diretórios usando o terminal;<br />
*formato de um comando básico;<br />
*quase tudo no Linux é arquivo: tipos de arquivos, diretórios, arquivos ordinários;<br />
*conceito de sistema de arquivos;<br />
*conceito de referência absoluta e relativa;<br />
*conceito de diretório de entrada, diretório de trabalho;<br />
*mudando de diretório com cd;<br />
*listando diretórios e arquivos com ls;<br />
*vendo o significado de um comando com man;<br />
*criando diretórios com mkdir;<br />
*removendo diretórios e arquivos com rmdir e rm;<br />
*referência com . .. - ~<br />
*criando arquivos ordinários com touch;<br />
*arquivos e diretórios escondidos;<br />
*copiando arquivos;<br />
*movendo e renomeando arquivos;<br />
*vendo a história de comandos com history;<br />
<br />
===Slides===<br />
<br />
*[https://www.dropbox.com/s/wtc479wmrtle9m4/SistemaDeArquivos.odp?dl=0 Slides Sistema de Arquivos]<br />
<br />
==Conceito de sistemas de arquivos, arquivos e diretórios==<br />
<br />
* [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Sistemas de Arquivos pg.18]<br />
* [Estrutura básica de diretórios do Sistema Linux]<br />
<br />
==Comandos no Linux==<br />
<br />
* [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Comandos e Interpretador de Comandos no Linux pg.18]<br />
<br />
==Tipos de Arquivos==<br />
<br />
* [https://pt.scribd.com/doc/128912228/Administracao-de-Sistemas-Linux Tipos de Arquivos 12,13 e 14 ]<br />
<br />
==Os comandos de operação sobre arquivos e diretórios==<br />
<br />
*[https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Interpretador de comandos - Comandos Básicos - pg.20 e 21]<br />
*[https://www.dropbox.com/s/mv6qpa8bqimiwzg/Aula1_Linux%282%29.pdf Ver lista de exercícios da Aula 2]<br />
<!-- *[https://www.dropbox.com/s/g3xr3wimffde2zm/Aula2_Linux_OperacoesComArquivos_2.pdf Ver lista de exercícios da Aula 3] --><br />
<br />
=AULA 3 - Dia 03/09/2019=<br />
<br />
<br />
===Mirros do Ubuntu Download e Outros===<br />
<br />
<br />
*[http://mirror.pop-sc.rnp.br/mirror/ubuntu-releases/18.04.3/ Ununtu 18.04.3 Mirror Brazil]<br />
<br />
*[https://linuxmint.com/edition.php?id=267 Linux Mint]<br />
<br />
*[https://software.opensuse.org/distributions/leap Opensuse]<br />
<br />
*[https://elementary.io/ Elementary Os]<br />
<br />
*[https://lubuntu.net/ Lubuntu]<br />
<br />
*[https://www.debian.org/CD/live/ Debian]<br />
<br />
*[https://kubuntu.org/getkubuntu/ Kubuntu]<br />
<br />
*[https://peppermintos.com/ Peppermint]<br />
<br />
*[https://www.linuxliteos.com/ Linux Lite]<br />
<br />
*[https://www.lxle.net/download/ LXLE para PCs Antigos...]<br />
<br />
*[https://www.bodhilinux.com/ Bodhi Linux]<br />
<br />
===Como verificar se o arquivo está correto?===<br />
<br />
*[https://help.ubuntu.com/community/HowToMD5SUM HowToMD5SUM] <br />
<br />
===Instalar e Preparar 3 transparências no Oppenoffice===<br />
<br />
*Nome da Equipe e da Distribuição - colar a desktop no slide<br />
*O que tem de interessante nesta distro<br />
*Requisitos da Distribuição<br />
<br />
*Gerar pdf e Enviar para o Siga a<br />
<br />
=AULA 4 - Dia 03/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Ainda operações com arquivos;<br />
*Uso de Coringas<br />
*Editor de texto sobre Ubuntu<br />
*Redirecionamento de Entradas e Saídas<br />
*Aspectos da Interface Gnome no Ubuntu 18.04<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/zti7nn0xq25x8ne/Aula2_Linux_OperacoesComArquivos_2.pdf Ainda Operações com Arquivos]<br />
*[https://www.dropbox.com/s/af3jolkvrb24g8c/Aula3_Linux_LinksSimb_licos_gedit_cat.pdf Edição de Texto]<br />
*[https://www.dropbox.com/s/vihh5r9186d40uj/Aula3_Linux_Parte4_RedirecionamentoEntradasSaidas.pdf Redirecionamento de Entradas e Saídas]<br />
<br />
=AULA 5 - Dia 10/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Gerenciamento de Processos - Parte 1<br />
*Permissionamento de Arquivos - Parte 1<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/4i1n2wqsds18eol/Aula5_Linux_GerenciamentoDeProcessos_Parte1.pdf?dl=0 Gerenciamento de Processos - Parte 1]<br />
*[https://www.dropbox.com/s/3z61r8r0b9wpftr/Aula4_Linux_PermissionamentoDeAcesso_Parte1.pdf Permissionamento de Arquivos - Parte 1]<br />
<br />
=AULA 6 - Dia 12/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Aval1<br />
<br />
==Comand wget==<br />
<br />
Para fazer o downloiad do Linux Ubuntu via linha de comando:<br />
<br />
wget http://mirror.pop-sc.rnp.br/mirror/ubuntu-releases/18.04.3/ubuntu-18.04.3-desktop-amd64.iso<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/fdl5kzq0ba2nv3v/Aula4_Linux_PermissionamentoDeAcesso_Parte2.pdf Permissionamento Parte 2 ]<br />
<br />
=AULA 7 - Dia 12/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Instalação do Ubuntu em partições separadas<br />
*Permissionamento de Grupos e Outros<br />
*Criação de Contas de Usuários<br />
*Camandos adicionais para gerenciamento de processos<br />
<br />
==Instalação==<br />
<br />
Considere a estrutura de sistemas de arquivos abaixo. Montar um sistema de arquivos da forma abaixo considerando que sb1 seria um segundo hd máquina virtual.<br />
<br />
[[arquivo:SOP2019-1-ExemploMontagemSistema.png]]<br />
<br />
Logar no sistema e usando o terminal verificar as configurações estabelecidas.<br />
<br />
df -h<br />
cd /home<br />
ls spock<br />
<br />
Usar o comando gparted para criar uma partição adicional no segundo disco.<br />
<br />
sudo apt-get install gparted<br />
sudo gparted<br />
<br />
Redimensionar a partição original para poder criar uma adicional.<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/fdl5kzq0ba2nv3v/Aula4_Linux_PermissionamentoDeAcesso_Parte2.pdf Permissionamento Parte 2 ]<br />
<br />
*[https://www.dropbox.com/s/ozjd3qz0yblcj43/Aula6_Comandos_Adicionais_de_Gerenciamento_de_Processos.pdf Gerenciamento de Processos Parte 2]<br />
<br />
=AULA 8 - Dia 12/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Permissionamento de Grupos e Outros<br />
*Criação de Contas de Usuários<br />
*Reparticionamento de Disco após instalação. Montagem de sistemas com mount.<br />
<br />
==Desafio Final==<br />
<br />
Na máquina instalada na aula anterior fazer as seguintes operações:<br />
<br />
*Reparticionar o disco 2 (/dev/sdb) em 2 partições de 5G (usar o comando gparted) (redimensionar a partição do spock)<br />
*Criar uma conta para o usuário uhura<br />
*Criar dois subdiretórios no diretório home de uhura. Estes diretórios serão pontos de montagem dos dois sistemas de arquivos criados no segundo disco.<br />
*Montar os sistemas de arquivos usando o comando mounthttps://wiki.sj.ifsc.edu.br/index.php/ISL-FicLinux_(Plano_de_Ensino)<br />
*Mudar o dono destes diretórios (usuário e grupo) )para o novo dono (uhura)<br />
*Verificar o sistema montado (comando df)<br />
*Testar o acesso entrando como <br />
<br />
==Continuando o o permissionamento de Grupos e Outros==<br />
<br />
Ver material de referência<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/fdl5kzq0ba2nv3v/Aula4_Linux_PermissionamentoDeAcesso_Parte2.pdf Permissionamento Parte 2 ]<br />
*[https://www.dropbox.com/s/ozjd3qz0yblcj43/Aula6_Comandos_Adicionais_de_Gerenciamento_de_Processos.pdf Gerenciamento de Processos Parte 2]<br />
<br />
=AULA 9 - Dia 24/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*ainda criação de usuários<br />
*ainda gerenciamento de processos: crontab<br />
*compactação e backups em linha de comando<br />
<br />
<br />
==Material de Referência==<br />
<br />
<br />
*[Ainda Gerenciamento de Usuários https://www.dropbox.com/s/8vsg0yeforcsuq9/Aula7_GerenciamentoDeUsuarios_Parte1.pdf?dl=0]<br />
*[https://www.dropbox.com/s/ozjd3qz0yblcj43/Aula6_Comandos_Adicionais_de_Gerenciamento_de_Processos.pdf Gerenciamento de Processos Parte 2]<br />
*[https://www.dropbox.com/s/61n9is9c8o7bgbz/Aula3_Linux_Parte3_vi.pdf?dl=0 Introdução ao VI]<br />
<br />
=AULA 10 - Dia 26/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Finalização da aula anterior: arquivo sudoers<br />
*Introdução ao shell script<br />
*Um pouco sobre instalação de pacotes<br />
*exercicício avaliativo 2<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/54tnv5rjwguzppd/Aula8_ShellScript_Parte1.pdf?dl=0 Introdução ao Shell script]<br />
*[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula9-pacotes.pdf Instalação de Pacotes (Prof.Luciano Barreto)]<br />
<br />
=AULA 11 - Dia 1/10/2019=<br />
<br />
Introdução a Redes de Computadores<br />
**Conceito Básicos em Redes e Protocolos<br />
**Ferramentas de Redes<br />
**Exemplo de Protocolo de Aplicação: http<br />
**O processo de encapsulamento<br />
<br />
==Plano de Ensino==<br />
<br />
*[https://wiki.sj.ifsc.edu.br/index.php/PRL-FicLinux_(Plano_de_Ensino) Plano de Ensino]<br />
<br />
<br />
==Laboratório 1 - Ferramentas de Rede e Conceitos Básicos==<br />
<br />
*Familiarização com a infraestrutura dos laboratórios de redes<br />
*Familiarização com ferramentas de rede: ifconfig, ping, traceroute;<br />
*Desenvolver a noção de endereçamentos de rede IP e de endereço de hardware (MAC)<br />
*Desenvolver a noção de rotas em redes IP<br />
*Testar a conectividade IP com ping<br />
<br />
*Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)]<br />
<br />
==Laboratório 2 - Wireshark e encapsulamento==<br />
<br />
*Familiarização com o sniffer de rede WireShark<br />
*Observar o comportamento do ping e se familiarizar com o processo de encapsulamento;<br />
<br />
**Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)]<br />
<br />
==Conceituando Protocolos e Aplicações de Rede==<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/Conceituando%20protocolos.pdf Conceituando protocolos]<br />
<br />
<br />
=AULA 12 - Dia 03/10/2019=<br />
<br />
==Objetivos==<br />
<br />
*Exercício de Revisão<br />
*Conceituando protocolos<br />
*Protocolos de aplicação: exemplo http<br />
*O serviço DNS<br />
<br />
==Exercício de revisão 2.1==<br />
<br />
#Liste as configurações da interface eth0 da sua máquina Linux. Recorte e cole em um doc (tipo DRAW) do openoffice. Indique usando flechas onde estão os endereços IPV4, IPV6, MAC(endereço de hardware) e o local indicando onde a interface está ativa.<br />
<br />
==Laboratório 3 - Conceituando protocolo==<br />
<br />
Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)#Laborat.C3.B3rios]<br />
<br />
==Laboratório 4 - Desvendando o HTTP com Wireshark - BÁSICO==<br />
<br />
Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)#Laborat.C3.B3rios]<br />
<br />
==Laboratório 7 - O DNS ==<br />
<br />
Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)#Laborat.C3.B3rios]<br />
<br />
{{collapse bottom}}<br />
<br />
<br />
<br />
{{collapse top | Semestre 2019-1 - Prof. Tiago Semprebom e Eraldo Silveira e Silva}}<br />
<br />
=Professor=<br />
<br />
:*Prof. [[Tiago Semprebom]]<br />
:*email: tisemp@ifsc.edu.br<br />
:*sala: Sala de II de Professores da Área de Telecomunicações (primeira sala lado da Biblioteca - direção esquerda)<br />
<br />
=12/03/2019=<br />
<br />
==Objetivos==<br />
<br />
===Parte 1===<br />
*Apresentar os professores e o coordenador;<br />
*Apresentar o IFSC: estrutura, câmpus e serviços<br />
*Apresentar o curso: perfil do egresso, competências gerais, áreas de atuação do egresso e conteúdos previstos<br />
*Apresentar o Cronograma Tentativa<br />
*Apresentar metodologia e forma de avaliação<br />
<br />
===Parte 2===<br />
<br />
*Conceitos de Hardware, Software e Firmware<br />
*Arquiteturas de processadores<br />
*Classificação de softwares<br />
*Conceitos de Sistemas Operacionais e exemplos<br />
<br />
===Parte 3===<br />
<br />
*Histórico do Linux<br />
*Linux e GNU/Linux<br />
*Arquitetura do Linux<br />
*Distribuições<br />
*Distribuições usadas no IFSC/SJ<br />
*Ligando e Desligando o Sistema<br />
*Primeiros contatos.<br />
<br />
==Professores do FIC Linux Edição 2019-1==<br />
*Prof. [[Tiago Semprebom]] (Introdução ao Linux)<br />
*Prof. [[Eraldo Silveira e Silva]] (Redes com Linux)<br />
<br />
==Apresentação do IFSC==<br />
<br />
*[http://www.ifsc.edu.br/estrutura-organizacional-inicio Página do IFSC]<br />
*[https://www.sj.ifsc.edu.br/index.php Página do Câmpus]<br />
<br />
==Apresentação do Curso==<br />
<br />
*[[ISL-FicLinux_(Plano_de_Ensino) | Introdução ao Linux]]<br />
*[[PRL-FicLinux (página) | Projeto de Rede Residencial com o Linux]]<br />
*[[Curso_de_Formação_Continuada_de_Configuração_de_Redes_de_Computadores_Linux | PPC do Curso e Outras Regulamentações]]<br />
<br />
==Cronograma Tentativa==<br />
<br />
Horários: 19h às 22h.<br />
<br />
{| class="wikitable"|<br />
| AULA || DATA || Professor || Conteúdo<br />
|-<br />
| 1 || 12/03/2019 || TIAGO || Programa da Disciplina.Forma de Avaliação. O computador: hardware e software. SO Linux: histórico e distribuições. Ligando/Logando/Desligando a Máquina. Conceitos básico de Sistema de Arquivos e Processos.<br />
|-<br />
| 2 || 14/03/2019 || TIAGO || Gerenciamento de Arquivos I: Operações sobre arquivos e diretórios usando o terminale o Nautilus.<br />
|-<br />
| 3 || 21/03/2019 || TIAGO || Gerenciamento de Arquivos II: continuação Operações sobre arquivos e diretórios. Links Simbólicos, Criação de Arquivo com vi e outros editores.<br />
|-<br />
| 4 || 26/03/2019 || TIAGO || Interfaces Gráficas: X11, Gnome. KDE e outras. Instalação de Programas via Gerenciador de Pacotes.<br />
|-<br />
| 5 || 28/03/2019 || TIAGO || Administração de contas de usuários I<br />
|-<br />
| 6 || 02/04/2019 || TIAGO || Administração de contas de usuários II<br />
|-<br />
| 7 || 04/04/2019 || TIAGO || Permissionamento de Arquivos<br />
|-<br />
| 8 || 09/04/2019 || TIAGO || Gerenciamento de Processos<br />
|-<br />
| 9 || 11/04/2019 || TIAGO || Introdução ao Shell Script<br />
|-<br />
| 10 || 16/04/2019 || TIAGO || Avaliação 1 - Introdução ao Sistema Operacional Linux<br />
|-<br />
| 11 || 09/10/2019 || ERALDO || Introdução a Redes. Conceito de Protocolos. Ferramentas de Rede.<br />
|-<br />
| 12 || 11/10/2019 || ERALDO || Protocolos de Aplicação: exemplo http <br />
|-<br />
| 13 || 16/10/2019 || ERALDO || O DNS como protocolo de Aplicação; Camada de Transporte: protocolo UDP <br />
|-<br />
| 14 || 18/10/2019 || ERALDO || Protocolo TCP. Diferenças dos protocolos de Transporte TCP/UDP. Camada IP e aspectos da configuração da mesma sob o Linux<br />
|-<br />
| 15 || 23/10/2017 || ERALDO || Camada de Enlace/Física. Hubs X Switches. O Papel do Protocolo ARP. Outros serviços/protocolos: Serviço DHCP e NAT<br />
|-<br />
| 16 || 25/10/2017 || ERALDO (TIAGO) || Segmentação Redes IP. Cálculo de subredes. <br />
|-<br />
| 17 || 30/10/2017 || ERALDO || Introdução ao IPV6. Introdução ao Access Point TPLINK N750: configuração da LAN e WAN<br />
|-<br />
| 18 || 01/11/2017 || ERALDO || Serviço SSH no Linux. Acesso a rede WIFI. Conceitos básicos de redes sem fio.<br />
|-<br />
| 19 || 06/11/2007 || ERALDO || Tópicos Adicionais sobre redes no Linux: Configuração Manual X NetworkManager. Relatório Avaliativo 1.<br />
|-<br />
| 20 || 08/11/2017 || ERALDO || Relatório Avaliativo 2<br />
|}<br />
<br />
==Metodologia, Avaliação e Critérios de Aprovação==<br />
<br />
*Aaulas expositivas e aulas práticas no laboratório. Nas aulas práticas serão desenvolvidos exercícios e trabalhos individuais.<br />
*Avaliações individuais: Listas de exercícios com aproveitamento e entregues no prazo. <br />
*Critérios para aprovação: Serão considerados aprovados os alunos que obtiverem conceito final 6 ou superior em cada componente curricular. ATENÇÂO: Possuir no mínimo 75% de presença<br />
<br />
==Bibliografia==<br />
<br />
#Odilson Tadeu Valle<br />
##Administração de redes com Linux: fundamentos e práticas<br />
##Editora IFSC, 2010<br />
#Gleydson Mazioli da Silva<br />
##Guia Foca Linux<br />
##http://www.guiafoca.org/<br />
#Luiz Carlos Lobato Lobo de Medeiros e Wendel Soares<br />
##Formação de suporte técnico PROINFO<br />
##https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo<br />
#Ari Frazão Jr e Marcelo Braga<br />
##Administração de Sistemas Linux<br />
##https://pt.scribd.com/doc/128912228/Administracao-de-Sistemas-Linux<br />
<br />
==Conceitos de Hardware, Software e Firmware==<br />
<br />
*Em informática, o hardware consiste nos equipamentos<br />
**Ex: Computador, teclado, mouse, monitor<br />
*Software é um aplicativo, desenvolvido em uma linguagem de programação<br />
**Ex: Windows, Linux, Mozilla Firefox, Google Chrome<br />
*Firmware é um conjunto de instruções básicas e específicas para um hardware<br />
**Ex: BIOS nos computadores, sistemas de controle das máquinas de lavar, etc.<br />
<br />
==Estrutura de um Computador e Arquitetura de Processadores==<br />
<br />
*Bits, [https://pt.wikipedia.org/wiki/Byte Bytes] e tamanho de memória;<br />
*Representação de Caracteres: [https://pt.wikipedia.org/wiki/ASCII Tabela ASCII];<br />
*O [https://pt.wikipedia.org/wiki/Microprocessador microprocessador], barramentos e memórias semicondutoras: RAM,ROM, E2PROM, FLASH;<br />
*Memórias cache e memórias secundárias;<br />
*[https://pt.wikipedia.org/wiki/Mem%C3%B3ria_virtual Memória Virtual] e Swapping;<br />
*Registradores de 32bits ou 64bits<br />
*Arquitetura [https://pt.wikipedia.org/wiki/X86 x86] / [https://pt.wikipedia.org/wiki/AMD64 x86-64] – presente nos computadores pessoais<br />
*Arquitetura ARM – presente em sistemas embarcados e dispositivos móveis<br />
*Múltiplos núcleos (core)<br />
*Máquinas Virtuas: VirtualBox, UML (User Mode Linux).<br />
<br />
==O papel do Sistema Operacional==<br />
<br />
*O [https://pt.wikipedia.org/wiki/Sistema_operativo SO] é um programa (software) que controla a máquina e a torna utilizável para o usuário;<br />
*Abstrações do Sistema: arquivos e processos;<br />
*Pode ser multitarefa e multiusuário;<br />
*[https://en.wikipedia.org/wiki/Device_driver Driver] de dispositivo<br />
*[https://pt.wikipedia.org/wiki/Multi_boot Múltiplos OS instalados] em um computador. É possível??<br />
<br />
==Sistema de Arquivos==<br />
<br />
*Forma como estão estruturados/organizados os arquivos/dados em uma determinada mídia [https://pt.wikipedia.org/wiki/Sistema_de_ficheiros];<br />
*Um sistema operacional deve saber como acessar e operar sobre este sistema;<br />
*Tipos de sistemas: ext4, NTFS, VFAT32<br />
<br />
==Exemplos de SO==<br />
<br />
*Unix<br />
*Microsoft DOS<br />
*IBM<br />
*Microsoft Windows<br />
*netBSD, freeBSD, openBSD<br />
*Linux<br />
*macOS<br />
*Android<br />
*iOS<br />
<br />
==Histórico do Linux==<br />
<br />
*O início de tudo: UNIX;<br />
*Surgiu em 1991 quando Linus Torvalds, um estudante finlandês, resolveu desenvolver um sistema operacional compatível com a POSIX, por em que pudesse ser executado em arquitetura x86;<br />
*Linux está sob uma licença de software livre e diversas pessoas e empresas contribuem para o desenvolvimento do mesmo.<br />
*E o que é [https://pt.wikipedia.org/wiki/POSIX POSIX]? Define padrões para a interface de programação de aplicações (API) de um OS de forma a manter compatibilidade com o UNIX;<br />
<br />
==Arquitetura do Linux==<br />
<br />
*Ver pg.16 a 19 de [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo]<br />
<br />
==Distribuições==<br />
<br />
Uma distribuição Linux consiste de um kernel Linux e uma coleção de software utilitários e aplicativos de usuário (baseado slides Prof. Emerson)<br />
**Redhat<br />
**Slackware<br />
**Debian<br />
**Ubuntu<br />
**OpenSuse<br />
**Fedora<br />
**CentOS<br />
**Kali<br />
<br />
<br />
Algumas distribuições podem ser executadas diretamente no CD/pendrive<br />
sem a necessidade de fazer sua instalação no disco rígido do computador<br />
<br />
==Distribuições aqui no IFSC SJ==<br />
<br />
*Ubuntu<br />
*Ubuntu Mate (fork do Ubuntu)<br />
*Debian<br />
<br />
==Ligando e Desligando o Sistema Linux==<br />
<br />
*Cuidado ao desligar um OS como o Linux!!! Dados podem ser perdidos.<br />
*Ver [https://pt.wikibooks.org/wiki/Guia_do_Linux/Iniciante%2BIntermedi%C3%A1rio/Introdu%C3%A7%C3%A3o/Ligando_o_computador]<br />
<br />
==O Desktop do Ubuntu - Primeiras Considerações==<br />
<br />
*O Desktop no Ubuntu ver[https://help.ubuntu.com/stable/ubuntu-help/shell-overview.html]<br />
<br />
=AULA 2 - Dia 14/03/2019=<br />
<br />
==Objetivos==<br />
<br />
===PARTE 1===<br />
<br />
*Revisão da aula passada;<br />
*repassar itens não mencionados na aula passada;<br />
**Paginação e Memória [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo pg.19]<br />
**Estrutura do Linux [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo pg.18]<br />
<br />
===PARTE 2===<br />
<br />
*Operações com arquivos e diretórios usando o terminal;<br />
*formato de um comando básico;<br />
*quase tudo no Linux é arquivo: tipos de arquivos, diretórios, arquivos ordinários;<br />
*conceito de sistema de arquivos;<br />
*conceito de referência absoluta e relativa;<br />
*conceito de diretório de entrada, diretório de trabalho;<br />
*mudando de diretório com cd;<br />
*listando diretórios e arquivos com ls;<br />
*vendo o significado de um comando com man;<br />
*criando diretórios com mkdir;<br />
*removendo diretórios e arquivos com rmdir e rm;<br />
*referência com . .. - ~<br />
*criando arquivos ordinários com touch;<br />
*arquivos e diretórios escondidos;<br />
*copiando arquivos;<br />
*movendo e renomeando arquivos;<br />
*vendo a história de comandos com history;<br />
<br />
==Conceito de sistemas de arquivos, arquivos e diretórios==<br />
<br />
* [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Sistemas de Arquivos pg.18]<br />
* [Estrutura básica de diretórios do Sistema Linux]<br />
<br />
==Comandos no Linux==<br />
<br />
* [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Comandos e Interpretador de Comandos no Linux pg.18]<br />
<br />
==Tipos de Arquivos==<br />
<br />
* [https://pt.scribd.com/doc/128912228/Administracao-de-Sistemas-Linux Tipos de Arquivos 12,13 e 14 ]<br />
<br />
==Os comandos de operação sobre arquivos e diretórios==<br />
<br />
*[https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Interpretador de comandos - Comandos Básicos - pg.20 e 21]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_2_FICLinux.pdf Ver lista de exercícios da Aula 2]<br />
<!-- *[https://www.dropbox.com/s/g3xr3wimffde2zm/Aula2_Linux_OperacoesComArquivos_2.pdf Ver lista de exercícios da Aula 3] --><br />
<br />
=AULA 3 - Dia 21/03/2019 (aula com Prof. Eraldo)=<br />
<br />
==Objetivos==<br />
<br />
===PARTE 1===<br />
<br />
*Rever comandos básicos de operações sobre arquivos;<br />
*Usar coringas<br />
*usar opções do comando ls<br />
<br />
===PARTE 2===<br />
<br />
*uso do editor gedit para criar arquivos texto;<br />
*usar comandos cat, more e less para visualizar conteúdos de arquivos.<br />
<br />
===PARTE 3===<br />
<br />
*Criar Links simbólicos<br />
<br />
===Parte 4===<br />
<br />
*Redirecionamento de entradas e saídas;<br />
*Pipes<br />
<br />
==Exercícios para esta aula==<br />
'''Créditos e agradecimentos ao Prof. Eraldo pelo desenvolvimento das listas utilizadas''':<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_3_FICLinux.pdf Mais operações Sobre Arquivos e Diretórios]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_4_FICLinux.pdf Editor Gedit, Link Simbólico]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_5_FICLinux.pdf Editor vi]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_6_FICLinux.pdf Entradas e Saídas]<br />
<br />
=AULA 4 - Dia 26/03/2019=<br />
<br />
==Objetivos==<br />
<br />
===PARTE 1===<br />
<br />
*Revisão geral<br />
<br />
<br />
===PARTE 2===<br />
<br />
*Redirecionamento de entradas e saídas: continuação;<br />
*Pipes<br />
<br />
===PARTE 3===<br />
<br />
*Permissão no acesso a arquivos;<br />
*Owner, grupo e outros<br />
<br />
==Exercícios para esta aula==<br />
<br />
=Referências=<br />
<br />
[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_7_FICLinux.pdf Permissão de Acesso a Arquivos: parte 1]<br />
<br />
[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_8_FICLinux.pdf Permissão de Acesso a Arquivos: parte 2]<br />
<br />
=AULA 5 - Dia 28/03/2019=<br />
<br />
==Objetivos==<br />
<br />
*Revisão e preparação para teste;<br />
*introdução ao gerenciamento de processos;<br />
**conceito de processo<br />
**escalonamento de processos<br />
**PID e PPID<br />
**fork/exec<br />
**espaço de endereçamento de um processo;<br />
**estados de um processo: Running, Stopped, Sleeping, Zombie<br />
<br />
https://www.tecmint.com/linux-process-management/<br />
<br />
==Referências==<br />
<br />
[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_9_FICLinux.pdf Gerenciamento De Processos Parte 1]<br />
[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_10_FICLinux.pdf Gerenciamento De Processos Parte 2]<br />
<br />
[https://www.dropbox.com/s/gm1sv856ailny2e/Aula5_TreinamentoTeste.pdf Treinamento Teste 1]<br />
<br />
=AULA 6 - Dia 02/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*Comandos adicionais de gerenciamento de processos;<br />
*Mudança de prioridade com nice e renice;<br />
*Agendamento de processos com crontab<br />
*Aplicações do crontab: conectividade de rede e backup<br />
*Ferramentas de compactação;<br />
*Execução de comandos inseridos em outros comandos;<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/z1d0itcz9ommhrm/Aula6_Aval1.pdf Avaliação 1]<br />
<br />
=AULA 7 - Dia 04/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*Comandos adicionais de manipulação de arquivos:<br />
**comando grep;<br />
**comando find;<br />
*Gerenciamento de usuários:<br />
**adição e remoção de usuários e grupos<br />
**arquivo sudoers<br />
<br />
<br />
==Exercícios==<br />
<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_11_FICLinux.pdf Comandos Adicionais] <br />
<!--*[https://www.dropbox.com/s/h0v122is4aj9ogr/Aula7_GerenciamentoDeUsuarios_Parte1.pdf Aula 7 - Parte 2]--><br />
<br />
=AULA 8 - Dia 09/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*Introdução ao Shell script<br />
*variáveis<br />
*Comando if<br />
<br />
==Referências==<br />
<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_14_FICLinux.pdf Outros comando gerenciamento de processos]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_12_FICLinux.pdf Shell Parte 1]<br />
<br />
{{collapse top | script DESAFIO (a)}}<br />
<syntaxhighlight lang=c><br />
#!/bin/bash<br />
<br />
FILE="$1"<br />
<br />
if [ ! $# -eq 1 ]; then<br />
echo opa! Algo errado...<br />
echo uso: script parametro<br />
exit<br />
fi<br />
<br />
<br />
if [ -h $FILE ]; then<br />
echo $FILE é um link simbólico<br />
else<br />
echo $FILE não é um link simbólico<br />
fi<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
{{collapse top | script DESAFIO (b)}}<br />
<syntaxhighlight lang=c><br />
<br />
#!/bin/bash<br />
<br />
FILE="$1"<br />
<br />
if [ ! $# -eq 1 ]; then<br />
echo opa! Algo errado...<br />
echo uso: script parametro<br />
exit<br />
fi<br />
<br />
<br />
if [[ -w $FILE && -O $FILE ]]; then<br />
echo Possui permissao de escrita de $FILE<br />
else<br />
echo Colocando permissão de escrita para $FILE<br />
chmod u+w $FILE<br />
echo permissoes adicionadas com sucesso para $FILE ver abaixo<br />
ls -l $FILE<br />
<br />
fi<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
{{collapse top | script DESAFIO (c)}}<br />
<syntaxhighlight lang=c><br />
#!/bin/bash<br />
<br />
FILE1="$1"<br />
FILE2="$2"<br />
<br />
if [ ! $# -eq 2 ]; then<br />
echo opa! Algo errado...<br />
echo uso: script parametro<br />
exit<br />
fi<br />
<br />
if [[ -f $FILE1 && -r $FILE1 ]]; then<br />
echo $1 É regular e possui permissao de leitura<br />
mv $FILE1 $FILE2<br />
echo Mudei o nome de $FILE1 para $FILE2<br />
else<br />
echo $FILE1 não tem permissao...<br />
fi<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
=AULA 9 - Dia 11/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*ainda shell script<br />
*comando for<br />
*comando while<br />
<br />
==Referências==<br />
<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_13_FICLinux.pdf Shell Parte 2]<br />
<br />
=AULA 10 - Dia 16/04/2019=<br />
<br />
*Avaliação da disciplina<br />
<br />
=Tópicos extras=<br />
<br />
==Objetivos==<br />
<br />
*mais alguns tópicos sobre criação de usuários;<br />
*servidores de janelas: X11, <br />
*gerenciadores de janelas e desktops: Gnome, KDE<br />
*instalação de pacotes;<br />
*o Linux e o Software Livre<br />
*avaliação<br />
<br />
==Servidores de Janelas==<br />
<br />
[https://pt.wikipedia.org/wiki/X_Window_System X Windows System]<br />
<br />
[https://en.wikipedia.org/wiki/X_Window_System_protocols_and_architecture Arquitetura do X]<br />
<br />
==Desktops e Geneciadores de Janelas==<br />
<br />
[https://pt.wikipedia.org/wiki/Interface_gr%C3%A1fica_do_utilizador Interfaces Gráficas]<br />
<br />
==Instalando pacotes==<br />
<br />
[https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Ver pg.43 do Formacao-de-Suporte-Tecnico-Proinfo]<br />
<br />
[http://www.hardware.com.br/tutoriais/tutorial-completo-apt-get/ uso do apt-get]<br />
<br />
Exercício: instalar e executar um servidor ssh:<br />
<br />
sudo apt-get update<br />
sudo apt-get install openssh-server<br />
sudo service start ssh<br />
<br />
Acessar o ssh de outra máquina<br />
ssh usuario@numero_ip<br />
<br />
Exportar o display e executar o comando remoto:<br />
export DISPLAY=IP_cliente_ssh:0.0<br />
firefox &<br />
<br />
Conferir se o firefox realmente está se executando (use o ps)<br />
<br />
Remover o pacote ssh server:<br />
<br />
sudo apt-get remove openssh-server<br />
<br />
==Linux = Software Livre==<br />
<br />
[https://pt.wikipedia.org/wiki/Software_livre]<br />
<br />
<br />
<br />
[https://www.novell.com/coolsolutions/feature/1532.html]<br />
<br />
==Onde baixar o Ubuntu==<br />
<br />
[https://www.ubuntu.com/download/desktop Baixar Ubuntu daqui]<br />
<br />
==Sobre o Boot==<br />
<br />
[http://www.rodsbooks.com/linux-uefi/ by Roderick W. Smith]<br />
<br />
[https://www.happyassassin.net/2014/01/25/uefi-boot-how-does-that-actually-work-then/ AdamW on Linux and more]<br />
<br />
==Sobre o Desktop Environment e o Desktop Shell==<br />
<br />
[https://ittutorials.net/linux/ubuntu/desktop-guide/ /desktop-guide]<br />
<br />
==Instalar Ubuntu no Virtual Box==<br />
<br />
[http://www.edivaldobrito.com.br/virtualbox-no-linux/ Instalar VirtualBox no Linux]<br />
<br />
[http://www.bosontreinamentos.com.br/virtualizacao/como-instalar-o-virtualbox-no-windows-para-criacao-de-maquinas-virtuais/ Instalar VirtualBox no Windows]<br />
<br />
[http://www.techtudo.com.br/dicas-e-tutoriais/noticia/2016/04/como-instalar-o-ubuntu-com-o-virtualbox.html Instalar Linux no VirtualBox]<br />
<br />
=AULA 11 - Dia 23/04/2019=<br />
<br />
*Introdução a Redes de Computadores<br />
**Conceito Básicos em Redes e Protocolos<br />
**Ferramentas de Redes<br />
**Exemplo de Protocolo de Aplicação: http<br />
**O processo de encapsulamento<br />
<br />
==Plano de Ensino==<br />
<br />
*[https://wiki.sj.ifsc.edu.br/index.php/PRL-FicLinux_(Plano_de_Ensino) Plano de Ensino]<br />
<br />
<br />
==Laboratório 1 - Ferramentas de Rede e Conceitos Básicos==<br />
<br />
*Familiarização com a infraestrutura dos laboratórios de redes<br />
*Familiarização com ferramentas de rede: ifconfig, ping, traceroute;<br />
*Desenvolver a noção de endereçamentos de rede IP e de endereço de hardware (MAC)<br />
*Desenvolver a noção de rotas em redes IP<br />
*Testar a conectividade IP com ping<br />
<br />
*Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)]<br />
<br />
==Laboratório 2 - Wireshark e encapsulamento==<br />
<br />
*Familiarização com o sniffer de rede WireShark<br />
*Observar o comportamento do ping e se familiarizar com o processo de encapsulamento;<br />
<br />
**Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)]<br />
<br />
==Conceituando Protocolos e Aplicações de Rede==<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/Conceituando%20protocolos.pdf Conceituando protocolos]<br />
<br />
=AULA 12 - Dia 25/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*Protocolos de aplicação: exemplo http<br />
<br />
==Laboratório 4 - Desvendando o HTTP com Wireshark - BÁSICO==<br />
<br />
Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)#Parte_1:_Observando_interfaces_do_sistema_com_ifconfig]<br />
<br />
=AULA 13 - Dia 30/04/2019=<br />
<br />
*Revisão do Conceito de Protocolo ([-] Laboratório 3 - Conceituando protocolos )<br />
*O DNS como protocolo de Aplicação;<br />
*Camada de Transporte: protocolo UDP<br />
<br />
==Revisão dos Conceitos de Protocolo==<br />
<br />
Laboratório 3 - Conceituando protocolos [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)#Parte_1:_Observando_interfaces_do_sistema_com_ifconfig]<br />
<br />
==O DNS como protocolo de Aplicação==<br />
<br />
Laboratório 7 - Serviço de Nomes (DNS) [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)#Parte_1:_Observando_interfaces_do_sistema_com_ifconfig]<br />
<br />
==O Protocolo UDP==<br />
<br />
Laboratório 8 - Desvendando o UDP - Básico <br />
<br />
=AULA 14 - Dia 02/05/2019=<br />
<br />
==Objetivos==<br />
<br />
*Explorar o papel e diferenças dos protocolos de Transporte TCP/UDP<br />
*Explorar a Camada IP e aspectos da configuração da mesma sob o Linux<br />
<br />
<br />
===TCP e UDP===<br />
<br />
*[docente.ifsc.edu.br/odilson/RCO60803/TCP%20controle%20de%20erros.pdf]<br />
*[docente.ifsc.edu.br/odilson/RCO60803/UDP%20Basico.pdf[<br />
<br />
==Camada IP no Linux: Configuração das Interfaces usando ifconfig e ip addr==<br />
<br />
Usando a ferramenta Netkit2, que permite construir redes virtuais com o Linux vamos construir DUAS redes locais interligadas por um roteador. Em cada rede colocaremos dois PCs. As interfaces estarão completamente desconfiguradas:<br />
<br />
<ol><br />
<li><br />
Construir um arquivo texto de nome rede.conf usando o editor de texto gedit.<br />
<code>gedit rede.conf &</syntaxhighlight> <br />
</li><br />
<li><br />
Criar a seguinte topologia:<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=generic<br />
<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
#Definição da Topologia da Rede<br />
<br />
pc1[eth0]=lan0<br />
pc2[eth0]=lan0<br />
<br />
pc3[eth0]=lan1<br />
pc4[eth0]=lan1<br />
<br />
r1[eth0]=lan0<br />
r1[eth1]=lan1<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Executar netkit fazendo (atualize se necessário - pergunte para o professor como fazer):<br />
Aplicativos >> Educativo >> Netkit2 <br />
</li><br />
<li><br />
Carregar o arquivo lab.conf a partir do Netkit2:<br />
<code>File >> Load Only</syntaxhighlight><br />
</li><br />
<li><br />
Visualizar a rede a ser implementada:<br />
<code>File >> Graph</syntaxhighlight><br />
</li><br />
<li> <br />
Executar a configuração:<br />
<code>Network >> Start</syntaxhighlight><br />
</li><br />
<li><br />
Verificar o estado de todas interfaces (se UP ou DOWN) com:<br />
<code>ifconfig -a</syntaxhighlight><br />
<code>ip addr</syntaxhighlight> <br />
Note que nas últimas versões do Linux o comando ip vem sendo recomendado (embora o ifconfig ainda esteja disponível).<br />
</li><br />
<li><br />
Vamos configurar as interfaces. Para tanto vamos assumir que teremos duas sub-redes:<br />
<code>lan0 - endereço da rede 10.10.10.0/24</syntaxhighlight><br />
<code>lan1 - endereço da rede 20.20.20.0/24</syntaxhighlight><br />
A interface eth0 de PC1 receberá o endereço 10.10.10.1/24 e a interface eth0 de PC2 recebera 10.10.10.2/24. A interface do roteador NA lan0 também deve receber um endereço: 10.10.10.254/24:<br />
<br />
No PC1:<br />
<code>ifconfig eth0 10.10.10.1/24</syntaxhighlight><br />
No PC2:<br />
<code>ifconfig eth0 10.10.10.2/24</syntaxhighlight><br />
No R1:<br />
<code>ifconfig eth0 10.10.10.254/24</syntaxhighlight><br />
</li> <br />
<li><br />
Seguindo a mesma lógica configure as máquinas e o roteador na lan1<br />
</li><br />
<li> Um ponto importante a ser lembrado é que quando uma interface é configurada com um número IP, a tabela de roteamento do sistema é alimentada com o número correspondente da rede associada ao número. Isto pode ser observado em TODAS as máquinas, inclusive no roteador:<br />
<code> route -n </syntaxhighlight><br />
ou <br />
<code> ip route </syntaxhighlight><br />
</li><br />
</ol><br />
<br />
==Camada IP no Linux: verificando e configurando rotas - configuração da rota default ==<br />
<br />
<ol><br />
<li> Um ponto importante a ser lembrado é que quando uma interface é configurada com um número IP, a tabela de roteamento do sistema é alimentada com o número correspondente da rede associada ao número. Isto pode ser observado em TODAS as máquinas, inclusive no roteador:<br />
<code> route -n </syntaxhighlight><br />
ou <br />
<code> ip route </syntaxhighlight><br />
Esta informação é importante pois define a entrega DIRETA de pacotes na rede, ou seja, se PC1 quiser enviar um pacote para PC2, esta linha na tabela de roteamento garante que o pacote IP seja despachado diretamente para o PC2 através de um frame ETHERNET endereçado para o MAC do PC1.<br />
</li><br />
<li> Confira os endereços MAC e IP das interfaces dos PC1 e PC2 e anote. Faça um ping no PC1 em direção a PC2.<br />
<code>root@pc1:~# ping 10.10.10.2</syntaxhighlight><br />
</li><br />
<li> Use um capturador de pacotes em modo texto para observar o tráfego na eth0 do PC2. Observe os endereços MAC do Frame Ethernet e os endereços IP do pacote IP.<br />
<code>root@pc2:~# tcpdump -i eth0 -e</syntaxhighlight><br />
ENTÃO? O que se pode concluir? É uma entrega direta ou indireta? <br />
</li><br />
<li> Uma curiosidade. Tente observar o tráfego na interface eth0 do Roteador R1. É possível observar algo? O que se pode concluir? Pare agora o ping e os tcpdumps executados.<br />
</li><br />
<li> Qualquer máquina IP acaba tomando uma decisão de roteamento. O PC1, ao observar que PC2 está na sua própria rede 10.10.10.0/24, entrega diretamente o pacote. E se PC1 tentar entregar para PC3? Faça um ping e observe o que acontece:<br />
<code>root@pc1:~#ping 20.20.20.1</syntaxhighlight><br />
Não deve ter funcionado :-(<br />
Um primeiro problema é que simplesmente a camada IP observa que o endereço não é entrega DIRETA mas não tem informação (linha) na tabela de roteamento dizendo para quem deve ser entregue o pacote. <br />
</li><br />
<li> Vamos acrescentar uma linha na tabela de PC1 dizendo como fazer esta entrega INDIRETA. Usaremos o conceito de gateway default. Ou seja, se não tiver para quem entregar explicitamente, o pacote será entregue para o gateway default:<br />
<code>root@pc1:~# route add default gateway 10.10.10.254</syntaxhighlight><br />
confira o estabelocimento da rota:<br />
<code>root@pc1:~# route -n</syntaxhighlight><br />
tente o ping novamente escutando com o tcpdump na interface eth0 de R1. Ainda não funcionou mas o R1 já recebe os pacotes. Confira o MAC de destino do pacote. Deve ser o MAC do roteador. <br />
</li> <br />
<li><br />
POR QUE NÃO FUNCIONOU: será que R1 não sabe como entregar o pacote para PC3? Confira se o pacote sai de R1 na rede lan1:<br />
<code>root@r1:~# tcpdump -i eth2 -e</syntaxhighlight><br />
</li> <br />
<li><br />
Temos um problema ainda que o nosso roteador Linux NÃO está habilitado a ser roteador. Isto pode ser feito com:<br />
<code>echo 1 > /proc/sys/net/ipv4/ip_forward</syntaxhighlight><br />
</li> <br />
<li> Tente novamente o ping de PC1 para PC3. Ainda não funcionará mas escute a interface eth1 de R1 e a interface eth0 de PC3 e verá que os pacotes do ICMP REQUEST estão chegando. Confira inclusive os MACs envolvidos...<br />
</li><br />
<li><br />
O que estaria faltando ainda para que PC3 responda aos ECHO REQUEST? O problema é de entrega indireta. O PC3 não sabe como entregar pacotes "externos". Acrescente um gateway default.<br />
</li><br />
<li><br />
Exercício adicional com 2 roteadores. Ver manual:<br />
* [http://linux-ip.net/html Guia de Administração da Camada IP no Linux<br />
</li><br />
</ol><br />
<br />
==Exercício: acrescentando uma lan2 com com 2 PCs no roteador==<br />
<br />
Acrescente uma rede 30.30.30.0/24 (lan2) no roteador R1. Acrescente 2 PCs e configure o sistema.<br />
Teste a conectividade entre todos os PCs.<br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
pc5[type]=generic<br />
pc6[type]=generic<br />
<br />
pc7[type]=generic<br />
pc8[type]=generic<br />
<br />
<br />
#Definição da Topologia da Rede<br />
<br />
pc1[eth0]=lan0:ip=10.10.10.1/24<br />
pc1[default_gateway]=10.10.10.254<br />
<br />
pc2[eth0]=lan0:ip=10.10.10.2/24<br />
pc2[default_gateway]=10.10.10.254<br />
<br />
pc3[eth0]=lan1:ip=20.20.20.1/24<br />
pc3[default_gateway]=20.20.20.254<br />
<br />
pc4[eth0]=lan1:ip=20.20.20.2/24<br />
pc4[default_gateway]=20.20.20.254<br />
<br />
pc5[eth0]=lan2:ip=30.30.30.1/24<br />
pc5[default_gateway]=30.30.30.254<br />
<br />
pc6[eth0]=lan2:ip=30.30.30.2/24<br />
pc6[default_gateway]=30.30.30.254<br />
<br />
pc7[eth0]=lan4:ip=40.40.40.1/24<br />
pc7[default_gateway]=40.40.40.254<br />
<br />
pc8[eth0]=lan3:ip=50.50.50.1/24<br />
pc8[default_gateway]=40.40.40.254<br />
<br />
<br />
r1[eth0]=lan0:ip=10.10.10.254/24<br />
r1[eth1]=lan1:ip=20.20.20.254/24<br />
r1[eth2]=lan2:ip=30.30.30.254/24<br />
r1[eth3]=lan3:ip=50.50.50.253/24<br />
r2[eth1]=lan3:ip=50.50.50.254/24<br />
r2[eth0]=lan4:ip=40.40.40.254/24<br />
<br />
r2[route]=10.10.10.0/24:gateway=50.50.50.253<br />
<br />
</syntaxhighlight><br />
<br />
=AULA 15 - Dia 7/05/2019=<br />
<br />
*Hubs X Switches. O Papel do Protocolo ARP<br />
<br />
<br />
*Serviço DHCP e NAT<br />
[-] Laboratório 16 - Sub-redes e Roteamento Estático em Redes <br />
<br />
==Hubs, Switches. Protocolo ARP==<br />
<br />
[Laboratório 17 - Tecnologia de Enlace Ethernet]<br />
<br />
==Serviço DHCP==<br />
<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IP_DHCP_NAT.pdf DHCP e NAT]<br />
<br />
Construir uma rede simular a aula anterior mas deixar PC1 e PC2 desconfigurados. Criar uma máquina para atuar como servidor DHCP. <br />
<br />
<ol><br />
<li><br />
Editar o arquivo de configuração do dhcp server:<br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=gateway #já habilitado para forward<br />
<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
pcdhcp[type]=generic<br />
<br />
<br />
#Definição da Topologia da Rede<br />
<br />
pc1[eth0]=lan0 #desconfigurada...<br />
<br />
pc2[eth0]=lan0:ip=10.10.10.2/24<br />
pc2[default_gateway]=10.10.10.254<br />
<br />
pcdhcp[eth0]=lan0:ip=10.10.10.3/24<br />
pcdhcp[default_gateway]=10.10.10.254 <br />
<br />
pc3[eth0]=lan1:ip=20.20.20.1/24<br />
pc3[default_gateway]=20.20.20.254<br />
<br />
pc4[eth0]=lan1:ip=20.20.20.2/24<br />
pc4[default_gateway]=20.20.20.254<br />
<br />
<br />
r1[eth0]=lan0:ip=10.10.10.254/24<br />
r1[eth1]=lan1:ip=20.20.20.254/24<br />
<br />
</syntaxhighlight><br />
</li><br />
<li> No server estabelecer a configuração desejada:<br />
<br />
nano /etc/dhcp/dhcpd.conf<br />
<br />
com:<br />
<br />
<code><br />
<br />
subnet 10.10.10.0 netmask 255.255.255.0 {<br />
range 10.10.10.10 10.10.10.50;<br />
option routers 10.10.10.254;<br />
option broadcast-address 10.10.10.255;<br />
default-lease-time 600;<br />
max-lease-time 7200;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
</li><br />
<li><br />
Rodar o servidor DHCP na máquina pc_dhcp:<br />
<code><br />
/usr/sbin/dhcpd -q -4 -pf /run/dhcp-server/dhcpd.pid -cf /etc/dhcp/dhcpd.conf eth0<br />
</syntaxhighlight><br />
</li><br />
<li><br />
No cliente (PC1) fazer:<br />
<code><br />
dhclient -v eth0<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Usando o ifconfig e route confira se o PC1 está completamente configurado. Faça teste com o ping<br />
</li><br />
<li> Rode o tcpdump na eth0 de r1 para "verificar" os pacotes DHCP:<br />
<code><br />
tcpdump -i eth0<br />
</syntaxhighlight><br />
</li><br />
<li> Repetir a operação no PC2. Baixe a interface antes:<br />
<code><br />
ifconfig eth0 down<br />
dhclient -v eth0<br />
</syntaxhighlight><br />
</li><br />
</ol><br />
<br />
==O NAT==<br />
<br />
Vamos tentar elaborar um laboratório usando o NAT MASQUERADE<br />
https://www.karlrupp.net/en/computer/nat_tutorial<br />
<br />
Construir uma rede com 3 LANs e 2 roteadores como na aula passada. Executar o APACHE em uma máquina da lan3 (exemplo PC4). Não colocar rotas para lan0 em r2. Desta forma PC1 não deve pingar em PC4. <br />
<br />
<code><br />
LAN0 <-R1-> LAN1 <-R2 -> LAN3<br />
</syntaxhighlight><br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
pc1[type]=generic<br />
apache[type]=generic<br />
<br />
<br />
pc1[eth0]=lan0:ip=10.10.10.1/24<br />
pc1[default_gateway]=10.10.10.254<br />
<br />
<br />
r1[eth0]=lan0:ip=10.10.10.254/24<br />
r1[eth1]=lan1:ip=20.20.20.254/24<br />
r1[route]=30.30.30.0/24:gateway=20.20.20.253<br />
<br />
r2[eth0]=lan1:ip=20.20.20.253/24<br />
r2[eth1]=lan2:ip=30.30.30.254/24<br />
<br />
apache[eth0]=lan2:ip=30.30.30.1/24<br />
apache[default_gateway]=30.30.30.254<br />
</syntaxhighlight><br />
<br />
<ol><br />
<li> Rodar o apache em PC4:<br />
<code> /etc/init.d/apache2 start </syntaxhighlight><br />
</li><br />
<li> Testar se o Apache é acessível a partir de PC3<br />
<code>lynx END_PC3 </syntaxhighlight><br />
<li><br />
Em R1 fazer:<br />
<code>iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE</syntaxhighlight><br />
</li><br />
<li> Monitorar os pacotes que chegam e saem da eth0 de PC4.<br />
</li><br />
<li> Fazer em PC1:<br />
lynx END_PC4 #endereço de PC4.<br />
O que se pode concluir?<br />
</li><br />
<br />
</ol><br />
<br />
=AULA 16 - Dia 09/05/2019=<br />
*Endereçamento IPv4.<br />
*Exercícios segmentação Redes. <br />
<br />
===Objetivos===<br />
*Compreender endereçamento IPv4.<br />
*Compreender o processo de alocação de faixas de IPs.<br />
*Compreender e manipular os números IPs.<br />
*Compreender e manipular as máscaras de rede.<br />
*Proporcionar ao aluno uma visão prática de roteamento IP.<br />
<br />
===Fonte Básica===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IP_DHCP_NAT.pdf DHCP e NAT]<br />
*[http://www.davidc.net/sites/default/subnets/subnets.html Cálculo de sub-redes]<br />
<br />
===Roteiro===<br />
<br />
#Baseado no arquivo exemplo abaixo, crie um arquivo de configuração para o NetKit que implemente sua proposta. O arquivo deve contemplar todas as configurações necessárias para o perfeito funcionamento da rede, ou seja, ao carregar o arquivo todos os hosts deverão ser capazes de "pingar" uma ao outro. <br />
##Faça testes de conectividade entre os hosts.<br />
##Demonstre para o professor o perfeito funcionamento de sua rede.<br />
*O arquivo de configuração do Netkit abaixo, é a definição para o funcionamento da simulação da rede apresentada na Figura 2. Falta adicionar as rotas.<br />
<br />
[[Arquivo:DynamicRoutingTriangle.png |thumb | 400px| Figura 2 - Rede exemplo]]<br />
<br />
<code><br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=link0:ip=192.168.0.1/24<br />
pc2[eth0]=link1:ip=192.168.1.1/24<br />
pc3[eth0]=link2:ip=192.168.2.1/24<br />
<br />
# Default gateways definitions<br />
pc1[default_gateway]=192.168.0.254<br />
pc2[default_gateway]=192.168.1.254<br />
pc3[default_gateway]=192.168.2.254<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
r3[type]=gateway<br />
<br />
# Routers' interfaces to local networks<br />
r1[eth0]=link0:ip=192.168.0.254/24<br />
r2[eth0]=link1:ip=192.168.1.254/24<br />
r3[eth0]=link2:ip=192.168.2.254/24<br />
<br />
# Network "backbone" links<br />
r1[eth1]=backbone0:ip=10.0.0.1/30<br />
r1[eth2]=backbone1:ip=10.0.1.1/30<br />
<br />
r2[eth1]=backbone0:ip=10.0.0.2/30<br />
r2[eth2]=backbone2:ip=10.0.2.1/30<br />
<br />
r3[eth1]=backbone1:ip=10.0.1.2/30<br />
r3[eth2]=backbone2:ip=10.0.2.2/30 <br />
<br />
# Routes definition<br />
r1[route]=192.168.2.0/24:gateway=10.0.1.2<br />
r1[route]=192.168.1.0/24:gateway=10.0.0.2<br />
r1[route]=10.0.2.0/30:gateway=10.0.0.2<br />
<br />
r2[route]=192.168.0.0/24:gateway=10.0.0.1 <br />
r2[route]=192.168.2.0/24:gateway=10.0.2.2<br />
r2[route]=10.0.1.0/30:gateway=10.0.2.2<br />
<br />
r3[route]=192.168.0.0/24:gateway=10.0.1.1<br />
r3[route]=192.168.1.0/24:gateway=10.0.2.1<br />
r3[route]=10.0.0.0/30:gateway=10.0.2.1<br />
</syntaxhighlight><br />
<br />
===Exercícios Extras (resolvidos)===<br />
*[[Arquivo:exercicios_CIDR.pdf]]<br />
<br />
===Referencia===<br />
*[http://www.davidc.net/sites/default/subnets/subnets.html Link Calculador Online de Subnets]<br />
<br />
=AULA 17 - Dia 14/05/2019=<br />
<br />
*Finalização do Laboratório do NAT<br />
*Laboratório de Introdução ao IPV6<br />
*Introdução ao Access Point TPLINK N750: configuração da LAN e WAN<br />
<br />
==LAboratório de Introdução ao IPv6==<br />
<br />
===Material de REferência===<br />
<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IPv6.pdf IPv6]<br />
<br />
===Roteiro de atividades sobre o IPv6===<br />
<br />
A figura abaixo apresenta o diagrama esquemático da rede a ser montada/analisada. Observe que todos os IPv6 ''Global Unicast'' já estão definidos na mesma, são esses IPs que utilizaremos em nosso experimento.<br />
<br />
[[Arquivo:Diagrama_rede_IPv6.jpg]]<br />
<br />
#Crie em seu computador um arquivo com nome '''/home/aluno/IPv6.conf''', com o seguinte conteúdo: <syntaxhighlight lang=bash><br />
#Ligacao das maquinas nos dominios de colisao<br />
#Duas pequenas redes interligadas pelo backbone<br />
<br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=link0:ipv6=2001:bcc:faca:1::101/64<br />
pc2[eth0]=link1:ipv6=2001:bcc:cafe:1::102/64<br />
pc3[eth0]=HUB1:ipv6=2001:bcc:1f0:1::103/64<br />
pc4[eth0]=HUB1<br />
<br />
#Default Gateways definitions<br />
pc1[route]=default6:gateway=2001:bcc:faca:1::1<br />
pc2[route]=default6:gateway=2001:bcc:cafe:1::1<br />
pc3[route]=default6:gateway=2001:bcc:1f0:1::1<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
#Routers interfaces definitions<br />
r1[eth0]=backbone0:ipv6=2001:db8:dead:1::1/64<br />
r1[eth1]=link0:ipv6=2001:bcc:faca:1::1/64<br />
r1[eth2]=link1:ipv6=2001:bcc:cafe:1::1/64<br />
<br />
r2[eth0]=backbone0:ipv6=2001:db8:dead:1::2/64<br />
r2[eth1]=HUB1:ipv6=2001:bcc:1f0:1::1/64<br />
<br />
#Routers definitions<br />
r1[route]=2001:bcc:1f0:1::0/64:gateway=2001:db8:dead:1::2<br />
r2[route]=2001:bcc:faca:1::0/64:gateway=2001:db8:dead:1::1<br />
r2[route]=2001:bcc:cafe:1::0/64:gateway=2001:db8:dead:1::1<br />
</syntaxhighlight><br />
#Tenha certeza que o Netkit2 estja atualizado: General >> Update.<br />
#Rode o NetKit em seu computador. Em um terminal digite: <syntaxhighlight lang=bash><br />
netkit2 & </syntaxhighlight><br />
#No menu '''File''' - '''Load and Run''', procure o arquivo '''/home/aluno/IPv6.conf''' e clique em OK. Abrirá uma janela com 6 abas, onde cada uma delas é um terminal de configuração do respectivo equipamento: '''pc1-4''' ou '''r1-2'''.<br />
#Observe que o '''pc4''' não está com sua interface configurada.<br />
#Ao clicar no menu '''File''' - '''Graph''', pode-se ter uma visão da rede a ser simulada e conferir se é equivalente ao diagrama proposto.<br />
#Faça um '''ping6''' entre o '''pc1''' ao '''pc3''': <syntaxhighlight lang=bash><br />
ping6 -c4 2001:bcc:1f0:1::103 </syntaxhighlight><br />
#Faça um '''ping6''' entre o '''pc1''' e '''pc2'''.<br />
#No '''pc4''' use o seguinte comando para adicionar o endereço IPv6 à interface de rede: <syntaxhighlight lang=bash><br />
ip addr add 2001:bcc:1f0:1::104/64 dev eth0 </syntaxhighlight><br />
#No '''pc4''', acrescente o ''default gateway'' com o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add default via 2001:bcc:1f0:1::1 dev eth0 </syntaxhighlight><br />
#No '''pc1''' use o seguinte comando para verificar como ficou a configuração dos endereços da interface de rede. O resultado é similar ao apresentado pelo comando '''ifconfig''': <syntaxhighlight lang=bash><br />
ip addr show dev eth0 </syntaxhighlight><br />
#Todo o roteamento está pronto, mas caso desejássemos poderíamos acrescentar rotas com comando similares aos já utilizados. Por exemplo, no '''r1''', para adicionar uma rota estática para a rede dos '''pc3''' e '''pc4''' utilizaríamos o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add 2001:bcc:1f0:1::/64 via 2001:db8:dead:1::2 dev eth0 </syntaxhighlight><br />
#Confira as rotas estabelecidas em todos os ''hosts'' com o comando abaixo. <br />
##São coerentes com os dados apresentados no diagrama acima?<syntaxhighlight lang=bash><br />
ip -6 route show </syntaxhighlight><br />
#No '''pc1''' use os seguintes comandos para ver a rota para alguns vizinhos: <syntaxhighlight lang=bash><br />
traceroute6 2001:bcc:1f0:1::103<br />
traceroute6 2001:bcc:1f0:1::104 </syntaxhighlight><br />
#*Anote as rotas.<br />
#Deixe um '''ping6''' entre o '''pc1''' ao '''pc3''' rodando: <syntaxhighlight lang=bash><br />
ping6 2001:bcc:1f0:1::103 </syntaxhighlight><br />
<br />
==Introdução ao Roteador-AP da TP-Link==<br />
<br />
Ver manual https://www.tp-link.com/us/support/download/tl-wdr4300/<br />
<br />
===Configuração Básica===<br />
<br />
Seguir as instruções do professor para a seguinte configuração:<br />
<br />
#Retirar o plugue cabo ethernet que liga o PC do Lab a rede do IFSC. Conectar o PC a uma das portas LAN do AP;<br />
#Conectar a WAN do AP ao Lab. do IFSC;<br />
#Em um terminal do PC aplique o comando:<br />
sudo dhclient eth0<br />
#No browser do PC acesse o AP colocando o endereço:<br />
http://tplinklogin.net<br />
#Entrar com user admin e senha admin<br />
#Configurar a WAN para DHCP (IP dinâmico)<br />
#Configurar a LAN para DHCP na faixa 192.168.0.10 a 192.168.0.100<br />
#Usar uma máquina virtual para testar a aquisição do IP:<br />
pc1[type]=generic<br />
pc1[eth0]=uplink:bridge=eth0<br />
<br />
DESAFIO 1: Elabore um experimento para mostrar que a LAN do AP funciona como um switch.<br />
Sugestão: Use uma máquina adicional colocada em uma porta do AP.<br />
<br />
DESAFIO 2: Elabore um experimento para mostrar como o NAT funciona no AP. Se inspire no experimento realizado sobre o NAT.<br />
<br />
=AULA 18 - Dia 16/05/2019=<br />
<br />
==Objetivos==<br />
<br />
<br />
PARTE 0 - Exercício de Revisão<br />
<br />
PARTE 1 - Serviços de rede sobre o Linux<br />
<br />
*serviço SSH no Linux<br />
<br />
PARTE 2 - Acesso a rede WIFI<br />
<br />
*conceitos básicos de redes sem fio: pg.103 de [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo]<br />
*configuração da WIFI no Access Point e Acesso via Linux<br />
<br />
===PARTE 0===<br />
<br />
Considere a rede abaixo definida pelo arquivo do netkit. Configure as redes com os seguintes prefixos:<br />
<br />
*lan0: 50.50.50.0/24<br />
*lan1: 60.60.60.0/24<br />
*lan2: 70.70.70.0/24<br />
<br />
O pc2dhcp deve ser configurado como servidor DHCP e deverá liberar IPs na faixa de 50.50.50.100/24 a 50.50.50.200/24. Todos os PCs receberão IP estáticos com exceção do PC1 que deverá receber dinamicamente o endereço. Toda a configuração deve ser realizada manualmente.<br />
<br />
Teste a conectividade entre todos os PCs. Usando o tcpdump demonstre que quando PC2 faz um ping em PC4 a entrega será indireta. Demonstre usando o MAC address das máquinas como apoio. Chame o professor para demonstrar.<br />
<br />
ALGUNS COMANDOS NOTÁVEIS:<br />
<br />
ifconfig<br />
ifconfig eth0 10.10.10.1/24<br />
route -n<br />
route add default gw 200.10.1.254<br />
route del -net 200.10.1.0/24 gw 200.10.2.1<br />
route add -net 200.10.1.0/24 gw 200.10.2.1<br />
<br />
tcpdump -i eth1 -n -e<br />
<br />
<code><br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2dhcp[type]=generic<br />
<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=lan0<br />
pc2dhcp[eth0]=lan0<br />
<br />
pc3[eth0]=lan1<br />
<br />
pc4[eth0]=lan2<br />
<br />
r1[eth0]=lan0<br />
r1[eth1]=lan1<br />
<br />
r2[eth0]=lan1<br />
r2[eth1]=lan2<br />
</syntaxhighlight><br />
<br />
Solução:<br />
R1:<br />
ifconfig eth0 50.50.50.254/24<br />
ifconfig eth1 60.60.60.254/24<br />
route add -net 70.70.70.0/254 gw 60.60.60.253<br />
R2:<br />
ifconfig eth1 70.70.70.254/24<br />
ifconfig eth0 60.60.60.253/24<br />
route add -net 50.50.50.0/24 gw 60.60.60.254<br />
PC2DHCP:<br />
ifconfig eth0 50.50.50.2/24<br />
route add default gateway 50.50.50.254<br />
configurar server: nano /etc/dhcp/dhcpd.conf<br />
# A slightly different configuration for an internal subnet.<br />
subnet 50.50.50.0 netmask 255.255.255.0 {<br />
range 50.50.50.100 50.50.50.200;<br />
# option domain-name-servers ns1.internal.example.org;<br />
# option domain-name "internal.example.org";<br />
option routers 50.50.50.254;<br />
option broadcast-address 50.50.50.255;<br />
default-lease-time 600;<br />
max-lease-time 7200;<br />
}<br />
<br />
/usr/sbin/dhcpd -q -4 -pf /run/dhcp-server/dhcpd.pid -cf /etc/dhcp/dhcpd.conf eth0<br />
PC3:<br />
ifconfig eth0 60.60.60.1/24<br />
route add default gw 60.60.60.254 #note que poderia ser para o outro roteador (R2)<br />
PC4:<br />
ifconfig eth0 70.70.70.1/24<br />
route add default gw 70.70.70.254<br />
PC1:<br />
dhclient eth0 -v<br />
<br />
==Serviço SSH==<br />
<br />
O Serviço SSH se utiliza do modelo cliente-servidor. Deve-se executar um servidora ssh na máquina que permitirá o acesso remoto.<br />
Um cliente a partir de uma outra máquina poderá logar remotamente usando um cliente ssh ou poderá fazer outras operações, tipo cópia remota<br />
de arquivos.<br />
<br />
===ETAPA 1 - Rodando o servidor SSH===<br />
*Baseado no Material do Prof.Odilson Valle<br />
<br />
No Ubuntu server:<br />
<ol><br />
<li><br />
<code>sudo su</syntaxhighlight><br />
<code>apt-get update</syntaxhighlight><br />
<code>apt-get install ssh</syntaxhighlight> O SSH já estará funcionando normalmente.<br />
Para configurações extras deve-se editar o arquivo /etc/ssh/sshd_config e acrescentar, por exemplo:<br />
*X11Forwarding yes (no) ### habilita/desabilita acesso com ambiente gráfico remoto<br />
*AllowUsers Fred Wilma ### Libera o acesso somente para os usuários Fred e Wilma<br />
*DenyUsers Dino Pebbles ### Bloqueia o acesso aos usuários Dino e Pebbles e libera para os demais usuários<br />
*AllowGroups admin ### Libera o acesso somente para o grupo admin.<br />
</li><br />
<li><br />
Após modificar o arquivo de configuração deve-se reiniciar o serviço: <code>service ssh restart</syntaxhighlight><br />
</li><br />
<li><br />
Criar um usuário na máquina servidora:<br />
<code>adduser alien</syntaxhighlight><br />
</li><br />
<li><br />
Logar como alien:<br />
<code>su alien</syntaxhighlight><br />
</li><br />
</ol><br />
<br />
===ETAPA 2 - Logando remotamente===<br />
<br />
<ol><br />
<li><br />
Para acessar o servidor basta digitar em um terminal: <br />
<code>ssh alien@ip_do_servidor. </syntaxhighlight> Será solicitado a senha.<br />
</li><br />
<li><br />
Confira que está "dentro" da máquina remota:<code>hostname</syntaxhighlight><br />
</li><br />
<li><br />
Confira os arquivos do diretório corrente:<code>ls -l</syntaxhighlight><br />
</li><br />
</ol><br />
<br />
<br />
===ETAPA 3 - Cópia Remota de aquivos===<br />
<br />
#Na máquina hospedeira/cliente, EM OUTRO TERMINAL, criar um arquivo qualquer usando um editor de texto:<code>gedit teste.txt &</syntaxhighlight><br />
#Envie o arquivo para a máquina servidora: <code>scp teste.txt alien@IP_MAQUINA_SERVIDORA:./</syntaxhighlight><br />
#No terminal onde está logado remotamente confira se o arquivo está copiado: <code>ls -l</syntaxhighlight><br />
#Mude o nome do arquivo: <code>mv teste.txt alfat.txt</syntaxhighlight><br />
#No terminal da máquina cliente traga novamente o arquivo: <code>scp alien@IP_MAQUINA_SERVIDORA:./alfa.txt .</syntaxhighlight><br />
#Confira se o arquivo foi copiado corretamente: <code>ls -l</syntaxhighlight><br />
<br />
==PARTE 2 - Configuração do Access Point na rede de 2.4Ghz==<br />
<br />
#Entrar na configuração do AP conforme aula anterior.<br />
#Conectara a WAN do AP na rede do laboratório e o PC em uma porta da LAN do AP.<br />
#Configurar a WAN para IP dinâmico.<br />
#Configurar a rede WIreless 2.4 Ghz:<br />
##Nome SSID: nome FIC-NomeAluno<br />
##Configurar canal AUTO e channel width para AUTO<br />
##Habilite o broadcast da rede.<br />
#Configurar segurança (Wireless Security) para WPA versão Automática, Criptografia AES e password ABCDEF<br />
#Configurar o DHCP na LAN para distribuir endereços entre 192.168.0.100 e 192.168.0.200<br />
#Salve as configurações<br />
#Reboote o roteador<br />
<br />
==Acessando a rede de dispostivo Celular==<br />
<br />
#Teste o acesso a rede a partir de um celular. No Androi ligue e desligue o wifi. Deve aparecer a lista de dispositivos.<br />
<br />
==Habilitando Filtros por MAC==<br />
<br />
*Na configuração da WLAN entre em Wireless MAC Filtering<br />
*Em Filtering Rules coloque Deny (negar)<br />
*Adicione um terminal que deseja bloquear o acesso. Utilize o MAC do seu celular (veja em configurações do telefone ou anote na opção Wireless Statistics)<br />
*Habilite o Filtro e tente se conectar<br />
<br />
OBS: Este filtro é interessante para ter maior segurança na rede, garantindo que somente dispositivos gabilitados possam acessá-la.<br />
<br />
==Coloque no ar a rede 5Ghz==<br />
<br />
Repita o procedimento da rede de 2.4Ghz e coloque-a no ar.<br />
<br />
Teste a conectividade com o celular.<br />
<br />
<br />
<br />
=AULA 19 - Dia 21/05/2019=<br />
<br />
==Objetivos==<br />
<br />
*Tópicos Adicionais sobre redes no Linux: Configuração Manual X NetworkManager<br />
**Opções de Acesso a Internet: ADSL, Cabo<br />
**Sistema de Arquivos em Rede: Samba Server<br />
*Relatório de Avaliação 1<br />
*Opções de Extensão da Rede Wireless<br />
<br />
==Tópicos Adicionais sobre redes no Linux==<br />
<br />
===Configuração da Rede no Linux - o NetworkManager===<br />
<br />
Ao longo do curso estudamos vários comandos para ver e modificar parâmetros de rede. Entretanto, em uma instalação padrão de um sistema Linux Ubuntu vamos verificar que existe um serviço de suporte a estas configurações que permite configurar interfaces graficamente e reconectar/escolher uma rede. Trata-se do NetworkManager. Ver alguns detalhes aqui [https://www.hardware.com.br/dicas/entendendo-networkmanager.html] e aqui[https://wiki.debian.org/pt_BR/NetworkManager]. Este serviço tenta fornecer a melhor conectividade possível usando as interfaces disponíveis. O serviço é composto por:<br />
<br />
*um processo do sistema (roda como serviço) monitorando constantemente as interfaces;<br />
*uma applet para interação com o usuário (canto direito da interface);<br />
<br />
O NetworkManager vai ignorar as configurações das interfaces realizadas em /etc/network/interfaces<br />
<br />
Teste o uso do NetworkManager. Clique no topo do desktop a direita e inspecione as interfaces disponíveis.<br />
<br />
Em algumas situações pode ser desejável desabilitar o NetworkManager. Na linha de comando pode ser executado:<br />
<br />
sudo service network-manager stop<br />
<br />
===Configurando interfaces de forma manual ===<br />
<br />
TEXTO baseado nas anotações do Prog.Marcelo Sobral:<br />
<br />
O arquivo ''/etc/network/interfaces'' contém declarações para configurar as interfaces de rede. Um exemplo de configuração básica contida nesse arquivo pode ser vista a seguir:<br />
<br />
<syntaxhighlight lang=text><br />
auto lo eth0<br />
iface lo inet loopback<br />
iface eth0 inet dhcp<br />
</syntaxhighlight><br />
<br />
Esse exemplo pode ser interpretado assim:<br />
* ''Linha 1'': declara que as interfaces ''lo'' e ''eth0'' devem ser ativadas automaticamente no boot. Se uma interface não aparecer em uma declaração como esta, então ela não será ativada. OBS: interface ativadas desta forma NÃO são controladas pelo ''NetworkManager''.<br />
* ''Linha 2'': configura a interface ''lo'' como sendo do tiupo ''loopback''. Essa é uma interface especial criada puramente em software (uma interface de rede virtual), usada para comunicação entre processos de um mesmo computador.<br />
* ''Linha 3'': configura a interface ''eth0'' de forma dinâmica usando [[GER-2010-1#DHCP|DHCP]]. A configuração de rede é solicitada usando a própria rede. Ness ecaso, deve existir algum equipamento ou computador nessa rede que seja um servidor DHCP, capaz de responder com uma mensagem contendo a configuração de rede a ser utilizada.<br />
<br />
<br />
O exemplo anterior é bastante simplificado, uma vez que a configuração de rede de fato é obtida dinamicamente com DHCP. Isso pode ser suficiente para computadores usados somente para acesso a Internet, mas não para computadores que sejam servidores. Nesse caso, é melhor definir uma configuração de rede estática, como mostrado a seguir:<br />
<br />
<syntaxhighlight lang=text><br />
auto lo eth0<br />
iface lo inet loopback<br />
iface eth0 inet static<br />
address 172.18.80.251<br />
netmask 255.255.128.0<br />
gateway 172.18.0.254<br />
dns-nameservers 191.36.8.2 191.36.8.3<br />
</syntaxhighlight><br />
<br />
<br />
A diferença em relação ao caso anterior está na declaração da interface ''eth0''. Ao invés de configurá-la com ''DHCP'', declararam-se todas as informações de rede. Assim, essa interface sempre será ativada com essas informações configuradas. No exemplo apresentado, as configurações de rede são:<br />
* ''address 172.18.80.251'': endereço IP da interface<br />
* ''netmask 255.255.128.0'': máscara de rede<br />
* ''gateway 172.18.0.254'': endereço do gateway (ou roteador ''default'')<br />
* ''dns-nameservers 191.36.8.2 191.36.8.3'': servidores DNS a serem utilizados (podem-se especificar um ou mais endereços IP)<br />
<br />
O [http://manpages.ubuntu.com/manpages/trusty/en/man5/interfaces.5.html manual do arquivo /etc/network/interfaces] apresenta muitos outros detalhes sobre possíveis configurações de rede.<br />
<br />
Antes da alteração de configuração de uma interface é interessante desativá-la:<br />
ifdown eth0<br />
Alterar o arquivo /etc/network/interfaces<br />
<br />
E na sequência ativá-la novamente:<br />
ifup eth0<br />
ou<br />
sudo /etc/init.d/networking restart<br />
<br />
O comando ifup vai consultar o arquivo e alterar as configurações. Indiretamente, o script networking também usa o ifup para ativar as configurações (e todas demais que forem realizadas).<br />
<br />
==Relatório Avaliativo 1==<br />
<br />
Criar um arquivo no OpenOffice nomeando-o SeuNomeSemEspaco-FICLinux-2019-A1<br />
<br />
Copiar e responder as questões abaixo:<br />
<br />
1.Faça um ifconfig na interface eth0. Cole um recorte da tela no espaço abaixo e faça um texto indicando qual o endereço de hardware associado a esta interface, qual o endereço IPv4 e qual a máscara de subrede.<br />
<br />
<br />
2.Faça um experimento usando o ping e o wireshark mostrando como o DNS atua para resolver o nome que está sendo "pingando". Informe em texto abaixo qual o IP do servidor DNS local e qual o IP do site que está sendo "pingado".<br />
<br />
<br />
3,Execute o laboratório do Netkit da forma e cole abaixo a figura da rede fornecida pelo netkit:<br />
<code><br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
<br />
# Hosts' interfaces to local routers<br />
<br />
r1[eth0]=lan0<br />
r1[eth1]=lan1<br />
<br />
pc1[eth0]=lan0<br />
pc2[eth0]=lan0<br />
pc3[eth0]=lan1<br />
</syntaxhighlight><br />
<br />
<br />
4.Configure todas as interfaces dos PC usando para lan0 o prefixo 50.50.50.0/24 e para lan1 use no lugar de 50 o dia de seu nascimento.<br />
Cole uma tela mostrando PC1 pingando PC3. <br />
<br />
5.Informe abaixo o MAC da eth0 do roteador.<br />
<br />
6.Usando o tcpdump na eth0 do roteador mostre que a entrega é indireta.<br />
<br />
==Estendendo a rede através da LAN usando segundo AP e WAN==<br />
<br />
Conecte um segundo AP (WAN do segundo AP a LAN do primeiro AP). Teste a conectividade colocando uma máquina Linux na LAN do segundo AP.<br />
Esta configuração deve funcionar mas impõe um overhead adicional devido ao NAT realizado duas vezes... <br />
<br />
DESAFIO: mostrar que o NAT está sendo duplicado.<br />
<br />
[[Arquivo:WLAN-2PAs-viaWAN.png]]<br />
<br />
==Estendendo a rede através da LAN usando segundo AP e LAN==<br />
<br />
Discuta com o colega ao lado e pense como poderia conectar o segundo AP via LAN. Uma configuração adicional será necessária.<br />
<br />
==Estendendo a rede através do Wireless (WDS)==<br />
<br />
Estude no manual como poderia estender a rede Sem Fio usando conexão via WDS.<br />
<br />
=AULA 20 - Dia 18/04/2019=<br />
<br />
*Tópicos Adicionais sobre redes no Linux:<br />
**Opções de Acesso a Internet: ADSL, Cabo<br />
**Sistema de Arquivos em Rede: Samba Server (http://www.guiafoca.org/cgs/guia/avancado/ch-s-samba.html)<br />
*Relatório Avaliativo 2<br />
<br />
==Relatório Avaliativo==<br />
<br />
===PARTE 1=== <br />
<br />
Usando a configuração abaixo do netkit2 e uma máquina Virtualbox devidamente configurada implementar a configuração abaixo:<br />
<br />
ATENÇÂO: Vamos substituir a VirtualBox por uma máquina Netkit executada em OUTRO PC com a configuração:<br />
<br />
INSTRUÇÔES para virtual box:<br />
*colocar rede como bridge<br />
*desabilitar o network manager<br />
sudo service network-manager stop<br />
*baixar a interface<br />
sudo ifconfig enp0s3 down<br />
*reconfigurar a interface (usar o endereço do seu grupo)<br />
sudo ifconfig enp0s3 50.50.50.11/24<br />
*colocar a rota direta (que se perdeu) (usar o endereço do seu grupo)<br />
sudo route add -net 50.50.50.0/24 dev enp0s3<br />
*colocar gateway default (usar o endereço do seu grupo)<br />
sudo route add default gateway 50.50.50.1<br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
<br />
pc1[type]=generic<br />
pc1[eth0]=uplink:bridge=eth0:ip=dhcp<br />
<br />
</syntaxhighlight><br />
<br />
<br />
[[Arquivo:Aval2-Parte1-FICLinux2019-2.png]]<br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
pc1[type]=generic<br />
<br />
pc1[eth0]=lan1<br />
<br />
r1[eth0]=uplink:bridge=eth0:ip=VER COM PROFESSOR<br />
r1[eth1]=lan2<br />
<br />
r2[eth0]=lan1<br />
r2[eth1]=lan2<br />
</syntaxhighlight><br />
<br />
Construir um doc conforme aula anterior com as seguintes informações:<br />
<br />
#Coloque a tela de um píng funcionando de R1 para PC1<br />
#Cole a tela da tabela de roteamento de R2<br />
#Cole a tela de um ping de uma máquina VirtualBox (netkit) no R1 (uplink)<br />
#Cole a tela de um ping funcionando uma máquina VirtualBox (netkit) no PC1<br />
<br />
Note que o gateway default da máquina virtual deverá ser reconfigurado para PC1.<br />
<br />
ADENDO: Coloque em R1 rotas para as redes dos PC1 dos demais grupos.<br />
<br />
===PARTE 2===<br />
<br />
Acrescente na sua rede um AP configurado como indicado abaixo:<br />
<br />
OBS: Para este exercício configuramos estaticamente todos os endereços para o lado do backbone (Laboratório). Usamos 50.50.50.0/24<br />
<br />
[[Arquivo:Aval2-Parte2-FICLinux2019-2.png]]<br />
<br />
<br />
=ATIVIDADE DE RECUPERAÇÃO 1=<br />
<br />
Refazer o relatório Avaliativo 1 proposto anteriormente. Enviar doc para o SIGA A<br />
<br />
=ATIVIDADE DE RECUPERAÇÃO 2=<br />
<br />
Registre em um DOC e faça um post no SIGA A colando a imagem das telas das saídas de cada comando!<br />
<br />
===Roteiro de atividades sobre o IPv6===<br />
<br />
A figura abaixo apresenta o diagrama esquemático da rede a ser montada/analisada. Observe que todos os IPv6 ''Global Unicast'' já estão definidos na mesma, são esses IPs que utilizaremos em nosso experimento.<br />
<br />
[[Arquivo:Diagrama_rede_IPv6.jpg]]<br />
<br />
#Crie em seu computador um arquivo com nome '''/home/aluno/IPv6.conf''', com o seguinte conteúdo: <syntaxhighlight lang=bash><br />
#Ligacao das maquinas nos dominios de colisao<br />
#Duas pequenas redes interligadas pelo backbone<br />
<br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=link0:ipv6=2001:bcc:faca:1::101/64<br />
pc2[eth0]=link1:ipv6=2001:bcc:cafe:1::102/64<br />
pc3[eth0]=HUB1:ipv6=2001:bcc:1f0:1::103/64<br />
pc4[eth0]=HUB1<br />
<br />
#Default Gateways definitions<br />
pc1[route]=default6:gateway=2001:bcc:faca:1::1<br />
pc2[route]=default6:gateway=2001:bcc:cafe:1::1<br />
pc3[route]=default6:gateway=2001:bcc:1f0:1::1<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
#Routers interfaces definitions<br />
r1[eth0]=backbone0:ipv6=2001:db8:dead:1::1/64<br />
r1[eth1]=link0:ipv6=2001:bcc:faca:1::1/64<br />
r1[eth2]=link1:ipv6=2001:bcc:cafe:1::1/64<br />
<br />
r2[eth0]=backbone0:ipv6=2001:db8:dead:1::2/64<br />
r2[eth1]=HUB1:ipv6=2001:bcc:1f0:1::1/64<br />
<br />
#Routers definitions<br />
r1[route]=2001:bcc:1f0:1::0/64:gateway=2001:db8:dead:1::2<br />
r2[route]=2001:bcc:faca:1::0/64:gateway=2001:db8:dead:1::1<br />
r2[route]=2001:bcc:cafe:1::0/64:gateway=2001:db8:dead:1::1<br />
</syntaxhighlight><br />
#Tenha certeza que o Netkit2 estja atualizado: General >> Update.<br />
#Rode o NetKit em seu computador. Em um terminal digite: <syntaxhighlight lang=bash><br />
netkit2 & </syntaxhighlight><br />
#No menu '''File''' - '''Load and Run''', procure o arquivo '''/home/aluno/IPv6.conf''' e clique em OK. Abrirá uma janela com 6 abas, onde cada uma delas é um terminal de configuração do respectivo equipamento: '''pc1-4''' ou '''r1-2'''.<br />
#Observe que o '''pc4''' não está com sua interface configurada.<br />
#Ao clicar no menu '''File''' - '''Graph''', pode-se ter uma visão da rede a ser simulada e conferir se é equivalente ao diagrama proposto.<br />
#Faça um '''ping6''' entre o '''pc1''' ao '''pc3''': <syntaxhighlight lang=bash><br />
ping6 -c4 2001:bcc:1f0:1::103 </syntaxhighlight><br />
#Faça um '''ping6''' entre o '''pc1''' e '''pc2'''.<br />
#No '''pc4''' use o seguinte comando para adicionar o endereço IPv6 à interface de rede: <syntaxhighlight lang=bash><br />
ip addr add 2001:bcc:1f0:1::104/64 dev eth0 </syntaxhighlight><br />
#No '''pc4''', acrescente o ''default gateway'' com o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add default via 2001:bcc:1f0:1::1 dev eth0 </syntaxhighlight><br />
#No '''pc1''' use o seguinte comando para verificar como ficou a configuração dos endereços da interface de rede. O resultado é similar ao apresentado pelo comando '''ifconfig''': <syntaxhighlight lang=bash><br />
ip addr show dev eth0 </syntaxhighlight><br />
#Todo o roteamento está pronto, mas caso desejássemos poderíamos acrescentar rotas com comando similares aos já utilizados. Por exemplo, no '''r1''', para adicionar uma rota estática para a rede dos '''pc3''' e '''pc4''' utilizaríamos o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add 2001:bcc:1f0:1::/64 via 2001:db8:dead:1::2 dev eth0 </syntaxhighlight><br />
#Confira as rotas estabelecidas em todos os ''hosts'' com o comando abaixo. <br />
##São coerentes com os dados apresentados no diagrama acima?<syntaxhighlight lang=bash><br />
ip -6 route show </syntaxhighlight><br />
#No '''pc1''' use os seguintes comandos para ver a rota para alguns vizinhos: <syntaxhighlight lang=bash><br />
traceroute6 2001:bcc:1f0:1::103<br />
traceroute6 2001:bcc:1f0:1::104 </syntaxhighlight><br />
#*Anote as rotas.<br />
#Deixe um '''ping6''' entre o '''pc1''' ao '''pc3''' rodando: <syntaxhighlight lang=bash><br />
ping6 2001:bcc:1f0:1::103 </syntaxhighlight><br />
<br />
=ATIVIDADE DE RECUPERAÇÃO 3=<br />
<br />
Registre em um DOC e faça um post no SIGA A colando a imagem das telas das saídas de cada comando! Coloque também a resposta as perguntas.<br />
<br />
===Objetivos===<br />
<br />
*Familiarizar-se com o UDP<br />
*Entender a estrutura do pacote UDP<br />
*Entender o conceito de portas<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/UDP%20Basico.pdf Introdução a camada de transporte e UDP básico]<br />
<br />
===Parte 1 - Fluxo único UDP===<br />
<br />
#Combinar equipes com dois computadores para execução do experimento.<br />
#*Uma equipe escutará na porta 5000 e a outra equipe transmitirá uma mensagem nessa porta. Os processos de transmissão e recepção podem ocorrer simultaneamente, em terminais distintos.<br />
#*Cada equipe deve identificar os IPs ('''IP_DEST''') das máquinas de seus pares.<br />
#Cada equipe deve abrir uma Janela de terminal.<br />
#Cada equipe deve preparar o '''Wireshark''', interfaces '''any''', para escuta das portas no protocolo UDP usando um filtro:<syntaxhighlight lang=bash><br />
udp.port==5000</syntaxhighlight><br />
#A equipe da escuta na porta 5000 executa no terminal: <syntaxhighlight lang=bash><br />
netcat -u -l -p 5000 </syntaxhighlight><br />
#A equipe que irá transmitir para a porta 5000 executa no terminal: <syntaxhighlight lang=bash><br />
netcat -u IP_DEST 5000 </syntaxhighlight><br />
#*Em seguida escreve no terminal uma mensagem de até 20 caracteres, ao teclar <Enter> a mensagem será enviada.<br />
#*O wireshark deve ter capturado os pacotes UDP <br />
#Identifique e anote os seguintes dados na captura do wireshark:<br />
#*IP FONTE e DESTINO<br />
#*PORTAS FONTE E DESTINO para ambas comunicações<br />
#*Campo de protocolo no pacote IP<br />
#*Campo de tamanho (anote o tamanho) e ''checksum'' no pacote (datagrama) UDP<br />
#*O campo de dados no pacote UDP<br />
#Troquem os papéis das equipes: quem houvia agora transmite mensagens.<br />
#Cada equipe pode transmitir sequencialmente várias mensagens, devendo identificar múltiplos datagramas UDP.<br />
#PERGUNTAS baseadas na captura:<br />
##Qual o tamanho de cada campo do cabeçalho do pacote UDP?<br />
##Qual o tamanho máximo do número de porta?<br />
##Qual o tamanho máximo da área de dados (payload) do pacote?<br />
##Qual o número identificador de protocolo UDP no pacote IP? <br />
##Em algum momento foi identificado algum procedimento para estabelecimento de conexão? <br />
##Em algum campo do UDP existe numeração de mensagens?<br />
<br />
=AULA 20 - Dia 18/04/2019=<br />
<br />
{{collapse bottom}}<br />
<br />
==Curso FIC Linux 2018==<br />
<br />
{{collapse top|Semestre 2018-2 - Prof. André D'Amato}}<br />
<br />
== Introdução ao Sistema Operacional Linux ==<br />
<br />
'''10/09/18: Aula01'''<br />
<br />
Apresentação da Disciplina, Introdução a Informática e Memória e Armazenamento<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula01.pdf Aula 01]<br />
<br />
{{collapse bottom}}<br />
<br />
==Curso FIC Linux 2016==<br />
<br />
{{collapse top|Semestre 2016-2 - Prof. Luciano Barreto}}<br />
<br />
== Introdução ao Sistema Operacional Linux ==<br />
<br />
'''04/10/16: Aula01'''<br />
<br />
Apresentação da Disciplina, Introdução a Informática e Memória e Armazenamento<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula01.pdf Aula 01]<br />
<br />
'''06/10/16: Aula 02'''<br />
<br />
Introdução ao Linux, Sistema de Arquivos e Conhecendo o Terminal<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula02.pdf Aula 02]<br />
<br />
''' 11/10/2016: Aula 03'''<br />
<br />
Continuação Comandos no Terminal<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula03.pdf Aula 03]<br />
<br />
''' 13/10/2016: Aula 04''' <br />
<br />
Continuação Comandos no Terminal<br />
<br />
''' 18/10/2016: Aula 05''' <br />
<br />
Lista de Exercícios<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/ficlinux-aula05-exercicios.pdf Aula 05 - Lista de Exercícios]<br />
<br />
''' 20/10/2016: Aula 06'''<br />
<br />
Introdução ao Gerenciamento de Processos<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula06-processos.pdf Aula 06 - Gerenciamento de Processos]<br />
<br />
''' 25/10/2016: Aula 07''' <br />
<br />
Gerenciamento de Usuários<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula07-usuariosgrupos.pdf Aula 07 - Gerenciamento de Usuários]<br />
<br />
Permissionamento<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula07-permissionamento.pdf Aula 07 - Permissionamento]<br />
<br />
''' 27/10/2016: Aula 08'''<br />
<br />
Continuação Permissionamento<br />
<br />
Instalação Linux<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula8-instalacao.pdf Aula 08 - Instalação Linux] <br />
<br />
''' 01/11/2016: Aula 09'''<br />
<br />
Continuação Instalação Linux<br />
<br />
Instalação de Pacotes via Apt<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula9-pacotes.pdf Aula 09 - Instalação Pacotes] <br />
<br />
''' 03/11/2016: Aula 10'''<br />
Continuação Lista Exercícios (47 - 60)<br />
<br />
=AULA 11 - Dia 18/04/2019=<br />
<br />
=AULA 12 - Dia 18/04/2019=<br />
<br />
=AULA 13 - Dia 18/04/2019=<br />
<br />
=AULA 14 - Dia 18/04/2019=<br />
<br />
=AULA 15 - Dia 18/04/2019=<br />
<br />
=AULA 16 - Dia 18/04/2019=<br />
<br />
=AULA 17 - Dia 18/04/2019=<br />
<br />
=AULA 18 - Dia 18/04/2019=<br />
<br />
=AULA 19 - Dia 18/04/2019=<br />
<br />
=AULA 20 - Dia 18/04/2019=<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top|Semestre 2016-1 - Prof. Luciano Barreto}}<br />
<br />
= Diário de Aulas 2016 - 1 =<br />
<br />
==29/03/16: Apresentação do curso==<br />
Apresentação do curso, Visão geral de funções, responsabilidades e estruturas de um SO.<br />
<br />
==31/03/16: Introdução a Sistema de Arquivos e Terminal==<br />
Estrutura do Sistema de Arquivos Linux, Introdução a comandos no Terminal.<br />
<br />
==04/04/16: Continuação Terminal==<br />
Continuação de comandos no terminal, redirecionamento de saída e caracteres coringa.<br />
<br />
==07/04/16: Introdução a Processos e Usuários==<br />
Conhecendo Processos e Gerenciamento de usuários<br />
<br />
==12/04/16: Lista de Exercícios de Comandos no Terminal==<br />
<br />
[http://bellard.org/jslinux/ Emulador de Terminal no navegador (demora um pouquinho pra abrir)]<br />
<br />
==14/04/16: Usuários, Grupos e Permissões==<br />
Administração de usuários, grupos e adicionando permissões a arquivos.<br />
<br />
==19/04/16: Instalação do Linux==<br />
Instalação do Sistema Linux em modo texto, gráfico e dualboot.<br />
<br />
==26/04/16: Introdução ao Shell Script==<br />
Introdução ao Shell Script<br />
<br />
==28/04/16: Continuação ao Shell Script==<br />
Introdução ao Shell Script<br />
<br />
==03/05/16: Lista de Exercícios==<br />
Lista de Exercícios até a aula de 28/04/16<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top|Semestre 2015-2}}<br />
<br />
*'''Professores:''' [[Ana Paula Rosa Negri]] e [[Francisco de Assis Souza dos Santos]]<br />
<br />
{| style="background-color:#ABCDEF; font-family:verdana,Arial, Helvetica, sans-serif; font-size:100%; margin:0; border: 1px solid #C7D0F8; padding:7px 7px 0px 7px; text-align:center;" width="100%"<br />
| | Bem-vindo ao<br /><br />
<span style="font-size:200%">'''Curso de Formação Continuada de Configuração de Redes de Computadores Linux''' <br />do Instituto Federal de Santa Catarina - Campus São José</span><br />
|}<br />
<br />
Introdução ao Sistema Operacional Linux<br />
<br />
*'''Professores:''' [[Ana Paula Rosa Negri]] e [[Francisco de Assis Souza dos Santos]]<br />
*'''Encontros:''' Terças e quintas das 19:00 às 22:00 no Laboratório de Apoio ao Ensino.<br />
<br />
*[[ISL-FicLinux_(Plano_de_Ensino)| Plano de Ensino]]<br />
*[[Cronograma de atividades (ISL-FicLinux) | Cronograma]]<br />
<br />
= Diário de Aulas 2015 =<br />
== 13/10 ==<br />
'''Parte 1:'''<br />
Slides da aula:<br />
[[Arquivo:introducao.pdf]]<br />
<br>Exercício sobre taxa de transferência:<br />
[[Arquivo:Exercicio_taxa_Transferencia.pdf]]<br />
<br><br />
<br />
'''Parte 2:'''<br />
Slides da Aula:<br />
[[Arquivo:LinuxModoTexto.pdf]]<br />
<br>Exercícios sobre comandos básicos do Linux:<br />
[[Arquivo:ExercícioLinuxTexto.pdf]]<br />
<br />
== 15/10 ==<br />
'''Parte 3:'''<br />
Slides da Aula:<br />
[[Arquivo:Parte3.pdf]]<br />
== 20/10 ==<br />
'''Parte 4:'''<br />
Slides caracteres coringas: [[Arquivo:Coringas.pdf]]<br />
<br />
Exercícios caracteres coringas: [[Arquivo:Exercício CB03 Pokemon.pdf]]<br />
<br />
'''Parte 5:'''<br />
Sildes Redirecionamento: [[Arquivo: Redirecionamento.pdf]]<br />
<br />
Exercícios redirecionamento e pipe: [[Arquivo: ex_pipe.pdf]]<br />
<br />
== 22/10 ==<br />
'''Parte 6:'''<br />
Slides Processos: [[Arquivo:FICLinux_Processos.pdf]]<br />
<br />
== 27/10 ==<br />
'''Parte 7:''''<br />
Slides Usuários e Grupos: [[Arquivo:UserGroup.pdf]]<br />
<br>Exercícios: [[Arquivo:usuarios.pdf]]<br />
<br>Exercícios (.odt): [[Arquivo:usuarios.odt]]<br />
<br />
== 29/10 ==<br />
'''Parte 8:'''<br />
Slides Introducao a Redes: [[Arquivo:FICLinux_Introducao_Redes.pdf]]<br />
<br />
== 03/11 ==<br />
<br />
'''Parte 9:'''<br />
Slides permissionamento: [[Arquivo:permissionamento.odp]]<br><br />
Exercícios permissionamento: [[Arquivo: Exercício Perm02.odt]]<br><br />
Outro exercício permissionamento: [[Arquivo: Exercício Perm04 GatosRatosCães.odt]]<br />
<br />
== 05/11 ==<br />
<br />
'''Parte 10:'''<br />
Slides Redes - Broadcast: [[Arquivo:FICLinux_Introducao_Redes_Broadcast_01.pdf]]<br><br />
<br />
== 10/11 ==<br />
<br />
'''Parte 11:'''<br />
Slides Script: [[Arquivo:Scripts do Linux.odp]]<br />
<br>Exercícios Scripts: [[Arquivo:Exercício Scripts01 pdfmerger.odt]]<br />
<br />
== 12/11 ==<br />
<br />
'''Parte 12:'''<br />
Introdução para comandos em Bash: [[Arquivo:Introdução ao Shell_2015_1.pdf]]<br />
<br />
{{collapse bottom}}</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=PRG29002-2019-2&diff=162083PRG29002-2019-22019-10-08T17:42:34Z<p>127.0.0.1: /* AULA 20 - Dia 3/10/2019 */</p>
<hr />
<div>=PROFESSOR=<br />
<br />
*Eraldo Silveira e Silva<br />
<br />
=ATENDIMENTO PARALELO=<br />
<br />
A DEFINIR...<br />
<br />
LOCAL: Sala 1 de Professores de Telecomunicações ou em algum dos laboratórios de TELE/CAD<br />
<br />
<br />
=AULA 1 - Dia 31/7/2019 =<br />
<br />
==Objetivos==<br />
<br />
*Apresentação do Plano de Ensino;<br />
*Conceituar Algoritmo<br />
*Utilizar variáveis, constantes e expressões nas instruções do algoritmo.<br />
*Representar Algoritmos na forma de Fluxogramas e Pseudocódigo<br />
*Utilizar Teste de Mesa para verificar o funcionamento do algoritmo <br />
<br />
==Material de Referência==<br />
<br />
[https://wiki.sj.ifsc.edu.br/index.php/AULA_1_-_Programa%C3%A7%C3%A3o_1_-_Engenharia Aula Introdutória sobre Lógica de Programação]<br />
<br />
=AULA 2 - Dia 1/8/2019 =<br />
<br />
<br />
==Objetivos==<br />
<br />
*Exercícios de Lógica de Programação (ver AULA 1)<br />
*Estruturas de Decisão<br />
<br />
==Material de Referência==<br />
<br />
https://wiki.sj.ifsc.edu.br/index.php/AULA_2_-_Programa%C3%A7%C3%A3o_1_-_Engenharia<br />
<br />
=AULA 3 - Dia 7/8/2019 =<br />
<br />
==Objetivos==<br />
<br />
*Exercícios<br />
*Continuação de Estruturas de Decisão<br />
*Estruturas de Repetição<br />
<br />
==Material de Referência==<br />
<br />
*[https://wiki.sj.ifsc.edu.br/index.php/AULA_2_-_Programa%C3%A7%C3%A3o_1_-_Engenharia Estruturas de Decisão]<br />
<br />
*[https://wiki.sj.ifsc.edu.br/index.php/AULA_3_-_Programa%C3%A7%C3%A3o_1_-_Engenharia Estruturas de Repetição]<br />
<br />
=AULA 4 - Dia 8/8/2019 =<br />
<br />
==Objetivos==<br />
<br />
*Estruturas de Repetição<br />
<br />
==Material de Referência==<br />
<br />
*[https://wiki.sj.ifsc.edu.br/index.php/AULA_2_-_Programa%C3%A7%C3%A3o_1_-_Engenharia Estruturas de Decisão]<br />
<br />
*[https://wiki.sj.ifsc.edu.br/index.php/AULA_3_-_Programa%C3%A7%C3%A3o_1_-_Engenharia Estruturas de Repetição]<br />
<br />
=AULA 5 - Dia 13/8/2019 =<br />
<br />
==Objetivos==<br />
<br />
*Estruturas de Repetição<br />
<br />
==Material de Referência==<br />
<br />
*[https://wiki.sj.ifsc.edu.br/index.php/AULA_2_-_Programa%C3%A7%C3%A3o_1_-_Engenharia Estruturas de Decisão]<br />
<br />
*[https://wiki.sj.ifsc.edu.br/index.php/AULA_3_-_Programa%C3%A7%C3%A3o_1_-_Engenharia Estruturas de Repetição]<br />
<br />
=AULA 6 - Dia 15/8/2019 =<br />
<br />
==Objetivos==<br />
<br />
*Exercícios de Estruturas de Repetição<br />
*Introdução a Linguagem C<br />
<br />
==Material de Referência==<br />
<br />
*[https://wiki.sj.ifsc.edu.br/index.php/AULA_4_-_Programa%C3%A7%C3%A3o_1_-_Engenharia Introdução a C]<br />
<br />
=AULA 7 - Dia 21/8/2019 =<br />
<br />
==Objetivos==<br />
<br />
*Introdução a Linguagem C (continuação)<br />
*Estrutura if else de decisão no C<br />
<br />
==Material de Referência==<br />
<br />
*[https://wiki.sj.ifsc.edu.br/index.php/AULA_4_-_Programa%C3%A7%C3%A3o_1_-_Engenharia Introdução a C]<br />
*[https://wiki.sj.ifsc.edu.br/index.php/AULA_5_-_Programa%C3%A7%C3%A3o_1_-_Engenharia]<br />
<br />
=AULA 8 - Dia 22/8/2019 =<br />
<br />
==Objetivos==<br />
<br />
*Estrutura if else de decisão no C<br />
<br />
==Material de Referência==<br />
<br />
*[https://wiki.sj.ifsc.edu.br/index.php/AULA_5_-_Programa%C3%A7%C3%A3o_1_-_Engenharia]<br />
<br />
<br />
=AULA 9 - Dia 28/8/2019 =<br />
<br />
==Objetivos==<br />
<br />
*Estrutura if else de decisão no C (continuação)<br />
<br />
Exercício proposto no início da aula.<br />
<br />
<syntaxhighlight lang=c><br />
/*<br />
<br />
<br />
FAZER UM PROGRAMA C PARA<br />
#Ler 2 números "a" e "b";<br />
#SE "a" for maior que "b" então ler 3 números reais adicionais, <br />
calcular a média destes 3 números<br />
e caso a média seja maior que 6 mostrar uma mensagem;<br />
#SE "a" for menor que "b" então ler um número inteiro "c" adicional,<br />
calcular o produto de "a","b" e "c" e dividir o resultador por 3 mostrando o resultado;<br />
#SE "a" for igual a "b" somente mostrar uma mensagem;<br />
*/<br />
*/<br />
<br />
</syntaxhighlight><br />
<br />
=AULA 10 - Dia 29/8/2019 =<br />
<br />
==Objetivos==<br />
<br />
*Estruturas de Repetição no C<br />
<br />
==Material de Referência==<br />
<br />
*[https://wiki.sj.ifsc.edu.br/index.php/AULA_6_-_Programa%C3%A7%C3%A3o_1_-_Engenharia Estruturas de Repetição no C]<br />
<br />
<br />
=AULA 11 - Dia 4/8/2019 =<br />
<br />
==Objetivos==<br />
<br />
*Estruturas de Repetição no C<br />
<br />
==Material de Referência==<br />
<br />
*[https://wiki.sj.ifsc.edu.br/index.php/AULA_6_-_Programa%C3%A7%C3%A3o_1_-_Engenharia Estruturas de Repetição no C]<br />
<br />
<br />
=AULA 12 - Dia 5/8/2019 =<br />
<br />
==Objetivos==<br />
<br />
*Estruturas de Repetição no C<br />
<br />
==Material de Referência==<br />
<br />
*[https://wiki.sj.ifsc.edu.br/index.php/AULA_6_-_Programa%C3%A7%C3%A3o_1_-_Engenharia Estruturas de Repetição no C]<br />
<br />
<br />
=AULA 13 - Dia 11/8/2019 =<br />
<br />
==Objetivos==<br />
<br />
*Aula de Exercícios de Preparação para AVALIAÇÃO 1<br />
<br />
=AULA 14 - Dia 12/8/2019 =<br />
<br />
==Objetivos==<br />
<br />
*Avaliação 1<br />
<br />
=AULA 15 - Dia 18/8/2019 =<br />
<br />
==Objetivos==<br />
<br />
*Uso de IDEs - Clion<br />
*Correção da Avaliação usando o Clion<br />
<br />
==Material de Referência==<br />
<br />
*[https://wiki.sj.ifsc.edu.br/index.php/AULA_X_-_Programa%C3%A7%C3%A3o_1_-_Uso_de_IDE_com_o_C]<br />
<br />
=AULA 16 - Dia 19/8/2019 =<br />
<br />
==Objetivos==<br />
<br />
*Funções no C<br />
*Variáveis Globais X Variáveis Locais<br />
<br />
==Material de Referência==<br />
<br />
*[https://wiki.sj.ifsc.edu.br/index.php/AULA_8_-_Programa%C3%A7%C3%A3o_1_-_Engenharia Funções]<br />
<br />
=AULA 17 - Dia 25/9/2019 =<br />
<br />
==Objetivos==<br />
<br />
*Funções no C<br />
*Variáveis Globais X Variáveis Locais<br />
<br />
==Material de Referência==<br />
<br />
*[https://wiki.sj.ifsc.edu.br/index.php/AULA_8_-_Programa%C3%A7%C3%A3o_1_-_Engenharia Funções]<br />
<br />
<code><br />
1) Elaborar uma função que recebe 2 números reais como parâmetro e retorna a média entre eles. Testar na função main(). Chamar pelo menos 3 vezes.<br />
<br />
float calc_media(float num1, float num2)<br />
{<br />
<br />
}<br />
<br />
main()<br />
{<br />
int x,y=7.9;<br />
<br />
x=calc_media(5.5,3.6);<br />
<br />
x=calc_media(y,3.6);<br />
<br />
x=calc_media(y=7.9,3.6);<br />
<br />
x = calc_media(7.9,3.6) + calc_media(y*3,2.7);<br />
<br />
printf("valor = %f\n", x=calc_media(x,y));<br />
<br />
}<br />
<br />
2) Elaborar uma função que recebe dois números inteiros e que retorna a soma de todos os números inteiros entre estes números (inclusive). Testar na função main().<br />
</syntaxhighlight><br />
<br />
=AULA 18 - Dia 26/9/2019 =<br />
<br />
==Objetivos==<br />
<br />
*Introdução a vetores<br />
<br />
==Material de Referência==<br />
<br />
*[https://wiki.sj.ifsc.edu.br/index.php/AULA_9_-_Programa%C3%A7%C3%A3o_1_-_Engenharia Vetores - parte 1]<br />
<br />
<br />
=AULA 19 - Dia 2/10/2019 =<br />
<br />
==Objetivos==<br />
<br />
*Introdução a vetores<br />
<br />
==Material de Referência==<br />
<br />
*[https://wiki.sj.ifsc.edu.br/index.php/AULA_10_-_Programa%C3%A7%C3%A3o_1_-_Engenharia Vetor de char]<br />
<br />
<br />
=AULA 20 - Dia 3/10/2019 =<br />
<br />
==Objetivos==<br />
<br />
*Introdução a vetores: strings - exercicios<br />
<br />
==Material de Referência==<br />
<br />
*[https://wiki.sj.ifsc.edu.br/index.php/AULA_10_-_Programa%C3%A7%C3%A3o_1_-_Engenharia Vetor de char]<br />
<br />
==Link para a computação do seno via série de Taylor==<br />
<br />
*https://en.wikipedia.org/wiki/Trigonometric_functions<br />
<br />
=Link para todas as aulas==<br />
<br />
*[https://wiki.sj.ifsc.edu.br/index.php/Proposta_de_Aulas_de_Introdu%C3%A7%C3%A3o_a_Programa%C3%A7%C3%A3o_C Aulas de C]</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=MTG-EngTel_(p%C3%A1gina)&diff=162081MTG-EngTel (página)2019-10-08T15:22:42Z<p>127.0.0.1: /* Bibliografia Básica */</p>
<hr />
<div>{{DivulgueEngtelecom}}<br />
<br />
= [[MTG-EngTel|Carga horária, Ementas, Bibliografia, Professores]]=<br />
<br />
= [[Cronograma de atividades (MTG-EngTel)]]=<br />
<br />
= [[MTG-EngTel (Plano de Ensino) | Plano de Ensino]]=<br />
<br />
<br />
'''Professores da Unidade Curricular'''<br />
<br />
{{Professor|2019-2|[[Jorge Henrique B. Casagrande]] }}<br />
<br />
{{Professor|'''2017-2'''| [[MTG29007 2017-2|'''Meios de Transmissão Guiados - Wiki''']] - [[https://moodle.sj.ifsc.edu.br/course/view.php?id=80 '''Meios de Transmissão Guiados - Moodle''']]([https://wiki.sj.ifsc.edu.br/index.php/Usu%C3%A1rio:Ederson.luiz Ederson Luiz de Souza Santos])}}<br />
{{Professor|'''2017-2'''| [[MTG29007 2017-2|'''Meios de Transmissão Guiados - Wiki''']] - [[https://moodle.sj.ifsc.edu.br/course/view.php?id=80 '''Meios de Transmissão Guiados - Moodle''']]([https://wiki.sj.ifsc.edu.br/index.php/Usu%C3%A1rio:karin.eickhoff Karin Eickhoff Cavalhieri])}}<br />
<br />
{{Professor|2015-2|[[Saul S. Caetano]] ([[MTG-EngTel-2015-2 Meios de Transmissão Guiados | Diário de aulas)]]}}<br />
{{Professor|2015-1|[[Saul S. Caetano]] ([[MTG-EngTel-2015-1 Meios de Transmissão Guiados | Diário de aulas)]]}}<br />
<br />
<br />
=Dados Importantes=<br />
''Professor'': [[Jorge Henrique B. Casagrande]]<br />
<br>''Email'': casagrande@ifsc.edu.br<br />
<br>'''Atendimento paralelo: 2as e 5as das 17:35h às 18:30h''' (Sala de Professores de TELE II ou Laboratório de Meios de Transmissão)<br />
<br> ''Link alternativo para Material de Apoio da disciplina'': http://www.sj.ifsc.edu.br/~casagrande/MTG<br />
<br />
=Resultados das Avaliações=<br />
<br />
;Critérios<br />
:Os alunos serão avaliados da seguinte forma:<br />
::- 3 Avaliações parciais A1, A2 e A3. Cada avaliação parcial contará com uma '''PROVA ESCRITA''' de 2HA de conteúdos preferencialmente associados as teorias e práticas da disciplina os quais representam 60% da nota; Os outros 40% de cada avaliação parcial é relativa a média das notas atribuídas a aptidão e qualidade das atividades práticas e teóricas correspondentes, atividades extras e avaliação individual.<br><br />
::- Avaliação Individual (AI1, AI2 e AI3) é uma nota atribuída pelo professor que representa o mérito de assiduidade, participação em sala, cumprimento de tarefas adicionais como relatórios e listas de exercícios.<br><br />
::- Todas as notas parciais serão valoradas de 0 à 10 em passos de 1 ponto e convertidas em conceitos conforme abaixo:<br />
::Se '''NOTA FINAL (NF)''' OU '''PROVA ESCRITA'''da avaliação parcial '''< 6''' é OBRIGATÓRIO realizar a recuperação dos conteúdos da respectiva avaliação parcial <br><br />
::Se '''NOTA FINAL''' OU '''PROVA ESCRITA'''da avaliação parcial '''>= 6''' a recuperação de conteúdos é opcional<br><br />
<br />
::- '''Para a aprovação na disciplina''' é necessário atingir no mínimo nota '''6''' na média final ponderada em carga horária de todas as avaliações parciais e 75% de participação em sala de aula;<br><br />
::- As datas de recuperação das avaliações parciais serão decididas em comum acordo com a turma. <br><br />
<br />
<br />
{| border="1" cellpadding="5" cellspacing="0" <br />
!Aluno<br />
!AE1<br />
!AE2<br />
!AI1<br />
!Prova1 <br />
!A1<br />
!REC A1<br />
!NF A1<br />
!AE4<br />
|-<br />
|Alisson ||90 ||70 ||90 ||35 ||54 || || ||<br />
|-<br />
|Guilherme ||90 ||70 ||90||48 ||62 || || ||<br />
|-<br />
|Rafael ||90 ||80 ||90|| 54|| 67|| || ||<br />
|-<br />
|Victor ||90 ||70 ||90 ||37 || 56|| || ||<br />
|-<br />
|Yan ||90 ||80 ||90 ||80 ||83 || || ||<br />
|- <br />
|}<br />
<br />
'''LEGENDA E DETALHES '''<br />
<br />
AE1 = Parâmetros distribuídos de cabos comerciais - 29/08 <br><br />
AE2 = Simulação MATLAB Magnitude versus tamanho da LT - 12/09 <br><br />
<br />
=Recados Importantes=<br />
<br />
<br> Toda vez que você encontrar a marcação <math>\blacklozenge</math> ao lado de alguma atividade, significa que essa atividade estará sendo computada na avaliação como AIn de An. O prazo estabelecido para entrega estará destacado ao lado da atividade. Portanto, não perca o prazo limite para entrega. '''Atividades entregues fora do prazo terão seu valor máximo de nota debitado de 10 pontos ao dia;'''<br />
<br />
<br> '''Uso da Wiki:''' Todo o repositório de material de apoio e referências de nossas aulas passam a usar a Wiki de tele;<br />
<br />
<br> '''Whatsapp:''' Para interação fora da sala de aula, acessem nosso grupo no Whatsapp;<br />
<br />
<br> '''SIGAA: ''' Eventualmente alguns materiais, mídias instrucionais, avaliações ou atividades poderão usar o ambiente da turma virtual do SIGAA. O professor fará o devido destaque para isso;<br />
<br />
<br> '''ATENÇÃO:''' Uma avaliação poderá ser recuperada somente se existir justificativa reconhecida pela coordenação. Desse modo, deve-se protocolar a justificativa no prazo de 48 horas, contando da data e horário da avaliação, e aguardar o parecer da coordenação. O não cumprimento desse procedimento implica a impossibilidade de fazer a recuperação.<br />
<br />
=Material de Apoio=<br />
<br />
;Tabela de leitura básica e de atividades correlatas das Bibliografias recomendadas.<br />
<br />
{| border="1" cellpadding="5" cellspacing="0" <br />
!Referência<br />
!Tópicos<br />
!Observações<br />
|-<br />
| || || <br />
|-<br />
| || || <br />
|-<br />
| || || <br />
|-<br />
|}<br />
<br />
;Atividades extra sala de aula<br />
:* [[media:MTG29007_lista1_2019_2.pdf | LISTA1]] de exercícios para a avaliação A1<br />
:* [[media:MTG29007_lista2_2019_2.pdf | LISTA2]] de exercícios para a avaliação A2<br />
:* [[media:MTG29007_lista3_2019_2.pdf | LISTA3]] de exercícios para a avaliação A3<br />
<br />
;Slides utilizados durante algumas aulas<br />
<br />
:* [[media:MTG29007_parte1_parametros.pdf | Parte1 - Parâmetros Distribuídos - Primários]] Slides sobre os Paramêtros Primários de LTs da Parte 1;<br />
:* [[media:MTG29007_parte1_fasores.pdf | Parte1 - Fasore e Parâmetros Distribuídos - Secundários]] Slides sobre Fasores e os Paramêtros Secundários de LTs da Parte 1;<br />
:* [[media:MTG29007_parte2.pdf | Parte2]] Slides da Parte 2 para acompanhamento das aulas<br />
:* [[media:MTG29007_parte3.pdf | Parte3]] Slides da Parte 3 para acompanhamento das aulas<br />
<br />
<br />
;Manuais e outros<br />
<br />
* [https://www.youtube.com/watch?v=mNkWP61GiVs vídeo sobre a meios guiados]<br />
* [http://tele.sj.ifsc.edu.br/~casagrande/MTG/apoio/cartasmith.pdf Carta de Smith] <br />
<br />
<br />
== Bibliografia Básica ==<br />
<br />
* WENTWORTH, Stuart M. Eletromagnetismo aplicado : abordagem antecipada das linhas de transmissão; ed. [S.l]: Bookman, 2009.<br />
* DUTTA WDM TECHNOLOGIES - OPTICAL NETWORKS; ed. [S.l]:ELSEVIER, 2004;<br />
* RAMASWAMI, R.; SIVARAJAN, K. Optical Networks: A Practical Perspective; 3ª ed. [S.l]:Morgan Kaufmann, 2009;<br />
<br />
== Bibliografia Complementar ==<br />
<br />
* KRAMER, Glen Ethernet passive optical networks; ed. New York:McGraw-Hill,, 2005;<br />
* AMAZONAS, José R.A Projeto de sistemas de comunicações ópticas; 1ª ed. [S.l]:Manole, 2005;<br />
* COELHO, Paulo Eustáquio Projetos de redes locais com cabeamento estruturado; ed. Belo Horizonte: Instituto Online, 2003;<br />
* MAGNUSSON, Philip C. Transmission lines and wave propagation; 4ª ed. [S.l]:Boca Raton, FL : CRC Press, 2001;<br />
* HECHT, Jeff. Understanding Fiber Optics; 5ª ed. [S.l]:Prentice Hall, 2005.<br />
<br />
<br />
Para pesquisar o acervo das bibliotecas do IFSC:<br />
<br />
* [http://biblioteca.ifsc.edu.br/sophia/ Acesso ao acervo da Biblioteca do IFSC]<br />
<br />
== Softwares e Links úteis ==<br />
<br />
<!--* [[Netkit]]: possibilita criar experimentos com redes compostas por máquinas virtuais Linux<br />
* [http://tele.sj.ifsc.edu.br/~casagrande/IER/ipkit.html IPKIT]: um simulador de encaminhamento IP em java (roda direto no navegador)--><br />
* [https://www.sejda.com/pdf-editor editor de PDF]:<br />
<br />
=Diário de aulas MTG29007 - 2019-2 - Prof. Jorge H. B. Casagrande=<br />
<br />
<br />
{{Collapse top |30/07 - Os Meios de transmissão e suas limitações}}<br />
<br />
==30/07 - Os Meios de transmissão e suas limitações ==<br />
<br />
* Apresentação da disciplina e plano de ensino;<br />
* Relembrando os principais meios de transmissão.<br />
<br />
== Tipos de meios utilizados em telecomunicações ==<br />
<br />
:'''Par trançado:''' Utilizado na rede de distribuição telefônica, principalmente do armário de distribuição até o assinante. Também é utilizado no cabeamento estruturado. Em geral esta acondicionado em cabos com vários pares, os quais são identificados por um código de cores.<br />
<br />
[http://www.conducab.ind.br/anexos/Anexo054-Cabos%20Telefonicos%20CCE%20APL.pdf detalhes de fabricante]<br />
<br />
:: [[Arquivo:cabo_telefonico.jpg |300px]] [http://www.furukawa.com.br/br/produtos/cabo-telefonico-metalico/rede-subterranea-ou-rede-espinada-em-mensageiro/cabo-telefonico-metalico-ctp-apl-g-540.html fonte]<br />
<br />
<br />
<br />
::'''Cabo coaxial:''' Empregado nas redes de distribuição de CATV e CFTV, na interligação entre equipamentos de telecomunicações e nas ligações entre transmissores e antenas. É formado por um condutor central, dielétrico, malha externa e capa protetora.<br />
:: [[Arquivo: cabo_coaxial.jpg |300px]] [http://en.wikipedia.org/wiki/Coaxial_cable fonte]<br />
<br />
<br />
::'''Fibra óptica:''' Está no coração de todas as redes de telecomunicações (Voz, Imagem e Dados).É utilizada em redes de transmissão e distribuição telefônicas, em redes de CATV e no cabeamento estruturado. É composta por um núcleo e uma casca, dois vidros com índices de refração diferentes. A tendência é que substitua o par trançado e o cabo coaxial. No cabeamento estruturado sua maior restrição de uso é o custo dos equipamentos de ponta (placas de rede e portas ópticas de equipamentos).<br />
::[[Arquivo: Optical_Fiber.jpg |300px]] [[http://en.wikipedia.org/wiki/Optical_fiber fonte]]<br />
<br />
:::* [http://www.cablemap.info/ Mapa dos cabos ópticos ao redor do planeta]<br />
<br />
<br />
<br />
::'''Ar (wireless):''' empregado nas comunicações sem fio.<br />
::[[Arquivo: radiotransmissao.jpg|300px]] [http://en.wikipedia.org/wiki/Twisted_pair fonte]<br />
<br />
; ...e a novidade:<br />
<br />
::''' Guia de onda:''' Utilizado na faixa de microondas, em frequências próximas ou superiores a 2 GHz. Nessa faixa de frequência apresenta menor atenuação do que os cabos coaxiais equivalentes. Utilizado para interligar os estágios amplificadores de potência em sistemas de radiodifusão e para ligar esses amplificadores aos seus respectivos sistemas de antenas.<br />
:: [[Arquivo:Guia_de_onda.jpg |300px]] [http://www.epirsa.com/htm/productos.asp?id=79 fonte]<br />
<br />
<br />
<br />
: Independente do meio os cabos que os encapsulam podem diferir em função do ambiente onde serão instalados. Existem cabos para ambientes internos, para instalação aérea, subterrânea ou diretamente enterrada.<br />
<br />
<br />
::'''Código de cores'''<br />
<br />
:::Para identificação dos pares trançados dentro dos cabos multipares existe um código de cores padronizado como por exemplo, do fabricante Furukawa [[Arquivo:ET923.pdf]].<br />
<br />
:::Além do código de cores os cabos de pares trançados são fabricados através do agrupamento de grupos de 25 ou supergrupos de 50 ou 100 pares .<br />
<br />
:::Os cabos de fibra óptica também utilizam um código de cores.<br />
<br />
:: [[Arquivo: FiberCableCodes2.jpg|500px]] [http://www.accu-tech.com/accu-insider/bid/98212/Corning-Accu-tech-Introduction-to-Fiber-Color-Codes]<br />
<br />
== Parâmetros concentrados x Parâmetros distribuídos ==<br />
<br />
No estudo de análise de circuitos é comum tratar os condutores que interligam fontes, resistores, indutores e capacitores como ideais. Estes condurores não apresentam resistência ou outras propriedades elétricas, são condutores perfeitos. <br />
<br />
Este tipo de abordagem é possível devido a boa qualidade dos condutores utilizados nos circuitos elétricos. A resistência desses condutores é muito baixa podendo ser desprezada na maioria dos casos.<br />
<br />
Além da boa qualidade dos condutores, é possível desprezar seus efeitos elétricos quando estamos trabalhando em baixas frequências e/ou com comprimentos de onda que se propaga no meio muito maiores do que o comprimento dos condutores.<br />
<br />
Os condutores que interligam uma fonte a uma impedância não são tratados como ideais quando tem comprimentos da mesma ordem de grandeza ou maiores do que o comprimento de onda gerado pela fonte. Nesses casos os efeitos resistivos, capacitivos e indutivos dos condutores influenciam no comportamento das tensões e das correntes do circuito elétrico. <br />
<br />
<br />
::'''Parâmetros Concentrados:''' Quando tratamos os condutores que interligam componentes como ideais, trabalhamos com a abordagem de '''parâmetros concentrados''', isto é, consideramos que os efeitos resistivos, capacitivos e indutivos resultam apenas dos componentes que inserimos no circuito.<br />
<br />
<br />
::'''Parâmetros Distribuídos:''' Quando o comprimento de onda que se propaga num circuito apresenta a mesma ordem de grandeza ou é muito menor do que o tamanho dos condutores que interligam os componentes, temos que considerar os efeitos das propriedades elétricas desses condutores. Nesse caso, utilizamos uma abordagem de '''parâmetros distribuídos'''.<br />
<br />
<br />
::''' Tensão, corrente e onda eletromagnética:''' Um condutor percorrido por corrente elétrica gera ao seu redor um campo magnético. Se a corrente variar no tempo, o campo magnético também sofrerá variações, produzindo uma perturbação magnética que se propaga na forma de uma onda eletromagnética. De formar semelhante um par de condutores submetidos a uma tensão elétrica geram no espaço um campo elétrico. Se a tensão variar o campo elétrico irá gera uma perturbação eletromagnética. Essa breve descrição da relação entre tensão, corrente e onda eletromagnética, já fornece elementos para admitirmos que a propagação da energia elétrica por circuitos pode ser analisada considerando suas tensões e correntes ou a onda eletromagnética que o percorre.<br />
<br />
<br />
::'''Parâmetros de uma onda sinusoidal:''' Onda é a propagação de uma perturbação através do espaço ou de um meio sem que acha a propagação da matéria. Apenas a energia da perturbação é propagada. São parâmetros de uma onda periódica sinusoidal:<br />
<br />
<br />
::<span style="color: red">'''1. Frequência (f)'''</span>: quantidade de vezes que a onda se repete em um segundo (Hz)<br />
::<span style="color: red">'''2. Período (T)'''</span>: intervalo de tempo entre o fim e o início de um ciclo da onda. É o inverso da frequência (s)<br />
::<span style="color: red">'''3. Amplitude máxima'''</span>: valor máximo que a perturbação atinge durante um ciclo. Sua unidade depende da natureza da onda. (tensão - V, corrente - A, campo elétrico - N/C, campo Magnético - T ...)<br />
::<span style="color: red">'''4. Velocidade de propagação (Vp)'''</span>: a velocidade da onda eletromagnética é a velocidade da luz. No vácuo é aproximadamente <math>3x10^8</math> m/s<br />
::<span style="color: red">'''5. Comprimento de onda (<math>\lambda</math>)'''</span>: comprimento de um ciclo completo da onda (m)<br />
<br />
::'''Relação entre Vp,<math>\lambda</math> e f:<span style="color: red"> <math>Vp= \lambda . f</math></span>'''<br />
<br />
{|class="wikitable"<br />
|style= "width:400px;"|[[Arquivo:Parametros_onda_lambda.png ]]<br />
|style= "width:400px;"| [[Arquivo:Parametros_onda_periodo.png ]]<br />
|}<br />
<br />
<br />
== Relação entre <math>\lambda</math> e o tamanho dos "condutores" que interligam os componentes ==<br />
<br />
As duas comparações que seguem procuram mostrar a diferença do fenômeno físico entre para o circuito abaixo, percorrido por uma onda com <span style="color: red">'''&lambda;'''</span> muito maior do que o seu tamanho físico e um circuito percorrido por uma onda com <span style="color: red">'''&lambda;'''</span> igual ou inferior ao seu tamanho físico.<br />
<br />
[[Arquivo:Circuito_1.gif |700px]] <br />
<br />
: <<strike>-----------------------------------------------------------------</strike>0,30 m <strike>--------------------------------------------------------------</strike>><br />
<br />
<br />
<br />
* <u> Circuito com <span style="color: red">'''&lambda;'''</span> muito maior do que o seu tamanho físico.</u><br />
<br />
Neste circuito a fonte gera uma onda com f=60 Hz, para simplificação dos cálculos vamos considerar que a velocidade da onda eletromagnética no condutor é igual a 3x10<sup>8</sup>, portanto: <br />
<br />
:::<math>\lambda={Vp \over f}= {3.10^8 \over 60} = 5.10^6 m</math><br />
<br />
Como o circuito tem apenas 0,30 m a variação da tensão entre o ponto onde esta a fonte e o ponto onde esta o resistor é menor que 3x10<sup>-6</sup>. Comparando esse valor com a tensão da fonte percebe-se que o mesmo é desprezível. Quanto a fase, temos que:<br />
<br />
:::: <math>\beta = {360 \over 5.10^6}= 7,2.10^{-5 } { .^o}/m </math>.<br />
<br />
<br />
Para 0,30 m <math>\theta = 0,30 \beta = 2,2.10^{-5} {.^o}</math>, novamente desprezível.<br />
<br />
Considerando a diferença da tensão e da fase entre a fonte e o resistor, podemos considerar que as mesmas são iguais e o condutor como ideal.<br />
<br />
<br />
[[Arquivo:Seno60.png|700px]]<br />
<br />
<br />
<br />
* <u> Circuito com <span style="color: red">'''&lambda;'''</span> muito menor do que o seu tamanho físico.</u><br />
<br />
Para o segundo circuito abaixo, a fonte gera uma onda com <math>f= 3 GHz</math>, portanto: <math>\lambda={Vp \over f}= {3.10^8 \over 3.10^9} = 0,10 m</math><br />
<br />
<br />
[[Arquivo:Circuito_2.gif|700px]]<br />
<br />
: <<strike>------------------------------------------------------------</strike>0,30 m <strike>---------------------------------------------------------------</strike>><br />
<br />
<br />
Como o circuito tem 0,30 m entre a fonte e o resistor cabem 3 comprimentos de onda completos. Se acompanharmos o valor da tensão ao longo do condutor vemos que o mesmo altera várias vezes entre o valor máximo e o mínimo. Não podemos desconsiderar essa variação, temos que analisar o que ocorre em cada parte do condutor também.<br />
<br />
Se o nosso circuito tivesse 0,35m o valor da tensão no resistor seria de 10V enquanto na fonte o valor seria de 0 V !!!!<br />
<br />
Em relação a fase temos que <math>\beta = {360 \over 0,1}= 36^o/m </math>. Para 0,30 m <math>\theta = 0,30 \beta = 1080^o</math>.Essa defasagem não pode ser desconsiderada.<br />
<br />
<br />
Nesta situação trabalhamos com a abordagem de parâmetros distribuídos.<br />
<br />
<br />
<br />
[[Arquivo:Seno_3giga.png|700px]]<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |22/08 - Parâmetros Distribuídos - Parâmetros Primários da Linha de transmissão}}<br />
<br />
==22/08 - Parâmetros Distribuídos - Parâmetros Primários da Linha de transmissão ==<br />
<br />
:* [[media:MTG29007_parte1_parametros.pdf | Parte1 - Parâmetros Distribuídos]] Slides sobre os Paramêtros Primários de LTs da Parte 1<br />
<br />
Parâmetros Distribuídos considerando Sinais de frequências elevadas<br />
<br />
* R' - Resistência por comprimento de Linha;<br />
* G' - Condutância por comprimento de Linha;<br />
* C' - Capacitância por comprimento de Linha;<br />
* L' - Indutância por comprimento de Linha;<br />
<br />
<br />
* Par Trançado e cabo Coaxial.<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |27/08 - Fasores e Parâmetros Distribuídos - Parâmetros Secundários da Linha de Transmissão}}<br />
<br />
==27/08 - Fasores e Parâmetros Distribuídos - Parâmetros Secundários da Linha de Transmissão ==<br />
<br />
:* [[media:MTG29007_parte1_fasores.pdf | Parte1 - Fasores e Parâmetros Distribuídos - Secundários]] Slides sobre Fasores e os Parâmetros Secundários de LTs da Parte 1<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 29/08 - <math>\blacklozenge</math> Parâmetros Distribuídos - Impedância Característica das Linhas de Transmissão}}<br />
<br />
== 29/08 - <math>\blacklozenge</math> Parâmetros Distribuídos - Impedância Característica das Linhas de Transmissão ==<br />
<br />
* Equações Telegráficas das Linhas de Transmissão;<br />
* Parâmetros secundários das Linhas de Transmissão;<br />
* Impedância característica;<br />
* Exercício.<br />
<br />
<math>\blacklozenge</math> '''Atividade Extra: Entrega INDIVIDUAL até 03/09/2019, manuscrito ou impresso.'''<br />
<br />
Pesquise e selecione na internet fabricante de boa procedência de um dos tipos de cabo: par trançado (UTP, STP, ou para redes telefônicas) ou coaxial (linha RG). Procure encontrar os detalhes construtivos informados pela folha de dados do fabricante como medidas e características elétricas dos condutores e isolantes de tal modo que você consiga determinar com precisão, os valores dos parâmetros distribuídos primários do cabo (R', C', L' e G') para uma operação com ondas viajantes de 1GHz. De posse desses valores determine também os valores esperados dos parâmetros secundários do mesmo meio ('''<math> \alpha; \beta; \gamma </math>'''). Detalhe as informações, ilustrações e cálculos de todos os parâmetros calculados para futuro uso em ensaios de laboratório.<br />
<br />
Links sugestão de alguns cabos:<br />
[https://www.timesmicrowave.com/calculator/?productId=121 Times Microwave]<br />
[https://www.furukawalatam.com/pt-br/catalogo-de-produtos-categoria/FCS/produto-fcs/cabo-lan Furukawa]<br />
[https://www.nexans.com.br/eservice/Brazil-pt_BR/navigate_219588/Cabos_telefonicos.html Nexans]<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 03/09 - Linhas de Transmissão sem Perdas}}<br />
<br />
== 03/09 - Linhas de Transmissão sem Perdas ==<br />
<br />
* Constante de Propagação desconsiderando perdas;<br />
* Impedância Característica;<br />
* Parâmetros de cabos coaxiais sem perdas;<br />
* Exercícios;<br />
* Transmissão de Potência em LTs sem perdas.<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 05/09 - Transmissão de Potência em LTs com Perdas - LTs Terminadas com Carga}}<br />
<br />
== 05/09 - Transmissão de Potência em LTs com Perdas - LTs Terminadas com Carga ==<br />
<br />
* Transmissão de Potência em LTs com Perdas;<br />
* Exercício;<br />
* LTs Terminadas com Carga;<br />
* Coeficiente de Reflexão na carga;<br />
* Coeficiente de Reflexão em qquer pto da LT.<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 10/09 - Razão de Onda de Tensão Estacionária - VSWR ou ROTE}}<br />
<br />
== 10/09 - Razão de Onda de Tensão Estacionária - VSWR ou ROTE ==<br />
<br />
* Relação do Coeficiente de Reflexão com VSWR;<br />
* Exercícios;<br />
* Impedância de Entrada para LTs com perdas e sem perdas;<br />
* Cargas Complexas;<br />
* Circuitos Completos;<br />
* Exercícios.<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 12/09 - <math>\blacklozenge</math> Circuito Completo da LT - Transitórios - Resposta ao Degrau}}<br />
<br />
== 12/09 - <math>\blacklozenge</math> Circuito Completo da LT - Transitórios - Resposta ao Degrau ==<br />
<br />
* Circuito Completo da LT - Resumo e revisão;<br />
* Comparativo dos modelos de LT SEM perdas simples e com parâmetros Concentrados;<br />
* Transitórios - Resposta da LT ao Degrau;<br />
* Diagrama de Saltos ou Diagrama de Reflexão;<br />
* Exercício.<br />
* Entrega da lista de exercícios do livro texto.<br />
<br />
<math>\blacklozenge</math> '''Atividade Extra: Entrega INDIVIDUAL até 19/09/2019, manuscrito ou impresso.'''<br />
<br />
;Tarefa 1:<br />
<br />
Foi distribuída uma cópia da páginas 74 à 77 do livro texto (Wentworth) que contém o desenvolvimento de um código em MATLAB objetivando mostrar um comparativo entre as respostas da modelagem de um circuito completo de LT SEM perdas simples (considerando as ondas viajantes incidentes e refletidas vistas até aqui) e com parâmetros concentrados. Os circuitos são formados considerando Zo=50 ohms e RL=RS=200 ohms. Os gráficos comparativos mostram a relação entre a Magnitude do sinal na carga (VL) em relação ao tamanho da LT em termos de quantidade de comprimentos de onda. As diferenças entre os gráficos são muito relevantes. <br><br />
<br />
A tarefa agora é levantar os mesmos gráficos, porém considerando os parâmetros distribuídos de uma LT real com os mesmos valores de RS e RL. Fica assim designado os seguintes tipos de cabos por aluno:<br />
* Victor, Yan e Rafael: '''Usar os mesmos cabos comerciais da atividade extra solicitada em 29/08''';<br />
* Guilherme: Cabo comercial RG58 da DATALINK;<br />
* Alisson: Cabo UTP (análise de um par dos 4) Cat 5e da FURUKAWA.<br />
<br />
;Tarefa 2:<br />
<br />
Refaça o Exercício 1 da aula anterior considerando o mesmo circuito porém acrescentando nele a chave em paralelo com a fonte Vs como detalhado na figura 2.38 na página 107 do livro texto. Considere T=2ns para este exercício o qual determina a largura de pulso entre as ondas Vo e -Vo que irão propagar na linha. Levante o DIAGRAMA DE SALTOS, o gráfico de VL em relação ao tempo e o valor de VL depois de um tempo suficientemente grande quando não houver mais reflexões na LT.<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 17/09 - Respostas às Terminações de Sinais Digitais - TDR }}<br />
<br />
== 17/09 - Respostas às Terminações de Sinais Digitais - TDR ==<br />
<br />
* Terminações com diodos Schottky;<br />
* Cargas Reativas em transitórios;<br />
* Reflectômetro no Domínio do Tempo (TDR)<br />
* Dispersão em sinais digitais;<br />
* [[media:wentworth_cap2_parcial.pdf | slides com figuras de apoio]]<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 19/09 - Laboratório - Medições de SWR em cabos reais - Exercícios de Revisão}}<br />
<br />
== 19/09 - Laboratório - Medições de SWR em cabos reais - Exercícios de Revisão ==<br />
<br />
* Laboratório - Medições de SWR em cabos reais;<br />
* Exercícios de Revisão<br />
<br />
== Experimentos: Velocidade e comprimento da linha de transmissão e Descasamento de impedância e Onda Estacionária ==<br />
<br />
<br />
; Objetivos do experimento:<br />
<br />
- Realizar medições da tensão e do tempo de propagação em linhas descasadas.<br />
- Obter a velocidade da onda na linha conhecendo seu comprimento e o tempo de propagação do pulso.<br />
- Conhecer o método de identificação do local de ocorrência de curto ou linha aberta através da análise da reflexão no domínio do tempo.<br />
- Verificar o comportamento do pulso refletido para as situações de Zo < ZL, Zo=ZL e Zo>ZL.<br />
- Estimar a impedância de uma linha de transmissão.<br />
- Estimar o comprimento da onda numa linha de transmissão.<br />
<br />
; Material necessário:<br />
<br />
a) Cabo coaxial RG58, Zo = 50 Ohms<br />
b) Terminador de 50 Ohms.<br />
c) Par trançado.<br />
d) Balun 75-100 Ohms<br />
e) Potênciometro de 450 Ohms<br />
f) Multímetro.<br />
g) Osciloscópio.<br />
h) Conector coaxial do tipo T.<br />
i) Gerador de sinal.<br />
j) Analisador de espectro.<br />
k) Trena.<br />
<br />
; Procedimentos.<br />
<br />
=== Primeira parte ===<br />
<br />
1. Colocar o conector T na entrada do canal 1 do osciloscópio.<br />
2. Conectar o gerador de função numa das extremidades do conector T.<br />
3. Conectar o cabo coaxial na outra extremidade do conector T.<br />
4. Ajustar no gerador de sinal um pulso com largura de 20ns, período de 1ms e valor de pico de 2V.<br />
5. Com a extremidade da linha em aberto verificar o pulso refletido, anotar sua amplitude e a diferença de tempo entre o início do pulso enviado pelo gerador e o início do pulso refletido pela linha. Salvar a tela do osciloscópio.<br />
6. Com a extremidade da linha em curto verificar o pulso refletido, anotar sua amplitude e a diferença de tempo entre o início do pulso enviado pelo gerador e o início do pulso refletido pela linha. Salvar a tela do osciloscópio.<br />
7. Com a linha casada verificar o que ocorre com o o pulso refletido. Salvar a tela do osciloscópio.<br />
8. Medir o comprimento do cabo.<br />
<br />
<br />
<br />
=== Segunda parte ===<br />
<br />
1. Colocar o conector T na entrada do canal 1 do osciloscópio.<br />
2. Conectar o gerador de função numa das extremidades do conector T.<br />
3. Conectar o par trançado ao Balun e este a outra extremidada de conector T.<br />
4. Ajustar no gerador de sinal um pulso com largura de 20ns, período de 1ms e valor de pico de 2V.<br />
5. Ajustar o potênciomentro para Z= 0 W e conecta-lo a extremidade livre do par trançado.<br />
6. Anotar as amplitudes dos pulsos e a diferença de tempo entre o início do pulso enviado pelo gerador e o início do pulso refletido pela linha. Salvar a tela do osciloscópio.<br />
7. Repetir os passos 5 e 6 para os valores de resistência de 50, 100, 150 e 450 W<br />
8. Com a extremidade da linha em curto verificar o pulso refletido, anotar sua amplitude e a diferença de tempo entre o início do pulso enviado pelo gerador e o início do pulso refletido pela linha. Salvar a tela do osciloscópio.<br />
9. Com o potênciomentro conectado a linha variar a sua resistência e encontrar o valor mais próximo da impedância da linha. Desconecte o potênciometro da linha e meça o valor da resistência.<br />
10. Meça o comprimento do cabo.<br />
<br />
=== Terceira parte. ===<br />
<br />
1. Conectar o cabo coaxial com a terminação em aberto e cortes do isolante no gerador de sinal de alta frequência.<br />
2. Conectar uma ponteira de osciloscópio no analisador de espectro.<br />
3. Ajustar o sinal do gerador para uma onda senoidal de 400 mV de nível e 1GHz de frequência.<br />
4. Com a terminação do cabo em aberto medir em cada ponto de acesso do cabo o valor do nível de tensão. Anote os valores adequadamente.<br />
5. Medir com a trena a distância entre cada ponto no qual foi coletado a medida e a extremidade final do cabo.<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 23/09 - Laboratório - Medições de atenuação e defasagem de onda}}<br />
<br />
== 23/09 - Laboratório - Medições de atenuação e defasagem de onda ==<br />
<br />
<br />
== Experimentos: Roteiro distribuído em sala ==<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 26/09 - Avaliação A1}}<br />
<br />
== 26/09 - Avaliação A1 ==<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 01/10 - Carta de Smith}}<br />
<br />
== 01/10 - Carta de Smith ==<br />
<br />
* Introdução e interpretação da [[media:SmithChart.pdf |Carta de Smith]].<br />
* [[media:Smith.pdf | Slides de apoio]] (professora Evanaska)<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 03/10 - Correção Avaliação A1 }}<br />
<br />
== 03/10 - Correção Avaliação A1 ==<br />
<br />
* Correção avaliação A1<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 08/10 - Carta de Smith - Casamento de Impedâncias}}<br />
<br />
== 08/10 - Carta de Smith - Casamento de Impedâncias ==<br />
<br />
* Casamento de Impedâncias segundo carta de Smith.<br />
* [[media:Smith_casamento_misto.pdf | Slides de apoio sobre Casamento misto de Impedâncias em LTs]] (professora Evanaska)<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 10/10 - Recuperação Avaliação A1 }}<br />
<br />
== 10/10 - Recuperação Avaliação A1 ==<br />
<br />
* Recuperação Avaliação A1<br />
<br />
{{Collapse bottom}}<br />
<br />
{{ENGTELECO}}</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=MIC29004-2019-2&diff=162080MIC29004-2019-22019-10-08T14:30:36Z<p>127.0.0.1: /* Homework */</p>
<hr />
<div>= Microprocessadores: Diário de Aula 2019-2=<br />
<br />
*'''Professor:''' [[Roberto de Matos]]<br />
*'''Encontros:''' 2ª e 3ª feira às 9:40h<br />
*'''Atendimento Paralelo:''' 4ª às 10h e 14h (1h cada)<br />
* [[MIC-EngTel_(Plano_de_Ensino) |Plano de Ensino]]<br />
* [[Cronograma_de_atividades_(MIC-EngTel) | Cronograma de Aulas]]<br />
* [http://docente.ifsc.edu.br/roberto.matos/mic_public/2019-2/notas_MIC29004_2019-2.pdf Notas]<br />
<br />
== Material ==<br />
*[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/ApostilaMemorias.pdf Apostila Memória]<br />
*[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_1-memoria.pdf Slides Memória]<br />
<!--<br />
*[[Media:mic-slides_2-handout.pdf|Introdução a Microprocessadores]]<br />
*[[Media:bip.pdf|Arquitetura e Organização do BIP]]<br />
--><br />
<br />
==Listas de Exercício==<br />
* [[MIC29004-lista1 | Lista de Exercícios: Memória, Arquitetura, Organização e BIP]]<br />
*[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/Exercícios-sobre-a-programação-do-BIP.pdf Lista Introdução a programação do BIP]<br />
* [[MIC29004-lista2-avr | Lista de Exercícios Microcontroladores e AVR]]<br />
<br />
= Aula 29/07/2019: Apresentação =<br />
* Apresentação do professor.<br />
* Apresentação da disciplina: conteúdo, bibliografia e avaliação.<br />
<br />
<br />
= Aula 30/07/2019: Introdução sobre Memória =<br />
*[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/ApostilaMemorias.pdf Apostila Memória]<br />
*[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_1-memoria.pdf Slides Memória]<br />
<br />
*[[MIC29004-lista1 | Lista de Exercícios: Memória, Arquitetura, Organização e BIP]]<br />
<br />
<br />
==Diagrama em blocos da memória e barramentos==<br />
No diagrama abaixo está representado um bloco de memória primária de 16x8 (dezesseis endereços por 8 bits).<br />
*Note que uma posição de memória pode ser vista como uma caixa que possue um endereço e um conteúdo. <br />
*O conteúdo associado a posição de memória é uma palavra binária e, neste caso, possui 8 bits.<br />
<br />
[[imagem:DiagramaBlocosMemorias2.jpg|500px|center]]<br />
<br />
Para que us dispositivo externo possa "acessar" a memória para leitura ou escrita, ele deve se utilizar de um conjunto de fios que chamamos de barramentos.<br />
<br />
===Barramento de Endereços===<br />
<br />
Este barramento permite determinar o endereço de uma posição a ser acessada na memória.<br />
Um barramento de 4 linhas de endereço é designado por A3,A2,A1 e A0.<br />
<br />
Supondo uma memória com endereços designados da forma hexadecimal de 0h a Fh. Supondo que A3<br />
seja associado ao bit mais significativo e A0 ao bit menos significativo. Então, para acessar<br />
a posição Bh de memória, deve-se injetar A3=1, A2=0, A1=1 e A0=1. Note que <math> B_h = 1011_b </math><br />
<br />
O termo "injetar" significa aqui que um dispositivo externo deve forçar tensão nas linhas do barramento.<br />
Esta tensão depende da tecnologia utilizada. Poderia ser, por exemplo, 5V para o nível lógico 1 e 0V par ao nível lógico 0.,<br />
<br />
<br />
<br />
= Aula 04/08/2019: Laboratório de Memória - Introdução =<br />
<br />
*'''Notas de Aula:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_1-memoria.pdf Slides Memória]<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic_slides_1-memoria_tabela_associacao.pdf Exemplos de Associação de Memória]<br />
<br />
* '''Material de Apoio (Decodificadores):'''<br />
**[http://www.electronics-tutorials.ws/combination/comb_5.html Tutorial]<br />
**[http://www.skot9000.com/ttl/datasheets/139.pdf 74LS139]<br />
<br />
<br />
*'''Experimento 1 - Memória 16x4:'''<br />
#Entrar no Windows.<br />
#Baixar o arquivo de projeto [http://docente.ifsc.edu.br/roberto.matos/mic_public/labs/lab1-memoria.zip aqui]. Coloque em um diretório conhecido.<br />
#Descompacte. Clique sobre o arquivo *.pdsprj. O PROTEUS será executado e o projeto aberto.<br />
#Observe que o projeto está parcialmente pronto. Você pode entrar em modo simulação.<br />
#O sistema está preparado para que se possa inserir ou ler manualmente posições de memória.<br />
#Leia todas as 16 posições de memória e anote os valores.<br />
#Grave o número da sua matrícula na memória. Preencha o restante com zero.<br />
#Note o Chip Select está habilitado sempre. Coloque uma chave adicional para colocar o Chip Select.<br />
<br />
<br />
*'''Atividade 1 - Associação de Memórias:'''<br />
**Usando como referência o experimento 1 e os exemplos de associação de memória vistos em sala de aula, implemente o seguinte:<br />
:# Uma memória 16x8<br />
:# Uma memória 64x4<br />
:# Uma memória 64x8<br />
*Entrega:<br />
**Fazer em Duplas<br />
**Última Aula de dúvidas: 06/08 (segunda)<br />
**Apresentação: 07/08 (terça)<br />
<br />
= Aula 12/08/2019: Laboratório de Memória - Associação =<br />
* Finalizar o Exercício<br />
<br />
= Aula 13/08/2019: Introdução à Arquitetura e Organização de Computadores =<br />
<br />
*'''Objetivos:'''<br />
** Introdução a Microprocessadores<br />
<br />
*'''Notas de Aula:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_2-Arquitetura_e_Bip.pdf Introdução à Arquitetura e Organização de Computadores]<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_3-Projetando_um_Computador_slides.pdf Projetando um Computador - BIP]<br />
<br />
* '''Experimento:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/Exercícios-sobre-a-programação-do-BIP.pdf Lista Introdução a programação do BIP]<br />
<br />
<br />
= Aula 19/08/2019: Arquitetura BIP =<br />
<br />
*'''Objetivos:'''<br />
** Entender a Arquitetura BIP<br />
** Programar em Assembly o BIP<br />
<br />
*'''Notas de Aula:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_3-Projetando_um_Computador_slides.pdf Projetando um Computador - BIP]<br />
<br />
* '''Experimento:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/Exercícios-sobre-a-programação-do-BIP.pdf Lista Introdução a programação do BIP]<br />
<br />
<br />
= Aula 20/08/2019: Organização do BIP =<br />
*'''Objetivos:'''<br />
** Entender a Organização do BIP<br />
** Criar tabela de decodificação do BIP<br />
<br />
*'''Notas de Aula:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_3-Projetando_um_Computador_slides.pdf Projetando um Computador - BIP]<br />
<br />
*'''Software Utilizado:'''<br />
**[http://bipide.com.br/ BIP IDE]<br />
<br />
<br />
= Aula 26/08/2019: Decodificador BIP =<br />
<br />
*'''Objetivos:'''<br />
** Entender a execução do BIP passo-a-passo no Proteus<br />
** Implementar o circuito decodificador do BIP no Proteus<br />
** Entender as mudanças da arquitetura e da organização do BIP II<br />
<br />
*'''Experimento:'''<br />
** [[Experimento_BIP_I | Experimento BIP I]]<br />
<br />
<br />
= Aula 27/08/2019: Decodificador BIP (cont.) e BIP II=<br />
<br />
*'''Objetivos:'''<br />
** Finalizar o Decode do BIP<br />
** Introdução da arquitetura do BIP II<br />
<br />
*'''Exercícios:'''<br />
** Implementar e simular exemplos com as instruções de desvio do BIP II<br />
<br />
<br />
= Aula 02/09/2019: Organização do BIP II =<br />
*'''Objetivos:'''<br />
**Entender as mudanças da arquitetura e da organização do BIP II<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/Artigo-BIP.pdf Artigo BIP II]<br />
<br />
*'''Experimento:'''<br />
** [http://docente.ifsc.edu.br/roberto.matos/mic_public/labs/codigos_bip2.zip Instruções de Desvio BIP II]<br />
<br />
*'''Exercício:'''<br />
** Implementar as mudanças da organização do BIP para criar o BIP II <br />
** Implementar o decodificador do BIP II ([http://www.32x8.com/ 32x8])<br />
** Implementar programas de testes no assembly do BIP II<br />
** Trabalho em Dupla<br />
** Entrega 08/09 e Apresentação 10/09<br />
<br />
= Aula 03/09/2019: Dúvidas Lista de Exercício e Apoio Trabalho BIP II =<br />
*'''Objetivos:'''<br />
** Aula de dúvidas<br />
<br />
*'''Objetivos:'''<br />
** Dúvidas da [[MIC29004-lista1 | Lista de Exercícios: Memória, Arquitetura, Organização e BIP]] para prova I.<br />
<br />
<br />
= Aula 09/09/2019: Prova I =<br />
*'''Objetivos:'''<br />
** Avaliação dos conceitos de Memória, Arquitetura e Organização, BIP I e II<br />
<br />
= Aula 10/09/2019: Apresentação Trabalho BIP II=<br />
*'''Objetivos:'''<br />
** Apresentação do Trabalho BIP II<br />
<br />
<br />
= Aula 16/09/2019: Correção da Prova=<br />
*'''Objetivos:'''<br />
** Correção da avaliação para completar o processo de ensino-aprendizagem.<br />
<br />
*'''Notas:'''<br />
* Foi decidido junto à turma que o péssimo resultado da avaliação será recuperado no fim do semestre. <br />
* O professor se colocou à disposição para recuperar o conteúdo durante o semestre, tirando dúvidas em sala de aula ou no horário de atendimento. <br />
* Os alunos se comprometeram em recuperar o conteúdo, pois é essencial para a continuidade da disciplina.<br />
<br />
= Aula 17/09/2019: Introdução aos Microcontroladores =<br />
*'''Objetivos:'''<br />
** Entender os conceitos e diferenças entre um Processador e um Microcontrolador. <br />
** Introdução à aplicações microcontroladas<br />
<br />
*'''Notas de Aulas:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_4-Intro_Microcontroladores_CISC_RISC.pdf Introdução aos Microcontroladores, CISC vs. RISC]<br />
<br />
*'''Notas Extras:'''<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/30010135D.pdf Referência Rápida Família AVR]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/30009630M.pdf Overview Microcontroladores Microchip]<br />
<br />
==Homework==<br />
* [http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf Datasheet Atmega328p]<br />
<br />
*Ler:<br />
** 2. Visão Geral<br />
** 7. Núcleo AVR <br />
** Responder:<br />
*** Qual arquitetura de memória usada? <br />
*** Detalhes da ALU (Quais os tipos de operação?)<br />
*** Registradores (Status, Uso geral e de Pilha)<br />
*** Modos de endereçamento<br />
*** Conjunto de instruções (classes e exemplos)<br />
<br />
* Ler: <br />
** 8. Memórias do AVR<br />
*** Flash<br />
*** SRAM<br />
*** EEPROM<br />
** Responder<br />
*** Qual o tamanho e o formato da palavra de de dados?<br />
*** Qual o tamanho e o formato da palavra de instrução?<br />
<br />
= Aula 23/09/2019: Arquitetura do AVR =<br />
<br />
*'''Objetivos:'''<br />
** Finalizar CISC vs. RISC<br />
** Visão Geral dos Microcontroladores ATmega48A/PA/88A/PA/168A/PA/328/P<br />
** Núcleo do AVR (ALU e Banco de Registradores)<br />
** Hierarquia de Memórias do AVR<br />
<br />
*'''Notas de Aulas:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_5-AVR.pdf Introdução AVR]<br />
<br />
*'''Notas Extras:'''<br />
**Die do [https://siliconpr0n.org/archive/doku.php?id=azonenberg:atmel:atmega48 ATmega48] e do [https://siliconpr0n.org/archive/doku.php?id=azonenberg:atmel:atmega328 ATmega328]<br />
<br />
= Aula 23/09/2019: Arquitetura do AVR (cont.) =<br />
<br />
*'''Objetivos:'''<br />
** Finalizar os objetivos da última aula<br />
<br />
*'''Notas de Aulas:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/slides-AVR_aula01.pdf Introdução AVR]<br />
<br />
*'''Experimento:'''<br />
** Simulação do primeiro código em Assembly usando o MPLAB X IDE <br />
** [[Simular Assembly do AVR no MPLAB IDE | Criar projeto]]<br />
<code><br />
start:<br />
inc r16<br />
inc r17<br />
sts $0100,r16<br />
sts $0101,r16<br />
rjmp start<br />
</syntaxhighlight><br />
<br />
==Homework==<br />
* Instalar o MPLAB X e o XC8: [[Setup Ferramentas AVR para Assembly]]<br />
* Rodar o exemplo da aula para verificar<br />
<br />
<br />
= Aula 30/09/2019: Modos de Endereçamento =<br />
*'''Objetivos:'''<br />
**Introduzir arquitetura Load-Store<br />
**Entender: <br />
***Modos de endereçamento do AVR e <br />
***Instruções relacionadas a cada modo do ATmega328p<br />
**Implementar programas para compreensão dos novos conceitos<br />
<br />
*'''Notas de Aulas:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/slides-AVR_aula02.pdf Modos de Endereçamento]<br />
<br />
==Homework==<br />
* OBS.: Instalar e configurar as ferramentas em casa para quem não fez (ver homework da aula passada).<br />
<br />
===Exercício 1===<br />
* Testar '''TODOS''' os trechos de códigos apresentados. Modifique os valores das localizações de memória afetadas para verificar se o funcionamento está coerente. <br />
<br />
*Exemplo:<br />
<code><br />
start:<br />
ldi R16,0x14<br />
rjmp start<br />
</syntaxhighlight><br />
* Pergunte-se:<br />
** A instrução em linguagem de máquina está coerente?<br />
** Se mudar o valor do imediato 0x14 para 0x25, como afeta a instrução montada? E se mudar o registrador de R16 para R17?<br />
** Eu posso carregar um imediato para o registrador R0? Por quê?<br />
* Faça isso para todos os trechos de código apresentados.<br />
<br />
===Exercício 2===<br />
*Faça um programa que some dois números de 8 bits: '''C = A + B'''<br />
*Considere as varáveis armazenadas sequencialmente a partir do primeiro endereço da memória SRAM.<br />
<br />
<br />
= Aula 01/10/2019: Modos de Endereçamento (cont.) =<br />
*'''Objetivos:'''<br />
**Corrigir exercícios da Aula prática<br />
**Mais exercícios<br />
<br />
*'''Exercícios: '''<br />
** Some as constantes 25, 14 e 0x32 e armazene o resultado em R0.<br />
** Some as constantes 32 e 0x23 e armazene o resultado em uma variável na SRAM (endereço 0x010A).<br />
**Re-implemente o código abaixo usando endereçamento indireto para acessar o R20 como posição de memória na SRAM:<br />
:<code><br />
ldi r16, $BB<br />
mov r20, r16<br />
</syntaxhighlight><br />
<br />
<br />
==Homework==<br />
* Estudar instruções lógicas e aritméticas, de desvio (CPSE até BRID), bit e bit-test<br />
* Escrever códigos que:<br />
#Execute 1.000 vezes uma ação em loop.<br />
#Execute 100.000 vezes uma ação em loop.<br />
#Carregue na SRAM 10 valores sequenciais a partir do endereço 0x0102 usando endereçamento de dados indireto com pós-incremento.<br />
#Tenha o mesmo resultado do programa anterior, mas que utilize endereçamento de dados indireto com pré-decremento.<br />
<br />
*Links:<br />
**https://www.microchip.com/webdoc/avrassembler/avrassembler.wb_instruction_list.html<br />
**http://ww1.microchip.com/downloads/en/devicedoc/atmel-0856-avr-instruction-set-manual.pdf<br />
<br />
= Aula 07/10/2019: Instruções Aritmética e desvio =<br />
*'''Objetivos:'''<br />
**Corrigir exercícios da Aula prática<br />
**Mais exercícios<br />
<br />
*'''Exercícios: '''<br />
**Faça programas que utilizem a rotação para esquerda e direita. Quais os tipos de rotação possível? Quais os bits de status podem ser modificados?<br />
** Faça a soma de dois valores de 16 bits usando os registradores.<br />
** Implemente estrutura de alto nível: IF-THEN-ELSE, WHILE e SWITCH-CASE<br />
<br />
<br />
= Aula 08/10/2019: Instruções Aritmética e desvio (cont.) =<br />
<br />
<br />
==Homework==<br />
*Some duas variáveis de 16-bits da memória SRAM e devolva o resultado em outra variável na SRAM.<br />
*Implemente estrutura de alto nível: IF-THEN-ELSE, WHILE e SWITCH-CASE</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=MIC29004-2019-2&diff=162079MIC29004-2019-22019-10-08T14:14:36Z<p>127.0.0.1: /* Aula 08/10/2019: Instruções Aritmética e desvio (cont.) */</p>
<hr />
<div>= Microprocessadores: Diário de Aula 2019-2=<br />
<br />
*'''Professor:''' [[Roberto de Matos]]<br />
*'''Encontros:''' 2ª e 3ª feira às 9:40h<br />
*'''Atendimento Paralelo:''' 4ª às 10h e 14h (1h cada)<br />
* [[MIC-EngTel_(Plano_de_Ensino) |Plano de Ensino]]<br />
* [[Cronograma_de_atividades_(MIC-EngTel) | Cronograma de Aulas]]<br />
* [http://docente.ifsc.edu.br/roberto.matos/mic_public/2019-2/notas_MIC29004_2019-2.pdf Notas]<br />
<br />
== Material ==<br />
*[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/ApostilaMemorias.pdf Apostila Memória]<br />
*[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_1-memoria.pdf Slides Memória]<br />
<!--<br />
*[[Media:mic-slides_2-handout.pdf|Introdução a Microprocessadores]]<br />
*[[Media:bip.pdf|Arquitetura e Organização do BIP]]<br />
--><br />
<br />
==Listas de Exercício==<br />
* [[MIC29004-lista1 | Lista de Exercícios: Memória, Arquitetura, Organização e BIP]]<br />
*[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/Exercícios-sobre-a-programação-do-BIP.pdf Lista Introdução a programação do BIP]<br />
* [[MIC29004-lista2-avr | Lista de Exercícios Microcontroladores e AVR]]<br />
<br />
= Aula 29/07/2019: Apresentação =<br />
* Apresentação do professor.<br />
* Apresentação da disciplina: conteúdo, bibliografia e avaliação.<br />
<br />
<br />
= Aula 30/07/2019: Introdução sobre Memória =<br />
*[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/ApostilaMemorias.pdf Apostila Memória]<br />
*[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_1-memoria.pdf Slides Memória]<br />
<br />
*[[MIC29004-lista1 | Lista de Exercícios: Memória, Arquitetura, Organização e BIP]]<br />
<br />
<br />
==Diagrama em blocos da memória e barramentos==<br />
No diagrama abaixo está representado um bloco de memória primária de 16x8 (dezesseis endereços por 8 bits).<br />
*Note que uma posição de memória pode ser vista como uma caixa que possue um endereço e um conteúdo. <br />
*O conteúdo associado a posição de memória é uma palavra binária e, neste caso, possui 8 bits.<br />
<br />
[[imagem:DiagramaBlocosMemorias2.jpg|500px|center]]<br />
<br />
Para que us dispositivo externo possa "acessar" a memória para leitura ou escrita, ele deve se utilizar de um conjunto de fios que chamamos de barramentos.<br />
<br />
===Barramento de Endereços===<br />
<br />
Este barramento permite determinar o endereço de uma posição a ser acessada na memória.<br />
Um barramento de 4 linhas de endereço é designado por A3,A2,A1 e A0.<br />
<br />
Supondo uma memória com endereços designados da forma hexadecimal de 0h a Fh. Supondo que A3<br />
seja associado ao bit mais significativo e A0 ao bit menos significativo. Então, para acessar<br />
a posição Bh de memória, deve-se injetar A3=1, A2=0, A1=1 e A0=1. Note que <math> B_h = 1011_b </math><br />
<br />
O termo "injetar" significa aqui que um dispositivo externo deve forçar tensão nas linhas do barramento.<br />
Esta tensão depende da tecnologia utilizada. Poderia ser, por exemplo, 5V para o nível lógico 1 e 0V par ao nível lógico 0.,<br />
<br />
<br />
<br />
= Aula 04/08/2019: Laboratório de Memória - Introdução =<br />
<br />
*'''Notas de Aula:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_1-memoria.pdf Slides Memória]<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic_slides_1-memoria_tabela_associacao.pdf Exemplos de Associação de Memória]<br />
<br />
* '''Material de Apoio (Decodificadores):'''<br />
**[http://www.electronics-tutorials.ws/combination/comb_5.html Tutorial]<br />
**[http://www.skot9000.com/ttl/datasheets/139.pdf 74LS139]<br />
<br />
<br />
*'''Experimento 1 - Memória 16x4:'''<br />
#Entrar no Windows.<br />
#Baixar o arquivo de projeto [http://docente.ifsc.edu.br/roberto.matos/mic_public/labs/lab1-memoria.zip aqui]. Coloque em um diretório conhecido.<br />
#Descompacte. Clique sobre o arquivo *.pdsprj. O PROTEUS será executado e o projeto aberto.<br />
#Observe que o projeto está parcialmente pronto. Você pode entrar em modo simulação.<br />
#O sistema está preparado para que se possa inserir ou ler manualmente posições de memória.<br />
#Leia todas as 16 posições de memória e anote os valores.<br />
#Grave o número da sua matrícula na memória. Preencha o restante com zero.<br />
#Note o Chip Select está habilitado sempre. Coloque uma chave adicional para colocar o Chip Select.<br />
<br />
<br />
*'''Atividade 1 - Associação de Memórias:'''<br />
**Usando como referência o experimento 1 e os exemplos de associação de memória vistos em sala de aula, implemente o seguinte:<br />
:# Uma memória 16x8<br />
:# Uma memória 64x4<br />
:# Uma memória 64x8<br />
*Entrega:<br />
**Fazer em Duplas<br />
**Última Aula de dúvidas: 06/08 (segunda)<br />
**Apresentação: 07/08 (terça)<br />
<br />
= Aula 12/08/2019: Laboratório de Memória - Associação =<br />
* Finalizar o Exercício<br />
<br />
= Aula 13/08/2019: Introdução à Arquitetura e Organização de Computadores =<br />
<br />
*'''Objetivos:'''<br />
** Introdução a Microprocessadores<br />
<br />
*'''Notas de Aula:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_2-Arquitetura_e_Bip.pdf Introdução à Arquitetura e Organização de Computadores]<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_3-Projetando_um_Computador_slides.pdf Projetando um Computador - BIP]<br />
<br />
* '''Experimento:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/Exercícios-sobre-a-programação-do-BIP.pdf Lista Introdução a programação do BIP]<br />
<br />
<br />
= Aula 19/08/2019: Arquitetura BIP =<br />
<br />
*'''Objetivos:'''<br />
** Entender a Arquitetura BIP<br />
** Programar em Assembly o BIP<br />
<br />
*'''Notas de Aula:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_3-Projetando_um_Computador_slides.pdf Projetando um Computador - BIP]<br />
<br />
* '''Experimento:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/Exercícios-sobre-a-programação-do-BIP.pdf Lista Introdução a programação do BIP]<br />
<br />
<br />
= Aula 20/08/2019: Organização do BIP =<br />
*'''Objetivos:'''<br />
** Entender a Organização do BIP<br />
** Criar tabela de decodificação do BIP<br />
<br />
*'''Notas de Aula:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_3-Projetando_um_Computador_slides.pdf Projetando um Computador - BIP]<br />
<br />
*'''Software Utilizado:'''<br />
**[http://bipide.com.br/ BIP IDE]<br />
<br />
<br />
= Aula 26/08/2019: Decodificador BIP =<br />
<br />
*'''Objetivos:'''<br />
** Entender a execução do BIP passo-a-passo no Proteus<br />
** Implementar o circuito decodificador do BIP no Proteus<br />
** Entender as mudanças da arquitetura e da organização do BIP II<br />
<br />
*'''Experimento:'''<br />
** [[Experimento_BIP_I | Experimento BIP I]]<br />
<br />
<br />
= Aula 27/08/2019: Decodificador BIP (cont.) e BIP II=<br />
<br />
*'''Objetivos:'''<br />
** Finalizar o Decode do BIP<br />
** Introdução da arquitetura do BIP II<br />
<br />
*'''Exercícios:'''<br />
** Implementar e simular exemplos com as instruções de desvio do BIP II<br />
<br />
<br />
= Aula 02/09/2019: Organização do BIP II =<br />
*'''Objetivos:'''<br />
**Entender as mudanças da arquitetura e da organização do BIP II<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/Artigo-BIP.pdf Artigo BIP II]<br />
<br />
*'''Experimento:'''<br />
** [http://docente.ifsc.edu.br/roberto.matos/mic_public/labs/codigos_bip2.zip Instruções de Desvio BIP II]<br />
<br />
*'''Exercício:'''<br />
** Implementar as mudanças da organização do BIP para criar o BIP II <br />
** Implementar o decodificador do BIP II ([http://www.32x8.com/ 32x8])<br />
** Implementar programas de testes no assembly do BIP II<br />
** Trabalho em Dupla<br />
** Entrega 08/09 e Apresentação 10/09<br />
<br />
= Aula 03/09/2019: Dúvidas Lista de Exercício e Apoio Trabalho BIP II =<br />
*'''Objetivos:'''<br />
** Aula de dúvidas<br />
<br />
*'''Objetivos:'''<br />
** Dúvidas da [[MIC29004-lista1 | Lista de Exercícios: Memória, Arquitetura, Organização e BIP]] para prova I.<br />
<br />
<br />
= Aula 09/09/2019: Prova I =<br />
*'''Objetivos:'''<br />
** Avaliação dos conceitos de Memória, Arquitetura e Organização, BIP I e II<br />
<br />
= Aula 10/09/2019: Apresentação Trabalho BIP II=<br />
*'''Objetivos:'''<br />
** Apresentação do Trabalho BIP II<br />
<br />
<br />
= Aula 16/09/2019: Correção da Prova=<br />
*'''Objetivos:'''<br />
** Correção da avaliação para completar o processo de ensino-aprendizagem.<br />
<br />
*'''Notas:'''<br />
* Foi decidido junto à turma que o péssimo resultado da avaliação será recuperado no fim do semestre. <br />
* O professor se colocou à disposição para recuperar o conteúdo durante o semestre, tirando dúvidas em sala de aula ou no horário de atendimento. <br />
* Os alunos se comprometeram em recuperar o conteúdo, pois é essencial para a continuidade da disciplina.<br />
<br />
= Aula 17/09/2019: Introdução aos Microcontroladores =<br />
*'''Objetivos:'''<br />
** Entender os conceitos e diferenças entre um Processador e um Microcontrolador. <br />
** Introdução à aplicações microcontroladas<br />
<br />
*'''Notas de Aulas:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_4-Intro_Microcontroladores_CISC_RISC.pdf Introdução aos Microcontroladores, CISC vs. RISC]<br />
<br />
*'''Notas Extras:'''<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/30010135D.pdf Referência Rápida Família AVR]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/30009630M.pdf Overview Microcontroladores Microchip]<br />
<br />
==Homework==<br />
* [http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf Datasheet Atmega328p]<br />
<br />
*Ler:<br />
** 2. Visão Geral<br />
** 7. Núcleo AVR <br />
** Responder:<br />
*** Qual arquitetura de memória usada? <br />
*** Detalhes da ALU (Quais os tipos de operação?)<br />
*** Registradores (Status, Uso geral e de Pilha)<br />
*** Modos de endereçamento<br />
*** Conjunto de instruções (classes e exemplos)<br />
<br />
* Ler: <br />
** 8. Memórias do AVR<br />
*** Flash<br />
*** SRAM<br />
*** EEPROM<br />
** Responder<br />
*** Qual o tamanho e o formato da palavra de de dados?<br />
*** Qual o tamanho e o formato da palavra de instrução?<br />
<br />
= Aula 23/09/2019: Arquitetura do AVR =<br />
<br />
*'''Objetivos:'''<br />
** Finalizar CISC vs. RISC<br />
** Visão Geral dos Microcontroladores ATmega48A/PA/88A/PA/168A/PA/328/P<br />
** Núcleo do AVR (ALU e Banco de Registradores)<br />
** Hierarquia de Memórias do AVR<br />
<br />
*'''Notas de Aulas:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_5-AVR.pdf Introdução AVR]<br />
<br />
*'''Notas Extras:'''<br />
**Die do [https://siliconpr0n.org/archive/doku.php?id=azonenberg:atmel:atmega48 ATmega48] e do [https://siliconpr0n.org/archive/doku.php?id=azonenberg:atmel:atmega328 ATmega328]<br />
<br />
= Aula 23/09/2019: Arquitetura do AVR (cont.) =<br />
<br />
*'''Objetivos:'''<br />
** Finalizar os objetivos da última aula<br />
<br />
*'''Notas de Aulas:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/slides-AVR_aula01.pdf Introdução AVR]<br />
<br />
*'''Experimento:'''<br />
** Simulação do primeiro código em Assembly usando o MPLAB X IDE <br />
** [[Simular Assembly do AVR no MPLAB IDE | Criar projeto]]<br />
<code><br />
start:<br />
inc r16<br />
inc r17<br />
sts $0100,r16<br />
sts $0101,r16<br />
rjmp start<br />
</syntaxhighlight><br />
<br />
==Homework==<br />
* Instalar o MPLAB X e o XC8: [[Setup Ferramentas AVR para Assembly]]<br />
* Rodar o exemplo da aula para verificar<br />
<br />
<br />
= Aula 30/09/2019: Modos de Endereçamento =<br />
*'''Objetivos:'''<br />
**Introduzir arquitetura Load-Store<br />
**Entender: <br />
***Modos de endereçamento do AVR e <br />
***Instruções relacionadas a cada modo do ATmega328p<br />
**Implementar programas para compreensão dos novos conceitos<br />
<br />
*'''Notas de Aulas:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/slides-AVR_aula02.pdf Modos de Endereçamento]<br />
<br />
==Homework==<br />
* OBS.: Instalar e configurar as ferramentas em casa para quem não fez (ver homework da aula passada).<br />
<br />
===Exercício 1===<br />
* Testar '''TODOS''' os trechos de códigos apresentados. Modifique os valores das localizações de memória afetadas para verificar se o funcionamento está coerente. <br />
<br />
*Exemplo:<br />
<code><br />
start:<br />
ldi R16,0x14<br />
rjmp start<br />
</syntaxhighlight><br />
* Pergunte-se:<br />
** A instrução em linguagem de máquina está coerente?<br />
** Se mudar o valor do imediato 0x14 para 0x25, como afeta a instrução montada? E se mudar o registrador de R16 para R17?<br />
** Eu posso carregar um imediato para o registrador R0? Por quê?<br />
* Faça isso para todos os trechos de código apresentados.<br />
<br />
===Exercício 2===<br />
*Faça um programa que some dois números de 8 bits: '''C = A + B'''<br />
*Considere as varáveis armazenadas sequencialmente a partir do primeiro endereço da memória SRAM.<br />
<br />
<br />
= Aula 01/10/2019: Modos de Endereçamento (cont.) =<br />
*'''Objetivos:'''<br />
**Corrigir exercícios da Aula prática<br />
**Mais exercícios<br />
<br />
*'''Exercícios: '''<br />
** Some as constantes 25, 14 e 0x32 e armazene o resultado em R0.<br />
** Some as constantes 32 e 0x23 e armazene o resultado em uma variável na SRAM (endereço 0x010A).<br />
**Re-implemente o código abaixo usando endereçamento indireto para acessar o R20 como posição de memória na SRAM:<br />
:<code><br />
ldi r16, $BB<br />
mov r20, r16<br />
</syntaxhighlight><br />
<br />
<br />
==Homework==<br />
* Estudar instruções lógicas e aritméticas, de desvio (CPSE até BRID), bit e bit-test<br />
* Escrever códigos que:<br />
#Execute 1.000 vezes uma ação em loop.<br />
#Execute 100.000 vezes uma ação em loop.<br />
#Carregue na SRAM 10 valores sequenciais a partir do endereço 0x0102 usando endereçamento de dados indireto com pós-incremento.<br />
#Tenha o mesmo resultado do programa anterior, mas que utilize endereçamento de dados indireto com pré-decremento.<br />
<br />
*Links:<br />
**https://www.microchip.com/webdoc/avrassembler/avrassembler.wb_instruction_list.html<br />
**http://ww1.microchip.com/downloads/en/devicedoc/atmel-0856-avr-instruction-set-manual.pdf<br />
<br />
= Aula 07/10/2019: Instruções Aritmética e desvio =<br />
*'''Objetivos:'''<br />
**Corrigir exercícios da Aula prática<br />
**Mais exercícios<br />
<br />
*'''Exercícios: '''<br />
**Faça programas que utilizem a rotação para esquerda e direita. Quais os tipos de rotação possível? Quais os bits de status podem ser modificados?<br />
** Faça a soma de dois valores de 16 bits usando os registradores.<br />
** Implemente estrutura de alto nível: IF-THEN-ELSE, WHILE e SWITCH-CASE<br />
<br />
<br />
= Aula 08/10/2019: Instruções Aritmética e desvio (cont.) =<br />
<br />
<br />
==Homework==<br />
*Some duas variáveis de 16-bits da memória SRAM e devolva o resultado em outra variável na SRAM.</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=MIC29004-2019-2&diff=162078MIC29004-2019-22019-10-08T13:46:07Z<p>127.0.0.1: /* Aula 01/10/2019: Instruções Aritmética e desvio */</p>
<hr />
<div>= Microprocessadores: Diário de Aula 2019-2=<br />
<br />
*'''Professor:''' [[Roberto de Matos]]<br />
*'''Encontros:''' 2ª e 3ª feira às 9:40h<br />
*'''Atendimento Paralelo:''' 4ª às 10h e 14h (1h cada)<br />
* [[MIC-EngTel_(Plano_de_Ensino) |Plano de Ensino]]<br />
* [[Cronograma_de_atividades_(MIC-EngTel) | Cronograma de Aulas]]<br />
* [http://docente.ifsc.edu.br/roberto.matos/mic_public/2019-2/notas_MIC29004_2019-2.pdf Notas]<br />
<br />
== Material ==<br />
*[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/ApostilaMemorias.pdf Apostila Memória]<br />
*[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_1-memoria.pdf Slides Memória]<br />
<!--<br />
*[[Media:mic-slides_2-handout.pdf|Introdução a Microprocessadores]]<br />
*[[Media:bip.pdf|Arquitetura e Organização do BIP]]<br />
--><br />
<br />
==Listas de Exercício==<br />
* [[MIC29004-lista1 | Lista de Exercícios: Memória, Arquitetura, Organização e BIP]]<br />
*[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/Exercícios-sobre-a-programação-do-BIP.pdf Lista Introdução a programação do BIP]<br />
* [[MIC29004-lista2-avr | Lista de Exercícios Microcontroladores e AVR]]<br />
<br />
= Aula 29/07/2019: Apresentação =<br />
* Apresentação do professor.<br />
* Apresentação da disciplina: conteúdo, bibliografia e avaliação.<br />
<br />
<br />
= Aula 30/07/2019: Introdução sobre Memória =<br />
*[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/ApostilaMemorias.pdf Apostila Memória]<br />
*[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_1-memoria.pdf Slides Memória]<br />
<br />
*[[MIC29004-lista1 | Lista de Exercícios: Memória, Arquitetura, Organização e BIP]]<br />
<br />
<br />
==Diagrama em blocos da memória e barramentos==<br />
No diagrama abaixo está representado um bloco de memória primária de 16x8 (dezesseis endereços por 8 bits).<br />
*Note que uma posição de memória pode ser vista como uma caixa que possue um endereço e um conteúdo. <br />
*O conteúdo associado a posição de memória é uma palavra binária e, neste caso, possui 8 bits.<br />
<br />
[[imagem:DiagramaBlocosMemorias2.jpg|500px|center]]<br />
<br />
Para que us dispositivo externo possa "acessar" a memória para leitura ou escrita, ele deve se utilizar de um conjunto de fios que chamamos de barramentos.<br />
<br />
===Barramento de Endereços===<br />
<br />
Este barramento permite determinar o endereço de uma posição a ser acessada na memória.<br />
Um barramento de 4 linhas de endereço é designado por A3,A2,A1 e A0.<br />
<br />
Supondo uma memória com endereços designados da forma hexadecimal de 0h a Fh. Supondo que A3<br />
seja associado ao bit mais significativo e A0 ao bit menos significativo. Então, para acessar<br />
a posição Bh de memória, deve-se injetar A3=1, A2=0, A1=1 e A0=1. Note que <math> B_h = 1011_b </math><br />
<br />
O termo "injetar" significa aqui que um dispositivo externo deve forçar tensão nas linhas do barramento.<br />
Esta tensão depende da tecnologia utilizada. Poderia ser, por exemplo, 5V para o nível lógico 1 e 0V par ao nível lógico 0.,<br />
<br />
<br />
<br />
= Aula 04/08/2019: Laboratório de Memória - Introdução =<br />
<br />
*'''Notas de Aula:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_1-memoria.pdf Slides Memória]<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic_slides_1-memoria_tabela_associacao.pdf Exemplos de Associação de Memória]<br />
<br />
* '''Material de Apoio (Decodificadores):'''<br />
**[http://www.electronics-tutorials.ws/combination/comb_5.html Tutorial]<br />
**[http://www.skot9000.com/ttl/datasheets/139.pdf 74LS139]<br />
<br />
<br />
*'''Experimento 1 - Memória 16x4:'''<br />
#Entrar no Windows.<br />
#Baixar o arquivo de projeto [http://docente.ifsc.edu.br/roberto.matos/mic_public/labs/lab1-memoria.zip aqui]. Coloque em um diretório conhecido.<br />
#Descompacte. Clique sobre o arquivo *.pdsprj. O PROTEUS será executado e o projeto aberto.<br />
#Observe que o projeto está parcialmente pronto. Você pode entrar em modo simulação.<br />
#O sistema está preparado para que se possa inserir ou ler manualmente posições de memória.<br />
#Leia todas as 16 posições de memória e anote os valores.<br />
#Grave o número da sua matrícula na memória. Preencha o restante com zero.<br />
#Note o Chip Select está habilitado sempre. Coloque uma chave adicional para colocar o Chip Select.<br />
<br />
<br />
*'''Atividade 1 - Associação de Memórias:'''<br />
**Usando como referência o experimento 1 e os exemplos de associação de memória vistos em sala de aula, implemente o seguinte:<br />
:# Uma memória 16x8<br />
:# Uma memória 64x4<br />
:# Uma memória 64x8<br />
*Entrega:<br />
**Fazer em Duplas<br />
**Última Aula de dúvidas: 06/08 (segunda)<br />
**Apresentação: 07/08 (terça)<br />
<br />
= Aula 12/08/2019: Laboratório de Memória - Associação =<br />
* Finalizar o Exercício<br />
<br />
= Aula 13/08/2019: Introdução à Arquitetura e Organização de Computadores =<br />
<br />
*'''Objetivos:'''<br />
** Introdução a Microprocessadores<br />
<br />
*'''Notas de Aula:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_2-Arquitetura_e_Bip.pdf Introdução à Arquitetura e Organização de Computadores]<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_3-Projetando_um_Computador_slides.pdf Projetando um Computador - BIP]<br />
<br />
* '''Experimento:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/Exercícios-sobre-a-programação-do-BIP.pdf Lista Introdução a programação do BIP]<br />
<br />
<br />
= Aula 19/08/2019: Arquitetura BIP =<br />
<br />
*'''Objetivos:'''<br />
** Entender a Arquitetura BIP<br />
** Programar em Assembly o BIP<br />
<br />
*'''Notas de Aula:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_3-Projetando_um_Computador_slides.pdf Projetando um Computador - BIP]<br />
<br />
* '''Experimento:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/Exercícios-sobre-a-programação-do-BIP.pdf Lista Introdução a programação do BIP]<br />
<br />
<br />
= Aula 20/08/2019: Organização do BIP =<br />
*'''Objetivos:'''<br />
** Entender a Organização do BIP<br />
** Criar tabela de decodificação do BIP<br />
<br />
*'''Notas de Aula:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_3-Projetando_um_Computador_slides.pdf Projetando um Computador - BIP]<br />
<br />
*'''Software Utilizado:'''<br />
**[http://bipide.com.br/ BIP IDE]<br />
<br />
<br />
= Aula 26/08/2019: Decodificador BIP =<br />
<br />
*'''Objetivos:'''<br />
** Entender a execução do BIP passo-a-passo no Proteus<br />
** Implementar o circuito decodificador do BIP no Proteus<br />
** Entender as mudanças da arquitetura e da organização do BIP II<br />
<br />
*'''Experimento:'''<br />
** [[Experimento_BIP_I | Experimento BIP I]]<br />
<br />
<br />
= Aula 27/08/2019: Decodificador BIP (cont.) e BIP II=<br />
<br />
*'''Objetivos:'''<br />
** Finalizar o Decode do BIP<br />
** Introdução da arquitetura do BIP II<br />
<br />
*'''Exercícios:'''<br />
** Implementar e simular exemplos com as instruções de desvio do BIP II<br />
<br />
<br />
= Aula 02/09/2019: Organização do BIP II =<br />
*'''Objetivos:'''<br />
**Entender as mudanças da arquitetura e da organização do BIP II<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/Artigo-BIP.pdf Artigo BIP II]<br />
<br />
*'''Experimento:'''<br />
** [http://docente.ifsc.edu.br/roberto.matos/mic_public/labs/codigos_bip2.zip Instruções de Desvio BIP II]<br />
<br />
*'''Exercício:'''<br />
** Implementar as mudanças da organização do BIP para criar o BIP II <br />
** Implementar o decodificador do BIP II ([http://www.32x8.com/ 32x8])<br />
** Implementar programas de testes no assembly do BIP II<br />
** Trabalho em Dupla<br />
** Entrega 08/09 e Apresentação 10/09<br />
<br />
= Aula 03/09/2019: Dúvidas Lista de Exercício e Apoio Trabalho BIP II =<br />
*'''Objetivos:'''<br />
** Aula de dúvidas<br />
<br />
*'''Objetivos:'''<br />
** Dúvidas da [[MIC29004-lista1 | Lista de Exercícios: Memória, Arquitetura, Organização e BIP]] para prova I.<br />
<br />
<br />
= Aula 09/09/2019: Prova I =<br />
*'''Objetivos:'''<br />
** Avaliação dos conceitos de Memória, Arquitetura e Organização, BIP I e II<br />
<br />
= Aula 10/09/2019: Apresentação Trabalho BIP II=<br />
*'''Objetivos:'''<br />
** Apresentação do Trabalho BIP II<br />
<br />
<br />
= Aula 16/09/2019: Correção da Prova=<br />
*'''Objetivos:'''<br />
** Correção da avaliação para completar o processo de ensino-aprendizagem.<br />
<br />
*'''Notas:'''<br />
* Foi decidido junto à turma que o péssimo resultado da avaliação será recuperado no fim do semestre. <br />
* O professor se colocou à disposição para recuperar o conteúdo durante o semestre, tirando dúvidas em sala de aula ou no horário de atendimento. <br />
* Os alunos se comprometeram em recuperar o conteúdo, pois é essencial para a continuidade da disciplina.<br />
<br />
= Aula 17/09/2019: Introdução aos Microcontroladores =<br />
*'''Objetivos:'''<br />
** Entender os conceitos e diferenças entre um Processador e um Microcontrolador. <br />
** Introdução à aplicações microcontroladas<br />
<br />
*'''Notas de Aulas:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_4-Intro_Microcontroladores_CISC_RISC.pdf Introdução aos Microcontroladores, CISC vs. RISC]<br />
<br />
*'''Notas Extras:'''<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/30010135D.pdf Referência Rápida Família AVR]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/30009630M.pdf Overview Microcontroladores Microchip]<br />
<br />
==Homework==<br />
* [http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf Datasheet Atmega328p]<br />
<br />
*Ler:<br />
** 2. Visão Geral<br />
** 7. Núcleo AVR <br />
** Responder:<br />
*** Qual arquitetura de memória usada? <br />
*** Detalhes da ALU (Quais os tipos de operação?)<br />
*** Registradores (Status, Uso geral e de Pilha)<br />
*** Modos de endereçamento<br />
*** Conjunto de instruções (classes e exemplos)<br />
<br />
* Ler: <br />
** 8. Memórias do AVR<br />
*** Flash<br />
*** SRAM<br />
*** EEPROM<br />
** Responder<br />
*** Qual o tamanho e o formato da palavra de de dados?<br />
*** Qual o tamanho e o formato da palavra de instrução?<br />
<br />
= Aula 23/09/2019: Arquitetura do AVR =<br />
<br />
*'''Objetivos:'''<br />
** Finalizar CISC vs. RISC<br />
** Visão Geral dos Microcontroladores ATmega48A/PA/88A/PA/168A/PA/328/P<br />
** Núcleo do AVR (ALU e Banco de Registradores)<br />
** Hierarquia de Memórias do AVR<br />
<br />
*'''Notas de Aulas:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_5-AVR.pdf Introdução AVR]<br />
<br />
*'''Notas Extras:'''<br />
**Die do [https://siliconpr0n.org/archive/doku.php?id=azonenberg:atmel:atmega48 ATmega48] e do [https://siliconpr0n.org/archive/doku.php?id=azonenberg:atmel:atmega328 ATmega328]<br />
<br />
= Aula 23/09/2019: Arquitetura do AVR (cont.) =<br />
<br />
*'''Objetivos:'''<br />
** Finalizar os objetivos da última aula<br />
<br />
*'''Notas de Aulas:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/slides-AVR_aula01.pdf Introdução AVR]<br />
<br />
*'''Experimento:'''<br />
** Simulação do primeiro código em Assembly usando o MPLAB X IDE <br />
** [[Simular Assembly do AVR no MPLAB IDE | Criar projeto]]<br />
<code><br />
start:<br />
inc r16<br />
inc r17<br />
sts $0100,r16<br />
sts $0101,r16<br />
rjmp start<br />
</syntaxhighlight><br />
<br />
==Homework==<br />
* Instalar o MPLAB X e o XC8: [[Setup Ferramentas AVR para Assembly]]<br />
* Rodar o exemplo da aula para verificar<br />
<br />
<br />
= Aula 30/09/2019: Modos de Endereçamento =<br />
*'''Objetivos:'''<br />
**Introduzir arquitetura Load-Store<br />
**Entender: <br />
***Modos de endereçamento do AVR e <br />
***Instruções relacionadas a cada modo do ATmega328p<br />
**Implementar programas para compreensão dos novos conceitos<br />
<br />
*'''Notas de Aulas:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/slides-AVR_aula02.pdf Modos de Endereçamento]<br />
<br />
==Homework==<br />
* OBS.: Instalar e configurar as ferramentas em casa para quem não fez (ver homework da aula passada).<br />
<br />
===Exercício 1===<br />
* Testar '''TODOS''' os trechos de códigos apresentados. Modifique os valores das localizações de memória afetadas para verificar se o funcionamento está coerente. <br />
<br />
*Exemplo:<br />
<code><br />
start:<br />
ldi R16,0x14<br />
rjmp start<br />
</syntaxhighlight><br />
* Pergunte-se:<br />
** A instrução em linguagem de máquina está coerente?<br />
** Se mudar o valor do imediato 0x14 para 0x25, como afeta a instrução montada? E se mudar o registrador de R16 para R17?<br />
** Eu posso carregar um imediato para o registrador R0? Por quê?<br />
* Faça isso para todos os trechos de código apresentados.<br />
<br />
===Exercício 2===<br />
*Faça um programa que some dois números de 8 bits: '''C = A + B'''<br />
*Considere as varáveis armazenadas sequencialmente a partir do primeiro endereço da memória SRAM.<br />
<br />
<br />
= Aula 01/10/2019: Modos de Endereçamento (cont.) =<br />
*'''Objetivos:'''<br />
**Corrigir exercícios da Aula prática<br />
**Mais exercícios<br />
<br />
*'''Exercícios: '''<br />
** Some as constantes 25, 14 e 0x32 e armazene o resultado em R0.<br />
** Some as constantes 32 e 0x23 e armazene o resultado em uma variável na SRAM (endereço 0x010A).<br />
**Re-implemente o código abaixo usando endereçamento indireto para acessar o R20 como posição de memória na SRAM:<br />
:<code><br />
ldi r16, $BB<br />
mov r20, r16<br />
</syntaxhighlight><br />
<br />
<br />
==Homework==<br />
* Estudar instruções lógicas e aritméticas, de desvio (CPSE até BRID), bit e bit-test<br />
* Escrever códigos que:<br />
#Execute 1.000 vezes uma ação em loop.<br />
#Execute 100.000 vezes uma ação em loop.<br />
#Carregue na SRAM 10 valores sequenciais a partir do endereço 0x0102 usando endereçamento de dados indireto com pós-incremento.<br />
#Tenha o mesmo resultado do programa anterior, mas que utilize endereçamento de dados indireto com pré-decremento.<br />
<br />
*Links:<br />
**https://www.microchip.com/webdoc/avrassembler/avrassembler.wb_instruction_list.html<br />
**http://ww1.microchip.com/downloads/en/devicedoc/atmel-0856-avr-instruction-set-manual.pdf<br />
<br />
= Aula 07/10/2019: Instruções Aritmética e desvio =<br />
*'''Objetivos:'''<br />
**Corrigir exercícios da Aula prática<br />
**Mais exercícios<br />
<br />
*'''Exercícios: '''<br />
**Faça programas que utilizem a rotação para esquerda e direita. Quais os tipos de rotação possível? Quais os bits de status podem ser modificados?<br />
** Faça a soma de dois valores de 16 bits usando os registradores.<br />
** Implemente estrutura de alto nível: IF-THEN-ELSE, WHILE e SWITCH-CASE<br />
<br />
<br />
= Aula 08/10/2019: Instruções Aritmética e desvio (cont.) =</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=Curso_T%C3%A9cnico_em_Telecomunica%C3%A7%C3%B5es_-_Projeto_Integrador_I_(PJI1)&diff=162077Curso Técnico em Telecomunicações - Projeto Integrador I (PJI1)2019-10-08T01:27:51Z<p>127.0.0.1: /* Diário de aulas PJI1 - 2019-2 */</p>
<hr />
<div>'''Professores da unidade Curricular'''<br />
<br />
{{Professor|'''2019-2'''| [[PJI11101 2019-2|'''DIÁRIO DE AULAS''']] - ([[Jorge Henrique B. Casagrande]] e [[Ana Paula Rosa Negri]])}}<br />
<br />
{{Professor|'''2019-1'''| [[PJI11101 2019-1|'''DIÁRIO DE AULAS''']] ...}}<br />
<br />
{{Professor|'''2018-2'''| [[PJI11101 2018-2|'''DIÁRIO DE AULAS''']] ...}}<br />
<br />
{{Professor|'''2018-1'''| [[PJI11101 2018-1|'''DIÁRIO DE AULAS''']] - (Evanaska Maria B. Nogueira / Clayrton M. Henrique)}}<br />
<br />
{{Professor|'''2017-2'''| [[PJI11101 2017-2|'''DIÁRIO DE AULAS''']] - ([[Juliano de Souza]] e [[Cleber Jorge Amaral]])}}<br />
<br />
{{Professor|'''2017-1'''| [[PJI11101 2017-1|'''DIÁRIO DE AULAS''']] - ([[Juliano de Souza]] e [[Cleber Jorge Amaral]])}}<br />
<br />
{{Professor|'''2016-2'''| [[PJI11101 2016-2|'''DIÁRIO DE AULAS''']] - ([[Juliano de Souza]] e Fernando Rodrigues)}}<br />
<br />
;Material de aula da antiga disciplina de Projetos I (atual Projetos II) <br />
<br />
{{Professor|'''2016-1'''| [[PJI-2016-1|'''DIÁRIO DE AULAS''']] - ([[Marcelo Maia Sobral]] / [[Simara Sonaglio]])}}<br />
<br />
;Cronogramas da antiga disciplina de Projetos I (atual Projetos II) <br />
<br />
{{collapse top| bg=lightpurple | expandir=true |Semestre 2015-2}}<br />
{{Cronograma-top}}<br />
{{Cl|1 |2/10 | 3 | Apresentação da disciplina | Laboratório de Redes}}<br />
{{Cl|2 |8/10 | 3 | Conceitos básicos e início do projeto 1 | Laboratório de Redes}}<br />
{{Cl|3 |9/10 | 3 | Projeto 1: escolhendo e instalando o centro de midia; sistema operacional; introdução ao Linux | Laboratório de Redes}}<br />
{{Cl|4 |15/10 | 3 | Projeto 1: incluindo fontes de midia locais; arquivos e diretórios | Laboratório de Redes}}<br />
{{Cl|5 |16/10 | 3 | Projeto 1: transmitiindo a midia através da rede; comunicação de dados | Laboratório de Redes}}<br />
{{Cl|6 |22/10 | 3 | Projeto 1: transmitiindo a midia através da rede; comunicação de dados | Laboratório de Redes}}<br />
{{Cl|7 |23/10 | 3 | Projeto 1: continuação | Laboratório de Redes}}<br />
{{Cl|8 |29/10 | 3 | Projeto 1: continuação | Laboratório de Redes}}<br />
{{Cl|9 |5/11 | 3 | Projeto 1: apresentação pelas equipes; história das telecomunicações | Laboratório de Redes}}<br />
{{Cl|10 |6/11 | 3 | Projeto 2: implantando uma pequena rede local | Laboratório de Redes}}<br />
{{Cl|11 |12/11 | 3 | Projeto 2: instalação do sistema operacional em um computador | Laboratório de Redes}}<br />
{{Cl|12 |13/11 | 3 | Projeto 2: uso do sistema operacional; entendendo como o sistema operacional inicia (boot) | Laboratório de Redes}}<br />
{{Cl|13 |19/11 | 3 | Projeto 2: uso do sistema operacional; linha de comando: arquivos e diretórios | Laboratório de Redes}}<br />
{{Cl|14 |20/11 | 3 | Projeto 2: uso do sistema operacional; linha de comando: arquivos e diretórios; permissões | Laboratório de Redes}}<br />
{{Cl|15 |26/11 | 3 | Projeto 2: protegendo recursos no sistema operacional: usuários e grupos; linha de comando: compactadores | Laboratório de Redes}}<br />
{{Cl|16 |27/11 | 3 | Projeto 2: uso do sistema operacional; linha de comando: processos, entrada e saída padrão | Laboratório de Redes}}<br />
{{Cl|17 |3/12 | 3 | Projeto 2: uso do sistema operacional; linha de comando: entrada e saída padrão; instalação de software | Laboratório de Redes}}<br />
{{Cl|18 |4/12 | 3 | Projeto 2: configuração do sistema operacional para usar a rede; interfaces de rede e endereços IP | Laboratório de Redes}}<br />
{{Cl|19 |10/12 | 3 | Projeto 2: configuração do sistema operacional para usar a rede; rota default e rotas estáticas | Laboratório de Redes}}<br />
{{Cl|20 |11/12 | 3 | Projeto 2: revisão dos requisitos para adicionar um computador à rede | Laboratório de Redes}}<br />
{{Cl|21 |17/12 | 3 | Projeto 2: configuração automática de rede (dhcp); continuação do projeto | Laboratório de Redes}}<br />
{{Cl|22 |18/12 | 3 | Projeto 2: implantação da rede local: switches e ponto de acesso Wifi | Laboratório de Redes}}<br />
{{Cl|23 |4/2 | 3 | Projeto 2: implantação da rede local: switches e ponto de acesso Wifi | Laboratório de Redes}}<br />
{{Cl|24 |5/2 | 3 | Projeto 2: implantação do acesso a Internet: enlace ADSL | Laboratório de Redes}}<br />
{{Cl|25 |11/2 | 3 | Projeto 2: revisão sobre a implantação da rede do projeto; discussão sobre erros comuns de instalação | Laboratório de Redes}}<br />
{{Cl|26 |12/2 | 3 | Projeto 2: acesso externo ao computador da rede local com SSH e outros serviços | Laboratório de Redes}}<br />
{{Cl|27 |18/2 | 3 | Projeto 2: definição das características finais do projeto pelas equipes | Laboratório de Redes}}<br />
{{Cl|28 |25/2 | 3 | Projeto 2: conclusão e apresentação pelas equipes | Laboratório de Redes}}<br />
{{Cl|29 |26/2 | 3 | Projeto 3: apresentação; sistemas de telefonia; implantação de sua própria central telefônica | Laboratório de Redes}}<br />
{{Cl|30 |3/3 | 3 | Projeto 3: implantação de sua própria central telefônica | Laboratório de Redes}}<br />
{{Cl|31 |4/3 | 3 | Projeto 3: loop local e o enlace ADSL | Laboratório de Redes}}<br />
{{Cl|32 |10/3 | 3 | Projeto 3: rede telefônica convencional e telefonia IP; VoIP | Laboratório de Redes}}<br />
{{Cl|33 |11/3 | 3 | Projeto 3: conclusão e apresentação pelas equipes | }}<br />
{{cronograma-botton |120}}<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightpurple | expandir=true |Semestre 2015-1}}<br />
{{Cronograma-top}}<br />
{{Cl|1 |4/2 | 3 | Apresentação da disciplina | Laboratório de Redes}}<br />
{{Cl|2 |9/2 | 3 | Conceitos básicos e início do projeto 1 | Laboratório de Redes}}<br />
{{Cl|3 |11/2 | 3 | Projeto 1: escolhendo e instalando o centro de midia; sistema operacional; introdução ao Linux | Laboratório de Redes}}<br />
{{Cl|4 |23/2 | 3 | Projeto 1: incluindo fontes de midia locais; arquivos e diretórios | Laboratório de Redes}}<br />
{{Cl|5 |25/2 | 3 | Projeto 1: transmitiindo a midia através da rede; comunicação de dados | Laboratório de Redes}}<br />
{{Cl|6 |2/3 | 3 | Projeto 1: transmitiindo a midia através da rede; comunicação de dados | Laboratório de Redes}}<br />
{{Cl|7 |4/3 | 3 | Projeto 1: apresentação pelas equipes; história das telecomunicações | Laboratório de Redes}}<br />
{{Cl|8 |9/3 | 3 | Projeto 1: continuação | Laboratório de Redes}}<br />
{{Cl|9 |11/3 | 3 | Projeto 1: apresentação pelas equipes; história das telecomunicações | Laboratório de Redes}}<br />
{{Cl|10 |16/3 | 3 | Projeto 2: implantando uma pequena rede local | Laboratório de Redes}}<br />
{{Cl|11 |18/3 | 3 | Projeto 2: instalação do sistema operacional em um computador | Laboratório de Redes}}<br />
{{Cl|12 |23/3 | 3 | Projeto 2: uso do sistema operacional; entendendo como o sistema operacional inicia (boot) | Laboratório de Redes}}<br />
{{Cl|13 |25/3 | 3 | Projeto 2: protegendo recursos no sistema operacional: usuários e grupos; linha de comando: compactadores | Laboratório de Redes}}<br />
{{Cl|14 |30/3 | 3 | Projeto 2: uso do sistema operacional; linha de comando: processos, entrada e saída padrão | Laboratório de Redes}}<br />
{{Cl|15 |1/4 | 3 | Projeto 2: uso do sistema operacional; linha de comando: entrada e saída padrão; instalação de software | Laboratório de Redes}}<br />
{{Cl|16 |6/4 | 3 | Projeto 2: uso do sistema operacional; linha de comando: processos, entrada e saída padrão | Laboratório de Redes}}<br />
{{Cl|17 |8/4 | 3 | Projeto 2: uso do sistema operacional; linha de comando: entrada e saída padrão; instalação de software | Laboratório de Redes}}<br />
{{Cl|18 |13/4 | 3 | Projeto 2: configuração do sistema operacional para usar a rede; interfaces de rede e endereços IP | Laboratório de Redes}}<br />
{{Cl|19 |15/4 | 3 | Projeto 2: configuração do sistema operacional para usar a rede; rota default e rotas estáticas | Laboratório de Redes}}<br />
{{Cl|20 |22/4 | 3 | Projeto 2: revisão dos requisitos para adicionar um computador à rede | Laboratório de Redes}}<br />
{{Cl|21 |27/4 | 3 | Projeto 2: configuração automática de rede (dhcp); continuação do projeto | Laboratório de Redes}}<br />
{{Cl|22 |29/4 | 3 | Projeto 2: implantação da rede local: switches e ponto de acesso Wifi | Laboratório de Redes}}<br />
{{Cl|23 |4/5 | 3 | Projeto 2: implantação da rede local: switches e ponto de acesso Wifi | Laboratório de Redes}}<br />
{{Cl|24 |6/5 | 3 | Projeto 2: implantação do acesso a Internet: enlace ADSL | Laboratório de Redes}}<br />
{{Cl|25 |11/5 | 3 | Projeto 2: revisão sobre a implantação da rede do projeto; discussão sobre erros comuns de instalação | Laboratório de Redes}}<br />
{{Cl|26 |13/5 | 3 | Projeto 2: acesso externo ao computador da rede local com SSH e outros serviços | Laboratório de Redes}}<br />
{{Cl|27 |18/5 | 3 | Projeto 2: definição das características finais do projeto pelas equipes | Laboratório de Redes}}<br />
{{Cl|28 |20/5 | 3 | Projeto 2: continuação | Laboratório de Redes}}<br />
{{Cl|29 |25/5 | 3 | Projeto 2: continuação | Laboratório de Redes}}<br />
{{Cl|30 |27/5 | 3 | Projeto 2: conclusão e apresentação pelas equipes | Laboratório de Redes}}<br />
{{Cl|31 |1/6 | 3 | Projeto 3: apresentação; sistemas de telefonia | Laboratório de Redes}}<br />
{{Cl|32 |3/6 | 3 | Projeto 3: implantação de sua própria central telefônica | Laboratório de Redes}}<br />
{{Cl|33 |8/6 | 3 | Projeto 3: implantação de sua própria central telefônica | Laboratório de Redes}}<br />
{{Cl|34 |10/6 | 3 | Projeto 3: rede telefônica convencional e telefonia IP; VoIP | Laboratório de Redes}}<br />
{{Cl|35 |15/6 | 3 | Projeto 3: plano de numeração | Laboratório de Redes}}<br />
{{Cl|36 |17/6 | 3 | Projeto 3: integração de rede telefônica convencional e VoIP; interfaces FXO e FXS | Laboratório de Redes}}<br />
{{Cl|37 |22/6 | 3 | Projeto 3: convergência de telefonia; uso de PBX analógico | Laboratório de Redes}}<br />
{{Cl|38 |24/6 | 3 | Projeto 3: loop local e o enlace ADSL | Laboratório de Redes}}<br />
{{Cl|39 |29/6 | 3 | Projeto 3: continuação | Laboratório de Redes}}<br />
{{Cl|40 |1/7 | 3 | Projeto 3: conclusão e apresentação pelas equipes | Laboratório de Redes}}<br />
{{cronograma-botton |120}}<br />
<br />
{{collapse bottom}}<br />
<br />
;Objetivos e Cronograma de Atividades Geral<br />
<br />
{{collapse top| bg=lightgreen | expandir=true | Objetivos e Cronograma de Atividades Geral}}<br />
<br />
Objetivos:<br />
* Conhecer as normas para instalação do cabeamento estruturado;<br />
* Conhecer os elementos do cabeamento estruturado.<br />
* Instalar um cabeamento estruturado;<br />
* Conhecer o padrão da infraestrutura das redes de distribuição telefônica;<br />
* Conhecer os elementos da rede de distribuição de telefonia.<br />
* Instalar redes de distribuição de telefonia.<br />
* Conhecer a infraestrutura de redes HFC<br />
* Conhecer elementos da rede HFC.<br />
* Conhecer o funcionamento básica de um enlace de radiotransmissão (antena X comprimento de onda; antena X ganho; atenuação, direcionamento de antes no espaço livre)<br />
* Instalar um radio enlace<br />
* Conhecer a norma brasileira para instalações elétricas.<br />
* Conhecer a função e os tipos de nobreak<br />
* Instalar a infraestrutura de energia elétrica de uma rede local.<br />
<br />
Atividades:<br />
* Instalação de cabeamento estruturado;<br />
* Uso da instalação do cabeamento estruturado para rede de computadores, telefonia, sensores e TV;<br />
* Instalação de rede externa de telefonia;<br />
* Uso da rede instalada para operação de uma rede telefônica e acesso xDSL;<br />
* Realizar conexões e emendas em cabos coaxias e fibras ópticas;<br />
* Dimensionamento de um circuito de alimentação elétrica para um cabeamento estruturado.<br />
* Instalação da infraestrutura de energia elétrica de uma rede local.<br />
<br />
Atividades em 2 dias por semana / 20 semanas por semestre;<br />
<br />
{| border="1" cellpadding="2"<br />
!Semana<br />
!Aula 1<br />
!Aula 2<br />
|-<br />
|1 <br />
|| Apresentação do Projeto Integrador <br> Diferenciação de redes local e de acesso <br> Introdução ao cabeamento estruturado.<br />
|| Elementos do cabeamento estruturado (conhecer a função e manusear blocos, conectores, cabos ...). <br />
|-<br />
|2 <br />
|| Elementos do cabeamento estruturado <br> visão geral do cabeamento (distribuidores, backbones, cabeamento horizontal, área de trabalho <br> definição da estrutura a ser instalada. <br />
|| Instalação do cabeamento estruturado.<br />
|-<br />
|3 <br />
|| Instalação do cabeamento estruturado.<br />
|| Instalação do cabeamento estruturado.<br />
|-<br />
|4<br />
|| Verificação da instalação e da identificação (testes e relatório) <br> Instalação das redes locais (computadores, telefonia, sensores, TV).<br />
|| Instalação das redes locais: entender o funcionamento de switches ethernet (comutação de quadros de acordo com endereço MAC, aprendizado de endereços MAC, cuidados ao conectar switches - ex: evitar ''loops'')<br />
|-<br />
|5 <br />
|| Instalação das redes locais<br />
|| Visão geral da rede de distribuição de telefonia <br> Elementos do cabeamento estruturado (conhecer a função e manusear blocos, conectores, cabos ...)<br />
|-<br />
|6<br />
|| Instalar uma rede de distribuição telefônica.<br />
|| Instalar uma rede de distribuição telefônica.<br />
|-<br />
|7 <br />
|| Verificar a instalação da rede de distribuição telefônica <br> Operar uma central telefônica e uma rede Xdsl integrando com a rede de cabeamento estruturado.<br />
|| Operar uma central telefônica e uma rede Xdsl integrando com a rede de cabeamento estruturado.<br />
|-<br />
|8<br />
|| Visão geral da fibra óptica ,<br> cabos e conectores de fibra óptica <br> interligação de equipamentos com fibra óptica.<br />
|| Emendas com fibra e instrumentação óptica.<br />
|-<br />
|9 <br />
|| Instalar link com fibra óptica <br> verificar instalação <br> operar uma rede de telecomunicações no link de fibra<br />
|| Redes HFC e redes de distribuição de CATV <br> conhecer e manipular os elementos da rede HFC.<br />
|-<br />
|10 <br />
|| Instalar uma rede residencial de TV a cabo.<br />
|| Visão geral das redes PON (Palestra?)<br />
|-<br />
|11<br />
|| Visão geral da propagação de ondas e ocupação do espectro eletromagnético <br> Noções básicas e características fundamentais de antenas <br> Tipos de antenas e suas aplicações. <br />
|| Aspectos práticos em radiotransmissão: casamento de impedância, cabos e conectores empregados em altas frequências <br> Realização de conectorização e montagem de um sistema simples de radiotransmissão.<br />
|-<br />
|12 <br />
|| Noções de enlaces de rádio <br> Aspectos de propagação indoor x outdoor <br> Conexões ponto a ponto e multiponto <br> Balanço de potência em enlaces de rádio <br> Alinhamento de antenas <br> Polarização<br />
|| Instalação e teste de um enlace de rádio.<br />
|-https://wiki.sj.ifsc.edu.br/index.php/PJI11101_2018-1<br />
|13<br />
|| Implantação de rede local sem-fio: pontos de acesso e integração com rede local cabeada<br />
|| Implantação de rede local sem-fio: sistemas de distribuição (cabeado e sem-fio)<br />
|-Eletrônica e instrumentação<br />
|14 <br />
|| Implantação de rede local sem-fio: caracterização de canal sem-fio e impedimentos para a comunicação, uso de antenas direcionais, escolha de canais para pontos de acesso<br />
|| Implantação de rede local sem-fio: posicionamento de pontos de acesso para otimizar cobertura e minimizar interferências<br />
|-<br />
|15 <br />
|| Instalação do circuito elétrico para uma estrutura de cabeamento estruturado<br />
|| Nobreak - função, tipos forma de especificação.<br />
|-<br />
|16 <br />
|| Especificação de Nobreak.<br />
|| <br />
|-<br />
|17<br />
|| Dimensionamento de circuitos elétricos.<br />
|| Dimensionamento de circuitos elétricos voltados para infraestrutura de redes locais.<br />
|-<br />
|18<br />
|| Projeto de circuito elétrico para uma estrutura de cabeamento estruturado.<br />
|| Projeto de circuito elétrico para uma estrutura de cabeamento estruturado.<br />
|-<br />
|19 <br />
|| <br />
|| <br />
|-<br />
|20 <br />
|| folga para feriados e erros no dimensionamento da carga horária<br />
|| folga para feriados e erros no dimensionamento da carga horária<br />
|} <br />
{{collapse bottom}}<br />
<br />
;REGISTRO DAS ATIVIDADES 2019-2<br />
<br />
=[[PJI2-TecTel|Carga horária, Ementas, Bibliografia]]=<br />
<br />
=[[PJI2-TecTel (Plano de Ensino) | Plano de Ensino]]=<br />
<br />
=Dados Importantes=<br />
''Professores'': [[Jorge Henrique B. Casagrande]] - casagrande@ifsc.edu.br e [[Ana Paula Rosa Negri]] - ana.negri@ifsc.edu.br<br />
<br><br />
;Atendimento Paralelo conforme PPC<br />
2as e 4as 18:30h - 19h - Sala dos Professores de Tele 2 ou Laboratório de Meios de Transmissão.<br />
;Atendimento paralelo Adicional:<br />
'''Prof. Jorge Casagrande: 2as e 5as 17:35h - 18:30h - Sala dos Professores de Tele 2'''<br />
<br>'''Prof. Ana Negri: 3as e 6as às 15h - 16h - Sala dos Professores de Tele 2''' <br />
<br> ''Link alternativo para Material de Apoio da disciplina'': [http://www.sj.ifsc.edu.br/~casagrande/PJI veja link]<br />
<br />
=Avaliações=<br />
<br />
;Critérios <br />
:Os alunos serão avaliados da seguinte forma:<br />
::- 3 Avaliações parciais A1, A2 e A3. Cada avaliação parcial contará com uma '''PROVA ESCRITA''' de 1,5HA de conteúdos preferencialmente associados as teorias e práticas do projeto os quais representam 50% da nota; Os outros 50% de cada avaliação parcial é relativa a média das notas atribuídas a aptidão e qualidade das atividades práticas correspondentes as etapas desenvolvidas no projeto integrador, atividades extras e avaliação individual.<br><br />
::- Avaliação Individual (AI1, AI2 e AI3) é uma nota atribuída pelos professores que representa o mérito de assiduidade, participação em sala, cumprimento de tarefas adicionais como relatórios e listas de exercícios.<br><br />
::- Todas as notas parciais serão valoradas de 0 à 10 em passos de 1 pontos e convertidas em conceitos conforme abaixo:<br />
::Se '''NOTA FINAL (NF)''' OU '''PROVA ESCRITA'''da avaliação parcial '''< 6''' é OBRIGATÓRIO realizar a recuperação dos conteúdos da respectiva avaliação parcial <br><br />
::Se '''NOTA FINAL''' OU '''PROVA ESCRITA'''da avaliação parcial '''>= 6''' a recuperação de conteúdos é opcional<br><br />
<br />
::- '''Para a aprovação na disciplina''' é necessário atingir no mínimo nota '''6''' na média final ponderada em carga horária de todas as avaliações parciais e 75% de participação em sala de aula;<br><br />
::- As datas de recuperação das avaliações parciais serão decididas em comum acordo com a turma. <br><br />
<br />
=Resultados das Atividades Extras e Avaliações Parciais=<br />
<br />
{| border="1" cellpadding="5" cellspacing="0" <br />
!Aluno<br />
!AE1<br />
!AE2<br />
!AE3<br />
!AE4<br />
!AI1<br />
!Prova1 <br />
!A1<br />
!REC A1<br />
!NF A1<br />
|-<br />
|Adriano Augusto de Medeiros || || 9 || || || || || 1 || ||<br />
|-<br />
|Alden Liuti Nascimento || 10 || 10 || 9 || 10|| 10 || 9,4 || 9,6|| ||<br />
|-<br />
|Alessandra Alves da Silva || 6 || 10 || 7 ||7 || 10 || 6 || 7|| ||<br />
|-<br />
|Alexsandro Munzfeld || 8 || 7 || 9 ||9 || 10 || 5,1 || 6,8 || ||<br />
|-<br />
|Amanda Ferreira Pires || 6 || 9 || 4 || 7|| 8 || 2,9 || 4,8 || ||<br />
|-<br />
|Arieli Oliveira de Faria || 6 || 7 || 7 || 10|| 7 || 4 || 5,7|| ||<br />
|-<br />
|Bergery Janvier || 8 || 3 || 7 ||7 || 8 || 5 || 5,8 || ||<br />
|-<br />
|Daniel de Souza Lopes || 8 || 8 || 7 ||7 || 9 || 6,5 || 7,2|| ||<br />
|-<br />
|David Michael Niekelle || 7 || 7 || 9 || 7|| 10 || 6,6 || 7,3|| ||<br />
|-<br />
|Ermeson da Conceição Ribeiro dos Santos || 6* || 8 || 10 || 7|| 10 || 4,4 || 6,3|| ||<br />
|-<br />
|Fabio da Silva Moreira || 7 || 9 || 6 ||7 || 7 || 4,2 || 5,7|| ||<br />
|-<br />
|Gabriel Ferreira da Silva || || 10 || 8 || 10|| 10 || 8,6 || 8,1|| ||<br />
|-<br />
|Gisele Martins || 7 || 9 || 9 ||9 || 10 || 5,4 || 7,1|| ||<br />
|-<br />
|Hozana de Souza Freitas || 8 || 9 || 9 ||9 || 10 || 5,2 || 7,1|| ||<br />
|-<br />
|Kauan Kleber da SIlva || 8 || || 8 || 10|| 7 || ||3,3|| ||<br />
|-<br />
|Kenard Rodrigues Silva || 6 || || || || || || 0,6|| ||<br />
|-<br />
|Lesly Ogenus || 9 || 10 || 6 ||9 || 8 || 2,7 || 5,5|| ||<br />
|-<br />
|Louise Adriane da Costa Chagas || 6 || 8 || 8 || 7|| 10 || 4,5 || 6,1|| ||<br />
|-<br />
|Maiza da Cunha Silva || 7 || 8 || 7 ||7 || 10 || 5,3 || 6,5|| ||<br />
|-<br />
|Mariane da Silva Correa || || 8 || 6 || 10|| 10 || 6,4 || 6,6|| ||<br />
|-<br />
|Olívia Melo || || || ||10 || 9 || || 1,9|| ||<br />
|-<br />
|Patrick Freire Machado || 5 || || || || || || 0,5|| ||<br />
|-<br />
|Ronilda Amaral de Jesus || 6 || 10 || 7 || 7|| 10 || 6,7 || 7,3|| ||<br />
|-<br />
|Suzana Torres Moran || 6 || 10 || 8 || 9|| 8 || 4,3 || 6,2|| ||<br />
|-<br />
|Theophile Dorsaint || || || || 7|| 7 || 5 || 3,9|| ||<br />
|-<br />
|Whallace dos Santos Querino || 6 || 7 || 4 ||9 || 8 || || 3,4|| ||<br />
|-<br />
|}<br />
* [[Media: 1a_Lista_de_Exercicios.pdf | AE1]]: atividade extra do dia 07/08;<br />
* AE2: Questões do [[Media:4.2IFSC_Aula_Integrado_CAB_2015_1.pdf | material de apoio]] feitas em sala de aula no dia 12/08;<br />
* [[Media: 2a_Lista_de_Exercicios.pdf | AE3]]: atividade extra do dia 12/08;<br />
* [[media:lista1p2.pdf | AE4]]: atividade extra do dia 02/09;<br />
* AI1, AI2, AI3: Avaliação Individual de cada avaliação parcial.<br />
<br />
=Relatórios das Equipes=<br />
<br />
=Recados Importantes=<br />
<br />
<br> Toda vez que você encontrar a marcação <math>\blacklozenge</math> ao lado de alguma atividade, significa que essa atividade estará sendo computada na avaliação como Avaliação extra e/ou individual de A1, A2 ou A3. O prazo estabelecido para entrega estará destacado ao lado da atividade. Portanto, não perca o prazo limite para entrega. '''Atividades entregues fora do prazo terão seu valor máximo de nota debitado de 10 pontos ao dia;'''<br />
<br />
<br> '''Uso da Wiki:''' Todo o repositório de material de apoio e referências de nossas aulas passam a usar a Wiki de tele;<br />
<br />
<br> '''Whatsapp:''' Para interação fora da sala de aula, acessem nosso grupo no Whatsapp;<br />
<br />
<br> '''SIGAA: ''' Eventualmente alguns materiais, mídias instrucionais, avaliações ou atividades poderão usar o ambiente da turma virtual do SIGAA. O professor fará o devido destaque para isso;<br />
<br />
<br> '''ATENÇÃO:''' Uma avaliação poderá ser recuperada somente se existir justificativa reconhecida pela coordenação. Desse modo, deve-se protocolar a justificativa no prazo de 48 horas, contando da data e horário da avaliação, e aguardar o parecer da coordenação. O não cumprimento desse procedimento implica a impossibilidade de fazer a recuperação.<br />
<br />
=Material de Apoio=<br />
<br />
;Apostilas e Tutoriais<br />
<br />
* [http://www.sj.ifsc.edu.br/~saul/cabeamento%20estruturado/cabeamento%202011.pdf Apostila de Cabeamento Estruturado do Prof. Saul]<br />
* [http://www.sj.ifsc.edu.br/~casagrande/PIJ2/plantaexterna.pdf Apostila Sobre Planta Externa de Telefonia do Prof. Saul]<br />
* [http://www.sj.ifsc.edu.br/~casagrande/PIJ2/CATV.pdf Um Tutorial básico sobre CATV]<br />
* [http://www.sj.ifsc.edu.br/~casagrande/PIJ2/CFTV.pdf Um Tutorial básico sobre CFTV]<br />
* [http://www.aventuracctv.com/pt/dvr_tutorial/?index=11 Um link mais detalhado sore CFTV]<br />
<br />
;Slides utilizados durante algumas aulas<br />
* Cabeamento estruturado [http://www.sj.ifsc.edu.br/~casagrande/PIJ2/CE_visao.pdf Visão Geral]<br />
* Apresentação do básico da norma [http://www.sj.ifsc.edu.br/~casagrande/PIJ2/tia606.pdf TIA606 Visão Básica]<br />
* Cabos metálicos - Par trançado [[Media:4.2IFSC_Aula_Integrado_CAB_2015_1.pdf | Slides Par trançado]]<br />
* Visão geral de Cabeamento estruturado [[Media: Aula_05_-_PJI11101.pdf | Visão Geral]]<br />
* Fibra óptica [[Media:4.3IFSC_Aula_Integrado_CAB_2015_1.pdf | Slides Fibra Óptica]]<br />
<br />
;Listas de Exercícios<br />
<br />
* [http://www.sj.ifsc.edu.br/~casagrande/PIJ2/lista1_pj2.pdf LISTA 1] - parte 1.<br />
* [http://www.sj.ifsc.edu.br/~casagrande/PIJ2/lista2_pj2.pdf LISTA 2] - partes 2 e 3.<br />
<br />
;Vídeos Instrucionais<br />
* Video sobre Cabeamento Estruturado do CPT [https://www.youtube.com/watch?v=baLhqXPJGeY Parte 1] - Atenção: material disponibilizado somente para ser utilizado como estudo individual - Não usar em sala de aula!<br />
* Video Apresentando uma Visão Geral sobre a Norma técnica NBR14565:2012 [https://www.youtube.com/watch?v=4Ebo7_y3usU Click aqui]<br />
* Video Abordando o Cabo UTP - [https://www.youtube.com/watch?v=TEZqmd0z4Ps Click aqui]<br />
* Video com o Passo a Passo para Montar um Cabo de Rede - [https://www.youtube.com/watch?v=wmxiV0hQUGE Click aqui]<br />
<br />
;Manuais e outros<br />
* Norma ABNT [http://www.abntcatalogo.com.br/norma.aspx?ID=307178 NBR 14565]<br />
* Norma ABNT de projetos Elétricos de Baixa tensão [http://www.sj.ifsc.edu.br/~casagrande/PIJ2/nbr5410.pdf NBR5410]<br />
* Normas adotadas para Cabeamento Estruturado e Identificação por cores (Norma EIA/TIA-606)[[Media:Complemento.pdf]]<br />
* [http://www.peropi.com.br/index.php?option=com_content&view=article&id=63:cor-cabo-telefone&catid=34:dicas-&Itemid=57 código de cores de cabos telefônicos]<br />
* Manual de Instalação de Central Telefônica[[Media:ManualCentralTelefonica.pdf]]<br />
<br />
;Bibliografia Básica<br />
:1.CAETANO, S. S. Cabeamento estruturado. São José: IFSC. 2011. <br />
:2.Forouzan, Behrouz A. '''Comunicação de dados e redes de computadores'''; 5ª ed. São Paulo:McGraw-Hill, 2008. 1134p. ISBN 9788586804885<br />
:3.COELHO, P. E. Projetos de redes locais com cabeamento estruturado. 1a ed. Belo Horizonte: Instituto OnLine, 2003. <br />
:4.CREDER, H. Instalações elétricas. 15a ed. Rio de Janeiro: Livros Técnicos e Científicos, 2010. <br />
:5.MIYOSH, E. M., SANCHES, C. Projetos de sistemas rádio. 2a ed, São Paulo: Érica, 2002. <br />
<!--:5.Práticas TELEBRAS associadas a instalação e projeto de redes externas. 1a ed. Brasília: ANATEL, 1994.--><br />
<br />
;Bibliografia Complementar<br />
:1.CAVALIN G., CERVELIN, S. Instalações elétricas prediais: conforme norma NBR 5410:2004. 20a ed. São Paulo: Érica 2010 <br />
<!--:2.BARRADAS, O. C. M. Você e as telecomunicações. 1a ed, Rio de Janeiro: Interciência, 1995.--><br />
<br />
=Diário de aulas PJI1 - 2019-2 =<br />
<br />
{{Collapse top | 29/07 - Recepção da turma pela direção e coordenação }}<br />
<br />
* Recepção da turma pela direção e coordenação.<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 31/07 - Introdução a PJI2 - A Última Milha }}<br />
<br />
==31/07 - Introdução a PJI2 - A Última Milha==<br />
<br />
* Apresentação da disciplina e Plano de ensino;<br />
* Remontando a história das telecomunicações;<br />
* Uma visão geral sobre a última milha - a infraestrutura de Telecomunicações.<br />
<br />
===A Última Milha (last mile)===<br />
<br />
* Explicações básicas sobre a infra-estrutura de operadoras ou provedores de serviços de telecomunicações: tipos de meios de transmissão, custos de serviços, etc... <br />
* Noções de uma rede de telecom para atender um serviço de telefonia fixa a partir de um PoP, apresentadas a partir das seguintes situações:<br />
#Representação de todos os componentes e conexões envolvidos em um serviço de telefonia fixa usando a rede externa de cabeamento telefônico de uma operadora como por exemplo a OI. Considere o caso de um cliente que deseja um telefone fixo que está situado em uma região urbana, como uma residência individual (casa). <br />
#O que muda no diagrama para um outro caso como uma empresa ou instituição(ex.:IFSC)?<br />
#O tipo de rede que atende as duas situações acima são chamadas de rede de acesso (rede externa de telefonia) que também é utilizada para dar acesso a outros serviços como internet (ex. ADSL).<br />
<br />
===Diferenciando Rede Externa, Rede Interna e Cabeamento Estruturado===<br />
<br />
* Usar as mesmas questões da aula anterior considerando agora um serviço de internet fornecido pela mesma operadora. A partir das respostas das equipes concluir sobre:<br />
#Distinção entre Redes de Acesso, cabeamento estruturado e Redes Locais;<br />
#Componentes de uma infraestrutura de telecomunicações envolvidos em cada tipo de rede de acesso (associados com tipos de meios de transmissão diferentes: fibra óptica e rádio enlace);<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 05/08 - Componentes de Cabeamento Estruturado }}<br />
<br />
==05/08 - Componentes de Cabeamento Estruturado ==<br />
<br />
* Normas e padrões relativos a cabeamento estruturado: [[Media: T_tulo_da_aula.pdf | Slides utilizados em sala]];<br />
* Conceitos importantes sobre a banda passante dos meios de transmissão metálicos;<br />
* Componentes Passivos de rede: Aspectos físicos e elétricos; <br />
<br />
=== A seguir são Apresentados alguns Componentes Passivos de Cabeamento Estruturado ===<br />
<br />
=== Patch Panel ===<br />
<br />
A figura a baixo refere-se a um Patch Panel:<br />
<br />
[[Imagem:PatchPanel.GIF|500px]]<br />
<br />
O Patch panel é um elemento passivo que permite a conexão entre os cabos vindos de equipamentos ativos, <br />
cabeamentos primários e cabeamentos secundários. <br />
Apresenta portas no formato modular (RJ45) permitindo a conexão de cabos UTPs, STPs e FTPs com conectores <br />
modulares e no painel traseiro apresenta contatos do tipo IDC (Caetano, 2011).<br />
O cabo que ficará fixo na porta do patch panel é conectado no painel traseiro e o path cord (cordão de manobra),<br />
elemento móvel utiliza os conectores modulares RJ45.<br />
<br />
=== Bloco IDC 110 ===<br />
<br />
A figura a baixo refere-se a um Bloco IDC 110:<br />
<br />
[[Imagem:IDC110.JPEG|400px]]<br />
<br />
Possui a mesma função do patch panel, porém não apresenta as portas RJ45. Os cabos dos equipamentos ativos e do<br />
cabeamento primário são conectados no corpo do bloco 110 e os cabos secundários nos módulos de conexão colocados <br />
sobre o bloco 110, através de instrumento de pressão (Caetano, 2011).<br />
<br />
=== Patch Cord ===<br />
<br />
Veja a Figura abaixo:<br />
<br />
[[Imagem:PATCHCORD2.JPEG|350px]]<br />
<br />
O patch cord é um cabo que possui em suas extremidades conectores rj-45 macho, nestes conectores são seguidos padrões de montagem que podem ser T568A ou T568B.<br />
<br />
=== Tomada RJ45 ===<br />
<br />
Considere a Figura abaixo:<br />
<br />
[[Imagem:TomadaRJ45.JPEG|250px]]<br />
<br />
As tomadas RJ45 são utilizadas com os cabos UTP, STP e FTP de 4 pares. Esta tomadas apresentam contados do tipo IDC, <br />
para fixação do cabo da rede e conector modular RJ45 fêmea para conexão do cabo do equipamento. Existe uma diversidade <br />
de espelhos e suportes para tomadas RJ45 (Caetano, 2011).<br />
<br />
=== Conector RJ45 ===<br />
<br />
Os conectores RJ45 são utilizados para terminação de cabos UTP. Sua montagem exige a crimpagem do conector<br />
através de ferramenta apropriada, garantido um bom contato mecânico com o cabo UTP. A norma<br />
TIA/EIA 568, apresenta duas especificações de pino/par para a conexão dos conectores modulares (Caetano, 2011).<br />
Veja a Figura abaixo:<br />
<br />
[[Imagem:RJ45.JPEG|250px]]<br />
<br />
Quando utilizados conectores modulares em cabos STP ou FTP, cabos blindados, os conectores também devem ser blindados. <br />
<br />
=== Cabo Categoria 5e ===<br />
Veja a Figura abaixo:<br />
<br />
[[Imagem:CABO5E.PNG|250px]]<br />
<br />
O Cabo categoria 5e possui taxa de transmissão máxima para rede Ethernet de 1000 Mbps e 100MHz de Capacidade de BW<br />
em 100m.<br />
<br />
<br />
=== Cabo Categoria 6a ===<br />
Considere a Figura abaixo:<br />
<br />
[[Imagem:CABO6A.JPEG|250px]]<br />
<br />
O Cabo categoria 6a possui taxa de transmissão máxima para rede Ethernet de 10 Gbps e 500MHz de Capacidade de BW<br />
em 100 metros.<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 07/08 - <math>\blacklozenge</math> Elementos Funcionais de Cabeamento Estruturado }}<br />
<br />
==07/08 - Elementos Funcionais de Cabeamento Estruturado ==<br />
<br />
== Preparação para a primeira parte do projeto integrador ==<br />
<br />
* Revisão das primeiras aulas. <br />
* Banda passante e atenuação de um sinal em meio de transmissão metálico.<br />
* Questões de 1 a 7 feitas em sala de aula. Questões de 8 a 21 para entregar quarta-feira, dia 14/08. [[Media: 1a_Lista_de_Exercicios.pdf | Lista]]<math>\blacklozenge</math><br />
<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 12/08 - <math>\blacklozenge</math> Subsistemas de Cabeamento Estruturado e Tipos de Conexão }}<br />
<br />
==12/08 - Subsistemas de Cabeamento Estruturado e Tipos de Conexão ==<br />
<br />
== Preparação para a primeira parte do projeto integrador ==<br />
<br />
* Categorização de cabeamento e tipos. (UTP, STP, telefônicos externo, interno...) <br />
* Cabos metálicos: detalhes do funcionamento de cabos coaxiais e par trançado.<br />
* Material de apoio utilizado: [[Media:4.2IFSC_Aula_Integrado_CAB_2015_1.pdf | Slides Par trançado]]<br />
* Questões do material de apoio utilizado feitas em sala de aula.<math>\blacklozenge</math><br />
* Questões feitas em casa para entregar dia 19/08, segunda-feira. [[Media: 2a_Lista_de_Exercicios.pdf | Lista 2]] <math>\blacklozenge</math><br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 14/08 - Apresentação do Projeto do Semestre e início da execução }}<br />
<br />
==14/08 - Apresentação do Projeto do Semestre e início da execução==<br />
* Estrutura e normas de cores dos Conectores RJ-11, RJ-14, RJ-25 e RJ-45.<br />
* Visão geral sobre cabeamento estruturado (entrada de facilidades, sala de equipamentos, backbone, cabeamento horizontal, sala de telecomunicações...).<br />
* Tipos de conexões do cabeamento:<br />
#Conexão cruzada - Cross-connect<br />
#Interconexão - Interconnect<br />
#Ponto de Consolidação<br />
<br />
* Material de apoio utilizado: [[Media: Aula_05_-_PJI11101.pdf | Visão Geral]]<br />
<br />
* Video Abordando o Cabo UTP - [https://www.youtube.com/watch?v=TEZqmd0z4Ps Click aqui]<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 19/08 - Cabeamento Horizontal }}<br />
<br />
==19/08 - Cabeamento Horizontal ==<br />
<br />
* Fundamentos de fibra óptica. Material de apoio sobre [[Media:4.3IFSC_Aula_Integrado_CAB_2015_1.pdf | Fibra Óptica]]<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 21/08 - Apresentação do Projeto do Semestre e início da execução }}<br />
<br />
==21/08 - Apresentação do Projeto do Semestre e início da execução==<br />
<br />
* Definição de um projeto completo de Cabeamento Estruturado, de um sistema de CFTV e de uma rede externa de operadoras provendo de serviços de telefonia, internet e TV cabo;<br />
#Parte 1 Cabeamento Horizontal; Telefonia Privada;<br />
#Parte 2 Rede Externa de Telefonia - Última Milha com serviços de telefonia; Entrada de Facilidades;<br />
#Parte 3 Serviços de acesso ADSL; Wireless, CATV e CFTV;<br />
#Parte 4 Tecnologia FTTH;<br />
#Parte 5 Projeto Elétrico.<br />
<br />
* Definição do cabeamento horizontal a ser instalado para a primeira parte do projeto;<br />
* Organização das equipes e orientação sobre atitudes e o compartilhamento do Laboratório e recursos disponíveis.<br />
* Início da execução do cabeamento horizontal.<br />
<br />
===Parte 1 - Cabeamento Horizontal e entrada de facilidades===<br />
<br />
Passos para execução, para cada um dos quatro grupos:<br />
<br />
#Seleção de 6(seis) cabos de 1(um) metro de comprimento, e 12(doze) conectores RJ45;<br />
#Manufatura de seis cabos de interconexão (simulação de '''pacth-cords''') com os componentes acima;<br />
#Teste de continuidade dos cabos;<br />
#Seleção de quatro cabos para o cabeamento permanente conforme orientação dos professores;<br />
#Instalação de pacth-panel nos armários de telecomunicações de cada grupo;<br />
#Passagem dos cabos pela calha aérea e eletrodutos;<br />
#Instalação das tomadas de telecomunicações;<br />
#Conexão dos cabos permanentes aos pacth-panels.<br />
<br />
;Complementos da aula:<br />
<br />
* Video Abordando o Cabo UTP - [https://www.youtube.com/watch?v=TEZqmd0z4Ps Click aqui]<br />
* Video com o Passo a Passo para Montar um Cabo de Rede - [https://www.youtube.com/watch?v=wmxiV0hQUGE Click aqui]<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 26/08 - Parte 1 - Cabeamento Horizontal - Cabeamento Permanente }}<br />
<br />
==26/08 - Parte 1 - Cabeamento Horizontal - Cabeamento Permanente ==<br />
<br />
<br />
Passos para execução, para cada um dos quatro grupos:<br />
<br />
#Prática com ferramentas punch para path-panel e blocos IDC;<br />
#Seleção de quatro cabos para o cabeamento permanente conforme orientação dos professores;<br />
#Instalação de path-panel nos armários de telecomunicações de cada grupo;<br />
#Passagem dos cabos pela calha aérea e eletrodutos;<br />
#Instalação das tomadas de telecomuncações;<br />
#Conexão dos cabos permanentes aos path-panels.<br />
<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 28/08 - Parte 1 - Visão básica da identificação conforme TIA606 }}<br />
<br />
==28/08 - Parte 1- Visão básica da identificação conforme TIA606 ==<br />
<br />
* Apresentação do básico da norma [http://www.sj.ifsc.edu.br/~casagrande/PIJ2/tia606.pdf TIA606 Visão Básica]<br />
* continuação das atividades da aula anterior:<br />
<br />
#Instalação das tomadas de telecomunicações;<br />
#Conexão dos cabos permanentes aos pacth-panels.<br />
#Instalação do PABX ao Pacth Panel.<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 02/09 - <math>\blacklozenge</math> Parte 1 - Continuação do cabeamento horizontal - Exercícios }}<br />
<br />
==02/09 - <math>\blacklozenge</math> Parte 1 - Continuação do cabeamento horizontal - Exercícios ==<br />
<br />
* Término das atividades da aula anterior;<br />
* Testes dos pontos de telecomunicação com o PABX e aparelhos Telefônicos;<br />
* [[media:lista1p2.pdf | Lista de Exercício]] em sala<br />
<br />
<math>\blacklozenge</math> Atividade Extra: Entregar resolvida a [[media:lista1p2.pdf | Lista de Exercício]] orientada e iniciada em sala de aula, entregando por grupo até dia 09/09/2019 na forma MANUSCRITA.<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 04/09 - Parte 1 - Conclusão do cabeamento horizontal e identificação segundo TIA606 }}<br />
<br />
==04/09 - Parte 1 - Conclusão do cabeamento horizontal e identificação segundo TIA606 ==<br />
<br />
* Montagem da tabela de certificação do cabeamento horizontal;<br />
* Testes finais dos pontos de telecomunicação com o PABX e aparelhos Telefônicos;<br />
* [[media:tia-606-b.pdf | Norma TIA 606]] - Material de Apoio<br />
* [[media:Redes_NBR14565.pdf | Norma NBR 14565]] - Material de Apoio<br />
* [[media:template_29x90mm.odt | Modelo Etiqueta Brother QL700 29x90mm impressão vertical]]<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 09/09 - Parte 2 - Rede externa de Telefonia }}<br />
<br />
==09/09 - Parte 2 - Rede externa de Telefonia ==<br />
<br />
; Parte 2 - Rede Externa de Telefonia: Última Milha com serviços de telefonia; Entrada de Facilidades;<br />
<br />
* [https://www.nexans.com.br/eservice/Brazil-pt_BR/navigate_214261/CTP_APL.html Código de cores de cabos telefônicos];<br />
* Prática com Bloco IDC110 e ferramentas;<br />
* Prática Com Blocos Bargoa e ferramentas;<br />
* Passagem do cabo externo CTP APL do PoP ao Cliente.<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 11/09 - Parte 2 - Implementação da rede de acesso (última milha) de Telefonia }}<br />
<br />
==11/09 - Parte 2 - Implementação da rede de acesso (última milha) de Telefonia ==<br />
<br />
* Implementação da rede de acesso (última milha) de Telefonia<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 16/09 - Parte 2 - Testes e revisão da Rede externa de Telefonia }}<br />
<br />
==16/09 - Parte 2 - Testes e revisão da Rede externa de Telefonia ==<br />
<br />
* Testes e revisão da Rede externa de Telefonia <br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 18/09 - Parte 2 - Testes e revisão da Rede externa de Telefonia Rede externa de Telefonia entre equipes }}<br />
<br />
==18/09 - Parte 2 - Testes e revisão da Rede externa de Telefonia entre equipes ==<br />
<br />
*Testes e revisão da Rede externa de Telefonia entre equipes.<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 23/09 - Parte 2 - Continuação parte externa Telefonia - exercícios de preparação para prova A1 }}<br />
<br />
==23/09 - Parte 2 - Continuação parte externa Telefonia - exercícios de preparação para prova A1 ==<br />
<br />
* [[Media: Exercícios_PJI_preprova.odt | Exercícios]] feitos em sala de aula.<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 25/09 - Avaliação A1 }}<br />
<br />
==25/09 - Avaliação A1 ==<br />
<br />
* Primeiras aulas: Preparação para avaliação. Organização dos materiais, tira dúvidas entre membros de equipes, ensaios práticos no cabeamento construído, etc...<br />
* Uĺimas aulas, 50min de avaliação teórica e 30 min de avaliação prática;<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 30/09 - Correção da Avaliação A1 - Apresentação da parte 3 do projeto }}<br />
<br />
==30/09 - Correção da Avaliação A1 - Apresentação da parte 3 do projeto ==<br />
<br />
* Primeiras aulas: Correção da Prova A1<br />
* Uĺtimas aulas: Apresentação e início da parte 3 do projeto:<br />
<br />
;Parte 3 - Serviços de acesso ADSL; Wireless, CATV e CFTV;<br />
<br />
* Abordagem básica sobre a tecnologia ADSL: Telefonia + dados upload e download.<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 02/10 - Parte 3 - Ativação de serviços ADSL e router WIFI }}<br />
<br />
==02/10 - Parte 3 - Ativação de serviços ADSL e router WIFI==<br />
<br />
* Serviço ADSL: Fundamentos, ativos e explicações sobre a tecnologia;<br />
* Ativação de serviços ADSL configuração dos modens ADSL;<br />
* Ativação e configuração de router WIFI.<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 07/10 - Parte 3 - Redes de CATV }}<br />
<br />
==07/10 - Parte 3 - Redes de CATV==<br />
<br />
* [http://www.sj.ifsc.edu.br/~casagrande/PIJ2/CATV.pdf Um Tutorial básico sobre CATV]<br />
<br />
{{Collapse bottom}}<br />
<br />
<br />
{{Collapse top | 10/10 - <math>\blacklozenge</math> Parte 3 - Redes de CFTV - Recuperação Avaliação A1 }}<br />
<br />
==10/10 - <math>\blacklozenge</math> Parte 3 - Redes de CFTV - Recuperação Avaliação A1 ==<br />
<br />
* Primeiras aulas: CFTV - teoria, componentes, aplicações e uso em cabeamento estruturado;<br />
* Uĺimas aulas, 50min de recuperação de avaliação teórica e 30 min de avaliação prática;<br />
<br />
<math>\blacklozenge</math> Atividades Extra - Entrega em 21/10/2019 em equipe: <br />
<br />
{{Collapse bottom}}<br />
<br />
<br />
{{VOLTAR |Curso Técnico em Telecomunicações - Páginas das Disciplinas}}<br />
{{TECTELECO}}</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=Curso_T%C3%A9cnico_em_Telecomunica%C3%A7%C3%B5es_-_Projeto_Integrador_I_(PJI1)&diff=162076Curso Técnico em Telecomunicações - Projeto Integrador I (PJI1)2019-10-07T20:08:01Z<p>127.0.0.1: /* 02/10 - Parte 3 - Ativação de serviços ADSL e router WIFI */</p>
<hr />
<div>'''Professores da unidade Curricular'''<br />
<br />
{{Professor|'''2019-2'''| [[PJI11101 2019-2|'''DIÁRIO DE AULAS''']] - ([[Jorge Henrique B. Casagrande]] e [[Ana Paula Rosa Negri]])}}<br />
<br />
{{Professor|'''2019-1'''| [[PJI11101 2019-1|'''DIÁRIO DE AULAS''']] ...}}<br />
<br />
{{Professor|'''2018-2'''| [[PJI11101 2018-2|'''DIÁRIO DE AULAS''']] ...}}<br />
<br />
{{Professor|'''2018-1'''| [[PJI11101 2018-1|'''DIÁRIO DE AULAS''']] - (Evanaska Maria B. Nogueira / Clayrton M. Henrique)}}<br />
<br />
{{Professor|'''2017-2'''| [[PJI11101 2017-2|'''DIÁRIO DE AULAS''']] - ([[Juliano de Souza]] e [[Cleber Jorge Amaral]])}}<br />
<br />
{{Professor|'''2017-1'''| [[PJI11101 2017-1|'''DIÁRIO DE AULAS''']] - ([[Juliano de Souza]] e [[Cleber Jorge Amaral]])}}<br />
<br />
{{Professor|'''2016-2'''| [[PJI11101 2016-2|'''DIÁRIO DE AULAS''']] - ([[Juliano de Souza]] e Fernando Rodrigues)}}<br />
<br />
;Material de aula da antiga disciplina de Projetos I (atual Projetos II) <br />
<br />
{{Professor|'''2016-1'''| [[PJI-2016-1|'''DIÁRIO DE AULAS''']] - ([[Marcelo Maia Sobral]] / [[Simara Sonaglio]])}}<br />
<br />
;Cronogramas da antiga disciplina de Projetos I (atual Projetos II) <br />
<br />
{{collapse top| bg=lightpurple | expandir=true |Semestre 2015-2}}<br />
{{Cronograma-top}}<br />
{{Cl|1 |2/10 | 3 | Apresentação da disciplina | Laboratório de Redes}}<br />
{{Cl|2 |8/10 | 3 | Conceitos básicos e início do projeto 1 | Laboratório de Redes}}<br />
{{Cl|3 |9/10 | 3 | Projeto 1: escolhendo e instalando o centro de midia; sistema operacional; introdução ao Linux | Laboratório de Redes}}<br />
{{Cl|4 |15/10 | 3 | Projeto 1: incluindo fontes de midia locais; arquivos e diretórios | Laboratório de Redes}}<br />
{{Cl|5 |16/10 | 3 | Projeto 1: transmitiindo a midia através da rede; comunicação de dados | Laboratório de Redes}}<br />
{{Cl|6 |22/10 | 3 | Projeto 1: transmitiindo a midia através da rede; comunicação de dados | Laboratório de Redes}}<br />
{{Cl|7 |23/10 | 3 | Projeto 1: continuação | Laboratório de Redes}}<br />
{{Cl|8 |29/10 | 3 | Projeto 1: continuação | Laboratório de Redes}}<br />
{{Cl|9 |5/11 | 3 | Projeto 1: apresentação pelas equipes; história das telecomunicações | Laboratório de Redes}}<br />
{{Cl|10 |6/11 | 3 | Projeto 2: implantando uma pequena rede local | Laboratório de Redes}}<br />
{{Cl|11 |12/11 | 3 | Projeto 2: instalação do sistema operacional em um computador | Laboratório de Redes}}<br />
{{Cl|12 |13/11 | 3 | Projeto 2: uso do sistema operacional; entendendo como o sistema operacional inicia (boot) | Laboratório de Redes}}<br />
{{Cl|13 |19/11 | 3 | Projeto 2: uso do sistema operacional; linha de comando: arquivos e diretórios | Laboratório de Redes}}<br />
{{Cl|14 |20/11 | 3 | Projeto 2: uso do sistema operacional; linha de comando: arquivos e diretórios; permissões | Laboratório de Redes}}<br />
{{Cl|15 |26/11 | 3 | Projeto 2: protegendo recursos no sistema operacional: usuários e grupos; linha de comando: compactadores | Laboratório de Redes}}<br />
{{Cl|16 |27/11 | 3 | Projeto 2: uso do sistema operacional; linha de comando: processos, entrada e saída padrão | Laboratório de Redes}}<br />
{{Cl|17 |3/12 | 3 | Projeto 2: uso do sistema operacional; linha de comando: entrada e saída padrão; instalação de software | Laboratório de Redes}}<br />
{{Cl|18 |4/12 | 3 | Projeto 2: configuração do sistema operacional para usar a rede; interfaces de rede e endereços IP | Laboratório de Redes}}<br />
{{Cl|19 |10/12 | 3 | Projeto 2: configuração do sistema operacional para usar a rede; rota default e rotas estáticas | Laboratório de Redes}}<br />
{{Cl|20 |11/12 | 3 | Projeto 2: revisão dos requisitos para adicionar um computador à rede | Laboratório de Redes}}<br />
{{Cl|21 |17/12 | 3 | Projeto 2: configuração automática de rede (dhcp); continuação do projeto | Laboratório de Redes}}<br />
{{Cl|22 |18/12 | 3 | Projeto 2: implantação da rede local: switches e ponto de acesso Wifi | Laboratório de Redes}}<br />
{{Cl|23 |4/2 | 3 | Projeto 2: implantação da rede local: switches e ponto de acesso Wifi | Laboratório de Redes}}<br />
{{Cl|24 |5/2 | 3 | Projeto 2: implantação do acesso a Internet: enlace ADSL | Laboratório de Redes}}<br />
{{Cl|25 |11/2 | 3 | Projeto 2: revisão sobre a implantação da rede do projeto; discussão sobre erros comuns de instalação | Laboratório de Redes}}<br />
{{Cl|26 |12/2 | 3 | Projeto 2: acesso externo ao computador da rede local com SSH e outros serviços | Laboratório de Redes}}<br />
{{Cl|27 |18/2 | 3 | Projeto 2: definição das características finais do projeto pelas equipes | Laboratório de Redes}}<br />
{{Cl|28 |25/2 | 3 | Projeto 2: conclusão e apresentação pelas equipes | Laboratório de Redes}}<br />
{{Cl|29 |26/2 | 3 | Projeto 3: apresentação; sistemas de telefonia; implantação de sua própria central telefônica | Laboratório de Redes}}<br />
{{Cl|30 |3/3 | 3 | Projeto 3: implantação de sua própria central telefônica | Laboratório de Redes}}<br />
{{Cl|31 |4/3 | 3 | Projeto 3: loop local e o enlace ADSL | Laboratório de Redes}}<br />
{{Cl|32 |10/3 | 3 | Projeto 3: rede telefônica convencional e telefonia IP; VoIP | Laboratório de Redes}}<br />
{{Cl|33 |11/3 | 3 | Projeto 3: conclusão e apresentação pelas equipes | }}<br />
{{cronograma-botton |120}}<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightpurple | expandir=true |Semestre 2015-1}}<br />
{{Cronograma-top}}<br />
{{Cl|1 |4/2 | 3 | Apresentação da disciplina | Laboratório de Redes}}<br />
{{Cl|2 |9/2 | 3 | Conceitos básicos e início do projeto 1 | Laboratório de Redes}}<br />
{{Cl|3 |11/2 | 3 | Projeto 1: escolhendo e instalando o centro de midia; sistema operacional; introdução ao Linux | Laboratório de Redes}}<br />
{{Cl|4 |23/2 | 3 | Projeto 1: incluindo fontes de midia locais; arquivos e diretórios | Laboratório de Redes}}<br />
{{Cl|5 |25/2 | 3 | Projeto 1: transmitiindo a midia através da rede; comunicação de dados | Laboratório de Redes}}<br />
{{Cl|6 |2/3 | 3 | Projeto 1: transmitiindo a midia através da rede; comunicação de dados | Laboratório de Redes}}<br />
{{Cl|7 |4/3 | 3 | Projeto 1: apresentação pelas equipes; história das telecomunicações | Laboratório de Redes}}<br />
{{Cl|8 |9/3 | 3 | Projeto 1: continuação | Laboratório de Redes}}<br />
{{Cl|9 |11/3 | 3 | Projeto 1: apresentação pelas equipes; história das telecomunicações | Laboratório de Redes}}<br />
{{Cl|10 |16/3 | 3 | Projeto 2: implantando uma pequena rede local | Laboratório de Redes}}<br />
{{Cl|11 |18/3 | 3 | Projeto 2: instalação do sistema operacional em um computador | Laboratório de Redes}}<br />
{{Cl|12 |23/3 | 3 | Projeto 2: uso do sistema operacional; entendendo como o sistema operacional inicia (boot) | Laboratório de Redes}}<br />
{{Cl|13 |25/3 | 3 | Projeto 2: protegendo recursos no sistema operacional: usuários e grupos; linha de comando: compactadores | Laboratório de Redes}}<br />
{{Cl|14 |30/3 | 3 | Projeto 2: uso do sistema operacional; linha de comando: processos, entrada e saída padrão | Laboratório de Redes}}<br />
{{Cl|15 |1/4 | 3 | Projeto 2: uso do sistema operacional; linha de comando: entrada e saída padrão; instalação de software | Laboratório de Redes}}<br />
{{Cl|16 |6/4 | 3 | Projeto 2: uso do sistema operacional; linha de comando: processos, entrada e saída padrão | Laboratório de Redes}}<br />
{{Cl|17 |8/4 | 3 | Projeto 2: uso do sistema operacional; linha de comando: entrada e saída padrão; instalação de software | Laboratório de Redes}}<br />
{{Cl|18 |13/4 | 3 | Projeto 2: configuração do sistema operacional para usar a rede; interfaces de rede e endereços IP | Laboratório de Redes}}<br />
{{Cl|19 |15/4 | 3 | Projeto 2: configuração do sistema operacional para usar a rede; rota default e rotas estáticas | Laboratório de Redes}}<br />
{{Cl|20 |22/4 | 3 | Projeto 2: revisão dos requisitos para adicionar um computador à rede | Laboratório de Redes}}<br />
{{Cl|21 |27/4 | 3 | Projeto 2: configuração automática de rede (dhcp); continuação do projeto | Laboratório de Redes}}<br />
{{Cl|22 |29/4 | 3 | Projeto 2: implantação da rede local: switches e ponto de acesso Wifi | Laboratório de Redes}}<br />
{{Cl|23 |4/5 | 3 | Projeto 2: implantação da rede local: switches e ponto de acesso Wifi | Laboratório de Redes}}<br />
{{Cl|24 |6/5 | 3 | Projeto 2: implantação do acesso a Internet: enlace ADSL | Laboratório de Redes}}<br />
{{Cl|25 |11/5 | 3 | Projeto 2: revisão sobre a implantação da rede do projeto; discussão sobre erros comuns de instalação | Laboratório de Redes}}<br />
{{Cl|26 |13/5 | 3 | Projeto 2: acesso externo ao computador da rede local com SSH e outros serviços | Laboratório de Redes}}<br />
{{Cl|27 |18/5 | 3 | Projeto 2: definição das características finais do projeto pelas equipes | Laboratório de Redes}}<br />
{{Cl|28 |20/5 | 3 | Projeto 2: continuação | Laboratório de Redes}}<br />
{{Cl|29 |25/5 | 3 | Projeto 2: continuação | Laboratório de Redes}}<br />
{{Cl|30 |27/5 | 3 | Projeto 2: conclusão e apresentação pelas equipes | Laboratório de Redes}}<br />
{{Cl|31 |1/6 | 3 | Projeto 3: apresentação; sistemas de telefonia | Laboratório de Redes}}<br />
{{Cl|32 |3/6 | 3 | Projeto 3: implantação de sua própria central telefônica | Laboratório de Redes}}<br />
{{Cl|33 |8/6 | 3 | Projeto 3: implantação de sua própria central telefônica | Laboratório de Redes}}<br />
{{Cl|34 |10/6 | 3 | Projeto 3: rede telefônica convencional e telefonia IP; VoIP | Laboratório de Redes}}<br />
{{Cl|35 |15/6 | 3 | Projeto 3: plano de numeração | Laboratório de Redes}}<br />
{{Cl|36 |17/6 | 3 | Projeto 3: integração de rede telefônica convencional e VoIP; interfaces FXO e FXS | Laboratório de Redes}}<br />
{{Cl|37 |22/6 | 3 | Projeto 3: convergência de telefonia; uso de PBX analógico | Laboratório de Redes}}<br />
{{Cl|38 |24/6 | 3 | Projeto 3: loop local e o enlace ADSL | Laboratório de Redes}}<br />
{{Cl|39 |29/6 | 3 | Projeto 3: continuação | Laboratório de Redes}}<br />
{{Cl|40 |1/7 | 3 | Projeto 3: conclusão e apresentação pelas equipes | Laboratório de Redes}}<br />
{{cronograma-botton |120}}<br />
<br />
{{collapse bottom}}<br />
<br />
;Objetivos e Cronograma de Atividades Geral<br />
<br />
{{collapse top| bg=lightgreen | expandir=true | Objetivos e Cronograma de Atividades Geral}}<br />
<br />
Objetivos:<br />
* Conhecer as normas para instalação do cabeamento estruturado;<br />
* Conhecer os elementos do cabeamento estruturado.<br />
* Instalar um cabeamento estruturado;<br />
* Conhecer o padrão da infraestrutura das redes de distribuição telefônica;<br />
* Conhecer os elementos da rede de distribuição de telefonia.<br />
* Instalar redes de distribuição de telefonia.<br />
* Conhecer a infraestrutura de redes HFC<br />
* Conhecer elementos da rede HFC.<br />
* Conhecer o funcionamento básica de um enlace de radiotransmissão (antena X comprimento de onda; antena X ganho; atenuação, direcionamento de antes no espaço livre)<br />
* Instalar um radio enlace<br />
* Conhecer a norma brasileira para instalações elétricas.<br />
* Conhecer a função e os tipos de nobreak<br />
* Instalar a infraestrutura de energia elétrica de uma rede local.<br />
<br />
Atividades:<br />
* Instalação de cabeamento estruturado;<br />
* Uso da instalação do cabeamento estruturado para rede de computadores, telefonia, sensores e TV;<br />
* Instalação de rede externa de telefonia;<br />
* Uso da rede instalada para operação de uma rede telefônica e acesso xDSL;<br />
* Realizar conexões e emendas em cabos coaxias e fibras ópticas;<br />
* Dimensionamento de um circuito de alimentação elétrica para um cabeamento estruturado.<br />
* Instalação da infraestrutura de energia elétrica de uma rede local.<br />
<br />
Atividades em 2 dias por semana / 20 semanas por semestre;<br />
<br />
{| border="1" cellpadding="2"<br />
!Semana<br />
!Aula 1<br />
!Aula 2<br />
|-<br />
|1 <br />
|| Apresentação do Projeto Integrador <br> Diferenciação de redes local e de acesso <br> Introdução ao cabeamento estruturado.<br />
|| Elementos do cabeamento estruturado (conhecer a função e manusear blocos, conectores, cabos ...). <br />
|-<br />
|2 <br />
|| Elementos do cabeamento estruturado <br> visão geral do cabeamento (distribuidores, backbones, cabeamento horizontal, área de trabalho <br> definição da estrutura a ser instalada. <br />
|| Instalação do cabeamento estruturado.<br />
|-<br />
|3 <br />
|| Instalação do cabeamento estruturado.<br />
|| Instalação do cabeamento estruturado.<br />
|-<br />
|4<br />
|| Verificação da instalação e da identificação (testes e relatório) <br> Instalação das redes locais (computadores, telefonia, sensores, TV).<br />
|| Instalação das redes locais: entender o funcionamento de switches ethernet (comutação de quadros de acordo com endereço MAC, aprendizado de endereços MAC, cuidados ao conectar switches - ex: evitar ''loops'')<br />
|-<br />
|5 <br />
|| Instalação das redes locais<br />
|| Visão geral da rede de distribuição de telefonia <br> Elementos do cabeamento estruturado (conhecer a função e manusear blocos, conectores, cabos ...)<br />
|-<br />
|6<br />
|| Instalar uma rede de distribuição telefônica.<br />
|| Instalar uma rede de distribuição telefônica.<br />
|-<br />
|7 <br />
|| Verificar a instalação da rede de distribuição telefônica <br> Operar uma central telefônica e uma rede Xdsl integrando com a rede de cabeamento estruturado.<br />
|| Operar uma central telefônica e uma rede Xdsl integrando com a rede de cabeamento estruturado.<br />
|-<br />
|8<br />
|| Visão geral da fibra óptica ,<br> cabos e conectores de fibra óptica <br> interligação de equipamentos com fibra óptica.<br />
|| Emendas com fibra e instrumentação óptica.<br />
|-<br />
|9 <br />
|| Instalar link com fibra óptica <br> verificar instalação <br> operar uma rede de telecomunicações no link de fibra<br />
|| Redes HFC e redes de distribuição de CATV <br> conhecer e manipular os elementos da rede HFC.<br />
|-<br />
|10 <br />
|| Instalar uma rede residencial de TV a cabo.<br />
|| Visão geral das redes PON (Palestra?)<br />
|-<br />
|11<br />
|| Visão geral da propagação de ondas e ocupação do espectro eletromagnético <br> Noções básicas e características fundamentais de antenas <br> Tipos de antenas e suas aplicações. <br />
|| Aspectos práticos em radiotransmissão: casamento de impedância, cabos e conectores empregados em altas frequências <br> Realização de conectorização e montagem de um sistema simples de radiotransmissão.<br />
|-<br />
|12 <br />
|| Noções de enlaces de rádio <br> Aspectos de propagação indoor x outdoor <br> Conexões ponto a ponto e multiponto <br> Balanço de potência em enlaces de rádio <br> Alinhamento de antenas <br> Polarização<br />
|| Instalação e teste de um enlace de rádio.<br />
|-https://wiki.sj.ifsc.edu.br/index.php/PJI11101_2018-1<br />
|13<br />
|| Implantação de rede local sem-fio: pontos de acesso e integração com rede local cabeada<br />
|| Implantação de rede local sem-fio: sistemas de distribuição (cabeado e sem-fio)<br />
|-Eletrônica e instrumentação<br />
|14 <br />
|| Implantação de rede local sem-fio: caracterização de canal sem-fio e impedimentos para a comunicação, uso de antenas direcionais, escolha de canais para pontos de acesso<br />
|| Implantação de rede local sem-fio: posicionamento de pontos de acesso para otimizar cobertura e minimizar interferências<br />
|-<br />
|15 <br />
|| Instalação do circuito elétrico para uma estrutura de cabeamento estruturado<br />
|| Nobreak - função, tipos forma de especificação.<br />
|-<br />
|16 <br />
|| Especificação de Nobreak.<br />
|| <br />
|-<br />
|17<br />
|| Dimensionamento de circuitos elétricos.<br />
|| Dimensionamento de circuitos elétricos voltados para infraestrutura de redes locais.<br />
|-<br />
|18<br />
|| Projeto de circuito elétrico para uma estrutura de cabeamento estruturado.<br />
|| Projeto de circuito elétrico para uma estrutura de cabeamento estruturado.<br />
|-<br />
|19 <br />
|| <br />
|| <br />
|-<br />
|20 <br />
|| folga para feriados e erros no dimensionamento da carga horária<br />
|| folga para feriados e erros no dimensionamento da carga horária<br />
|} <br />
{{collapse bottom}}<br />
<br />
;REGISTRO DAS ATIVIDADES 2019-2<br />
<br />
=[[PJI2-TecTel|Carga horária, Ementas, Bibliografia]]=<br />
<br />
=[[PJI2-TecTel (Plano de Ensino) | Plano de Ensino]]=<br />
<br />
=Dados Importantes=<br />
''Professores'': [[Jorge Henrique B. Casagrande]] - casagrande@ifsc.edu.br e [[Ana Paula Rosa Negri]] - ana.negri@ifsc.edu.br<br />
<br><br />
;Atendimento Paralelo conforme PPC<br />
2as e 4as 18:30h - 19h - Sala dos Professores de Tele 2 ou Laboratório de Meios de Transmissão.<br />
;Atendimento paralelo Adicional:<br />
'''Prof. Jorge Casagrande: 2as e 5as 17:35h - 18:30h - Sala dos Professores de Tele 2'''<br />
<br>'''Prof. Ana Negri: 3as e 6as às 15h - 16h - Sala dos Professores de Tele 2''' <br />
<br> ''Link alternativo para Material de Apoio da disciplina'': [http://www.sj.ifsc.edu.br/~casagrande/PJI veja link]<br />
<br />
=Avaliações=<br />
<br />
;Critérios <br />
:Os alunos serão avaliados da seguinte forma:<br />
::- 3 Avaliações parciais A1, A2 e A3. Cada avaliação parcial contará com uma '''PROVA ESCRITA''' de 1,5HA de conteúdos preferencialmente associados as teorias e práticas do projeto os quais representam 50% da nota; Os outros 50% de cada avaliação parcial é relativa a média das notas atribuídas a aptidão e qualidade das atividades práticas correspondentes as etapas desenvolvidas no projeto integrador, atividades extras e avaliação individual.<br><br />
::- Avaliação Individual (AI1, AI2 e AI3) é uma nota atribuída pelos professores que representa o mérito de assiduidade, participação em sala, cumprimento de tarefas adicionais como relatórios e listas de exercícios.<br><br />
::- Todas as notas parciais serão valoradas de 0 à 10 em passos de 1 pontos e convertidas em conceitos conforme abaixo:<br />
::Se '''NOTA FINAL (NF)''' OU '''PROVA ESCRITA'''da avaliação parcial '''< 6''' é OBRIGATÓRIO realizar a recuperação dos conteúdos da respectiva avaliação parcial <br><br />
::Se '''NOTA FINAL''' OU '''PROVA ESCRITA'''da avaliação parcial '''>= 6''' a recuperação de conteúdos é opcional<br><br />
<br />
::- '''Para a aprovação na disciplina''' é necessário atingir no mínimo nota '''6''' na média final ponderada em carga horária de todas as avaliações parciais e 75% de participação em sala de aula;<br><br />
::- As datas de recuperação das avaliações parciais serão decididas em comum acordo com a turma. <br><br />
<br />
=Resultados das Atividades Extras e Avaliações Parciais=<br />
<br />
{| border="1" cellpadding="5" cellspacing="0" <br />
!Aluno<br />
!AE1<br />
!AE2<br />
!AE3<br />
!AE4<br />
!AI1<br />
!Prova1 <br />
!A1<br />
!REC A1<br />
!NF A1<br />
|-<br />
|Adriano Augusto de Medeiros || || 9 || || || || || 1 || ||<br />
|-<br />
|Alden Liuti Nascimento || 10 || 10 || 9 || 10|| 10 || 9,4 || 9,6|| ||<br />
|-<br />
|Alessandra Alves da Silva || 6 || 10 || 7 ||7 || 10 || 6 || 7|| ||<br />
|-<br />
|Alexsandro Munzfeld || 8 || 7 || 9 ||9 || 10 || 5,1 || 6,8 || ||<br />
|-<br />
|Amanda Ferreira Pires || 6 || 9 || 4 || 7|| 8 || 2,9 || 4,8 || ||<br />
|-<br />
|Arieli Oliveira de Faria || 6 || 7 || 7 || 10|| 7 || 4 || 5,7|| ||<br />
|-<br />
|Bergery Janvier || 8 || 3 || 7 ||7 || 8 || 5 || 5,8 || ||<br />
|-<br />
|Daniel de Souza Lopes || 8 || 8 || 7 ||7 || 9 || 6,5 || 7,2|| ||<br />
|-<br />
|David Michael Niekelle || 7 || 7 || 9 || 7|| 10 || 6,6 || 7,3|| ||<br />
|-<br />
|Ermeson da Conceição Ribeiro dos Santos || 6* || 8 || 10 || 7|| 10 || 4,4 || 6,3|| ||<br />
|-<br />
|Fabio da Silva Moreira || 7 || 9 || 6 ||7 || 7 || 4,2 || 5,7|| ||<br />
|-<br />
|Gabriel Ferreira da Silva || || 10 || 8 || 10|| 10 || 8,6 || 8,1|| ||<br />
|-<br />
|Gisele Martins || 7 || 9 || 9 ||9 || 10 || 5,4 || 7,1|| ||<br />
|-<br />
|Hozana de Souza Freitas || 8 || 9 || 9 ||9 || 10 || 5,2 || 7,1|| ||<br />
|-<br />
|Kauan Kleber da SIlva || 8 || || 8 || 10|| 7 || ||3,3|| ||<br />
|-<br />
|Kenard Rodrigues Silva || 6 || || || || || || 0,6|| ||<br />
|-<br />
|Lesly Ogenus || 9 || 10 || 6 ||9 || 8 || 2,7 || 5,5|| ||<br />
|-<br />
|Louise Adriane da Costa Chagas || 6 || 8 || 8 || 7|| 10 || 4,5 || 6,1|| ||<br />
|-<br />
|Maiza da Cunha Silva || 7 || 8 || 7 ||7 || 10 || 5,3 || 6,5|| ||<br />
|-<br />
|Mariane da Silva Correa || || 8 || 6 || 10|| 10 || 6,4 || 6,6|| ||<br />
|-<br />
|Olívia Melo || || || ||10 || 9 || || 1,9|| ||<br />
|-<br />
|Patrick Freire Machado || 5 || || || || || || 0,5|| ||<br />
|-<br />
|Ronilda Amaral de Jesus || 6 || 10 || 7 || 7|| 10 || 6,7 || 7,3|| ||<br />
|-<br />
|Suzana Torres Moran || 6 || 10 || 8 || 9|| 8 || 4,3 || 6,2|| ||<br />
|-<br />
|Theophile Dorsaint || || || || 7|| 7 || 5 || 3,9|| ||<br />
|-<br />
|Whallace dos Santos Querino || 6 || 7 || 4 ||9 || 8 || || 3,4|| ||<br />
|-<br />
|}<br />
* [[Media: 1a_Lista_de_Exercicios.pdf | AE1]]: atividade extra do dia 07/08;<br />
* AE2: Questões do [[Media:4.2IFSC_Aula_Integrado_CAB_2015_1.pdf | material de apoio]] feitas em sala de aula no dia 12/08;<br />
* [[Media: 2a_Lista_de_Exercicios.pdf | AE3]]: atividade extra do dia 12/08;<br />
* [[media:lista1p2.pdf | AE4]]: atividade extra do dia 02/09;<br />
* AI1, AI2, AI3: Avaliação Individual de cada avaliação parcial.<br />
<br />
=Relatórios das Equipes=<br />
<br />
=Recados Importantes=<br />
<br />
<br> Toda vez que você encontrar a marcação <math>\blacklozenge</math> ao lado de alguma atividade, significa que essa atividade estará sendo computada na avaliação como Avaliação extra e/ou individual de A1, A2 ou A3. O prazo estabelecido para entrega estará destacado ao lado da atividade. Portanto, não perca o prazo limite para entrega. '''Atividades entregues fora do prazo terão seu valor máximo de nota debitado de 10 pontos ao dia;'''<br />
<br />
<br> '''Uso da Wiki:''' Todo o repositório de material de apoio e referências de nossas aulas passam a usar a Wiki de tele;<br />
<br />
<br> '''Whatsapp:''' Para interação fora da sala de aula, acessem nosso grupo no Whatsapp;<br />
<br />
<br> '''SIGAA: ''' Eventualmente alguns materiais, mídias instrucionais, avaliações ou atividades poderão usar o ambiente da turma virtual do SIGAA. O professor fará o devido destaque para isso;<br />
<br />
<br> '''ATENÇÃO:''' Uma avaliação poderá ser recuperada somente se existir justificativa reconhecida pela coordenação. Desse modo, deve-se protocolar a justificativa no prazo de 48 horas, contando da data e horário da avaliação, e aguardar o parecer da coordenação. O não cumprimento desse procedimento implica a impossibilidade de fazer a recuperação.<br />
<br />
=Material de Apoio=<br />
<br />
;Apostilas e Tutoriais<br />
<br />
* [http://www.sj.ifsc.edu.br/~saul/cabeamento%20estruturado/cabeamento%202011.pdf Apostila de Cabeamento Estruturado do Prof. Saul]<br />
* [http://www.sj.ifsc.edu.br/~casagrande/PIJ2/plantaexterna.pdf Apostila Sobre Planta Externa de Telefonia do Prof. Saul]<br />
* [http://www.sj.ifsc.edu.br/~casagrande/PIJ2/CATV.pdf Um Tutorial básico sobre CATV]<br />
* [http://www.sj.ifsc.edu.br/~casagrande/PIJ2/CFTV.pdf Um Tutorial básico sobre CFTV]<br />
* [http://www.aventuracctv.com/pt/dvr_tutorial/?index=11 Um link mais detalhado sore CFTV]<br />
<br />
;Slides utilizados durante algumas aulas<br />
* Cabeamento estruturado [http://www.sj.ifsc.edu.br/~casagrande/PIJ2/CE_visao.pdf Visão Geral]<br />
* Apresentação do básico da norma [http://www.sj.ifsc.edu.br/~casagrande/PIJ2/tia606.pdf TIA606 Visão Básica]<br />
* Cabos metálicos - Par trançado [[Media:4.2IFSC_Aula_Integrado_CAB_2015_1.pdf | Slides Par trançado]]<br />
* Visão geral de Cabeamento estruturado [[Media: Aula_05_-_PJI11101.pdf | Visão Geral]]<br />
* Fibra óptica [[Media:4.3IFSC_Aula_Integrado_CAB_2015_1.pdf | Slides Fibra Óptica]]<br />
<br />
;Listas de Exercícios<br />
<br />
* [http://www.sj.ifsc.edu.br/~casagrande/PIJ2/lista1_pj2.pdf LISTA 1] - parte 1.<br />
* [http://www.sj.ifsc.edu.br/~casagrande/PIJ2/lista2_pj2.pdf LISTA 2] - partes 2 e 3.<br />
<br />
;Vídeos Instrucionais<br />
* Video sobre Cabeamento Estruturado do CPT [https://www.youtube.com/watch?v=baLhqXPJGeY Parte 1] - Atenção: material disponibilizado somente para ser utilizado como estudo individual - Não usar em sala de aula!<br />
* Video Apresentando uma Visão Geral sobre a Norma técnica NBR14565:2012 [https://www.youtube.com/watch?v=4Ebo7_y3usU Click aqui]<br />
* Video Abordando o Cabo UTP - [https://www.youtube.com/watch?v=TEZqmd0z4Ps Click aqui]<br />
* Video com o Passo a Passo para Montar um Cabo de Rede - [https://www.youtube.com/watch?v=wmxiV0hQUGE Click aqui]<br />
<br />
;Manuais e outros<br />
* Norma ABNT [http://www.abntcatalogo.com.br/norma.aspx?ID=307178 NBR 14565]<br />
* Norma ABNT de projetos Elétricos de Baixa tensão [http://www.sj.ifsc.edu.br/~casagrande/PIJ2/nbr5410.pdf NBR5410]<br />
* Normas adotadas para Cabeamento Estruturado e Identificação por cores (Norma EIA/TIA-606)[[Media:Complemento.pdf]]<br />
* [http://www.peropi.com.br/index.php?option=com_content&view=article&id=63:cor-cabo-telefone&catid=34:dicas-&Itemid=57 código de cores de cabos telefônicos]<br />
* Manual de Instalação de Central Telefônica[[Media:ManualCentralTelefonica.pdf]]<br />
<br />
;Bibliografia Básica<br />
:1.CAETANO, S. S. Cabeamento estruturado. São José: IFSC. 2011. <br />
:2.Forouzan, Behrouz A. '''Comunicação de dados e redes de computadores'''; 5ª ed. São Paulo:McGraw-Hill, 2008. 1134p. ISBN 9788586804885<br />
:3.COELHO, P. E. Projetos de redes locais com cabeamento estruturado. 1a ed. Belo Horizonte: Instituto OnLine, 2003. <br />
:4.CREDER, H. Instalações elétricas. 15a ed. Rio de Janeiro: Livros Técnicos e Científicos, 2010. <br />
:5.MIYOSH, E. M., SANCHES, C. Projetos de sistemas rádio. 2a ed, São Paulo: Érica, 2002. <br />
<!--:5.Práticas TELEBRAS associadas a instalação e projeto de redes externas. 1a ed. Brasília: ANATEL, 1994.--><br />
<br />
;Bibliografia Complementar<br />
:1.CAVALIN G., CERVELIN, S. Instalações elétricas prediais: conforme norma NBR 5410:2004. 20a ed. São Paulo: Érica 2010 <br />
<!--:2.BARRADAS, O. C. M. Você e as telecomunicações. 1a ed, Rio de Janeiro: Interciência, 1995.--><br />
<br />
=Diário de aulas PJI1 - 2019-2 =<br />
<br />
{{Collapse top | 29/07 - Recepção da turma pela direção e coordenação }}<br />
<br />
* Recepção da turma pela direção e coordenação.<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 31/07 - Introdução a PJI2 - A Última Milha }}<br />
<br />
==31/07 - Introdução a PJI2 - A Última Milha==<br />
<br />
* Apresentação da disciplina e Plano de ensino;<br />
* Remontando a história das telecomunicações;<br />
* Uma visão geral sobre a última milha - a infraestrutura de Telecomunicações.<br />
<br />
===A Última Milha (last mile)===<br />
<br />
* Explicações básicas sobre a infra-estrutura de operadoras ou provedores de serviços de telecomunicações: tipos de meios de transmissão, custos de serviços, etc... <br />
* Noções de uma rede de telecom para atender um serviço de telefonia fixa a partir de um PoP, apresentadas a partir das seguintes situações:<br />
#Representação de todos os componentes e conexões envolvidos em um serviço de telefonia fixa usando a rede externa de cabeamento telefônico de uma operadora como por exemplo a OI. Considere o caso de um cliente que deseja um telefone fixo que está situado em uma região urbana, como uma residência individual (casa). <br />
#O que muda no diagrama para um outro caso como uma empresa ou instituição(ex.:IFSC)?<br />
#O tipo de rede que atende as duas situações acima são chamadas de rede de acesso (rede externa de telefonia) que também é utilizada para dar acesso a outros serviços como internet (ex. ADSL).<br />
<br />
===Diferenciando Rede Externa, Rede Interna e Cabeamento Estruturado===<br />
<br />
* Usar as mesmas questões da aula anterior considerando agora um serviço de internet fornecido pela mesma operadora. A partir das respostas das equipes concluir sobre:<br />
#Distinção entre Redes de Acesso, cabeamento estruturado e Redes Locais;<br />
#Componentes de uma infraestrutura de telecomunicações envolvidos em cada tipo de rede de acesso (associados com tipos de meios de transmissão diferentes: fibra óptica e rádio enlace);<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 05/08 - Componentes de Cabeamento Estruturado }}<br />
<br />
==05/08 - Componentes de Cabeamento Estruturado ==<br />
<br />
* Normas e padrões relativos a cabeamento estruturado: [[Media: T_tulo_da_aula.pdf | Slides utilizados em sala]];<br />
* Conceitos importantes sobre a banda passante dos meios de transmissão metálicos;<br />
* Componentes Passivos de rede: Aspectos físicos e elétricos; <br />
<br />
=== A seguir são Apresentados alguns Componentes Passivos de Cabeamento Estruturado ===<br />
<br />
=== Patch Panel ===<br />
<br />
A figura a baixo refere-se a um Patch Panel:<br />
<br />
[[Imagem:PatchPanel.GIF|500px]]<br />
<br />
O Patch panel é um elemento passivo que permite a conexão entre os cabos vindos de equipamentos ativos, <br />
cabeamentos primários e cabeamentos secundários. <br />
Apresenta portas no formato modular (RJ45) permitindo a conexão de cabos UTPs, STPs e FTPs com conectores <br />
modulares e no painel traseiro apresenta contatos do tipo IDC (Caetano, 2011).<br />
O cabo que ficará fixo na porta do patch panel é conectado no painel traseiro e o path cord (cordão de manobra),<br />
elemento móvel utiliza os conectores modulares RJ45.<br />
<br />
=== Bloco IDC 110 ===<br />
<br />
A figura a baixo refere-se a um Bloco IDC 110:<br />
<br />
[[Imagem:IDC110.JPEG|400px]]<br />
<br />
Possui a mesma função do patch panel, porém não apresenta as portas RJ45. Os cabos dos equipamentos ativos e do<br />
cabeamento primário são conectados no corpo do bloco 110 e os cabos secundários nos módulos de conexão colocados <br />
sobre o bloco 110, através de instrumento de pressão (Caetano, 2011).<br />
<br />
=== Patch Cord ===<br />
<br />
Veja a Figura abaixo:<br />
<br />
[[Imagem:PATCHCORD2.JPEG|350px]]<br />
<br />
O patch cord é um cabo que possui em suas extremidades conectores rj-45 macho, nestes conectores são seguidos padrões de montagem que podem ser T568A ou T568B.<br />
<br />
=== Tomada RJ45 ===<br />
<br />
Considere a Figura abaixo:<br />
<br />
[[Imagem:TomadaRJ45.JPEG|250px]]<br />
<br />
As tomadas RJ45 são utilizadas com os cabos UTP, STP e FTP de 4 pares. Esta tomadas apresentam contados do tipo IDC, <br />
para fixação do cabo da rede e conector modular RJ45 fêmea para conexão do cabo do equipamento. Existe uma diversidade <br />
de espelhos e suportes para tomadas RJ45 (Caetano, 2011).<br />
<br />
=== Conector RJ45 ===<br />
<br />
Os conectores RJ45 são utilizados para terminação de cabos UTP. Sua montagem exige a crimpagem do conector<br />
através de ferramenta apropriada, garantido um bom contato mecânico com o cabo UTP. A norma<br />
TIA/EIA 568, apresenta duas especificações de pino/par para a conexão dos conectores modulares (Caetano, 2011).<br />
Veja a Figura abaixo:<br />
<br />
[[Imagem:RJ45.JPEG|250px]]<br />
<br />
Quando utilizados conectores modulares em cabos STP ou FTP, cabos blindados, os conectores também devem ser blindados. <br />
<br />
=== Cabo Categoria 5e ===<br />
Veja a Figura abaixo:<br />
<br />
[[Imagem:CABO5E.PNG|250px]]<br />
<br />
O Cabo categoria 5e possui taxa de transmissão máxima para rede Ethernet de 1000 Mbps e 100MHz de Capacidade de BW<br />
em 100m.<br />
<br />
<br />
=== Cabo Categoria 6a ===<br />
Considere a Figura abaixo:<br />
<br />
[[Imagem:CABO6A.JPEG|250px]]<br />
<br />
O Cabo categoria 6a possui taxa de transmissão máxima para rede Ethernet de 10 Gbps e 500MHz de Capacidade de BW<br />
em 100 metros.<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 07/08 - <math>\blacklozenge</math> Elementos Funcionais de Cabeamento Estruturado }}<br />
<br />
==07/08 - Elementos Funcionais de Cabeamento Estruturado ==<br />
<br />
== Preparação para a primeira parte do projeto integrador ==<br />
<br />
* Revisão das primeiras aulas. <br />
* Banda passante e atenuação de um sinal em meio de transmissão metálico.<br />
* Questões de 1 a 7 feitas em sala de aula. Questões de 8 a 21 para entregar quarta-feira, dia 14/08. [[Media: 1a_Lista_de_Exercicios.pdf | Lista]]<math>\blacklozenge</math><br />
<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 12/08 - <math>\blacklozenge</math> Subsistemas de Cabeamento Estruturado e Tipos de Conexão }}<br />
<br />
==12/08 - Subsistemas de Cabeamento Estruturado e Tipos de Conexão ==<br />
<br />
== Preparação para a primeira parte do projeto integrador ==<br />
<br />
* Categorização de cabeamento e tipos. (UTP, STP, telefônicos externo, interno...) <br />
* Cabos metálicos: detalhes do funcionamento de cabos coaxiais e par trançado.<br />
* Material de apoio utilizado: [[Media:4.2IFSC_Aula_Integrado_CAB_2015_1.pdf | Slides Par trançado]]<br />
* Questões do material de apoio utilizado feitas em sala de aula.<math>\blacklozenge</math><br />
* Questões feitas em casa para entregar dia 19/08, segunda-feira. [[Media: 2a_Lista_de_Exercicios.pdf | Lista 2]] <math>\blacklozenge</math><br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 14/08 - Apresentação do Projeto do Semestre e início da execução }}<br />
<br />
==14/08 - Apresentação do Projeto do Semestre e início da execução==<br />
* Estrutura e normas de cores dos Conectores RJ-11, RJ-14, RJ-25 e RJ-45.<br />
* Visão geral sobre cabeamento estruturado (entrada de facilidades, sala de equipamentos, backbone, cabeamento horizontal, sala de telecomunicações...).<br />
* Tipos de conexões do cabeamento:<br />
#Conexão cruzada - Cross-connect<br />
#Interconexão - Interconnect<br />
#Ponto de Consolidação<br />
<br />
* Material de apoio utilizado: [[Media: Aula_05_-_PJI11101.pdf | Visão Geral]]<br />
<br />
* Video Abordando o Cabo UTP - [https://www.youtube.com/watch?v=TEZqmd0z4Ps Click aqui]<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 19/08 - Cabeamento Horizontal }}<br />
<br />
==19/08 - Cabeamento Horizontal ==<br />
<br />
* Fundamentos de fibra óptica. Material de apoio sobre [[Media:4.3IFSC_Aula_Integrado_CAB_2015_1.pdf | Fibra Óptica]]<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 21/08 - Apresentação do Projeto do Semestre e início da execução }}<br />
<br />
==21/08 - Apresentação do Projeto do Semestre e início da execução==<br />
<br />
* Definição de um projeto completo de Cabeamento Estruturado, de um sistema de CFTV e de uma rede externa de operadoras provendo de serviços de telefonia, internet e TV cabo;<br />
#Parte 1 Cabeamento Horizontal; Telefonia Privada;<br />
#Parte 2 Rede Externa de Telefonia - Última Milha com serviços de telefonia; Entrada de Facilidades;<br />
#Parte 3 Serviços de acesso ADSL; Wireless, CATV e CFTV;<br />
#Parte 4 Tecnologia FTTH;<br />
#Parte 5 Projeto Elétrico.<br />
<br />
* Definição do cabeamento horizontal a ser instalado para a primeira parte do projeto;<br />
* Organização das equipes e orientação sobre atitudes e o compartilhamento do Laboratório e recursos disponíveis.<br />
* Início da execução do cabeamento horizontal.<br />
<br />
===Parte 1 - Cabeamento Horizontal e entrada de facilidades===<br />
<br />
Passos para execução, para cada um dos quatro grupos:<br />
<br />
#Seleção de 6(seis) cabos de 1(um) metro de comprimento, e 12(doze) conectores RJ45;<br />
#Manufatura de seis cabos de interconexão (simulação de '''pacth-cords''') com os componentes acima;<br />
#Teste de continuidade dos cabos;<br />
#Seleção de quatro cabos para o cabeamento permanente conforme orientação dos professores;<br />
#Instalação de pacth-panel nos armários de telecomunicações de cada grupo;<br />
#Passagem dos cabos pela calha aérea e eletrodutos;<br />
#Instalação das tomadas de telecomunicações;<br />
#Conexão dos cabos permanentes aos pacth-panels.<br />
<br />
;Complementos da aula:<br />
<br />
* Video Abordando o Cabo UTP - [https://www.youtube.com/watch?v=TEZqmd0z4Ps Click aqui]<br />
* Video com o Passo a Passo para Montar um Cabo de Rede - [https://www.youtube.com/watch?v=wmxiV0hQUGE Click aqui]<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 26/08 - Parte 1 - Cabeamento Horizontal - Cabeamento Permanente }}<br />
<br />
==26/08 - Parte 1 - Cabeamento Horizontal - Cabeamento Permanente ==<br />
<br />
<br />
Passos para execução, para cada um dos quatro grupos:<br />
<br />
#Prática com ferramentas punch para path-panel e blocos IDC;<br />
#Seleção de quatro cabos para o cabeamento permanente conforme orientação dos professores;<br />
#Instalação de path-panel nos armários de telecomunicações de cada grupo;<br />
#Passagem dos cabos pela calha aérea e eletrodutos;<br />
#Instalação das tomadas de telecomuncações;<br />
#Conexão dos cabos permanentes aos path-panels.<br />
<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 28/08 - Parte 1 - Visão básica da identificação conforme TIA606 }}<br />
<br />
==28/08 - Parte 1- Visão básica da identificação conforme TIA606 ==<br />
<br />
* Apresentação do básico da norma [http://www.sj.ifsc.edu.br/~casagrande/PIJ2/tia606.pdf TIA606 Visão Básica]<br />
* continuação das atividades da aula anterior:<br />
<br />
#Instalação das tomadas de telecomunicações;<br />
#Conexão dos cabos permanentes aos pacth-panels.<br />
#Instalação do PABX ao Pacth Panel.<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 02/09 - <math>\blacklozenge</math> Parte 1 - Continuação do cabeamento horizontal - Exercícios }}<br />
<br />
==02/09 - <math>\blacklozenge</math> Parte 1 - Continuação do cabeamento horizontal - Exercícios ==<br />
<br />
* Término das atividades da aula anterior;<br />
* Testes dos pontos de telecomunicação com o PABX e aparelhos Telefônicos;<br />
* [[media:lista1p2.pdf | Lista de Exercício]] em sala<br />
<br />
<math>\blacklozenge</math> Atividade Extra: Entregar resolvida a [[media:lista1p2.pdf | Lista de Exercício]] orientada e iniciada em sala de aula, entregando por grupo até dia 09/09/2019 na forma MANUSCRITA.<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 04/09 - Parte 1 - Conclusão do cabeamento horizontal e identificação segundo TIA606 }}<br />
<br />
==04/09 - Parte 1 - Conclusão do cabeamento horizontal e identificação segundo TIA606 ==<br />
<br />
* Montagem da tabela de certificação do cabeamento horizontal;<br />
* Testes finais dos pontos de telecomunicação com o PABX e aparelhos Telefônicos;<br />
* [[media:tia-606-b.pdf | Norma TIA 606]] - Material de Apoio<br />
* [[media:Redes_NBR14565.pdf | Norma NBR 14565]] - Material de Apoio<br />
* [[media:template_29x90mm.odt | Modelo Etiqueta Brother QL700 29x90mm impressão vertical]]<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 09/09 - Parte 2 - Rede externa de Telefonia }}<br />
<br />
==09/09 - Parte 2 - Rede externa de Telefonia ==<br />
<br />
; Parte 2 - Rede Externa de Telefonia: Última Milha com serviços de telefonia; Entrada de Facilidades;<br />
<br />
* [https://www.nexans.com.br/eservice/Brazil-pt_BR/navigate_214261/CTP_APL.html Código de cores de cabos telefônicos];<br />
* Prática com Bloco IDC110 e ferramentas;<br />
* Prática Com Blocos Bargoa e ferramentas;<br />
* Passagem do cabo externo CTP APL do PoP ao Cliente.<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 11/09 - Parte 2 - Implementação da rede de acesso (última milha) de Telefonia }}<br />
<br />
==11/09 - Parte 2 - Implementação da rede de acesso (última milha) de Telefonia ==<br />
<br />
* Implementação da rede de acesso (última milha) de Telefonia<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 16/09 - Parte 2 - Testes e revisão da Rede externa de Telefonia }}<br />
<br />
==16/09 - Parte 2 - Testes e revisão da Rede externa de Telefonia ==<br />
<br />
* Testes e revisão da Rede externa de Telefonia <br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 18/09 - Parte 2 - Testes e revisão da Rede externa de Telefonia Rede externa de Telefonia entre equipes }}<br />
<br />
==18/09 - Parte 2 - Testes e revisão da Rede externa de Telefonia entre equipes ==<br />
<br />
*Testes e revisão da Rede externa de Telefonia entre equipes.<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 23/09 - Parte 2 - Continuação parte externa Telefonia - exercícios de preparação para prova A1 }}<br />
<br />
==23/09 - Parte 2 - Continuação parte externa Telefonia - exercícios de preparação para prova A1 ==<br />
<br />
* [[Media: Exercícios_PJI_preprova.odt | Exercícios]] feitos em sala de aula.<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 25/09 - Avaliação A1 }}<br />
<br />
==25/09 - Avaliação A1 ==<br />
<br />
* Primeiras aulas: Preparação para avaliação. Organização dos materiais, tira dúvidas entre membros de equipes, ensaios práticos no cabeamento construído, etc...<br />
* Uĺimas aulas, 50min de avaliação teórica e 30 min de avaliação prática;<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 30/09 - Correção da Avaliação A1 - Apresentação da parte 3 do projeto }}<br />
<br />
==30/09 - Correção da Avaliação A1 - Apresentação da parte 3 do projeto ==<br />
<br />
* Primeiras aulas: Correção da Prova A1<br />
* Uĺtimas aulas: Apresentação e início da parte 3 do projeto:<br />
<br />
;Parte 3 - Serviços de acesso ADSL; Wireless, CATV e CFTV;<br />
<br />
* Abordagem básica sobre a tecnologia ADSL: Telefonia + dados upload e download.<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 02/10 - Parte 3 - Ativação de serviços ADSL e router WIFI }}<br />
<br />
==02/10 - Parte 3 - Ativação de serviços ADSL e router WIFI==<br />
<br />
* Serviço ADSL: Fundamentos, ativos e explicações sobre a tecnologia;<br />
* Ativação de serviços ADSL configuração dos modens ADSL;<br />
* Ativação e configuração de router WIFI.<br />
<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 07/10 - Parte 3 - Redes de CATV }}<br />
<br />
==07/10 - Parte 3 - Redes de CATV==<br />
<br />
* [http://www.sj.ifsc.edu.br/~casagrande/PIJ2/CATV.pdf Um Tutorial básico sobre CATV]<br />
<br />
{{Collapse bottom}}<br />
<br />
<br />
{{VOLTAR |Curso Técnico em Telecomunicações - Páginas das Disciplinas}}<br />
{{TECTELECO}}</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=RED2-EngTel_(p%C3%A1gina)&diff=162075RED2-EngTel (página)2019-10-07T20:01:59Z<p>127.0.0.1: /* Resultados das Avaliações */</p>
<hr />
<div>'''Professores da Unidade Curricular'''<br />
<br />
{{Professor|2019-2|[[Jorge Henrique B. Casagrande]] }}<br />
{{Professor|2019-1|[[Jorge Henrique B. Casagrande]] [[RED29005 2019-1|(Diário de aulas)]]}}<br />
{{Professor|2018-2|[[Jorge Henrique B. Casagrande]] [[RED29005 2018-2|(Diário de aulas)]]}}<br />
{{Professor|2018-1|[[Jorge Henrique B. Casagrande]] [[RED29005 2018-1|(Diário de aulas)]]}}<br />
{{Professor|2017-2|[[Jorge Henrique B. Casagrande]] [[RED29005 2017-2|(Diário de aulas)]]}}<br />
{{Professor|2017-1|[[Jorge Henrique B. Casagrande]] [[RED29005 2017-1|(Diário de aulas)]]}}<br />
{{Professor|2016-2|[[Jorge Henrique B. Casagrande]] [[RED29005 2016-2|(Diário de aulas)]]}}<br />
{{Professor|2016-1|[[Jorge Henrique B. Casagrande]] [[RED29005 2016-1|(Diário de aulas)]]}}<br />
{{Professor|2015-2|[[Jorge Henrique B. Casagrande]] [[RED29005 2015-2|(Diário de aulas)]]}}<br />
{{Professor|2015-1|[[Jorge Henrique B. Casagrande]] [[RED29005 2015-1|(Diário de aulas)]]}}<br />
{{Professor|2014-2|[[Jorge Henrique B. Casagrande]] [[RED29005 2014-2|(Diário de aulas)]]}}<br />
{{Professor|2014-1|[[Jorge Henrique B. Casagrande]] [[RED29005 2014-1|(Diário de aulas)]]}}<br />
<br />
= [[RED2-EngTel|Carga horária, Ementas, Bibliografia]]=<br />
<br />
= [[RED2-EngTel (Plano de Ensino) | Plano de Ensino]]=<br />
<br />
=Dados Importantes=<br />
''Professor'': [[Jorge Henrique B. Casagrande]]<br />
<br>''Email'': casagrande@ifsc.edu.br<br />
<br>''Atendimento paralelo'': 2as e 5as das 17:35h às 18:30h (Sala de Professores de TELE II ou Laboratório de Redes de Computadores)<br />
<br> ''Link alternativo para Material de Apoio da disciplina'': http://www.sj.ifsc.edu.br/~casagrande/RED<br />
<br />
=Resultados das Avaliações=<br />
<br />
;Critérios<br />
:Os alunos serão avaliados da seguinte forma:<br />
::- 3 Avaliações parciais A1, A2 e A3. Cada avaliação parcial contará com uma '''PROVA ESCRITA''' de 2HA de conteúdos preferencialmente associados as teorias e práticas da disciplina os quais representam 60% da nota; Os outros 40% de cada avaliação parcial é relativa a média das notas atribuídas a aptidão e qualidade das atividades práticas e teóricas correspondentes, atividades extras e avaliação individual.<br><br />
::- Avaliação Individual (AI1, AI2 e AI3) é uma nota atribuída pelo professor que representa o mérito de assiduidade, participação em sala, cumprimento de tarefas adicionais como relatórios e listas de exercícios.<br><br />
::- Todas as notas parciais serão valoradas de 0 à 10 em passos de 1 ponto e convertidas em conceitos conforme abaixo:<br />
::Se '''NOTA FINAL (NF)''' OU '''PROVA ESCRITA'''da avaliação parcial '''< 6''' é OBRIGATÓRIO realizar a recuperação dos conteúdos da respectiva avaliação parcial <br><br />
::Se '''NOTA FINAL''' OU '''PROVA ESCRITA'''da avaliação parcial '''>= 6''' a recuperação de conteúdos é opcional<br><br />
<br />
::- '''Para a aprovação na disciplina''' é necessário atingir no mínimo nota '''6''' na média final ponderada em carga horária de todas as avaliações parciais e 75% de participação em sala de aula;<br><br />
::- As datas de recuperação das avaliações parciais serão decididas em comum acordo com a turma. <br><br />
<br />
<br />
{| border="1" cellpadding="5" cellspacing="0" <br />
!Aluno<br />
!AE1<br />
!AE2<br />
!AE3<br />
!AI1<br />
!Prova1 <br />
!A1<br />
!REC A1<br />
!NF A1<br />
!AE4<br />
|-<br />
|Amanda || 100|| 80||0 ||90 || 74|| || || ||<br />
|-<br />
|Bruno ||100 || 70||100||80 ||49 || || || ||<br />
|-<br />
|Guilherme ||100 ||0 || 70||90 ||31 || || || ||<br />
|-<br />
|Luan ||100 ||60 || 0 || 80|| 46|| || || ||<br />
|-<br />
|Maria || 100|| 90||0 ||90 ||60 || || || ||<br />
|-<br />
|Thiago || || || || ||56 || || || ||<br />
|- <br />
|}<br />
<br />
'''LEGENDA E DETALHES '''<br />
<br />
AE1 = Pesquisa de Campo - 01/08 <br><br />
AE2 = Questionamento sobre a rede construída no laboratório - 09/09 <br><br />
AE3 = Uso da técnica de CRC - 30/09 <br><br />
<br />
=Resultados do Journal RED19-2 (40% da avaliação de A2)=<br />
<br />
{| border="1" cellpadding="5" cellspacing="0" <br />
!Matrícula<br />
!Aluno<br />
!Revisor1<br />
!Revisor2<br />
!Revisor3<br />
!Professor<br />
!NF Artigo<br />
|-<br />
| || <!--aluno--> || || || || ||'''0'''<br />
|-<br />
|}<br />
<br />
=Recados Importantes=<br />
<br />
<br> Toda vez que você encontrar a marcação <math>\blacklozenge</math> ao lado de alguma atividade, significa que essa atividade estará sendo computada na avaliação como AIn de An. O prazo estabelecido para entrega estará destacado ao lado da atividade. Portanto, não perca o prazo limite para entrega. '''Atividades entregues fora do prazo terão seu valor máximo de nota debitado de 10 pontos ao dia;'''<br />
<br />
<br> '''Uso da Wiki:''' Todo o repositório de material de apoio e referências de nossas aulas passam a usar a Wiki de tele;<br />
<br />
<br> '''Whatsapp:''' Para interação fora da sala de aula, acessem nosso grupo no Whatsapp;<br />
<br />
<br> '''SIGAA: ''' Eventualmente alguns materiais, mídias instrucionais, avaliações ou atividades poderão usar o ambiente da turma virtual do SIGAA. O professor fará o devido destaque para isso;<br />
<br />
<br> '''ATENÇÃO:''' Uma avaliação poderá ser recuperada somente se existir justificativa reconhecida pela coordenação. Desse modo, deve-se protocolar a justificativa no prazo de 48 horas, contando da data e horário da avaliação, e aguardar o parecer da coordenação. O não cumprimento desse procedimento implica a impossibilidade de fazer a recuperação.<br />
<br />
=Material de Apoio=<br />
<br />
;Tabela de leitura básica das Bibliografias recomendadas (PARA AVALIAÇÃO FINAL)<br />
<br />
{| border="1" cellpadding="5" cellspacing="0" <br />
!Referência<br />
!Tópicos<br />
!Observações<br />
|-<br />
|Kurose 5ª edição || seções dos capítulos 1.1 à 1.4, 5.1, 5.2, 5.7 e 5.8 || <br />
|-<br />
|Forouzan 4ª edição || capítulos 1 e 3 e as seções 4.1, 4.3, 5.1, 6.1, 7.1, 8.1 à 8.3, 9.2, 9.3, 10.1, 10.4, 10.5, 11.1 à 11.3, 11.6, 11.7 e 18.1 || <br />
|-<br />
|Tanenbaum 4ª edição ||cap 4, 5.4.5 (ou seção 5.6.5 da 5ª ed.)|| <br />
|-<br />
|}<br />
<br />
;Atividades extra sala de aula<br />
:* [http://tele.sj.ifsc.edu.br/~casagrande/RED/lista1_2019_1.pdf LISTA1] de exercícios para a avaliação A1 - parte 1<br />
:* [http://tele.sj.ifsc.edu.br/~casagrande/RED/lista2_2019_1.pdf LISTA2] de exercícios para a avaliação A1 - parte 2<br />
:* [http://tele.sj.ifsc.edu.br/~casagrande/RED/lista3_2015_2.pdf LISTA3] de exercícios para a avaliação A2<br />
:* [http://tele.sj.ifsc.edu.br/~casagrande/RED/lista4_2014_2.pdf LISTA4] de exercícios para a avaliação A3<br />
<br />
<br />
;Slides utilizados durante algumas aulas<br />
<br />
:* [http://www.sj.ifsc.edu.br/~casagrande/RED/slides/InterfacesDigitais.pdf Interfaces Digitais];<br />
:* [http://www.sj.ifsc.edu.br/~casagrande/RED/slides/modens.pdf Modens e enlaces de teste] <br />
:* [http://www.sj.ifsc.edu.br/~casagrande/RED/slides/redes_circuitos_virtuais_FR.pdf Redes Frame Relay];<br />
:* [http://www.sj.ifsc.edu.br/~casagrande/RED/slides/protocolos_pp.pdf Protocolos Ponto à Ponto];<br />
:* [http://tele.sj.ifsc.edu.br/~casagrande/RED/slides/lan.pdf REDES LOCAIS]<br />
:* [http://tele.sj.ifsc.edu.br/~casagrande/RED/slides/vlan.pdf IEEE802.3q VLAN]<br />
:* [http://tele.sj.ifsc.edu.br/~casagrande/RED/slides/stp.pdf IEEE802.3d]<br />
:* [http://tele.sj.ifsc.edu.br/~casagrande/RED/slides/ieee.pdf Arquitetura IEEE802.3]<br />
:* [http://tele.sj.ifsc.edu.br/~casagrande/RED/slides/wlan.pdf Conceitos básicos da arquitetura IEEE802.11]<br />
<br />
;Manuais e outros<br />
<br />
:* [https://www.youtube.com/watch?v=mNkWP61GQVs vídeo sobre a atividade dos técnicos de telecomunicações]<br />
:* [https://www.youtube.com/watch?v=ArKcy2WLRac LiFi]<br />
:* [https://www.youtube.com/watch?v=cZcXLu9qM7A VLC]<br />
:* [https://www.youtube.com/watch?v=SrjZDBsG1v8 PLC]<br />
<br />
* [http://www.sj.ifsc.edu.br/~msobral/RCO2/manuais/Guia_DT2048_SHDSL_T_E_S_VG_210.5088.00-1.pdf Guia Rápido de Configuração Modem DT2048SHDSL;]<br />
* [http://tele.sj.ifsc.edu.br/~casagrande/RED/apoio/Manual_DT2048SHDSL.pdf Manual Modem DT2048SHDSL;] da Digitel;<br />
* [http://tele.sj.ifsc.edu.br/~casagrande/RED/apoio/Manual_NR-2G_3200_e_4200.pdf Manual Modem Router NR2G;] da Digitel;<br />
<!--<br />
* [http://www.cisco.com/warp/cpropub/45/tutorial.htm Tutorial sobre a interface CLI de roteadores Cisco.]<br />
* [http://www.cisco.com/en/US/tech/tk713/tk507/technologies_tech_note09186a008019cfa7.shtml#ppp01 Resolução de problemas com PPP em roteadores Cisco]<br />
* [http://www.cisco.com/en/US/products/hw/routers/ps221/products_password_recovery09186a0080094773.shtml Recuperação de senha em roteadores Cisco 1700 e 1800]<br />
<br />
* [http://www.sj.ifsc.edu.br/~casagrande/RED/apoio/Globalink3420guia.pdf guia rápido de configuração Globalink UP3420;] <br />
* [http://www.sj.ifsc.edu.br/~casagrande/RED/apoio/Globalink3420.pdf Manual de configuração Gloalink3420;] <br />
* [http://www.sj.ifsc.edu.br/~casagrande/RED/apoio/DT34.pdf Manual de configuração DT34.] <br />
* [http://www.sj.ifsc.edu.br/~casagrande/RED/apoio/DAS-3324.pdf Manual DSLAM DLINK DAS3324.] <br />
* [http://www.sj.ifsc.edu.br/~casagrande/RED/apoio/DAS-3324guia.pdf Guia rápido DSLAM DLINK DAS3324.]<br />
--><br />
<br />
== Bibliografia Básica ==<br />
<br />
* ''Redes de Computadores e a Internet, 5a edição'', de James Kurose.<br />
* ''Redes de Computadores, 4a edição'', de Andrew Tanenbaum.<br />
* ''Comunicação de Dados e Redes de Computadores, 4a edição'', de Behrouz Forouzan.<br />
<br />
* [http://www.sj.ifsc.edu.br/~msobral/RCO2/docs.html Links para outros materiais, normas, artigos, e apostilas do prof. Jorge Casagrande]<br />
* [https://books.google.com.br/books?id=FIaDr9ZtwXgC&dq=forouzan&hl=pt-BR&source=gbs_book_other_versions Comunicação de dados e Redes de Computadores, de Berhouz Forouzan (alguns capítulos no Google Books)]<br />
<br />
Para pesquisar o acervo das bibliotecas do IFSC:<br />
* [http://biblioteca.ifsc.edu.br/sophia/ Acesso ao acervo da Biblioteca do IFSC]<br />
<br />
== Softwares e Links úteis ==<br />
<br />
* [[Netkit]]: possibilita criar experimentos com redes compostas por máquinas virtuais Linux<br />
* [http://tele.sj.ifsc.edu.br/~casagrande/IER/ipkit.html IPKIT]: um simulador de encaminhamento IP em java (roda direto no navegador)<br />
* [https://www.sejda.com/pdf-editor editor de PDF]:<br />
* [https://www.postscapes.com/internet-of-things-protocols/ Padrões diversos de protocolos para IoT]<br />
<br />
=Diário de aulas RED29005 - 2019-2 - Prof. Jorge H. B. Casagrande=<br />
<br />
<br />
{{Collapse top |29/07 - Os Meios de transmissão e suas limitações}}<br />
<br />
==29/07 - Os Meios de transmissão e suas limitações ==<br />
<br />
* Apresentação da disciplina e plano de ensino;<br />
* Remontando a história da necessidade de comunicação à distância;<br />
* Os principais meios de transmissão.<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 01/08 - <math>\blacklozenge</math> Redes de Acesso}}<br />
<br />
==01/08 - <math>\blacklozenge</math> Redes de Acesso ==<br />
<br />
* Os meios metálicos como meios de transmissão e suas limitações;<br />
* O modelo elétrico de pares metálicos;<br />
* A last mile e a relação com o perfil de serviços de telecom: Players, espelhos, ISPs<br />
<br />
* <math>\blacklozenge</math> '''Tarefa pra casa''': [[media:PesquisaCampo2019_2.pdf |Pesquisa de Campo - Tecnologias de Acesso e de transporte]]<br />
<br />
;Apresentações do semestre:<br />
<br />
[[media:PesquisaCampo2019_2_1.pdf |Pesquisa de Campo - NET Aluno]] <br><br />
[[media:PesquisaCampo2019_2_2.pdf |Pesquisa de Campo - OI Aluno]] <br><br />
[[media:PesquisaCampo2019_2_3.pdf |Pesquisa de Campo - OI Aluno]] <br><br />
[[media:PesquisaCampo2019_2_4.pdf |Pesquisa de Campo - NET Aluno]]<br><br />
<br />
ATENÇÃO: '''O conteúdo destas apresentações fazem parte da avaliação escrita A1.'''<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |05/08 à 19/08 - Licença Paternidade}}<br />
<br />
==05/08 à 19/08 - Licença Paternidade==<br />
<br />
* Licença Paternidade<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |22/08 - Modelo Básico de Comunicação de Dados - Apresentações das pesquisas de campo }}<br />
<br />
==22/08 - Modelo Básico de Comunicação de Dados - Apresentações das pesquisas de campo==<br />
<br />
;Apresentações das pesquisas de campo.<br />
<br />
* Introdução sobre o Modelo Básico de Comunicação de Dados.<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 26/08 - Modelo Básico de Comunicação de Dados - Continuação}}<br />
<br />
==26/08 - Modelo Básico de Comunicação de Dados - Continuação ==<br />
<br />
'''ATENÇÃO: Para reforço dos assuntos tratados a partir desse ponto nesta aula, faça uma leitura do capítulo 3 completo e da seção 4.3 do capítulo 4 do Forouzan'''<br />
<br />
* O modelo básico de Comunicação de dados.<br />
* Comunicação serial;<br />
* Comunicação Assíncrona e Interfaces Digitais - UART [http://sj.ifsc.edu.br/~casagrande/RED/comunicação_serial.pdf (veja seções correspondentes desta referência)];<br />
* O modelo básico de comunicação de dados com DCEs: comunicação pino-à-pino;<br />
* O modelo básico de comunicação de dados sem DCEs (modems): comunicação cross-over;<br />
<br />
* A Interface Digital - camada física;<br />
<br />
<br />
;Experimento: Comunicação entre Computadores via porta serial;<br />
<br />
* uso de emuladores de terminal burro (ou dummy): Minicom do Linux.<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 29/08 - Interfaces Digitais}}<br />
<br />
==29/08 - Interfaces Digitais ==<br />
<br />
* Circuitos diferenciais e não diferenciais;<br />
* A Interface Digital RS232;<br />
* Exemplo de circuito de Interface Digital (ID) duplex usando comunicação com Interface Digital RS232C.<br />
* [http://www.sj.ifsc.edu.br/~casagrande/RED/slides/InterfacesDigitais.pdf Interfaces Digitais] para apoiar o entendimento do que foi colocado em aula. <br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 02/09 - Interfaces Digitais - final}}<br />
<br />
==02/09 - Interfaces Digitais - final ==<br />
<br />
* Interfaces Digitais síncronas - RS232, V35, V36;<br />
<br />
; Links legais para vários pinouts de interfaces seriais da CISCO:<br />
* [https://www.cisco.com/c/en/us/support/docs/routers/10000-series-routers/46803-cabv35mt-fc.html cabos lógicos da CISCO] <br />
* [http://pinouts.ru/SerialPortsCables/ outros padrões elétricos]<br />
<br />
<br />
<br />
;A Interface Digital RS232<br />
<br />
Abaixo uma tabela resumo sobre os principais circuitos contidos em variados tipos de Interface Digital. Observe que a coluna "origem" indica em que tipo de equipamento de um circuito (ou modelo) básico de comunicação de dados (CBCD) se encontra a fonte do sinal correspondente.<br />
<br />
[[imagem: sinais_ID.png|thumb|400px|center]]<br />
<br />
<br> <br />
<br />
E na tabela abaixo o pinout usual das interfaces RS232C (coluna com conector padrão DB9) e RS232 (coluna com conector padrão DB25)<br />
<br />
[[imagem: sinais_ID_RS232.png|thumb|400px|center]]<br />
<br />
<br />
;Contribuição dos alunos da turma de 2016-2: TABELA COMPARATIVA de algumas interfaces digitais, revisado pelo professor:<br />
<br />
{| border="1" cellpadding="5" cellspacing="0" style="background: #ffffe0;" <br />
!style="background: #efefef;"|Alunos/Tema<br />
!style="background: #efefef;"|Características<br />
!style="background: #efefef;"|Pinout<br />
!style="background: #efefef;"|Ilustração<br />
|-<br />
|rowspan=3 style="border-bottom: 3px solid gray; vertical-align: top;"| Kauly e Angelo <br> '''RS232'''<br />
||'''Elétricas:''' <br />
* Tipos de sinal: GND ou SG (Terra), TD ou TX (Transmissão de dados), RD ou RX (Recepção de dados), DTR (Terminal de dados pronto), DSR (Conjunto de dados pronto), RTS (Pronto para enviar(computador)), CTS (Envie os dados (modem)), DCD, (Portadora detectada), RI (Indicador de telefone tocando) e FG (Frame Ground).<br />
* Sincronismo: O modo mais comum de transmissão de sinais e o assíncrono (em que não há necessidade do transmissor estar sincronizado com o receptor, pois ele é informado quando cada “pacote de dados” começa e termina) dispondo de bits de start e stop.<br />
* Tensões típicas: <br />
-3V a -15V como Marca = 1 = OFF<br />
+3V a +15V como Espaço = 0 = ON (Pronto)<br />
* Impedâncias de entrada e saída: <br />
3 a 7 kΩ<br />
* Faixas de bps:<br />
10, 300, 600, 1200, 4800, 9600, 19200, 38400 bits/s<br />
* Código digital:<br />
<br />
|rowspan=3 style="border-bottom: 3px solid gray; vertical-align: top;"| [[imagem: TabelaRS232.PNG|thumb|100x150px]]<br />
|rowspan=3 style="border-bottom: 3px solid gray; vertical-align: top;"| [[Arquivo:Db9.jpg|100x150px|thumb|left|Conector DB9]] [[Arquivo:Db25.jpg|100x150px|thumb|left|Conector DB25]]<br />
|-Coloque a<br />
||'''Mecânicas:''' Contem 25 pinos, e existem diversos padrões de utilização deles, alguns utilizam apenas 3 dos pinos, mas hoje em dia é utilizado os 25 pinos na grande maioria dos casos. <br />
|-<br />
||'''Funcionais:''' Ainda é muito utilizado para equipar DCE's, comunicação de periféricos com PC's, como impressoras matriciais, e em equipamentos de automação industrial.<br />
|-<br />
|rowspan=3 style="border-bottom: 3px solid gray; vertical-align: top;"| Alfredo e Giovana <br> '''V.35'''<br />
||'''Elétricas:''' <br />
*O conector V.35, utiliza sinais balanceados e não balanceados. O tipo de transmissão de dados é síncrono. A impedância de entrada é de 80 a 120 Ω. Tensões típicas de 0,55V +/- 20% com 100Ω de carga. A faixa de velocidade é de 56 Kbps a 2Mbps (podendo chegar a 10Mpbs, dependendo dos equipamentos que estão envolvidos no enlace). <br />
|rowspan=3 style="border-bottom: 3px solid gray; vertical-align: top;"| [[File:V.35.png|V.35|100x150px]] [[File:Tabela Pinos.png|thumb|Tabela descritiva dos pinos da interface Digital V.35|100x150px]]<br />
|rowspan=3 style="border-bottom: 3px solid gray; vertical-align: top;"|[[File:Conectores V.35.png|Conectores V.35|100x150px]][[File:Tabela comparativa.png|Tabela comparativa|100x150px]] <br />
|-Coloque a<br />
||'''Mecânicas:''' <br />
*Capacidade do contato 7A; Resistência de Contato máximo: 10mΩ; Resistência de Isolação: 1000MΩ min @ 500VCC; Rigidez dielétrica:1200 VAC (1 minuto); Temperatura de operação: -55º a 105º C; ;Material do isolador: PBT UL94V-0; Material de contato: Macho = latão, Femea = Bronze Fósforo; Acabamento terminal: Flash ouro; Fios aplicáveis: AWG: 22-28; Capa: Capa metálica totalmente blindada em EMI/RFI; Material da capa: Liga de alumínio com parafusos de aço niquelado. <br />
*A conexão mecânica da V.35 é realizada através de um conector retangular de 34 pinos do tipo fêmea. As dimensões físicas deste conector obedecem o padrão ISO-2593. Opcionalmente pode ser utilizado a conexão mecânica com conectores DB25 com pinagem padrão ISO2110 ou TELEBRÁS (225-540-736). <br />
|-<br />
||'''Funcionais:''' <br />
*Aplicações em equipamentos DCE (modem) e DTE(computador).<br />
|-<br />
|rowspan=3 style="border-bottom: 3px solid gray; vertical-align: top;"| Luísa, Natália, Jessica <br> '''V.36'''<br />
||'''Elétricas:''' A interface V36 possui sua aplicação semelhante à interface V35, porém para cenários onde pode haver ruídos ou interferências em seu percurso. As características elétricas da interface V36 se resumem em:<br />
* tipo de sinal: Utiliza todos os grupos incluindo o de controle com sinais diferenciais, usa recomendação V.11 para sinais de dados e relógios, e utiliza a recomendação V.10 e V.11 para sinais de controle.<br />
* sincronismo: aplicação síncrona.<br />
* código digital.<br />
* tensões típicas: Tensão de modo comum: +7 a -7 V.<br />
* impedância de entrada: 120 - 126 ohms. (Porém informa que deve ser menos que 100 ohms, os valores mais altos servem para evitar offset de acordo com o autor).<br />
* impedância de saída: o autor menciona uma impedância de terminação, e sugere que deve ser inferior a 100 ohms. Outro dado que o autor menciona é uma impedância de 33 ohms na saída em série com o fio para diminuir os problemas com offset.<br />
* faixas de bps: de 48 Kbps a 72 Kbps (típico) e pode chegar até 2 Mbps.<br />
<br />
(Fonte: TELECOMMUNICATION STANDARDIZATION SECTOR OF ITU: Recommendation V.36, Recommendation V.11).<br />
<br />
|rowspan=3 style="border-bottom: 3px solid gray; vertical-align: top;"|[[imagem: pinout.jpg|100x150px]][[imagem: cablesa2.gif|100x150px]]<br />
|rowspan=3 style="border-bottom: 3px solid gray; vertical-align: top;"|[[imagem: db37.jpg|100x150px]]<br />
|-Coloque a<br />
||'''Mecânicas:''' O conector padrão é o DB37 (ISO:IS4902) que possui 37 pinos. <br />
|-<br />
||'''Funcionais:'''<br />
* usado na comunicação serial em ambientes ruidosos.<br />
* assim como o V.35, é aplicado em equipamentos DTE e DCE. <br />
|-<br />
|rowspan=3 style="border-bottom: 3px solid gray; vertical-align: top;"| Pedro e Vitor <br> '''RS485'''<br />
||'''Elétricas:''' <br />
*Modo de operação: Diferencial;<br />
*Número de TX e RX: 32 TX e 32 RX;<br />
*Comprimento máximo: 1200 metros (taxa de transmissão de 100Kbps);<br />
*Taxa máxima de comunicação: 10Mbps (distância de 12 metros);<br />
*Tensão máxima em modo comum: 12 à -7V;<br />
*Tensão mínima de transmissão (carga): ± 1,5 V;<br />
*Tensão mínima de transmissão (sem carga): ± 6 V;<br />
*Limite da corrente mínima da saída em curto circuito (mA): 150 para terra e 250 para -7 até 12 V;<br />
*Impedância mínima de carga: 60Ω;<br />
*Impedância de entrada do RX: 12KΩ;<br />
*Sensibilidade do RX: ± 200 mV.<br />
(Fonte: http://olaria.ucpel.tche.br/autubi/lib/exe/fetch.php?media=padrao_rs485.pdf)<br />
|rowspan=3 style="border-bottom: 3px solid gray; vertical-align: top;"| [[Arquivo:VITOR PEDRO Pinout RS485.PNG|Pinout RS485|100x150px]]<br />
|rowspan=3 style="border-bottom: 3px solid gray; vertical-align: top;"| [[Arquivo:VITOR PEDRO CABO RS485.jpg|100x150px]] <br /> [[Arquivo:VITOR PEDRO DB9.jpg|100x150px]]<br />
<br />
|-Coloque a<br />
||'''Mecânicas:''' A RS485 não possui um conector e pinout padrão. Podem ser utilizados os conectores do tipo DB, terminal parafuso ou outros tipos de conectores. <br />
|-<br />
||'''Funcionais:''' Utilizado para sistemas de automação, redes de computadores, entre outros.<br />
|-<br />
|rowspan=4 style="border-bottom: 3px solid gray; vertical-align: top;"| Schaiana <br> '''G.703/G.704'''<br />
||'''Elétricas:''' <br />
*Modo de operação: Diferencial;<br />
*Tensão de operação: 1,5 V (para cabo coaxial) ou 1,9 V (para cabo por par trançado);<br />
*Taxa máxima de comunicação: 2,048Mbps para o G.703 e até 2,048 Mbps para o G.704 (com 32 frames de 64Kbps, sendo o primeiro para sincronização, ou menos frames, sendo esses múltiplos de 64Kbps);<br />
*A impedância de entrada é de 120 Ω utilizando o cabo por par trançado ou 75 Ω utilizando cabo coaxial.<br />
<br />
<br />
|rowspan=4 style="border-bottom: 3px solid gray; vertical-align: top;"| [[Arquivo:Schaiana_pinout_g703704.png|Pinout RS485|100x150px]]<br />
|rowspan=4 style="border-bottom: 3px solid gray; vertical-align: top;"| [[Arquivo:Schaiana_rj-48c.jpg|100x150px]] <br /> [[Arquivo:Schaiana_bnc.jpg|100x150px]]<br />
<br />
|-Coloque a<br />
||'''Mecânicas:''' Existem dois tipos de conexão:<br />
*Dois cabos coaxiais com conectores BNC;<br />
*Cabo por par trançado com conector RJ-48C. <br />
|-<br />
||'''Funcionais:''' é aplicada em equipamentos DTE e DCE.<br />
|-<br />
||'''Fontes:'''<BR>http://www.farsite.com/cable_standards/G.703_E1-T1_if_popup.shtml, Acesso em 02/03/2017 às 21h00;<BR>https://www.black-box.de/en-de/page/24571/Resources/Technical-Resources/Black-Box-Explains/wan/introduction-to-g703, Acesso em 02/03/2017 às 21h00.<br />
|}<br />
<br />
<!--<br />
<br />
=======NÃO ALTERAR DAQUI EM DIANTE !!!============<br />
<br />
{| border="1" cellpadding="5" cellspacing="0" style="background: #ffffe0;" <br />
!style="background: #efefef;"|Alunos/Tema<br />
!style="background: #efefef;"|Características<br />
!style="background: #efefef;"|Pinout<br />
!style="background: #efefef;"|Ilustração<br />
|-<br />
|rowspan=3 style="border-bottom: 3px solid gray; vertical-align: top;"| Fulano <br> '''RS232'''<br />
||'''Elétricas:''' Descreva aqui informações básicas que o padrão exige: tipo de sinal, sincronismo, código digital, tensões típicas, impedâncias de entrada e sáída, faixas de bps, etc... <br />
|rowspan=3 style="border-bottom: 3px solid gray; vertical-align: top;"| Coloque aqui fotos da relação sinais versus pinos do conector padrão RS232 e RS232C. Pode ser mais que uma.<br />
|rowspan=3 style="border-bottom: 3px solid gray; vertical-align: top;"| Coloque aqui fotos ilustrativas de cabos típicos com padrões de conexão RS232. Pode ser mais que uma.<br />
|-Coloque a<br />
||'''Mecânicas:''' Coloque aqui informações básicas sobre o conector padrão. <br />
|-<br />
||'''Funcionais:''' Coloque aqui informações básicas sobre grupo de sinais presentes, funções desses sinais e aplicações típicas da interface <br />
|}<br />
<br />
<br />
==================ATÉ AQUI=========================<br />
--><br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 05/09 - Implementação de um Modelo básico de Comunicação de Dados com emulador de DTE (test-set)}}<br />
<br />
==05/09 - Implementação de um Modelo básico de Comunicação de Dados com emulador de DTE (Test-Set) ==<br />
<br />
<br />
* Montagem de um modelo básico de comunicação de dados com modens Broad Band - 64Kbps e 2048Kbps;<br />
<br />
<br />
;Montagem de circuitos ponto à ponto com Modens Broad Band<br />
<br />
Para a montagem de circuitos básicos de comunicação de dados, será utilizada a infraestrutura dos racks Principal e de apoio do laboratório para simular os enlaces de 2 fios como meio básico de transmissão de dados entre os circuitos de Modens. Estes circuitos ponto-à-ponto simulam um SLDD - Serviço Local de Linha Digital - formadas por LPCDs - Linha Privativa de Comunicação de Dados - à 2 fios. Aguarde as instruções do professor para efetivar os circuitos. Para os modens de baixa velocidade, 64Kbps, use o próprio resumo de configuração impresso na placa de circuito impresso do modem (Caso dos UP64 da PARKS). Para os modens de alta velocidade SHDSL, 2048Kbps, os modens da DIGITEL modelo DT2048SHDSL devem ser configurados da seguinte forma: <br />
<br />
* Modens lado A - RACK PRINCIPAL (placas instaladas nos slots do Sub-bastidor): DIP1: todas em OFF; DIP2: 3 à 8 em ON; DIP3: todas em ON; DIP4: todas em ON; DIP 5: todas em OFF - Modo LTU (Modem como Unidade de Terminação de Linha), relógio interno, 2048Kbps, e interface V.35 padrão ISO2110;<br />
* Modens dos RACKs de apoio A ou B: DIP1: todas em OFF; DIP2: 1,4 à 8 em ON; DIP3: todas em ON; DIP4: todas em ON; DIP 5-: todas em OFF - Modo NTU (Modem como Unidade de Terminação de Rede), relógio regenerado, 2048Kbps, e interface V.35 padrão ISO2110;<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 09/09 - <math>\blacklozenge</math> Finalização - Modelo básico de Comunicação de Dados com emulador de DTE (test-set) - Modens Narrow Band}}<br />
<br />
==09/09 - <math>\blacklozenge</math> Finalização - Modelo básico de Comunicação de Dados com emulador de DTE (Test-Set) - Modens Narrow Band ==<br />
<br />
<br />
== Enlaces de Teste com auxílio do Test-Set==<br />
<br />
; Comissionamento dos Circuitos Ponto à Ponto<br />
<br />
Após montados os circuitos será feito o comissionamento dos enlaces através do uso dos enlaces de teste juntamente com os Emuladores de DTE - Test-Sets. Aguarde as explicações dos slides sobre [http://www.sj.ifsc.edu.br/~casagrande/RED/slides/modens.pdf modens e enlaces de teste] e as respectivas orientações do professor.<br />
<br />
<br />
; <math>\blacklozenge</math> Questionário sobre a Rede Construída - '''Entrega INDIVIDUAL, MANUSCRITO até dia 12/09/2019 às 13:30h.'''<br />
<br />
A esta altura vc deve ter muitas noções de que mesmo em um circuito ponto à ponto, uma simples ligação entre dois nós de rede, muitos componentes e variáveis estão envolvidos, principalmente no que se refere a camada física. Voce percebeu que na prática, os links ponto à ponto para serem estabelecidos de fato exigem do aluno um prévio conhecimento de todos os ativos e passivos que precisam ser selecionados e dimensionados de acordo com a especificação de cada link. Na vida real, essa especificação nasce da necessidade que o usuário (cliente) contrata com a operadora. São cabos lógicos, adaptadores, modens, interfaces, passivos de cabeamentos estruturado, configurações de modens, routers e PCs, ferramentas, softwares, protocolos, enfim, tudo muito bem alinhado para que se consiga sucesso na troca perfeita de dados na velocidade requerida pelo usuário, quem contrata uma operadora de telecomunicações para prestar esse serviço. <br />
<br />
Embora pouco popular atualmente, o s circuitos ponto à ponto a rede que estudamos e implementamos no laboratório é um típico exemplo de uma Rede Privada usando links privativos (ou LPCD - Linha Privativa de comunicação de Dados ou Leased Line), limitados às instalações do laboratório. Uma LPCD poderia ser efetivada entre quaisquer pontos do planeta através da interconexão de longa distância dos dois circuitos ponto à ponto das redes de acesso dos dois PoPs (Point Of Presence) envolvidos. Quem permite ou decide qual infraestrutura usar nessas redes de acesso (última milha) é a operadora e não é incomum encontrar neste trecho, dentre as diversas soluções, o uso do par trançado que está sendo o meio de transmissão foco desta parte da disciplina. O par trançado tanto está presente nos cabos lógicos que interligam interfaces digitais dos ativos de rede, quanto no cabeamento estruturado de uma LAN ou como opção de meio de transmissão da última milha de uma WAN ou MAN. <br />
<br />
Na implementação destes circuitos é possível entender como duas redes de computadores, podem se comunicar livremente através de links de uma rede WAN. Vislumbrando esse cenário que simulamos no laboratório, visando consolidar a teoria discutida até aqui, responda objetivamente as seguintes questões:<br />
<br />
# Mesmo usando os cabos lógicos WAN proprietários dos Test-Sets outros componentes precisaram ser envolvidos para efetivar as conexões entre as interfaces digitais (IDs) dos modens com estee emuladores de DTE. Que componentes foram esses e porque foram obrigatórios estarem presentes?<br />
# a) Que tipo padrão elétrico de interface digital foi adotado nas conexões dos Test-Sets? b) poderíamos ter escolhido outros tipo de IDs nessas conexões? porque? (talvez seja interessante você consultar o link do manual dos equipamentos em nosso material de apoio para concluir sobre sua resposta...)<br />
# Consulte os manuais dos modens em nosso material de apoio e responda: a) Poderíamos usar velocidades maiores nos links? justifique! b)Poderíamos usar interfaces digitais diferentes nos links? <br />
# Nós utilizamos um equipamento de teste chamado TEST SET para constatar a efetividade e qualidade dos links implementados. Esse equipamento simula a presença de um equipamento terminal de dados (DTE). O uso de um conector de loop aplicado na ID do modem remoto proporcionou verificar através da conexão e execução de teste do TEST-SET no modem local, de que os links estavam perfeitos. Esses testes fazem parte do que algumas operadoras chamam de '''comissionamento''' do circuito. No entanto nesta parte do comissionamento é possível que o link esteja com taxas de erros na transmissão ou mesmo não se efetive. Nessas situações é necessário identificar qual ou quais componentes do link estão com problemas para que possam ser substituídos permitindo assim retorno à operação normal do circuito. Reveja os explicações dadas sobre [http://www.sj.ifsc.edu.br/~casagrande/RED/slides/modens.pdf enlaces de teste] na parte específica deste assunto e responda: Suponha que o modem remoto (aquele que está no lado oposto do link onde você está executando os testes) está com um problema em seu circuito modulador de modo que erros de bit são enviados ao circuito. Ao conectar um TEST SET no modem local e o conector de loop no modem remoto vc observa tais erros indicados no instrumento. No entanto você desconhece em que ponto do link esses erros estão sendo gerados para providenciar o diagnóstico e reparo do circuito. Com as teclas de apoio de enlaces de teste LDL, LAL e LDR disponíveis nos modens das duas pontas do link, relate um procedimento que você realizaria para concluir que o modem remoto é a raiz do problema e que precisa ser substituído. Considere que vc só possui um TEST-SET junto com vc na ponta do modem local e eventualmente voce poderia contar com alguém na ponta remota sendo orientada por telefone ou aplicativo de mensagens para te auxiliar nos testes.<br />
<br />
==Tecnologia de Modens ==<br />
<br />
* O modelo básico de comunicação de dados versus Linha Privativa e a Linha Discada;<br />
* Arquitetura interna básica de um modem: Analógico e Digital;<br />
* Ver: http://www.itu.int/rec/T-REC-V/en <br />
<br />
<br />
;Uma classificação genérica de aplicações entre modens analógicos e modens banda base (digitais):<br />
<br />
[[imagem: aplicações_modens.png|thumb|600px|center]]<br />
<br />
<br />
; Veja em [https://en.wikipedia.org/wiki/Dial-up_Internet_access#Performance Dial-up Internet access] um exemplo de handshake em linha comutada e o áudio típico de modens "negociando".<br />
<br />
==Sinais e Espectros, as bases para os Modens Analógicos e Digitais==<br />
<br />
* Ver Modems Narrowband em http://en.wikipedia.org/wiki/List_of_device_bit_rates;<br />
* Sinais periódicos e não periódicos e seus espectros;<br />
* O Modem Analógico: Arquitetura interna genérica e Técnicas de modulação.<br />
<br />
<br />
Abaixo uma Arquitetura interna genérica de um modem analógico:<br />
<br />
[[imagem: arquitetura_modem_analogico.png|thumb|600px|center]]<br />
<br />
<br />
;Contribuição da turma de 2016-2:<br />
<br />
; Tabela Resumo sobre os padrões internacionais de modens analógicos (narrowband) que foram ou ainda são amplamente utilizados pelas prestadoras de serviços de telecomunicações em linha privativa e linha discada (comutada): <br><br />
<br />
{| border="1" cellpadding="5" cellspacing="0" <br />
!Autor<br />
!Tecnologia (padrão)<br />
!Descrição<br />
|-<br />
<br />
|Angelo || <br />
'''V.22''' <br><br />
<br />
||<br />
:* Uma das versões pioneiras no desenvolvimento de modens de alta velocidade para linhas discadas.<br><br />
:* Transmite dados de forma síncrona e assíncrona, -duplex.<br><br />
:* Taxas de transferência de 600bps e 1200bps.<br><br />
:* Frequências de 1200Hz para 600bps e 2400Hz para 1200bps. <br><br />
:* Modulação DPSK. <br><br />
:* Tipo de linha LP/LD(fixo). <br><br />
:* Modo e meio de comunicação FDX 2 F. <br />
<br><br />
<br />
|-<br />
<br />
|Kauly || <br />
'''V.23''' <br><br />
<br />
||<br />
:* Modem de baixa velocidade.<br><br />
:* Transmite dados de forma síncrona ou assíncrona, half-duplex.<br><br />
:* Taxas de transferência de 600bps e 1200bps.<br><br />
:* Frequências de 1500Hz para 600bps e 1700Hz para 1200bps. <br><br />
:* Modulação AFSK. <br><br />
:* Possui um canal reverso de 75 bps para o controle de erros, usando freqüência de 390 Hz para representar o bit 1 e 450 Hz para representar o bit 0. <br><br />
:* Uma das aplicações mais comuns do V-23 é o vídeo-texto onde o canal reverso é utilizado para seleção de tela na casa do usuário. <br />
<br><br />
|-<br />
<br />
| Giovana ||<br />
'''V.92''' <br><br />
||<br />
:* Em Junho de 2000, um novo padrão definido pelo ITU, introduziu no mercado, <br />
o V.92, padrão em modens de 56K. <br />
Com isto, o padrão V.90 ganhou três novas funções:<br />
QuickConnect, Moden-on-Hold e PCM Upstream. <br />
Em conjunto com o novo algoritmo de compressão V.44, apresentam um avanço significativo <br />
em conexões analógicas por modem. <br />
<br />
* Em adição aos melhoramentos gerais da tecnologia V90,para <br />
utilizar destas novas funções, tanto o modem do usuário como do ISP (provedor),<br />
precisam ser atualizados para a tecnologia V.92. <br />
<br />
'''Modem on Hold'''<br />
:* Sistema chamado modem em espera (MOH, Modem On Hold). Através desse sistema, o computador avisa quando<br />
alguém está tentando ligar para você enquanto você estiver conectado na Internet, <br />
permitindo que você atenda a ligação. A conexão com o seu provedor de acesso não cai, <br />
ela permanece ativa, porém pausada. Assim que você terminar a sua conversa telefônica, <br />
você poderá continuar navegando normalmente. Para esse serviço funcionar,<br />
é preciso habilitar o serviço de chamada em espera junto à sua companhia telefônica.<br />
<br />
'''Maior velocidade de Upload'''<br />
:* Nos modems 56 Kbps v.90, a taxa de download (transferências no sentido provedor/usuário) máxima é de 56 Kbps,<br />
porém a velocidade máxima de upload (transferências no sentido usuário/provedor) é de 33.600 bps.<br />
Nos modems v.92, a taxa máxima de upload foi aumentada para 48.000 bps, <br />
agilizando o envio de e-mails, upload de arquivos e videoconferência. <br />
<br />
'''Quick Connect'''<br />
:* Conexão rápida (quick connect)<br />
Modens v.90 demoram cerca de 20 segundos para fazer a conexão, <br />
modems v.92, "aprende" as condições da linha telefônica onde ele está instalado na primeira vez que conecta ao provedor.<br />
Da segunda vez em diante, ele não executará novamente suas rotinas de verificação da linha,<br />
pois ele já a "conhece". Assim, o tempo de hand-shaking cai pela metade, <br />
demorando apenas cerca de 10 segundos.<br />
<br />
:* 56 Kbps, são modems assimétricos em velocidades acima de 33,6 Kbps. <br />
Assimétrica significa que a velocidade de upstream (os dados que envia) <br />
é diferente do que a velocidade de downstream (os dados recebidos).<br />
<br />
'''Normas reconhecidas de modulação 56Kbps'''<br />
:* K56Flex por Conexant - (anteriormente Rockwell)<br />
:* V.90 padronizado pela ITU-T (ex-CCITT)<br />
:* V.92 padronizado pela ITU-T (idem)<br />
:* K56Flex por Conexant <Rockwell> K56Flex é praticamente obsoleto<br />
:* X2 pela 3Com - (anteriormente USR: US Robotics) X2 é praticamente obsoleto.<br />
[https://www.patton.com/whitepapers/v92.pdf ''Referência'']<br />
[https://www.itu.int/rec/T-REC-V.92-200107-I!Amd1/en ''Referência'']<br />
[http://www.almcom.net/56kfaqs.html''Referência'']<br />
|-<br />
<br />
|Jessica || <br />
'''V.34''' <br><br />
<br />
||<br />
<br />
:*Este modem é destinado para uso em conexões em geral redes telefónicas comutadas (PSTNs ou POTs) e ponto-a-ponto.<br><br />
<br />
:*Sua principais características são:<br />
- Modo de operação duplex e half-duplex na rede geral de telefonia fixa comutada.<br />
- Separação de canais por técnicas de cancelamento de eco.<br />
- Utiliza modulação QAM (Quadrature Amplitude Modulation) para cada canal com transmissão por linha síncrona. A taxa de símbolo pode ser selecionada (variam de 2400 a 3200 símbolos por segundo).<br />
- Taxas de transmissão variam de 2400 bit/s até 33600 bits/s.<br />
- Possui um canal auxiliar opcional com um conjunto de dados síncronos taxa de 200 bit/s de sinalização<br />
- Envia 9 bits por símbolo.<br />
- Requer uma relação sinal-ruído de 32~34 dB para manter a sua taxa de 28800 bps.<br><br />
<br />
:*A tabela abaixo mostra outros dados:<br><br />
[[Arquivo:v34.png|400px|]]<br />
<br />
[https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-V.34-199802-I!!PDF-E&type=items ''Referência'']<br />
[http://www.sj.ifsc.edu.br/~msobral/RCO2/docs/casagrande/MODULO3/cap9/cap9.pdfF-E&type=items ''Referência2'']<br />
<br />
<br />
|-<br />
<br />
|Pedro Hames || <br />
'''V.32bis''' <br><br />
<br />
||<br />
:*Frequência: opera com 3 sinais de 200Hz de largura de banda e frequências centrais em 600Hz, 1800Hz e 3000Hz com tolerância de ±7Hz;<br><br />
:*Comunicação duplex com um par de fios;<br><br />
:*Taxas de transmissão de 14400bits/p, 12000bits/p, 9600bits/p, 7200bits/p e 4800bits/p;<br><br />
:*Taxa de modulação de 2400 símbolos por segundo;<br><br />
[https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-V.32bis-199102-I!!PDF-E&type=items ''Referência V.32bis'']<br />
|-<br />
<br />
<br />
<br />
|Vitor || <br />
'''V.90''' <br><br />
<br />
||<br />
:*Desenvolvido entre Março de 1998 e Fevereiro de 1999;<br><br />
:*Comunicação duplex;<br><br />
:*Taxas de transmissão de 56k bits/s (Downstream) e 33,6k bits/s (Upstream);<br><br />
;*Utiliza modulação PCM (Pulse-Code Modulation) para Downstream e modulação V.34 para Upstream;<br><br />
:*Taxa de modulação de 8000 símbolos por segundo;<br><br />
;*Um modem V.90 tenta uma conexão V.34 quando o computador remoto não fornece suporte ao protocolo V.90.<br><br />
[https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-V.90-199809-I!!PDF-E&type=items ''Referência''] [https://en.wikipedia.org/wiki/List_of_ITU-T_V-series_recommendations ''Referência'']<br />
|-<br />
<br />
|Natália || '''V.22 BIS'''||<br />
É uma recomendação ITU-T V.22 que se estende com uma taxa mais rápida usando QAM para transportar dados digitais.<br />
<br />
:*Ligação ponto-a-ponto com linhas dedicadas e operação em modo duplex em linha telefônica comutada;<br><br />
:*Separação de canais por divisão de freqüência;<br><br />
:*Inclusão de equalização adaptativa;<br><br />
:*Inclusão de facilidades de teste;<br><br />
:*Compatibilidade com o modem V.22 a 1200 bit/s com detecção automática de taxa de transmissão;<br><br />
:*Modulação QAM para transmissão síncrona com cada canal a 600 bps;<br><br />
:*Interface de conexão V.24;<br><br />
:*Taxas de transmissão: 2400 ou 1200 bit/s <br><br />
[http://penta2.ufrgs.br/Claudio/caracv22.html ''Referência''] [https://en.wikipedia.org/wiki/List_of_ITU-T_V-series_recommendations ''Referência'']<br />
|-<br />
<br />
|Luísa || '''V.32'''||<br />
Este tipo de modem destina-se no uso em ligação com a rede telefônica de comutação geral (GSTN) e em circuitos alugados do tipo telefone ponto-a-ponto.<br />
Características:<br />
:*Modo de funcionamento duplex em GSTN e nos circuitos alugados de dois fios ponto-a-ponto;<br><br />
:*Separação de canais por técnicas de cancelamento de eco;<br><br />
:*Transmissão e recepção síncrona;<br><br />
:*Modulação de amplitude em quadratura para cada canal com transmissão por linha síncrona em 2400 bauds;<br><br />
:*Taxas de transmissão: 9600 bit/s; 4800 bit/s; 2400 bit/s;<br><br />
:*Disposição opcional de um modo assíncrono de operação de acordo com recomendações V.14 ou V.42. <br><br />
[https://www.itu.int/rec/dologin_pub.asp?lang=s&id=T-REC-V.32-199303-I!!PDF-E&type=items ''Referência'']<br />
|-<br />
<br />
<br />
|}<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 12/09 - Modens Broad Band e Instalação e Comissionamento de Circuitos Ponto à Ponto com protocolo HDLC }}<br />
<br />
== 12/09 - Modens Broad Band e Instalação e Comissionamento de Circuitos Ponto à Ponto com protocolo HDLC ==<br />
<br />
=== Modens Banda Base (Broad-Band ou Digitais) ===<br />
<br />
* [http://www.sj.ifsc.edu.br/~casagrande/RED/slides/modens.pdf Slides sobre Modens] para apoiar o entendimento do que foi colocado em aula. <br />
* Ver Modems Broadband em http://en.wikipedia.org/wiki/List_of_device_bit_rates <br><br />
<br />
<br />
Abaixo uma arquitetura básica de um modem digital de baixas taxas de transmissão (<256Kbps).<br />
<br />
[[imagem: arquitetura_modem_digital.png|thumb|600px|center]]<br />
<br />
<br><br />
<br />
;Contribuição da turma de 2016-2:<br />
<br />
<br><br />
;Tabela Resumo sobre os padrões internacionais de modens digitais (broadband) que foram ou ainda são amplamente utilizados pelas prestadoras de serviços de telecomunicações em linha privativa, ou em redes de acesso (last mile):<br><br />
<br />
{| border="1" cellpadding="5" cellspacing="0" <br />
!Autor<br />
!Tecnologia (padrão)<br />
!Descrição <br />
|-<br />
|Angelo || '''ADSL'''|| <br />
:* Se diferencia das outras DSLs pelo fato dos dados serem transmitidos de forma mais rapida para uma direção do que para outra.<br><br />
:* Padrão ITU G.992.1 (G.DMT).<br><br />
:* Suas principais características incluem downstream de até 8 Mb/s (megabits por segundo) e upstream de até 1 Mb/s.<br><br />
:* Existem outras versões de ADSL, em que os valores de Download e Upload são maiores, EX: ADSL2 e ADSL2+.<br><br />
:* Existe uma grande variedade de técnicas de modulação, mas no Brasil a mais usada é a DMT.<br><br />
:* É atualmente o Padrão mais utilizado no Brasil..<br><br />
|-<br />
<br />
<br />
|Kauly || '''G.Lite'''|| <br><br />
:* Também conhecido como ADSL Lite.<br><br />
:* Padrão ITU G.992.2.<br><br />
:* Taxas de download e upload são de até 1,5 Mb/s e 512 Kb/s, respectivamente.<br><br />
:* Teoricamente não é necessário splitters, porém funciona melhor com eles.<br><br />
:* Modulação OFDM.<br><br />
:* Por sua baixa taca de transmissão e problemas técnicos como, interferências, alto índice de erros na transmissão de dados, é pouco utilizado atualmente.<br><br />
<br />
|-<br />
<br />
|Pedro Hames || '''SHDSL'''(''Single-pair high-speed digital subscriber line'')|| <br><br />
:*Frequência: de 100 kHz até 350 kHz;<br><br />
:*Distância máxima de 4322 metros;<br><br />
:*Taxa de transmissão de até 2304kbits/s<br><br />
:*Modulação pode ser 16-TCPAM ou 2-PAM<br><br />
[https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-G.991.2-200502-I!Amd2!PDF-E&type=items''Referência SHDSL''] <br />
|-<br />
|Alfredo || <br />
'''VDSL2''' <br> <br />
<br />
||<br />
<br />
VDSL2(Very-High-Bit-Rate Digital Subscriber Line 2 - padrão ITU-T G.993.2) é um padrao tecnologico de acesso que explora a rede existente de uma operadora(par de fios de cobre), oferencendo uma taxa de downstream de até 250Mbps(cliente ao lado do DSLAN).<br />
Seu objetivo é oferecer estrutura para serviços triple play(voz, video, dados, televisão de alta definição e jogos interativos).<br />
O padrão ITU-T G.993.2 é uma atualização do G.993.1, que permite a transmissão de taxas de dados na forma assimétrica e simétrica(full-duplex) em até 200 Mbit/s em pares métaĺicos, usando uma BW de até 30Mhz.<br />
<br />
Tabela <br />
:*Taxa de dados vs Distancia<br />
<br />
<br />
:*200Mbit/s - cliente próximo do DSLAM("na fonte")<br />
:*100Mbit/s - 500 metros do DSLAM<br />
:*50Mbit/s - 1000 metros do DSLAM<br />
:*acima de 1600 metros(01 milha)não viável; convém usar o ADSL como acesso a rede por ter um menor custo e oferecer uma distância maior.<br />
<br />
[https://pt.wikipedia.org/wiki/VDSL2 " Referencia VDSL2"]<br />
|-<br />
<br />
|-<br />
<br />
|Jessica || <br />
'''VDSL''' <br><br />
<br />
||<br />
VDSL, do termo Very-high-bit-rate Digital Subscriber Line é um dos diversos tipos de conexão DSL existentes. Pertence a recomendação ITU G.993.1.<br />
Abaixo algumas características que melhor descrevem o VDSL:<br />
<br />
:* Sua taxa de transmissão é mais alta que a ADSL.<br />
:* Pode transmitir sinais de TV (podendo competir com os sistemas de TV a cabo).<br />
:* Utiliza fibras ópticas no cabeamento externo vindo do provedor de serviços. A GVT é uma empresa que utiliza VDSL.<br />
:* A tecnologia VDSL utiliza nós ópticos para trazer o sinal à casa do usuário, reduzindo a distância do cabo que conecta a fibra com a residência do usuário e assim, resolvendo o problema de velocidade (permitindo taxas mais altas de transmissão e recepção).<br />
:* O alcance de frequência vai de 0 a 12 MHz.<br />
:* A modulação que o VDSL utiliza é a QAM.<br />
:* Velocidades de upload e download são cerca de 15 Mbps e 55 Mbps, respectivamente.<br />
<br />
[https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-G.993.1-200406-I!!PDF-E&type=items ''Referência'']<br />
<br />
[http://www.clubedohardware.com.br/artigos/como-a-conexao-vdsl-funciona/2894-E&type=items ''Referência2'']<br />
<br />
[http://www.teleco.com.br/pdfs/tutorialvdsl.pdf-E&type=items ''Referência3'']<br />
<br />
[http://www.ieee802.org/3/efm/public/jul01/presentations/oksman_1_0701.pdf-E&type=items ''Referência4'']<br />
<br />
|-<br />
<br />
|Vitor || <br />
'''ADSL2+''' ( <br><br />
<br />
||<br />
:*Taxa de transmissão de 24mbps;<br><br />
:*Frequência: de 26k Hz até 2200 kHz;<br><br />
;*Faixa de frequência de Upstream é a mesma utilizada para o ASDL e ASDL2, o que limita a taxa de transmissão de Upstream em apenas 1 mbps;<br><br />
;*A taxa de 24 mbps é obtida a até 1,5 km e decai para até 4 megabits em distâncias superiores a 3.6 km;<br />
[http://www.hardware.com.br/tutoriais/opcoes-acesso/pagina3.html ''Referência'']<br />
|-<br />
<br />
|Natália || '''HDSL''' ||<br />
A Tecnologia HDSL (High bit rate Digital Subscriber Line) foi a primeira tecnologia DSL a ser desenvolvida, no final da década de 80, como alternativa às linhas T1 (E1 na Europa). Estas linhas, apesar de oferecerem uma velocidade satisfatória T1 (1,544 Mbit/s) e E1 (2 Mbit/s). As linhas de HDSL são simétricas, o download e o upload possuem a mesma velocidade, e aproveita a infraestrutura utilizada pelos telefones comuns. O canal de conexão HDSL usa dois pares trançados para implementar o modo de transmissão full-duplex (TOLEDO; PEREIRA, 2001).<br />
[http://www.teleco.com.br/tutoriais/tutorialropassiva1/pagina_2.asp ''Referência''] <br><br />
<br><br />
Outra vantagem da tecnologia HDSL é que ela permite transmissões full-duplex, ou seja, transmissão nos dois sentidos simultaneamente, enquanto que a tecnologia T1 é half-duplex, ou seja, só permite transmissões em um sentido de cada vez. As linhas HDSL oferecem taxas de transferência de 1,544 Mbps para transmissões half-duplex e 784 kbps em cada sentido para transmissões full-duplex. Esta comparação entre as linhas HDSL e T1 é mostrada na figura abaixo: <br><br />
[[Arquivo:Hdsl.jpg]] <br><br />
[http://www.gta.ufrj.br/grad/03_1/dsl/hdsl.htm ''Referência'']<br />
|-<br />
<br />
|Luísa || '''SDSL''' ||<br />
Linha Digital Simétrica de Assinante (Symmetric Digital Subscriber Line - SDSL) refere-se a tecnologias de transmissão de dados digitais ao longo dos fios de cobre da rede de telefonia onde a largura de banda na direção downstream é idêntica à largura de banda no direção upstream, é uma variante do HDSL. Esta largura de banda simétrica pode ser considerado como sendo o inverso da largura de banda assimétrica oferecido pela tecnologia ADSL, em que a largura de banda de upstream é mais baixa do que a largura de banda de downstream. A taxa de transmissão varia entre 72 Kbps e 2320 Kbps, em uma distância máxima de até 3,4Km. SDSL é geralmente comercializada para clientes empresariais.<br />
[https://pt.wikipedia.org/wiki/Symmetric_digital_subscriber_line ''Referência''][https://en.wikipedia.org/wiki/Symmetric_digital_subscriber_line ''Referência'']<br />
|-<br />
<br />
|}<br />
<br />
<br />
Após comissionados os circuitos da aula anterior, efetivar a instalação de dois circuitos ponto à ponto completos incluindo os DTEs (roteadores), considerando as configurações nos routers NR2G seguindo o procedimento a seguir:<br />
<br />
===Implementação de uma rede privada com três nós de rede e protocolo ponto à ponto HDLC.===<br />
<br />
* Construção da rede no laboratório.<br />
<br />
Implemente uma rede rede física composta por três roteadores da Digitel NR2G, que devem ser interconectados como mostrado abaixo:<br />
<br />
[[imagem:Rede-nr2g.png|600px]]<br />
<br />
A rede contém dois enlaces dedicados ponto-à-ponto (simulando duas SLDDs - Serviço Local de Linha Digital - formadas por LPCDs - Linha Privativa de Comunicação de Dados - à 2 fios) com modems digitais operando a 2048Kbps. Os Modens da DIGITEL modelo DT2048SHDSL devem ser configurados da seguinte forma: (chaves em ON) <br />
* Modens do RACK PRINCIPAL (placas instaladas nos slots do Sub-bastidor): DIP1: todas em OFF; DIP2: 3 à 8 em ON; DIP3: todas em ON; DIP4: todas em ON; DIP 5-: todas em OFF - Modo LTU (Modem como Unidade de Terminação de Linha), relógio interno, 2048Kbps, e interface V.35 padrão ISO2110;<br />
* Modens dos RACKs de apoio A e B: DIP1: todas em OFF; DIP2: 1,4 à 8 em ON; DIP3: todas em ON; DIP4: todas em ON; DIP 5-: todas em OFF - Modo NTU (Modem como Unidade de Terminação de Rede), relógio regenerado, 2048Kbps, e interface V.35 padrão ISO2110;<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 16/09 - Interligação de LANs via Circuitos Ponto à Ponto (LPCD) e protocolo HDLC }}<br />
<br />
== 16/09 - Interligação de LANs via Circuitos Ponto à Ponto (LPCD) e protocolo HDLC ==<br />
<br />
* Instalação de duas LANs independentes através do cabeamento estruturado dos racks de apoio;<br />
* Ampliando a LAN através do cascateamento de portas de switch;<br />
* Criação de LANs independentes no mesmo Switch via racks de apoio;<br />
* Implementação de uma rede privada com três nós de rede via duas LPCDs e protocolo ponto à ponto HDLC;<br />
* Configuração dos routers;<br />
<br />
===Instalação de duas LANs independentes através do cabeamento estruturado dos racks de apoio===<br />
<br />
Instale de dois a quatro PCs em cada switch nos racks de apoio (A e B) conforme o esquema mostrado na orientação do professor mantendo as mesmas configurações da rede IP desses PCs. Isso permite que um computador vai se comunicar com qualquer outro da mesma rede. Ao manobrar o cabeamento seguindo as orientações, somente os PCs conectados ao swicth devem trocar pacotes em uma LAN que fica isolada da rede do IFSC e portanto sem acesso à internet também. Use o comando '''ping''' para testar e se certificar.<br />
<br />
===Ampliando a LAN através do cascateamento de portas de switch===<br />
<br />
Interligue com um cabo de rede entre quaisquer portas de cada switch dos racks de apoio das duas LANs criadas anteriormente. Observe que todos os PCs estão em uma mesma LAN agora. Todos devem se comunicar.<br />
<br />
===Criação de LANs independentes no mesmo Switch via racks de apoio===<br />
<br />
Para isso, use os comandos nos PCs como abaixo com o seguinte endereçamento de rede: Para quem estiver no switch do rack de apoio A use o IP 192.168.10.x para dois PCs e 192.168.20.x para outros dois PCs, onde x tem que ser valores de 2 à 254. Para quem estiver no switch do rack de apoio B use o IP 192.168.30.x para dois PCs e 192.168.40.x para outros dois PCs, onde x tem que ser valores de 2 à 254. Para os PCs, aplique os seguintes comandos:<br />
* sudo ifconfg eth0 x.x.x.x netmask m.m.m.m up - para atribuir outro endereço na placa de rede<br />
* sudo route add default gw x.x.x.x - para atribuir um novo gateway para a placa de rede (use o último endereço válido para host da classe da rede - 254)<br />
* route -n - para ver a tabela atual de roteamento.<br />
<br />
Após este procedimento somente os PCs de mesma rede devem estar trocando pacotes. Use o comando '''ping''' para testar.<br />
<br />
===Implementação de uma rede privada com três nós de rede via duas LPCDs e protocolo ponto à ponto HDLC===<br />
<br />
* Construção da rede no laboratório.<br />
<br />
Usando as LANs criadas anteriormente e os dois links ponto à ponto SHDSL já comissionados, vamos implementar uma rede rede física composta por três roteadores da Digitel NR2G, que devem ser interconectados como mostrado abaixo:<br />
<br />
[[imagem:Rede-modems.png|600px]]<br />
<br />
<br />
; Comissionamento das LPCDs (já realiado na aula anterior)<br />
<br />
A rede contém dois enlaces dedicados ponto-à-ponto (simulando duas SLDDs - Serviço Local de Linha Digital - formadas por LPCDs - Linha Privativa de Comunicação de Dados - à 2 fios) com modems digitais operando a 2048Kbps. Os Modens da DIGITEL modelo DT2048SHDSL já estão configurados da seguinte forma: (chaves em ON) <br />
* Modens do RACK PRINCIPAL (placas instaladas nos slots do Sub-bastidor): DIP1: todas em OFF; DIP2: 3 à 8 em ON; DIP3: todas em ON; DIP4: todas em ON; DIP 5-: todas em OFF - Modo LTU (Modem como Unidade de Terminação de Linha), relógio interno, 2048Kbps, e interface V.35 padrão ISO2110;<br />
* Modens dos RACKs de apoio A e B: DIP1: todas em OFF; DIP2: 1,4 à 8 em ON; DIP3: todas em ON; DIP4: todas em ON; DIP 5-: todas em OFF - Modo NTU (Modem como Unidade de Terminação de Rede), relógio regenerado, 2048Kbps, e interface V.35 padrão ISO2110;<br />
<br />
=== Confirguração dos routers ===<br />
<br />
Todos os roteadores devem ser configurados com protocolo HDLC aplicados sobre suas interfaces serias WAN e rodando o algoritmo de roteamento RIP em sua forma mais básica, visando evitar a configuração demorada e cansativa de rotas estáticas na interligação das LANs dos Switches dos Racks de apoio A e B.<br />
<br />
;Configurando a Rede<br />
<br />
# Acesse a interface de gerência (console) do roteador R1 ou R2. O roteador R1 está no rack de apoio A, o roteador R3 está no rack Principal, e R2 está no rack B. Para acessar a console, faça o seguinte:<br />
## Conecte o cabo serial específico na interface serial RS232 do seu computador. Conecte esse cabo também na interface ''console'' do roteador, que fica no painel traseiro. Como os roteadores e switches estão distantes das bancadas, será necessário usar as tomadas exclusivas que conectam as bancadas aos racks. Se tiver dúvidas, consulte o professor para entender a disposição do cabeamento estruturado;<br />
## Execute o programa ''minicom'', que abre um terminal de texto via porta serial. Ele deve ser configurado para se comunicar pela porta serial ''/dev/ttyS0'', com 57600 bps, 8 bits de dados e 1 stop-bit (isso aparece descrito assim: 57600 8N1) e sem controles de fluxo. <syntaxhighlight lang=bash><br />
sudo minicom -s<br />
</syntaxhighlight><br />
## Se o ''minicom'' estiver correto, você deverá ver a interface [http://tele.sj.ifsc.edu.br/~casagrande/RED/apoio/Manual_NR-2G_3200_e_4200.pdf CLI] do roteador (''Command Line Interface''). Caso contrário, confira se o cabo serial está bem encaixado, e se os parâmetros do ''minicom'' estão certos.<br />
# O login e senha para acessar a configuração dos routers é "nr2g" e "digitel" respectivamente. Ao entrar na CLI avalie a configuração geral dos routers com o comando DUMP ALL;<br />
# Estando os links ativos nas WANs, voce pode acessar qualquer router usando a facilidade do protocolo TELNET. Para tanto, dentro da CLI do router aplique o comando EXEC TELNET [IP da WAN ou LAN]. Voce também podem acessa-los por qualquer computador das redes direita ou esquerda, desde que esses estejam na mesma subrede das interfaces LAN dos routers. Uma vez estando na CLI de um dos routers, voce pode acessar os demais com EXEC TELNET;<br />
# Observe se a configuração dos routers está como o previsto na janela abaixo. Talvez voce precise ajustar a configuração em algum roteador.<br />
# Faça a configuração básica dos PCs e Roteadores NR2G com protocolo HDLC. Esta configuração já permite que a rede se conecte a internet através da porta LAN0 do router PRINCIPAL, desde que as configurações de rotas nos PCs de cada subrede e do professor sejam aplicadas conforme na sequência.<br />
<br />
<br />
; ATENÇÂO: As vezes é possível que o status de algum link fique DOWN mesmo após as configurações corretamente realizadas nos modens e baixadas nos routers. Neste caso certifique-se de retirar o cabo de console do router. Ele pode causar mau funcionamento nas seriais WANs do router (ruídos via GND).<br />
<br />
<br />
#* '''R1:''' <syntaxhighlight lang=text><br />
A> <br />
SET LAN LAN0 IP 192.168.10.254 MASK 255.255.255.0 BROADCAST 192.168.10.255 <br />
SET LAN LAN0 UP <br />
SET LAN LAN1 IP 192.168.20.254 MASK 255.255.255.0 BROADCAST 192.168.20.255 <br />
SET LAN LAN1 UP <br />
SET WAN WAN0 PROTO HDLC IP 10.1.1.2 MASK 255.255.255.252 PEER 10.1.1.1 UP <br />
SET WAN WAN1 PURGE <br />
<br />
SET RIP REDIST-STATIC TRUE REDIST-CONNECTED TRUE REDIST-OSPF FALSE DEFAULTMETRIC 2<br />
SET RIP WAN0 ENABLED TRUE TYPE ACTIVE <br />
SET RIP WAN0 AUTH TYPE NONE <br />
SET RIP UP <br />
<br />
SET ROUTES DEFAULT GW1 10.1.1.1 COST1 0 <br />
SET ROUTES UP <br />
CONFIG SAVE <br />
<br />
</syntaxhighlight><br />
#* '''R2:''' <syntaxhighlight lang=text><br />
B> <br />
SET LAN LAN0 IP 192.168.30.254 MASK 255.255.255.0 BROADCAST 192.168.30.255 <br />
SET LAN LAN0 UP <br />
SET LAN LAN1 IP 192.168.40.254 MASK 255.255.255.0 BROADCAST 192.168.40.255 <br />
SET LAN LAN1 UP <br />
SET WAN WAN0 PROTO HDLC IP 10.1.1.6 MASK 255.255.255.252 PEER 10.1.1.5 UP <br />
SET WAN WAN1 PURGE <br />
<br />
SET RIP REDIST-STATIC TRUE REDIST-CONNECTED TRUE REDIST-OSPF FALSE DEFAULTMETRIC 2<br />
SET RIP WAN0 ENABLED TRUE TYPE ACTIVE <br />
SET RIP WAN0 AUTH TYPE NONE <br />
SET RIP UP <br />
<br />
SET ROUTES DEFAULT GW1 10.1.1.5 COST1 0 <br />
SET ROUTES UP<br />
CONFIG SAVE <br />
<br />
</syntaxhighlight><br />
#* '''R3:''' <syntaxhighlight lang=text><br />
PRINCIPAL> <br />
SET LAN LAN0 PURGE <br />
SET LAN LAN1 PURGE <br />
SET WAN WAN0 PROTO HDLC IP 10.1.1.1 MASK 255.255.255.252 PEER 10.1.1.2 UP<br />
SET WAN WAN1 PROTO HDLC IP 10.1.1.5 MASK 255.255.255.252 PEER 10.1.1.6 UP<br />
<br />
SET RIP REDIST-STATIC TRUE REDIST-CONNECTED TRUE REDIST-OSPF FALSE DEFAULTMETRIC 2<br />
SET RIP WAN0 ENABLED TRUE TYPE ACTIVE <br />
SET RIP WAN0 AUTH TYPE NONE <br />
SET RIP WAN1 ENABLED TRUE TYPE ACTIVE <br />
SET RIP WAN1 AUTH TYPE NONE <br />
SET RIP UP <br />
<br />
SET LAN LAN0 IP 192.168.1.231 MASK 255.255.255.0 BROADCAST 192.168.1.255 UP <br />
SET ROUTES DEFAULT GW1 192.168.1.1 COST1 0 <br />
SET ROUTES UP <br />
CONFIG SAVE <br />
<br />
<br />
</syntaxhighlight><br />
# Para conferir as configurações das interfaces, use o comando ''SHOW'' seguido da interface. Exemplo: <syntaxhighlight lang=text><br />
# SHOW WAN WAN0 ALL<br />
# Para as rotas construídas dinamicamente pelo protocolo RIP:<br />
# SHOW ROUTES ALL<br />
</syntaxhighlight><br />
# Assim que os enlaces forem estabelecidos, o que pode ser também constatado com o comando ''SHOW'' aplicado às interfaces, ''conclua'' a configuração da rede (rotas nos pcs e roteadores). Ela deve ser configurada de forma que um computador possa se comunicar com qualquer outro computador da outra rede, e também acessar a Internet. Para isso, use os comandos nos PCs como:<br />
#* sudo ifconfg eth0 x.x.x.x netmask m.m.m.m up - para atribuir outro endereço na placa de rede<br />
#* sudo route add default gw x.x.x.x - para atribuir um novo gateway para a placa de rede<br />
#* sudo route add -net x.x.x.x netmask m.m.m.m eth0 - para associar uma nova rede a interface eth0<br />
#* route -n - para ver a tabela atual de roteamento<br />
# Observe que optamos pelo uso de um protocolo de roteamento dinâmico (RIP na camada 3). Procure entender melhor como foi feita essa configuração, a partir do que está no [http://tele.sj.ifsc.edu.br/~casagrande/RED/apoio/Manual_NR-2G_3200_e_4200.pdf manual], começando pela página 82.<br />
# Para os PCs das subredes direita e esquerda caso necessite reconfigurar novamente: <syntaxhighlight lang=bash><br />
$ sudo ifconfig eth0 192.168.x.y netmask 255.255.255.0 up - x={10,20,30,40}; y={1,2,3,4}<br />
$ sudo route add default gw 192.168.x.254 - x={10,20,30,40} </syntaxhighlight><br />
# Veja se o status das interfaces e protocolos da WAN e LAN de todos os routers estão em UP. Anote e avalie a configuração de todos os routers e os PCs das duas LANs direita e esquerda. Voce pode usar o comando ''' $telnet <address> ''' a partir de qualquer PC que está ativo na rede e a partir desta seção, dentro de cada router, executar o comando '''EXEC TELNET <ADDRESS>''' para acessar qualquer router da rede, bastando endereçar quaisquer interfaces ativas;<br />
# Verificar e anotar todas as configurações e instalações dos componentes de redes, modens, cabos, adaptadores, manobras dos cabos, etc...<br />
# Verificar e anotar todas as configurações lógicas dos modens, routers e PCs.<br />
# Acessar as redes mutuamente qualquer computador de um subrede deve acessar qualquer outro da outra subrede;<br />
# Acessar a internet em todos os PCs;<br />
# Interprete as configurações dos routers e destaque como está configurada a rede. <br />
<br />
<br />
_________________________________<br />
<br />
<br />
Embora pouco popular atualmente, a rede que estudamos e implementamos no laboratório é um típico exemplo de uma Rede Privada usando links privativos (ou LPCD - Linha Privativa de comunicação de Dados ou Leased Line). Limitados as dimensões do laboratório, uma LPCD poderia ser efetivada entre quaisquer pontos do planeta. Quem permite ou decide qual infraestrutura usar é a operadora e não é incomum encontrar na última milha dentre as diversas soluções, o uso do par trançado que está sendo o meio de transmissão foco desta parte da disciplina. O par trançado tanto está presente nos cabos lógicos que interligam interfaces digitais dos ativos de rede, quanto no cabeamento estruturado de uma LAN ou como opção de meio de transmissão da última milha de uma WAN ou MAN. <br />
<br />
Na implementação desta rede foi possível entender como duas LANs que podem se situar em localidades distantes e com endereçamentos distintos, podem se comunicar livremente através de links de uma rede WAN.<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 19/09 - Uso de Ambientes de Simulação com PACKET TRACER }}<br />
<br />
==19/09 - Uso de Ambientes de Simulação com PACKET TRACER ==<br />
<br />
<br />
* Passos iniciais para uso do Packet Tracer da CISCO.<br />
<br />
<br />
''' Após as instruções básicas do professor no uso do simulador PACKET TRACER, efetive neste ambiente o mesmo cenário físico em anel implementado em nosso laboratório. Salve o arquivo .pkt que é gerado pelo aplicativo para futuro uso. ''' Para apoio na conclusão da tarefa, vocês irão encontrar inúmeros exemplos de vídeos e guias de configuração de uso do Packet Tracer na internet. Outro ponto de partida para fazer a configuração dos equipamentos da simulação é obrigatoriamente adotar a própria configuração utilizada nos routers NR2G do Laboratório. <br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 23/09 - Protocolos Ponto à Ponto e Enquadramento (Framing)}}<br />
<br />
==23/09 - Protocolos Ponto à Ponto e Enquadramento (Framing)==<br />
<br />
<br />
'''Resumo da aula:'''<br />
<br />
* [http://www.sj.ifsc.edu.br/~casagrande/RED/slides/protocolos_pp.pdf Protocolos Ponto à Ponto];<br />
* bit e byte stuffing;<br />
* Explicações e exemplos de enquadramento e delimitação em HDLC e PPP; Identificação de pacote;<br />
* Protocolos orientados à bit e à Byte;<br />
* RFC1662 e exemplos de byte stuffing;<br />
* Diagramas de tempo de protocolos HDLC;<br />
* Protocolos PPP e seus protocolos de apoio.<br />
<br />
'''Bibliografia relacionada:'''<br />
'''ATENÇÃO:'''<br />
* Ler Seção 5.7 do livro "Redes de Computadores" do Kurose 5a ed.'''<br />
* Parte III e capítulos 10 e 11 do livro "Comunicação de Dados e Redes de Computadores, 4a ed.", de Behrouz Forouzan<br />
* Capítulo 3 do livro "Redes de Computadores" de Andrew Tanenbaum.<br />
<br />
'''Fundamentos Teóricos'''<br />
<br />
=== Enlaces lógicos ===<br />
<br />
Equipamentos de rede se comunicam por meio de enlaces (''links''). Um enlace é composto por uma '''parte física''', composta pelo meio de transmissão e o hardware necessário para transmitir e receber um sinal que transporta a informação, e uma '''parte lógica''', responsável por empacotar os dados a serem transmitidos. O diagrama abaixo ilustra um enlace entre dois equipamentos, realçando as formas com que a informação é representada durante a transmissão e recepção. Nesse diagrama, a ''parte lógica'' está representada no bloco ''Enlace'', e a ''parte física'' está no bloco ''Física''; a informação transmitida, representada por ''Dados'', pode ser, por exemplo, um datagrama IP.<br />
<br />
[[imagem:Datalink-phy.png|600px]]<br />
<br />
O enlace lógico tem uma dependência total em relação à parte física. Isso quer dizer que o tipo de tecnologia de transmissão existente na parte física traz requisitos para o projeto da parte lógica.<br />
<br />
Deste ponto em diante, a ''parte lógica'' será chamada simplesmente de '''Camada de Enlace''', e a parte física de '''Camada Física'''.<br />
<br />
Em nosso estudo vamos investigar '''enlaces ponto-a-ponto''', os quais necessitam de protocolos específicos. Para ficar mais claro o que deve fazer um protocolo de enlace ponto-a-ponto, vamos listar os serviços típicos existentes na camada de enlace. <br />
<br />
===== Serviços da camada de enlace =====<br />
<br />
[[Image:Data-link.png]]<br />
<br />
Os serviços identificados na figura acima estão descritos a seguir. A eles foram acrescentados outros dois:<br />
<br />
* '''Encapsulamento (ou ''enquadramento'')''': identificação das PDUs (quadros) de enlace dentro de sequências de bits enviadas e recebidas da camada física<br />
* '''Controle de erros''': garantir que quadros sejam entregues no destino<br />
** '''''Detecção de erros''''': verificação da integridade do conteúdo de quadros (se foram recebidos sem erros de bits)<br />
* '''Controle de fluxo''': ajuste da quantidade de quadros transmitidos, de acordo com a capacidade do meio de transmissão (incluindo o atraso de transmissão) e do receptor<br />
* '''Endereçamento''': necessário quando o enlace for do tipo '''multi-ponto''', em que vários equipamentos compartilham o meio de transmissão (ex: redes locais e redes sem-fio)<br />
* '''Controle de acesso ao meio (MAC)''': também necessário para '''meios compartilhados''', para disciplinar as transmissões dos diversos equipamentos de forma a evitar ou reduzir a chance de haver colisões (transmissões sobrepostas)<br />
* '''Gerenciamento de enlace''': funções para ativar, desativar e manter enlaces<br />
<br />
==== Protocolos de enlace ponto-a-ponto ====<br />
<br />
Dois protocolos de enlace ponto-a-ponto muito utilizados são:<br />
* '''PPP (''Point-to-Point Protocol''):''' proposto no início dos anos 90 pelo IETF (ver [http://www.ietf.org/rfc/rfc1661.txt RFC 1661 e][http://www.ietf.org/rfc/rfc1662.txt RFC 1662] ), e amplamente utilizado desde então. Este protocolo não faz controle de erros nem de fluxo, portanto se quadros sofrerem erros de transmissão serão sumariamente descartados no receptor. Originalmente muito usado em acesso discado, recentemente sua aplicação se concentra em enlaces por linhas dedicadas, enlaces sem-fio 3G, e uma versão modificada para acesso doméstico ADSL (''PPPoE''). Ver mais detalhes na seção 5.7 do livro do Kurose e na seção 11.7 do livro ''Comunicação de Dados e Redes de Computadores'', de Behrouz Forouzan. <br />
* '''HDLC (''High-level Data Link Control''):''' criado nos anos 70, foi largamente utilizado em enlaces ponto-a-ponto, porém atualmente foi substituído pelo PPP na maioria dos cenários em que era usado. Este protocolo faz controle de erros e de fluxo usando um [[Desempenho_ARQ|mecanismo ARQ do tipo Go-Back-N]] (com janela de tamanho 7 ou 127). Ainda se aplica a enlaces ponto-a-ponto em linhas dedicadas, enlaces por satélite e aplicações específicas onde a presença de ruídos no meio de transmissão é relevante ou se deseja confiabilidade na entrega de pacotes na camada 2. Ver mais detalhes na seção 11.6 do livro ''Comunicação de Dados e Redes de Computadores'', de Behrouz Forouzan.<br />
<br />
Ambos protocolos possuem o mesmo formato de quadro. Na verdade, o PPP copiou o formato de quadro do HDLC, apesar de não utilizar os campos ''Address'' e ''Control''. O campo ''Flag'', que tem o valor predefinido <math>7E_H</math>, serve para delimitar quadros, assim o receptor sabe quando inicia e termina cada quadro.<br />
<br />
[[imagem:Ppp-frame.png|400px]]<br />
<br>''Quadro PPP ou HDLC (tamanho de campos dados em bytes)''<br><br />
<br />
Esses protocolos foram criados para uso com comunicação serial síncrona (ver capítulo 4, seção 4.3 do livro ''Comunicação de Dados e Redes de Computadores'', de Behrouz Forouzan). O PPP funciona também com [http://pt.wikipedia.org/wiki/Comunica%C3%A7%C3%A3o_serial_ass%C3%ADncrona comunicação serial assíncrona].<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 26/09 - Detecção e Correção de Erros }}<br />
<br />
==26/09 - Detecção e Correção de Erros ==<br />
<br />
;Protocolo PPP<br />
<br />
;Técnicas de Detecção e Correção de Erros <br />
<br />
* Paridade Simples; <br />
* Paridade Combinada (ou longitudinal);<br />
* Checksum;<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 30/09 - <math>\blacklozenge</math> - Exercícios de revisão avaliação A1}}<br />
<br />
==30/09 - Exercícios de revisão avaliação A1 ==<br />
<br />
<br />
0) <math>\blacklozenge</math> '''Entrega em 03/10 - de forma MANUSCRITA E INDIVIDUAL''' - Utilize a técnica de CRC (Ciclical Redundance Check) para determinar o FCS de um pacote completo de dados representado pelas duas primeiras letras MINÚSCULAS seu nome na codificação ASCII. Como polinômio gerador utilize os bits que representam a última letra MAIÚSCULA de seu nome. Por exemplo: '''jo'''rg'''E''' - pacote de dados: 6AH ('''j''') 6FH ('''o''') --> 0110101001101111 Polinômio Gerador: C5H ('''E''') --> 11000101 = x^7+x^2+1. Para a tarefa apresente:<br />
<br />
a) O desenvolvimento do cálculo dos bits de CRC realizado no processo de transmissão do pacote de dados;<br />
<br />
b) O desenvolvimento do cálculo da verificação do pacote de dados realizado na camada de enlace no receptor considerando que não houve erros na transmissão dos dados. Neste caso o pacote é dado como correto;<br />
<br />
c) O desenvolvimento do cálculo da verificação do pacote de dados realizado na camada de enlace no receptor considerando erros de bit ou bits durante a transmissão dos dados. Neste caso o pacote é dado como incorreto e descartado. Escolha ao seu gosto a posição e quantidade de bits errados e comprove a detecção de erros no pacote na recepção;<br />
<br />
d) Leia todo o Capítulo 10 do Livro do Fourozan e avalie qual a eficiência (capacidades) que o seu polinômio gerador tem para detectar erros de bit e de rajada que eventualmente podem ocorrer durante a propagação do sinal até a recepção. <br />
<br />
<br />
;Exercícios<br />
<br />
<br />
1) Não é exemplo de ''last mile'':<br />
a) Uma linha Privativa de Comunicação de dados (LPCD) com modens VDSL em cada ponta da linha;<br />
b) Uma LPCD urbana formada exclusivamente por dois pares de fios;<br />
c) Um enlace wireless interurbano entre dois pontos de presença (PoP) de um ISP (Internet Service Provider);<br />
d) Um SLDD (Serviço de Linha Dedicada Digital) urbano; <br />
e) todas alternativas.<br />
<br />
2)Um determinado trecho de uma sequencia de bits identificado pela camada física é mostra abaixo. Considerando a sequencia<br />
possui delimitação de frames e os bit-stuffing, a sequencia identificada pela cada de enlace será:<br />
<br />
11101111110001010100001111101111101111101101111101010101101111110001010101110 <br />
<br />
a) 1110111111000101010000111111111111111110111111010101101111110001010101110; <br />
b) 0111110001010100001111101111101111101101111101010101101111110; <br />
c) 0010101000011111011111011111011011111010101011;<br />
d) 001010100001111111111111111101111110101011; <br />
e) nenhuma das alternativas.<br />
<br />
3) Considerando a estrutura de um protocolo PPP, os bytes referentes ao check de frame (FCS - CRC), os quais serão identificados pela camada de enlace a partir do conjunto de bytes recebidos pela camada física mostrado na sequência abaixo, será: <br />
<br />
...FF FF FF 7E FF 03 80 21 7D 5D 7D 5E 5D 29 4E AA 2B 5C 22 55 48 7D 5E 25 7E FF... <br />
<br />
a) 5E 25;<br />
b) 48 7D 5E 25;<br />
c) 55 48 7E 25;<br />
d) 7E 25;<br />
e) nenhuma das anteriores.<br />
<br />
4) O protocolo HDLC:<br />
a) não usa a técnica de reconhecimento por carona como faz o protocolo PPP;<br />
b) Usa sempre o protocolo LCP para guiar os processos de conexão e desconexão;<br />
c) é o tipo ideal para enlaces ruidosos;<br />
d) não realiza controle de fluxo;<br />
e) nenhuma das anteriores.<br />
<br />
5) O CRC (Ciclical Redundance Check) de uma sequência de dados 110001 gerada com polinômio gerador $x^{3}+x+1$:<br />
a) terá 4 bits;<br />
b) será a sequencia 111;<br />
c) não é possível calcular o CRC com uma quantidade tão pequena de bits;<br />
d) será a sequencia 0011;<br />
e) nenhuma das anteriores está correta.<br />
<br />
6) Uma transmissão de dados de 4800 bps necessita ser transmitido através de um modem. Decidiu-se utilizar um modem com<br />
modulação por chaveamento de amplitude e fase com uma constelação de 32 símbolos de modulação para executar essa tarefa. Calcule a taxa em bauds no sinal de saída do modem, sendo que a frequência da portadora é 1920 Hz. Considere um canal sem ruído.<br />
a) 4800 bauds;<br />
b) 2400 bauds;<br />
c) 1200 bauds;<br />
d) Impossível determinar com essa frequência de portadora;<br />
e) nenhuma das anteriores está correta.<br />
<br />
7) O fall-back e fall-forward utilizado em modens analógicos dentro das várias versões normatizadas pelo ITU-T:<br />
a) é uma tarefa fundamental entre esses modens banda base;<br />
b) funciona da mesma forma para os modens digitais;<br />
c) exige o controle de fluxo via hardware ou software entre DTE e DCE;<br />
d) são técnicas aplicadas somente em linha privativa;<br />
e) todas as alternativas anteriores estão corretas.<br />
<br />
8) É exemplo de DCE:<br />
a) um modem com tecnologia VDSL;<br />
b) um conversor de mídia (ou transceiver);<br />
c) um modem analógico;<br />
d) a parte do circuito de interface com o cabeamento de uma placa de rede de uma LAN;<br />
e) todas as alternativas anteriores estão corretas.<br />
<br />
9) Uma implementação de um circuito básico de comunicação de dados que exige uma Interface Digital(ID) com todos os sinais de<br />
controle e sincronismo:<br />
a) a ID tipo V.36 não atende essa implementação;<br />
b) a ID tipo G703/G704 atente essa implementação;<br />
c) se ela prevê o uso de uma ID com V.35 será necessário um cabo lógico entre DTE e DCE pino à pino com pelo menos 13 fios: 2 para os dados, 5 para os de controle e 6 para o sincronismo;<br />
d) se ela prevê o uso de uma ID com RS232 será necessário um cabo lógico entre DTE e DCE com pelo menos 11 fios: 1 para referência (GND); 2 para os dados, 5 para os de controle e 3 para o sincronismo;<br />
e) todas as alternativas anteriores estão corretas.<br />
<br />
10) O meio de transmissão formado por pares metálicos sob ação de ruídos e transportando sinais modulados e/ou codificados:<br />
a) possui uma SNR (Relação Sinal Ruído) maior quanto maior seu comprimento;<br />
b) não seguem a regra da capacidade de Shannon;<br />
c) provoca perdas de sinal principalmente pelo seu valor de capacitância por quilômetro;<br />
d) não é determinante para os limites de banda passante;<br />
e) nenhuma das alternativas está correta.<br />
<br />
11) Um enlace digital local (LAL) aplicado em um modem local:<br />
a) precisa de um conector de loop conectado na interface digital do modem remoto para se obter diagnóstico sobre o modem remoto;<br />
b) não consegue oferecer diagnóstico sobre o estado da interface digital do modem remoto;<br />
c) testa completamente os moduladores de demoduladores dos modens local e remoto de um modem digital;<br />
d) oferece diagnóstico sobre a interface analógica remota desde que seja um modem broadband (ou modem banda base);<br />
e) nenhuma das alternativas está correta.<br />
<br />
12)Um nível DC ainda é encontrado em codificações do tipo:<br />
a) NRZ-L;<br />
b) bifásico Manchester;<br />
c) AMI;<br />
d) HDB3;<br />
e) nenhuma das alternativas está correta.<br />
<br />
13) Avalie cada afirmação abaixo e conclua colocando um número de 1 à 3 no espaço indicado, se ela refere-se a uma característica <br />
ou atributo genérico de um modem: (1) analógico ou narrowband, (2) digital(ou banda base, ou broadband) ou (3) tanto analógico quanto digital.<br />
a.( ) uso com linha discada;<br />
b.( ) uso em LPCD;<br />
c.( ) limite de distância menor quanto maior a taxa de transmissão (bps);<br />
d.( ) possui as características de Retreino, Fall-back e Fall-Forward;<br />
e.( ) realiza controle de fluxo via hardware ou software;<br />
f.( ) possui um espectro de frequências maior do que a banda de telefonia;<br />
g.( ) pode operar com uma taxa de 256Kbps na interface analógica;<br />
h.( ) opera com velocidades da interface digital maiores ou iguais a interface analógica; <br />
i.( ) podem operar na última milha em linha de assinante; <br />
j.( ) dependendo do tipo de tecnologia ou versão, usa técnicas de modulação como QAM;<br />
k.( ) podem ser equipados com a facilidade de enlaces de teste;<br />
l.( ) usam codificações como as do tipo bipolares na interface analógica;<br />
m.( ) podem operar em aplicações síncronas ou assíncronas;<br />
n.( ) podem operar com fonte de sincronismo própria (relógio interno);<br />
o.( ) operações full-duplex.<br />
<br />
<br />
<br />
;GABARITO de 1 à 13: C D D C E E C E D C B A (1 3 2 1 1 2 2 1 3 3 3 2 1 3 3) <br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 03/10 - Avaliação A1 }}<br />
<br />
==03/10 - Avaliação A1 ==<br />
<br />
Avaliação A1<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 07/10 - Correção Avaliação A1 - Redes LAN }}<br />
<br />
== 07/10 - Correção Avaliação A1 - Redes LAN ==<br />
<br />
* Correção avaliação A1<br />
<br />
* [http://tele.sj.ifsc.edu.br/~casagrande/RED/slides/lan.pdf REDES LOCAIS];<br />
<br />
=== Redes LAN - Princípios da LAN Comutada ===<br />
<br />
* Round Trip Time (RTT) para redes locais fundamentadas no protocolo CSMA/CD;<br />
* Os limites físicos de extensão de LANs com CSMA/CD - a regra 5 4 3 2 1. <br />
* Dos HUBs para a ethernet comutada - O SWITCH.<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 10/10 - <math>\blacklozenge</math> - Redes LAN - IEEE802.1D - LANÇAMENTO DO JOURNAL RED19-2}}<br />
<br />
== 08/05 - <math>\blacklozenge</math> - Redes LAN - IEEE802.1D - LANÇAMENTO DO JOURNAL RED19-2 ==<br />
<br />
<br />
=== Interligando redes locais de LANs (norma IEEE802.1D) ===<br />
<br />
Ao final deste conteúdo, voce terá condições de responder as seguintes questões:<br />
<br />
#Como um switch aprende que endereços MAC estão em cada porta ?<br />
#Como um switch encaminha um quadro cujo destinatário é desconhecido ?<br />
#Como um switch propaga quadros em broadcast ?<br />
<br />
<br />
;Princípios da Ethernet Comutada<br />
<br />
* [http://www.sj.ifsc.edu.br/~msobral/RCO2/slides/lan-switch-transparent.swf funcionamento de switches]<br />
<br />
=== Tecnologias de LAN switches ===<br />
<br />
Switches ''store-and-forward'' X ''cut-through''<br />
<br />
Veja a seguir detalhes sobre os dois tipos básicos de tecnologias na arquitetura interna de switches e na sequencia faça uma leitura técnica sobre o que ocorre com o fluxo de pacotes e o tratamento deles entre quaisquer portas de um swtch.<br />
<br />
;funcionamento básico de switches ''store-and-forward'' e ''cut-through'':<br />
<br />
* [switches cut-through]<br />
* [switches store-and-forward]<br />
* [switches simétricos (todas portas com mesma taxa de bits)]<br />
* [switches assimétricos (portas com diferentes taxas de bits)]<br />
<br />
;Leitura técnica de apoio sobre como os switches são construídos<br />
<br />
* [http://www.cisco.com/en/US/prod/collateral/switches/ps9441/ps9670/white_paper_c11-465436.html Texto sobre tecnologias de switches (store-and-forward e cut-through)]<br />
* [https://www.safaribooksonline.com/library/view/ethernet-switches/9781449367299/ch01.html Funcionamento básico de um Switch]<br />
* Leia este [http://tele.sj.ifsc.edu.br/~msobral/RCO2/docs/switch-internals.pdf bom texto] sobre estruturas internas de switches.<br />
<br />
<br />
=== Demonstração das fases do SWITCH com PACKET TRACER ===<br />
<br />
Siga as orientações do professor quem irá construir uma LAN com somente três PCs conectados em um SWITCH e um HUB no Packet Tracer.<br />
<br />
<br />
<math>\blacklozenge</math> '''Relatório da Atividade:''' Entrega EM DUPLA, por email ao professor '''até 14/10/2019'''. De acordo com os resultados e respostas às questões formuladas durante a execução do cenário da demonstração acima de LAN com o Packet Tracer, realize agora uma LAN com pelo menos um switch, um Hub e um router (CISCO1941) e '''relate''' brevemente como você identificou cada uma das operações básicas abaixo de um switch, no cumprimento de sua função em uma LAN: (Você pode usar screenshots das telas das avaliações no ambiente de simulação e resultados dos comandos realizados nos PCs e switches).<br />
<br />
*Learning<br />
*Flooding<br />
*Filtering<br />
*Forwarding<br />
*Aging<br />
<br />
=== <math>\blacklozenge</math> Orientações para a atividade principal da Avaliação A2 ===<br />
<br />
; Avaliação A2 - Submissão de artigo Técnico:<br />
<br />
; Call for Papers for RED19-2 journal.<br />
<br />
;Datas Importantes:<br />
# Abertura das inscrições para submissão: '''10/10/2019'''<br />
# Escolha do assunto e tópico: '''17/10/2019''' (veja nota abaixo!) <br />
# Deadline para Submissões: '''11/11/2019'''<br />
# Notificação de Aceite: '''18/11/2019'''<br />
# Submissão de Versão Final: '''25/11/2019''' (para aqueles artigos que não atingirem avaliação 60)<br />
<br />
; Nota:<br />
<br />
Solicito que me enviem a proposta de título com um breve resumo do artigo destacando o que ele irá abordar. Quanto antes entregar, melhor! <br />
<br />
;Escopo:<br />
<br />
Seguindo a necessidade da disciplina de explorar com mais atenção conteúdos envolvidos com a segunda parte da disciplina de Redes 2, Redes Locais (LAN), pretende-se que o evento RED19-1 proporcione aos estudantes e pesquisadores, que atuam em áreas diretamente relacionadas à Redes de Computadores, como conectividade, equipamentos de rede e gestão de redes a fim de apresentar e discutir trabalhos em nível de tutorial científico (de cunho teórico e/ou envolvendo aplicações específicas) relacionados principalmente aos seguintes tópicos: <br />
<br />
;Tópicos de Interesse<br />
<br />
Aplicações inteligentes em equipamentos de redes locais; camadas física e enlace da Internet das Coisas (IoT) e redes de sensores; Padronização e Interoperabilidade de redes locais; Sistemas embarcados aplicados a equipamentos de redes locais; Equipamentos de redes LAN de alta performance; Tecnologias store-and-forward e cut-through, Power over Ethernet (PoE), Viabilidade, estudos de caso, aplicação e gestão de redes locais; Segurança e políticas de uso de redes locais, Qualidade de serviços, priorização, gestão e projetos de redes locais. <br />
<br />
; Instruções para confecção dos artigos<br />
<br />
Os artigos poderão ser submetidos em português ou inglês com até 4 páginas, incluindo as referências, em arquivo formato .pdf conforme o modelo disponível ([http://www.sj.ifsc.edu.br/~casagrande/RED/sbai17-modelo-latex.zip LateX] ou [http://www.sj.ifsc.edu.br/~casagrande/RED/sbai17-modelo.doc Word]). Faça aqui o download dos templates para a submissão dos artigos: [http://www.sj.ifsc.edu.br/~casagrande/RED/sbai17-modelo-latex.zip LateX] ou [http://www.sj.ifsc.edu.br/~casagrande/RED/sbai17-modelo.doc Word]). Estes modelos referência do '''SBAI 2017 - Simpósio Brasileiro de Automação Inteligente'''.<br />
<br />
<br />
;IMPORTANTE <br />
<br />
#É OBRIGATÓRIO utilizar um dos templates em LateX ou Windows; <br />
#Independente do assunto escolhido dentro dos temas, é OBRIGATÓRIO que ele esteja explorando as camadas 1 e 2 das Redes Locais... LIMITANDO-SE às LANs e eventualmente às MANs; <br />
#Usem referenciais técnicos relacionados com os temas para desenvolver o artigo como por exemplo a revistas técnicas como a RTI, que além de possuir na biblioteca do campus, tem sua versão online: http://www.arandanet.com.br/revista/rti/edicao/2017/maio. Vejam o resumo das edições anteriores... tem muito assunto que cabe nos conteúdos que foram explorados em sala; <br />
<br />
;Submissão de artigos <br />
<br />
Os autores devem submeter eletronicamente seus manuscritos em formato .pdf para o professor (casagrande@ifsc.edu.br). <br />
<br />
;Publicação<br />
<br />
Os autores de artigos aceitos deverão publicar em arquivo pdf ou odt no espaço da WIKI da Disciplina com hyperlink no nome correspondente abaixo do título de cada artigo. <br />
<br />
;Avaliação <br />
<br />
#Os artigos serão distribuídos para os professores (revisores) da área de telecomunicações sem identificação dos autores (blind review). Os revisores já estarão orientados sobre as características do Journal (60% da avaliação A2 prevista no plano de ensino) e irão fazer uma breve avaliação sobre o artigo classificando-os em quatro possibilidades de recomendação para publicação com os seguintes pesos em nota de 20 à 100:<br>(1) artigo não recomendado, peso 20;<br>(2) artigo fracamente recomendado, peso 50;<br>(3) artigo recomendado, peso 70;<br>(4) artigo fortemente recomendado, peso 100.<br />
#Caso um mesmo artigo tenha a avaliação 1 ou 2 de um revisor nas possibilidades de recomendação e outra em 3 ou 4 por outro revisor, um terceiro revisor será delegado para avaliar o artigo, descartando a menor avaliação dos três; <br />
#Artigos que tiverem avaliados como recomendação final 3 ou 4 serão selecionados para serem publicados no Journal; <br />
#Para fechar a nota da avaliação 2 uma terceira nota será atribuída pelo professor de 50 à 100 a qual será somada as outras duas melhores notas finais dos revisores. A média das 3 notas será o valor de A2 (60% dela, conforme o plano de ensino). <br />
<br />
; Exemplos de artigos do Journal RED17-1:<br />
<br />
[http://www.sj.ifsc.edu.br/~casagrande/RED/red171.zip Exemplos do Journal RED17-1] <br />
<br />
<br />
{{Collapse bottom}}</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=RED2-EngTel_(p%C3%A1gina)&diff=162074RED2-EngTel (página)2019-10-07T19:48:25Z<p>127.0.0.1: /* Resultados das Avaliações */</p>
<hr />
<div>'''Professores da Unidade Curricular'''<br />
<br />
{{Professor|2019-2|[[Jorge Henrique B. Casagrande]] }}<br />
{{Professor|2019-1|[[Jorge Henrique B. Casagrande]] [[RED29005 2019-1|(Diário de aulas)]]}}<br />
{{Professor|2018-2|[[Jorge Henrique B. Casagrande]] [[RED29005 2018-2|(Diário de aulas)]]}}<br />
{{Professor|2018-1|[[Jorge Henrique B. Casagrande]] [[RED29005 2018-1|(Diário de aulas)]]}}<br />
{{Professor|2017-2|[[Jorge Henrique B. Casagrande]] [[RED29005 2017-2|(Diário de aulas)]]}}<br />
{{Professor|2017-1|[[Jorge Henrique B. Casagrande]] [[RED29005 2017-1|(Diário de aulas)]]}}<br />
{{Professor|2016-2|[[Jorge Henrique B. Casagrande]] [[RED29005 2016-2|(Diário de aulas)]]}}<br />
{{Professor|2016-1|[[Jorge Henrique B. Casagrande]] [[RED29005 2016-1|(Diário de aulas)]]}}<br />
{{Professor|2015-2|[[Jorge Henrique B. Casagrande]] [[RED29005 2015-2|(Diário de aulas)]]}}<br />
{{Professor|2015-1|[[Jorge Henrique B. Casagrande]] [[RED29005 2015-1|(Diário de aulas)]]}}<br />
{{Professor|2014-2|[[Jorge Henrique B. Casagrande]] [[RED29005 2014-2|(Diário de aulas)]]}}<br />
{{Professor|2014-1|[[Jorge Henrique B. Casagrande]] [[RED29005 2014-1|(Diário de aulas)]]}}<br />
<br />
= [[RED2-EngTel|Carga horária, Ementas, Bibliografia]]=<br />
<br />
= [[RED2-EngTel (Plano de Ensino) | Plano de Ensino]]=<br />
<br />
=Dados Importantes=<br />
''Professor'': [[Jorge Henrique B. Casagrande]]<br />
<br>''Email'': casagrande@ifsc.edu.br<br />
<br>''Atendimento paralelo'': 2as e 5as das 17:35h às 18:30h (Sala de Professores de TELE II ou Laboratório de Redes de Computadores)<br />
<br> ''Link alternativo para Material de Apoio da disciplina'': http://www.sj.ifsc.edu.br/~casagrande/RED<br />
<br />
=Resultados das Avaliações=<br />
<br />
;Critérios<br />
:Os alunos serão avaliados da seguinte forma:<br />
::- 3 Avaliações parciais A1, A2 e A3. Cada avaliação parcial contará com uma '''PROVA ESCRITA''' de 2HA de conteúdos preferencialmente associados as teorias e práticas da disciplina os quais representam 60% da nota; Os outros 40% de cada avaliação parcial é relativa a média das notas atribuídas a aptidão e qualidade das atividades práticas e teóricas correspondentes, atividades extras e avaliação individual.<br><br />
::- Avaliação Individual (AI1, AI2 e AI3) é uma nota atribuída pelo professor que representa o mérito de assiduidade, participação em sala, cumprimento de tarefas adicionais como relatórios e listas de exercícios.<br><br />
::- Todas as notas parciais serão valoradas de 0 à 10 em passos de 1 ponto e convertidas em conceitos conforme abaixo:<br />
::Se '''NOTA FINAL (NF)''' OU '''PROVA ESCRITA'''da avaliação parcial '''< 6''' é OBRIGATÓRIO realizar a recuperação dos conteúdos da respectiva avaliação parcial <br><br />
::Se '''NOTA FINAL''' OU '''PROVA ESCRITA'''da avaliação parcial '''>= 6''' a recuperação de conteúdos é opcional<br><br />
<br />
::- '''Para a aprovação na disciplina''' é necessário atingir no mínimo nota '''6''' na média final ponderada em carga horária de todas as avaliações parciais e 75% de participação em sala de aula;<br><br />
::- As datas de recuperação das avaliações parciais serão decididas em comum acordo com a turma. <br><br />
<br />
<br />
{| border="1" cellpadding="5" cellspacing="0" <br />
!Aluno<br />
!AE1<br />
!AE2<br />
!AE3<br />
!AI1<br />
!Prova1 <br />
!A1<br />
!REC A1<br />
!NF A1<br />
!AE4<br />
|-<br />
|Amanda || 100|| 80||0 ||90 || 74|| || || ||<br />
|-<br />
|Bruno ||100 || 70||100||80 ||49 || || || ||<br />
|-<br />
|Guilherme ||100 ||0 || 70||90 ||31 || || || ||<br />
|-<br />
|Luan ||100 ||60 || 0 || 80|| 46|| || || ||<br />
|-<br />
|Maria || 100|| 90||0 ||90 ||60 || || || ||<br />
|-<br />
|Thiago || || || || || || || || ||<br />
|- <br />
|}<br />
<br />
'''LEGENDA E DETALHES '''<br />
<br />
AE1 = Pesquisa de Campo - 01/08 <br><br />
AE2 = Questionamento sobre a rede construída no laboratório - 09/09 <br><br />
AE3 = Uso da técnica de CRC - 30/09 <br><br />
<br />
=Resultados do Journal RED19-2 (40% da avaliação de A2)=<br />
<br />
{| border="1" cellpadding="5" cellspacing="0" <br />
!Matrícula<br />
!Aluno<br />
!Revisor1<br />
!Revisor2<br />
!Revisor3<br />
!Professor<br />
!NF Artigo<br />
|-<br />
| || <!--aluno--> || || || || ||'''0'''<br />
|-<br />
|}<br />
<br />
=Recados Importantes=<br />
<br />
<br> Toda vez que você encontrar a marcação <math>\blacklozenge</math> ao lado de alguma atividade, significa que essa atividade estará sendo computada na avaliação como AIn de An. O prazo estabelecido para entrega estará destacado ao lado da atividade. Portanto, não perca o prazo limite para entrega. '''Atividades entregues fora do prazo terão seu valor máximo de nota debitado de 10 pontos ao dia;'''<br />
<br />
<br> '''Uso da Wiki:''' Todo o repositório de material de apoio e referências de nossas aulas passam a usar a Wiki de tele;<br />
<br />
<br> '''Whatsapp:''' Para interação fora da sala de aula, acessem nosso grupo no Whatsapp;<br />
<br />
<br> '''SIGAA: ''' Eventualmente alguns materiais, mídias instrucionais, avaliações ou atividades poderão usar o ambiente da turma virtual do SIGAA. O professor fará o devido destaque para isso;<br />
<br />
<br> '''ATENÇÃO:''' Uma avaliação poderá ser recuperada somente se existir justificativa reconhecida pela coordenação. Desse modo, deve-se protocolar a justificativa no prazo de 48 horas, contando da data e horário da avaliação, e aguardar o parecer da coordenação. O não cumprimento desse procedimento implica a impossibilidade de fazer a recuperação.<br />
<br />
=Material de Apoio=<br />
<br />
;Tabela de leitura básica das Bibliografias recomendadas (PARA AVALIAÇÃO FINAL)<br />
<br />
{| border="1" cellpadding="5" cellspacing="0" <br />
!Referência<br />
!Tópicos<br />
!Observações<br />
|-<br />
|Kurose 5ª edição || seções dos capítulos 1.1 à 1.4, 5.1, 5.2, 5.7 e 5.8 || <br />
|-<br />
|Forouzan 4ª edição || capítulos 1 e 3 e as seções 4.1, 4.3, 5.1, 6.1, 7.1, 8.1 à 8.3, 9.2, 9.3, 10.1, 10.4, 10.5, 11.1 à 11.3, 11.6, 11.7 e 18.1 || <br />
|-<br />
|Tanenbaum 4ª edição ||cap 4, 5.4.5 (ou seção 5.6.5 da 5ª ed.)|| <br />
|-<br />
|}<br />
<br />
;Atividades extra sala de aula<br />
:* [http://tele.sj.ifsc.edu.br/~casagrande/RED/lista1_2019_1.pdf LISTA1] de exercícios para a avaliação A1 - parte 1<br />
:* [http://tele.sj.ifsc.edu.br/~casagrande/RED/lista2_2019_1.pdf LISTA2] de exercícios para a avaliação A1 - parte 2<br />
:* [http://tele.sj.ifsc.edu.br/~casagrande/RED/lista3_2015_2.pdf LISTA3] de exercícios para a avaliação A2<br />
:* [http://tele.sj.ifsc.edu.br/~casagrande/RED/lista4_2014_2.pdf LISTA4] de exercícios para a avaliação A3<br />
<br />
<br />
;Slides utilizados durante algumas aulas<br />
<br />
:* [http://www.sj.ifsc.edu.br/~casagrande/RED/slides/InterfacesDigitais.pdf Interfaces Digitais];<br />
:* [http://www.sj.ifsc.edu.br/~casagrande/RED/slides/modens.pdf Modens e enlaces de teste] <br />
:* [http://www.sj.ifsc.edu.br/~casagrande/RED/slides/redes_circuitos_virtuais_FR.pdf Redes Frame Relay];<br />
:* [http://www.sj.ifsc.edu.br/~casagrande/RED/slides/protocolos_pp.pdf Protocolos Ponto à Ponto];<br />
:* [http://tele.sj.ifsc.edu.br/~casagrande/RED/slides/lan.pdf REDES LOCAIS]<br />
:* [http://tele.sj.ifsc.edu.br/~casagrande/RED/slides/vlan.pdf IEEE802.3q VLAN]<br />
:* [http://tele.sj.ifsc.edu.br/~casagrande/RED/slides/stp.pdf IEEE802.3d]<br />
:* [http://tele.sj.ifsc.edu.br/~casagrande/RED/slides/ieee.pdf Arquitetura IEEE802.3]<br />
:* [http://tele.sj.ifsc.edu.br/~casagrande/RED/slides/wlan.pdf Conceitos básicos da arquitetura IEEE802.11]<br />
<br />
;Manuais e outros<br />
<br />
:* [https://www.youtube.com/watch?v=mNkWP61GQVs vídeo sobre a atividade dos técnicos de telecomunicações]<br />
:* [https://www.youtube.com/watch?v=ArKcy2WLRac LiFi]<br />
:* [https://www.youtube.com/watch?v=cZcXLu9qM7A VLC]<br />
:* [https://www.youtube.com/watch?v=SrjZDBsG1v8 PLC]<br />
<br />
* [http://www.sj.ifsc.edu.br/~msobral/RCO2/manuais/Guia_DT2048_SHDSL_T_E_S_VG_210.5088.00-1.pdf Guia Rápido de Configuração Modem DT2048SHDSL;]<br />
* [http://tele.sj.ifsc.edu.br/~casagrande/RED/apoio/Manual_DT2048SHDSL.pdf Manual Modem DT2048SHDSL;] da Digitel;<br />
* [http://tele.sj.ifsc.edu.br/~casagrande/RED/apoio/Manual_NR-2G_3200_e_4200.pdf Manual Modem Router NR2G;] da Digitel;<br />
<!--<br />
* [http://www.cisco.com/warp/cpropub/45/tutorial.htm Tutorial sobre a interface CLI de roteadores Cisco.]<br />
* [http://www.cisco.com/en/US/tech/tk713/tk507/technologies_tech_note09186a008019cfa7.shtml#ppp01 Resolução de problemas com PPP em roteadores Cisco]<br />
* [http://www.cisco.com/en/US/products/hw/routers/ps221/products_password_recovery09186a0080094773.shtml Recuperação de senha em roteadores Cisco 1700 e 1800]<br />
<br />
* [http://www.sj.ifsc.edu.br/~casagrande/RED/apoio/Globalink3420guia.pdf guia rápido de configuração Globalink UP3420;] <br />
* [http://www.sj.ifsc.edu.br/~casagrande/RED/apoio/Globalink3420.pdf Manual de configuração Gloalink3420;] <br />
* [http://www.sj.ifsc.edu.br/~casagrande/RED/apoio/DT34.pdf Manual de configuração DT34.] <br />
* [http://www.sj.ifsc.edu.br/~casagrande/RED/apoio/DAS-3324.pdf Manual DSLAM DLINK DAS3324.] <br />
* [http://www.sj.ifsc.edu.br/~casagrande/RED/apoio/DAS-3324guia.pdf Guia rápido DSLAM DLINK DAS3324.]<br />
--><br />
<br />
== Bibliografia Básica ==<br />
<br />
* ''Redes de Computadores e a Internet, 5a edição'', de James Kurose.<br />
* ''Redes de Computadores, 4a edição'', de Andrew Tanenbaum.<br />
* ''Comunicação de Dados e Redes de Computadores, 4a edição'', de Behrouz Forouzan.<br />
<br />
* [http://www.sj.ifsc.edu.br/~msobral/RCO2/docs.html Links para outros materiais, normas, artigos, e apostilas do prof. Jorge Casagrande]<br />
* [https://books.google.com.br/books?id=FIaDr9ZtwXgC&dq=forouzan&hl=pt-BR&source=gbs_book_other_versions Comunicação de dados e Redes de Computadores, de Berhouz Forouzan (alguns capítulos no Google Books)]<br />
<br />
Para pesquisar o acervo das bibliotecas do IFSC:<br />
* [http://biblioteca.ifsc.edu.br/sophia/ Acesso ao acervo da Biblioteca do IFSC]<br />
<br />
== Softwares e Links úteis ==<br />
<br />
* [[Netkit]]: possibilita criar experimentos com redes compostas por máquinas virtuais Linux<br />
* [http://tele.sj.ifsc.edu.br/~casagrande/IER/ipkit.html IPKIT]: um simulador de encaminhamento IP em java (roda direto no navegador)<br />
* [https://www.sejda.com/pdf-editor editor de PDF]:<br />
* [https://www.postscapes.com/internet-of-things-protocols/ Padrões diversos de protocolos para IoT]<br />
<br />
=Diário de aulas RED29005 - 2019-2 - Prof. Jorge H. B. Casagrande=<br />
<br />
<br />
{{Collapse top |29/07 - Os Meios de transmissão e suas limitações}}<br />
<br />
==29/07 - Os Meios de transmissão e suas limitações ==<br />
<br />
* Apresentação da disciplina e plano de ensino;<br />
* Remontando a história da necessidade de comunicação à distância;<br />
* Os principais meios de transmissão.<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 01/08 - <math>\blacklozenge</math> Redes de Acesso}}<br />
<br />
==01/08 - <math>\blacklozenge</math> Redes de Acesso ==<br />
<br />
* Os meios metálicos como meios de transmissão e suas limitações;<br />
* O modelo elétrico de pares metálicos;<br />
* A last mile e a relação com o perfil de serviços de telecom: Players, espelhos, ISPs<br />
<br />
* <math>\blacklozenge</math> '''Tarefa pra casa''': [[media:PesquisaCampo2019_2.pdf |Pesquisa de Campo - Tecnologias de Acesso e de transporte]]<br />
<br />
;Apresentações do semestre:<br />
<br />
[[media:PesquisaCampo2019_2_1.pdf |Pesquisa de Campo - NET Aluno]] <br><br />
[[media:PesquisaCampo2019_2_2.pdf |Pesquisa de Campo - OI Aluno]] <br><br />
[[media:PesquisaCampo2019_2_3.pdf |Pesquisa de Campo - OI Aluno]] <br><br />
[[media:PesquisaCampo2019_2_4.pdf |Pesquisa de Campo - NET Aluno]]<br><br />
<br />
ATENÇÃO: '''O conteúdo destas apresentações fazem parte da avaliação escrita A1.'''<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |05/08 à 19/08 - Licença Paternidade}}<br />
<br />
==05/08 à 19/08 - Licença Paternidade==<br />
<br />
* Licença Paternidade<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |22/08 - Modelo Básico de Comunicação de Dados - Apresentações das pesquisas de campo }}<br />
<br />
==22/08 - Modelo Básico de Comunicação de Dados - Apresentações das pesquisas de campo==<br />
<br />
;Apresentações das pesquisas de campo.<br />
<br />
* Introdução sobre o Modelo Básico de Comunicação de Dados.<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 26/08 - Modelo Básico de Comunicação de Dados - Continuação}}<br />
<br />
==26/08 - Modelo Básico de Comunicação de Dados - Continuação ==<br />
<br />
'''ATENÇÃO: Para reforço dos assuntos tratados a partir desse ponto nesta aula, faça uma leitura do capítulo 3 completo e da seção 4.3 do capítulo 4 do Forouzan'''<br />
<br />
* O modelo básico de Comunicação de dados.<br />
* Comunicação serial;<br />
* Comunicação Assíncrona e Interfaces Digitais - UART [http://sj.ifsc.edu.br/~casagrande/RED/comunicação_serial.pdf (veja seções correspondentes desta referência)];<br />
* O modelo básico de comunicação de dados com DCEs: comunicação pino-à-pino;<br />
* O modelo básico de comunicação de dados sem DCEs (modems): comunicação cross-over;<br />
<br />
* A Interface Digital - camada física;<br />
<br />
<br />
;Experimento: Comunicação entre Computadores via porta serial;<br />
<br />
* uso de emuladores de terminal burro (ou dummy): Minicom do Linux.<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 29/08 - Interfaces Digitais}}<br />
<br />
==29/08 - Interfaces Digitais ==<br />
<br />
* Circuitos diferenciais e não diferenciais;<br />
* A Interface Digital RS232;<br />
* Exemplo de circuito de Interface Digital (ID) duplex usando comunicação com Interface Digital RS232C.<br />
* [http://www.sj.ifsc.edu.br/~casagrande/RED/slides/InterfacesDigitais.pdf Interfaces Digitais] para apoiar o entendimento do que foi colocado em aula. <br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 02/09 - Interfaces Digitais - final}}<br />
<br />
==02/09 - Interfaces Digitais - final ==<br />
<br />
* Interfaces Digitais síncronas - RS232, V35, V36;<br />
<br />
; Links legais para vários pinouts de interfaces seriais da CISCO:<br />
* [https://www.cisco.com/c/en/us/support/docs/routers/10000-series-routers/46803-cabv35mt-fc.html cabos lógicos da CISCO] <br />
* [http://pinouts.ru/SerialPortsCables/ outros padrões elétricos]<br />
<br />
<br />
<br />
;A Interface Digital RS232<br />
<br />
Abaixo uma tabela resumo sobre os principais circuitos contidos em variados tipos de Interface Digital. Observe que a coluna "origem" indica em que tipo de equipamento de um circuito (ou modelo) básico de comunicação de dados (CBCD) se encontra a fonte do sinal correspondente.<br />
<br />
[[imagem: sinais_ID.png|thumb|400px|center]]<br />
<br />
<br> <br />
<br />
E na tabela abaixo o pinout usual das interfaces RS232C (coluna com conector padrão DB9) e RS232 (coluna com conector padrão DB25)<br />
<br />
[[imagem: sinais_ID_RS232.png|thumb|400px|center]]<br />
<br />
<br />
;Contribuição dos alunos da turma de 2016-2: TABELA COMPARATIVA de algumas interfaces digitais, revisado pelo professor:<br />
<br />
{| border="1" cellpadding="5" cellspacing="0" style="background: #ffffe0;" <br />
!style="background: #efefef;"|Alunos/Tema<br />
!style="background: #efefef;"|Características<br />
!style="background: #efefef;"|Pinout<br />
!style="background: #efefef;"|Ilustração<br />
|-<br />
|rowspan=3 style="border-bottom: 3px solid gray; vertical-align: top;"| Kauly e Angelo <br> '''RS232'''<br />
||'''Elétricas:''' <br />
* Tipos de sinal: GND ou SG (Terra), TD ou TX (Transmissão de dados), RD ou RX (Recepção de dados), DTR (Terminal de dados pronto), DSR (Conjunto de dados pronto), RTS (Pronto para enviar(computador)), CTS (Envie os dados (modem)), DCD, (Portadora detectada), RI (Indicador de telefone tocando) e FG (Frame Ground).<br />
* Sincronismo: O modo mais comum de transmissão de sinais e o assíncrono (em que não há necessidade do transmissor estar sincronizado com o receptor, pois ele é informado quando cada “pacote de dados” começa e termina) dispondo de bits de start e stop.<br />
* Tensões típicas: <br />
-3V a -15V como Marca = 1 = OFF<br />
+3V a +15V como Espaço = 0 = ON (Pronto)<br />
* Impedâncias de entrada e saída: <br />
3 a 7 kΩ<br />
* Faixas de bps:<br />
10, 300, 600, 1200, 4800, 9600, 19200, 38400 bits/s<br />
* Código digital:<br />
<br />
|rowspan=3 style="border-bottom: 3px solid gray; vertical-align: top;"| [[imagem: TabelaRS232.PNG|thumb|100x150px]]<br />
|rowspan=3 style="border-bottom: 3px solid gray; vertical-align: top;"| [[Arquivo:Db9.jpg|100x150px|thumb|left|Conector DB9]] [[Arquivo:Db25.jpg|100x150px|thumb|left|Conector DB25]]<br />
|-Coloque a<br />
||'''Mecânicas:''' Contem 25 pinos, e existem diversos padrões de utilização deles, alguns utilizam apenas 3 dos pinos, mas hoje em dia é utilizado os 25 pinos na grande maioria dos casos. <br />
|-<br />
||'''Funcionais:''' Ainda é muito utilizado para equipar DCE's, comunicação de periféricos com PC's, como impressoras matriciais, e em equipamentos de automação industrial.<br />
|-<br />
|rowspan=3 style="border-bottom: 3px solid gray; vertical-align: top;"| Alfredo e Giovana <br> '''V.35'''<br />
||'''Elétricas:''' <br />
*O conector V.35, utiliza sinais balanceados e não balanceados. O tipo de transmissão de dados é síncrono. A impedância de entrada é de 80 a 120 Ω. Tensões típicas de 0,55V +/- 20% com 100Ω de carga. A faixa de velocidade é de 56 Kbps a 2Mbps (podendo chegar a 10Mpbs, dependendo dos equipamentos que estão envolvidos no enlace). <br />
|rowspan=3 style="border-bottom: 3px solid gray; vertical-align: top;"| [[File:V.35.png|V.35|100x150px]] [[File:Tabela Pinos.png|thumb|Tabela descritiva dos pinos da interface Digital V.35|100x150px]]<br />
|rowspan=3 style="border-bottom: 3px solid gray; vertical-align: top;"|[[File:Conectores V.35.png|Conectores V.35|100x150px]][[File:Tabela comparativa.png|Tabela comparativa|100x150px]] <br />
|-Coloque a<br />
||'''Mecânicas:''' <br />
*Capacidade do contato 7A; Resistência de Contato máximo: 10mΩ; Resistência de Isolação: 1000MΩ min @ 500VCC; Rigidez dielétrica:1200 VAC (1 minuto); Temperatura de operação: -55º a 105º C; ;Material do isolador: PBT UL94V-0; Material de contato: Macho = latão, Femea = Bronze Fósforo; Acabamento terminal: Flash ouro; Fios aplicáveis: AWG: 22-28; Capa: Capa metálica totalmente blindada em EMI/RFI; Material da capa: Liga de alumínio com parafusos de aço niquelado. <br />
*A conexão mecânica da V.35 é realizada através de um conector retangular de 34 pinos do tipo fêmea. As dimensões físicas deste conector obedecem o padrão ISO-2593. Opcionalmente pode ser utilizado a conexão mecânica com conectores DB25 com pinagem padrão ISO2110 ou TELEBRÁS (225-540-736). <br />
|-<br />
||'''Funcionais:''' <br />
*Aplicações em equipamentos DCE (modem) e DTE(computador).<br />
|-<br />
|rowspan=3 style="border-bottom: 3px solid gray; vertical-align: top;"| Luísa, Natália, Jessica <br> '''V.36'''<br />
||'''Elétricas:''' A interface V36 possui sua aplicação semelhante à interface V35, porém para cenários onde pode haver ruídos ou interferências em seu percurso. As características elétricas da interface V36 se resumem em:<br />
* tipo de sinal: Utiliza todos os grupos incluindo o de controle com sinais diferenciais, usa recomendação V.11 para sinais de dados e relógios, e utiliza a recomendação V.10 e V.11 para sinais de controle.<br />
* sincronismo: aplicação síncrona.<br />
* código digital.<br />
* tensões típicas: Tensão de modo comum: +7 a -7 V.<br />
* impedância de entrada: 120 - 126 ohms. (Porém informa que deve ser menos que 100 ohms, os valores mais altos servem para evitar offset de acordo com o autor).<br />
* impedância de saída: o autor menciona uma impedância de terminação, e sugere que deve ser inferior a 100 ohms. Outro dado que o autor menciona é uma impedância de 33 ohms na saída em série com o fio para diminuir os problemas com offset.<br />
* faixas de bps: de 48 Kbps a 72 Kbps (típico) e pode chegar até 2 Mbps.<br />
<br />
(Fonte: TELECOMMUNICATION STANDARDIZATION SECTOR OF ITU: Recommendation V.36, Recommendation V.11).<br />
<br />
|rowspan=3 style="border-bottom: 3px solid gray; vertical-align: top;"|[[imagem: pinout.jpg|100x150px]][[imagem: cablesa2.gif|100x150px]]<br />
|rowspan=3 style="border-bottom: 3px solid gray; vertical-align: top;"|[[imagem: db37.jpg|100x150px]]<br />
|-Coloque a<br />
||'''Mecânicas:''' O conector padrão é o DB37 (ISO:IS4902) que possui 37 pinos. <br />
|-<br />
||'''Funcionais:'''<br />
* usado na comunicação serial em ambientes ruidosos.<br />
* assim como o V.35, é aplicado em equipamentos DTE e DCE. <br />
|-<br />
|rowspan=3 style="border-bottom: 3px solid gray; vertical-align: top;"| Pedro e Vitor <br> '''RS485'''<br />
||'''Elétricas:''' <br />
*Modo de operação: Diferencial;<br />
*Número de TX e RX: 32 TX e 32 RX;<br />
*Comprimento máximo: 1200 metros (taxa de transmissão de 100Kbps);<br />
*Taxa máxima de comunicação: 10Mbps (distância de 12 metros);<br />
*Tensão máxima em modo comum: 12 à -7V;<br />
*Tensão mínima de transmissão (carga): ± 1,5 V;<br />
*Tensão mínima de transmissão (sem carga): ± 6 V;<br />
*Limite da corrente mínima da saída em curto circuito (mA): 150 para terra e 250 para -7 até 12 V;<br />
*Impedância mínima de carga: 60Ω;<br />
*Impedância de entrada do RX: 12KΩ;<br />
*Sensibilidade do RX: ± 200 mV.<br />
(Fonte: http://olaria.ucpel.tche.br/autubi/lib/exe/fetch.php?media=padrao_rs485.pdf)<br />
|rowspan=3 style="border-bottom: 3px solid gray; vertical-align: top;"| [[Arquivo:VITOR PEDRO Pinout RS485.PNG|Pinout RS485|100x150px]]<br />
|rowspan=3 style="border-bottom: 3px solid gray; vertical-align: top;"| [[Arquivo:VITOR PEDRO CABO RS485.jpg|100x150px]] <br /> [[Arquivo:VITOR PEDRO DB9.jpg|100x150px]]<br />
<br />
|-Coloque a<br />
||'''Mecânicas:''' A RS485 não possui um conector e pinout padrão. Podem ser utilizados os conectores do tipo DB, terminal parafuso ou outros tipos de conectores. <br />
|-<br />
||'''Funcionais:''' Utilizado para sistemas de automação, redes de computadores, entre outros.<br />
|-<br />
|rowspan=4 style="border-bottom: 3px solid gray; vertical-align: top;"| Schaiana <br> '''G.703/G.704'''<br />
||'''Elétricas:''' <br />
*Modo de operação: Diferencial;<br />
*Tensão de operação: 1,5 V (para cabo coaxial) ou 1,9 V (para cabo por par trançado);<br />
*Taxa máxima de comunicação: 2,048Mbps para o G.703 e até 2,048 Mbps para o G.704 (com 32 frames de 64Kbps, sendo o primeiro para sincronização, ou menos frames, sendo esses múltiplos de 64Kbps);<br />
*A impedância de entrada é de 120 Ω utilizando o cabo por par trançado ou 75 Ω utilizando cabo coaxial.<br />
<br />
<br />
|rowspan=4 style="border-bottom: 3px solid gray; vertical-align: top;"| [[Arquivo:Schaiana_pinout_g703704.png|Pinout RS485|100x150px]]<br />
|rowspan=4 style="border-bottom: 3px solid gray; vertical-align: top;"| [[Arquivo:Schaiana_rj-48c.jpg|100x150px]] <br /> [[Arquivo:Schaiana_bnc.jpg|100x150px]]<br />
<br />
|-Coloque a<br />
||'''Mecânicas:''' Existem dois tipos de conexão:<br />
*Dois cabos coaxiais com conectores BNC;<br />
*Cabo por par trançado com conector RJ-48C. <br />
|-<br />
||'''Funcionais:''' é aplicada em equipamentos DTE e DCE.<br />
|-<br />
||'''Fontes:'''<BR>http://www.farsite.com/cable_standards/G.703_E1-T1_if_popup.shtml, Acesso em 02/03/2017 às 21h00;<BR>https://www.black-box.de/en-de/page/24571/Resources/Technical-Resources/Black-Box-Explains/wan/introduction-to-g703, Acesso em 02/03/2017 às 21h00.<br />
|}<br />
<br />
<!--<br />
<br />
=======NÃO ALTERAR DAQUI EM DIANTE !!!============<br />
<br />
{| border="1" cellpadding="5" cellspacing="0" style="background: #ffffe0;" <br />
!style="background: #efefef;"|Alunos/Tema<br />
!style="background: #efefef;"|Características<br />
!style="background: #efefef;"|Pinout<br />
!style="background: #efefef;"|Ilustração<br />
|-<br />
|rowspan=3 style="border-bottom: 3px solid gray; vertical-align: top;"| Fulano <br> '''RS232'''<br />
||'''Elétricas:''' Descreva aqui informações básicas que o padrão exige: tipo de sinal, sincronismo, código digital, tensões típicas, impedâncias de entrada e sáída, faixas de bps, etc... <br />
|rowspan=3 style="border-bottom: 3px solid gray; vertical-align: top;"| Coloque aqui fotos da relação sinais versus pinos do conector padrão RS232 e RS232C. Pode ser mais que uma.<br />
|rowspan=3 style="border-bottom: 3px solid gray; vertical-align: top;"| Coloque aqui fotos ilustrativas de cabos típicos com padrões de conexão RS232. Pode ser mais que uma.<br />
|-Coloque a<br />
||'''Mecânicas:''' Coloque aqui informações básicas sobre o conector padrão. <br />
|-<br />
||'''Funcionais:''' Coloque aqui informações básicas sobre grupo de sinais presentes, funções desses sinais e aplicações típicas da interface <br />
|}<br />
<br />
<br />
==================ATÉ AQUI=========================<br />
--><br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 05/09 - Implementação de um Modelo básico de Comunicação de Dados com emulador de DTE (test-set)}}<br />
<br />
==05/09 - Implementação de um Modelo básico de Comunicação de Dados com emulador de DTE (Test-Set) ==<br />
<br />
<br />
* Montagem de um modelo básico de comunicação de dados com modens Broad Band - 64Kbps e 2048Kbps;<br />
<br />
<br />
;Montagem de circuitos ponto à ponto com Modens Broad Band<br />
<br />
Para a montagem de circuitos básicos de comunicação de dados, será utilizada a infraestrutura dos racks Principal e de apoio do laboratório para simular os enlaces de 2 fios como meio básico de transmissão de dados entre os circuitos de Modens. Estes circuitos ponto-à-ponto simulam um SLDD - Serviço Local de Linha Digital - formadas por LPCDs - Linha Privativa de Comunicação de Dados - à 2 fios. Aguarde as instruções do professor para efetivar os circuitos. Para os modens de baixa velocidade, 64Kbps, use o próprio resumo de configuração impresso na placa de circuito impresso do modem (Caso dos UP64 da PARKS). Para os modens de alta velocidade SHDSL, 2048Kbps, os modens da DIGITEL modelo DT2048SHDSL devem ser configurados da seguinte forma: <br />
<br />
* Modens lado A - RACK PRINCIPAL (placas instaladas nos slots do Sub-bastidor): DIP1: todas em OFF; DIP2: 3 à 8 em ON; DIP3: todas em ON; DIP4: todas em ON; DIP 5: todas em OFF - Modo LTU (Modem como Unidade de Terminação de Linha), relógio interno, 2048Kbps, e interface V.35 padrão ISO2110;<br />
* Modens dos RACKs de apoio A ou B: DIP1: todas em OFF; DIP2: 1,4 à 8 em ON; DIP3: todas em ON; DIP4: todas em ON; DIP 5-: todas em OFF - Modo NTU (Modem como Unidade de Terminação de Rede), relógio regenerado, 2048Kbps, e interface V.35 padrão ISO2110;<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 09/09 - <math>\blacklozenge</math> Finalização - Modelo básico de Comunicação de Dados com emulador de DTE (test-set) - Modens Narrow Band}}<br />
<br />
==09/09 - <math>\blacklozenge</math> Finalização - Modelo básico de Comunicação de Dados com emulador de DTE (Test-Set) - Modens Narrow Band ==<br />
<br />
<br />
== Enlaces de Teste com auxílio do Test-Set==<br />
<br />
; Comissionamento dos Circuitos Ponto à Ponto<br />
<br />
Após montados os circuitos será feito o comissionamento dos enlaces através do uso dos enlaces de teste juntamente com os Emuladores de DTE - Test-Sets. Aguarde as explicações dos slides sobre [http://www.sj.ifsc.edu.br/~casagrande/RED/slides/modens.pdf modens e enlaces de teste] e as respectivas orientações do professor.<br />
<br />
<br />
; <math>\blacklozenge</math> Questionário sobre a Rede Construída - '''Entrega INDIVIDUAL, MANUSCRITO até dia 12/09/2019 às 13:30h.'''<br />
<br />
A esta altura vc deve ter muitas noções de que mesmo em um circuito ponto à ponto, uma simples ligação entre dois nós de rede, muitos componentes e variáveis estão envolvidos, principalmente no que se refere a camada física. Voce percebeu que na prática, os links ponto à ponto para serem estabelecidos de fato exigem do aluno um prévio conhecimento de todos os ativos e passivos que precisam ser selecionados e dimensionados de acordo com a especificação de cada link. Na vida real, essa especificação nasce da necessidade que o usuário (cliente) contrata com a operadora. São cabos lógicos, adaptadores, modens, interfaces, passivos de cabeamentos estruturado, configurações de modens, routers e PCs, ferramentas, softwares, protocolos, enfim, tudo muito bem alinhado para que se consiga sucesso na troca perfeita de dados na velocidade requerida pelo usuário, quem contrata uma operadora de telecomunicações para prestar esse serviço. <br />
<br />
Embora pouco popular atualmente, o s circuitos ponto à ponto a rede que estudamos e implementamos no laboratório é um típico exemplo de uma Rede Privada usando links privativos (ou LPCD - Linha Privativa de comunicação de Dados ou Leased Line), limitados às instalações do laboratório. Uma LPCD poderia ser efetivada entre quaisquer pontos do planeta através da interconexão de longa distância dos dois circuitos ponto à ponto das redes de acesso dos dois PoPs (Point Of Presence) envolvidos. Quem permite ou decide qual infraestrutura usar nessas redes de acesso (última milha) é a operadora e não é incomum encontrar neste trecho, dentre as diversas soluções, o uso do par trançado que está sendo o meio de transmissão foco desta parte da disciplina. O par trançado tanto está presente nos cabos lógicos que interligam interfaces digitais dos ativos de rede, quanto no cabeamento estruturado de uma LAN ou como opção de meio de transmissão da última milha de uma WAN ou MAN. <br />
<br />
Na implementação destes circuitos é possível entender como duas redes de computadores, podem se comunicar livremente através de links de uma rede WAN. Vislumbrando esse cenário que simulamos no laboratório, visando consolidar a teoria discutida até aqui, responda objetivamente as seguintes questões:<br />
<br />
# Mesmo usando os cabos lógicos WAN proprietários dos Test-Sets outros componentes precisaram ser envolvidos para efetivar as conexões entre as interfaces digitais (IDs) dos modens com estee emuladores de DTE. Que componentes foram esses e porque foram obrigatórios estarem presentes?<br />
# a) Que tipo padrão elétrico de interface digital foi adotado nas conexões dos Test-Sets? b) poderíamos ter escolhido outros tipo de IDs nessas conexões? porque? (talvez seja interessante você consultar o link do manual dos equipamentos em nosso material de apoio para concluir sobre sua resposta...)<br />
# Consulte os manuais dos modens em nosso material de apoio e responda: a) Poderíamos usar velocidades maiores nos links? justifique! b)Poderíamos usar interfaces digitais diferentes nos links? <br />
# Nós utilizamos um equipamento de teste chamado TEST SET para constatar a efetividade e qualidade dos links implementados. Esse equipamento simula a presença de um equipamento terminal de dados (DTE). O uso de um conector de loop aplicado na ID do modem remoto proporcionou verificar através da conexão e execução de teste do TEST-SET no modem local, de que os links estavam perfeitos. Esses testes fazem parte do que algumas operadoras chamam de '''comissionamento''' do circuito. No entanto nesta parte do comissionamento é possível que o link esteja com taxas de erros na transmissão ou mesmo não se efetive. Nessas situações é necessário identificar qual ou quais componentes do link estão com problemas para que possam ser substituídos permitindo assim retorno à operação normal do circuito. Reveja os explicações dadas sobre [http://www.sj.ifsc.edu.br/~casagrande/RED/slides/modens.pdf enlaces de teste] na parte específica deste assunto e responda: Suponha que o modem remoto (aquele que está no lado oposto do link onde você está executando os testes) está com um problema em seu circuito modulador de modo que erros de bit são enviados ao circuito. Ao conectar um TEST SET no modem local e o conector de loop no modem remoto vc observa tais erros indicados no instrumento. No entanto você desconhece em que ponto do link esses erros estão sendo gerados para providenciar o diagnóstico e reparo do circuito. Com as teclas de apoio de enlaces de teste LDL, LAL e LDR disponíveis nos modens das duas pontas do link, relate um procedimento que você realizaria para concluir que o modem remoto é a raiz do problema e que precisa ser substituído. Considere que vc só possui um TEST-SET junto com vc na ponta do modem local e eventualmente voce poderia contar com alguém na ponta remota sendo orientada por telefone ou aplicativo de mensagens para te auxiliar nos testes.<br />
<br />
==Tecnologia de Modens ==<br />
<br />
* O modelo básico de comunicação de dados versus Linha Privativa e a Linha Discada;<br />
* Arquitetura interna básica de um modem: Analógico e Digital;<br />
* Ver: http://www.itu.int/rec/T-REC-V/en <br />
<br />
<br />
;Uma classificação genérica de aplicações entre modens analógicos e modens banda base (digitais):<br />
<br />
[[imagem: aplicações_modens.png|thumb|600px|center]]<br />
<br />
<br />
; Veja em [https://en.wikipedia.org/wiki/Dial-up_Internet_access#Performance Dial-up Internet access] um exemplo de handshake em linha comutada e o áudio típico de modens "negociando".<br />
<br />
==Sinais e Espectros, as bases para os Modens Analógicos e Digitais==<br />
<br />
* Ver Modems Narrowband em http://en.wikipedia.org/wiki/List_of_device_bit_rates;<br />
* Sinais periódicos e não periódicos e seus espectros;<br />
* O Modem Analógico: Arquitetura interna genérica e Técnicas de modulação.<br />
<br />
<br />
Abaixo uma Arquitetura interna genérica de um modem analógico:<br />
<br />
[[imagem: arquitetura_modem_analogico.png|thumb|600px|center]]<br />
<br />
<br />
;Contribuição da turma de 2016-2:<br />
<br />
; Tabela Resumo sobre os padrões internacionais de modens analógicos (narrowband) que foram ou ainda são amplamente utilizados pelas prestadoras de serviços de telecomunicações em linha privativa e linha discada (comutada): <br><br />
<br />
{| border="1" cellpadding="5" cellspacing="0" <br />
!Autor<br />
!Tecnologia (padrão)<br />
!Descrição<br />
|-<br />
<br />
|Angelo || <br />
'''V.22''' <br><br />
<br />
||<br />
:* Uma das versões pioneiras no desenvolvimento de modens de alta velocidade para linhas discadas.<br><br />
:* Transmite dados de forma síncrona e assíncrona, -duplex.<br><br />
:* Taxas de transferência de 600bps e 1200bps.<br><br />
:* Frequências de 1200Hz para 600bps e 2400Hz para 1200bps. <br><br />
:* Modulação DPSK. <br><br />
:* Tipo de linha LP/LD(fixo). <br><br />
:* Modo e meio de comunicação FDX 2 F. <br />
<br><br />
<br />
|-<br />
<br />
|Kauly || <br />
'''V.23''' <br><br />
<br />
||<br />
:* Modem de baixa velocidade.<br><br />
:* Transmite dados de forma síncrona ou assíncrona, half-duplex.<br><br />
:* Taxas de transferência de 600bps e 1200bps.<br><br />
:* Frequências de 1500Hz para 600bps e 1700Hz para 1200bps. <br><br />
:* Modulação AFSK. <br><br />
:* Possui um canal reverso de 75 bps para o controle de erros, usando freqüência de 390 Hz para representar o bit 1 e 450 Hz para representar o bit 0. <br><br />
:* Uma das aplicações mais comuns do V-23 é o vídeo-texto onde o canal reverso é utilizado para seleção de tela na casa do usuário. <br />
<br><br />
|-<br />
<br />
| Giovana ||<br />
'''V.92''' <br><br />
||<br />
:* Em Junho de 2000, um novo padrão definido pelo ITU, introduziu no mercado, <br />
o V.92, padrão em modens de 56K. <br />
Com isto, o padrão V.90 ganhou três novas funções:<br />
QuickConnect, Moden-on-Hold e PCM Upstream. <br />
Em conjunto com o novo algoritmo de compressão V.44, apresentam um avanço significativo <br />
em conexões analógicas por modem. <br />
<br />
* Em adição aos melhoramentos gerais da tecnologia V90,para <br />
utilizar destas novas funções, tanto o modem do usuário como do ISP (provedor),<br />
precisam ser atualizados para a tecnologia V.92. <br />
<br />
'''Modem on Hold'''<br />
:* Sistema chamado modem em espera (MOH, Modem On Hold). Através desse sistema, o computador avisa quando<br />
alguém está tentando ligar para você enquanto você estiver conectado na Internet, <br />
permitindo que você atenda a ligação. A conexão com o seu provedor de acesso não cai, <br />
ela permanece ativa, porém pausada. Assim que você terminar a sua conversa telefônica, <br />
você poderá continuar navegando normalmente. Para esse serviço funcionar,<br />
é preciso habilitar o serviço de chamada em espera junto à sua companhia telefônica.<br />
<br />
'''Maior velocidade de Upload'''<br />
:* Nos modems 56 Kbps v.90, a taxa de download (transferências no sentido provedor/usuário) máxima é de 56 Kbps,<br />
porém a velocidade máxima de upload (transferências no sentido usuário/provedor) é de 33.600 bps.<br />
Nos modems v.92, a taxa máxima de upload foi aumentada para 48.000 bps, <br />
agilizando o envio de e-mails, upload de arquivos e videoconferência. <br />
<br />
'''Quick Connect'''<br />
:* Conexão rápida (quick connect)<br />
Modens v.90 demoram cerca de 20 segundos para fazer a conexão, <br />
modems v.92, "aprende" as condições da linha telefônica onde ele está instalado na primeira vez que conecta ao provedor.<br />
Da segunda vez em diante, ele não executará novamente suas rotinas de verificação da linha,<br />
pois ele já a "conhece". Assim, o tempo de hand-shaking cai pela metade, <br />
demorando apenas cerca de 10 segundos.<br />
<br />
:* 56 Kbps, são modems assimétricos em velocidades acima de 33,6 Kbps. <br />
Assimétrica significa que a velocidade de upstream (os dados que envia) <br />
é diferente do que a velocidade de downstream (os dados recebidos).<br />
<br />
'''Normas reconhecidas de modulação 56Kbps'''<br />
:* K56Flex por Conexant - (anteriormente Rockwell)<br />
:* V.90 padronizado pela ITU-T (ex-CCITT)<br />
:* V.92 padronizado pela ITU-T (idem)<br />
:* K56Flex por Conexant <Rockwell> K56Flex é praticamente obsoleto<br />
:* X2 pela 3Com - (anteriormente USR: US Robotics) X2 é praticamente obsoleto.<br />
[https://www.patton.com/whitepapers/v92.pdf ''Referência'']<br />
[https://www.itu.int/rec/T-REC-V.92-200107-I!Amd1/en ''Referência'']<br />
[http://www.almcom.net/56kfaqs.html''Referência'']<br />
|-<br />
<br />
|Jessica || <br />
'''V.34''' <br><br />
<br />
||<br />
<br />
:*Este modem é destinado para uso em conexões em geral redes telefónicas comutadas (PSTNs ou POTs) e ponto-a-ponto.<br><br />
<br />
:*Sua principais características são:<br />
- Modo de operação duplex e half-duplex na rede geral de telefonia fixa comutada.<br />
- Separação de canais por técnicas de cancelamento de eco.<br />
- Utiliza modulação QAM (Quadrature Amplitude Modulation) para cada canal com transmissão por linha síncrona. A taxa de símbolo pode ser selecionada (variam de 2400 a 3200 símbolos por segundo).<br />
- Taxas de transmissão variam de 2400 bit/s até 33600 bits/s.<br />
- Possui um canal auxiliar opcional com um conjunto de dados síncronos taxa de 200 bit/s de sinalização<br />
- Envia 9 bits por símbolo.<br />
- Requer uma relação sinal-ruído de 32~34 dB para manter a sua taxa de 28800 bps.<br><br />
<br />
:*A tabela abaixo mostra outros dados:<br><br />
[[Arquivo:v34.png|400px|]]<br />
<br />
[https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-V.34-199802-I!!PDF-E&type=items ''Referência'']<br />
[http://www.sj.ifsc.edu.br/~msobral/RCO2/docs/casagrande/MODULO3/cap9/cap9.pdfF-E&type=items ''Referência2'']<br />
<br />
<br />
|-<br />
<br />
|Pedro Hames || <br />
'''V.32bis''' <br><br />
<br />
||<br />
:*Frequência: opera com 3 sinais de 200Hz de largura de banda e frequências centrais em 600Hz, 1800Hz e 3000Hz com tolerância de ±7Hz;<br><br />
:*Comunicação duplex com um par de fios;<br><br />
:*Taxas de transmissão de 14400bits/p, 12000bits/p, 9600bits/p, 7200bits/p e 4800bits/p;<br><br />
:*Taxa de modulação de 2400 símbolos por segundo;<br><br />
[https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-V.32bis-199102-I!!PDF-E&type=items ''Referência V.32bis'']<br />
|-<br />
<br />
<br />
<br />
|Vitor || <br />
'''V.90''' <br><br />
<br />
||<br />
:*Desenvolvido entre Março de 1998 e Fevereiro de 1999;<br><br />
:*Comunicação duplex;<br><br />
:*Taxas de transmissão de 56k bits/s (Downstream) e 33,6k bits/s (Upstream);<br><br />
;*Utiliza modulação PCM (Pulse-Code Modulation) para Downstream e modulação V.34 para Upstream;<br><br />
:*Taxa de modulação de 8000 símbolos por segundo;<br><br />
;*Um modem V.90 tenta uma conexão V.34 quando o computador remoto não fornece suporte ao protocolo V.90.<br><br />
[https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-V.90-199809-I!!PDF-E&type=items ''Referência''] [https://en.wikipedia.org/wiki/List_of_ITU-T_V-series_recommendations ''Referência'']<br />
|-<br />
<br />
|Natália || '''V.22 BIS'''||<br />
É uma recomendação ITU-T V.22 que se estende com uma taxa mais rápida usando QAM para transportar dados digitais.<br />
<br />
:*Ligação ponto-a-ponto com linhas dedicadas e operação em modo duplex em linha telefônica comutada;<br><br />
:*Separação de canais por divisão de freqüência;<br><br />
:*Inclusão de equalização adaptativa;<br><br />
:*Inclusão de facilidades de teste;<br><br />
:*Compatibilidade com o modem V.22 a 1200 bit/s com detecção automática de taxa de transmissão;<br><br />
:*Modulação QAM para transmissão síncrona com cada canal a 600 bps;<br><br />
:*Interface de conexão V.24;<br><br />
:*Taxas de transmissão: 2400 ou 1200 bit/s <br><br />
[http://penta2.ufrgs.br/Claudio/caracv22.html ''Referência''] [https://en.wikipedia.org/wiki/List_of_ITU-T_V-series_recommendations ''Referência'']<br />
|-<br />
<br />
|Luísa || '''V.32'''||<br />
Este tipo de modem destina-se no uso em ligação com a rede telefônica de comutação geral (GSTN) e em circuitos alugados do tipo telefone ponto-a-ponto.<br />
Características:<br />
:*Modo de funcionamento duplex em GSTN e nos circuitos alugados de dois fios ponto-a-ponto;<br><br />
:*Separação de canais por técnicas de cancelamento de eco;<br><br />
:*Transmissão e recepção síncrona;<br><br />
:*Modulação de amplitude em quadratura para cada canal com transmissão por linha síncrona em 2400 bauds;<br><br />
:*Taxas de transmissão: 9600 bit/s; 4800 bit/s; 2400 bit/s;<br><br />
:*Disposição opcional de um modo assíncrono de operação de acordo com recomendações V.14 ou V.42. <br><br />
[https://www.itu.int/rec/dologin_pub.asp?lang=s&id=T-REC-V.32-199303-I!!PDF-E&type=items ''Referência'']<br />
|-<br />
<br />
<br />
|}<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 12/09 - Modens Broad Band e Instalação e Comissionamento de Circuitos Ponto à Ponto com protocolo HDLC }}<br />
<br />
== 12/09 - Modens Broad Band e Instalação e Comissionamento de Circuitos Ponto à Ponto com protocolo HDLC ==<br />
<br />
=== Modens Banda Base (Broad-Band ou Digitais) ===<br />
<br />
* [http://www.sj.ifsc.edu.br/~casagrande/RED/slides/modens.pdf Slides sobre Modens] para apoiar o entendimento do que foi colocado em aula. <br />
* Ver Modems Broadband em http://en.wikipedia.org/wiki/List_of_device_bit_rates <br><br />
<br />
<br />
Abaixo uma arquitetura básica de um modem digital de baixas taxas de transmissão (<256Kbps).<br />
<br />
[[imagem: arquitetura_modem_digital.png|thumb|600px|center]]<br />
<br />
<br><br />
<br />
;Contribuição da turma de 2016-2:<br />
<br />
<br><br />
;Tabela Resumo sobre os padrões internacionais de modens digitais (broadband) que foram ou ainda são amplamente utilizados pelas prestadoras de serviços de telecomunicações em linha privativa, ou em redes de acesso (last mile):<br><br />
<br />
{| border="1" cellpadding="5" cellspacing="0" <br />
!Autor<br />
!Tecnologia (padrão)<br />
!Descrição <br />
|-<br />
|Angelo || '''ADSL'''|| <br />
:* Se diferencia das outras DSLs pelo fato dos dados serem transmitidos de forma mais rapida para uma direção do que para outra.<br><br />
:* Padrão ITU G.992.1 (G.DMT).<br><br />
:* Suas principais características incluem downstream de até 8 Mb/s (megabits por segundo) e upstream de até 1 Mb/s.<br><br />
:* Existem outras versões de ADSL, em que os valores de Download e Upload são maiores, EX: ADSL2 e ADSL2+.<br><br />
:* Existe uma grande variedade de técnicas de modulação, mas no Brasil a mais usada é a DMT.<br><br />
:* É atualmente o Padrão mais utilizado no Brasil..<br><br />
|-<br />
<br />
<br />
|Kauly || '''G.Lite'''|| <br><br />
:* Também conhecido como ADSL Lite.<br><br />
:* Padrão ITU G.992.2.<br><br />
:* Taxas de download e upload são de até 1,5 Mb/s e 512 Kb/s, respectivamente.<br><br />
:* Teoricamente não é necessário splitters, porém funciona melhor com eles.<br><br />
:* Modulação OFDM.<br><br />
:* Por sua baixa taca de transmissão e problemas técnicos como, interferências, alto índice de erros na transmissão de dados, é pouco utilizado atualmente.<br><br />
<br />
|-<br />
<br />
|Pedro Hames || '''SHDSL'''(''Single-pair high-speed digital subscriber line'')|| <br><br />
:*Frequência: de 100 kHz até 350 kHz;<br><br />
:*Distância máxima de 4322 metros;<br><br />
:*Taxa de transmissão de até 2304kbits/s<br><br />
:*Modulação pode ser 16-TCPAM ou 2-PAM<br><br />
[https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-G.991.2-200502-I!Amd2!PDF-E&type=items''Referência SHDSL''] <br />
|-<br />
|Alfredo || <br />
'''VDSL2''' <br> <br />
<br />
||<br />
<br />
VDSL2(Very-High-Bit-Rate Digital Subscriber Line 2 - padrão ITU-T G.993.2) é um padrao tecnologico de acesso que explora a rede existente de uma operadora(par de fios de cobre), oferencendo uma taxa de downstream de até 250Mbps(cliente ao lado do DSLAN).<br />
Seu objetivo é oferecer estrutura para serviços triple play(voz, video, dados, televisão de alta definição e jogos interativos).<br />
O padrão ITU-T G.993.2 é uma atualização do G.993.1, que permite a transmissão de taxas de dados na forma assimétrica e simétrica(full-duplex) em até 200 Mbit/s em pares métaĺicos, usando uma BW de até 30Mhz.<br />
<br />
Tabela <br />
:*Taxa de dados vs Distancia<br />
<br />
<br />
:*200Mbit/s - cliente próximo do DSLAM("na fonte")<br />
:*100Mbit/s - 500 metros do DSLAM<br />
:*50Mbit/s - 1000 metros do DSLAM<br />
:*acima de 1600 metros(01 milha)não viável; convém usar o ADSL como acesso a rede por ter um menor custo e oferecer uma distância maior.<br />
<br />
[https://pt.wikipedia.org/wiki/VDSL2 " Referencia VDSL2"]<br />
|-<br />
<br />
|-<br />
<br />
|Jessica || <br />
'''VDSL''' <br><br />
<br />
||<br />
VDSL, do termo Very-high-bit-rate Digital Subscriber Line é um dos diversos tipos de conexão DSL existentes. Pertence a recomendação ITU G.993.1.<br />
Abaixo algumas características que melhor descrevem o VDSL:<br />
<br />
:* Sua taxa de transmissão é mais alta que a ADSL.<br />
:* Pode transmitir sinais de TV (podendo competir com os sistemas de TV a cabo).<br />
:* Utiliza fibras ópticas no cabeamento externo vindo do provedor de serviços. A GVT é uma empresa que utiliza VDSL.<br />
:* A tecnologia VDSL utiliza nós ópticos para trazer o sinal à casa do usuário, reduzindo a distância do cabo que conecta a fibra com a residência do usuário e assim, resolvendo o problema de velocidade (permitindo taxas mais altas de transmissão e recepção).<br />
:* O alcance de frequência vai de 0 a 12 MHz.<br />
:* A modulação que o VDSL utiliza é a QAM.<br />
:* Velocidades de upload e download são cerca de 15 Mbps e 55 Mbps, respectivamente.<br />
<br />
[https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-G.993.1-200406-I!!PDF-E&type=items ''Referência'']<br />
<br />
[http://www.clubedohardware.com.br/artigos/como-a-conexao-vdsl-funciona/2894-E&type=items ''Referência2'']<br />
<br />
[http://www.teleco.com.br/pdfs/tutorialvdsl.pdf-E&type=items ''Referência3'']<br />
<br />
[http://www.ieee802.org/3/efm/public/jul01/presentations/oksman_1_0701.pdf-E&type=items ''Referência4'']<br />
<br />
|-<br />
<br />
|Vitor || <br />
'''ADSL2+''' ( <br><br />
<br />
||<br />
:*Taxa de transmissão de 24mbps;<br><br />
:*Frequência: de 26k Hz até 2200 kHz;<br><br />
;*Faixa de frequência de Upstream é a mesma utilizada para o ASDL e ASDL2, o que limita a taxa de transmissão de Upstream em apenas 1 mbps;<br><br />
;*A taxa de 24 mbps é obtida a até 1,5 km e decai para até 4 megabits em distâncias superiores a 3.6 km;<br />
[http://www.hardware.com.br/tutoriais/opcoes-acesso/pagina3.html ''Referência'']<br />
|-<br />
<br />
|Natália || '''HDSL''' ||<br />
A Tecnologia HDSL (High bit rate Digital Subscriber Line) foi a primeira tecnologia DSL a ser desenvolvida, no final da década de 80, como alternativa às linhas T1 (E1 na Europa). Estas linhas, apesar de oferecerem uma velocidade satisfatória T1 (1,544 Mbit/s) e E1 (2 Mbit/s). As linhas de HDSL são simétricas, o download e o upload possuem a mesma velocidade, e aproveita a infraestrutura utilizada pelos telefones comuns. O canal de conexão HDSL usa dois pares trançados para implementar o modo de transmissão full-duplex (TOLEDO; PEREIRA, 2001).<br />
[http://www.teleco.com.br/tutoriais/tutorialropassiva1/pagina_2.asp ''Referência''] <br><br />
<br><br />
Outra vantagem da tecnologia HDSL é que ela permite transmissões full-duplex, ou seja, transmissão nos dois sentidos simultaneamente, enquanto que a tecnologia T1 é half-duplex, ou seja, só permite transmissões em um sentido de cada vez. As linhas HDSL oferecem taxas de transferência de 1,544 Mbps para transmissões half-duplex e 784 kbps em cada sentido para transmissões full-duplex. Esta comparação entre as linhas HDSL e T1 é mostrada na figura abaixo: <br><br />
[[Arquivo:Hdsl.jpg]] <br><br />
[http://www.gta.ufrj.br/grad/03_1/dsl/hdsl.htm ''Referência'']<br />
|-<br />
<br />
|Luísa || '''SDSL''' ||<br />
Linha Digital Simétrica de Assinante (Symmetric Digital Subscriber Line - SDSL) refere-se a tecnologias de transmissão de dados digitais ao longo dos fios de cobre da rede de telefonia onde a largura de banda na direção downstream é idêntica à largura de banda no direção upstream, é uma variante do HDSL. Esta largura de banda simétrica pode ser considerado como sendo o inverso da largura de banda assimétrica oferecido pela tecnologia ADSL, em que a largura de banda de upstream é mais baixa do que a largura de banda de downstream. A taxa de transmissão varia entre 72 Kbps e 2320 Kbps, em uma distância máxima de até 3,4Km. SDSL é geralmente comercializada para clientes empresariais.<br />
[https://pt.wikipedia.org/wiki/Symmetric_digital_subscriber_line ''Referência''][https://en.wikipedia.org/wiki/Symmetric_digital_subscriber_line ''Referência'']<br />
|-<br />
<br />
|}<br />
<br />
<br />
Após comissionados os circuitos da aula anterior, efetivar a instalação de dois circuitos ponto à ponto completos incluindo os DTEs (roteadores), considerando as configurações nos routers NR2G seguindo o procedimento a seguir:<br />
<br />
===Implementação de uma rede privada com três nós de rede e protocolo ponto à ponto HDLC.===<br />
<br />
* Construção da rede no laboratório.<br />
<br />
Implemente uma rede rede física composta por três roteadores da Digitel NR2G, que devem ser interconectados como mostrado abaixo:<br />
<br />
[[imagem:Rede-nr2g.png|600px]]<br />
<br />
A rede contém dois enlaces dedicados ponto-à-ponto (simulando duas SLDDs - Serviço Local de Linha Digital - formadas por LPCDs - Linha Privativa de Comunicação de Dados - à 2 fios) com modems digitais operando a 2048Kbps. Os Modens da DIGITEL modelo DT2048SHDSL devem ser configurados da seguinte forma: (chaves em ON) <br />
* Modens do RACK PRINCIPAL (placas instaladas nos slots do Sub-bastidor): DIP1: todas em OFF; DIP2: 3 à 8 em ON; DIP3: todas em ON; DIP4: todas em ON; DIP 5-: todas em OFF - Modo LTU (Modem como Unidade de Terminação de Linha), relógio interno, 2048Kbps, e interface V.35 padrão ISO2110;<br />
* Modens dos RACKs de apoio A e B: DIP1: todas em OFF; DIP2: 1,4 à 8 em ON; DIP3: todas em ON; DIP4: todas em ON; DIP 5-: todas em OFF - Modo NTU (Modem como Unidade de Terminação de Rede), relógio regenerado, 2048Kbps, e interface V.35 padrão ISO2110;<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 16/09 - Interligação de LANs via Circuitos Ponto à Ponto (LPCD) e protocolo HDLC }}<br />
<br />
== 16/09 - Interligação de LANs via Circuitos Ponto à Ponto (LPCD) e protocolo HDLC ==<br />
<br />
* Instalação de duas LANs independentes através do cabeamento estruturado dos racks de apoio;<br />
* Ampliando a LAN através do cascateamento de portas de switch;<br />
* Criação de LANs independentes no mesmo Switch via racks de apoio;<br />
* Implementação de uma rede privada com três nós de rede via duas LPCDs e protocolo ponto à ponto HDLC;<br />
* Configuração dos routers;<br />
<br />
===Instalação de duas LANs independentes através do cabeamento estruturado dos racks de apoio===<br />
<br />
Instale de dois a quatro PCs em cada switch nos racks de apoio (A e B) conforme o esquema mostrado na orientação do professor mantendo as mesmas configurações da rede IP desses PCs. Isso permite que um computador vai se comunicar com qualquer outro da mesma rede. Ao manobrar o cabeamento seguindo as orientações, somente os PCs conectados ao swicth devem trocar pacotes em uma LAN que fica isolada da rede do IFSC e portanto sem acesso à internet também. Use o comando '''ping''' para testar e se certificar.<br />
<br />
===Ampliando a LAN através do cascateamento de portas de switch===<br />
<br />
Interligue com um cabo de rede entre quaisquer portas de cada switch dos racks de apoio das duas LANs criadas anteriormente. Observe que todos os PCs estão em uma mesma LAN agora. Todos devem se comunicar.<br />
<br />
===Criação de LANs independentes no mesmo Switch via racks de apoio===<br />
<br />
Para isso, use os comandos nos PCs como abaixo com o seguinte endereçamento de rede: Para quem estiver no switch do rack de apoio A use o IP 192.168.10.x para dois PCs e 192.168.20.x para outros dois PCs, onde x tem que ser valores de 2 à 254. Para quem estiver no switch do rack de apoio B use o IP 192.168.30.x para dois PCs e 192.168.40.x para outros dois PCs, onde x tem que ser valores de 2 à 254. Para os PCs, aplique os seguintes comandos:<br />
* sudo ifconfg eth0 x.x.x.x netmask m.m.m.m up - para atribuir outro endereço na placa de rede<br />
* sudo route add default gw x.x.x.x - para atribuir um novo gateway para a placa de rede (use o último endereço válido para host da classe da rede - 254)<br />
* route -n - para ver a tabela atual de roteamento.<br />
<br />
Após este procedimento somente os PCs de mesma rede devem estar trocando pacotes. Use o comando '''ping''' para testar.<br />
<br />
===Implementação de uma rede privada com três nós de rede via duas LPCDs e protocolo ponto à ponto HDLC===<br />
<br />
* Construção da rede no laboratório.<br />
<br />
Usando as LANs criadas anteriormente e os dois links ponto à ponto SHDSL já comissionados, vamos implementar uma rede rede física composta por três roteadores da Digitel NR2G, que devem ser interconectados como mostrado abaixo:<br />
<br />
[[imagem:Rede-modems.png|600px]]<br />
<br />
<br />
; Comissionamento das LPCDs (já realiado na aula anterior)<br />
<br />
A rede contém dois enlaces dedicados ponto-à-ponto (simulando duas SLDDs - Serviço Local de Linha Digital - formadas por LPCDs - Linha Privativa de Comunicação de Dados - à 2 fios) com modems digitais operando a 2048Kbps. Os Modens da DIGITEL modelo DT2048SHDSL já estão configurados da seguinte forma: (chaves em ON) <br />
* Modens do RACK PRINCIPAL (placas instaladas nos slots do Sub-bastidor): DIP1: todas em OFF; DIP2: 3 à 8 em ON; DIP3: todas em ON; DIP4: todas em ON; DIP 5-: todas em OFF - Modo LTU (Modem como Unidade de Terminação de Linha), relógio interno, 2048Kbps, e interface V.35 padrão ISO2110;<br />
* Modens dos RACKs de apoio A e B: DIP1: todas em OFF; DIP2: 1,4 à 8 em ON; DIP3: todas em ON; DIP4: todas em ON; DIP 5-: todas em OFF - Modo NTU (Modem como Unidade de Terminação de Rede), relógio regenerado, 2048Kbps, e interface V.35 padrão ISO2110;<br />
<br />
=== Confirguração dos routers ===<br />
<br />
Todos os roteadores devem ser configurados com protocolo HDLC aplicados sobre suas interfaces serias WAN e rodando o algoritmo de roteamento RIP em sua forma mais básica, visando evitar a configuração demorada e cansativa de rotas estáticas na interligação das LANs dos Switches dos Racks de apoio A e B.<br />
<br />
;Configurando a Rede<br />
<br />
# Acesse a interface de gerência (console) do roteador R1 ou R2. O roteador R1 está no rack de apoio A, o roteador R3 está no rack Principal, e R2 está no rack B. Para acessar a console, faça o seguinte:<br />
## Conecte o cabo serial específico na interface serial RS232 do seu computador. Conecte esse cabo também na interface ''console'' do roteador, que fica no painel traseiro. Como os roteadores e switches estão distantes das bancadas, será necessário usar as tomadas exclusivas que conectam as bancadas aos racks. Se tiver dúvidas, consulte o professor para entender a disposição do cabeamento estruturado;<br />
## Execute o programa ''minicom'', que abre um terminal de texto via porta serial. Ele deve ser configurado para se comunicar pela porta serial ''/dev/ttyS0'', com 57600 bps, 8 bits de dados e 1 stop-bit (isso aparece descrito assim: 57600 8N1) e sem controles de fluxo. <syntaxhighlight lang=bash><br />
sudo minicom -s<br />
</syntaxhighlight><br />
## Se o ''minicom'' estiver correto, você deverá ver a interface [http://tele.sj.ifsc.edu.br/~casagrande/RED/apoio/Manual_NR-2G_3200_e_4200.pdf CLI] do roteador (''Command Line Interface''). Caso contrário, confira se o cabo serial está bem encaixado, e se os parâmetros do ''minicom'' estão certos.<br />
# O login e senha para acessar a configuração dos routers é "nr2g" e "digitel" respectivamente. Ao entrar na CLI avalie a configuração geral dos routers com o comando DUMP ALL;<br />
# Estando os links ativos nas WANs, voce pode acessar qualquer router usando a facilidade do protocolo TELNET. Para tanto, dentro da CLI do router aplique o comando EXEC TELNET [IP da WAN ou LAN]. Voce também podem acessa-los por qualquer computador das redes direita ou esquerda, desde que esses estejam na mesma subrede das interfaces LAN dos routers. Uma vez estando na CLI de um dos routers, voce pode acessar os demais com EXEC TELNET;<br />
# Observe se a configuração dos routers está como o previsto na janela abaixo. Talvez voce precise ajustar a configuração em algum roteador.<br />
# Faça a configuração básica dos PCs e Roteadores NR2G com protocolo HDLC. Esta configuração já permite que a rede se conecte a internet através da porta LAN0 do router PRINCIPAL, desde que as configurações de rotas nos PCs de cada subrede e do professor sejam aplicadas conforme na sequência.<br />
<br />
<br />
; ATENÇÂO: As vezes é possível que o status de algum link fique DOWN mesmo após as configurações corretamente realizadas nos modens e baixadas nos routers. Neste caso certifique-se de retirar o cabo de console do router. Ele pode causar mau funcionamento nas seriais WANs do router (ruídos via GND).<br />
<br />
<br />
#* '''R1:''' <syntaxhighlight lang=text><br />
A> <br />
SET LAN LAN0 IP 192.168.10.254 MASK 255.255.255.0 BROADCAST 192.168.10.255 <br />
SET LAN LAN0 UP <br />
SET LAN LAN1 IP 192.168.20.254 MASK 255.255.255.0 BROADCAST 192.168.20.255 <br />
SET LAN LAN1 UP <br />
SET WAN WAN0 PROTO HDLC IP 10.1.1.2 MASK 255.255.255.252 PEER 10.1.1.1 UP <br />
SET WAN WAN1 PURGE <br />
<br />
SET RIP REDIST-STATIC TRUE REDIST-CONNECTED TRUE REDIST-OSPF FALSE DEFAULTMETRIC 2<br />
SET RIP WAN0 ENABLED TRUE TYPE ACTIVE <br />
SET RIP WAN0 AUTH TYPE NONE <br />
SET RIP UP <br />
<br />
SET ROUTES DEFAULT GW1 10.1.1.1 COST1 0 <br />
SET ROUTES UP <br />
CONFIG SAVE <br />
<br />
</syntaxhighlight><br />
#* '''R2:''' <syntaxhighlight lang=text><br />
B> <br />
SET LAN LAN0 IP 192.168.30.254 MASK 255.255.255.0 BROADCAST 192.168.30.255 <br />
SET LAN LAN0 UP <br />
SET LAN LAN1 IP 192.168.40.254 MASK 255.255.255.0 BROADCAST 192.168.40.255 <br />
SET LAN LAN1 UP <br />
SET WAN WAN0 PROTO HDLC IP 10.1.1.6 MASK 255.255.255.252 PEER 10.1.1.5 UP <br />
SET WAN WAN1 PURGE <br />
<br />
SET RIP REDIST-STATIC TRUE REDIST-CONNECTED TRUE REDIST-OSPF FALSE DEFAULTMETRIC 2<br />
SET RIP WAN0 ENABLED TRUE TYPE ACTIVE <br />
SET RIP WAN0 AUTH TYPE NONE <br />
SET RIP UP <br />
<br />
SET ROUTES DEFAULT GW1 10.1.1.5 COST1 0 <br />
SET ROUTES UP<br />
CONFIG SAVE <br />
<br />
</syntaxhighlight><br />
#* '''R3:''' <syntaxhighlight lang=text><br />
PRINCIPAL> <br />
SET LAN LAN0 PURGE <br />
SET LAN LAN1 PURGE <br />
SET WAN WAN0 PROTO HDLC IP 10.1.1.1 MASK 255.255.255.252 PEER 10.1.1.2 UP<br />
SET WAN WAN1 PROTO HDLC IP 10.1.1.5 MASK 255.255.255.252 PEER 10.1.1.6 UP<br />
<br />
SET RIP REDIST-STATIC TRUE REDIST-CONNECTED TRUE REDIST-OSPF FALSE DEFAULTMETRIC 2<br />
SET RIP WAN0 ENABLED TRUE TYPE ACTIVE <br />
SET RIP WAN0 AUTH TYPE NONE <br />
SET RIP WAN1 ENABLED TRUE TYPE ACTIVE <br />
SET RIP WAN1 AUTH TYPE NONE <br />
SET RIP UP <br />
<br />
SET LAN LAN0 IP 192.168.1.231 MASK 255.255.255.0 BROADCAST 192.168.1.255 UP <br />
SET ROUTES DEFAULT GW1 192.168.1.1 COST1 0 <br />
SET ROUTES UP <br />
CONFIG SAVE <br />
<br />
<br />
</syntaxhighlight><br />
# Para conferir as configurações das interfaces, use o comando ''SHOW'' seguido da interface. Exemplo: <syntaxhighlight lang=text><br />
# SHOW WAN WAN0 ALL<br />
# Para as rotas construídas dinamicamente pelo protocolo RIP:<br />
# SHOW ROUTES ALL<br />
</syntaxhighlight><br />
# Assim que os enlaces forem estabelecidos, o que pode ser também constatado com o comando ''SHOW'' aplicado às interfaces, ''conclua'' a configuração da rede (rotas nos pcs e roteadores). Ela deve ser configurada de forma que um computador possa se comunicar com qualquer outro computador da outra rede, e também acessar a Internet. Para isso, use os comandos nos PCs como:<br />
#* sudo ifconfg eth0 x.x.x.x netmask m.m.m.m up - para atribuir outro endereço na placa de rede<br />
#* sudo route add default gw x.x.x.x - para atribuir um novo gateway para a placa de rede<br />
#* sudo route add -net x.x.x.x netmask m.m.m.m eth0 - para associar uma nova rede a interface eth0<br />
#* route -n - para ver a tabela atual de roteamento<br />
# Observe que optamos pelo uso de um protocolo de roteamento dinâmico (RIP na camada 3). Procure entender melhor como foi feita essa configuração, a partir do que está no [http://tele.sj.ifsc.edu.br/~casagrande/RED/apoio/Manual_NR-2G_3200_e_4200.pdf manual], começando pela página 82.<br />
# Para os PCs das subredes direita e esquerda caso necessite reconfigurar novamente: <syntaxhighlight lang=bash><br />
$ sudo ifconfig eth0 192.168.x.y netmask 255.255.255.0 up - x={10,20,30,40}; y={1,2,3,4}<br />
$ sudo route add default gw 192.168.x.254 - x={10,20,30,40} </syntaxhighlight><br />
# Veja se o status das interfaces e protocolos da WAN e LAN de todos os routers estão em UP. Anote e avalie a configuração de todos os routers e os PCs das duas LANs direita e esquerda. Voce pode usar o comando ''' $telnet <address> ''' a partir de qualquer PC que está ativo na rede e a partir desta seção, dentro de cada router, executar o comando '''EXEC TELNET <ADDRESS>''' para acessar qualquer router da rede, bastando endereçar quaisquer interfaces ativas;<br />
# Verificar e anotar todas as configurações e instalações dos componentes de redes, modens, cabos, adaptadores, manobras dos cabos, etc...<br />
# Verificar e anotar todas as configurações lógicas dos modens, routers e PCs.<br />
# Acessar as redes mutuamente qualquer computador de um subrede deve acessar qualquer outro da outra subrede;<br />
# Acessar a internet em todos os PCs;<br />
# Interprete as configurações dos routers e destaque como está configurada a rede. <br />
<br />
<br />
_________________________________<br />
<br />
<br />
Embora pouco popular atualmente, a rede que estudamos e implementamos no laboratório é um típico exemplo de uma Rede Privada usando links privativos (ou LPCD - Linha Privativa de comunicação de Dados ou Leased Line). Limitados as dimensões do laboratório, uma LPCD poderia ser efetivada entre quaisquer pontos do planeta. Quem permite ou decide qual infraestrutura usar é a operadora e não é incomum encontrar na última milha dentre as diversas soluções, o uso do par trançado que está sendo o meio de transmissão foco desta parte da disciplina. O par trançado tanto está presente nos cabos lógicos que interligam interfaces digitais dos ativos de rede, quanto no cabeamento estruturado de uma LAN ou como opção de meio de transmissão da última milha de uma WAN ou MAN. <br />
<br />
Na implementação desta rede foi possível entender como duas LANs que podem se situar em localidades distantes e com endereçamentos distintos, podem se comunicar livremente através de links de uma rede WAN.<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 19/09 - Uso de Ambientes de Simulação com PACKET TRACER }}<br />
<br />
==19/09 - Uso de Ambientes de Simulação com PACKET TRACER ==<br />
<br />
<br />
* Passos iniciais para uso do Packet Tracer da CISCO.<br />
<br />
<br />
''' Após as instruções básicas do professor no uso do simulador PACKET TRACER, efetive neste ambiente o mesmo cenário físico em anel implementado em nosso laboratório. Salve o arquivo .pkt que é gerado pelo aplicativo para futuro uso. ''' Para apoio na conclusão da tarefa, vocês irão encontrar inúmeros exemplos de vídeos e guias de configuração de uso do Packet Tracer na internet. Outro ponto de partida para fazer a configuração dos equipamentos da simulação é obrigatoriamente adotar a própria configuração utilizada nos routers NR2G do Laboratório. <br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 23/09 - Protocolos Ponto à Ponto e Enquadramento (Framing)}}<br />
<br />
==23/09 - Protocolos Ponto à Ponto e Enquadramento (Framing)==<br />
<br />
<br />
'''Resumo da aula:'''<br />
<br />
* [http://www.sj.ifsc.edu.br/~casagrande/RED/slides/protocolos_pp.pdf Protocolos Ponto à Ponto];<br />
* bit e byte stuffing;<br />
* Explicações e exemplos de enquadramento e delimitação em HDLC e PPP; Identificação de pacote;<br />
* Protocolos orientados à bit e à Byte;<br />
* RFC1662 e exemplos de byte stuffing;<br />
* Diagramas de tempo de protocolos HDLC;<br />
* Protocolos PPP e seus protocolos de apoio.<br />
<br />
'''Bibliografia relacionada:'''<br />
'''ATENÇÃO:'''<br />
* Ler Seção 5.7 do livro "Redes de Computadores" do Kurose 5a ed.'''<br />
* Parte III e capítulos 10 e 11 do livro "Comunicação de Dados e Redes de Computadores, 4a ed.", de Behrouz Forouzan<br />
* Capítulo 3 do livro "Redes de Computadores" de Andrew Tanenbaum.<br />
<br />
'''Fundamentos Teóricos'''<br />
<br />
=== Enlaces lógicos ===<br />
<br />
Equipamentos de rede se comunicam por meio de enlaces (''links''). Um enlace é composto por uma '''parte física''', composta pelo meio de transmissão e o hardware necessário para transmitir e receber um sinal que transporta a informação, e uma '''parte lógica''', responsável por empacotar os dados a serem transmitidos. O diagrama abaixo ilustra um enlace entre dois equipamentos, realçando as formas com que a informação é representada durante a transmissão e recepção. Nesse diagrama, a ''parte lógica'' está representada no bloco ''Enlace'', e a ''parte física'' está no bloco ''Física''; a informação transmitida, representada por ''Dados'', pode ser, por exemplo, um datagrama IP.<br />
<br />
[[imagem:Datalink-phy.png|600px]]<br />
<br />
O enlace lógico tem uma dependência total em relação à parte física. Isso quer dizer que o tipo de tecnologia de transmissão existente na parte física traz requisitos para o projeto da parte lógica.<br />
<br />
Deste ponto em diante, a ''parte lógica'' será chamada simplesmente de '''Camada de Enlace''', e a parte física de '''Camada Física'''.<br />
<br />
Em nosso estudo vamos investigar '''enlaces ponto-a-ponto''', os quais necessitam de protocolos específicos. Para ficar mais claro o que deve fazer um protocolo de enlace ponto-a-ponto, vamos listar os serviços típicos existentes na camada de enlace. <br />
<br />
===== Serviços da camada de enlace =====<br />
<br />
[[Image:Data-link.png]]<br />
<br />
Os serviços identificados na figura acima estão descritos a seguir. A eles foram acrescentados outros dois:<br />
<br />
* '''Encapsulamento (ou ''enquadramento'')''': identificação das PDUs (quadros) de enlace dentro de sequências de bits enviadas e recebidas da camada física<br />
* '''Controle de erros''': garantir que quadros sejam entregues no destino<br />
** '''''Detecção de erros''''': verificação da integridade do conteúdo de quadros (se foram recebidos sem erros de bits)<br />
* '''Controle de fluxo''': ajuste da quantidade de quadros transmitidos, de acordo com a capacidade do meio de transmissão (incluindo o atraso de transmissão) e do receptor<br />
* '''Endereçamento''': necessário quando o enlace for do tipo '''multi-ponto''', em que vários equipamentos compartilham o meio de transmissão (ex: redes locais e redes sem-fio)<br />
* '''Controle de acesso ao meio (MAC)''': também necessário para '''meios compartilhados''', para disciplinar as transmissões dos diversos equipamentos de forma a evitar ou reduzir a chance de haver colisões (transmissões sobrepostas)<br />
* '''Gerenciamento de enlace''': funções para ativar, desativar e manter enlaces<br />
<br />
==== Protocolos de enlace ponto-a-ponto ====<br />
<br />
Dois protocolos de enlace ponto-a-ponto muito utilizados são:<br />
* '''PPP (''Point-to-Point Protocol''):''' proposto no início dos anos 90 pelo IETF (ver [http://www.ietf.org/rfc/rfc1661.txt RFC 1661 e][http://www.ietf.org/rfc/rfc1662.txt RFC 1662] ), e amplamente utilizado desde então. Este protocolo não faz controle de erros nem de fluxo, portanto se quadros sofrerem erros de transmissão serão sumariamente descartados no receptor. Originalmente muito usado em acesso discado, recentemente sua aplicação se concentra em enlaces por linhas dedicadas, enlaces sem-fio 3G, e uma versão modificada para acesso doméstico ADSL (''PPPoE''). Ver mais detalhes na seção 5.7 do livro do Kurose e na seção 11.7 do livro ''Comunicação de Dados e Redes de Computadores'', de Behrouz Forouzan. <br />
* '''HDLC (''High-level Data Link Control''):''' criado nos anos 70, foi largamente utilizado em enlaces ponto-a-ponto, porém atualmente foi substituído pelo PPP na maioria dos cenários em que era usado. Este protocolo faz controle de erros e de fluxo usando um [[Desempenho_ARQ|mecanismo ARQ do tipo Go-Back-N]] (com janela de tamanho 7 ou 127). Ainda se aplica a enlaces ponto-a-ponto em linhas dedicadas, enlaces por satélite e aplicações específicas onde a presença de ruídos no meio de transmissão é relevante ou se deseja confiabilidade na entrega de pacotes na camada 2. Ver mais detalhes na seção 11.6 do livro ''Comunicação de Dados e Redes de Computadores'', de Behrouz Forouzan.<br />
<br />
Ambos protocolos possuem o mesmo formato de quadro. Na verdade, o PPP copiou o formato de quadro do HDLC, apesar de não utilizar os campos ''Address'' e ''Control''. O campo ''Flag'', que tem o valor predefinido <math>7E_H</math>, serve para delimitar quadros, assim o receptor sabe quando inicia e termina cada quadro.<br />
<br />
[[imagem:Ppp-frame.png|400px]]<br />
<br>''Quadro PPP ou HDLC (tamanho de campos dados em bytes)''<br><br />
<br />
Esses protocolos foram criados para uso com comunicação serial síncrona (ver capítulo 4, seção 4.3 do livro ''Comunicação de Dados e Redes de Computadores'', de Behrouz Forouzan). O PPP funciona também com [http://pt.wikipedia.org/wiki/Comunica%C3%A7%C3%A3o_serial_ass%C3%ADncrona comunicação serial assíncrona].<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 26/09 - Detecção e Correção de Erros }}<br />
<br />
==26/09 - Detecção e Correção de Erros ==<br />
<br />
;Protocolo PPP<br />
<br />
;Técnicas de Detecção e Correção de Erros <br />
<br />
* Paridade Simples; <br />
* Paridade Combinada (ou longitudinal);<br />
* Checksum;<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 30/09 - <math>\blacklozenge</math> - Exercícios de revisão avaliação A1}}<br />
<br />
==30/09 - Exercícios de revisão avaliação A1 ==<br />
<br />
<br />
0) <math>\blacklozenge</math> '''Entrega em 03/10 - de forma MANUSCRITA E INDIVIDUAL''' - Utilize a técnica de CRC (Ciclical Redundance Check) para determinar o FCS de um pacote completo de dados representado pelas duas primeiras letras MINÚSCULAS seu nome na codificação ASCII. Como polinômio gerador utilize os bits que representam a última letra MAIÚSCULA de seu nome. Por exemplo: '''jo'''rg'''E''' - pacote de dados: 6AH ('''j''') 6FH ('''o''') --> 0110101001101111 Polinômio Gerador: C5H ('''E''') --> 11000101 = x^7+x^2+1. Para a tarefa apresente:<br />
<br />
a) O desenvolvimento do cálculo dos bits de CRC realizado no processo de transmissão do pacote de dados;<br />
<br />
b) O desenvolvimento do cálculo da verificação do pacote de dados realizado na camada de enlace no receptor considerando que não houve erros na transmissão dos dados. Neste caso o pacote é dado como correto;<br />
<br />
c) O desenvolvimento do cálculo da verificação do pacote de dados realizado na camada de enlace no receptor considerando erros de bit ou bits durante a transmissão dos dados. Neste caso o pacote é dado como incorreto e descartado. Escolha ao seu gosto a posição e quantidade de bits errados e comprove a detecção de erros no pacote na recepção;<br />
<br />
d) Leia todo o Capítulo 10 do Livro do Fourozan e avalie qual a eficiência (capacidades) que o seu polinômio gerador tem para detectar erros de bit e de rajada que eventualmente podem ocorrer durante a propagação do sinal até a recepção. <br />
<br />
<br />
;Exercícios<br />
<br />
<br />
1) Não é exemplo de ''last mile'':<br />
a) Uma linha Privativa de Comunicação de dados (LPCD) com modens VDSL em cada ponta da linha;<br />
b) Uma LPCD urbana formada exclusivamente por dois pares de fios;<br />
c) Um enlace wireless interurbano entre dois pontos de presença (PoP) de um ISP (Internet Service Provider);<br />
d) Um SLDD (Serviço de Linha Dedicada Digital) urbano; <br />
e) todas alternativas.<br />
<br />
2)Um determinado trecho de uma sequencia de bits identificado pela camada física é mostra abaixo. Considerando a sequencia<br />
possui delimitação de frames e os bit-stuffing, a sequencia identificada pela cada de enlace será:<br />
<br />
11101111110001010100001111101111101111101101111101010101101111110001010101110 <br />
<br />
a) 1110111111000101010000111111111111111110111111010101101111110001010101110; <br />
b) 0111110001010100001111101111101111101101111101010101101111110; <br />
c) 0010101000011111011111011111011011111010101011;<br />
d) 001010100001111111111111111101111110101011; <br />
e) nenhuma das alternativas.<br />
<br />
3) Considerando a estrutura de um protocolo PPP, os bytes referentes ao check de frame (FCS - CRC), os quais serão identificados pela camada de enlace a partir do conjunto de bytes recebidos pela camada física mostrado na sequência abaixo, será: <br />
<br />
...FF FF FF 7E FF 03 80 21 7D 5D 7D 5E 5D 29 4E AA 2B 5C 22 55 48 7D 5E 25 7E FF... <br />
<br />
a) 5E 25;<br />
b) 48 7D 5E 25;<br />
c) 55 48 7E 25;<br />
d) 7E 25;<br />
e) nenhuma das anteriores.<br />
<br />
4) O protocolo HDLC:<br />
a) não usa a técnica de reconhecimento por carona como faz o protocolo PPP;<br />
b) Usa sempre o protocolo LCP para guiar os processos de conexão e desconexão;<br />
c) é o tipo ideal para enlaces ruidosos;<br />
d) não realiza controle de fluxo;<br />
e) nenhuma das anteriores.<br />
<br />
5) O CRC (Ciclical Redundance Check) de uma sequência de dados 110001 gerada com polinômio gerador $x^{3}+x+1$:<br />
a) terá 4 bits;<br />
b) será a sequencia 111;<br />
c) não é possível calcular o CRC com uma quantidade tão pequena de bits;<br />
d) será a sequencia 0011;<br />
e) nenhuma das anteriores está correta.<br />
<br />
6) Uma transmissão de dados de 4800 bps necessita ser transmitido através de um modem. Decidiu-se utilizar um modem com<br />
modulação por chaveamento de amplitude e fase com uma constelação de 32 símbolos de modulação para executar essa tarefa. Calcule a taxa em bauds no sinal de saída do modem, sendo que a frequência da portadora é 1920 Hz. Considere um canal sem ruído.<br />
a) 4800 bauds;<br />
b) 2400 bauds;<br />
c) 1200 bauds;<br />
d) Impossível determinar com essa frequência de portadora;<br />
e) nenhuma das anteriores está correta.<br />
<br />
7) O fall-back e fall-forward utilizado em modens analógicos dentro das várias versões normatizadas pelo ITU-T:<br />
a) é uma tarefa fundamental entre esses modens banda base;<br />
b) funciona da mesma forma para os modens digitais;<br />
c) exige o controle de fluxo via hardware ou software entre DTE e DCE;<br />
d) são técnicas aplicadas somente em linha privativa;<br />
e) todas as alternativas anteriores estão corretas.<br />
<br />
8) É exemplo de DCE:<br />
a) um modem com tecnologia VDSL;<br />
b) um conversor de mídia (ou transceiver);<br />
c) um modem analógico;<br />
d) a parte do circuito de interface com o cabeamento de uma placa de rede de uma LAN;<br />
e) todas as alternativas anteriores estão corretas.<br />
<br />
9) Uma implementação de um circuito básico de comunicação de dados que exige uma Interface Digital(ID) com todos os sinais de<br />
controle e sincronismo:<br />
a) a ID tipo V.36 não atende essa implementação;<br />
b) a ID tipo G703/G704 atente essa implementação;<br />
c) se ela prevê o uso de uma ID com V.35 será necessário um cabo lógico entre DTE e DCE pino à pino com pelo menos 13 fios: 2 para os dados, 5 para os de controle e 6 para o sincronismo;<br />
d) se ela prevê o uso de uma ID com RS232 será necessário um cabo lógico entre DTE e DCE com pelo menos 11 fios: 1 para referência (GND); 2 para os dados, 5 para os de controle e 3 para o sincronismo;<br />
e) todas as alternativas anteriores estão corretas.<br />
<br />
10) O meio de transmissão formado por pares metálicos sob ação de ruídos e transportando sinais modulados e/ou codificados:<br />
a) possui uma SNR (Relação Sinal Ruído) maior quanto maior seu comprimento;<br />
b) não seguem a regra da capacidade de Shannon;<br />
c) provoca perdas de sinal principalmente pelo seu valor de capacitância por quilômetro;<br />
d) não é determinante para os limites de banda passante;<br />
e) nenhuma das alternativas está correta.<br />
<br />
11) Um enlace digital local (LAL) aplicado em um modem local:<br />
a) precisa de um conector de loop conectado na interface digital do modem remoto para se obter diagnóstico sobre o modem remoto;<br />
b) não consegue oferecer diagnóstico sobre o estado da interface digital do modem remoto;<br />
c) testa completamente os moduladores de demoduladores dos modens local e remoto de um modem digital;<br />
d) oferece diagnóstico sobre a interface analógica remota desde que seja um modem broadband (ou modem banda base);<br />
e) nenhuma das alternativas está correta.<br />
<br />
12)Um nível DC ainda é encontrado em codificações do tipo:<br />
a) NRZ-L;<br />
b) bifásico Manchester;<br />
c) AMI;<br />
d) HDB3;<br />
e) nenhuma das alternativas está correta.<br />
<br />
13) Avalie cada afirmação abaixo e conclua colocando um número de 1 à 3 no espaço indicado, se ela refere-se a uma característica <br />
ou atributo genérico de um modem: (1) analógico ou narrowband, (2) digital(ou banda base, ou broadband) ou (3) tanto analógico quanto digital.<br />
a.( ) uso com linha discada;<br />
b.( ) uso em LPCD;<br />
c.( ) limite de distância menor quanto maior a taxa de transmissão (bps);<br />
d.( ) possui as características de Retreino, Fall-back e Fall-Forward;<br />
e.( ) realiza controle de fluxo via hardware ou software;<br />
f.( ) possui um espectro de frequências maior do que a banda de telefonia;<br />
g.( ) pode operar com uma taxa de 256Kbps na interface analógica;<br />
h.( ) opera com velocidades da interface digital maiores ou iguais a interface analógica; <br />
i.( ) podem operar na última milha em linha de assinante; <br />
j.( ) dependendo do tipo de tecnologia ou versão, usa técnicas de modulação como QAM;<br />
k.( ) podem ser equipados com a facilidade de enlaces de teste;<br />
l.( ) usam codificações como as do tipo bipolares na interface analógica;<br />
m.( ) podem operar em aplicações síncronas ou assíncronas;<br />
n.( ) podem operar com fonte de sincronismo própria (relógio interno);<br />
o.( ) operações full-duplex.<br />
<br />
<br />
<br />
;GABARITO de 1 à 13: C D D C E E C E D C B A (1 3 2 1 1 2 2 1 3 3 3 2 1 3 3) <br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 03/10 - Avaliação A1 }}<br />
<br />
==03/10 - Avaliação A1 ==<br />
<br />
Avaliação A1<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 07/10 - Correção Avaliação A1 - Redes LAN }}<br />
<br />
== 07/10 - Correção Avaliação A1 - Redes LAN ==<br />
<br />
* Correção avaliação A1<br />
<br />
* [http://tele.sj.ifsc.edu.br/~casagrande/RED/slides/lan.pdf REDES LOCAIS];<br />
<br />
=== Redes LAN - Princípios da LAN Comutada ===<br />
<br />
* Round Trip Time (RTT) para redes locais fundamentadas no protocolo CSMA/CD;<br />
* Os limites físicos de extensão de LANs com CSMA/CD - a regra 5 4 3 2 1. <br />
* Dos HUBs para a ethernet comutada - O SWITCH.<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 10/10 - <math>\blacklozenge</math> - Redes LAN - IEEE802.1D - LANÇAMENTO DO JOURNAL RED19-2}}<br />
<br />
== 08/05 - <math>\blacklozenge</math> - Redes LAN - IEEE802.1D - LANÇAMENTO DO JOURNAL RED19-2 ==<br />
<br />
<br />
=== Interligando redes locais de LANs (norma IEEE802.1D) ===<br />
<br />
Ao final deste conteúdo, voce terá condições de responder as seguintes questões:<br />
<br />
#Como um switch aprende que endereços MAC estão em cada porta ?<br />
#Como um switch encaminha um quadro cujo destinatário é desconhecido ?<br />
#Como um switch propaga quadros em broadcast ?<br />
<br />
<br />
;Princípios da Ethernet Comutada<br />
<br />
* [http://www.sj.ifsc.edu.br/~msobral/RCO2/slides/lan-switch-transparent.swf funcionamento de switches]<br />
<br />
=== Tecnologias de LAN switches ===<br />
<br />
Switches ''store-and-forward'' X ''cut-through''<br />
<br />
Veja a seguir detalhes sobre os dois tipos básicos de tecnologias na arquitetura interna de switches e na sequencia faça uma leitura técnica sobre o que ocorre com o fluxo de pacotes e o tratamento deles entre quaisquer portas de um swtch.<br />
<br />
;funcionamento básico de switches ''store-and-forward'' e ''cut-through'':<br />
<br />
* [switches cut-through]<br />
* [switches store-and-forward]<br />
* [switches simétricos (todas portas com mesma taxa de bits)]<br />
* [switches assimétricos (portas com diferentes taxas de bits)]<br />
<br />
;Leitura técnica de apoio sobre como os switches são construídos<br />
<br />
* [http://www.cisco.com/en/US/prod/collateral/switches/ps9441/ps9670/white_paper_c11-465436.html Texto sobre tecnologias de switches (store-and-forward e cut-through)]<br />
* [https://www.safaribooksonline.com/library/view/ethernet-switches/9781449367299/ch01.html Funcionamento básico de um Switch]<br />
* Leia este [http://tele.sj.ifsc.edu.br/~msobral/RCO2/docs/switch-internals.pdf bom texto] sobre estruturas internas de switches.<br />
<br />
<br />
=== Demonstração das fases do SWITCH com PACKET TRACER ===<br />
<br />
Siga as orientações do professor quem irá construir uma LAN com somente três PCs conectados em um SWITCH e um HUB no Packet Tracer.<br />
<br />
<br />
<math>\blacklozenge</math> '''Relatório da Atividade:''' Entrega EM DUPLA, por email ao professor '''até 14/10/2019'''. De acordo com os resultados e respostas às questões formuladas durante a execução do cenário da demonstração acima de LAN com o Packet Tracer, realize agora uma LAN com pelo menos um switch, um Hub e um router (CISCO1941) e '''relate''' brevemente como você identificou cada uma das operações básicas abaixo de um switch, no cumprimento de sua função em uma LAN: (Você pode usar screenshots das telas das avaliações no ambiente de simulação e resultados dos comandos realizados nos PCs e switches).<br />
<br />
*Learning<br />
*Flooding<br />
*Filtering<br />
*Forwarding<br />
*Aging<br />
<br />
=== <math>\blacklozenge</math> Orientações para a atividade principal da Avaliação A2 ===<br />
<br />
; Avaliação A2 - Submissão de artigo Técnico:<br />
<br />
; Call for Papers for RED19-2 journal.<br />
<br />
;Datas Importantes:<br />
# Abertura das inscrições para submissão: '''10/10/2019'''<br />
# Escolha do assunto e tópico: '''17/10/2019''' (veja nota abaixo!) <br />
# Deadline para Submissões: '''11/11/2019'''<br />
# Notificação de Aceite: '''18/11/2019'''<br />
# Submissão de Versão Final: '''25/11/2019''' (para aqueles artigos que não atingirem avaliação 60)<br />
<br />
; Nota:<br />
<br />
Solicito que me enviem a proposta de título com um breve resumo do artigo destacando o que ele irá abordar. Quanto antes entregar, melhor! <br />
<br />
;Escopo:<br />
<br />
Seguindo a necessidade da disciplina de explorar com mais atenção conteúdos envolvidos com a segunda parte da disciplina de Redes 2, Redes Locais (LAN), pretende-se que o evento RED19-1 proporcione aos estudantes e pesquisadores, que atuam em áreas diretamente relacionadas à Redes de Computadores, como conectividade, equipamentos de rede e gestão de redes a fim de apresentar e discutir trabalhos em nível de tutorial científico (de cunho teórico e/ou envolvendo aplicações específicas) relacionados principalmente aos seguintes tópicos: <br />
<br />
;Tópicos de Interesse<br />
<br />
Aplicações inteligentes em equipamentos de redes locais; camadas física e enlace da Internet das Coisas (IoT) e redes de sensores; Padronização e Interoperabilidade de redes locais; Sistemas embarcados aplicados a equipamentos de redes locais; Equipamentos de redes LAN de alta performance; Tecnologias store-and-forward e cut-through, Power over Ethernet (PoE), Viabilidade, estudos de caso, aplicação e gestão de redes locais; Segurança e políticas de uso de redes locais, Qualidade de serviços, priorização, gestão e projetos de redes locais. <br />
<br />
; Instruções para confecção dos artigos<br />
<br />
Os artigos poderão ser submetidos em português ou inglês com até 4 páginas, incluindo as referências, em arquivo formato .pdf conforme o modelo disponível ([http://www.sj.ifsc.edu.br/~casagrande/RED/sbai17-modelo-latex.zip LateX] ou [http://www.sj.ifsc.edu.br/~casagrande/RED/sbai17-modelo.doc Word]). Faça aqui o download dos templates para a submissão dos artigos: [http://www.sj.ifsc.edu.br/~casagrande/RED/sbai17-modelo-latex.zip LateX] ou [http://www.sj.ifsc.edu.br/~casagrande/RED/sbai17-modelo.doc Word]). Estes modelos referência do '''SBAI 2017 - Simpósio Brasileiro de Automação Inteligente'''.<br />
<br />
<br />
;IMPORTANTE <br />
<br />
#É OBRIGATÓRIO utilizar um dos templates em LateX ou Windows; <br />
#Independente do assunto escolhido dentro dos temas, é OBRIGATÓRIO que ele esteja explorando as camadas 1 e 2 das Redes Locais... LIMITANDO-SE às LANs e eventualmente às MANs; <br />
#Usem referenciais técnicos relacionados com os temas para desenvolver o artigo como por exemplo a revistas técnicas como a RTI, que além de possuir na biblioteca do campus, tem sua versão online: http://www.arandanet.com.br/revista/rti/edicao/2017/maio. Vejam o resumo das edições anteriores... tem muito assunto que cabe nos conteúdos que foram explorados em sala; <br />
<br />
;Submissão de artigos <br />
<br />
Os autores devem submeter eletronicamente seus manuscritos em formato .pdf para o professor (casagrande@ifsc.edu.br). <br />
<br />
;Publicação<br />
<br />
Os autores de artigos aceitos deverão publicar em arquivo pdf ou odt no espaço da WIKI da Disciplina com hyperlink no nome correspondente abaixo do título de cada artigo. <br />
<br />
;Avaliação <br />
<br />
#Os artigos serão distribuídos para os professores (revisores) da área de telecomunicações sem identificação dos autores (blind review). Os revisores já estarão orientados sobre as características do Journal (60% da avaliação A2 prevista no plano de ensino) e irão fazer uma breve avaliação sobre o artigo classificando-os em quatro possibilidades de recomendação para publicação com os seguintes pesos em nota de 20 à 100:<br>(1) artigo não recomendado, peso 20;<br>(2) artigo fracamente recomendado, peso 50;<br>(3) artigo recomendado, peso 70;<br>(4) artigo fortemente recomendado, peso 100.<br />
#Caso um mesmo artigo tenha a avaliação 1 ou 2 de um revisor nas possibilidades de recomendação e outra em 3 ou 4 por outro revisor, um terceiro revisor será delegado para avaliar o artigo, descartando a menor avaliação dos três; <br />
#Artigos que tiverem avaliados como recomendação final 3 ou 4 serão selecionados para serem publicados no Journal; <br />
#Para fechar a nota da avaliação 2 uma terceira nota será atribuída pelo professor de 50 à 100 a qual será somada as outras duas melhores notas finais dos revisores. A média das 3 notas será o valor de A2 (60% dela, conforme o plano de ensino). <br />
<br />
; Exemplos de artigos do Journal RED17-1:<br />
<br />
[http://www.sj.ifsc.edu.br/~casagrande/RED/red171.zip Exemplos do Journal RED17-1] <br />
<br />
<br />
{{Collapse bottom}}</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=PSD29007-Engtelecom(2019-2)_-_Prof._Marcos_Moecke&diff=162068PSD29007-Engtelecom(2019-2) - Prof. Marcos Moecke2019-10-07T16:52:29Z<p>127.0.0.1: /* ATUAL */</p>
<hr />
<div>==Registro on-line das aulas==<br />
===Unidade 1===<br />
{{collapse top | expand=true | Unidade 1}}<br />
;Aula 1 (29 jul):<br />
*[[PSD-EngTel (Plano de Ensino) | Apresentação da disciplina]]<br />
* Auto inscrição na [https://moodle.sj.ifsc.edu.br/course/index.php?categoryid=163 Plataforma Moodle de PSD29007] (engtelecom2019-2)<br />
<br />
;Aula 2 e 3 (1 e 5 ago):<br />
*[[Transformadas de Fourier]]<br />
<br />
;Aula 4 (8 ago):<br />
<br />
* Revisão de Sinais e Sistemas no tempo discreto em Matlab:<br />
:* Explorar a interface do Matlab. <br />
:* Funções de visualização das variáveis no workspace.<br />
:* Execução de instruções passo a passo.<br />
:* Escrita de script .m<br />
:* Uso da execução das seções de um script. <br />
:* Incremento de valor e execução.<br />
:EXEMPLOS:<br />
* Leia com atenção e execute o exemplo (Moving-Avarage Filter) na página de help da função [http://www.mathworks.com/help/matlab/ref/filter.html filter].<br />
* Revisão de Sinais e Sistemas no tempo discreto em Matlab:<br />
* Leia com atenção o help [https://www.mathworks.com/help/matlab/examples/using-fft.html Using FFT], abra o script clicando no botão ['''Open this Example''']. Execute o script seção após seção. Note o uso da fft para determinar a frequência das manchas solares.<br />
* Para melhorar o desempenho no Matlab recomendo que leiam a pagina do [http://www.mathworks.com/help/matlab/learn_matlab/help.html Help], . Também gostaria de lembra-los que a tecla F9 executa o código destacado no Help. [http://www.mathworks.com/help/matlab/learn_matlab/scripts.html Programação com scripts .m].<br />
:* Leia sobre [https://en.wikipedia.org/wiki/Sunspot manchas solares] para entender o que são os dados do segundo exemplo.<br />
<br />
: Sinais no dominio do tempo e dominio da frequencia. Uso da função [https://www.mathworks.com/help/matlab/ref/fft.html fft]<br />
{{collapse top| Exemplo de uso da FFT}}<br />
<syntaxhighlight lang=matlab><br />
%% Signal in Time Domain <br />
% Use Fourier transforms to find the frequency components of a signal buried in noise.<br />
% Specify the parameters of a signal with a sampling frequency of 1 kHz and a signal duration of 1.5 seconds<br />
Fs = 1000; % Sampling frequency <br />
T = 1/Fs; % Sampling period <br />
L = 1500; % Length of signal<br />
t = (0:L-1)*T; % Time vector<br />
<br />
% Form a signal containing a 50 Hz sinusoid of amplitude 0.7 and a 120 Hz sinusoid of amplitude 1.<br />
S = 0.7*sin(2*pi*50*t) + sin(2*pi*120*t);<br />
<br />
% Corrupt the signal with zero-mean white noise with a variance of 4.<br />
X = S + 2*randn(size(t));<br />
<br />
% Plot the noisy signal in the time domain. It is difficult to identify the frequency components by looking at the signal X(t).<br />
subplot(211);<br />
plot(1000*t(1:200),X(1:200))<br />
title('Signal Corrupted with Zero-Mean Random Noise')<br />
xlabel('t (milliseconds)')<br />
ylabel('X(t)')<br />
<br />
%% Signal in Frequency Domain<br />
% Compute the Fourier transform of the signal.<br />
Y = fft(X);<br />
<br />
% Compute the two-sided spectrum P2. Then compute the single-sided spectrum P1 based on P2 and the even-valued signal length L.<br />
P2 = abs(Y/L);<br />
P1 = P2(1:L/2+1);<br />
P1(2:end-1) = 2*P1(2:end-1);<br />
<br />
% Define the frequency domain f and plot the single-sided amplitude spectrum P1. <br />
% The amplitudes are not exactly at 0.7 and 1, as expected, because of the added noise. <br />
% On average, longer signals produce better frequency approximations.<br />
f = Fs*(0:(L/2))/L;<br />
subplot(212);<br />
plot(f,P1)<br />
ylim([0 1.05]) <br />
title('Single-Sided Amplitude Spectrum of X(t)')<br />
xlabel('f (Hz)')<br />
ylabel('|P1(f)|')<br />
<br />
% Now, take the Fourier transform of the original, uncorrupted signal and retrieve the exact amplitudes, 0.7 and 1.0.<br />
Y = fft(S);<br />
P2 = abs(Y/L);<br />
P1 = P2(1:L/2+1);<br />
P1(2:end-1) = 2*P1(2:end-1);<br />
<br />
plot(f,P1) <br />
title('Single-Sided Amplitude Spectrum of S(t)')<br />
xlabel('f (Hz)')<br />
ylabel('|P1(f)|')<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
:* Amostragem de Sinais (Experimento 1.2)<br />
::* Relembrar teorema da amostragem. Efeito da amostragem abaixo da frequência de Nyquist. Aliasing.<br />
::* Notar que as amostras de um sinal <math>s_1(t) = cos (2\pi \times 3 t)</math> (3 Hz) e um sinal <math>s_2(t) = cos (2\pi \times 7 t)</math> (7 Hz) são idênticas quando amostrado com um sinal de 10 Hz. <br />
<br />
{{collapse top| Experimento 1.2}}<br />
<syntaxhighlight lang=matlab><br />
% Exemplos e Experimentos baseados no livro:<br />
% DINIZ, P. S. R., DA SILVA, E. A. B., e LIMA NETTO, S. Processamento Digital de Sinais: Projeto e Análise de Sistemas. 2. ed. Porto Alegre: Bookman, 2014. 976 p. ISBN 978-8582601235.<br />
%% Experimento 1.2<br />
fs = 10; % frequencia (Hz) de amostragem dos sinais<br />
Ts = 1/fs; fase = 0;<br />
time = 0:Ts:(1-Ts);<br />
f1 = 3; % frequencia (Hz) do sinal s_1<br />
f2 = 7; % frequencia (Hz) do sinal s_2<br />
s_1 = cos(2*pi*f1*time+fase);<br />
s_2 = cos(2*pi*f2*time+fase);<br />
fsa = 1000; % frequência auxiliar de amostragem usada apenas para representação dos sinais originais<br />
Tsa = 1/fsa;<br />
time_aux = 0:Tsa:(1-Tsa);<br />
figure(1);<br />
stem(time,s_1,'ob');<br />
hold on;<br />
plot(time_aux, cos(2*pi*f1*time_aux+fase),'--k');<br />
stem(time,s_2,'+r');<br />
plot(time_aux, cos(2*pi*f2*time_aux+fase),'--m');<br />
hold off;<br />
legend('s_1 discreto','s_1 contínuo','s_2 discreto','s_2 contínuo')<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
:'''DICAS:''' <br />
*No help on-line da Mathworks, usando o botão ['''Try This Example > Try in your browser'''], permite executar o código no próprio browser sem ter nenhuma instalação do Matlab. Para verificar que o código realmente é executado mude a amplitude do ruído randômico para 0.1 ou 0.5, insira o comando '''close all''' antes da primeira linha, e execute todo o código ['''Run All''']<br />
*No help do Matlab, usando o botão ['''Open this Example'''], é possível executar o código seção a seção.<br />
<br />
;Aula 5 (12 ago):<br />
*Revisão de Sinais e Sistemas no tempo discreto em Matlab:<br />
:* Filtragem de Sinais (Experimentos 1.3, 2.1 e 2.2)<br />
:* Consulte a documentação do Matlab sobre [http://www.mathworks.com/access/helpdesk/help/techdoc/ref/roots.html roots], [http://www.mathworks.com/help/matlab/ref/poly.html poly], [http://www.mathworks.com/help/matlab/ref/linspace.html linspace], [http://www.mathworks.com/help/matlab/ref/logspace.html logspace], [http://www.mathworks.com/help/matlab/ref/residue.html residue], [http://www.mathworks.com/help/signal/ref/residuez.html residuez], [http://www.mathworks.com/help/matlab/ref/pretty.html pretty], [http://www.mathworks.com/help/matlab/ref/latex.html latex], [http://www.mathworks.com/help/signal/ref/freqs.html freqs], [http://www.mathworks.com/help/signal/ref/freqz.html freqz], [http://www.mathworks.com/help/symbolic/syms.html syms], [http://www.mathworks.com/help/signal/ref/symfun.html symfun], [http://www.mathworks.com/help/signal/ref/zplane.html zplane].<br />
:* Ver também o [http://www.mathworks.com/help/matlab/ref/publish.html Publish] para a geração automática de relatórios em html, doc, pdf, latex ou ppt. Ver também [http://www.mathworks.com/help/matlab/matlab_prog/publishing-matlab-code.html Publishing MATLAB Code].<br />
:* Ver pag. 138 a 141 de <ref name="DINIZ2014"/><br />
{{collapse top | Variação do Experimento 2.2}}<br />
<syntaxhighlight lang=matlab><br />
% Exemplos e Experimentos baseados no livro:<br />
% DINIZ, P. S. R., DA SILVA, E. A. B., e LIMA NETTO, S. Processamento Digital de Sinais: Projeto e Análise de Sistemas. 2. ed. Porto Alegre: Bookman, 2014. 976 p. ISBN 978-8582601235.<br />
%% Experimento 2.2<br />
% Resposta em frequencia usando a função freqz<br />
N = 1;<br />
num = [1 0 0 0];<br />
den = poly([0.8 0.2])<br />
%den = [1 0.6 -0.16];<br />
% modo 1<br />
%[H,w]=freqz(num,den,[0:pi/100:N*pi-pi/100]);<br />
%plot(w/pi, abs(H));<br />
% modo 2<br />
%[H,w]=freqz(num,den);<br />
%plot(w/pi, abs(H));<br />
% modo 3<br />
%[H,w]=freqz(num, den, 'whole');<br />
%plot(w/pi, abs(H));<br />
% modo 4<br />
freqz(num, den, 'whole');<br />
figure(2);<br />
zplane(num,den);<br />
<br />
%% Resposta em frequencia substituindo z -> e^(jw)<br />
syms z<br />
Hf(z) = symfun(z^2/(z-0.2)/(z+0.8),z);<br />
pretty(Hf)<br />
latex(Hf)<br />
N = 1;<br />
w = [0:pi/100:N*pi-pi/100];<br />
plot(w/pi,abs(Hf(exp(1i*w))))<br />
%title(['$' latex(Hf) '$'],'interpreter','latex')<br />
text(0.2,2,['H(z) = ' '$$' latex(Hf) '$$'],'interpreter','latex')<br />
xlabel(['w/' '$$' '\pi' '$$'],'interpreter','latex')<br />
</syntaxhighlight><br />
#Verifique a diferença entre os tipos de plots comentados no código.<br />
#substitua o denominador de H(z) por dois polos em [-0.8 -0.8].<br />
#verifique o que ocorre se forem utilizados polos complexos conjugados [0.3-0.4i 0.3+0.4i 0.1]<br />
#verifique o que ocorre se forem utilizados polos complexos não conjugados [0.3-0.4i 0.3+0.8i]<br />
#verifique o que ocorre se os polos estiverem fora do circulo unitário [1.2 -0.2]. Interprete este resultado <br />
{{collapse bottom}}<br />
<br />
:* Consulte a documentação do Matlab sobre [http://www.mathworks.com/help/matlab/ref/zeros.html zeros], [http://www.mathworks.com/help/matlab/ref/ones.html ones], [http://www.mathworks.com/help/matlab/ref/plot.html plot], [http://www.mathworks.com/help/matlab/ref/stem.html stem], [http://www.mathworks.com/help/matlab/ref/subplot.html subplot], [http://www.mathworks.com/help/matlab/ref/filter.html filter].<br />
:* Para usar melhor a interface do Matlab leia também [http://www.mathworks.com/help/matlab/matlab_prog/run-sections-of-programs.html?searchHighlight=script%20sections Execução de seções e variação de valores nos scripts], e ainda [http://www.mathworks.com/help/matlab/learn_matlab/plots.html Uso de gráficos no Matlab]. <br />
:* Ver pag. 65 a 71 de <ref name="DINIZ2014"> DINIZ, P. S. R., DA SILVA, E. A. B., e LIMA NETTO, S. '''Processamento Digital de Sinais: Projeto e Análise de Sistemas'''. 2. ed. Porto Alegre: Bookman, 2014. 976 p. ISBN 978-8582601235 </ref><br />
:*Ver também [http://www.mathworks.com/help/releases/R2014a/pdf_doc/matlab/index.html PDF Documentation for MATLAB]. Principalmente [http://www.mathworks.com/help/releases/R2014a/pdf_doc/matlab/getstart.pdf MATLAB Primer].<br />
====Aula 1 EAD====<br />
;Aula 6 (15 ago EAD):<br />
*Revisão de Sinais e Sistemas no tempo discreto em Matlab:<br />
:* Filtros Digitais <br />
<!--([https://owncloud.ifsc.edu.br/index.php/s/WWY2LWexts8PKDs Experimento 2.3])--><br />
;ATIVIDADE 1:<br />
<br />
Execute no Matlab o código abaixo, e analise os 3 filtros implementados através dos seus zeros e polos. Busque tirar conclusões sobre a influência da posição dos polos e zeros (ver o gráfico do plano z) e correlacione com a resposta de frequência em magnitude (gráfico do freqz). <br />
<br />
<syntaxhighlight lang=matlab><br />
%% Experimento 2.3 - Filtros Digitais<br />
% Exemplos e Experimentos baseados no livro:<br />
% DINIZ, P. S. R., DA SILVA, E. A. B., e LIMA NETTO, S. Processamento Digital de Sinais: Projeto e Análise de Sistemas. 2. ed. Porto Alegre: Bookman, 2014. 976 p. ISBN 978-8582601235.<br />
% FILE: Exp2_3.m<br />
<br />
%% 1º filtro<br />
p1 = 0.9*exp(1j*pi/4);<br />
Z = [1 -1 ]'; P = [p1 p1']';<br />
[num,den] = zp2tf(Z,P,1);<br />
[h,w] = freqz(num,den);<br />
figure(1); plot(w,abs(h)/max(abs(h)));<br />
figure(2); zplane(num,den);<br />
<br />
%% 2º filtro<br />
z1 = exp(1j*pi/8);<br />
z2 = exp(1j*3*pi/8);<br />
p1 = 0.9*exp(1j*pi/4);<br />
Z = [1 -1 z1 z1' z2 z2']';<br />
P = [p1 p1' p1 p1' p1 p1']';<br />
[num,den] = zp2tf(Z,P,1);<br />
[h,w] = freqz(num,den);<br />
figure(1); plot(w,abs(h)/max(abs(h)));<br />
figure(2); zplane(num,den);<br />
<br />
%% 3º filtro<br />
z1 = exp(1j*pi/8);<br />
z2 = exp(1j*3*pi/8);<br />
p1 = 0.99*exp(1j*pi/4);<br />
p2 = 0.9*exp(1j*pi/4 - 1j*pi/30);<br />
p3 = 0.9*exp(1j*pi/4 + 1j*pi/30);<br />
Z = [1 -1 z1 z1' z2 z2']';<br />
P = [p1 p1' p2 p2' p3 p3']';<br />
[num,den] = zp2tf(Z,P,1);<br />
[h,w] = freqz(num,den);<br />
figure(1); plot(w,abs(h)/max(abs(h)));<br />
figure(2); zplane(num,den);<br />
</syntaxhighlight><br />
<br />
<br />
;ATIVIDADE 2:<br />
<br />
:* A filtragem de sinais digitais pode ser realizada de diferentes formas: <br />
::* convolução (y = conv(x,h)), onde x(n) é o sinal de entrada e h(n) é a resposta ao impulso do filtro (sistema linear invariante no tempo), <br />
::* filtragem no domínio do tempo (y = a1.x(n)+ a2.x(n-1)+ .. ak.x(n-k));<br />
::* no domínio da frequência (y = ifft(fft(x)fft(h))<br />
<br />
{{collapse top |expand=true | Variação do Experimento 3.1}}<br />
<syntaxhighlight lang=matlab><br />
%% Variação do Experimento 3.1 do livro:<br />
% DINIZ, P. S. R., DA SILVA, E. A. B., e LIMA NETTO, S. Processamento Digital de Sinais: Projeto e Análise de Sistemas. 2. ed. Porto Alegre: Bookman, 2014. 976 p. ISBN 978-8582601235.<br />
% FILE: Ex3_1.m<br />
% Exemplificando as possiveis formas de realizar a filtragem de um sinal x(n)<br />
<br />
clc; clear all; close all;<br />
%% Definindo valores iniciais<br />
Nh = 10; Nx = 20;<br />
%Nh = 400; Nx = 10000;<br />
x = ones(1,Nx);<br />
% A resposta ao impulso de um sistema h(n) <br />
% no filtro FIR aos coeficientes b(n) = h(n) <br />
h = [1:Nh]; b = h;<br />
%% Filtrando o sinal e medindo tempos<br />
<br />
% OPÇÃO 1 - Filtragem utilizando a convolução<br />
% NOTE: length(y) = length(x) + length(h) -1<br />
<br />
tic; % iniciar a contagem do tempo<br />
y1 = conv(x,h); <br />
t(1) = toc; % terminar a contagem e mostrar tempo no console<br />
<br />
% OPÇÃO 2 - filtragem utilizando a equação recursiva<br />
% NOTE: length(y) = length(x)<br />
<br />
tic;<br />
y2 = filter(b,1,x);<br />
t(2) = toc;<br />
<br />
% OPÇÃO 3 - filtragem utilizando a equação recursiva <br />
% aumentando o tamanho de x para que length(y3) = length(y1)<br />
x3 = [x zeros(1,length(h)-1)];<br />
<br />
tic;<br />
y3 = filter(h,1,x3); <br />
t(3) = toc;<br />
<br />
length_y = length(x) + length(h) - 1;<br />
<br />
% OPÇÃO 4 - filtragem utilizando a FFT <br />
% a y = IFFT(FFT(x)*FFT(h))<br />
<br />
tic;<br />
X = fft(x,length_y);<br />
H = fft(h,length_y);<br />
Y4 = X.*H;<br />
y4 = ifft(Y4);<br />
t(4) = toc;<br />
<br />
% OPÇÃO 5 - filtragem utilizando a função fftfilt<br />
% a y = IFFT(FFT(x)*FFT(h))<br />
<br />
tic<br />
y5 = fftfilt(h,x3);<br />
t(5) = toc;<br />
<br />
disp('Comprimento do vetor de saída length(y)')<br />
disp([' ' num2str([length(y1) length(y2) length(y3) length(y4) length(y5)])])<br />
disp('Tempo usado na filtragem em micro segundos')<br />
disp([' ' num2str(t*1e6) ' us'])<br />
<br />
%% Plotando o gráfico<br />
subplot(411);stem(y1);<br />
hold on;<br />
stem(y2,'xr');<br />
stem(y3,'+m');<br />
legend('y1', 'y2', 'y3')<br />
hold off<br />
subplot(412);stem(y1, 'ob');legend('y1')<br />
subplot(413);stem(y2, 'xr'); hold on; stem(zeros(size(y1)),'.w');hold off; legend('y2')<br />
subplot(414);stem(y3, '+m');legend('y3')<br />
</syntaxhighlight><br />
<br />
{{collapse bottom}}<br />
* Verificar as funções [https://la.mathworks.com/help/matlab/ref/tic.html tic] e [https://la.mathworks.com/help/matlab/ref/toc.html toc]<br />
* Notar a diferença de tempo de processamento entre os processos de filtragem. <br />
* A situação pode ser muito diferente conforme muda o tamanho do sinal e ordem do filtro (h(n)). Modifique a resposta ao impulso e o sinal de entrada modificando os valores das variáveis de tamanho: Nh = 10, 100, 1000; Nx = 20, 1000, 10000;<br />
* Em função do sistema operacional e reserva de memória para as variáveis é importante desprezar a primeira medida de tempo. Realize 3 medidas de tempo para cada uma das 5 opções de filtragem, com pelo menos duas combinações de comprimento Nh e Nx. Relate os resultados obtidos no comentário da atividade no Moodle.<br />
<br />
;Aula 7 (19 ago):<br />
:* Exercício - Sinal DTMF com ruído<br />
::* Verifique se o Matlab está reproduzindo corretamente o som.<br />
<syntaxhighlight lang=matlab><br />
%% Carregando o som<br />
clear, close, clc<br />
load handel;<br />
<br />
%% Reproduzindo o som <br />
sound(y,Fs)<br />
<br />
% Reproduzindo o som <br />
%soundsc(y,Fs)<br />
<br />
% Reproduzindo o som <br />
%player = audioplayer(y, Fs);<br />
%play(player);<br />
</syntaxhighlight><br />
::* Usando o Matlab (ou Audacity) para gerar um sinal [https://pt.wikipedia.org/wiki/DTMF DTMF] correspondente a um número N e adicionar um ruido ao sinal. Opcionalmente utilize um [[Media:DFMT EX1.ogg | sinal DTMF gravado]]<br />
::* Utilizar uma frequência de amostragem de 8000Hz de fazer a duração do sinal igual a 2 segundos.<br />
<center> [[Arquivo:audacity_DTMF.png | Sinal 1234567890*# | 600 px]] </center><br />
::* Para adicionar o ruído utilize a função y = [http://www.mathworks.com/help/comm/ref/awgn.html awgn](x,snr), ou y = x + nivel*[http://www.mathworks.com/help/matlab/ref/randn.html randn](n).<br />
<br />
::* Observe este sinal no domínio do tempo (DT) e domínio da frequência (DF).<br />
<syntaxhighlight lang=matlab><br />
%% Carregando o som<br />
clear, close, clc<br />
[y,Fs] = audioread('DTMF_8kHz.ogg');<br />
<br />
%% Reproduzindo o som <br />
sound(y,Fs)<br />
<br />
%% Visualizando o som no DT<br />
time = [0:length(y)-1]'/Fs;<br />
plot(time',y'); xlabel('segundos');<br />
xlim([0 time(end)]), ylim([-1 1]);<br />
<br />
%% Visualizando o som no DF<br />
Nfreq = length(y);<br />
freq = linspace(0,2*pi,Nfreq)'*Fs/pi/2;<br />
Y = fft(y,Nfreq)/Nfreq;<br />
plot(freq,abs(Y)); xlabel('Hertz');<br />
xlim([0 Fs/2]);<br />
</syntaxhighlight><br />
:* Utilizar no Audacity um sinal DTMF ("1234567890") com fa= 8kHz <br />
::* Visualizar no domínio do tempo e frequência.<br />
::* Realizar a filtragem passa-baixas com fc = 1066 Hz, (selecionar a maior atenuação permitida)<br />
::* Realizar a filtragem passa-faixa com f0 = 770 Hz e B = 70Hz (selecionar a maior ordem permitida)<br />
:* Repetir o procedimento anterior para um sinal de ruído branco.<br />
<br />
:* Consulte a documentação do Matlab sobre <syntaxhighlight lang=matlab> fft, ifft, fftshift, randn </syntaxhighlight><br />
:* Consulte a documentação do Matlab sobre <syntaxhighlight lang=matlab> plot, grid, subplot, hold, xlabel, ylabel, title, legend, xlim, ylim, log10, log </syntaxhighlight><br />
:* Consulte a documentação do Matlab sobre [https://www.mathworks.com/help/matlab/ref/text.html text], [http://www.mathworks.com/help/signal/ref/zp2tf.html zp2tf], [http://www.mathworks.com/help/signal/ref/tf2zp.html tf2zp], [http://www.mathworks.com/help/signal/ref/fftfilt.html fftfilt], [http://www.mathworks.com/help/matlab/ref/awgn.html awgn] <br />
:*Ver pag. 141 a 145 e 230 a 235 de <ref name="DINIZ2014"/><br />
{{collapse bottom}}<br />
<br />
===Unidade 2===<br />
{{collapse top |expand=true | Unidade 2}}<br />
;Aula 8 (22 ago):<br />
*Filtros Analógicos:<br />
:* Função de transferência<br />
::<math> H(s) = \frac {c_0 + c_1 s + c_2 s^2 + ... + c_m s^m} {d_0 + d_1 s + d_2 s^2 + ... + d_n s^n}, m \le n</math><br />
<br />
:* Resposta em frequência: para obter a resposta em frequência é necessário avaliar <br />
::<math>H(j\omega) = H(s)\left|\begin{matrix}\\ s=j\omega \end{matrix}\right.</math><br />
<br />
::<math> H(j \omega) = \left | H(j \omega) \right | e^{j \phi(\omega)}</math><br />
<br />
::<math> \left | H(j \omega) \right |^2 = H(j \omega) H(-j \omega)</math><br />
<br />
::<math> e^{j 2 \phi(\omega)} = \frac {H(j \omega)} {H(-j \omega)}</math><br />
:* O projeto de filtros analógicos é realizado em 2 etapas:<br />
# projeto de um filtro passa baixas (LP) protótipo normalizado <math> H(p) </math> com frequência de passagem <math> \Omega_s = 1 </math><br />
# transformação em frequência para o tipo de filtro (LP, HP, BP ou BS) <br />
::<math> H(s) = H(p)\left|\begin{matrix}\\ p=g(s) \end{matrix}\right. </math> <br />
<br />
* Análise básica de filtros analógicos com Matlab.<br />
:Dado um sistema linear invariante no tempo, representado pela função de transferência <math> H(s) </math>, obter a resposta de frequência do sistema (Magnitude e Fase).<br />
::<math> H(s) = \frac {s + 1} {s^2 + s + 5} </math> <br />
::<math> H(j\omega) = \frac {s + 1} {s^2 + s + 5}\left|\begin{matrix}\\ s=j\omega \end{matrix}\right.</math><br />
::<math> H(j\omega) = \frac{1 + w\, \mathrm{i}}{ - w^2 + w\, \mathrm{i} + 5} </math><br />
<br />
<syntaxhighlight lang=matlab><br />
b = [1 1];<br />
a = [1 1 5];<br />
[z1,p1,k]=tf2zp(b,a)<br />
z2 = roots(b);<br />
p2 = roots(a);<br />
zplane(b,a);<br />
%%<br />
freqs(b,a);<br />
%%<br />
syms s w<br />
H(s) = (s+1)/(s^2 + s + 5);<br />
pretty(H(1j*w))<br />
latex(H(1j*w))<br />
%%<br />
ws = logspace(-2, 1, 1000);<br />
h = H(1j*ws);<br />
subplot(211)<br />
semilogx(ws,abs(h)); grid on;<br />
subplot(212)<br />
semilogx(ws,angle(h)/pi*180); grid on;<br />
</syntaxhighlight><br />
<br />
* Projeto de filtros analógicos do tipo Butterworth<br />
:* A aproximação de magnitude de filtros analógicos pode ser realizado usando as aproximações de Butterworth, Chebyshev (tipo 1 ou 2) e Cauer.<br />
<br />
[[Arquivo:TiposFiltrosHs.png | 600px]]<br />
<br />
;Proposta de exercício: <br />
*Use os polinômios de Butterworth com ordens de 1 a 10 mostrados na tabela abaixo para obter os filtros <math>H_n(s) = 1/B_n(s)</math>.<br />
<br />
{|<br />
|-----<br />
|<br />
{| class="wikitable" style="text-align: center;"<br />
|-<br />
!n!!Fatores Polinomiais de <math>B_n(s)</math><br />
|-<br />
!1<br />
|<math>(s+1)</math><br />
|-<br />
!2<br />
|<math>(s^2+1.4142s+1)</math><br />
|-<br />
!3<br />
|<math>(s+1)(s^2+s+1)</math><br />
|-<br />
!4<br />
|<math>(s^2+0.7654s+1)(s^2+1.8478s+1)</math><br />
|-<br />
!5<br />
|<math>(s+1)(s^2+0.6180s+1)(s^2+1.6180s+1)</math><br />
|-<br />
!6<br />
|<math>(s^2+0.5176s+1)(s^2+1.4142s+1)(s^2+1.9319s+1)</math><br />
|-<br />
!7<br />
|<math>(s+1)(s^2+0.4450s+1)(s^2+1.2470s+1)(s^2+1.8019s+1)</math><br />
|-<br />
!8<br />
|<math>(s^2+0.3902s+1)(s^2+1.1111s+1)(s^2+1.6629s+1)(s^2+1.9616s+1)</math><br />
|-<br />
!9<br />
|<math>(s+1)(s^2+0.3473s+1)(s^2+s+1)(s^2+1.5321s+1)(s^2+1.879s+1)</math><br />
|-<br />
!10<br />
|<math>(s^2+0.3129s+1)(s^2+0.9080s+1)(s^2+1.4142s+1)(s^2+1.7820s+1)(s^2+1.9754s+1)</math><br />
|}<br />
|}<br />
*Escolha uma ordem n (entre 5 e 10) <br />
*Plote a resposta em frequência em escala log da amplitude (em dB) e da fase (em rad/pi). <br />
*Qual é o ganho do filtro na banda passante? <br />
*Qual é a frequência de corte (-3dB) do filtro.<br />
*Qual é o salto de de fase que ocorre em algumas frequências?<br />
*Qual é o fator de atenuação em dB/decada após a frequência de corte?<br />
<br />
*Faça o diagrama de polos e zeros desse filtro.<br />
*Procure observar o que ocorre com a posição dos polos do filtro.<br />
*Calcule o valor do módulo dos pólos.<br />
<br />
<br />
;Aula 9, 10 (16, 26 ago):<br />
<br />
* Projeto de filtros analógicos passa baixas (low pass - LP) do tipo Butterworth, considerando: <math> \omega_p </math> é a frequência de passagem, <math> A_p = 3 dB </math> é a atenuação em dB na frequência de passagem, <math> \omega_s </math> é a frequência de ''stopband'', <math> A_s </math> é a atenuação em dB na frequência de ''stopband''.<br />
[[Arquivo:MascaraFiltroLP.png | 600px]]<br />
<br />
*Escalando as frequências em relação a <math> {\omega_p} </math>, teremos que <math> \Omega_s = \frac {\omega_s} {\omega_p} </math>, e <math> \Omega_p = \frac {\omega_p} {\omega_p} = 1 </math> são as frequências de passagem e ''stopband'' do filtro protótipo <math> H(p) </math>, que tem ganho unitário e frequência de passagem 1.<br />
<br />
;<math> A_p = 3 dB </math>:<br />
*Se considerarmos o caso particular em que na frequência de passagem o ganho (em escala linear) deve ser <math> G_p = 1/\sqrt{2} = 0,707 </math>, que corresponde a um ganho (em escala log) <math> G_p = - 3 dB </math>, ou atenuação <math> A_p = 3 dB </math>.<br />
*Considere que <math> \epsilon = \sqrt{10^{0.1A_p}-1}</math>, teremos <math> \epsilon = 1 </math><br />
*Para projetar o filtro é necessário:<br />
<br />
:1) determinar a ordem <math> n </math> do filtro: <br />
<br />
::<math> n \ge \frac {\log(10^{0.1A_s}-1)} {2 \log \Omega_s} </math><br />
<br />
:2) obter os polos do filtro: <br />
<br />
::<math> p_k = e^{\left[ j \frac{(2 k + n - 1)} {2 n} \pi \right]}, k = 1, 2, 3, ... n</math><br />
<br />
:3) obter a função de transferência:<br />
<br />
::<math> H(p)= \frac{1}{D(p)} </math>, onde <math> D(p)=\prod_{k=1}^{n} \left ( p-p_{k} \right ) </math><br />
<br />
::* No caso de um filtro LP é necessário ainda obter a função de transferência do filtro especificado fazendo a transformação de frequência <math> H(p) -> H(s) </math><br />
<br />
::<math>H(s) = H(p)\left|\begin{matrix} \\ p=\frac{s}{\omega_p} \end{matrix}\right. </math><br />
<br />
<br />
;Para qualquer <math> A_p </math>:<br />
*Teremos <math> \epsilon = \sqrt{10^{0.1A_p}-1}</math><br />
<br />
*Para projetar o filtro é necessário:<br />
:1) determinar a ordem <math> n </math> do filtro: <br />
<br />
::<math> n \ge \frac {\log[(10^{0.1A_s}-1)/\epsilon^2]} {2 \log \Omega_s} </math><br />
<br />
:2) obter os polos do filtro: <br />
<br />
::<math> p_k = \epsilon^{(-1/n)} e^{\left[ j \frac{(2 k + n - 1)} {2 n} \pi \right]}, k = 1, 2, 3, ... n</math><br />
<br />
:3) obter a função de transferência:<br />
<br />
::<math> H(p)= \frac{k}{D(p)} </math>, onde <math> k=\prod_{k=1}^{n} \left (-p_{k} \right ) = \epsilon^{-1}</math> e <math> D(p)=\prod_{k=1}^{n} \left ( p-p_{k} \right ) </math>.<br />
::NOTA: o valor <math> k </math> também pode ser obtido a partir de <math> {D(p)} </math>, pois corresponde ao último termo do polinômio <math> {D(end)} </math>.<br />
<br />
::* No caso de um filtro LP é necessário ainda obter a função de transferência do filtro especificado fazendo a transformação de frequência <math> H(p) -> H(s) </math><br />
::<math>H(s) = H(p)\left|\begin{matrix} \\ p=\frac{s}{\omega_p} \end{matrix}\right. </math><br />
<br />
:*Ver [[Uso do calculo simbólico na Matlab]]<br />
:*Ver pag. 186 a 204 de <ref name="SHENOI2006"> SHENOI, B. A. '''Introduction to Digital Signal Processing and Filter Design'''. 1.ed. New Jersey: John Wiley-Interscience, 2006. 440 p. ISBN 978-0471464822 </ref><br />
<br />
<!--<br />
<syntaxhighlight lang=matlab><br />
%Butterworth lowpass Responses (db)<br />
w = 0.1:0.01:10;<br />
H=inline('10*log10(1./(1+w.^(2*n)))','w','n');<br />
for k = 1:1:10<br />
semilogx(w,H(w,k)); hold on; <br />
end<br />
grid on<br />
<br />
%Butterworth lowpass Responses (linear)<br />
w = 0.1:0.01:2;<br />
H=inline('1./(1+w.^(2*n))','w','n');<br />
for k = 1:1:10<br />
plot(w,H(w,k)); hold on; <br />
end<br />
grid on<br />
</syntaxhighlight><br />
--><br />
<br />
<br />
;Aula 11 e 12 (29 ago e 2 set):<br />
* Projeto de filtros analógicos do tipo Chebyshev I.<br />
:* Polinômios de Chebyshev:<br />
:<math>C_n(\Omega) = cos (n cos^{-1}(\Omega))\!</math><br />
Os polinômios de Chebyshev de primeira ordem são definidos pela relação recursiva:<br />
:<math>C_0(\Omega) = 1 \,\!</math><br />
:<math>C_1(\Omega) = \Omega \,\!</math><br />
:<math>C_{n}(\Omega) = 2 \times \Omega \times C_{n-1}(\Omega) - C_{n-2}(\Omega). \,\!</math><br />
<br />
Os primeiros cinco polinômios de Chebyshev de primeira ordem são:<br />
:<math> C_0(\Omega) = 1 \,</math><br />
:<math> C_1(\Omega) = \Omega \,</math><br />
:<math> C_2(\Omega) = 2\Omega^2 - 1 \,</math><br />
:<math> C_3(\Omega) = 4\Omega^3 - 3\Omega \,</math><br />
:<math> C_4(\Omega) = 8\Omega^4 - 8\Omega^2 + 1 \,</math><br />
:<math> C_5(\Omega) = 16\Omega^5 - 20\Omega^3 + 5\Omega \,</math><br />
<br />
::*Determine a ordem mínima necessária considerando: <math> \omega_p </math> é a frequência de passagem do filtro LP, <math> A_p </math> é a atenuação em dB na frequência de passagem, <math> \omega_s </math> é a frequência de ''stopband'' do filtro, <math> A_s </math> é a atenuação em dB na frequência de ''stopband'', <math> \epsilon = \sqrt{10^{0.1A_p}-1 } </math>, <math> \Omega_s = \frac {\omega_s} {\omega_p} </math>, <math> \Omega_p = \frac {\omega_p} {\omega_p} = 1 </math> são as frequências de passagem e ''stopband'' do filtro protótipo. <br />
::<math> n \ge \frac {\cosh^{-1} \sqrt{(10^{0.1A_s}-1)/(10^{0.1A_p}-1)}} {\cosh^{-1} \Omega_s} </math><br />
<br />
::*Em seguida obter os polos do filtro: <br />
<br />
::<math> p_k = -\sinh(\varphi_2) \sin(\theta_k)+ j \cosh(\varphi_2) \cos(\theta_k) \ \ \ \ \ k = 1, 2, 3, ... n</math>, onde <br />
::<math> \theta_k = \left ( \frac{(2k-1)\pi}{2n} \right ) </math><br />
::<math> \varphi_2 = \frac{1}{n} \sinh^{-1}\left (\frac{1}{\epsilon} \right ) </math><br />
<br />
:<math>\left | H( j\Omega ) \right | ^2 = 1 \text{para n impar}, \frac {1}{1+\epsilon^2} \text{para n par} </math><br />
<br />
:<math>\left | H(0) \right | ^2 = \frac{H_0^2}{ 1+ \epsilon^2 C_n ^2 \left ( \Omega_0 \right )} </math><br />
<br />
::* Para obter a função de transferência:<br />
<br />
::<math> H(p)= \frac{H0}{D(p)} </math>, onde <math> D(p)=\prod_{k-1}^{n} \left ( p-p_{k} \right ) </math><br />
::onde<br />
::<math> H_0 = d_0*\sqrt{\frac{1}{ 1+ \epsilon^2}} </math> se n é par<br />
::<math> H_0 = d_0 </math> se n é impar<br />
::<math> d_0 =\prod_{k-1}^{n} \left (-p_{k} \right ) </math> é o último termo do denominador D(p)<br />
<br />
:* Uso das funções [http://www.mathworks.com/help/signal/ref/buttord.html buttord], [http://www.mathworks.com/help/signal/ref/butter.html butter], [http://www.mathworks.com/help/signal/ref/cheb1ord.html cheb1ord], [http://www.mathworks.com/help/signal/ref/cheby1.html cheby1], [http://www.mathworks.com/help/signal/ref/cheb2ord.html cheb2ord], [http://www.mathworks.com/help/signal/ref/cheby2.html cheby2], [http://www.mathworks.com/help/signal/ref/ellipord.html ellipord], [http://www.mathworks.com/help/signal/ref/ellip.html ellip] para o projeto de filtros analógicos com Matlab (é necessário usar o parâmetro ''''s'''').<br />
:* Ler '''Comparison of Analog IIR Lowpass Filters''' em [http://www.mathworks.com/help/signal/ref/ellip.html ellip]<br />
:* Uso das funções [http://www.mathworks.com/help/signal/ref/freqs.html freqs], "zplane", [http://www.mathworks.com/help/signal/ref/fvtool.html fvtool] na análise da resposta em frequência de filtros analógicos.<br />
<br />
* Projeto de filtros analógicos do tipo Butterworth, Chebyshev I e II e Cauer (eliptico) usando funções do Matlab.<br />
<syntaxhighlight lang=matlab><br />
%% Projeto de filtro passa-baixas usando funções do Matlab <br />
%% Especificações do filtro <br />
Wp =16000; Ws = 20000; Ap = 0.3; As = 20; G0= 3;<br />
% Para analisar o filtro projetado, use fvtool(b,a) para observar plano s, resposta em magnitude, fase e atraso de grupo<br />
<br />
%% Butterworth<br />
[n,Wn] = buttord(Wp, Ws, Ap, As,'s')<br />
[b,a] = butter(n,Wn, 's');<br />
<br />
%% Chebyshev I<br />
n = cheb1ord(Wp, Ws, Ap, As,'s')<br />
[b,a] = cheby1(n,Ap, Wp, 's');<br />
<br />
%% Chebyshev II<br />
n = cheb2ord(Wp, Ws, Ap, As,'s')<br />
[b,a] = cheby2(n,As, Ws, 's');<br />
<br />
%% Elliptic - Cauer<br />
[n, Wn] = ellipord(Wp, Ws, Ap, As,'s')<br />
[b,a] = ellip(n,Ap,As, Wn, 's');<br />
</syntaxhighlight><br />
:*Ver pag. 204 a 208 de <ref name="SHENOI2006"/><br />
<br />
<br />
;Aula 13 e 14 (5 e 9 set): <br />
*Filtros Analógicos: <br />
:* Transformações de frequência de filtros analógicos <br />
:*passa-baixas (<math> \Omega_p= 1 </math>) -> passa-baixas (<math> \omega_p</math>)<br />
::*Cálculo do protótipo com <math> \Omega_s = \frac{\omega_s}{\omega_p}</math><br />
::*Substituição de variáveis <math> p = \frac{s}{\omega_p}</math><br />
<br />
:*passa-baixas (<math> \Omega_p= 1 </math>) -> passa-altas (<math> \omega_p</math>)<br />
::*Cálculo do protótipo com <math> \Omega_s = \frac{\omega_p}{\omega_s}</math><br />
::*Substituição de variáveis <math> p = \frac{\omega_p} {s}</math><br />
<br />
:*passa-baixas (<math> \Omega_p= 1 </math>) -> passa-faixa (<math> \omega_0 </math> e <math> B </math>)<br />
::*Cálculo do protótipo com <math> \Omega_s = \Bigg|\frac{-\omega_s^2 + \omega_0^2} {B \omega_s}\Bigg|</math><br />
::*Substituição de variáveis <math> p = \frac{s^2 + \omega_0^2} {B s}</math><br />
:: onde <math> B = \omega_{p2} - \omega_{p1}</math> e <math> \omega_0 = \sqrt{\omega_{p2} \omega_{p1}}</math> <br />
<br />
:*passa-baixas (<math> \Omega_p= 1 </math>) -> rejeita-faixa (<math> \omega_0 </math> e <math> B </math>)<br />
::*Cálculo do protótipo com <math> \Omega_s = \Bigg| \frac {B \omega_s} {-\omega_s^2 + \omega_0^2}\Bigg|</math><br />
::*Substituição de variáveis <math> p = \frac {B s} {s^2 + \omega_0^2}</math><br />
:: onde <math> B = \omega_{p2} - \omega_{p1}</math> e <math> \omega_0 = \sqrt{\omega_{p2} \omega_{p1}}</math><br />
<br />
:* Uso das funções [http://www.mathworks.com/help/matlab/ref/semilogx.html semilogx], [http://www.mathworks.com/help/matlab/ref/semilogy.html semilogy],[http://www.mathworks.com/help/matlab/ref/logspace.html logspace], [http://www.mathworks.com/help/matlab/ref/linspace.html linspace].<br />
:*Ver em [http://www.mathworks.com/help/signal/ug/iir-filter-design.html IIR Filter Design], [http://www.mathworks.com/help/signal/ug/special-topics-in-iir-filter-design.html Special Topics in IIR Filter Design]. <br />
::*Funções para projeto do filtro protótipo analógico passa-baixas: [http://www.mathworks.com/help/signal/ref/buttap.html buttap], [http://www.mathworks.com/help/signal/ref/cheb1ap.html cheb1ap], [http://www.mathworks.com/help/signal/ref/cheb2ap.html cheb2ap], [http://www.mathworks.com/help/signal/ref/ellipap.html ellipap]<br />
::*Funções de transformação de frequencia: [http://www.mathworks.com/help/signal/ref/lp2lp.html lp2bp], [http://www.mathworks.com/help/signal/ref/lp2hp.html lp2bs], lp2hp, lp2lp<br />
:*Ver pag. 208 a 218 de <ref name="SHENOI2006"/><br />
<br />
*Exemplos de Filtros Analógicos: <br />
:* Exemplo 1: Filtro passa-baixas (<math> f_p </math> = 941Hz, <math> f_s </math> = 1209 Hz, <math> A_p </math> = 1 dB, <math> A_s </math> = 20 dB)<br />
:* Exemplo 2: Filtro passa-altas (<math> f_p </math> = 1209 Hz, <math> f_s </math> = 941Hz, <math> A_p </math> = 1 dB, <math> A_s </math> = 20 dB)<br />
<!--:* Exemplo 3: Filtro passa-faixa (<math> f_{p1} </math> = 811 Hz, <math> f_{p2} </math> = 895,5 Hz <math> f_{s1} </math> = 770 Hz, <math> f_{s2} </math> = 941 Hz, <math> A_p </math> = 1 dB, <math> A_r </math> = 30 dB)--><br />
:* Exemplo 3: Filtro passa-faixa (<math> f_{p1} </math> = 811 Hz, <math> f_{p2} </math> = 895,5 Hz <math> f_{s1} </math> = 770 Hz, <math> f_{s2} </math> = 1209 Hz, <math> A_p </math> = 1 dB, <math> A_r </math> = 30 dB)<br />
:* Exemplo 4: Filtro rejeita-faixa (<math> f_{p1} </math> = 53 Hz, <math> f_{s1} </math> = 58 Hz, <math> f_{s2} </math> = 62 Hz <math> f_{p2} </math> = 67 Hz, <math> A_p </math> = 2 dB, <math> A_r </math> = 25 dB)<br />
::'''NOTA:''' <br />
:::*No calculo do filtro lembre-se de usar as frequências angulares para <math> \omega_p </math>, <math> \omega_s </math>, <math> B\omega </math>, <math> \omega_0 </math>.<br />
:::*onde <math> f_p </math> (<math> \omega_p </math>) é a frequência de passagem em Hz (rad/s), <math> f_s </math> (<math> \omega_s </math>) é a frequência de rejeição em Hz (rad/s), <math> f_0 </math> (<math> \omega_0 </math>) é a frequência central em Hz (rad/s), <math> B </math> (<math> B\omega </math>) é a largura de banda em Hz (rad/s).<br />
:::*Confira os projetos dos filtros plotando as respostas em frequência dos filtros protótipo H(p) e filtro final H(s) de cada um dos exemplos. <br />
<br />
;Aula 15 (16 set):<br />
*Filtros Digitais: Filtros IIR: transformações do tempo contínuo no tempo discreto<br />
:*[[Transformação Invariante ao Impulso]] (pode ser usada apenas para filtros com forte atenuação em frequência altas, ex: passa-baixas e passa-faixa)<br />
:*[[Transformação Bilinear]] (pode ser usada para todos tipos de filtro) <math> s = 2fa \frac {z-1}{z+1} </math><br />
::*Obter a especificação do filtro em angulo entre 0 e 1, onde 1 corresponde a metade da frequência de amostragem <math> (fa/2) </math><br />
::*Obter o valor desse angulo predistorcido <math> \lambda </math> para compensar a distorção na frequência causada pela transformação bilinear <math> \lambda= 2 tan \left (\frac{\theta \pi}{2} \right ) </math>, onde <math> \theta = \frac{f}{f_a/2} = \frac{\omega}{\omega_a /2} </math><br />
<br />
:*passa-baixas (<math> \Omega_p= 1 </math>) -> passa-baixas (<math> \lambda_p</math>)<br />
::*Substituição de variáveis <math> p = \frac{s}{\lambda_p}</math><br />
::*Cálculo do protótipo com <math> \Omega_s = \frac{\lambda_s}{\lambda_p}</math><br />
<br />
:*passa-baixas (<math> \Omega_p= 1 </math>) -> passa-altas (<math> \lambda_p</math>)<br />
::*Substituição de variáveis <math> p = \frac{\lambda_p} {s}</math><br />
::*Cálculo do protótipo com <math> \Omega_s = \frac{\lambda_p}{\lambda_s}</math><br />
<br />
:*passa-baixas (<math> \Omega_p= 1 </math>) -> passa-faixa (<math> \lambda_0 </math> e <math> B </math>)<br />
::*Substituição de variáveis <math> p = \frac{s^2 + \lambda_0^2} {B s}</math><br />
::*Cálculo do protótipo com <math> \Omega_s = \Bigg|\frac{-\lambda_s^2 + \lambda_0^2} {B \lambda_s}\Bigg|</math><br />
:: onde <math> B = \lambda_{p2} - \lambda_{p1}</math> e <math> \lambda_0 = \sqrt{\lambda_{p2} \lambda_{p1}}</math> <br />
<br />
:*passa-baixas (<math> \Omega_p= 1 </math>) -> rejeita-faixa (<math> \lambda_0 </math> e <math> B </math>)<br />
::*Substituição de variáveis <math> p = \frac {B s} {s^2 + \lambda_0^2}</math><br />
::*Cálculo do protótipo com <math> \Omega_s = \Bigg| \frac {B \lambda_s} {-\lambda_s^2 + \lambda_0^2}\Bigg|</math><br />
:: onde <math> B = \lambda_{p2} - \lambda_{p1}</math> e <math> \lambda_0 = \sqrt{\lambda_{p2} \lambda_{p1}}</math> <br />
::*Ver as funções de discretização usadas no Matlab: [http://www.mathworks.com/help/signal/ref/bilinear.html bilinear], [http://www.mathworks.com/help/signal/ref/impinvar.html impinvar]<br />
<br />
* Realizar os projetos dos exemplos anteriores, considerando uma frequência de amostragem de 8 kHz.<br />
<br />
:*Ver pag. 219 a 229 de <ref name="SHENOI2006"/><br />
:*Ver pag. 403 a 415 e 434 a 435 de <ref name="DINIZ2014"/><br />
<br />
;Aula 16 (19 set):<br />
:* Ver em [http://www.mathworks.com/help/signal/ug/iir-filter-design.html IIR Filter Design]<br />
:* Uso das funções [http://www.mathworks.com/help/signal/ref/buttord.html buttord], [http://www.mathworks.com/help/signal/ref/butter.html butter], [http://www.mathworks.com/help/signal/ref/cheb1ord.html cheb1ord], [http://www.mathworks.com/help/signal/ref/cheby1.html cheby1], [http://www.mathworks.com/help/signal/ref/cheb2ord.html cheb2ord], [http://www.mathworks.com/help/signal/ref/cheby2.html cheby2], [http://www.mathworks.com/help/signal/ref/ellipord.html ellipord], [http://www.mathworks.com/help/signal/ref/ellip.html ellip] para o projeto de filtros IIR digitais (sem o parâmetro ''''s'''').<br />
::O projeto dos filtros digitais IIR baseados na transformada bilinear no Matlab é realizada em dois passos: (1) Determinação da ordem do filtro; (2) Determinação dos coeficientes do numerador <math> b(n) </math> e denominador <math> a(n) </math> de <math> H(z) </math> .<br />
<br />
:* Outros tipos de filtros IIR: [http://www.mathworks.com/help/signal/ref/yulewalk.html yulewalk], [https://www.mathworks.com/help/dsp/ref/iirnotch.html iirnotch], [https://www.mathworks.com/help/dsp/ref/iirpeak.html iirpeak], [https://www.mathworks.com/help/dsp/ref/iircomb.html iircomb], [http://www.mathworks.com/help/signal/ref/maxflat.html maxflat], [http://www.mathworks.com/help/signal/ref/invfreqz.html invfreqz] e outros filtros de [http://www.mathworks.com/help/signal/ug/parametric-modeling.html modelagem paramétrica].<br />
:* Ver funcionamento em [https://www.mathworks.com/help/signal/ug/anti-causal-zero-phase-filter-implementation.html Anti-Causal, Zero-Phase Filter Implementation]), [http://www.mathworks.com/help/signal/ref/filtfilt.html filtfilt], <br />
<br />
<syntaxhighlight lang=matlab><br />
fa = 200;<br />
fN = fa/2;<br />
wo = 60/fN; bw = 10/fN;<br />
[b,a] = iirnotch(wo,bw);<br />
fvtool(b,a);<br />
syms z;<br />
N(z) = poly2sym(b,z);<br />
D(z) = poly2sym(a,z);<br />
H(z) = N(z)/D(z);<br />
pretty(vpa(H(z),3))<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=matlab><br />
fa = 8000;<br />
fN = fa/2;<br />
wo = 941/fN; bw = 100/fN;<br />
[b,a] = iirpeak(wo,bw);<br />
fvtool(b,a);<br />
syms z;<br />
N(z) = poly2sym(b,z);<br />
D(z) = poly2sym(a,z);<br />
H(z) = N(z)/D(z);<br />
pretty(vpa(H(z),3))<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=matlab><br />
fa = 8000; fN = fa/2;<br />
fo = 1000; bw = 20/fN;<br />
[b,a] = iircomb(fa/fo,bw,'peak'); % ou use a flag 'notch'<br />
fvtool(b,a);<br />
syms z;<br />
N(z) = poly2sym(b,z);<br />
D(z) = poly2sym(a,z);<br />
H(z) = N(z)/D(z);<br />
pretty(vpa(H(z),3))<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
===Unidade 3===<br />
{{collapse_top | expand=true | Unidade 3 - Filtros FIR}}<br />
;Aula 16 (23 set):<br />
*Filtros Digitais: Filtros FIR<br />
:*Filtros de fase linear: simétricos e antisimétricos (Tipo 1, 2, 3 e 4) <br />
:*Filtros de fase linear: propriedades (respostas em frequência possíveis, distribuição dos zeros em simetria quadrantal)<br />
* Observar as propriedades dos FIR tipo 1, 2, 3 e 4. Observe a resposta de frequência, fase, atraso de grupo, coeficientes e diagrama de polos e zeros dos filtros abaixo.<br />
<br />
<syntaxhighlight lang=matlab><br />
N = 10;<br />
bi = 2*(rand(1,N)-0.5)<br />
%% Tipo I - LP, HP, BS, BP<br />
b = [bi (2*rand(1,1)-0.5) flip(bi)];<br />
...<br />
%% Tipo II - LP, BP<br />
% tem um zero em -1 <br />
b = [bi flip(bi)];<br />
...<br />
<br />
%% Tipo III - BP<br />
% tem um zero em 1 e -1 <br />
b = [bi 0 -flip(bi)];<br />
...<br />
<br />
%% Tipo IV - BP, HP<br />
% tem um zero em 1 <br />
b = [bi -flip(bi)];<br />
...<br />
</syntaxhighlight><br />
<center><br />
[[Arquivo:FIR_tipo1.png | 800px]]<br />
<br><br />
Figura 1 - Propriedades do filtro FIR de fase linear (Tipo 1)<br />
</center><br />
<br />
====ATUAL====<br />
;Aula 17 (26 set)<br />
:*Coeficientes da série de Fourier de filtros ideias: LP, HP, BP, BS<br />
::*Passa-baixas (''Low-pass'')<br />
::<math>c_\text{LP}(n) = \left \{ \begin{matrix} \frac{\omega_c}{\pi}; & \qquad n = 0 \\ \frac {\sin (\omega_c n)}{\pi n}; & \qquad \left | n \right | > 0 \end{matrix}\right. </math><br />
::*Passa-altas (''High-pass'')<br />
::<math>c_\text{HP}(n) = \left \{ \begin{matrix} 1-\frac{\omega_c}{\pi}; \qquad n = 0 \\ -\frac {\sin (\omega_c n)}{\pi n}; \qquad \left | n \right | > 0 \end{matrix}\right. </math><br />
::*Passa-faixa (''Band-pass'')<br />
::<math>c_\text{BP}(n) = \left \{ \begin{matrix} \frac{\omega_{c2}-\omega_{c1}}{\pi}; \qquad n = 0 \\ \frac {\sin (\omega_{c2} n)- \sin (\omega_{c1} n)}{\pi n}; \qquad \left | n \right | > 0 \end{matrix}\right. </math><br />
::*Rejeita-banda (''Band-stop'')<br />
::<math>c_\text{BS}(n) = \left \{ \begin{matrix} 1-\frac{\omega_{c2}-\omega_{c1}}{\pi}; \qquad n = 0 \\ -\frac {\sin (\omega_{c2} n)- \sin (\omega_{c1} n)}{\pi n}; \qquad \left | n \right | > 0 \end{matrix}\right. </math><br />
:*Janela retangular, fenômeno de Gibbs<br />
<br />
:*Estudar no Matlab as funções [http://www.mathworks.com/help/signal/ref/wintool.html wintool], [http://www.mathworks.com/help/signal/ref/wvtool.html wvtool], [http://www.mathworks.com/help/signal/ref/window.html window]<br />
<br />
:*Ver pag. 249 a 256 de <ref name="SHENOI2006"/><br />
:*Ver [https://www.mathworks.com/help/signal/ug/fir-filter-design.html FIR Filter Design]<br />
<br />
:*Uso de funções de janelamento temporal no projeto de filtros digitais. <br />
:*Tipos de janelas temporais usadas no projeto de filtros digitais.<br />
::*Retangular<br />
::<math>w(n)=1; \qquad -M \le n \le M </math><br />
<br />
::*Bartlett<br />
::<math>w(n)= 1 - \frac{\left | n \right |}{M+1}; \qquad -M \le n \le M </math><br />
<br />
::*Hanning<br />
::<math>w(n) = 0.5 + 0.5 \cos \left( \frac{2\pi n}{2M+1} \right), -M \le n \le M</math><br />
<br />
::*Hamming<br />
::<math>w(n) = 0.54 + 0.46 \cos\left(\frac{2\pi n}{2M+1}\right); \qquad -M \le n \le M</math><br />
<br />
::*Blackman<br />
::<math>w(n) = 0.42 + 0.5 \cos\left(\frac{2\pi n}{2M+1}\right) + 0.08\cos\left(\frac{4\pi n}{2M+1}\right); \qquad -M \le n \le M</math><br />
* em todas as janelas <math>w\left ( n \right ) = 0 </math> quando <math> \left | n \right | \ge M</math><br />
::onde <math>M </math> é <math>N/2</math> para <math>N</math> par e <math>(N+1)/2</math> para <math>N</math> impar<br />
*Uso de janelas fixas no Matlab : [http://www.mathworks.com/help/signal/ref/rectwin.html rect], [http://www.mathworks.com/help/signal/ref/triang.html triang], [http://www.mathworks.com/help/signal/ref/bartlett.html bartlett], [http://www.mathworks.com/help/signal/ref/hann.html hann], [http://www.mathworks.com/help/signal/ref/hamming.html hamming], [http://www.mathworks.com/help/signal/ref/blackman.html blackman], [http://www.mathworks.com/help/signal/ref/blackmanharris.html blackmanharris], [http://www.mathworks.com/help/signal/ref/nuttallwin.html nuttall].<br />
::ver também [http://mathworld.wolfram.com/ApodizationFunction.html apodization function]<br />
<syntaxhighlight lang=matlab><br />
L = 64; <br />
wvtool(rectwin(L), triang(L), bartlett(L), hann(L), hamming(L), blackman(L), blackmanharris(L), nuttallwin(L));<br />
</syntaxhighlight><br />
<br />
;Tabela 5.1:<br />
{| class="wikitable" border="1" cellpadding="3" cellspacing="0" style="text-align:center; font-size:100%" bgcolor="#efefef"<br />
! scope="col" width=25% align="center"| Janela<br />
! scope="col" width=10% align="center"| <math>A_{sl}</math><br />
! scope="col" width=10% align="center"| <math>A_{s}</math><br />
! scope="col" width=10% align="center"| <math>\Delta \omega</math><br />
{{tabFIRwindow | Retangular | 13.3| 20.33 | 0.92<math>\pi</math>/M }}<br />
{{tabFIRwindow | Triangular | 26.6| 27.41 | }}<br />
{{tabFIRwindow | Bartlett | 26.5| 27.48 | }}<br />
{{tabFIRwindow | Hann | 31.5| 44.03 | 3.11<math>\pi</math>/M}}<br />
{{tabFIRwindow | Bartlett-Hanning | 35.9| 40.77| }}<br />
{{tabFIRwindow | Hamming | 42.5| 54.08 | 3.32<math>\pi</math>/M}}<br />
{{tabFIRwindow | Bohman | 46.0| 51.84 | 7.01<math>\pi</math>/M}}<br />
{{tabFIRwindow | Parzen | 53.1| 56.89 |}}<br />
{{tabFIRwindow | Blackman | 58.1| 75.25 | 5.56<math>\pi</math>/M}}<br />
{{tabFIRwindow | Flat Top | 88.0| 106.3| }}<br />
{{tabFIRwindow | Blackman-Harris | 92.1| 108.8 |}}<br />
{{tabFIRwindow | Nutfall | 93.8| 109.7|}}<br />
|}<br />
:*Dados acima obtidos para um filtro passa baixas de ordem N = 64 com <math>\omega_{c} = 0.5 \pi</math> <br />
:*Projeto de filtro FIR utilizando janelas temporais fixas.<br />
<br />
::* Exemplo de projeto<br />
Projetar um filtro passa baixas usando uma janela temporal fixa (verificar a janela que atende a especificação)<br />
wp = 0.2*pi; Ap = 0.2 dB; Gp = 0 dB<br />
ws = 0.3*pi; As = 60 dB;<br />
::* Informar qual o tipo de janela, a ordem obtida, e o valor de ''wc'' do projeto final <br />
<br />
::* Exemplo de projeto<br />
Projetar um filtro LP usando uma janela temporal fixa (hamming, bartlett-hanning, hanning).<br />
wp = 0.4*pi; Ap = 1 dB; Gp = 0 dB<br />
ws = 0.6*pi; As = 40 dB;<br />
::* Comparar os 3 tipos de janela, a ordem obtida, e o valor de ''wc'' em cada projeto.<br />
<br />
:: Use como uma estimativa inicial os valores da Tabela 5.1 pag. 268.<br />
::* PASSO 1 - Escolher o tipo de janela de acordo com a atenuação do lóbulo lateral Asl e As.<br />
::* PASSO 2 - Estimar a ordem N1 do filtro considerando os parâmetros Dw<br />
::* PASSO 3 - Calcule os coeficientes clp do filtro LP , calcule os valores da janela w e obtenha a resposta ao impulso do filtro h = clp * w.<br />
::* PASSO 4 - Ajuste o ganho do filtro para que a resposta na banda de passagem fique abaixo da especificação maxima.<br />
::* PASSO 5 - Verifique o valor real de Dwr = wAs-wAp, e faça a correção da ordem do filtro em função do desvio constatado. N2 = N*Dwr/Dw.<br />
::* PASSO 6 - Corrija o valor de projeto dos coeficientes Clp do filtro ideal, a janela e a resposta ao impulso.<br />
::* Repita o PASSO 3 até 6, até obter um filtro que atenda as especificações de Dw.<br />
::* PASSO 7 - Desloque a frequência de corte wc de modo a obter o valor correto de wp. wc2 = wp + (wp-wAp).<br />
:* Projeto de filtro FIR.<br />
::*Projete os dois filtros projetados anteriormente como IIR, utilizando 3 janelas diferentes. Compare os filtros obtidos com os filtros IIR.<br />
<syntaxhighlight lang=matlab><br />
N = <ordem><br />
h_fir = fir1(N,Wn,hamming(N+1));<br />
[Hw,w] =freqz(h_fir);<br />
plot(w/pi,20*log10(abs(Hw)))<br />
title(['hamming N = ' num2str(N)])<br />
%fvtool(h_fir,1)<br />
</syntaxhighlight><br />
<br />
:*Ver pag. 256 a 265 de <ref name="SHENOI2006"/><br />
:*Ver artigos:<br />
::*[https://ieeexplore-ieee-org.ez130.periodicos.capes.gov.br/stamp/stamp.jsp?tp=&arnumber=21693 A new window and comparison to standard windows] Yeong Ho Ha ; Pearce, J.A. IEEE Transactions on Acoustics, Speech, and Signal Processing, Feb. 1989, Vol.37(2), pp.298-301.<br />
::*[https://ieeexplore.ieee.org.ez130.periodicos.capes.gov.br/stamp/stamp.jsp?arnumber=1163506 Some windows with very good sidelobe behavior] Nuttall, A. IEEE Transactions on Acoustics, Speech, and Signal Processing, February 1981, Vol.29(1), pp.84-91<br />
;Aula 18:<br />
* Projetar os filtros LP, HP e BP de acordo com as especificações dadas.<br />
<br />
;Aula 19 (07 out):<br />
*Filtros Digitais: Filtros FIR<br />
*Projeto de filtro FIR utilizando janelas temporais ajustáveis<br />
:*Uso de janelas ajustáveis no Matlab: [http://www.mathworks.com/help/signal/ref/kaiser.html kaiser], [http://www.mathworks.com/help/signal/ref/chebwin.html chebyshev], [http://www.mathworks.com/help/signal/ref/gausswin.html gauss], [http://www.mathworks.com/help/signal/ref/tukeywin.html tukey], [http://www.mathworks.com/help/signal/ref/taylorwin.html taylor].<br />
<syntaxhighlight lang=matlab><br />
L = 64; <br />
r = 60; % Chebyshev e Tukey<br />
alpha = 3; % Gauss<br />
betha = 8; % Kaiser<br />
nbar = 10; % Taylor<br />
wvtool(kaiser(L,betha), chebwin(L,r), gausswin(L,alpha),tukeywin(L,r), taylorwin(L,nbar,-r));<br />
</syntaxhighlight><br />
Para a janela de Kaiser, a estimação do fator <math>\beta </math> e da ordem do filtro <math> N </math> são obtidos por:<br />
<br />
<math>\beta = \left \{ \begin{matrix} 0.1102 (\alpha-8.7), & \alpha > 50, \\ 0.5842 (\alpha- 21)^{0.4} + 0.07886 (\alpha- 21) , & 50 \ge \alpha \ge 21, \\ 0, & \alpha < 21. \end{matrix}\right.</math> <br />
<br />
<math> N = \frac {\alpha - 8} {2.285 \Delta \omega} + 1. </math><br />
<br />
onde <math> \alpha </math> é a atenuação do lóbulo lateral e <math> \Delta \omega </math> é a largura da banda de transição em rad/amostra.<br />
<br />
A janela de Kaiser é definida por:<br />
<br />
<math> w(n) = \frac{I_0 \left(\beta \sqrt{1-(\frac{n-\alpha}{\alpha})^2} \right)}{I_0(\beta)} </math><br />
<br />
onde :<math> I_0(x) = 1+ \sum_{k=1}^\infty {\left( \frac{(\frac{x}{2})^k}{k!}\right)}^2 </math> é a função de Bessel de ordem zero [http://mathworld.wolfram.com/ModifiedBesselFunctionoftheFirstKind.html]<br />
<br />
Utilizando o Matlab é possível estimar esses valores utilizando a função kaiserord. Exemplo da obtenção de um filtro passa baixa com <math> f_{pass} = 1000 Hz </math>, <math> f_{stop} = 1500 Hz </math>, <math> f_{amostragem} = 8000 Hz </math> atenuação de 40 dB na "stopband"<br />
<br />
<syntaxhighlight lang=matlab><br />
fsamp = 8000;<br />
fcuts = [1000 1500];<br />
mags = [1 0];<br />
devs = [0.01 0.01];<br />
[n,Wn,beta,ftype] = kaiserord(fcuts,mags,devs,fsamp);<br />
</syntaxhighlight><br />
<br />
Com os parâmetros é possível projetar o filtro usando a função fir1, que utiliza o método da janela para o projeto do filtro.<br />
<br />
<!--<br />
<syntaxhighlight lang=matlab><br />
h_fir = fir1(n,Wn,ftype,kaiser(n+1,beta),'noscale');<br />
[Hw,w] =freqz(h_fir);<br />
plot(w*fsamp/2/pi,20*log10(abs(Hw)))<br />
title(['Kaiser filter N = ' num2str(n)])<br />
%fvtool(h_fir,1)<br />
</syntaxhighlight><br />
:*Ver as funções [http://www.mathworks.com/help/signal/ref/fir1.html fir1], [http://www.mathworks.com/help/signal/ref/kaiserord.html kaiserord] do Matlab.<br />
:*Ver pag. 266 a 273 de <ref name="SHENOI2006"/><br />
:* Uso das funções [http://www.mathworks.com/help/signal/ref/window.html window] e [http://www.mathworks.com/help/signal/ref/fir1.html fir1] do Matlab para projeto de filtro FIR<br />
<br />
<code><br />
%% Exemplo de Filtro <br />
wp1 = 0.1 \pi;<br />
ws1 = 0.2 \pi;<br />
ws2 = 0.6 \pi;<br />
wp2 = 0.8 \pi;<br />
Ap = 1 dB;<br />
Ar = 40 dB;<br />
</syntaxhighlight><br />
<!--<br />
<br />
;Aula 22 (08 mai):<br />
*Filtros Digitais: Filtros FIR<br />
:*Filtro de Parks-McClellan. Funções [http://www.mathworks.com/help/signal/ref/firpm.html firpm] e [http://www.mathworks.com/help/signal/ref/firpmord.html firpmord].<br />
:*[http://mathworld.wolfram.com/RemezAlgorithm.html Remez exchange algorithm] - o básico em Wolfram Alpha<br />
:*[http://eeweb.poly.edu/iselesni/EL713/remez/remez.pdf Remez exchange algorithm] - o detalhe com implementação em Matlab. Como resolver as anomalias na banda de transição.<br />
:*[http://www.ee.ic.ac.uk/hp/staff/dmb/courses/DSPDF/00700_OptimalFIR.pdf]<br />
<br />
*Projeto de filtro FIR <br />
:*projetar os filtros usando: 1) Janela fixa 2) Janela ajustável 3) Parks-McClellan.<br />
:*garantir que o filtro seja de menor ordem em cada caso, mas que esteja dentro das especificações.<br />
:*se necessário ajustar os valores de fs, fp, Ap, As, e a ordem do filtro, indicando o critério utilizado para o ajuste.<br />
<br />
<br />
<syntaxhighlight lang=matlab><br />
%% Projetar o filtro passa baixas <br />
fp = 1200 Hz;<br />
fs = 1380 Hz;<br />
fa = 8000 Hz;<br />
Ap = 1 dB;<br />
Ar = 50 dB;<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=matlab><br />
%% Projetar o filtro passa altas <br />
fs = 1200 Hz;<br />
fp = 1380 Hz;<br />
fa = 8000 Hz;<br />
Ap = 1 dB;<br />
Ar = 50 dB;<br />
</syntaxhighlight><br />
<br />
;Aula 23 (10 mai)<br />
<br />
*Projeto de filtro FIR <br />
:*projetar os filtros usando: 1) Janela fixa 2) Janela ajustável 3) Parks-McClellan.<br />
:*garantir que o filtro seja de menor ordem em cada caso, mas que esteja dentro das especificações.<br />
:*se necessário ajustar os valores de fs, fp, Ap, As, e a ordem do filtro, indicando o critério utilizado para o ajuste.<br />
<br />
<syntaxhighlight lang=matlab><br />
%% Projetar o filtro passa faixa <br />
fs1 = 800 Hz;<br />
fp1 = 900 Hz;<br />
fp2 = 1000 Hz;<br />
fs2 = 1300 Hz;<br />
fa = 8000 Hz;<br />
Ap = 1 dB;<br />
Ar = 50 dB;<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=matlab><br />
%% Projetar o filtro rejeita faixa <br />
fp1 = 800 Hz;<br />
fs1 = 900 Hz;<br />
fs2 = 1000 Hz;<br />
fp2 = 1300 Hz;<br />
fa = 8000 Hz;<br />
Ap = 1 dB;<br />
Ar = 50 dB;<br />
</syntaxhighlight><br />
<br />
Entrega do trabalho de projeto e análise de filtros digitais (05 de junho de 2019, as 9:40)<br />
<br />
<!--<br />
;Aula 22 (09 out)<br />
:*Uso do [http://la.mathworks.com/help/dsp/ug/use-fdatool-with-dsp-system-toolbox-software.html] para projeto de filtro IIR, FIR equiripple e FIR com janela.<br />
*Uso do [http://la.mathworks.com/help/dsp/gs/design-and-implement-a-filter.html] no Simulink.<br />
<br />
;Aula 23 (23 out): <br />
:*Uso do Simulink<br />
::* Uso dos blocos de simulação [http://www.mathworks.com/help/simulink/slref/sinewave.html sinewave], [http://www.mathworks.com/help/simulink/slref/floatingscope.html scope] e [http://www.mathworks.com/help/dsp/ref/spectrumanalyzer.html Spectrum Analyzer].<br />
::* Outros blocos [http://www.mathworks.com/help/simulink/slref/mux.html mux], [http://www.mathworks.com/help/simulink/slref/demux.html demux], [http://www.mathworks.com/help/simulink/slref/add.html sum], [http://www.mathworks.com/help/simulink/slref/product.html product].<br />
::*[https://www.mathworks.com/help/simulink/gs/create-a-simple-model.html?s_cid=learn_doc Create Simple Model] [https://www.mathworks.com/videos/getting-started-with-simulink-118723.html]<br />
<br />
;Aula 24 (25 out): <br />
:*Uso do Simulink<br />
:*Tipos de Solver ([http://www.mathworks.com/help/simulink/ug/choosing-a-solver.html Choose a Solver]).<br />
:*Diferença entre processamento por amostra e processamento por quadro ([http://www.mathworks.com/help/dsp/ug/sample-and-frame-based-concepts.html Sample- and Frame-Based Concepts]).<br />
:*Exemplos: <br />
::*[https://www.mathworks.com/help/dsp/ug/filter-frames-of-a-noisy-sine-wave-signal-in-simulink.html Filtragem] - frame based<br />
::*[[Modulações Analógicas]]<br />
::*[[Amostragem de sinais]]<br />
::*[https://www.mathworks.com/help/dsp/ug/digital-filter-design-block.html Digital Filter Design Block], [https://www.mathworks.com/help/dsp/ref/digitalfilterdesign.html], [https://www.mathworks.com/help/dsp/ref/filterrealizationwizard.html]<br />
<br />
:::*É importante ler informações complementares sobre o [http://www.mathworks.com/help/simulink/gui/solver-pane.html Solver Pane], [http://www.mathworks.com/help/simbio/ug/simulating-models.html Model Simulation], [http://www.mathworks.com/help/simulink/ug/types-of-solvers.html Types of Solvers], [http://www.mathworks.com/help/simevents/ug/solvers-for-simevents-models.html Solvers for Discrete-Event Systems].<br />
<br />
:::*É importante ler informações complementares sobre, [http://www.mathworks.com/help/simulink/sample-time.html Tempo de amostragem (Time Sample)], [http://www.mathworks.com/help/simulink/ug/how-to-view-sample-time-information.html View Sample Time Information], [http://www.mathworks.com/help/simulink/slref/concatenate.html Vector Concatenate, Matrix Concatenate]<br />
Para configurar o Simulink para sistemas discretos execute o comando dspstartup.m antes de abrir um novo modelo.<br />
<br />
;Aula 25 (ESTUDOS EXTRACLASSE): <br />
para compensar a palestra da MCC<br />
--><br />
{{collapse bottom}}<br />
<br />
==Avaliações==<br />
* Entrega dos diversas Atividades Extraclasse ao longo do semestre.<br />
* Provas escritas A1 e A2<br />
* Entrega do Projeto Final. O projeto é avaliado nos quesitos: <br />
:1) Implementação do Sistema, <br />
:2) Documentação, <br />
:3) Avaliação Global do aluno no projeto.<br />
<br />
*Entrega dos Atividades Extraclasse ao longo do semestre AE1 a AE(N). A entrega, detalhes e prazos de cada AE serão indicados na plataforma Moodle<br />
<br />
<br />
==Referências Bibliográficas==<br />
<references/><br />
<br />
{{ENGTELECO}}</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=Circuitos_L%C3%B3gicos_Aritm%C3%A9ticos&diff=162066Circuitos Lógicos Aritméticos2019-10-07T14:26:58Z<p>127.0.0.1: /* Simulação Temporal com o QSIM */</p>
<hr />
<div>=Objetivos=<br />
*Construir testar um circuito somador completo (FA -full adder) a partir de portas lógicas usando o diagrama esquemático do QUARTUS II.<br />
*Fazer a simulação funcional do circuito com o QSIM.<br />
*Criar componentes após o teste e reutiliza-los em projetos maiores.<br />
*Construir um somador de 4 bits usando os FA como componente.<br />
*Construir um multiplicador de 4 bits usando os FA como componente.<br />
*Construir um circuito que realiza o complemento de 2.<br />
*Construir um somador/subtrator de 4 bits usando o somador de 4 bits e complemento de 2 como componentes. (TAREFA ADICIONAL PARA OS ALUNOS)<br />
*Preparar o circuito para programação e implementação do hardware FPGA do kit DE2-115.<br />
*Escrever relatório técnico do projeto seguindo as normas ABNT<br />
<br />
=Somador Completo=<br />
==Diagrama Esquemático==<br />
#Crie uma pasta '''/home/aluno/somador'''.<br />
#Abra o Quartus II e crie um novo projeto na pasta '''somador''' com nome FullAdder, utilizando a família family='''Cyclone IV E''' com o dispositivo device='''EP4CE115F29C7''' ou '''Family = Cyclone IV E''' com dispositivo '''device = EP4CE30F23C7'''.<br />
#Crie um novo diagrama esquemático (''File >> New >> Block Diagram/Schematic File''), conforme figura abaixo: <center> [[Arquivo:FA-bdf.png|600px]] </center><br />
#Salve o arquivo como FullAdder.bdf.<br />
#Faça a Análise e Síntese do projeto e tenha certeza que tudo esteja funcionando perfeitamente através da compilação do projeto.<br />
<br />
==Criar o componente FullAdder==<br />
#Crie um simbolo para este circuito, selecionando na IDE do Quartus II o diagrama esquemático e [File > Create/Update > Create Symbol Files for Current File] > [Save] > [OK].<br />
#Note que um novo simbolo estará disponível para uso no diagrama esquemático com o nome FullAdder [Symbol >> Project >> FullAdder]<br />
<br />
<center><br />
[[Arquivo:FA-bsf.png|thumb|150px]]<br />
</center><br />
<br />
==Simulação funcional com o QSIM==<br />
#Abra o editor de forma de onda do simulador QSIM (File > New > University Programa VWF) (v 13.0 e 13.1). <br />
#Defina o tempo de simulação (Edit > Set End Time ...) = 200 ns.<br />
#Importe todos os nós de lista do projeto (Edit > Insert > Insert Node or Bus) > [Node Finder] > [List] > [>>] > [OK] > [OK].<br />
#Desenhe a forma de onda dos sinais de entrada conforme mostrado na figura abaixo, e salve com o nome TesteFA.vwf. [[Arquivo:FA-SIM_IN.png|800 px]]<br />
#Indique que o QSIM será usado na simulação (Simulation > Options > (x) Quartus II Simulator) > [OK] > [OK] (v. 13.0)<br />
#Faça a simulação funcional do circuito lógico usando o sinal criado (Simulation > Run Functional Simulation)<br />
#O resultado da simulação deve corresponder a um somador completo. <br />
#Note que os bits das entradas estão agrupados e definidos como RADIX "Binary". Para isso selecione os sinais [Edit > Grouping] [Group name = IN] > [Radix = Binary] > [OK].<br />
#Note que os bits das saídas estão agrupados e definidos como RADIX = "Decimal sem sinal". Para isso selecione os sinais [Edit > Grouping] [Group name = OUT] > [Radix = Unsigned Decimal] > [OK].<br />
<br />
[[Arquivo:FA-SIM.png|800 px]]<br />
<br />
==Análise dos resultados==<br />
#Analise o resultado preenchendo a tabela-verdade abaixo:<center><br />
{| border="1" cellpadding="5" cellspacing="0" style="text-align: center;"<br />
! colspan="3" style="background: #efefef;" | Entradas<br />
! colspan="2" style="background: #ffdead;" | Saídas<br />
|-<br />
!width="40"| cin <br />
!width="40"| a <br />
!width="40"| b <br />
!width="40"| s <br />
!width="40"| cout <br />
|-<br />
| 0 || 0 || 0 || || |<br />
|- <br />
| 0 || 0 || 1 || || |<br />
|- <br />
| 0 || 1 || 0 || || | <br />
|-<br />
| 0 || 1 || 1 || || | <br />
|-<br />
| 1 || 0 || 0 || || | <br />
|-<br />
| 1 || 0 || 1 || || | <br />
|-<br />
| 1 || 1 || 0 || || | <br />
|-<br />
| 1 || 1 || 1 || || | <br />
|}<br />
</center><br />
<br />
=Somador de 4 bits=<br />
==Diagrama Esquemático==<br />
#Crie um novo diagrama (File >> New >> Block Diagram/Schematic File) e insira o diagrama esquemático do somador completo, utilizando o componente FullAdder criado anteriormente. <center> [[Arquivo:Somador4bits-bdf.png|800px]] </center><br />
#Salve o arquivo como Somador4bits.bdf na mesma pasta do '''somador'''.<br />
#Mude o Top Level para este circuito (Aba Files >> tecla direita do mouse em Somador4bits >> Set as Top-Level Entity).<br />
#Faça a Análise e Síntese do projeto.<br />
#Crie um simbolo para este módulo, selecionando na IDE do Quartus II o diagrama esquemático e [File > Create/Update > Create Symbol Files for Current File] > [Save] > [OK].<br />
<center><br />
[[Arquivo:Somador4bits-bsf.png|thumb|150px]]<br />
</center><br />
<br />
==Simulação funcional com o QSIM==<br />
#Abra o editor de forma de onda do simulador QSIM (File > New > University Programa VWF). <br />
#Defina o tempo de simulação (Edit > Set End Time ...) = 200 ns.<br />
#Importe todos os nós de lista do projeto (Edit > Insert > Insert Node or Bus) > [Node Finder] > [List] > [>>] > [OK] > [OK].<br />
#Note que os bits das entradas e das saídas estão agrupados e definidos como RADIX "Unsigned Decimal". Para isso selecione os sinais a0, a1, a2, e a3 [Edit > Grouping] [Group name = A] > [Radix = Unsigned Decimal], b0, b1, b2 e b3 [Group name = B] > [Radix = Unsigned Decimal] e s0, s1, s2 e s3 [Group name = S] > [Radix = Unsigned Decimal]> [OK].<br />
#Note que ao fazer este procedimento os bits estão provavelmente na ordem x0,x1,x2,x3. Isso implica que o simulador está interpretando o Vetor X como sendo x3 o LSB e x0 o MSB. Normalmente queremos que o x0 seja o LSB, então é necessário trocar a ordem. [Edit > Reverse Group or Bus Bit Order]<br />
#Gere uma forma de onda dos sinais de entrada semelhante a mostrado na figura abaixo (Use a função [Randon Value] em A e B, e salve com o nome TesteSomador4bits.vwf. [[Arquivo:S4b-SIM_IN.png|800 px]]<br />
#Indique que o QSIM será usado na simulação (Simulation > Options > (x) Quartus II Simulator) > [OK] > [OK]<br />
#Faça a simulação funcional do circuito lógico usando o sinal criado (Simulation > Run Functional Simulation)<br />
#O resultado da simulação deve corresponder a um somador completo. <br />
[[Arquivo:S4b-SIM.png|800 px]]<br />
<br />
==Análise dos resultados==<br />
*Analise os resultados preenchendo a tabela abaixo:<br />
<!--<br />
<center><br />
{| border="1" cellpadding="5" cellspacing="0" style="text-align: center;"<br />
! colspan="3" style="background: #efefef;" | Entradas<br />
! colspan="2" style="background: #ffdead;" | Saídas<br />
! style="background: #00dead;" | x<br />
! colspan="3" style="background: #efefef;" | Entradas<br />
! colspan="2" style="background: #ffdead;" | Saídas<br />
|-<br />
!width="40"| cin <br />
!width="40"| A <br />
!width="40"| B <br />
!width="40"| S <br />
!width="40"| cout <br />
!width="5" style="background: #00dead;"| x<br />
!width="40"| cin <br />
!width="40"| A <br />
!width="40"| B <br />
!width="40"| S <br />
!width="40"| cout <br />
|-<br />
| || || || || || x || || || || || |<br />
|-<br />
| || || || || || x || || || || || |<br />
|-<br />
| || || || || || x || || || || || |<br />
|-<br />
| || || || || || x || || || || || |<br />
|-<br />
| || || || || || x || || || || || |<br />
|-<br />
| || || || || || x || || || || || |<br />
|-<br />
| || || || || || x || || || || || |<br />
|-<br />
| || || || || || x || || || || || |<br />
|-<br />
| || || || || || x || || || || || |<br />
|}<br />
</center><br />
--><br />
<br />
<center><br />
{| border="1" cellpadding="5" cellspacing="0" style="text-align: center;"<br />
! colspan="3" style="background: #efefef;" | Entradas<br />
! colspan="2" style="background: #ffdead;" | Saídas<br />
|-<br />
!width="40"| cin <br />
!width="40"| A <br />
!width="40"| B <br />
!width="40"| S <br />
!width="40"| cout <br />
|-<br />
| . || || || || |<br />
|-<br />
| . || || || || |<br />
|-<br />
| . || || || || |<br />
|-<br />
| . || || || || |<br />
|-<br />
| . || || || || |<br />
|-<br />
| . || || || || |<br />
|-<br />
| . || || || || |<br />
|-<br />
| . || || || || |<br />
|-<br />
| . || || || || |<br />
|-<br />
| . || || || || |<br />
|-<br />
| . || || || || |<br />
|-<br />
| . || || || || |<br />
|}<br />
</center><br />
<br />
==Simulação Temporal com o QSIM==<br />
*Mude a família lógica para que permita a simulação temporal (as famílias mais avançadas não admitem): Assignments >> Device >> Family: Cyclone II E e Available Devices: EP2C5AF256A7 >> OK<br />
*Compile o circuito [Processing > Start Compilation] > após alguns minutos [OK]. Confira o [Compilation Report], verificando que o circuito e dispositivo corretos foram utilizados na compilação.<br />
*Abra o arquivo TesteSomador4bits.vwf e faça a simulação temporal do circuito lógico usando o sinal anteriormente já criado (Simulation > Run Timing Simulation).<br />
*O resultado da simulação deve corresponder a um somador completo com ''glitches'' e um atraso no sinal de saída.<br />
*Dê zoom nos ''glitches'' e analise-os.<br />
[[Arquivo:S4b-SIM-timing.png|800 px]]<br />
<br />
==Análise dos resultados==<br />
*Identifique as diferenças entre os sinais gerados na simulação funcional e na simulação temporal.<br />
*Responda as seguintes questões:*<br />
;Como este tipo de somador deveria ser utilizado? <br />
;Meça o atraso do resultado em relação a entrada? Considere a resposta após o término dos ''gliches''.<br />
;Por que esse atraso acontece?<br />
;Quantas somas por segundo o circuito pode realizar?<br />
;Apresente alguma solução utilizar esse circuito mesmo com o atraso no resultado.<br />
;Que tipo de outro circuito pode ser utilizado para fazer a soma de 4 bits?<br />
<br />
=Multiplicador de 4 bits=<br />
==Diagrama Esquemático==<br />
Abra o Quartus II e insira o diagrama esquemático do módulo básico do multiplicador, utilizando o componente FullAdder criado anteriormente.<br />
<center><br />
[[Arquivo:ModuloBMultiplier-bdf.png|600px]]<br />
</center><br />
<br />
<center><br />
[[Arquivo:ModuloBMultiplier-bsf.png|thumb|150px]]<br />
</center><br />
*Salve o arquivo como ModuloBMultiplicador.bdf na mesma pasta do PROJ2.<br />
*Mude o Top Level para este circuito. Após isso faça a Análise e Síntese do projeto.<br />
*Crie um simbolo para este módulo, selecionando na IDE do Quartus II o diagrama esquemático do ModuloBMultiplicador > [File > Create/Update > Create Symbol Files for Current File] > [Save] > [OK].<br />
Abra um novo diagrama esquematico no Quartus II e insira o circuito digital abaixo utilizando os componentes FullAdder e ModuloBMultiplicador criados anteriormente.<br />
<br />
<center><br />
[[Arquivo:Multiplier4bits-bdf.png|800px]]<br />
</center><br />
<br />
*Salve o arquivo como Multiplicador4bits.bdf na mesma pasta do PROJ2.<br />
*Mude o Top Level para este circuito. Após isso faça a Análise e Síntese do projeto.<br />
<br />
==Simulação funcional com o QSIM==<br />
*Abra o editor de forma de onda do simulador QSIM (File > New > University Programa VWF). <br />
*Defina o tempo de simulação (Edit > Set End Time ...) = 1000 ns.<br />
*Importe todos os nós de lista do projeto (Edit > Insert > Insert Node or Bus) > [Node Finder] > [List] > [>>] > [OK] > [OK].<br />
*Gere uma forma de onda dos sinais de entrada semelhante a mostrado na figura abaixo (Use a função [Randon Value] em A e B, e salve com o nome TesteMultiplicador4bits.vwf.<br />
*Note que os bits das entradas e saídas estão agrupados em ordem reversa e definidos como RADIX = "Decimal sem sinal"<br />
[[Arquivo:M4b-SIM_IN.png|800 px]]<br />
<br />
*Indique que o QSIM será usado na simulação (Simulation > Options > (x) Quartus II Simulator) > [OK] > [OK]<br />
*Faça a simulação funcional do circuito lógico usando o sinal criado (Simulation > Run Functional Simulation)<br />
*O resultado da simulação deve corresponder a um somador completo. <br />
[[Arquivo:M4b-SIM.png|800 px]]<br />
<br />
==Análise dos resultados==<br />
*Analise os resultados preenchendo a tabela abaixo, e conferindo em uma calculadora:<br />
<br />
<center><br />
{| border="1" cellpadding="5" cellspacing="0" style="text-align: center;"<br />
! colspan="2" style="background: #efefef;" | Entradas<br />
! colspan="1" style="background: #ffdead;" | Saídas<br />
! style="background: #00dead;" | x<br />
! colspan="2" style="background: #efefef;" | Entradas<br />
! colspan="1" style="background: #ffdead;" | Saídas<br />
|-<br />
!width="40"| A <br />
!width="40"| B <br />
!width="80"| P <br />
!width="5" style="background: #00dead;"| x<br />
!width="40"| A <br />
!width="40"| B <br />
!width="80"| P <br />
|-<br />
| || || || x || || || |<br />
|-<br />
| || || || x || || || |<br />
|-<br />
| || || || x || || || |<br />
|-<br />
| || || || x || || || |<br />
|-<br />
| || || || x || || || |<br />
|-<br />
| || || || x || || || |<br />
|-<br />
| || || || x || || || |<br />
|-<br />
| || || || x || || || |<br />
|-<br />
| || || || x || || || |<br />
|-<br />
| || || || x || || || |<br />
|}<br />
</center><br />
<br />
==Simulação Temporal com o QSIM==<br />
*Compile o circuito [Processing > Start Compilation] > após alguns minutos [OK]. Confira o [Compilation Report], verificando que o circuito correto foi compilado e anote o número de elementos lógicos e o total de pinos (16 -> 4 entradas A, 4 entradas B, 8 saidas P).<br />
*Abra o arquivo TesteMultiplicador4bits.vwf e faça a simulação temporal do circuito lógico usando o sinal anteriormente já criado (Simulation > Run Timing Simulation)<br />
*O resultado da simulação deve corresponder a um multiplicador de 4 bits com ''gliches'' e um atraso no sinal de saída. <br />
[[Arquivo:M4b-SIM-timing.png|800 px]]<br />
==Análise dos resultados==<br />
*Identifique as diferenças entre os sinais gerados na simulação funcional e na simulação temporal.<br />
*Responda as seguintes questões:<br />
;Como este tipo de multiplicar deveria ser utilizado? <br />
;Meça o atraso do resultado em relação a entrada? Considere a resposta após o término dos ''gliches''.<br />
;Determine o atraso para 4 valores diferentes de multiplicação. Existem diferença nos atrasos dessas operações?<br />
;Por que esse atraso acontece?<br />
;Quantas multiplicações por segundo o circuito pode realizar?<br />
;Compare o tempo do atraso do somador de 4 bits com o multiplicador de 4 bits.<br />
;De que outra forma a mesma multiplicação poderia ser feita?<br />
<br />
=Complemento de 2=<br />
==Diagrama Esquemático==<br />
Abra o Quartus II e insira o diagrama esquemático do módulo básico do complementador de 2.<br />
<center><br />
[[Arquivo:Complemento2-bdf.png|600px]]<br />
</center><br />
<br />
*Salve o arquivo como Complemento2.bdf na mesma pasta do PROJ2.<br />
*Mude o Top Level para este circuito. Após isso faça a Análise e Síntese do projeto.<br />
*Crie um simbolo para este módulo, selecionando na IDE do Quartus II o diagrama esquemático e [File > Create/Update > Create Symbol Files for Current File] > [Save] > [OK].<br />
<center><br />
[[Arquivo:Complemento2-bsf.png|thumb|150px]]<br />
</center><br />
<br />
==Simulação funcional com o QSIM==<br />
*Abra o editor de forma de onda do simulador QSIM (File > New > University Programa VWF). <br />
*Defina o tempo de simulação (Edit > Set End Time ...) = 1000 ns.<br />
*Importe todos os nós de lista do projeto (Edit > Insert > Insert Node or Bus) > [Node Finder] > [List] > [>>] > [OK] > [OK].<br />
*Gere uma forma de onda dos sinais de entrada semelhante a mostrado na figura abaixo (Use a função [Randon Value] em A e B, e salve com o nome TesteComplemento2.vwf.<br />
*Note que os bits das entradas e saídas estão agrupados em ordem reversa e definidos como RADIX = "Decimal com sinal"<br />
[[Arquivo:C2-SIM_IN.png|800 px]]<br />
<br />
*Indique que o QSIM será usado na simulação (Simulation > Options > (x) Quartus II Simulator) > [OK] > [OK]<br />
*Faça a simulação funcional do circuito lógico usando o sinal criado (Simulation > Run Functional Simulation)<br />
*O resultado da simulação deve corresponder a um somador completo. <br />
[[Arquivo:C2-SIM.png|800 px]]<br />
<br />
==Análise dos resultados==<br />
*Analise os resultados preenchendo a tabela abaixo, e conferindo se está correto:<br />
<br />
<center><br />
{| border="1" cellpadding="5" cellspacing="0" style="text-align: center;"<br />
! colspan="2" style="background: #efefef;" | Entradas<br />
! colspan="1" style="background: #ffdead;" | Saídas<br />
! style="background: #00dead;" | x<br />
! colspan="2" style="background: #efefef;" | Entradas<br />
! colspan="1" style="background: #ffdead;" | Saídas<br />
|-<br />
!width="40"| X >= 0 <br />
!width="40"| Y <br />
!width="80"| OK <br />
!width="5" style="background: #00dead;"| x<br />
!width="40"| X < 0<br />
!width="40"| Y <br />
!width="80"| OK <br />
|-<br />
| 0 || || || x || || || |<br />
|-<br />
| 1 || || || x || -1 || || |<br />
|-<br />
| 2 || || || x || -2 || || |<br />
|-<br />
| 3 || || || x || -3 || || |<br />
|-<br />
| 4 || || || x || -4 || || |<br />
|-<br />
| 5 || || || x || -5 || || |<br />
|-<br />
| 6 || || || x || -6 || || |<br />
|-<br />
| 7 || || || x || -7 || || |<br />
|-<br />
| 8 || || || x || -8 || || |<br />
|}<br />
</center><br />
<br />
*Responda as seguintes questões:<br />
;Qual é o valor minimo e máximo que pode ser representado em complemento de 2 com 4 bits?<br />
;Quais são as restrições de uso desse circuito? <br />
;Qual o valor obtido quando colocamos um valor positivo na entrada?<br />
;Qual o valor obtido quando colocamos um valor negativo na entrada? <br />
;Se for inserido um inversor em cada saída qual é o resultado obtido? Como poderia ser chamado este circuito?<br />
<br />
=Multiplexador de 2 para 1=<br />
==Diagrama Esquemático==<br />
Abra o Quartus II e insira o diagrama esquemático do módulo básico do complementador de 2.<br />
<center><br />
[[Arquivo:Mux2para1-bdf.png|600px]]<br />
</center><br />
<br />
<center><br />
[[Arquivo:Mux2para1-bsf.png|thumb|150px]]<br />
</center><br />
*Salve o arquivo como Mux2para1.bdf na mesma pasta do PROJ2.<br />
*Mude o Top Level para este circuito. Após isso faça a Análise e Síntese do projeto.<br />
*Crie um simbolo para este módulo, selecionando na IDE do Quartus II o diagrama esquemático e [File > Create/Update > Create Symbol Files for Current File] > [Save] > [OK].<br />
<br />
*Utilize 4 desses componentes para criar um multiplexador de 2 entradas para 1 saída de 4 bits.<br />
<center><br />
[[Arquivo:QUADMux2para1-bdf.png|600px]]<br />
</center><br />
*Crie um simbolo para este módulo, selecionando na IDE do Quartus II o diagrama esquemático e [File > Create/Update > Create Symbol Files for Current File] > [Save] > [OK].<br />
<center><br />
[[Arquivo:QUADMux2para1-bsf.png|thumb|150px]]<br />
</center><br />
<br />
==Simulação funcional com o QSIM==<br />
*Abra o editor de forma de onda do simulador QSIM (File > New > University Programa VWF). <br />
*Defina o tempo de simulação (Edit > Set End Time ...) = 1000 ns.<br />
*Importe todos os nós de lista do projeto (Edit > Insert > Insert Node or Bus) > [Node Finder] > [List] > [>>] > [OK] > [OK].<br />
*Gere uma forma de onda dos sinais de entrada semelhante a mostrado na figura abaixo (Use a função [Randon Value] em A, B e Sel e salve com o nome QUADMux2para1.vwf.<br />
*Indique que o QSIM será usado na simulação (Simulation > Options > (x) Quartus II Simulator) > [OK] > [OK]<br />
*Faça a simulação funcional do circuito lógico usando o sinal criado (Simulation > Run Functional Simulation)<br />
[[Arquivo:QUADMux2para1-SIM.png|800 px]]<br />
<br />
==Análise dos resultados==<br />
*Verifique se o multiplexador está funcionando. Quando S = 0 => Y = x0, e quando S = 1 => Y = x1.<br />
<br />
=Circuito Somador e Substrator de 4 bits=<br />
==Diagrama Esquemático==<br />
Utilizando os componentes anteriormente criados, insira o diagrama esquemático do circuito a seguir.<br />
<center><br />
[[Arquivo:Sub_Add4bits-bdf.png|600px]]<br />
</center><br />
<br />
*Salve o arquivo como Sub_Add4bits.bdf na mesma pasta do PROJ2.<br />
*Mude o Top Level para este circuito. Após isso faça a Análise e Síntese do projeto.<br />
*Crie um simbolo para este módulo, selecionando na IDE do Quartus II o diagrama esquemático e [File > Create/Update > Create Symbol Files for Current File] > [Save] > [OK].<br />
<center><br />
[[Arquivo:Sub_Add4bits-bsf.png|thumb|150px]]<br />
</center><br />
<br />
==Simulação funcional com o QSIM==<br />
*Abra o editor de forma de onda do simulador QSIM (File > New > University Programa VWF). <br />
*Defina o tempo de simulação (Edit > Set End Time ...) = 1000 ns.<br />
*Importe todos os nós de lista do projeto (Edit > Insert > Insert Node or Bus) > [Node Finder] > [List] > [>>] > [OK] > [OK].<br />
*Gere uma forma de onda dos sinais de entrada semelhante a mostrado na figura abaixo (Use a função [Randon Value] em A, B e Sel e salve com o nome Sub_Add4bits.vwf.<br />
*Indique que o QSIM será usado na simulação (Simulation > Options > (x) Quartus II Simulator) > [OK] > [OK]<br />
*Faça a simulação funcional do circuito lógico usando o sinal criado (Simulation > Run Functional Simulation)<br />
[[Arquivo:Sub_Add4bits-SIM.png|800 px]]<br />
<br />
==Análise dos resultados==<br />
* Anote os resultados das operações de soma e subtração<br />
<center><br />
{| border="1" cellpadding="5" cellspacing="0" style="text-align: center;"<br />
! colspan="1" style="background: #efefef;" | Entrada Carry<br />
! colspan="2" style="background: #efefef;" | Entrada A<br />
! colspan="2" style="background: #efefef;" | Entrada B<br />
! colspan="2" style="background: #ffdead;" | Saídas<br />
|-<br />
!width="30"| C_in <br />
!width="30"| Op_A <br />
!width="80"| A <br />
!width="30"| Op_B <br />
!width="80"| B <br />
!width="40"| Erro<br />
!width="80"| Soma<br />
|-<br />
| . || || || || || || |<br />
|-<br />
| . || || || || || || |<br />
|-<br />
| . || || || || || || |<br />
|-<br />
| . || || || || || || |<br />
|-<br />
| . || || || || || || |<br />
|-<br />
| . || || || || || || |<br />
|-<br />
| . || || || || || || |<br />
|-<br />
| . || || || || || || |<br />
|-<br />
| . || || || || || || |<br />
|-<br />
| . || || || || || || |<br />
|-<br />
| . || || || || || || |<br />
|}<br />
</center><br />
<br />
*Verifique se o circuito está funcionando corretamente.<br />
<br />
*Responda as seguintes questões:<br />
;Qual é o valor minimo e máximo que pode ser representado na saída do circuito sem que haja erro?<br />
;Quais são as restrições de entrada no uso desse circuito?<br />
;Qual a função da entrada op_a e op_b?<br />
;Como interpretar o resultado da saída S do circuito quando a saída Over_Under está em 1?<br />
<br />
==Programação do FPGA e testes finais==<br />
Para programar o circuito lógico no FPGA, é necessário escolher um FPGA para a aplicação. Neste caso utilizaremos o kit DE2-115. <br />
*Mude a família e dispositivo a ser usado (Assignments > Devices), [Family = Cyclone IV E] e selecione EP4CE115F29C7 ou ou '''Family = Cyclone IV''' E com dispositivo '''device = EP4CE30F23C7'''<br />
*Defina como alta impedância o estado dos pinos não utilizados no projeto. (Assignments > Devices), [Device and Pin Options...], escolha a (Category=Unused Pins), e selecione Reserve all unused pins: As input tri-stated. [OK].<br />
*Selecione as interfaces de entrada e saída que deseja no kit educacional disponível, utilizando 4 chaves para cada entrada de dado A (a0-3) e B (b0-3), 2 chaves para os op_A e Op_B, 1 chave para o C_in. Para as saídas utilize 4 leds para o dado S (s0-3) e um led para a indicação de erro. <br />
<br />
;Entradas:<br />
*a0 -> PIN_AB28<br />
*a1 -> PIN_AC28<br />
*a2 -> PIN_AC27<br />
*a3 -> PIN_AD27<br />
*op_A -> PIN_AB27<br />
<br />
*b0 -> PIN_AC24<br />
*b1 -> PIN_AB24<br />
*b2 -> PIN_AB23<br />
*b3 -> PIN_AA24<br />
*op_B -> PIN_AA23<br />
<br />
*C_in -> PIN_Y23<br />
<br />
;Saídas:<br />
*s0 -> PIN_E21<br />
*s1 -> PIN_E22<br />
*s2 -> PIN_E25<br />
*s3 -> PIN_E24<br />
*erro -> PIN_G19 <br />
<br />
*Para ver as pinagens completa das [[Interfaces de entrada e saída da DE2-115]] no [[Media:ManualDE2-115.pdf | Manual]].<br />
*Compile o projeto. Note que agora a numeração dos pinos aparece no diagrama esquemático.<br />
<center><br />
[[Arquivo:Sub_Add4bitsBLOCK-bdf.png|800px]]<br />
</center></div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=Setup_Ferramentas_AVR_para_Assembly&diff=162064Setup Ferramentas AVR para Assembly2019-10-07T13:42:58Z<p>127.0.0.1: </p>
<hr />
<div>* Baixar e instalar os seguintes arquivos para o SO desejado:<br />
** IDE: [https://www.microchip.com/development-tools/pic-and-dspic-downloads-archive MPLAB X v5.20] (v5.20 é a utilizada no laboratório)<br />
** Compilador: [https://www.microchip.com/mplab/compilers MPLAB XC8 v2.10] (Aba downloads).<br />
** Anotar os caminhos das instalações <br />
<br />
*Configurar (adicionar o montador em avrasm2):<br />
** Abrir o MPLAB X IDE<br />
** Abra Tools -> Options. Abrirá a seguinte [http://docente.ifsc.edu.br/roberto.matos/mic_public/figs/mplab_preferences.png janela].<br />
** Selecione Embedded -> Build Tools -> Add ...<br />
** Adicione o caminho da instalação do compilador (anotado no passo anterior) em "Base Directory". Exemplo: /opt/microchip/xc8/v2.05/avr/bin<br />
** Em "Version" selecione "avrasm2" clique em OK e OK novamente.<br />
<br />
* Crie um [[Simular Assembly do AVR no MPLAB IDE | projeto]] para testar.<br />
<br />
<br />
=Resolução de Problemas=<br />
*Preparar Linux para pacotes 32-bits:<br />
https://akrabat.com/installing-32-bit-packages-on-ubuntu-14-04/<br />
<br />
*Instalar bibliotecas 32-bits:<br />
https://microchipdeveloper.com/install:mplabx-lin64</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=MIC29004-2019-2&diff=162063MIC29004-2019-22019-10-07T13:37:29Z<p>127.0.0.1: /* Aula 01/10/2019: Modos de Endereçamento (cont.) */</p>
<hr />
<div>= Microprocessadores: Diário de Aula 2019-2=<br />
<br />
*'''Professor:''' [[Roberto de Matos]]<br />
*'''Encontros:''' 2ª e 3ª feira às 9:40h<br />
*'''Atendimento Paralelo:''' 4ª às 10h e 14h (1h cada)<br />
* [[MIC-EngTel_(Plano_de_Ensino) |Plano de Ensino]]<br />
* [[Cronograma_de_atividades_(MIC-EngTel) | Cronograma de Aulas]]<br />
* [http://docente.ifsc.edu.br/roberto.matos/mic_public/2019-2/notas_MIC29004_2019-2.pdf Notas]<br />
<br />
== Material ==<br />
*[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/ApostilaMemorias.pdf Apostila Memória]<br />
*[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_1-memoria.pdf Slides Memória]<br />
<!--<br />
*[[Media:mic-slides_2-handout.pdf|Introdução a Microprocessadores]]<br />
*[[Media:bip.pdf|Arquitetura e Organização do BIP]]<br />
--><br />
<br />
==Listas de Exercício==<br />
* [[MIC29004-lista1 | Lista de Exercícios: Memória, Arquitetura, Organização e BIP]]<br />
*[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/Exercícios-sobre-a-programação-do-BIP.pdf Lista Introdução a programação do BIP]<br />
* [[MIC29004-lista2-avr | Lista de Exercícios Microcontroladores e AVR]]<br />
<br />
= Aula 29/07/2019: Apresentação =<br />
* Apresentação do professor.<br />
* Apresentação da disciplina: conteúdo, bibliografia e avaliação.<br />
<br />
<br />
= Aula 30/07/2019: Introdução sobre Memória =<br />
*[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/ApostilaMemorias.pdf Apostila Memória]<br />
*[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_1-memoria.pdf Slides Memória]<br />
<br />
*[[MIC29004-lista1 | Lista de Exercícios: Memória, Arquitetura, Organização e BIP]]<br />
<br />
<br />
==Diagrama em blocos da memória e barramentos==<br />
No diagrama abaixo está representado um bloco de memória primária de 16x8 (dezesseis endereços por 8 bits).<br />
*Note que uma posição de memória pode ser vista como uma caixa que possue um endereço e um conteúdo. <br />
*O conteúdo associado a posição de memória é uma palavra binária e, neste caso, possui 8 bits.<br />
<br />
[[imagem:DiagramaBlocosMemorias2.jpg|500px|center]]<br />
<br />
Para que us dispositivo externo possa "acessar" a memória para leitura ou escrita, ele deve se utilizar de um conjunto de fios que chamamos de barramentos.<br />
<br />
===Barramento de Endereços===<br />
<br />
Este barramento permite determinar o endereço de uma posição a ser acessada na memória.<br />
Um barramento de 4 linhas de endereço é designado por A3,A2,A1 e A0.<br />
<br />
Supondo uma memória com endereços designados da forma hexadecimal de 0h a Fh. Supondo que A3<br />
seja associado ao bit mais significativo e A0 ao bit menos significativo. Então, para acessar<br />
a posição Bh de memória, deve-se injetar A3=1, A2=0, A1=1 e A0=1. Note que <math> B_h = 1011_b </math><br />
<br />
O termo "injetar" significa aqui que um dispositivo externo deve forçar tensão nas linhas do barramento.<br />
Esta tensão depende da tecnologia utilizada. Poderia ser, por exemplo, 5V para o nível lógico 1 e 0V par ao nível lógico 0.,<br />
<br />
<br />
<br />
= Aula 04/08/2019: Laboratório de Memória - Introdução =<br />
<br />
*'''Notas de Aula:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_1-memoria.pdf Slides Memória]<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic_slides_1-memoria_tabela_associacao.pdf Exemplos de Associação de Memória]<br />
<br />
* '''Material de Apoio (Decodificadores):'''<br />
**[http://www.electronics-tutorials.ws/combination/comb_5.html Tutorial]<br />
**[http://www.skot9000.com/ttl/datasheets/139.pdf 74LS139]<br />
<br />
<br />
*'''Experimento 1 - Memória 16x4:'''<br />
#Entrar no Windows.<br />
#Baixar o arquivo de projeto [http://docente.ifsc.edu.br/roberto.matos/mic_public/labs/lab1-memoria.zip aqui]. Coloque em um diretório conhecido.<br />
#Descompacte. Clique sobre o arquivo *.pdsprj. O PROTEUS será executado e o projeto aberto.<br />
#Observe que o projeto está parcialmente pronto. Você pode entrar em modo simulação.<br />
#O sistema está preparado para que se possa inserir ou ler manualmente posições de memória.<br />
#Leia todas as 16 posições de memória e anote os valores.<br />
#Grave o número da sua matrícula na memória. Preencha o restante com zero.<br />
#Note o Chip Select está habilitado sempre. Coloque uma chave adicional para colocar o Chip Select.<br />
<br />
<br />
*'''Atividade 1 - Associação de Memórias:'''<br />
**Usando como referência o experimento 1 e os exemplos de associação de memória vistos em sala de aula, implemente o seguinte:<br />
:# Uma memória 16x8<br />
:# Uma memória 64x4<br />
:# Uma memória 64x8<br />
*Entrega:<br />
**Fazer em Duplas<br />
**Última Aula de dúvidas: 06/08 (segunda)<br />
**Apresentação: 07/08 (terça)<br />
<br />
= Aula 12/08/2019: Laboratório de Memória - Associação =<br />
* Finalizar o Exercício<br />
<br />
= Aula 13/08/2019: Introdução à Arquitetura e Organização de Computadores =<br />
<br />
*'''Objetivos:'''<br />
** Introdução a Microprocessadores<br />
<br />
*'''Notas de Aula:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_2-Arquitetura_e_Bip.pdf Introdução à Arquitetura e Organização de Computadores]<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_3-Projetando_um_Computador_slides.pdf Projetando um Computador - BIP]<br />
<br />
* '''Experimento:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/Exercícios-sobre-a-programação-do-BIP.pdf Lista Introdução a programação do BIP]<br />
<br />
<br />
= Aula 19/08/2019: Arquitetura BIP =<br />
<br />
*'''Objetivos:'''<br />
** Entender a Arquitetura BIP<br />
** Programar em Assembly o BIP<br />
<br />
*'''Notas de Aula:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_3-Projetando_um_Computador_slides.pdf Projetando um Computador - BIP]<br />
<br />
* '''Experimento:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/Exercícios-sobre-a-programação-do-BIP.pdf Lista Introdução a programação do BIP]<br />
<br />
<br />
= Aula 20/08/2019: Organização do BIP =<br />
*'''Objetivos:'''<br />
** Entender a Organização do BIP<br />
** Criar tabela de decodificação do BIP<br />
<br />
*'''Notas de Aula:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_3-Projetando_um_Computador_slides.pdf Projetando um Computador - BIP]<br />
<br />
*'''Software Utilizado:'''<br />
**[http://bipide.com.br/ BIP IDE]<br />
<br />
<br />
= Aula 26/08/2019: Decodificador BIP =<br />
<br />
*'''Objetivos:'''<br />
** Entender a execução do BIP passo-a-passo no Proteus<br />
** Implementar o circuito decodificador do BIP no Proteus<br />
** Entender as mudanças da arquitetura e da organização do BIP II<br />
<br />
*'''Experimento:'''<br />
** [[Experimento_BIP_I | Experimento BIP I]]<br />
<br />
<br />
= Aula 27/08/2019: Decodificador BIP (cont.) e BIP II=<br />
<br />
*'''Objetivos:'''<br />
** Finalizar o Decode do BIP<br />
** Introdução da arquitetura do BIP II<br />
<br />
*'''Exercícios:'''<br />
** Implementar e simular exemplos com as instruções de desvio do BIP II<br />
<br />
<br />
= Aula 02/09/2019: Organização do BIP II =<br />
*'''Objetivos:'''<br />
**Entender as mudanças da arquitetura e da organização do BIP II<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/Artigo-BIP.pdf Artigo BIP II]<br />
<br />
*'''Experimento:'''<br />
** [http://docente.ifsc.edu.br/roberto.matos/mic_public/labs/codigos_bip2.zip Instruções de Desvio BIP II]<br />
<br />
*'''Exercício:'''<br />
** Implementar as mudanças da organização do BIP para criar o BIP II <br />
** Implementar o decodificador do BIP II ([http://www.32x8.com/ 32x8])<br />
** Implementar programas de testes no assembly do BIP II<br />
** Trabalho em Dupla<br />
** Entrega 08/09 e Apresentação 10/09<br />
<br />
= Aula 03/09/2019: Dúvidas Lista de Exercício e Apoio Trabalho BIP II =<br />
*'''Objetivos:'''<br />
** Aula de dúvidas<br />
<br />
*'''Objetivos:'''<br />
** Dúvidas da [[MIC29004-lista1 | Lista de Exercícios: Memória, Arquitetura, Organização e BIP]] para prova I.<br />
<br />
<br />
= Aula 09/09/2019: Prova I =<br />
*'''Objetivos:'''<br />
** Avaliação dos conceitos de Memória, Arquitetura e Organização, BIP I e II<br />
<br />
= Aula 10/09/2019: Apresentação Trabalho BIP II=<br />
*'''Objetivos:'''<br />
** Apresentação do Trabalho BIP II<br />
<br />
<br />
= Aula 16/09/2019: Correção da Prova=<br />
*'''Objetivos:'''<br />
** Correção da avaliação para completar o processo de ensino-aprendizagem.<br />
<br />
*'''Notas:'''<br />
* Foi decidido junto à turma que o péssimo resultado da avaliação será recuperado no fim do semestre. <br />
* O professor se colocou à disposição para recuperar o conteúdo durante o semestre, tirando dúvidas em sala de aula ou no horário de atendimento. <br />
* Os alunos se comprometeram em recuperar o conteúdo, pois é essencial para a continuidade da disciplina.<br />
<br />
= Aula 17/09/2019: Introdução aos Microcontroladores =<br />
*'''Objetivos:'''<br />
** Entender os conceitos e diferenças entre um Processador e um Microcontrolador. <br />
** Introdução à aplicações microcontroladas<br />
<br />
*'''Notas de Aulas:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_4-Intro_Microcontroladores_CISC_RISC.pdf Introdução aos Microcontroladores, CISC vs. RISC]<br />
<br />
*'''Notas Extras:'''<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/30010135D.pdf Referência Rápida Família AVR]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/30009630M.pdf Overview Microcontroladores Microchip]<br />
<br />
==Homework==<br />
* [http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf Datasheet Atmega328p]<br />
<br />
*Ler:<br />
** 2. Visão Geral<br />
** 7. Núcleo AVR <br />
** Responder:<br />
*** Qual arquitetura de memória usada? <br />
*** Detalhes da ALU (Quais os tipos de operação?)<br />
*** Registradores (Status, Uso geral e de Pilha)<br />
*** Modos de endereçamento<br />
*** Conjunto de instruções (classes e exemplos)<br />
<br />
* Ler: <br />
** 8. Memórias do AVR<br />
*** Flash<br />
*** SRAM<br />
*** EEPROM<br />
** Responder<br />
*** Qual o tamanho e o formato da palavra de de dados?<br />
*** Qual o tamanho e o formato da palavra de instrução?<br />
<br />
= Aula 23/09/2019: Arquitetura do AVR =<br />
<br />
*'''Objetivos:'''<br />
** Finalizar CISC vs. RISC<br />
** Visão Geral dos Microcontroladores ATmega48A/PA/88A/PA/168A/PA/328/P<br />
** Núcleo do AVR (ALU e Banco de Registradores)<br />
** Hierarquia de Memórias do AVR<br />
<br />
*'''Notas de Aulas:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_5-AVR.pdf Introdução AVR]<br />
<br />
*'''Notas Extras:'''<br />
**Die do [https://siliconpr0n.org/archive/doku.php?id=azonenberg:atmel:atmega48 ATmega48] e do [https://siliconpr0n.org/archive/doku.php?id=azonenberg:atmel:atmega328 ATmega328]<br />
<br />
= Aula 23/09/2019: Arquitetura do AVR (cont.) =<br />
<br />
*'''Objetivos:'''<br />
** Finalizar os objetivos da última aula<br />
<br />
*'''Notas de Aulas:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/slides-AVR_aula01.pdf Introdução AVR]<br />
<br />
*'''Experimento:'''<br />
** Simulação do primeiro código em Assembly usando o MPLAB X IDE <br />
** [[Simular Assembly do AVR no MPLAB IDE | Criar projeto]]<br />
<code><br />
start:<br />
inc r16<br />
inc r17<br />
sts $0100,r16<br />
sts $0101,r16<br />
rjmp start<br />
</syntaxhighlight><br />
<br />
==Homework==<br />
* Instalar o MPLAB X e o XC8: [[Setup Ferramentas AVR para Assembly]]<br />
* Rodar o exemplo da aula para verificar<br />
<br />
<br />
= Aula 30/09/2019: Modos de Endereçamento =<br />
*'''Objetivos:'''<br />
**Introduzir arquitetura Load-Store<br />
**Entender: <br />
***Modos de endereçamento do AVR e <br />
***Instruções relacionadas a cada modo do ATmega328p<br />
**Implementar programas para compreensão dos novos conceitos<br />
<br />
*'''Notas de Aulas:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/slides-AVR_aula02.pdf Modos de Endereçamento]<br />
<br />
==Homework==<br />
* OBS.: Instalar e configurar as ferramentas em casa para quem não fez (ver homework da aula passada).<br />
<br />
===Exercício 1===<br />
* Testar '''TODOS''' os trechos de códigos apresentados. Modifique os valores das localizações de memória afetadas para verificar se o funcionamento está coerente. <br />
<br />
*Exemplo:<br />
<code><br />
start:<br />
ldi R16,0x14<br />
rjmp start<br />
</syntaxhighlight><br />
* Pergunte-se:<br />
** A instrução em linguagem de máquina está coerente?<br />
** Se mudar o valor do imediato 0x14 para 0x25, como afeta a instrução montada? E se mudar o registrador de R16 para R17?<br />
** Eu posso carregar um imediato para o registrador R0? Por quê?<br />
* Faça isso para todos os trechos de código apresentados.<br />
<br />
===Exercício 2===<br />
*Faça um programa que some dois números de 8 bits: '''C = A + B'''<br />
*Considere as varáveis armazenadas sequencialmente a partir do primeiro endereço da memória SRAM.<br />
<br />
<br />
= Aula 01/10/2019: Modos de Endereçamento (cont.) =<br />
*'''Objetivos:'''<br />
**Corrigir exercícios da Aula prática<br />
**Mais exercícios<br />
<br />
*'''Exercícios: '''<br />
** Some as constantes 25, 14 e 0x32 e armazene o resultado em R0.<br />
** Some as constantes 32 e 0x23 e armazene o resultado em uma variável na SRAM (endereço 0x010A).<br />
**Re-implemente o código abaixo usando endereçamento indireto para acessar o R17 como posição de memória na SRAM:<br />
:<code><br />
ldi r16, $BB<br />
mov r17, r16<br />
</syntaxhighlight><br />
<br />
<br />
==Homework==<br />
* Estudar instruções de desvio e aritméticas<br />
* Escrever códigos que:<br />
#Execute 1.000 vezes uma ação em loop.<br />
#Execute 100.000 vezes uma ação em loop.<br />
#Carregue na SRAM 10 valores sequenciais a partir do endereço 0x0102 usando endereçamento de dados indireto com pós-incremento.<br />
#Tenha o mesmo resultado do programa anterior, mas que utilize endereçamento de dados indireto com pré-decremento.<br />
<br />
*Links:<br />
**https://www.microchip.com/webdoc/avrassembler/avrassembler.wb_instruction_list.html<br />
**http://ww1.microchip.com/downloads/en/devicedoc/atmel-0856-avr-instruction-set-manual.pdf<br />
<br />
= Aula 01/10/2019: Instruções Aritmética e desvio =<br />
*'''Objetivos:'''<br />
**Corrigir exercícios da Aula prática<br />
**Mais exercícios<br />
<br />
*'''Exercícios: '''<br />
**Faça programas que utilizem a rotação para esquerda e direita. Quais os tipos de rotação possível? Quais os bits de status podem ser modificados?<br />
** Faça a soma de dois valores de 16 bits usando os registradores.<br />
** Implemente estrutura de alto nível: IF-THEN-ELSE, WHILE e SWITCH-CASE</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=MIC29004-2019-2&diff=162062MIC29004-2019-22019-10-07T13:06:30Z<p>127.0.0.1: /* Homework */</p>
<hr />
<div>= Microprocessadores: Diário de Aula 2019-2=<br />
<br />
*'''Professor:''' [[Roberto de Matos]]<br />
*'''Encontros:''' 2ª e 3ª feira às 9:40h<br />
*'''Atendimento Paralelo:''' 4ª às 10h e 14h (1h cada)<br />
* [[MIC-EngTel_(Plano_de_Ensino) |Plano de Ensino]]<br />
* [[Cronograma_de_atividades_(MIC-EngTel) | Cronograma de Aulas]]<br />
* [http://docente.ifsc.edu.br/roberto.matos/mic_public/2019-2/notas_MIC29004_2019-2.pdf Notas]<br />
<br />
== Material ==<br />
*[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/ApostilaMemorias.pdf Apostila Memória]<br />
*[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_1-memoria.pdf Slides Memória]<br />
<!--<br />
*[[Media:mic-slides_2-handout.pdf|Introdução a Microprocessadores]]<br />
*[[Media:bip.pdf|Arquitetura e Organização do BIP]]<br />
--><br />
<br />
==Listas de Exercício==<br />
* [[MIC29004-lista1 | Lista de Exercícios: Memória, Arquitetura, Organização e BIP]]<br />
*[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/Exercícios-sobre-a-programação-do-BIP.pdf Lista Introdução a programação do BIP]<br />
* [[MIC29004-lista2-avr | Lista de Exercícios Microcontroladores e AVR]]<br />
<br />
= Aula 29/07/2019: Apresentação =<br />
* Apresentação do professor.<br />
* Apresentação da disciplina: conteúdo, bibliografia e avaliação.<br />
<br />
<br />
= Aula 30/07/2019: Introdução sobre Memória =<br />
*[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/ApostilaMemorias.pdf Apostila Memória]<br />
*[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_1-memoria.pdf Slides Memória]<br />
<br />
*[[MIC29004-lista1 | Lista de Exercícios: Memória, Arquitetura, Organização e BIP]]<br />
<br />
<br />
==Diagrama em blocos da memória e barramentos==<br />
No diagrama abaixo está representado um bloco de memória primária de 16x8 (dezesseis endereços por 8 bits).<br />
*Note que uma posição de memória pode ser vista como uma caixa que possue um endereço e um conteúdo. <br />
*O conteúdo associado a posição de memória é uma palavra binária e, neste caso, possui 8 bits.<br />
<br />
[[imagem:DiagramaBlocosMemorias2.jpg|500px|center]]<br />
<br />
Para que us dispositivo externo possa "acessar" a memória para leitura ou escrita, ele deve se utilizar de um conjunto de fios que chamamos de barramentos.<br />
<br />
===Barramento de Endereços===<br />
<br />
Este barramento permite determinar o endereço de uma posição a ser acessada na memória.<br />
Um barramento de 4 linhas de endereço é designado por A3,A2,A1 e A0.<br />
<br />
Supondo uma memória com endereços designados da forma hexadecimal de 0h a Fh. Supondo que A3<br />
seja associado ao bit mais significativo e A0 ao bit menos significativo. Então, para acessar<br />
a posição Bh de memória, deve-se injetar A3=1, A2=0, A1=1 e A0=1. Note que <math> B_h = 1011_b </math><br />
<br />
O termo "injetar" significa aqui que um dispositivo externo deve forçar tensão nas linhas do barramento.<br />
Esta tensão depende da tecnologia utilizada. Poderia ser, por exemplo, 5V para o nível lógico 1 e 0V par ao nível lógico 0.,<br />
<br />
<br />
<br />
= Aula 04/08/2019: Laboratório de Memória - Introdução =<br />
<br />
*'''Notas de Aula:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_1-memoria.pdf Slides Memória]<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic_slides_1-memoria_tabela_associacao.pdf Exemplos de Associação de Memória]<br />
<br />
* '''Material de Apoio (Decodificadores):'''<br />
**[http://www.electronics-tutorials.ws/combination/comb_5.html Tutorial]<br />
**[http://www.skot9000.com/ttl/datasheets/139.pdf 74LS139]<br />
<br />
<br />
*'''Experimento 1 - Memória 16x4:'''<br />
#Entrar no Windows.<br />
#Baixar o arquivo de projeto [http://docente.ifsc.edu.br/roberto.matos/mic_public/labs/lab1-memoria.zip aqui]. Coloque em um diretório conhecido.<br />
#Descompacte. Clique sobre o arquivo *.pdsprj. O PROTEUS será executado e o projeto aberto.<br />
#Observe que o projeto está parcialmente pronto. Você pode entrar em modo simulação.<br />
#O sistema está preparado para que se possa inserir ou ler manualmente posições de memória.<br />
#Leia todas as 16 posições de memória e anote os valores.<br />
#Grave o número da sua matrícula na memória. Preencha o restante com zero.<br />
#Note o Chip Select está habilitado sempre. Coloque uma chave adicional para colocar o Chip Select.<br />
<br />
<br />
*'''Atividade 1 - Associação de Memórias:'''<br />
**Usando como referência o experimento 1 e os exemplos de associação de memória vistos em sala de aula, implemente o seguinte:<br />
:# Uma memória 16x8<br />
:# Uma memória 64x4<br />
:# Uma memória 64x8<br />
*Entrega:<br />
**Fazer em Duplas<br />
**Última Aula de dúvidas: 06/08 (segunda)<br />
**Apresentação: 07/08 (terça)<br />
<br />
= Aula 12/08/2019: Laboratório de Memória - Associação =<br />
* Finalizar o Exercício<br />
<br />
= Aula 13/08/2019: Introdução à Arquitetura e Organização de Computadores =<br />
<br />
*'''Objetivos:'''<br />
** Introdução a Microprocessadores<br />
<br />
*'''Notas de Aula:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_2-Arquitetura_e_Bip.pdf Introdução à Arquitetura e Organização de Computadores]<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_3-Projetando_um_Computador_slides.pdf Projetando um Computador - BIP]<br />
<br />
* '''Experimento:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/Exercícios-sobre-a-programação-do-BIP.pdf Lista Introdução a programação do BIP]<br />
<br />
<br />
= Aula 19/08/2019: Arquitetura BIP =<br />
<br />
*'''Objetivos:'''<br />
** Entender a Arquitetura BIP<br />
** Programar em Assembly o BIP<br />
<br />
*'''Notas de Aula:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_3-Projetando_um_Computador_slides.pdf Projetando um Computador - BIP]<br />
<br />
* '''Experimento:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/Exercícios-sobre-a-programação-do-BIP.pdf Lista Introdução a programação do BIP]<br />
<br />
<br />
= Aula 20/08/2019: Organização do BIP =<br />
*'''Objetivos:'''<br />
** Entender a Organização do BIP<br />
** Criar tabela de decodificação do BIP<br />
<br />
*'''Notas de Aula:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_3-Projetando_um_Computador_slides.pdf Projetando um Computador - BIP]<br />
<br />
*'''Software Utilizado:'''<br />
**[http://bipide.com.br/ BIP IDE]<br />
<br />
<br />
= Aula 26/08/2019: Decodificador BIP =<br />
<br />
*'''Objetivos:'''<br />
** Entender a execução do BIP passo-a-passo no Proteus<br />
** Implementar o circuito decodificador do BIP no Proteus<br />
** Entender as mudanças da arquitetura e da organização do BIP II<br />
<br />
*'''Experimento:'''<br />
** [[Experimento_BIP_I | Experimento BIP I]]<br />
<br />
<br />
= Aula 27/08/2019: Decodificador BIP (cont.) e BIP II=<br />
<br />
*'''Objetivos:'''<br />
** Finalizar o Decode do BIP<br />
** Introdução da arquitetura do BIP II<br />
<br />
*'''Exercícios:'''<br />
** Implementar e simular exemplos com as instruções de desvio do BIP II<br />
<br />
<br />
= Aula 02/09/2019: Organização do BIP II =<br />
*'''Objetivos:'''<br />
**Entender as mudanças da arquitetura e da organização do BIP II<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/Artigo-BIP.pdf Artigo BIP II]<br />
<br />
*'''Experimento:'''<br />
** [http://docente.ifsc.edu.br/roberto.matos/mic_public/labs/codigos_bip2.zip Instruções de Desvio BIP II]<br />
<br />
*'''Exercício:'''<br />
** Implementar as mudanças da organização do BIP para criar o BIP II <br />
** Implementar o decodificador do BIP II ([http://www.32x8.com/ 32x8])<br />
** Implementar programas de testes no assembly do BIP II<br />
** Trabalho em Dupla<br />
** Entrega 08/09 e Apresentação 10/09<br />
<br />
= Aula 03/09/2019: Dúvidas Lista de Exercício e Apoio Trabalho BIP II =<br />
*'''Objetivos:'''<br />
** Aula de dúvidas<br />
<br />
*'''Objetivos:'''<br />
** Dúvidas da [[MIC29004-lista1 | Lista de Exercícios: Memória, Arquitetura, Organização e BIP]] para prova I.<br />
<br />
<br />
= Aula 09/09/2019: Prova I =<br />
*'''Objetivos:'''<br />
** Avaliação dos conceitos de Memória, Arquitetura e Organização, BIP I e II<br />
<br />
= Aula 10/09/2019: Apresentação Trabalho BIP II=<br />
*'''Objetivos:'''<br />
** Apresentação do Trabalho BIP II<br />
<br />
<br />
= Aula 16/09/2019: Correção da Prova=<br />
*'''Objetivos:'''<br />
** Correção da avaliação para completar o processo de ensino-aprendizagem.<br />
<br />
*'''Notas:'''<br />
* Foi decidido junto à turma que o péssimo resultado da avaliação será recuperado no fim do semestre. <br />
* O professor se colocou à disposição para recuperar o conteúdo durante o semestre, tirando dúvidas em sala de aula ou no horário de atendimento. <br />
* Os alunos se comprometeram em recuperar o conteúdo, pois é essencial para a continuidade da disciplina.<br />
<br />
= Aula 17/09/2019: Introdução aos Microcontroladores =<br />
*'''Objetivos:'''<br />
** Entender os conceitos e diferenças entre um Processador e um Microcontrolador. <br />
** Introdução à aplicações microcontroladas<br />
<br />
*'''Notas de Aulas:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_4-Intro_Microcontroladores_CISC_RISC.pdf Introdução aos Microcontroladores, CISC vs. RISC]<br />
<br />
*'''Notas Extras:'''<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/30010135D.pdf Referência Rápida Família AVR]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/30009630M.pdf Overview Microcontroladores Microchip]<br />
<br />
==Homework==<br />
* [http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf Datasheet Atmega328p]<br />
<br />
*Ler:<br />
** 2. Visão Geral<br />
** 7. Núcleo AVR <br />
** Responder:<br />
*** Qual arquitetura de memória usada? <br />
*** Detalhes da ALU (Quais os tipos de operação?)<br />
*** Registradores (Status, Uso geral e de Pilha)<br />
*** Modos de endereçamento<br />
*** Conjunto de instruções (classes e exemplos)<br />
<br />
* Ler: <br />
** 8. Memórias do AVR<br />
*** Flash<br />
*** SRAM<br />
*** EEPROM<br />
** Responder<br />
*** Qual o tamanho e o formato da palavra de de dados?<br />
*** Qual o tamanho e o formato da palavra de instrução?<br />
<br />
= Aula 23/09/2019: Arquitetura do AVR =<br />
<br />
*'''Objetivos:'''<br />
** Finalizar CISC vs. RISC<br />
** Visão Geral dos Microcontroladores ATmega48A/PA/88A/PA/168A/PA/328/P<br />
** Núcleo do AVR (ALU e Banco de Registradores)<br />
** Hierarquia de Memórias do AVR<br />
<br />
*'''Notas de Aulas:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_5-AVR.pdf Introdução AVR]<br />
<br />
*'''Notas Extras:'''<br />
**Die do [https://siliconpr0n.org/archive/doku.php?id=azonenberg:atmel:atmega48 ATmega48] e do [https://siliconpr0n.org/archive/doku.php?id=azonenberg:atmel:atmega328 ATmega328]<br />
<br />
= Aula 23/09/2019: Arquitetura do AVR (cont.) =<br />
<br />
*'''Objetivos:'''<br />
** Finalizar os objetivos da última aula<br />
<br />
*'''Notas de Aulas:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/slides-AVR_aula01.pdf Introdução AVR]<br />
<br />
*'''Experimento:'''<br />
** Simulação do primeiro código em Assembly usando o MPLAB X IDE <br />
** [[Simular Assembly do AVR no MPLAB IDE | Criar projeto]]<br />
<code><br />
start:<br />
inc r16<br />
inc r17<br />
sts $0100,r16<br />
sts $0101,r16<br />
rjmp start<br />
</syntaxhighlight><br />
<br />
==Homework==<br />
* Instalar o MPLAB X e o XC8: [[Setup Ferramentas AVR para Assembly]]<br />
* Rodar o exemplo da aula para verificar<br />
<br />
<br />
= Aula 30/09/2019: Modos de Endereçamento =<br />
*'''Objetivos:'''<br />
**Introduzir arquitetura Load-Store<br />
**Entender: <br />
***Modos de endereçamento do AVR e <br />
***Instruções relacionadas a cada modo do ATmega328p<br />
**Implementar programas para compreensão dos novos conceitos<br />
<br />
*'''Notas de Aulas:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/slides-AVR_aula02.pdf Modos de Endereçamento]<br />
<br />
==Homework==<br />
* OBS.: Instalar e configurar as ferramentas em casa para quem não fez (ver homework da aula passada).<br />
<br />
===Exercício 1===<br />
* Testar '''TODOS''' os trechos de códigos apresentados. Modifique os valores das localizações de memória afetadas para verificar se o funcionamento está coerente. <br />
<br />
*Exemplo:<br />
<code><br />
start:<br />
ldi R16,0x14<br />
rjmp start<br />
</syntaxhighlight><br />
* Pergunte-se:<br />
** A instrução em linguagem de máquina está coerente?<br />
** Se mudar o valor do imediato 0x14 para 0x25, como afeta a instrução montada? E se mudar o registrador de R16 para R17?<br />
** Eu posso carregar um imediato para o registrador R0? Por quê?<br />
* Faça isso para todos os trechos de código apresentados.<br />
<br />
===Exercício 2===<br />
*Faça um programa que some dois números de 8 bits: '''C = A + B'''<br />
*Considere as varáveis armazenadas sequencialmente a partir do primeiro endereço da memória SRAM.<br />
<br />
<br />
= Aula 01/10/2019: Modos de Endereçamento (cont.) =<br />
*'''Objetivos:'''<br />
**Corrigir exercícios da Aula prática<br />
**Mais exercícios<br />
<br />
*'''Exercícios: '''<br />
** Some as constantes 25, 14 e 0x32 e armazene o resultado em R0.<br />
** Some as constantes 32 e 0x23 e armazene o resultado em uma variável na SRAM (endereço 0x010A).<br />
**Re-implemente o código abaixo usando endereçamento indireto para acessar o R0 como posição de memória na SRAM:<br />
:<code><br />
ldi r16, $BB<br />
mov r0, r16<br />
</syntaxhighlight><br />
<br />
<br />
==Homework==<br />
* Estudar instruções de desvio e aritméticas<br />
* Escrever códigos que:<br />
#Execute 1.000 vezes uma ação em loop.<br />
#Execute 100.000 vezes uma ação em loop.<br />
#Carregue na SRAM 10 valores sequenciais a partir do endereço 0x0102 usando endereçamento de dados indireto com pós-incremento.<br />
#Tenha o mesmo resultado do programa anterior, mas que utilize endereçamento de dados indireto com pré-decremento.<br />
<br />
*Links:<br />
**https://www.microchip.com/webdoc/avrassembler/avrassembler.wb_instruction_list.html<br />
**http://ww1.microchip.com/downloads/en/devicedoc/atmel-0856-avr-instruction-set-manual.pdf<br />
<br />
= Aula 01/10/2019: Instruções Aritmética e desvio =<br />
*'''Objetivos:'''<br />
**Corrigir exercícios da Aula prática<br />
**Mais exercícios<br />
<br />
*'''Exercícios: '''<br />
**Faça programas que utilizem a rotação para esquerda e direita. Quais os tipos de rotação possível? Quais os bits de status podem ser modificados?<br />
** Faça a soma de dois valores de 16 bits usando os registradores.<br />
** Implemente estrutura de alto nível: IF-THEN-ELSE, WHILE e SWITCH-CASE</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=MIC29004-2019-2&diff=162061MIC29004-2019-22019-10-07T12:18:05Z<p>127.0.0.1: /* Aula 01/10/2019: Modos de Endereçamento (cont.) */</p>
<hr />
<div>= Microprocessadores: Diário de Aula 2019-2=<br />
<br />
*'''Professor:''' [[Roberto de Matos]]<br />
*'''Encontros:''' 2ª e 3ª feira às 9:40h<br />
*'''Atendimento Paralelo:''' 4ª às 10h e 14h (1h cada)<br />
* [[MIC-EngTel_(Plano_de_Ensino) |Plano de Ensino]]<br />
* [[Cronograma_de_atividades_(MIC-EngTel) | Cronograma de Aulas]]<br />
* [http://docente.ifsc.edu.br/roberto.matos/mic_public/2019-2/notas_MIC29004_2019-2.pdf Notas]<br />
<br />
== Material ==<br />
*[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/ApostilaMemorias.pdf Apostila Memória]<br />
*[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_1-memoria.pdf Slides Memória]<br />
<!--<br />
*[[Media:mic-slides_2-handout.pdf|Introdução a Microprocessadores]]<br />
*[[Media:bip.pdf|Arquitetura e Organização do BIP]]<br />
--><br />
<br />
==Listas de Exercício==<br />
* [[MIC29004-lista1 | Lista de Exercícios: Memória, Arquitetura, Organização e BIP]]<br />
*[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/Exercícios-sobre-a-programação-do-BIP.pdf Lista Introdução a programação do BIP]<br />
* [[MIC29004-lista2-avr | Lista de Exercícios Microcontroladores e AVR]]<br />
<br />
= Aula 29/07/2019: Apresentação =<br />
* Apresentação do professor.<br />
* Apresentação da disciplina: conteúdo, bibliografia e avaliação.<br />
<br />
<br />
= Aula 30/07/2019: Introdução sobre Memória =<br />
*[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/ApostilaMemorias.pdf Apostila Memória]<br />
*[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_1-memoria.pdf Slides Memória]<br />
<br />
*[[MIC29004-lista1 | Lista de Exercícios: Memória, Arquitetura, Organização e BIP]]<br />
<br />
<br />
==Diagrama em blocos da memória e barramentos==<br />
No diagrama abaixo está representado um bloco de memória primária de 16x8 (dezesseis endereços por 8 bits).<br />
*Note que uma posição de memória pode ser vista como uma caixa que possue um endereço e um conteúdo. <br />
*O conteúdo associado a posição de memória é uma palavra binária e, neste caso, possui 8 bits.<br />
<br />
[[imagem:DiagramaBlocosMemorias2.jpg|500px|center]]<br />
<br />
Para que us dispositivo externo possa "acessar" a memória para leitura ou escrita, ele deve se utilizar de um conjunto de fios que chamamos de barramentos.<br />
<br />
===Barramento de Endereços===<br />
<br />
Este barramento permite determinar o endereço de uma posição a ser acessada na memória.<br />
Um barramento de 4 linhas de endereço é designado por A3,A2,A1 e A0.<br />
<br />
Supondo uma memória com endereços designados da forma hexadecimal de 0h a Fh. Supondo que A3<br />
seja associado ao bit mais significativo e A0 ao bit menos significativo. Então, para acessar<br />
a posição Bh de memória, deve-se injetar A3=1, A2=0, A1=1 e A0=1. Note que <math> B_h = 1011_b </math><br />
<br />
O termo "injetar" significa aqui que um dispositivo externo deve forçar tensão nas linhas do barramento.<br />
Esta tensão depende da tecnologia utilizada. Poderia ser, por exemplo, 5V para o nível lógico 1 e 0V par ao nível lógico 0.,<br />
<br />
<br />
<br />
= Aula 04/08/2019: Laboratório de Memória - Introdução =<br />
<br />
*'''Notas de Aula:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_1-memoria.pdf Slides Memória]<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic_slides_1-memoria_tabela_associacao.pdf Exemplos de Associação de Memória]<br />
<br />
* '''Material de Apoio (Decodificadores):'''<br />
**[http://www.electronics-tutorials.ws/combination/comb_5.html Tutorial]<br />
**[http://www.skot9000.com/ttl/datasheets/139.pdf 74LS139]<br />
<br />
<br />
*'''Experimento 1 - Memória 16x4:'''<br />
#Entrar no Windows.<br />
#Baixar o arquivo de projeto [http://docente.ifsc.edu.br/roberto.matos/mic_public/labs/lab1-memoria.zip aqui]. Coloque em um diretório conhecido.<br />
#Descompacte. Clique sobre o arquivo *.pdsprj. O PROTEUS será executado e o projeto aberto.<br />
#Observe que o projeto está parcialmente pronto. Você pode entrar em modo simulação.<br />
#O sistema está preparado para que se possa inserir ou ler manualmente posições de memória.<br />
#Leia todas as 16 posições de memória e anote os valores.<br />
#Grave o número da sua matrícula na memória. Preencha o restante com zero.<br />
#Note o Chip Select está habilitado sempre. Coloque uma chave adicional para colocar o Chip Select.<br />
<br />
<br />
*'''Atividade 1 - Associação de Memórias:'''<br />
**Usando como referência o experimento 1 e os exemplos de associação de memória vistos em sala de aula, implemente o seguinte:<br />
:# Uma memória 16x8<br />
:# Uma memória 64x4<br />
:# Uma memória 64x8<br />
*Entrega:<br />
**Fazer em Duplas<br />
**Última Aula de dúvidas: 06/08 (segunda)<br />
**Apresentação: 07/08 (terça)<br />
<br />
= Aula 12/08/2019: Laboratório de Memória - Associação =<br />
* Finalizar o Exercício<br />
<br />
= Aula 13/08/2019: Introdução à Arquitetura e Organização de Computadores =<br />
<br />
*'''Objetivos:'''<br />
** Introdução a Microprocessadores<br />
<br />
*'''Notas de Aula:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_2-Arquitetura_e_Bip.pdf Introdução à Arquitetura e Organização de Computadores]<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_3-Projetando_um_Computador_slides.pdf Projetando um Computador - BIP]<br />
<br />
* '''Experimento:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/Exercícios-sobre-a-programação-do-BIP.pdf Lista Introdução a programação do BIP]<br />
<br />
<br />
= Aula 19/08/2019: Arquitetura BIP =<br />
<br />
*'''Objetivos:'''<br />
** Entender a Arquitetura BIP<br />
** Programar em Assembly o BIP<br />
<br />
*'''Notas de Aula:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_3-Projetando_um_Computador_slides.pdf Projetando um Computador - BIP]<br />
<br />
* '''Experimento:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/Exercícios-sobre-a-programação-do-BIP.pdf Lista Introdução a programação do BIP]<br />
<br />
<br />
= Aula 20/08/2019: Organização do BIP =<br />
*'''Objetivos:'''<br />
** Entender a Organização do BIP<br />
** Criar tabela de decodificação do BIP<br />
<br />
*'''Notas de Aula:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_3-Projetando_um_Computador_slides.pdf Projetando um Computador - BIP]<br />
<br />
*'''Software Utilizado:'''<br />
**[http://bipide.com.br/ BIP IDE]<br />
<br />
<br />
= Aula 26/08/2019: Decodificador BIP =<br />
<br />
*'''Objetivos:'''<br />
** Entender a execução do BIP passo-a-passo no Proteus<br />
** Implementar o circuito decodificador do BIP no Proteus<br />
** Entender as mudanças da arquitetura e da organização do BIP II<br />
<br />
*'''Experimento:'''<br />
** [[Experimento_BIP_I | Experimento BIP I]]<br />
<br />
<br />
= Aula 27/08/2019: Decodificador BIP (cont.) e BIP II=<br />
<br />
*'''Objetivos:'''<br />
** Finalizar o Decode do BIP<br />
** Introdução da arquitetura do BIP II<br />
<br />
*'''Exercícios:'''<br />
** Implementar e simular exemplos com as instruções de desvio do BIP II<br />
<br />
<br />
= Aula 02/09/2019: Organização do BIP II =<br />
*'''Objetivos:'''<br />
**Entender as mudanças da arquitetura e da organização do BIP II<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/Artigo-BIP.pdf Artigo BIP II]<br />
<br />
*'''Experimento:'''<br />
** [http://docente.ifsc.edu.br/roberto.matos/mic_public/labs/codigos_bip2.zip Instruções de Desvio BIP II]<br />
<br />
*'''Exercício:'''<br />
** Implementar as mudanças da organização do BIP para criar o BIP II <br />
** Implementar o decodificador do BIP II ([http://www.32x8.com/ 32x8])<br />
** Implementar programas de testes no assembly do BIP II<br />
** Trabalho em Dupla<br />
** Entrega 08/09 e Apresentação 10/09<br />
<br />
= Aula 03/09/2019: Dúvidas Lista de Exercício e Apoio Trabalho BIP II =<br />
*'''Objetivos:'''<br />
** Aula de dúvidas<br />
<br />
*'''Objetivos:'''<br />
** Dúvidas da [[MIC29004-lista1 | Lista de Exercícios: Memória, Arquitetura, Organização e BIP]] para prova I.<br />
<br />
<br />
= Aula 09/09/2019: Prova I =<br />
*'''Objetivos:'''<br />
** Avaliação dos conceitos de Memória, Arquitetura e Organização, BIP I e II<br />
<br />
= Aula 10/09/2019: Apresentação Trabalho BIP II=<br />
*'''Objetivos:'''<br />
** Apresentação do Trabalho BIP II<br />
<br />
<br />
= Aula 16/09/2019: Correção da Prova=<br />
*'''Objetivos:'''<br />
** Correção da avaliação para completar o processo de ensino-aprendizagem.<br />
<br />
*'''Notas:'''<br />
* Foi decidido junto à turma que o péssimo resultado da avaliação será recuperado no fim do semestre. <br />
* O professor se colocou à disposição para recuperar o conteúdo durante o semestre, tirando dúvidas em sala de aula ou no horário de atendimento. <br />
* Os alunos se comprometeram em recuperar o conteúdo, pois é essencial para a continuidade da disciplina.<br />
<br />
= Aula 17/09/2019: Introdução aos Microcontroladores =<br />
*'''Objetivos:'''<br />
** Entender os conceitos e diferenças entre um Processador e um Microcontrolador. <br />
** Introdução à aplicações microcontroladas<br />
<br />
*'''Notas de Aulas:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_4-Intro_Microcontroladores_CISC_RISC.pdf Introdução aos Microcontroladores, CISC vs. RISC]<br />
<br />
*'''Notas Extras:'''<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/30010135D.pdf Referência Rápida Família AVR]<br />
**[http://ww1.microchip.com/downloads/en/DeviceDoc/30009630M.pdf Overview Microcontroladores Microchip]<br />
<br />
==Homework==<br />
* [http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf Datasheet Atmega328p]<br />
<br />
*Ler:<br />
** 2. Visão Geral<br />
** 7. Núcleo AVR <br />
** Responder:<br />
*** Qual arquitetura de memória usada? <br />
*** Detalhes da ALU (Quais os tipos de operação?)<br />
*** Registradores (Status, Uso geral e de Pilha)<br />
*** Modos de endereçamento<br />
*** Conjunto de instruções (classes e exemplos)<br />
<br />
* Ler: <br />
** 8. Memórias do AVR<br />
*** Flash<br />
*** SRAM<br />
*** EEPROM<br />
** Responder<br />
*** Qual o tamanho e o formato da palavra de de dados?<br />
*** Qual o tamanho e o formato da palavra de instrução?<br />
<br />
= Aula 23/09/2019: Arquitetura do AVR =<br />
<br />
*'''Objetivos:'''<br />
** Finalizar CISC vs. RISC<br />
** Visão Geral dos Microcontroladores ATmega48A/PA/88A/PA/168A/PA/328/P<br />
** Núcleo do AVR (ALU e Banco de Registradores)<br />
** Hierarquia de Memórias do AVR<br />
<br />
*'''Notas de Aulas:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/mic-slides_5-AVR.pdf Introdução AVR]<br />
<br />
*'''Notas Extras:'''<br />
**Die do [https://siliconpr0n.org/archive/doku.php?id=azonenberg:atmel:atmega48 ATmega48] e do [https://siliconpr0n.org/archive/doku.php?id=azonenberg:atmel:atmega328 ATmega328]<br />
<br />
= Aula 23/09/2019: Arquitetura do AVR (cont.) =<br />
<br />
*'''Objetivos:'''<br />
** Finalizar os objetivos da última aula<br />
<br />
*'''Notas de Aulas:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/slides-AVR_aula01.pdf Introdução AVR]<br />
<br />
*'''Experimento:'''<br />
** Simulação do primeiro código em Assembly usando o MPLAB X IDE <br />
** [[Simular Assembly do AVR no MPLAB IDE | Criar projeto]]<br />
<code><br />
start:<br />
inc r16<br />
inc r17<br />
sts $0100,r16<br />
sts $0101,r16<br />
rjmp start<br />
</syntaxhighlight><br />
<br />
==Homework==<br />
* Instalar o MPLAB X e o XC8: [[Setup Ferramentas AVR para Assembly]]<br />
* Rodar o exemplo da aula para verificar<br />
<br />
<br />
= Aula 30/09/2019: Modos de Endereçamento =<br />
*'''Objetivos:'''<br />
**Introduzir arquitetura Load-Store<br />
**Entender: <br />
***Modos de endereçamento do AVR e <br />
***Instruções relacionadas a cada modo do ATmega328p<br />
**Implementar programas para compreensão dos novos conceitos<br />
<br />
*'''Notas de Aulas:'''<br />
**[http://docente.ifsc.edu.br/roberto.matos/mic_public/material/slides-AVR_aula02.pdf Modos de Endereçamento]<br />
<br />
==Homework==<br />
* OBS.: Instalar e configurar as ferramentas em casa para quem não fez (ver homework da aula passada).<br />
<br />
===Exercício 1===<br />
* Testar '''TODOS''' os trechos de códigos apresentados. Modifique os valores das localizações de memória afetadas para verificar se o funcionamento está coerente. <br />
<br />
*Exemplo:<br />
<code><br />
start:<br />
ldi R16,0x14<br />
rjmp start<br />
</syntaxhighlight><br />
* Pergunte-se:<br />
** A instrução em linguagem de máquina está coerente?<br />
** Se mudar o valor do imediato 0x14 para 0x25, como afeta a instrução montada? E se mudar o registrador de R16 para R17?<br />
** Eu posso carregar um imediato para o registrador R0? Por quê?<br />
* Faça isso para todos os trechos de código apresentados.<br />
<br />
===Exercício 2===<br />
*Faça um programa que some dois números de 8 bits: '''C = A + B'''<br />
*Considere as varáveis armazenadas sequencialmente a partir do primeiro endereço da memória SRAM.<br />
<br />
<br />
= Aula 01/10/2019: Modos de Endereçamento (cont.) =<br />
*'''Objetivos:'''<br />
**Corrigir exercícios da Aula prática<br />
**Mais exercícios<br />
<br />
*'''Exercícios: '''<br />
** Some as constantes 25, 14 e 0x32 e armazene o resultado em R0.<br />
** Some as constantes 32 e 0x23 e armazene o resultado em uma variável na SRAM (endereço 0x010A).<br />
**Re-implemente o código abaixo usando endereçamento indireto para acessar o R0 como posição de memória na SRAM:<br />
:<code><br />
ldi r16, $BB<br />
mov r0, r16<br />
</syntaxhighlight><br />
<br />
<br />
==Homework==<br />
* Estudar instruções de desvio e aritméticas<br />
* Escrever códigos que:<br />
#Execute 1.000 vezes uma ação em loop.<br />
#Execute 100.000 vezes uma ação em loop.<br />
#Carregue na SRAM 10 valores sequenciais a partir do endereço 0x0102 usando endereçamento de dados indireto com pós-incremento.<br />
#Tenha o mesmo resultado do programa anterior, mas que utilize endereçamento de dados indireto com pré-decremento.<br />
<br />
<br />
<br />
= Aula 01/10/2019: Instruções Aritmética e desvio =<br />
*'''Objetivos:'''<br />
**Corrigir exercícios da Aula prática<br />
**Mais exercícios<br />
<br />
*'''Exercícios: '''<br />
**Faça programas que utilizem a rotação para esquerda e direita. Quais os tipos de rotação possível? Quais os bits de status podem ser modificados?<br />
** Faça a soma de dois valores de 16 bits usando os registradores.<br />
** Implemente estrutura de alto nível: IF-THEN-ELSE, WHILE e SWITCH-CASE</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=STE29008-2019-2&diff=162060STE29008-2019-22019-10-07T11:44:29Z<p>127.0.0.1: /* Classe de Interrupção Externa: */</p>
<hr />
<div>= Sistemas Embarcados: Diário de Aula 2019-2 =<br />
<br />
*'''Professor:''' [[Roberto de Matos]]<br />
*'''Encontros:''' 2ª e 4ª às 07:30h <br />
*'''Atendimento Paralelo:''' 4ª às 10h e 14h (1h cada)<br />
*[[STE-EngTel_(Plano_de_Ensino)| Plano de Ensino]].<br />
* [http://sigaa.ifsc.edu.br/ Cronograma de Aulas]: Conteúdo Programado no Portal SIGAA<br />
<br />
*[http://docente.ifsc.edu.br/roberto.matos/ste_public/adm/STE2019-2_notas.pdf Notas]<br />
<br />
= 29/07/2019 – Apresentação=<br />
<br />
* Apresentação do professor.<br />
* Apresentação da disciplina.<br />
* [https://m.eet.com/media/1246048/2017-embedded-market-study.pdf 2017 Embedded Markets Study]<br />
<br />
= 31/07/2019 – Introdução=<br />
*Notas de Aula:<br />
**[http://www.lisha.ufsc.br/teaching/esl/intro.pdf Introdução]<br />
**[http://www.lisha.ufsc.br/teaching/esl/esd.pdf Embedded Systems Development: Design Principles]<br />
<br />
= 05/08/2019 – GPIO=<br />
<br />
*Notas de Aula:<br />
**[http://www.lisha.ufsc.br/teaching/esl/esd.pdf Embedded Systems Development: Design Principles]<br />
<br />
*Experimento:<br />
**[[ESTE: General Purpose Input and Output (GPIO) | Lab 01: GPIO - Hello LED]]<br />
**[https://www.arduino.cc/en/Tutorial/DigitalPins Arduino - Digital Pins]<br />
<br />
<br />
*Definição das Duplas:<br />
** Daniel e Anderson<br />
** Ameliza e Natalia<br />
** Guilherme e Marcone<br />
** Allex e Douglas<br />
** Fabiano e Filipe Kuhnen<br />
** Felipe Cardoso e Luiza<br />
** Gustavo e Gabriel<br />
<br />
= 07/08/2019 – Experimento UART=<br />
*[https://www.arduino.cc/reference/en/language/functions/communication/serial/ Serial Arduino]<br />
<br />
*Experimentos:<br />
**[[ESTE:_Universal_Assynchronous_Receiver_and_Transmitter_(UART) | Lab 02: UART - Serial Communication]]<br />
**[[ESTE:_UART_-_Serial_Communication | Lab 03: UART - Master/Slave]]<br />
<br />
= 12/08/2019 – Projeto 1: Sensor de Temperatura - Arduino =<br />
<br />
* Notas de Aula:<br />
** https://www.arduino.cc/en/tutorial/AnalogInput<br />
** https://www.arduino.cc/reference/en/language/functions/analog-io/analogread/<br />
<br />
==Atividade==<br />
O objetivo deste experimento é apresentar um exemplo básico de programação de sistema embarcado com microcontrolador. Para isto, será desenvolvido um sensor de temperatura com comunicação serial utilizando a plataforma Arduino.<br />
<br />
*Material necessário:<br />
**Arduino Uno;<br />
**Termistor NTC 10KOhm;<br />
**Resistor 10KOhm;<br />
**Matriz de contato;<br />
**Computador com IDE do Arduino instalada.<br />
<br />
*Para completar o desafio, utilize o site arduino.cc como referência, e construa um sketch (programa na IDE do Arduino) que, a cada 1 segundo, pisque um LED (veja o LED já na placa do Arduino no pino 13), e leia um valor do sensor de temperatura e escreva, em graus celcius, na tela. Um pseudo-código da sua aplicação seria:<br />
<br />
<syntaxhighlight lang=c><br />
loop() {<br />
ligaLED();<br />
AdquireTemperatura(); // lê do ADC e converte para Celcius<br />
desligaLED();<br />
ImprimeResultado(); // pela serial<br />
dorme1segundo();<br />
}<br />
</syntaxhighlight><br />
<br />
*Para completar esta atividade, você precisará:<br />
**Montar um circuito com divisor de tensão utilizando o NTC e o resistor para aquisição do sinal através de uma porta analógica do Arduino<br />
**Especificar um modelo (equação) para obter o valor da resistência do NTC a partir do valor de tensão lido no canal analógico do Arduino;<br />
**Utilizar o modelo de [https://en.wikipedia.org/wiki/Steinhart–Hart_equation Steinhart-Hart] para obter a temperatura a partir da resistência;<br />
**Calibrar o seu sistema para temperaturas entre 0 e 50 graus celcius ([https://www.thinksrs.com/downloads/programs/Therm%20Calc/NTCCalibrator/NTCcalculator.htm utilize esta calculadora] e a tabela de resistência-temperatura do seu NTC abaixo);<br />
**No programa arduino, implemente duas versões do software: uma utilizando apenas "float" e outra utilizando apenas "int 32-bits" (compare as versões).<br />
<br />
*Entregue um relatório curto (1 página), comparando os resultados obtidos em termos de:<br />
**Uso de memória de programa (flash - código-fonte);<br />
**Uso de memória de dados (RAM);<br />
**Tempo necessário para o cálculo (conecte o pino do LED a um osciloscópio - o tempo que o LED fica acesso é o tempo que leva para fazer o cálculo).<br />
<br />
*Observações:<br />
** O trabalho deve ser executado em dupla.<br />
** Entrega até 18/08 via Sigaa<br />
<br />
<br />
http://docente.ifsc.edu.br/roberto.matos/ste_public/fig/NTC-10Kohm-tabela.jpg<br />
<br />
= 14/08/2019 – Projeto 1: Sensor de Temperatura - Arduino (cont.)=<br />
<br />
*Verificar "β parameter equation":<br />
** https://en.wikipedia.org/wiki/Thermistor<br />
<br />
= 19/08/2019 – Correção Projeto 1=<br />
* Implementado em conjunto a versão long e float.<br />
<br />
<br />
= 21/08/2019 – Usando C++=<br />
<br />
==Mudança de nível de abstração==<br />
*Arduino Mega --> ATmega2560 (Ex.: I/O Ports)<br />
*[http://docente.ifsc.edu.br/roberto.matos/ste_public/doc/sch_mega2560-original.pdf Esquemático Arduino Mega]<br />
*[http://docente.ifsc.edu.br/roberto.matos/ste_public/doc/sch_mega2560-clone_CH340G.pdf Esquemático Arduino Mega - CLONE]<br />
<br />
<!--<br />
*[https://www.arduino.cc/en/uploads/Main/arduino-mega2560-schematic.pdf Esquemático Arduino Mega]<br />
*[https://robotdyn.com/pub/media/0G-00005641==MEGA-PRO-CH340GATmega2560/DOCS/Schematic==0G-00005641==MEGA-PRO-CH340GATmega2560.pdf Esquemático Arduino Mega - CLONE]<br />
<br />
<br />
<br />
--><br />
<br />
[[Arquivo: portas_arduino_MEGA.png|800px]]<br />
<br />
<br />
Fonte: https://www.arduino.cc/en/Hacking/PinMapping2560<br />
<br />
<br />
<br />
[[Arquivo:megapdf.jpg|800px]]<br />
<br />
== ATmega2560: I/O Ports==<br />
*[http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2549-8-bit-AVR-Microcontroller-ATmega640-1280-1281-2560-2561_datasheet.pdf Datasheet ATmega2560]<br />
*[http://docente.ifsc.edu.br/roberto.matos/ste_public/doc/datasheet_ATmega2560.pdf Datasheet ATmega2560 (local)]<br />
<br />
*[http://www.avr-tutorials.com/digital/about-avr-8-bit-microcontrollers-digital-io-ports Resumo Portas]<br />
<br />
<br />
*Tabela verdade de configuração das portas:<br />
[[Arquivo:Port_Pin_Configurations.png|600px]]<br />
<br />
<br />
*Endereços registradores de I/O:<br />
[[Arquivo:io_registers_address_2560.png|800px]]<br />
<br />
==GCC, avr-libc==<br />
<br />
===Fluxo Ferramentas:===<br />
<br />
[[Arquivo:Avr-gcc.png|800px]]<br />
<br />
<br />
===AVR-LIBC:===<br />
*[https://www.nongnu.org/avr-libc/ avr-libc]<br />
*[https://www.nongnu.org/avr-libc/user-manual/group__demo__project.html A simple Project]<br />
<br />
===Desenvolvimento:===<br />
* É obrigatório a instalação das ferramentas (Toolchain e AVR-Libc).<br />
* O aluno pode escolher usar o MPLAB X ou montar seu próprio Makefile.<br />
<br />
* MPLAB X:<br />
** [https://www.microchip.com/mplab/mplab-x-ide MPLAB® X IDE v5.20]<br />
** [https://www.microchip.com/mplab/avr-support/avr-and-arm-toolchains-c-compilers AVR 8-bit Toolchain]<br />
<br />
*Makefile:<br />
** Tools: '''sudo apt-get install gcc-avr binutils-avr avr-libc gdb-avr avrdude'''<br />
**[http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/ Guia]<br />
**[http://docente.ifsc.edu.br/roberto.matos/ste_public/src/Makefile Exemplo Simples]<br />
**[https://gist.github.com/rynr/72734da4b8c7b962aa65 Exemplo Complexo]<br />
<br />
* Gravação:<br />
** [https://www.nongnu.org/avrdude/ avrdude]<br />
** MPLAB X: '''avrdude -c avrispmkII -P /dev/ttyUSB0 -D -p ${Device} -U flash:w:${ImagePath}:i''' <br />
** Terminal: '''avrdude -c avrispmkII -P<PORTA> -D -p ATmega2560 -U flash:w:<HEX>:i'''<br />
<br />
==Prática==<br />
*Implemente um programa usando GCC e avr-libc para ligar um led (D13) quando um botão (A0) for pressionado ([[ESTE:_General_Purpose_Input_and_Output_(GPIO)|exemplo]])<br />
*[https://www.geeksforgeeks.org/bitwise-hacks-for-competitive-programming/ Operação de Bits em C/C++]<br />
*[http://www.cplusplus.com/doc/boolean/ Operações Booleanas em C/C++]<br />
*[https://www.avrfreaks.net/forum/tut-c-bit-manipulation-aka-programming-101?name=PNphpBB2&file=viewtopic&t=37871 Programming 101 - By Eric Weddington]<br />
<br />
= 26/08/2019 – Usando C++ (cont.)=<br />
<br />
==Prática==<br />
*Configuração da ferramenta:<br />
** Tools -> Options -> Embedded -> Build Tools-> Add<br />
** Base Directory: '''/opt/microchip/avr8-gnu-toolchain/bin<br />
<br />
*Implemente um programa usando GCC e avr-libc para ligar um led (D13) quando um botão (A0) for pressionado ([[ESTE:_General_Purpose_Input_and_Output_(GPIO)|exemplo]])<br />
<br />
==Notas==<br />
*[https://www.geeksforgeeks.org/bitwise-hacks-for-competitive-programming/ Operação de Bits em C/C++]<br />
*[http://www.cplusplus.com/doc/boolean/ Operações Booleanas em C/C++]<br />
*[https://www.avrfreaks.net/forum/tut-c-bit-manipulation-aka-programming-101?name=PNphpBB2&file=viewtopic&t=37871 Programming 101 - By Eric Weddington]<br />
<br />
<br />
= 28/08/2019 – Usando C++ Serial =<br />
==Objetivos==<br />
* Entender o periférico Serial e implementar métodos de configuração, envio e recepção. <br />
*[http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2549-8-bit-AVR-Microcontroller-ATmega640-1280-1281-2560-2561_datasheet.pdf Datasheet ATmega2560]<br />
<br />
==Experimento==<br />
* Implementar comunicação serial 9600bps 8N1<br />
<br />
<br />
= 02/09/2019 – Usando C++ ADC =<br />
==Objetivos==<br />
* Entender o periférico ADC e implementar métodos de configuração e leitura do ADC.<br />
*[http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2549-8-bit-AVR-Microcontroller-ATmega640-1280-1281-2560-2561_datasheet.pdf Datasheet ATmega2560]<br />
<br />
==Experimento==<br />
* Implementar leitura do ADC<br />
<br />
==Exercício==<br />
* Implementar o "sensor de temperatura" com C++ e AVR-LIBC<br />
* Comparar o tamanho do código gerado<br />
* Entrega: 08/09<br />
<br />
<br />
= 04/09/2019 – Interrupção =<br />
*Desafio:<br />
**Usando Round Robin sem interrupções implementar um sistema com um LED e um botão. O sistema deve piscar o LED (D13) a cada 1 segundos e ao botão (D2) ser pressionado envia uma mensagem pela serial.<br />
<br />
*Notas de Aula:<br />
**[http://www.lisha.ufsc.br/teaching/esl/esd.pdf Embedded Systems Development: Design Principles]<br />
<br />
*Experimentos:<br />
**[[ESTE:_GPIO_and_External_Interrupts_-_part_1 | Lab 04: GPIO and External Interrupts - part 1]]<br />
**[[ESTE:_GPIO_and_External_Interrupts_-_part_2 | Lab 05: GPIO and External Interrupts - part 2]]<br />
<br />
*Referências:<br />
**[https://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html Interrupções AVR-Libc]<br />
<br />
<br />
= 09/09/2019 – Classe GPIO =<br />
* Análise GPIO:<br />
** avr-objdump -h -S <PROJECT_NAME>.elf > <PROJECT_NAME>.lst<br />
*[https://drive.google.com/open?id=1-Duj1Ofn1B4K1mi_MfhXVml8XcJv0AOhAhWjeak-Qf8 Mapeamento de Pinos Arduino Mega]<br />
<br />
* Classe GPIO_v1 discutida em sala de aula.<br />
** [http://docente.ifsc.edu.br/roberto.matos/ste_public/src/gpio_v1.zip GPIO v1 ]<br />
<br />
*Exercício:<br />
** Implementar classe GPIO com ponteiros para as portas.<br />
** Verificar tamanho do "set" e da ocupação da memória de dados<br />
** Comparar com a primeira versão.<br />
<br />
<br />
<syntaxhighlight lang=c><br />
#include <avr/io.h><br />
#include <util/delay.h><br />
#include "GPIO.h"<br />
<br />
<br />
//LEDS PLACA (acende com '0')<br />
GPIO led0(0, GPIO::OUTPUT); //PE0<br />
GPIO led1(1, GPIO::OUTPUT); //PE1<br />
<br />
//LEDS PLACA (acende com '1')<br />
GPIO led13(13, GPIO::OUTPUT); //PB7<br />
<br />
//Adicionar LED<br />
GPIO led4(4, GPIO::OUTPUT); //PG5<br />
GPIO led6(6, GPIO::OUTPUT); //PH0<br />
<br />
int main(void){<br />
<br />
UCSR0B = 0;<br />
<br />
led0.set(1);<br />
led1.set(1);<br />
led6.clear();<br />
led4.clear();<br />
led13.clear();<br />
_delay_ms(1000);<br />
led0.clear();<br />
led1.clear();<br />
led6.set(1);<br />
led4.set(1);<br />
led13.set(1);<br />
_delay_ms(1000);<br />
<br />
while (1){<br />
led0.toggle();<br />
led1.toggle();<br />
led6.toggle();<br />
led4.toggle();<br />
led13.toggle();<br />
_delay_ms(1000);<br />
}<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
[[Arquivo:megapdf.jpg|800px]]<br />
<br />
= 10/09/2019 – Classe GPIO (cont.) =<br />
* Re-fatoração da classe GPIO<br />
** [http://docente.ifsc.edu.br/roberto.matos/ste_public/src/GPIO_Port.zip GPIO Port]<br />
<br />
* Experimento:<br />
** Implementar a classe GPIO_v1.3 com o GPIO_Port.<br />
** Verificar o consumo da memória de dados e programa? Por que o consumo da memória de dados foi 23 bytes?<br />
<br />
* Exercício (fora da sala de aula):<br />
** Implementar todas as versões compreendendo os conceitos de modelagem (v1.2 e v1.3).<br />
** Implementar a v2.0 com o construtor indexado (informações abaixo) entendendo o conceito da indexação dos pinos a partir do id.<br />
** Implementar a v3.0 com todos os pinos do Arduino Mega. Apoio: [https://drive.google.com/open?id=1-Duj1Ofn1B4K1mi_MfhXVml8XcJv0AOhAhWjeak-Qf8 Mapeamento de Pinos Arduino Mega]<br />
<br />
<br />
<br />
* Modificação GPIO.cpp (uso)<br />
<syntaxhighlight lang=c><br />
GPIO::GPIO(uint8_t id, PortDirection_t dir)<br />
{<br />
_bit = GPIO_PORT::id_to_bit[id];<br />
_port = GPIO_PORT::AllPorts[GPIO_PORT::id_to_port[id]];<br />
_port->dir(_bit, dir);<br />
}<br />
</syntaxhighlight><br />
<br />
*Modificação GPIO_Port.h (dentro do namespace GPIO_PORT)<br />
<syntaxhighlight lang=c><br />
extern GPIO_Port * AllPorts[4];<br />
extern const uint8_t id_to_port[14];<br />
extern const uint8_t id_to_bit[14];<br />
</syntaxhighlight><br />
<br />
<br />
*Modificação GPIO_Port.cpp (dentro do namespace GPIO_PORT)<br />
<syntaxhighlight lang=c><br />
GPIO_Port * AllPorts[4] = {<br />
reinterpret_cast<GPIO_Port*>(AVR_PB),<br />
reinterpret_cast<GPIO_Port*>(AVR_PE),<br />
reinterpret_cast<GPIO_Port*>(AVR_PG),<br />
reinterpret_cast<GPIO_Port*>(AVR_PH)<br />
};<br />
<br />
<br />
enum Ports_index {<br />
PB_i = 0,<br />
PE_i = 1,<br />
PG_i = 2,<br />
PH_i = 3<br />
};<br />
<br />
const uint8_t id_to_port[14] = {<br />
PE_i ,<br />
PE_i ,<br />
PE_i ,<br />
PE_i ,<br />
PG_i ,<br />
PE_i ,<br />
PH_i ,<br />
PH_i ,<br />
PH_i ,<br />
PH_i ,<br />
PB_i ,<br />
PB_i ,<br />
PB_i ,<br />
PB_i<br />
};<br />
<br />
const uint8_t id_to_bit[14] = {<br />
(1 << (0)) ,<br />
(1 << (1)) ,<br />
_BV( 4 ) ,<br />
_BV( 5 ) ,<br />
_BV( 5 ) ,<br />
_BV( 3 ) ,<br />
_BV( 3 ) ,<br />
_BV( 4 ) ,<br />
_BV( 5 ) ,<br />
_BV( 6 ) ,<br />
_BV( 4 ) ,<br />
_BV( 5 ) ,<br />
_BV( 6 ) ,<br />
_BV( 7 )<br />
};<br />
</syntaxhighlight><br />
<br />
= (16/09/2019) – Classe UART Bloqueante =<br />
<br />
Proposta e implementação da UART Bloqueante<br />
* Usar a implementação feita em sala de aula e encapsular na classe abaixo. <br />
*Dúvidas: Ler o capítulo 22 do datasheet (USART). Atenção especial as seguintes seções<br />
**"Clock Generation"<br />
**"USART Initialization"<br />
**"Sending Frames with 5 to 8 Data Bit"<br />
**"Receiving Frames with 5 to 8 Data Bits"<br />
**"Register Description"<br />
<br />
*Diagrama de Classe:<br />
http://docente.ifsc.edu.br/roberto.matos/ste_public/uml/UART_bloqueante.png<br />
<br />
<br />
<syntaxhighlight lang=c><br />
#include <avr/io.h><br />
#include <util/delay.h><br />
#include "UART.h"<br />
<br />
UART uart(115200, UART::DATABITS_8, UART::NONE, UART::STOPBIT_1);<br />
<br />
int main(){<br />
uint8_t echo;<br />
char msg[] = "Byte Received: ";<br />
<br />
while(1){<br />
echo = uart.get();<br />
uart.puts(msg);<br />
uart.put(echo);<br />
uart.put('\n');<br />
}<br />
<br />
return 1;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
= (18/09/2019) – Classe UART com interrupção =<br />
<br />
* Dúvidas: Ler manuais da AVR-LIBC<br />
** https://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html<br />
** https://www.microchip.com/webdoc/AVRLibcReferenceManual/group__avr__interrupts.html<br />
** Ler o capítulo 14 do datasheet (Interrupts).<br />
** Ler Seção "7.8 Reset and Interrupt Handling"<br />
** Ler o capítulo 22 do datasheet (USART). Atenção especial as seguintes seções:<br />
***"Transmitter Flags and Interrupts" <br />
***"Receive Compete Flag and Interrupt"<br />
***"Register Description"<br />
*Atenção, a interrupção TXCIEn não deve ser usada - normalmente ela é utilizada apenas para implementar protocolos com reconhecimento/ack;<br />
*Diagrama de Classe:<br />
http://docente.ifsc.edu.br/roberto.matos/ste_public/uml/UART_interrupt.png<br />
<br />
<br />
== Exercício ==<br />
* Implementar Fila e adicionar na Classe UART com interrupção.<br />
http://docente.ifsc.edu.br/roberto.matos/ste_public/uml/UART_interrupt_queue.png<br />
<br />
= (23/09/2018) – Análise do Andamento dos Exercícios =<br />
* Verificação dos alunos com relação as dúvidas<br />
* Análise das implementações executadas até o momento<br />
<br />
<br />
<br />
= (24/09/2018) – Timer e Timeouts =<br />
<br />
* Leitura capítulo 16 ("8-bit Timer/Counter0 with PWM").<br />
*Adaptar e testar a classe timer fornecida para o Atmega2560:<br />
**[http://docente.ifsc.edu.br/roberto.matos/ste_public/src/Timer.zip Classe Timer]<br />
**[https://pt.wikipedia.org/wiki/Singleton Singleton]<br />
<br />
*Implementar a classe Timeout e e inserir os métodos "TimeoutManager" e "addTimeout" na classe Timer:<br />
http://docente.ifsc.edu.br/roberto.matos/ste_public/uml/timeouts.png<br />
<br />
<syntaxhighlight lang=c><br />
#include <avr/io.h><br />
#include <avr/interrupt.h><br />
#include "GPIO.h"<br />
#include "Timer.h"<br />
<br />
<br />
GPIO p2(2, GPIO::OUTPUT);<br />
GPIO p3(3, GPIO::OUTPUT);<br />
GPIO p4(4, GPIO::OUTPUT);<br />
GPIO p5(5, GPIO::OUTPUT);<br />
<br />
void timeout2_handler(void){<br />
p2.toggle();<br />
}<br />
<br />
void timeout3_handler(void){<br />
p3.toggle();<br />
}<br />
<br />
void timeout4_handler(void){<br />
p4.toggle();<br />
}<br />
<br />
void timeout5_handler(void){<br />
p5.toggle();<br />
}<br />
<br />
<br />
Timer t = Timer(1000);<br />
<br />
int main(){<br />
<br />
sei();<br />
t.addTimeout(1000, &timeout2_handler);<br />
t.addTimeout(2000, &timeout3_handler);<br />
t.addTimeout(3000, &timeout4_handler);<br />
t.addTimeout(4000, &timeout5_handler);<br />
while(true){<br />
t.timeoutManager();<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
= (30/09/2018) – Timer e Timeouts (cont.)=<br />
* Finalizar a implementação da classe Timeouts.<br />
<br />
* Desenvolvimento C++<br />
** 21/08 e 26/08: Botão LED<br />
** 28/08: Transmissão Serial Bloqueante<br />
* ISR com a AVR-LIBC<br />
** 04/09: Desafio e Interrupção Externa<br />
*Consumo Memória (Dados e Programa), LSS<br />
** 09/09: GPIO_v1 ("case")<br />
** 10/09: GPIO_v1.2 (ponteiros DDR, PORT, PIN)<br />
*Refatoração Classe <br />
** 10/09: GPIO_v1.3 (GPIO_Port)<br />
*Indexação do Construtor<br />
** 16/09: GPIO_v2 (wiki) e GPIO_v3 (todos os pinos do Mega)<br />
<br />
*Modelando Classes:<br />
**16/09: Classe UART Bloqueante<br />
**18/09: Classe UART com interrupção (tarefa: adicionar FIFO)<br />
**24/09: Classe Timer/Timeout<br />
<br />
<br />
= (02/10/2018) – A3 =<br />
* Avaliação individual prática em sala de aula.<br />
<br />
<br />
= (07/10/2018) – Correção A3 e Interrupção =<br />
* Correção da A3<br />
<br />
<br />
==Classe de Interrupção Externa: ==<br />
* A [http://docente.ifsc.edu.br/roberto.matos/ste_public/src/extint.zip Classe extint] funciona para as 8 interrupções externas (INTn). Não confundir com a PCINTn.<br />
<br />
* Ler manuais da AVR-LIBC:<br />
** https://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html<br />
** https://www.microchip.com/webdoc/AVRLibcReferenceManual/group__avr__interrupts.html<br />
<br />
* Ler o capítulo 14 do datasheet (Interrupts).<br />
* Ler Seção "7.8 Reset and Interrupt Handling"<br />
* Ler o capítulo 15 do datasheet (External Interrupts). Atenção especial as seguintes seções:<br />
**"Register Description" (EICRA, EICRB, EIMSK e EIFR)<br />
<br />
*Diagrama de Classe:<br />
http://docente.ifsc.edu.br/roberto.matos/ste_public/uml/ExtInt.png<br />
<br />
*Atividade<br />
** Fazer proposta de integração com a GPIO<br />
** Codificar e fazer teste</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=ADS29009-2019-2&diff=162037ADS29009-2019-22019-10-04T18:34:06Z<p>127.0.0.1: /* Aula 14 - Dia 27/09/2019 */</p>
<hr />
<div>=AULA 1 - Dia 30/07/2019=<br />
<br />
==Objetivos==<br />
<br />
*Apresentação da Disciplina (SIGA A)<br />
*Plano de Ensino (SIGA A)<br />
*Avaliação (SIGA A)<br />
<br />
==Introdução a ADS==<br />
<br />
*Que projeto estou fazendo? Como procedo para fazer uma ADS?<br />
<br />
==Tarefa A1.1==<br />
<br />
*Pesquisar um artigo sobre ADS em uma área de seu interesse. Analisar um arquivo a luz das etapas e conceitos discutidos nesta semana.<br />
Fazer slides que devem ser postados na data anterior da apresentação. O slide deve apresentar:<br />
*Objetivo da ADS no artigo<br />
*Métricas <br />
*Parâmetros<br />
*Fatores<br />
*Workload<br />
*Técnicas usadas<br />
*Resumo de como são apresentados os dados<br />
*Conclusão Pessoal<br />
<br />
APRESENTAÇÃO: Dia 9/8/2019<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/2egcm7xkmmqjqv1/IntroducaoAvaliacaoDesempenho.pdf?dl=0 Slides de Introdução a ADS]<br />
<br />
=AULA 2 - Dia 2/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Continuação conceitos de ADS<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/2egcm7xkmmqjqv1/IntroducaoAvaliacaoDesempenho.pdf?dl=0 Slides de Introdução a ADS]<br />
<br />
=AULA 3 - Dia 9/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Finalização Introdução ADS<br />
*Apresentação dos Trabalhos<br />
<br />
=AULA 4 - Dia 13/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Introdução a DTMC<br />
<br />
==Materialde Referência==<br />
<br />
https://www.dropbox.com/s/oz2dlua2kmc1w2m/CadeiasDeMarkovDiscretas_Parte1.pdf?dl=0<br />
<br />
=AULA 5 - Dia 16/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Continuação DTMC<br />
<br />
==Material de Referência==<br />
<br />
https://www.dropbox.com/s/oz2dlua2kmc1w2m/CadeiasDeMarkovDiscretas_Parte1.pdf?dl=0<br />
<br />
==Links Interessantes==<br />
<br />
*[http://setosa.io/ev/markov-chains/]<br />
<br />
=AULA 6 - Dia 23/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Continuação DTMC<br />
*Simulação DTMC<br />
<br />
==Itens a constar da atividade de simulação==<br />
<br />
*código fonte matlab<br />
*minirelatório com:<br />
**comparação dos resultados das probabilidades em regime estacionário conforme slide;<br />
**resposta as questões do slide<br />
**Uma pdf das transições de primeira passagem para os estados colocados no slide. <br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/miyswj7r4bil8fb/CadeiasDeMarkovDiscretas_Parte2.pdf DTMC parte2]<br />
<br />
* https://www.dropbox.com/s/hvgk42nhhcsyjlt/SimMarkovAlunos.m<br />
<br />
<syntaxhighlight lang=c><br />
P = [ <br />
0.2 0 0.8 0 0 0 0 0 0 0;<br />
0 0.2 0.3 0.3 0.2 0 0 0 0 0;<br />
0 0 0.1 0 0 0.9 0 0 0 0;<br />
0 0 0 0 0 0 1.0 0 0 0;<br />
0 0 0 0 0 0.3 0.7 0 0 0;<br />
0 0 0 0 0 0 0 0.2 0 0.8;<br />
0 0 0 0 0 0 0 0 0.8 0.2;<br />
1.0 0 0 0 0 0 0 0 0 0;<br />
0 1.0 0 0 0 0 0 0 0 0;<br />
0.2 0.6 0 0 0 0 0 0 0 0.2;<br />
];<br />
</syntaxhighlight><br />
<br />
=AULA 7 - Dia 27/08/2019=<br />
<br />
*Simulação da DTMC (conclusão)<br />
<br />
=AULA 8 - Dia 30/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Aplicações de DTMC: Aloha Puro<br />
*Discussão de Projeto usando os Mindstorms<br />
<br />
==Slides desta Aula==<br />
<br />
*[https://www.dropbox.com/s/miq14l2hp0uxqky/AplicacoesCadeiasDeMarkovDiscretas_SomenteMAC.pdf?dl=0 Slides Aloha Puro ]<br />
<br />
=Aula 9 - Dia 06/09/2019=<br />
<br />
*Introdução a CTMC<br />
*Projeto de Desempenho sobre o Robô<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/oh9br0no8wmwz4o/CadeiasDeMarkovCont_nuas_Parte1.pdf Slides CTMC - parte1]<br />
<br />
==Links sobre o EV3==<br />
<br />
*[https://www.ev3dev.org/ Site Ev3 - Opções de Programação]<br />
*[https://c4ev3.github.io/ Biblioteca C++ from Germany]<br />
<br />
<br />
=Aula 10 - Dia 10/09/2019=<br />
<br />
<br />
*Instalação de tools C++ no ev3<br />
<br />
Usar máquina virtual com Ubuntu 18.04<br />
<br />
Fazer conforme <br />
<br />
*Toolchain<br />
<br />
O make e o gcc devem estar instalados.<br />
<br />
https://c4ev3.github.io/ (Lembrar que são ferramentas 32 bits)<br />
sudo apt-get install lib32ncurses5 lib32z1<br />
sudo apt-get install libudev-dev pkg-config<br />
wget -c http://www.codesourcery.com/sgpp/lite/arm/portal/package4571/public/arm-none-linux-gnueabi/arm-2009q1-203-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2<br />
mkdir CodeSourcery<br />
tar -jxvf ~/arm-2009q1-203-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2 -C ~/CodeSourcery/<br />
echo export PATH=~/CodeSourcery/arm-2009q1/bin/:$PATH >> ~/.bashrc && . ~/.bashrc <br />
<br />
*Uploader (não usei diretamente pois fiz scp para robot@IP_ROBO (password "maker".<br />
<br />
git clone --recursive https://github.com/c4ev3/ev3duder<br />
<br />
Entrar e compilar usando o make<br />
Entrar em EV3-API/API e compilar. EU tive que editar o Makefile para remover a referência ao Windows<br />
<br />
*Compilar<br />
arm-none-linux-gnueabi-gcc -I../EV3-API/API -L../EV3-API/API/ alo.c -lev3api<br />
<br />
=Aula 11 - Dia 13/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*CTMC - Aplicações: modelagelam da alocação de GTS no IEEE802.15.4<br />
<br />
==Problema (simplificação do GTS no IEEE 802.15.4==<br />
<br />
O padrão de rede sem fio IEEE802.15.4 prevê a comunicação sem BEACON (CSMA-CA) e com BEACON, onde parte do frame possui até 7 canais que podem ser alocados sob demanda por um coordenaodor (supor topologia em estrela com coordenador no centro). A alocação é realizada em canal de controle a parte. Construir uma cadeia de Markov em Tempo Contínuo de forma:<br />
<br />
(i) a computar a probabilidade de bloqueio. Supor N nodos com número médio de requisições <math>lambda</math><br />
<br />
(ii) como poderia ser computada a vazão esperada do sistema?<br />
<br />
(iii) como poderíamos estimar a vazão na parte CSMA-CA (supor comportamento como Slotted Aloha)<br />
<br />
(iv) na parte GTS, como poderíamos considerar dois grupos de nodos onde o primeiro grupo pode ocupar os 7 slots e o segundo grupo, com taxa diferente poderia ocupar até dois slots?<br />
<br />
=Aula 12 - Dia 20/09/2019=<br />
<br />
*Introdução a Teoria de Filas<br />
*Filas MM1 com buffer ilimitado<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/ayq1hek9xxglpmn/TeoriaDeFilas_Introducao.pdf Introdução a Teoria de Filas]<br />
*[https://www.dropbox.com/s/yg391s7nipbqxbr/Filas_MM1_CapacidadeIlimitada.pdf Filas MM1]<br />
<br />
=Aula 13 - Dia 24/09/2019=<br />
<br />
==Objteivos==<br />
<br />
*Desenvolvimento de Projeto de ADS<br />
<br />
==Visão geral do Software no Mindstorm==<br />
<br />
[[imagem:ADSProjetoMindstorm.png|600px]]<br />
<br />
==Especificação dos Recursos Rest==<br />
<br />
==Especificação das mensagens no socket==<br />
<br />
O "programa sob teste" se conecta no servidor Flask através de um socket. O programa se comporta como um servidor<br />
que recebe comandos atraváes de uma string de tamanho fixo (15 caracteres). A todo comando ele envia uma resposta também de 15 caracteres.<br />
<br />
No momento que recebe um comando o programa deve ler o tempo do sistema e ao enviar uma resposta ele deverá ler novamente o tempo e enviá-lo<br />
na string de resposta;<br />
<br />
Formato da string (ideal seria usar padrão: XML,JSON?). Vantagem de usar XML seria usar uma biblioteca padrão.<br />
<br />
Comando;P:par1;P:par2;...;TE:...tempo;TS:tempo<br />
<br />
Pontos a verificar:<br />
<br />
*o tamanho da string deveria ser aumentada ou flexibilizado?<br />
<br />
<br />
==Especificação do Gerador de Cargas/Monitor==<br />
<br />
*O gerador de carga deverá ler uma especificação de um arquivo e gerar a carga. Prever identificação do Experimento e da Repetição.<br />
*O monitor deverá ler as respostas e armazená-las devidamente em arquivo.<br />
*Um analisador/visalizador de dados deverá permitir sumarizar dados, gerar intervalo de confiança e mostrar os resultados<br />
<br />
==Módulo de Processamento Autônomo==<br />
<br />
==Referências==<br />
<br />
*[https://www.lego.com/cdn/cs/set/assets/bltbef4d6ce0f40363c/LMSUser_Guide_LEGO_MINDSTORMS_EV3_11_Tablet_ENUS.pdf Guia Ev3]<br />
*[http://www.inpharmix.com/jps/PID_Controller_For_Lego_Mindstorms_Robots.html PID explained]<br />
*[https://biblio.ugent.be/publication/8563711/file/8563712.pdf Autonomous Navigation Robot]<br />
*[https://www.ev3dev.org/docs/tutorials/tacho-motors/ Using tacho motors Using Tacho Motors]<br />
<br />
=Aula 14 - Dia 27/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Revisão Fila M/M/1<br />
*Fila M/M/1/c (c servidores)<br />
<br />
==Material de Referência para esta aula==<br />
<br />
*[https://www.dropbox.com/s/2vo6nlywwsfeonr/FilaMMc_MultiplosServidores.pdf?dl=0 Filas M/M/1/c]<br />
<br />
<br />
<br />
=Aula 15 - Dia 04/10/2019=<br />
<br />
==Objetivos==<br />
<br />
*Revisão Fila M/M/n<br />
*Fila M/M/1/K<br />
<br />
==Material de Referência para esta aula==<br />
<br />
https://www.dropbox.com/s/jycdd2dzqqsxb5g/FilaMM1_CapacidadeLimitada.pdf?dl=0<br />
<br />
=Livros sobre ADS=<br />
<br />
*[https://www.amazon.com/Foundations-Software-System-Performance-Engineering/dp/0321833821/ref=sr_1_2?keywords=Workload+Modeling+for+Computer+Systems+Performance+Evaluation&qid=1566306559&s=gateway&sr=8-2]<br />
*[https://www.amazon.com/Workload-Modeling-Computer-Performance-Evaluation/dp/1107078237/ref=sr_1_1?keywords=Workload+Modeling+for+Computer+Systems+Performance+Evaluation&qid=1566307081&s=gateway&sr=8-1]<br />
*[https://www.amazon.com/Performance-Evaluation-Network-Services-Protocols-ebook/dp/B06XSQ392S/ref=sr_1_4?keywords=Workload+Modeling+for+Computer+Systems+Performance+Evaluation&qid=1566306764&s=gateway&sr=8-4]<br />
*[https://www.amazon.com/Effects-Traffic-Structure-Application-Performance-ebook/dp/B00APXDHLG/ref=sr_1_6?keywords=Workload+Modeling+for+Computer+Systems+Performance+Evaluation&qid=1566306809&s=gateway&sr=8-6#reader_B00APXDHLG]<br />
*[https://www.amazon.com/Performance-Modeling-Design-Computer-Systems/dp/1107027500/ref=sr_1_fkmr3_1?keywords=Workload+Modeling+for+Computer+Systems+Performance+Evaluation&qid=1566306892&s=gateway&sr=8-1-fkmr3#reader_1107027500]<br />
*[https://www.amazon.com/Analytical-Performance-Modeling-Computer-Systems/dp/1627052690/ref=sr_1_fkmr3_2?keywords=Workload+Modeling+for+Computer+Systems+Performance+Evaluation&qid=1566307106&s=gateway&sr=8-2-fkmr3#reader_1627052690]<br />
*[http://lipas.uwasa.fi/~tsottine/psp/psp.pdf]<br />
<br />
=Links Interessantes=<br />
<br />
*[http://web.iitd.ac.in/~jbseo/ell785/Queueing_2017_Fall.pdf]</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=SOP29005-2019-2&diff=162036SOP29005-2019-22019-10-04T18:06:46Z<p>127.0.0.1: /* PARTE 3 - POSIX Semaphores */</p>
<hr />
<div>=AULA 1 - Dia 30/07/2019=<br />
<br />
===Objetivos/Conteúdos===<br />
<br />
*Apresentação do Plano de Ensino<br />
**Objetivos e Conteúdo Programático da Disciplina (ver SIGAA)<br />
**Forma de Avaliação (ver SIGAA)<br />
<br />
*Introdução a Sistemas Operacionais (Cap1. do Silberschatz)<br />
**O que faz um sistema operacional (1.1)<br />
**Organização e Arquitetura de um Sistema Computacional (1.2 e 1.3)<br />
***Importância da Interrupção e Timers (1.2.1)<br />
***Estrutura de Armazenamento (1.2.2)<br />
***Estrutura de IO (1.2.3)<br />
**Estrutura e Operações de um Sistema Operacional (1.4 e 1.5)<br />
<br />
===Material de Referência===<br />
<br />
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte1.pdf Apresentação sobre histórico visão geral e estruturas básicas de um SO]<br />
* [http://codex.cs.yale.edu/avi/os-book/OSE1/slide-dir/index.html Slides Silberschatz Oitava Edição]<br />
* [http://professor.unisinos.br/barbosa/SO/ch1br.ppt Tradução Slides Silberschatz Cap1]<br />
* [http://professor.unisinos.br/barbosa/SO/ch2br.ppt Tradução Slides Silberschatz Cap2]<br />
* [http://professor.unisinos.br/barbosa/SO/ch3br.ppt Tradução Slides Silberschatz Cap3]<br />
* [http://professor.unisinos.br/barbosa/SO/ch4br.ppt Tradução Slides Silberschatz Cap4]<br />
* [http://wiki.inf.ufpr.br/maziero/doku.php?id=so:livro_de_sistemas_operacionais Livro do Prof.Maziero]<br />
* [http://deptinfo.unice.fr/~rr/l3systres/ Université Nice Sophia Antipolis]<br />
<br />
Arliones:<br />
<br />
*[https://www.dropbox.com/s/dt80g3tml65rpmg/SOP29005-parte6.odp?dl=0]<br />
*[https://www.dropbox.com/s/7lneavq0go9kz2t/SOP29005-parte7.odp?dl=0]<br />
<br />
===Leitura Recomendada===<br />
<br />
*Cap.1 do Silberschatz principalmente:<br />
**1.1 a 1.9<br />
<br />
===Exercícios Práticos de Apoio a Aula===<br />
<br />
Na sequência. com fins motivacionais, são apresentados alguns exercícios ilustrando conceitos de processos, arquivos e permissionamento.<br />
<br />
<ol><br />
<li><br />
Comando para ver todos os processos no linux:<br />
<code><br />
$ ps aux<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Colocar 2 processos se executando no contexto de um terminal e verificar número dos processos e então "destruí-los":<br />
<code><br />
$ yes > /dev/null<br />
$ yes > /dev/null<br />
$ ps <br />
$ kill -9 <pid_yes><br />
$ kill -9 <pid_yes><br />
</syntaxhighlight><br />
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.<br />
</li><br />
<li><br />
Criar um terminal adicional<br />
<code><br />
$ xterm<br />
</syntaxhighlight><br />
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:<br />
<code><br />
$ echo Alo Terminal > /dev/pts/2<br />
$ kill -9 <pid_terminal><br />
</syntaxhighlight><br />
</li><br />
<li><br />
Comunicação entre processos:<br />
<code><br />
$ cat /etc/passwd | grep home | wc -l<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Retirando a permissão de leitura de um arquivo em nível de usuário proprietário:<br />
<code><br />
$ echo Alo Mundo > alfa.txt<br />
$ ls -l alfa.txt<br />
$ cat alfa.txt<br />
$ chmod u-r alfa.txt<br />
$ cat alfa.txt<br />
$ chmod u+r alfa.txt<br />
$ cat alfa.txt <br />
</syntaxhighlight><br />
</li><br />
</ol><br />
<br />
=AULA 2 - Dia 2/08/2019=<br />
<br />
===Objetivos/Conteúdos===<br />
<br />
*Continuação da Aula<br />
*Estruturas do Sistema Operacional (cap.2)<br />
**Serviços do Sistema Operacional (2.1)<br />
**Interfaces com Usuários (2.2)<br />
**Chamadas do Sistema (2.3)<br />
**Tipos de Chamadas de Sistema (2.4) ver Fig.2.8<br />
***Chamadas de Controle de Processos<br />
**Arquiteturas e Estruturas de Sistemas Operacionais (2.7)<br />
**Máquinas Virtuais (2.8)<br />
<br />
===Material de Referência===<br />
<br />
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte1.pdf Apresentação sobre histórico visão geral<br />
* [http://www.fil.univ-lille1.fr/~sedoglav/OS/TP.html ]<br />
<br />
===Leitura Recomendada===<br />
<br />
*Cap.2 do Silberschatz principalmente:<br />
**2.1 a 2.8<br />
<br />
===Exercícios===<br />
<br />
=AULA 3 - Dia 7/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*Continuação da aula anterior<br />
**Chamadas do Sistema (2.3)<br />
**Tipos de Chamadas de Sistema (2.4) ver Fig.2.8<br />
***Chamadas de Controle de Processos<br />
**Arquiteturas e Estruturas de Sistemas Operacionais (2.7)<br />
**Máquinas Virtuais (2.8)<br />
<br />
===Exercícios===<br />
<br />
<ol><br />
<li> Estudar e executar o código em http://cs.lmu.edu/~ray/notes/gasexamples/ <br />
Detalhes das chamadas na arquitetura x86_64 ver em https://lwn.net/Articles/604287/ <br />
<li>Estudar (usar o man) e executar o código usando a função (em conformidade com a API POSIX) write() para o ''hello world'':<br />
<code><br />
#include <unistd.h> <br />
<br />
main()<br />
{<br />
write(1,"Alo Mundo\n",10);<br />
}<br />
</syntaxhighlight><br />
</li><br />
<li> Use o comando strace para verificar todas as chamadas de sistema dos programas acima.<br />
</li><br />
<li><br />
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() 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:<br />
<code><br />
void meu_hello();<br />
<br />
int main()<br />
{<br />
meu_hello();<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
</li><br />
Gere o assembly do código em C e discuta a diferença entre uma chamada de função e uma chamada de sistema.<br />
<li><br />
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:<br />
<code><br />
#include <string.h><br />
main()<br />
{<br />
char *p="Tudo bem com vocês?";<br />
meu_hello_world(p, strlen(p));<br />
}<br />
</syntaxhighlight><br />
Solução:<br />
{{collapse top|Solução}}<br />
<code><br />
modificado de http://cs.lmu.edu/~ray/notes/gasexamples/<br />
.global meu_hello_world<br />
<br />
.text<br />
meu_hello_world:<br />
<br />
push %rdi # salva primeiro parâmetro<br />
push %rsi # salva segundo parâmetro<br />
mov $1, %rax # system call 1 é write<br />
mov $1, %rdi # file handle 1 é stdout<br />
mov $message, %rsi # endereço da string<br />
mov $13, %rdx # número de bytes da string<br />
syscall # chamada ao sistema<br />
<br />
pop %rdx # o que havia sido passado em rsi (número de bytes) é colocado em rdx<br />
pop %rsi # o que havia sido colocado em rdi (endereço da string) é colocado em rsi<br />
mov $1, %rax # system call 1 is write<br />
mov $1, %rdi # file handle 1 é stdout<br />
syscall # nova chamada ao sistema<br />
<br />
ret<br />
<br />
message:<br />
.ascii "Hello, World\n"<br />
</syntaxhighlight><br />
</li><br />
</ol><br />
{{collapse bottom}}<br />
<br />
=AULA 4 - Dia 9/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*PARTE 2A: Gerenciamento de Processos (cap.3)<br />
*3.1.Conceito de Processo<br />
*3.2.Escalonamento de Processos<br />
*3.3.Operações sobre Processos (Laboratório Operações sobre Processos no Linux: Fork/Exec/Wait)<br />
<br />
===Material de Referência===<br />
<br />
*Slides do Cap.3 - Silberschatz<br />
*Laboratório Fork/Exec/Wait<br />
<br />
=== Exercícios de Demonstração===<br />
<br />
#Executar em um terminal o comando top. Em um outro terminal executar:<br />
yes > /dev/null &<br />
yes > /dev/null &<br />
#Parar um dos processos yes<br />
kill -STOP <pid_yes><br />
#Continuar o processo<br />
kill -CONT <pid_yes><br />
#Destruir todos<br />
killall yes<br />
<br />
=AULA 5 - Dia 14/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*Ainda Processos<br />
*Cap.3.2..Escalonamento de Processos<br />
*Cap.2.3.Operaçṍes sobre processos<br />
*Finalização do Laboratório Fork/Exec/Wait<br />
<br />
===Adendo===<br />
<br />
*Estudar e comentar [https://www.geeksforgeeks.org/wait-system-call-c/]<br />
<br />
=AULA 6 - Dia 16/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*Comunicação Interprocessos (3.4 e 3.5)<br />
*Laboratório de Memória Compartilhada<br />
<br />
=AULA 7 - Dia 21/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Comunicação Interprocessos: Troca de Mensagens (3.6)<br />
*Laboratório de Pipes<br />
<br />
=AULA 8 - Dia 23/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Finalização Lab. pipes nomeados.<br />
*Threads ((cap.4.1, 4.2)<br />
*Lab.Threads de Aplicação<br />
<br />
=AULA 9 - Dia 28/08/2019=<br />
<br />
*Laboratório: Ainda Threads - Um escalonador semi-automático<br />
<br />
<br />
=AULA 10 - Dia 30/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Repassar um primeiro estudo sobre o RTOS<br />
*Revisar Processos e Threads<br />
<br />
==Questionário - Processos==<br />
<br />
#Conceitue processo. Descreva e explique cada uma das seções de um processo na memória.<br />
#Faça um diagrama e explique os possíveis estados de um processo no sistema. O que produz a transição entre estados?<br />
#O que é um Bloco de Controle de Processo? Quais informações ficam armazenadas neste bloco?<br />
#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.<br />
#Explique o que é multiprogramação e escalonamento de processos.<br />
#O que é a fila de processos prontos?<br />
#Diferencie um processo limitado por IO de um processo limitado por CPU.<br />
#Diferencie escalonamento de longo prazo de escalonamento de curto prazo.<br />
#Discuta o papel da interrupção na troca de contexto entre processos.<br />
#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?<br />
#Explique como funciona a chamada exec no UNIX/Linux<br />
#Explique como funciona a chamada wait no UNIX/Linux e como é possível retornar valores de um filho para o pai.<br />
#Faça um esqueleto de um programa UNIX/Linux que ao se tornar processo cria 3 filhos e espera pela execução dos mesmos.<br />
<br />
==Questionário - Comunicação entre Processos==<br />
<br />
#Diferenciar processos independentes de processos cooperantes.<br />
#Enumere e explique quatro razões para cooperação entre processos.<br />
#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.<br />
#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.<br />
#A memória compartilhada requer chamada ao sistema na sua operação? Discuta.<br />
#Por que o processo de troca de mensagem deve ser mais lento que a memória compartilhada?<br />
#Apresente em pseudocódigo uma proposta de funcionamento do problema do produtor consumidor usando memória compartilhada.<br />
#A construção de uma solução para o problema produtor consumidor pode ser facilitado pelo uso da memória compartilhada? Discuta.<br />
#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?<br />
#Enumere três métodos de implementação de uma lógica de ligação (link) entre processos.<br />
#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.<br />
#Descreva a variante assimétrica da troca direta de mensagens. O que muda em termos de primitiva de comunicação?<br />
#Descreva o problema de hard-coding associado a nomeação direta e como pode ser contornado através da nomeação/comunicação indireta?<br />
#O que é uma caixa postal? Como o Posix identifica uma caixa postal no caso de fila de mensagens?<br />
#Dois processos podem usar mais do que uma caixa postal para se comunicar? Qual a condição para que isto ocorra?<br />
#Descreva as duas operações básicas para a troca de mensagens com Caixa Postal.<br />
#Descreva na comunicação indireta via Caixa Postal as 3 propriedades básicas.<br />
#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.<br />
#De que forma a caixa postal estando no espaço de endereçamento de um processo (propriedade) afeta a recepção por mensagens? Descreva.<br />
#Quais as operações sobre uma caixa postal criada no espaço do sistema operacional deverão ser disponíveis? Descreva.<br />
#A transmissão de mensagem pode ser com e sem bloqueio. Descreva as 4 possibilidades (síncrona/assíncrona).<br />
#Discuta as 3 possibilidades de armazenamento de mensagens em buffer. Em que condições um remetente pode ser bloqueado?<br />
<br />
==ETAPA 1 - Projeto Final==<br />
<br />
*Apresentação (slides) sobre a parte de gerenciamento de tarefas no RTOS;<br />
*apresentação dia 18/09/2019<br />
<br />
==Referências==<br />
<br />
*[https://www.freertos.org/RTOS.html Site do FreeRTOS] ver Mastering the FreeRTOS Real Time Kernel - a Hands On Tutorial Guide <br />
*[https://www.embarcados.com.br/rtos-sistema-operacional-de-tempo-real/]<br />
*[https://github.com/feilipu/avrfreertos]<br />
<br />
=AULA 11 - Dia 4/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Pico de CPU X Pico de IO <br />
*Preempção X Não Preempção<br />
*Escalonamento de Processos: Escalonamento FCFS<br />
<br />
<br />
=AULA 12 - Dia 6/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Escalonamento de Processos: <br />
**Shortest Job First (preemptivo e não preemptivo)<br />
**Prioridade (preemptivo e não preemptivo)<br />
**Round-Robin: Preemptivo<br />
*Lab.Round Robin<br />
<br />
==Material de Referência==<br />
<br />
http://docente.ifsc.edu.br/andre.damato/sop2018/SOP2018-parte2.pdf<br />
<br />
<br />
=AULA 13 - Dia 13/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Sincronização entre Processos<br />
*Laboratório do Esquema de Peterson<br />
<br />
==Material de Referência==<br />
<br />
*Livro Silberchatz<br />
*https://www.os-book.com/OSE1/slide-dir/PPT-dir/ch6.ppt<br />
<br />
=AULA 14 - Dia 18/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Sincronização entre Processos<br />
*Lock de Hardware<br />
*Laboratório do TSL<br />
<br />
==Laboratório Proposto==<br />
<br />
*Refazer o problema proposto usando uma instrução simualada de test and set. Prever um liite superior para entrada de um processo na região crítica.<br />
<br />
==Material de Referência==<br />
<br />
*Livro Silberchatz<br />
*https://www.os-book.com/OSE1/slide-dir/PPT-dir/ch6.ppt<br />
<br />
<br />
=AULA 15 - Dia 20/08/2019=<br />
<br />
==O ATmega238 usado no Arduino UNO==<br />
<br />
Ver [https://pt.wikipedia.org/wiki/ATmega328]<br />
<br />
==O Arduino UNO==<br />
<br />
Ver [https://pt.wikipedia.org/wiki/Arduino]<br />
Ver [https://github.com/feilipu/Arduino_FreeRTOS_Library]<br />
<br />
==O FreeRtos para o Arduino==<br />
<br />
Ver [https://github.com/feilipu/Arduino_FreeRTOS_Library]<br />
<br />
Para instalar no IDE:<br />
*Baixar o ZIP do link acima<br />
*No IDE importar a biblioteca:<br />
**sketch->IncluirBiblioteca->Adicionar do arquivo ZIP<br />
<br />
<br />
==Código Experimental==<br />
<br />
Este código demonstra a ocorrência de "race condition".<br />
<br />
<syntaxhighlight lang=c><br />
// Code based on Examples of Arduino and examples <br />
// from https://github.com/feilipu/Arduino_FreeRTOS_Library<br />
<br />
#include <Arduino_FreeRTOS.h><br />
#include <FreeRTOSVariant.h><br />
#include <task.h><br />
#include <semphr.h><br />
<br />
#define TAM_BUFF 10<br />
<br />
volatile unsigned long race_flag=0xFFEEDDCC;<br />
volatile unsigned long int cont;<br />
int task_cont=0;<br />
<br />
void PrintSerial( void *pvParameters ); // Task para imprimir valor de race_flag<br />
void TaskBlink( void *pvParameters );<br />
void TaskSetarace_flag(void *pvParameters); //Task que atribui race_flag=0xFFEEDDCC<br />
void TaskZerarace_flag(void *pvParameters); //Task que atribui race_flag=0xAA0000AA<br />
<br />
// função de setup<br />
<br />
void setup() {<br />
<br />
Serial.begin(9600);<br />
<br />
while (!Serial) {<br />
; // wait for serial port to connect. Needed for native USB, on LEONARDO, MICRO, YUN, and other 32u4 based boards.<br />
}<br />
<br />
<br />
// criar as 2 tarefas<br />
<br />
xTaskCreate(<br />
TaskBlink<br />
, (const portCHAR *)"Blink" // A name just for humans<br />
, 128 // This stack size can be checked & adjusted by reading the Stack Highwater<br />
, NULL<br />
, 1 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.<br />
, NULL );<br />
<br />
xTaskCreate(<br />
TaskPrintSerial<br />
, (const portCHAR *) "PrintSerial"<br />
, 128 // Stack size<br />
, NULL<br />
, 1 // Priority<br />
, NULL );<br />
<br />
xTaskCreate(<br />
TaskSetarace_flag<br />
, (const portCHAR *) "Setarace_flag"<br />
, 128 // Stack size<br />
, NULL<br />
, 1 // Priority<br />
, NULL );<br />
<br />
xTaskCreate(<br />
TaskZerarace_flag<br />
, (const portCHAR *) "Zerarace_flag"<br />
, 128 // Stack size<br />
, NULL<br />
, 1 // Priority<br />
, NULL );<br />
<br />
cont = race_flag;<br />
<br />
// escalonador toma conta a partir daqui<br />
<br />
}<br />
<br />
void loop()<br />
{<br />
// nada a fazer aqui<br />
}<br />
<br />
/*--------------------------------------------------*/<br />
/*---------------------- Tasks ---------------------*/<br />
/*--------------------------------------------------*/<br />
<br />
void TaskBlink(void *pvParameters) // This is a task.<br />
{<br />
(void) pvParameters;<br />
<br />
/*<br />
Blink<br />
Turns on an LED on for one second, then off for one second, repeatedly.<br />
<br />
Most Arduinos have an on-board LED you can control. On the UNO, LEONARDO, MEGA, and ZERO <br />
it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN takes care <br />
of use the correct LED pin whatever is the board used.<br />
<br />
The MICRO does not have a LED_BUILTIN available. For the MICRO board please substitute<br />
the LED_BUILTIN definition with either LED_BUILTIN_RX or LED_BUILTIN_TX.<br />
e.g. pinMode(LED_BUILTIN_RX, OUTPUT); etc.<br />
<br />
If you want to know what pin the on-board LED is connected to on your Arduino model, check<br />
the Technical Specs of your board at https://www.arduino.cc/en/Main/Products<br />
<br />
This example code is in the public domain.<br />
<br />
modified 8 May 2014<br />
by Scott Fitzgerald<br />
<br />
modified 2 Sep 2016<br />
by Arturo Guadalupi<br />
*/<br />
<br />
// initialize digital LED_BUILTIN on pin 13 as an output.<br />
pinMode(LED_BUILTIN, OUTPUT);<br />
<br />
for (;;) // A Task shall never return or exit.<br />
{<br />
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)<br />
vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second<br />
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW<br />
vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second<br />
}<br />
}<br />
<br />
<br />
<br />
<br />
void TaskPrintSerial(void *pvParameters) // Task que imprime na serial - must be improved...<br />
{<br />
(void) pvParameters;<br />
/*<br />
<br />
*/<br />
<br />
<br />
for (;;)<br />
{ <br />
while (cont==0xAA0000AA || cont==0xFFEEDDCC)<br />
cont = race_flag;<br />
;<br />
<br />
Serial.println("Problemas: valor race_flag é");<br />
Serial.println(cont, HEX);<br />
<br />
vTaskDelay(5); // one tick delay (15ms) in between reads for stability - b<br />
cont = race_flag;<br />
}<br />
}<br />
<br />
void TaskSetarace_flag(void *pvParameters) <br />
{<br />
(void) pvParameters;<br />
const TickType_t xMaxBlockTimeTicks = 0x20;<br />
/*<br />
<br />
*/<br />
<br />
race_flag=0xAA0000AA;<br />
for (;;)<br />
{<br />
race_flag=0xAA0000AA;<br />
//Serial.println("Produtor");<br />
vTaskDelay( ( rand() %xMaxBlockTimeTicks) ); <br />
} <br />
<br />
}<br />
<br />
void TaskZerarace_flag(void *pvParameters) <br />
{<br />
(void) pvParameters;<br />
const TickType_t xMaxBlockTimeTicks = 0x20;<br />
/*<br />
<br />
*/<br />
race_flag=0xFFEEDDCC;<br />
<br />
for (;;)<br />
{<br />
race_flag=0xFFEEDDCC;<br />
vTaskDelay( ( rand() %xMaxBlockTimeTicks) ); <br />
if(task_cont++==100) {<br />
delay(1);<br />
Serial.println("Fim TaskZera - valor race_flag ");<br />
Serial.println(race_flag, HEX);<br />
for(;;);<br />
} <br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=AULA 16 - Dia 25/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Preparação de exemplos de RTOS sobre Arduíno para apresentação na sexta;<br />
<br />
=Laboratórios Propostos= <br />
<br />
Considere o código abaixo. Observe que a região de dados compartilhada shared_data é zerada pelo pai e setada pelo processo filho. O pai detecta inconsistências nos dados que operou. Tente corrigir usando o esquema de Peterson para acesso a região crítica. Crie uma função de entrada e de saída da região crítica.<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
<br />
<br />
#define BUFFER_SIZE 4096<br />
char *shared_data;<br />
char reference_data[BUFFER_SIZE];<br />
<br />
main()<br />
{ <br />
key_t key;<br />
int shmid;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, BUFFER_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
shared_data = shmat(shmid, (void *)0, 0);<br />
<br />
if (shared_data == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int count=0; <br />
memset(reference_data,0,BUFFER_SIZE); <br />
for(;;){ <br />
memset(shared_data,0,BUFFER_SIZE);<br />
if (memcmp(shared_data, reference_data, BUFFER_SIZE)!=0) {<br />
count++;<br />
if (count%1000000==0)<br />
printf("Processo pai detectou algo errado nos dados %d\n", count); <br />
} <br />
} <br />
<br />
<br />
}<br />
else { /*Child code */<br />
<br />
for(;;){ <br />
memset(shared_data,1,BUFFER_SIZE); <br />
}<br />
<br />
}<br />
<br />
if (shmdt(shared_data) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
Possível solução:<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
#include <unistd.h><br />
<br />
#define BUFFER_SIZE 4096<br />
#define ID_PAI 0<br />
#define ID_FILHO 1<br />
#define FALSE 0<br />
#define TRUE 1<br />
<br />
char *shared_data;<br />
char reference_data[BUFFER_SIZE];<br />
<br />
struct tipo_peterson{<br />
char flag[2];<br />
char turn;<br />
} *pet_struct;<br />
<br />
void ent_sec_crit(int id)<br />
{<br />
char id_outro = (id+1)%2;<br />
<br />
pet_struct->flag[id] = TRUE; // indica que o processo deseja entrar na região crítica<br />
pet_struct->turn = id_outro; // o processo sinaliza para o outrao entrar, <br />
// caso o outro esteja entrando<br />
// este ponto é uma race condition: turn pode ser 0 ou 1 <br />
while ( (pet_struct->flag[id_outro]==TRUE) && (pet_struct->turn == id_outro) )<br />
;<br />
}<br />
<br />
void sai_sec_crit(int id)<br />
{<br />
pet_struct->flag[id] = FALSE;<br />
}<br />
<br />
int main()<br />
{ <br />
key_t key;<br />
int shmid;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, BUFFER_SIZE+sizeof(struct tipo_peterson), S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
shared_data = shmat(shmid, (void *)0, 0);<br />
pet_struct = (struct tipo_peterson *) (shared_data + BUFFER_SIZE); <br />
<br />
if (shared_data == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int count=0; <br />
memset(reference_data,0,BUFFER_SIZE); <br />
for(;;){ <br />
ent_sec_crit(ID_PAI);<br />
memset(shared_data,0,BUFFER_SIZE);<br />
if (memcmp(shared_data, reference_data, BUFFER_SIZE)!=0) {<br />
count++;<br />
if (count%1000000==0)<br />
printf("Processo pai detectou algo errado nos dados %d\n", count); <br />
} <br />
sai_sec_crit(ID_PAI);<br />
} <br />
<br />
<br />
}<br />
else { /*Child code */<br />
<br />
for(;;){<br />
ent_sec_crit(ID_FILHO); <br />
memset(shared_data,1,BUFFER_SIZE);<br />
sai_sec_crit(ID_FILHO); <br />
}<br />
<br />
}<br />
<br />
if (shmdt(shared_data) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
=AULA 17 - Dia 27/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Apresentação dos Trabalhos<br />
*Definição da próxima etapa<br />
<br />
=AULA 18 - Dia 02/10/2019=<br />
<br />
==Objetivos==<br />
<br />
*Semáforos, Deadlock e o Problema da Inversão de Prioridade<br />
*Laboratório de Pthreads e Mutex;<br />
<br />
==Laboratório Proposto==<br />
<br />
*Lab. Programação concorrente - Parte 1<br />
<br />
==Materia de Referência==<br />
<br />
*[https://www.os-book.com/OSE1/slide-dir/PDF-dir/ch6.pdf]<br />
<br />
==Desafio==<br />
<br />
Usar <br />
ps -T aux | grep ex1vA<br />
<br />
Para ver os threads dormindo...<br />
<br />
Otimizar o programa abaixo<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <pthread.h><br />
#include <stdlib.h><br />
#include <unistd.h><br />
#include <time.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
pthread_mutex_t mut;<br />
<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
<br />
<br />
long long i;<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
usleep(5000000);<br />
printf("Novo saldo = %d\n",novo_saldo);<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d\n", (i+1));<br />
exit(-1);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
printf("Saldo final é %d\n", saldo);<br />
}<br />
</syntaxhighlight><br />
<br />
=AULA 19 - Dia 04/10/2019=<br />
<br />
==Objetivos==<br />
<br />
*Ainda Semáforos, Deadlock e o Problema da Inversão de Prioridade<br />
*Laboratório de Pthreads com semáforo binário;<br />
*Laboratório de Pthreads com semáforos contador como solução do problema do produtor e consumidor.<br />
<br />
<br />
==Material de Referência==<br />
<br />
*ver laboratório de Programação concorrente<br />
<br />
==Laboratório Proposto==<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Programação concorrente}}<br />
<br />
== Programação concorrente ==<br />
<br />
<br />
===PARTE 1 - Mutex e Biblioteca libpthreads===<br />
<br />
;POSIX Threads<br />
A 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):<br />
*''pthread_create'': cria uma thread;<br />
*''pthread_kill'': força a terminação de uma thread;<br />
*''pthread_join'': sincroniza o final de uma thread (qual a diferença/semelhança com o ''wait'' que usamos para processos?);<br />
*''pthread_exit'': finaliza uma thread.<br />
Para utilizar estas funções é necessário linkar o programa à libpthread (''-lpthread''). <br />
<br />
<br />
;POSIX pthread mutex<br />
<br />
A biblioteca pthread implementa um tipo ''pthread_mutex_t'', que garante a exclusão mútua entre threads. Estes mutex são manipulados através das funções (acesse as man-pages das chamadas para maiores detalhes):<br />
*''pthread_mutex_lock'': acessa um mutex.<br />
*''pthread_mutex_trylock'': tenta acessar um mutex (retorna valor indicando sucesso ou falha no lock).<br />
*''pthread_mutex_unlock'': libera um mutex.<br />
<br />
<br />
<br />
;Exercício 1<br />
<br />
O programa abaixo cria 5 threads, e cada uma destas threads atualiza uma variável global (memória compartilhada).<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
#include <pthread.h><br />
#include <stdlib.h><br />
#include <unistd.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
pthread_mutex_t mut;<br />
<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
long long i;<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
sleep(1);<br />
printf("Novo saldo = %d\n",novo_saldo);<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d\n", (i+1));<br />
exit(-1);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
printf("Saldo final é %d\n", saldo);<br />
}<br />
</syntaxhighlight><br />
<br />
# Compile este programa. <br />
# Execute este programa várias vezes. Ele funciona? Será que ele gera as saídas esperadas?<br />
# Identifique as '''seções críticas''' do programa.<br />
# Corrija o programa utilizando '''mutex'''. <br />
# Analise a função ''AtualizaSaldo()'' com a sua solução. Lembre-se que o uso do mutex implica em apenas uma thread acessar a seção crítica por vez, enquanto outras threads ficam bloqueadas, esperando. Disso vem que, quanto menor o trecho de código entre um ''lock'' e um ''unlock'', menos tempo uma thread necessita ficar esperando.<br />
<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <cstring><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
<br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
sem_t sem;<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
int value;<br />
sem_wait(&sem);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
sem_getvalue(&sem, &value);<br />
printf("valor sem = %d\n", value);<br />
sem_post(&sem);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
sem_init(&sem,0,1);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
sem_destroy(&sem);<br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
===PARTE 2 - POSIX Semaphores Binários===<br />
<br />
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):<br />
*''sem_init'': inicializa um semáforo;<br />
*''sem_destroy'': destroy um semáforo;<br />
*''sem_wait'': implementa a operação ''p'';<br />
*''sem_post'': implementa a operação ''v''.<br />
Para utilizar estas funções é necessário linkar o programa à librt ou à libpthread (''-lrt'' ou ''-lpthread'').<br />
<br />
;Exercício 1<br />
Modifique o programa para usar um semáforo binário ao invés de um mutex em sua solução.<br />
<br />
;Exercício 2 - Fazer em casa<br />
Refaça o exercício 3 usando processos criados com fork e exec. O semáforo deve ser criado em uma região de memória compartilhada.<br />
<br />
===PARTE 3 - POSIX Semaphores===<br />
<br />
;Exercício 3<br />
Implemente com pthreads e semáforos/mutex a solução do produtor/comsumidor conforme sugerido no livro do Silberchatz. USe dois semáforos: (i) um para controlar o numero de itens vazios no buffer (semáforo empty - quando zero o thread produtor deve parar de produzir). (ii) um semáforo para controlar o numero de itens ocupados no buffer (semáforo full - quando zero o consumidor deve parar de consumir).<br />
<br />
<!--<br />
<code><br />
#include <stdio.h><br />
#include <pthread.h><br />
#include <stdlib.h><br />
#include <unistd.h><br />
#include <time.h><br />
#include <semaphore.h> <br />
<br />
#define NUM_THREADS 5<br />
<br />
#define NUM_MAX 1000<br />
#define TAM_BUFF 100<br />
<br />
pthread_mutex_t mut;<br />
sem_t full,empty; <br />
<br />
int buffer[TAM_BUFF];<br />
<br />
<br />
void *Produtor(void* arg)<br />
{<br />
int i;<br />
int in=0;<br />
for(i=0;i<NUM_MAX;i++) {<br />
sem_wait(&empty);<br />
pthread_mutex_lock(&mut);<br />
buffer[in]=i;<br />
pthread_mutex_unlock(&mut);<br />
sem_post(&full); <br />
in=(in+1)%TAM_BUFF;<br />
printf("Produtor: produzi um item...\n");<br />
if(i%20==0)<br />
usleep(500000); <br />
}<br />
}<br />
<br />
void *Consumidor(void* arg)<br />
{<br />
int i;<br />
int dado;<br />
int out=0;<br />
for(i=0;i<NUM_MAX;i++) {<br />
//usleep(100000);<br />
sem_wait(&full);<br />
pthread_mutex_lock(&mut);<br />
dado=buffer[out];<br />
pthread_mutex_unlock(&mut);<br />
printf("item consumido = %d\n", dado);<br />
out=(out+1)%TAM_BUFF;<br />
sem_post(&empty);<br />
}<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[2];<br />
<br />
sem_init(&full, 0, 0);<br />
sem_init(&empty, 0, TAM_BUFF);<br />
pthread_mutex_init(&mut, NULL);<br />
pthread_create(&threads[0], NULL, Produtor,NULL);<br />
pthread_create(&threads[1], NULL, Consumidor,NULL);<br />
<br />
pthread_join(threads[0], NULL);<br />
pthread_join(threads[1], NULL);<br />
}<br />
</syntaxhighlight><br />
<br />
--><br />
<br />
===PARTE 4 - POSIX Semaphores===<br />
<br />
;Exercício 4<br />
<br />
O programa abaixo manipula uma matriz de tamanho MxN (veja os defines para o tamanho da matriz). A função ''SumValues'' soma todos os valores em uma linha da matriz. A linha a ser somada é identificada pela variável ''i''. Modifique o programa principal (''main'') nos locais indicados para:<br />
# Criar N threads, uma para somar os valores de cada linha.<br />
# Receber o resultado do somatório de cada linha e gerar o somatório total da matriz.<br />
# Analise o programa: há problemas de sincronização que precisam ser resolvidos? Se sim, resolva-os.<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include "thread.h"<br />
<br />
/* number of matrix columns and rows */<br />
#define M 5<br />
#define N 10<br />
<br />
using namespace std;<br />
<br />
int matrix[N][M];<br />
Thread *threads[N];<br />
<br />
<br />
/* thread function; it sums the values of the matrix in the row */<br />
int SumValues(int i)<br />
{<br />
int n = i; /* number of row */<br />
int total = 0; /* the total of the values in the row */<br />
int j;<br />
for (j = 0; j < M; j++) /* sum values in the "n" row */<br />
total += matrix[n][j];<br />
cout << "The total in row" << n << " is " << total << "." << endl;<br />
/* terminate a thread and return a total in the row */<br />
exit(total);<br />
}<br />
<br />
int main(int argc, char *argv[])<br />
{<br />
int i, j;<br />
int total = 0; /* the total of the values in the matrix */<br />
<br />
/* initialize the matrix */<br />
for (i = 0; i < N; i++)<br />
for (j = 0; j < M; j++)<br />
matrix[i][j] = i * M + j;<br />
<br />
/* create threads */<br />
/* COLOQUE SEU CÓDIGO PARA CRIAR AS THREADS AQUI! */<br />
<br />
/* wait for terminate a threads */<br />
/* COLOQUE SEU CÓDIGO PARA PEGAR O SOMATÓRIO DE LINHAS E TOTALIZAR A SOMA DA MATRIZ AQUI! */<br />
<br />
cout << "The total values in the matrix is " << total << endl;<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
{{collapse bottom}}<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Escalonamento Round Robin e FCFS para Threads"}}<br />
<br />
== Escalonamento Round-Robin ==<br />
<br />
OBS: ver https://www.quora.com/What-exactly-does-typedef-do-in-C<br />
<br />
O Exemplo abaixo mostra a implementação de um esquema de escalonamento Round Robin do exercício anterior.<br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
Modificado por Eraldo <br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 5<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
void runA(void) {<br />
for (;;) {<br />
printf("running A\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runB(void) {<br />
for (;;) {<br />
printf("running B\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 1<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
<br />
void scheduler_rr();<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void yield_thread()<br />
{<br />
scheduler_rr();<br />
}<br />
<br />
void delete_thread()<br />
{<br />
delete curr_thread;<br />
curr_thread=NULL;<br />
scheduler_rr();<br />
}<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
struct delta{<br />
long alfa;<br />
char epson[1000];<br />
long beta;<br />
} shar;<br />
<br />
int turn;<br />
int flag[2];<br />
<br />
#define TRUE 1<br />
#define FALSE 0<br />
<br />
void ent_rc(int p, int vt)<br />
{<br />
flag[p]=TRUE;<br />
turn = vt;<br />
if(p) p=0; else p=1;<br />
while (flag[p] && turn == vt);<br />
//printf("Thread %d: esperando para acessar a região crítica\n", p);<br />
}<br />
<br />
void sai_rc(int p)<br />
{<br />
flag[p]=FALSE;<br />
}<br />
<br />
void runA(void) {<br />
struct delta x = {0, 100};<br />
<br />
for (;;) {<br />
x.alfa=0;x.beta=0;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0);<br />
x.alfa=100;x.beta=100;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0); <br />
}<br />
}<br />
<br />
void runB(void) {<br />
<br />
for (;;) {<br />
ent_rc(1,0);<br />
printf("shar alfa = %ld shar beta = %ld \n",shar.alfa, shar.beta); // regiao crítica<br />
sai_rc(1);<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runC(void) {<br />
int i;<br />
for (i=0;i<10;i++) {<br />
printf("Thread C - parte 1\n");<br />
yield_thread();<br />
printf("Thread C - parte 2\n");<br />
yield_thread();<br />
}<br />
delete_thread();<br />
}<br />
<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
add_thread(runC);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
{{collapse bottom}}<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Um escalonador semi-automático"}}<br />
<br />
== Ainda Threads - Um escalonador semi-automático usando sinais ==<br />
<br />
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.<br />
<br />
===Exemplo 1:===<br />
<br />
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. <br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
<br />
void sig_handler(int signo)<br />
{<br />
int x;<br />
printf("Turma de SOP: recebido SIGUSR1\n");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
// Loop eterno dormindo 1s<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Fazer no terminal:<br />
ps aux<br />
anotar o pid do processo e enviar o sinal:<br />
kill -USR1 pid<br />
<br />
===Exemplo 2:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// loop eterno que nunca é executado<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Enviar o sinal USR1 para ver o efeito. <br />
<br />
===Exemplo 3:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void prepara_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void prepara_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
prepara_contexto_ping();<br />
prepara_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// A long long wait so that we can easily issue a signal to this process<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Exercício: Use o comando htop para verificar como estes threads são vistos pelo SOP.<br />
<br />
Exercício: Tente analisar as pilhas dos threads e verificar sob qual pilha o handler se executa.<br />
<br />
<br />
===Exercício 4:===<br />
<br />
Neste ponto associamos um timer ao handler com o apoio do sinal ALRM. Agora os threads são escalonados automaticamente.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
===Exercício Proposto 5===<br />
<br />
Colocar 3 threads rodando.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void preparar_contexto_ping(ucontext_t *pContext, char *p)<br />
{<br />
char *stack;<br />
<br />
getcontext(pContext);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
(*pContext).uc_stack.ss_sp = stack ;<br />
(*pContext).uc_stack.ss_size = STACKSIZE;<br />
(*pContext).uc_stack.ss_flags = 0;<br />
(*pContext).uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(pContext, (void*)(*f_ping), 1, p);<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping(&cPing, "ping");<br />
preparar_contexto_ping(&cPong, "pong");<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Threads de aplicação}}<br />
<br />
== Threads de aplicação ==<br />
<br />
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:<br />
*'''getcontext(&a)''': salva o contexto na variável '''a''';<br />
*'''setcontext(&a)''': restaura um contexto salvo anteriormente na variável '''a''';<br />
*'''swapcontext(&a,&b)''': salva o contexto atual na variável '''a''' e restaura o contexto salvo anteriormente na variável '''b''';<br />
*'''makecontext(&a, ...)''': ajusta parâmetros internos do contexto salvo em '''a''';<br />
*'''ucontext_t''': as variáveis '''a''' e '''b''' são do tipo '''ucontext_t'''. Este tipo armazena um contexto.<br />
<br />
Busque mais informações sobre estas funções utilizando o programa manpage do Linux (ex.: man getcontext).<br />
<br />
Estude o código no arquivo pingpong.c abaixo e explique seu funcionamento.<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
*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.<br />
*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.<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain, cFnew;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_new(void * arg1, void * arg2,void * arg3,void * arg4) <br />
{<br />
printf ("%s: Primeira string %s %s %s\n",(char*) arg1,(char*) arg2,(char*) arg3, (char*) arg4);<br />
swapcontext(&cFnew, &cMain); <br />
}<br />
<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
<br />
getcontext(&cFnew);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cFnew.uc_stack.ss_sp = stack ;<br />
cFnew.uc_stack.ss_size = STACKSIZE;<br />
cFnew.uc_stack.ss_flags = 0;<br />
cFnew.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cFnew, (void*)(*f_new), 4, "\tF_new", "\tAlo", "\tMundo","\tReal");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
swapcontext(&cMain, &cFnew);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
--><br />
Exercício 3: O que acontece se um dos threads é colocado para dormir? Todos os demais threads param a sua execução.<br />
<br />
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/<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Processos no Linux}}<br />
<br />
== Processos no Linux - Modificado por Eraldo ==<br />
<br />
<blockquote style="background: lime; border: 1px solid black; padding: 1em;"><br />
Processos no Linux<br />
</blockquote><br />
<br />
*Exercícios propostos pelo Prof.Arliones e Modificados por Eraldo<br />
<br />
<br />
[[imagem:DesenhoForkExec.png|border|650px]]<br />
<br />
<br />
;Syscall FORK<br />
<br />
* Em um terminal, execute "man fork"<br />
** 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'''.<br />
** O '''código''' dos dois processos (pai e filho) são '''idênticos''';<br />
** Os '''dados''' dos dois processos (pai e filho) são '''idênticos NO MOMENTO DA CRIAÇÃO''';<br />
** Execução do processo filho inicia na próxima instrução do programa (no retorno da chamada FORK);<br />
** Não é possível saber qual dos processos (pai ou filho) retormará a execução primeiro - isto fica a cargo do excalonador do SO;<br />
** Valores de retorno da chamada FORK:<br />
*** (-1): erro na criação do processo (ex.: memória insuficiente);<br />
*** (0): em caso de sucesso, este é o valor de retorno recebido pelo processo filho;<br />
*** (>0): em caso de sucesso, este é o valor de retorno recebido pelo processo pai;<br />
<br />
;Syscall JOIN<br />
<br />
* A syscall JOIN é implementada no POSIX pela função '''wait()'''. Execute "man wait".<br />
** Além da função '''wait()''', há também '''waitpid()''' e '''waitid()''';<br />
** 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);<br />
** A chamada wait também libera os recursos do processo filho que termina;<br />
** '''wait()''': esta função suspende a execução do processo chamador até que UM DOS SEUS FILHOS finalize;<br />
** '''waitpid()''': suspende a execução do processo chamador até que UM FILHO ESPECÍFICO finalize;<br />
<br />
;Syscall EXEC<br />
<br />
* A syscall EXEC é implementada no POSIX pela família de funções '''exec()'''. Execute "man exec".<br />
** As principais funções da família são '''execl()''', '''execlp()''' e '''execvp()''';<br />
** 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;<br />
** 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;<br />
<br />
<br />
;Exemplos POSIX utilizando fork/wait/exec<br />
<br />
*Exemplo 1: fork/wait básico<br />
<syntaxhighlight lang=c><br />
// ex1: fork/wait básico<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
printf("processo filho\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
printf("processo pai\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
arliones@socrates:~/tmp$ gcc ex1.c -o ex1 <br />
arliones@socrates:~/tmp$ ./ex1 <br />
processo filho pid: 27858 pid pai: 27857<br />
processo pai pid: 27857 pid pai: 5337<br />
arliones@socrates:~/tmp$ <br />
</syntaxhighlight><br />
<br />
* Exemplo 2: processos pai e filho compartilham código, mas não dados.<br />
<syntaxhighlight lang=c><br />
// ex2: fork/wait "compartilhando" dados<br />
// ex2: fork/wait "compartilhando" dados<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status, k=0;<br />
printf("processo %d\t antes do fork\n", getpid());<br />
pid = fork();<br />
printf("processo %d\t depois do fork\n", getpid());<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
k += 1000;<br />
printf("processo filho\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status); // espera o filho terminar<br />
k += 10;<br />
printf("processo pai\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
k += 1000;<br />
printf("FIM processo %d\t K: %d\n", getpid(), k); <br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
processo 17056 antes do fork<br />
processo 17056 depois do fork<br />
processo 17057 depois do fork<br />
processo filho pid: 17057 K: 1000 endereço K: 0x7ffd8923e318<br />
processo pai pid: 17056 K: 10 endereço K: 0x7ffd8923e318<br />
</syntaxhighlight><br />
<br />
* Modificação no código: comentar linhas 23 e 30<br />
<br />
<syntaxhighlight lang=bash><br />
<br />
</syntaxhighlight><br />
<br />
* Analise os resultados e busque entender a diferença.<br />
*Perguntas e desafios.:<br />
#Analisando os valores impressos de k pode-se dizer que os dados são compartilhados entre os dois processos?<br />
#O endereço de k impresso é o mesmo nos dois processos. ISto não contradiz a afirmação anterior?<br />
#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.<br />
<br />
<br />
;Exercício fork/wait<br />
<br />
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.<br />
<br />
*Use o comando pstree para verificar a árvore de processos criada.<br />
<br />
{{collapse top|Solução}}<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
<!--<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
--><br />
<br />
;DESAFIO: fork/wait<br />
<br />
Reimplementar o exercício anterior de criação de uma árvore de 3 processos, generalizando a criação de N processos onde N é repassado na linha de comando do programa. SUGESTÃO: usar um comando for, mas lembrar que se existe um fork dentro do for, então cada filho gerado dará continuidade a execução do for. É necessário que o processo faça um exit ou retorne neste momento.<br />
<br />
;DESAFIO: Exercício status/wait<br />
<br />
O ''status'' passado como parâmetro à função ''wait(&status)'' é, na verdade, o mecanismo de retorno de resultado do ''wait/waitpid''. Ao retornar, esta variável contém informações sobre o resultado da execução do processo filho. Por exemplo, se um processo terminou normalmente (i.e., chamou ''exit''), o comando ''WIFEXITED(status)'' retorna ''true''. Este comando retorna ''false'' se o processo foi abortado (e.g., ''segmentation fault'') ou morto (e.g., ''kill''). Investigue no manual do wait no Linux (''man wait'') o funcionamento do comando WEXITSTATUS(status). <br />
Imagine um problema de busca de dados armazenados na forma de uma matriz de inteiros 4x30. Você está interessado em saber quantas ocorrências de um determinado número existe em cada linha da matriz. Note que que são tarefas que podem ser paralelizadas e usufruir de um sistema capaz de executá-las em paralelo. Faça uma implementação paralelizando 4 processos filhos a partir de um pai, onde cada processo é responsável por uma busca. A quantidade de ocorrências do número buscado é retornada e capturada através de WEXITSTATUS.<br />
<br />
;Syscall EXEC<br />
<br />
*Exemplo exec()<br />
<br />
<syntaxhighlight lang=c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
execl("/bin/ls","ls","-l", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 1: Modificar o código para mostrar que o exec() não retorna (colocar um printf após o exec).<br />
<br />
*Exercício 2: Criar um exemplo (dois programas ) para demonstrar que o exec não cria novo processo. <br />
**Crie um primeiro programa (prog1) que imprime o seu pid e depois faz um exec do segundo programa.<br />
**Crie o segundo programa que simplesmente imprime o pid.<br />
<br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU ANTES DO EXEC: Meu pid é %d\n", getpid());<br />
execl("./prog2","prog2", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU DEPOIS DO EXEC:Meu pid é %d\n", getpid());<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 3: Criar um exemplo usando fork/exec mostrando que um processo pai cria um filho e espera por sua execução. O filho executa o comando "ps aux". Ambos devem mostrar seus pids.<br />
<br />
{{collapse bottom}} <br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Laboratório Memória Compartilhada entre Pai e Filho - Produtor Consumidor}}<br />
<br />
Baseado no Lab. do Prof.Arliones<br />
<br />
=== Objetivo ===<br />
<br />
*Familiarizar o aluno com o conceito de Memória Compartilhada entre Processos Pai e Filho<br />
*Familizarizar o aluno com o conceito de Produtor Consumidor<br />
<br />
=== Referencial Teórico-Prático ===<br />
<br />
* Silberchatz - 3.4 e 3.5<br />
* man nos comandos shmat e shmget<br />
<br />
=== Exemplo de Funcionamento ===<br />
<br />
No exemplo abaixo um processo pai compartilha uma área de memória com o processo filho. O processo filho escreve uma mensagem para o pai na área de memória compartilhada e termina. O processo pai é desbloqueado no wait e imprime a mensagem escrita.<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
char *ptr_msg = "alo pai, tudo bem?"; <br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
strcpy(segmento, ptr_msg);<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(&filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
=== Desafio a ser Implementado em Sala ===<br />
<br />
Construir um programa em que um processo pai atua como produtor e o processo filho atua como consumidor. O buffer circular compartilhado é um buffer de inteiro de tamanho 5. O pai alimentará o buffer com 50 itens gerados aleatóriamente entre 1 e 100. A cada escrita/leitura no buffer o produtor/consumidor deve esperar alguns milisegundos de forma a acontecer situações de buffer cheio e vazio. <br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
#include <unistd.h><br />
#include <time.h><br />
#include <sys/types.h><br />
#include <sys/wait.h><br />
<br />
<br />
<br />
#define SHM_SIZE 1024 <br />
<br />
#define BUFF_COMP_SIZE 5<br />
<br />
struct buff_comp {<br />
int buffer[BUFF_COMP_SIZE];<br />
int in,out;<br />
};<br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
struct buff_comp *p; <br />
<br />
/* initialize random seed: */<br />
srand ( time(NULL) );<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
p = (struct buff_comp *) shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
p->out = p->in = 0;<br />
<br />
if((filho = fork()) == -1)<br />
{<br />
<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
int i;<br />
for(i=0;i<50;i++) {<br />
while (p->in==p->out) {<br />
printf("FILHO: BUFFER VAZIO !!!!!!!\n");<br />
usleep(rand() % 10000 + 1);<br />
}<br />
printf("FILHO: item lido = %d\n", p->buffer[p->out]);<br />
p->out = (p->out+1)%BUFF_COMP_SIZE;<br />
}<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
int i; <br />
<br />
for(i=0;i<50;i++) {<br />
while (((p->in+1)%BUFF_COMP_SIZE) == p->out) {<br />
printf("PAI: BUFFER CHEIO !!!!!!!\n");<br />
usleep(rand() % 10000 + 1);<br />
}<br />
p->buffer[p->in] = rand() % 100 + 1;<br />
printf("PAI: item produzido = %d\n", p->buffer[p->in]);<br />
p->in = (p->in+1)%BUFF_COMP_SIZE;<br />
<br />
}<br />
wait(&filho); <br />
<br />
}<br />
<br />
<br />
if (shmdt(p) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Trocas de mensagens com pipes}}<br />
<br />
= Trocas de mensagens com pipes =<br />
<br />
;Troca de mensagens<br />
Um mecanismo disponibilizado por sistemas UNIX para troca de mensagens entre processos é o PIPE. Pipes são mecanismos de comunicação indireta onde mensagens são trocadas através de ''mailboxes''. Cada ''mailbox'' possui um identificador único, permitindo que processos identifiquem o canal de comunicação entre eles. O fluxo de mensagens em um Pipe é:<br />
*'''unidirecional''': sobre um mesmo pipe, apenas um processo envia mensagens e um processo recebe mensagens;<br />
*'''FIFO''': as mensagens são entregues na ordem de envio;<br />
*'''não-estruturado''': não há estrutura pré-definida para o formato da mensagem.<br />
No UNIX, pipes são inicializados através da '''SystemCall''' ''pipe'', que possui a seguinte sintaxe:<br />
*''int pipe(int pipefd[2])'': ''pipe'' inicializa um novo pipe no sistema e retorna, no array pipefd, os descritores identificando cada uma das pontas do pipe. A primeira posição do array, i.e. pipefd[0], recebe o descritor que pode ser aberto apenas para leitura, enquanto a segunda posição do array, i.e. pipefd[1], recebe o descritor que pode ser aberto apenas para escrita. A função retorna zero no caso de sucesso, ou -1 se ocorrer erro.<br />
As primitivas send/receive para uso de um pipe no UNIX são implementadas por '''SystemCalls''' read/write, conforme segue:<br />
*''ssize_t read(int fd, void *buf, size_t count)'': “puxa” dados do pipe identificado pelo descritor fd. Os dados recebidos são os apontados pelo ponteiro buf, sendo count a quantidade máxima de bytes a serem recebidos. A função retorna o número de bytes recebidos.<br />
*''ssize_t write(int fd, const void *buf, size_t count)'': “empurra” dados no pipe identificado pelo descritor fd. Os dados transmitidos são os apontados pelo ponteiro buf, sendo count a quantidade de bytes a serem transmitidos. A função retorna o número de bytes transmitidos.<br />
<br />
*Exemplo 1: Transmitindo e recebendo pelo próprio processo<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main()<br />
{<br />
int fd[2];<br />
char *ptr = "Alo eu mesmo";<br />
char *ptr_alvo;<br />
int tamanho_dados, ret;<br />
<br />
tamanho_dados = strlen(ptr)+1;<br />
<br />
if (pipe(fd)==-1){<br />
printf ("erro criação pipe\n");<br />
exit(-1);<br />
}<br />
printf("Transmitido %d bytes\n", tamanho_dados);<br />
write (fd[1], ptr, tamanho_dados);<br />
<br />
ptr_alvo = malloc(tamanho_dados);<br />
<br />
ret=read(fd[0],ptr_alvo,tamanho_dados);<br />
<br />
printf("ret = %d dados => %s\n", ret, ptr_alvo); <br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
*Exemplo 2: Abaixo há um exemplo de programa criando um pipe e compartilhando os descritores entre dois processos (criados via ''fork()'').<br />
<syntaxhighlight lang=c><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
<br />
char *message = "This is a message!!!" ;<br />
<br />
main()<br />
{<br />
char buf[1024] ;<br />
int fd[2];<br />
pipe(fd); /*create pipe*/<br />
if (fork() != 0) { /* I am the parent */<br />
write(fd[1], message, strlen (message) + 1) ;<br />
}<br />
else { /*Child code */<br />
read(fd[0], buf, 1024) ;<br />
printf("Got this from MaMa!!: %s\n", buf) ;<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
*'''Exercício 1: construa um “pipeline”'''. Crie um programa que conecta 4 processos através de 3 pipes. Utilize ''fork()'' para criar vários processos.<br />
<br />
<syntaxhighlight lang=cpp><br />
<br />
//Solução possível<br />
<br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
pipe(fd);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
<br />
</syntaxhighlight><br />
<br />
*'''Exercício 2: Modifique o exercício anterior para que o processo D, através de um novo pipe, mande uma mensagem diretamente para o pai de todos.<br />
<br />
<!--<br />
<code><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
int fd_retorno[2];<br />
<br />
pipe(fd);<br />
pipe(fd_retorno);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size);<br />
read(fd_retorno[0], buf, size);<br />
printf("PAI:%s\n", buf); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
char *ptr_msg_ret="Ok msg de D para o pai";<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
write(fd_retorno[1],ptr_msg_ret,strlen(ptr_msg_ret)+1);<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
*'''Exercício 3: Consultor de Login de Acesso:'''. Estude o link https://www.geeksforgeeks.org/named-pipe-fifo-example-c-program/ e projete um programa cliente servidor da seguinte forma: (i) O servidor possui uma tabela de usuários (userid). O user_id é de tamanho fixo de 7 caracteres. O servidor espera por consultas para verificar se um usuário está na tabela. Se estiver responde com o caracter 'S' senão com 'N'. (ii) O cliente espera por user_id no teclado e consulta o servidor sobre sua existência na tabela. O cliente imprime na tabela a existência ou não do usuário.<br />
<br />
*'''Exercício 4: cópia de arquivo'''. Projete um programa de cópia de arquivos chamado FileCopy usando pipes comuns. Esse programa receberá dois parâmetros: o primeiro é o nome do arquivo a ser copiado e o segundo é o nome do arquivo copiado. Em seguida, o programa criará um pipe comum e gravará nele o conteúdo do arquivo a ser copiado. O processo filho lerá esse arquivo do pipe e o gravará no arquivo de destino. Por exemplo, se chamarmos o programa como descrito a seguir:<br />
:<syntaxhighlight lang=bash><br />
$ FileCopy entrada.txt copia.txt<br />
</syntaxhighlight><br />
:o arquivo ''entrada.txt'' será gravado no pipe. O processo filho lerá o conteúdo desse arquivo e o gravará no arquivo de destino ''copia.txt''. Escreva o programa usando os pipes da API POSIX no Linux.<br />
<br />
<br />
{{collapse bottom}}<br />
<br />
=Laboratórios Disponíveis= <br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Escalonamento Round Robin e FCFS para Threads"}}<br />
<br />
<br />
== Escalonamento Round-Robin preemptivo ==<br />
<br />
OBS: ver https://www.quora.com/What-exactly-does-typedef-do-in-C<br />
<br />
A fazer: <br />
<br />
*primitiva de término de processo (destrutor do objeto); <br />
*primitiva de yield<br />
*isolar o escalonador em uma função;<br />
*isolar o dispatcher em uma função; <br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
Modificado por Eraldo <br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 5<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
void runA(void) {<br />
for (;;) {<br />
printf("running A\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runB(void) {<br />
for (;;) {<br />
printf("running B\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 1<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
<br />
void scheduler_rr();<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void yield_thread()<br />
{<br />
scheduler_rr();<br />
}<br />
<br />
void delete_thread()<br />
{<br />
delete curr_thread;<br />
curr_thread=NULL;<br />
scheduler_rr();<br />
}<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
struct delta{<br />
long alfa;<br />
char epson[1000];<br />
long beta;<br />
} shar;<br />
<br />
int turn;<br />
int flag[2];<br />
<br />
#define TRUE 1<br />
#define FALSE 0<br />
<br />
void ent_rc(int p, int vt)<br />
{<br />
flag[p]=TRUE;<br />
turn = vt;<br />
if(p) p=0; else p=1;<br />
while (flag[p] && turn == vt);<br />
//printf("Thread %d: esperando para acessar a região crítica\n", p);<br />
}<br />
<br />
void sai_rc(int p)<br />
{<br />
flag[p]=FALSE;<br />
}<br />
<br />
void runA(void) {<br />
struct delta x = {0, 100};<br />
<br />
for (;;) {<br />
x.alfa=0;x.beta=0;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0);<br />
x.alfa=100;x.beta=100;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0); <br />
}<br />
}<br />
<br />
void runB(void) {<br />
<br />
for (;;) {<br />
ent_rc(1,0);<br />
printf("shar alfa = %ld shar beta = %ld \n",shar.alfa, shar.beta); // regiao crítica<br />
sai_rc(1);<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runC(void) {<br />
int i;<br />
for (i=0;i<10;i++) {<br />
printf("Thread C - parte 1\n");<br />
yield_thread();<br />
printf("Thread C - parte 2\n");<br />
yield_thread();<br />
}<br />
delete_thread();<br />
}<br />
<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
add_thread(runC);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Um escalonador semi-automático"}}<br />
<br />
== Ainda Threads - Um escalonador semi-automático usando sinais ==<br />
<br />
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.<br />
<br />
===Exemplo 1:===<br />
<br />
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. <br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
<br />
void sig_handler(int signo)<br />
{<br />
int x;<br />
printf("Turma de SOP: recebido SIGUSR1\n");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
// Loop eterno dormindo 1s<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Fazer no terminal:<br />
ps aux<br />
anotar o pid do processo e enviar o sinal:<br />
kill -USR1 pid<br />
<br />
===Exemplo 2:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// loop eterno que nunca é executado<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Enviar o sinal USR1 para ver o efeito. <br />
<br />
===Exemplo 3:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void prepara_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void prepara_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
prepara_contexto_ping();<br />
prepara_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// A long long wait so that we can easily issue a signal to this process<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
Exercício: Tente analisar as pilhas dos threads e verificar sob qual pilha o handler se executa.<br />
<br />
===Exercício 4:===<br />
<br />
Neste ponto associamos um timer ao handler com o apoio do sinal ALRM. Agora os threads são escalonados automaticamente.<br />
<br />
<code><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void preparar_contexto_ping(ucontext_t *pContext, char *p)<br />
{<br />
char *stack;<br />
<br />
getcontext(pContext);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
(*pContext).uc_stack.ss_sp = stack ;<br />
(*pContext).uc_stack.ss_size = STACKSIZE;<br />
(*pContext).uc_stack.ss_flags = 0;<br />
(*pContext).uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(pContext, (void*)(*f_ping), 1, p);<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping(&cPing, "ping");<br />
preparar_contexto_ping(&cPong, "pong");<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Um Exemplo de Uso "API Padrão POSIX"}}<br />
<br />
== Um Exemplo de Uso "API Padrão POSIX" ==<br />
<br />
;Referências<br />
* Referência http://man7.org/linux/man-pages/man2/mmap.2.html<br />
<br />
<br />
Crie uma função soma que receba 2 ponteiros referenciando posições na memória, criadas utilizando nmap(), de maneira que estas posições armazenem números inteiros. A função soma deverá retornar a soma dos números apontados em regiões da memória sem a utilização de nenhuma rotina da biblioteca do C, que não sejam definidas por APIs posix, para criação destas <br />
regiões na memória (malloc, alloc, calloc). Após retornar o resultado da soma os devidos ponteiros deverão ser extintos da memória.<br />
<br />
<br />
*'''Experimento 1:''' Aumente o tamanho da memória alocada até quando for possível.<br />
<br />
Qual o tamanho limite da memória que você conseguiu alocar?<br />
<br />
*'''Experimento 2:''' Mude o escopo para PROT_NONE, após executar e depurar o código explique o que aconteceu.<br />
<br />
Em sua opinião NMAP trata-se de uma syscall ou de uma API? Afinal API e syscall são a mesma coisa? Explique.<br />
<br />
<syntaxhighlight lang=cpp><br />
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);<br />
int munmap(void *addr, size_t length);<br />
<br />
addr = Valor do início do mapeamento.<br />
length = valor do tamanho da região a ser alocada.<br />
prot = especificações de proteção da região alocada (consultar http://man7.org/linux/man-pages/man2/mmap.2.html).<br />
flags = especificação do escopo e do tipo da região criada (exemplo publica ou privada, se é anônima ou não). <br />
</syntaxhighlight><br />
<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
void* meu_malloc(size_t tamanho) {<br />
void* addr = mmap(0, // addr<br />
tamanho, // len<br />
PROT_READ | PROT_WRITE, // prot<br />
MAP_ANON | MAP_PRIVATE, // flags<br />
-1, // filedes<br />
0); // off<br />
*(size_t*)addr = tamanho;<br />
return addr;<br />
}<br />
<br />
int meu_free(void* addr) {<br />
return munmap(addr - sizeof(size_t), (size_t) addr);<br />
}<br />
<br />
<br />
int soma(int *N1, int *N2){<br />
<br />
return (*N1+*N2);<br />
<br />
}<br />
<br />
<br />
int main(int argc, char* argv[]) {<br />
<br />
int* numero1 = meu_malloc(sizeof(int));<br />
int* numero2 = meu_malloc(sizeof(int)); <br />
<br />
<br />
*numero1 = 10;<br />
*numero2 = 20; <br />
<br />
int resultado = soma(numero1, numero2);<br />
<br />
printf("\n\n O resultado da soma é %d \n\n",resultado); <br />
<br />
meu_free(numero1);<br />
meu_free(numero2);<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Processos no Linux}}<br />
<br />
== Processos no Linux - Modificado por Eraldo ==<br />
<br />
<blockquote style="background: lime; border: 1px solid black; padding: 1em;"><br />
Processos no Linux<br />
</blockquote><br />
<br />
*Exercícios propostos pelo Prof.Arliones e Modificados por Eraldo<br />
<br />
<br />
[[imagem:DesenhoForkExec.png|border|650px]]<br />
<br />
<br />
;Syscall FORK<br />
<br />
* Em um terminal, execute "man fork"<br />
** 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'''.<br />
** O '''código''' dos dois processos (pai e filho) são '''idênticos''';<br />
** Os '''dados''' dos dois processos (pai e filho) são '''idênticos NO MOMENTO DA CRIAÇÃO''';<br />
** Execução do processo filho inicia na próxima instrução do programa (no retorno da chamada FORK);<br />
** Não é possível saber qual dos processos (pai ou filho) retormará a execução primeiro - isto fica a cargo do excalonador do SO;<br />
** Valores de retorno da chamada FORK:<br />
*** (-1): erro na criação do processo (ex.: memória insuficiente);<br />
*** (0): em caso de sucesso, este é o valor de retorno recebido pelo processo filho;<br />
*** (>0): em caso de sucesso, este é o valor de retorno recebido pelo processo pai;<br />
<br />
;Syscall JOIN<br />
<br />
* A syscall JOIN é implementada no POSIX pela função '''wait()'''. Execute "man wait".<br />
** Além da função '''wait()''', há também '''waitpid()''' e '''waitid()''';<br />
** 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);<br />
** A chamada wait também libera os recursos do processo filho que termina;<br />
** '''wait()''': esta função suspende a execução do processo chamador até que UM DOS SEUS FILHOS finalize;<br />
** '''waitpid()''': suspende a execução do processo chamador até que UM FILHO ESPECÍFICO finalize;<br />
<br />
;Syscall EXEC<br />
<br />
* A syscall EXEC é implementada no POSIX pela família de funções '''exec()'''. Execute "man exec".<br />
** As principais funções da família são '''execl()''', '''execlp()''' e '''execvp()''';<br />
** 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;<br />
** 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;<br />
<br />
<br />
;Exemplos POSIX utilizando fork/wait/exec<br />
<br />
*Exemplo 1: fork/wait básico<br />
<syntaxhighlight lang=c><br />
// ex1: fork/wait básico<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
printf("processo filho\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
printf("processo pai\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
arliones@socrates:~/tmp$ gcc ex1.c -o ex1 <br />
arliones@socrates:~/tmp$ ./ex1 <br />
processo filho pid: 27858 pid pai: 27857<br />
processo pai pid: 27857 pid pai: 5337<br />
arliones@socrates:~/tmp$ <br />
</syntaxhighlight><br />
<br />
* Exemplo 2: processos pai e filho compartilham código, mas não dados.<br />
<syntaxhighlight lang=c><br />
// ex2: fork/wait "compartilhando" dados<br />
// ex2: fork/wait "compartilhando" dados<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status, k=0;<br />
printf("processo %d\t antes do fork\n", getpid());<br />
pid = fork();<br />
printf("processo %d\t depois do fork\n", getpid());<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
k += 1000;<br />
printf("processo filho\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status); // espera o filho terminar<br />
k += 10;<br />
printf("processo pai\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
k += 1000;<br />
printf("FIM processo %d\t K: %d\n", getpid(), k); <br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
processo 17056 antes do fork<br />
processo 17056 depois do fork<br />
processo 17057 depois do fork<br />
processo filho pid: 17057 K: 1000 endereço K: 0x7ffd8923e318<br />
processo pai pid: 17056 K: 10 endereço K: 0x7ffd8923e318<br />
</syntaxhighlight><br />
<br />
* Modificação no código: comentar linhas 23 e 30<br />
<br />
<syntaxhighlight lang=bash><br />
<br />
</syntaxhighlight><br />
<br />
* Analise os resultados e busque entender a diferença.<br />
*Perguntas e desafios.:<br />
#Analisando os valores impressos de k pode-se dizer que os dados são compartilhados entre os dois processos?<br />
#O endereço de k impresso é o mesmo nos dois processos. ISto não contradiz a afirmação anterior?<br />
#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.<br />
<br />
<br />
;Exercício fork/wait<br />
<br />
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.<br />
<br />
*Use o comando pstree para verificar a árvore de processos criada.<br />
<br />
{{collapse top|Solução}}<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
<!--<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
--><br />
<br />
;DESAFIO: fork/wait<br />
<br />
Reimplementar o exercício anterior de criação de uma árvore de 3 processos, generalizando a criação de N processos onde N é repassado na linha de comando do programa. SUGESTÃO: usar um comando for, mas lembrar que se existe um fork dentro do for, então cada filho gerado dará continuidade a execução do for. É necessário que o processo faça um exit ou retorne neste momento.<br />
<br />
;DESAFIO: Exercício status/wait<br />
<br />
O ''status'' passado como parâmetro à função ''wait(&status)'' é, na verdade, o mecanismo de retorno de resultado do ''wait/waitpid''. Ao retornar, esta variável contém informações sobre o resultado da execução do processo filho. Por exemplo, se um processo terminou normalmente (i.e., chamou ''exit''), o comando ''WIFEXITED(status)'' retorna ''true''. Este comando retorna ''false'' se o processo foi abortado (e.g., ''segmentation fault'') ou morto (e.g., ''kill''). Investigue no manual do wait no Linux (''man wait'') o funcionamento do comando WEXITSTATUS(status). <br />
Imagine um problema de busca de dados armazenados na forma de uma matriz de inteiros 4x30. Você está interessado em saber quantas ocorrências de um determinado número existe em cada linha da matriz. Note que que são tarefas que podem ser paralelizadas e usufruir de um sistema capaz de executá-las em paralelo. Faça uma implementação paralelizando 4 processos filhos a partir de um pai, onde cada processo é responsável por uma busca. A quantidade de ocorrências do número buscado é retornada e capturada através de WEXITSTATUS.<br />
<br />
;Syscall EXEC<br />
<br />
*Exemplo exec()<br />
<br />
<syntaxhighlight lang=c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
execl("/bin/ls","ls","-l", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 1: Modificar o código para mostrar que o exec() não retorna (colocar um printf após o exec).<br />
<br />
*Exercício 2: Criar um exemplo (dois programas ) para demonstrar que o exec não cria novo processo. <br />
**Crie um primeiro programa (prog1) que imprime o seu pid e depois faz um exec do segundo programa.<br />
**Crie o segundo programa que simplesmente imprime o pid.<br />
<br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU ANTES DO EXEC: Meu pid é %d\n", getpid());<br />
execl("./prog2","prog2", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU DEPOIS DO EXEC:Meu pid é %d\n", getpid());<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 3: Criar um exemplo usando fork/exec mostrando que um processo pai cria um filho e espera por sua execução. O filho executa o comando "ps aux". Ambos devem mostrar seus pids.<br />
<br />
{{collapse bottom}} <br />
{{collapse top| bg=lightyellow | expandir=true | Threads de aplicação}}<br />
<br />
== Threads de aplicação ==<br />
<br />
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:<br />
*'''getcontext(&a)''': salva o contexto na variável '''a''';<br />
*'''setcontext(&a)''': restaura um contexto salvo anteriormente na variável '''a''';<br />
*'''swapcontext(&a,&b)''': salva o contexto atual na variável '''a''' e restaura o contexto salvo anteriormente na variável '''b''';<br />
*'''makecontext(&a, ...)''': ajusta parâmetros internos do contexto salvo em '''a''';<br />
*'''ucontext_t''': as variáveis '''a''' e '''b''' são do tipo '''ucontext_t'''. Este tipo armazena um contexto.<br />
<br />
Busque mais informações sobre estas funções utilizando o programa manpage do Linux (ex.: man getcontext).<br />
<br />
Estude o código no arquivo pingpong.c abaixo e explique seu funcionamento.<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
*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.<br />
*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.<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain, cFnew;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_new(void * arg1, void * arg2,void * arg3,void * arg4) <br />
{<br />
printf ("%s: Primeira string %s %s %s\n",(char*) arg1,(char*) arg2,(char*) arg3, (char*) arg4);<br />
swapcontext(&cFnew, &cMain); <br />
}<br />
<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
<br />
getcontext(&cFnew);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cFnew.uc_stack.ss_sp = stack ;<br />
cFnew.uc_stack.ss_size = STACKSIZE;<br />
cFnew.uc_stack.ss_flags = 0;<br />
cFnew.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cFnew, (void*)(*f_new), 4, "\tF_new", "\tAlo", "\tMundo","\tReal");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
swapcontext(&cMain, &cFnew);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
--><br />
Exercício 3: O que acontece se um dos threads é colocado para dormir? Todos os demais threads param a sua execução.<br />
<br />
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/<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Trocas de mensagens com pipes}}<br />
<br />
== Trocas de mensagens com pipes ==<br />
<br />
;Troca de mensagens<br />
Um mecanismo disponibilizado por sistemas UNIX para troca de mensagens entre processos é o PIPE. Pipes são mecanismos de comunicação indireta onde mensagens são trocadas através de ''mailboxes''. Cada ''mailbox'' possui um identificador único, permitindo que processos identifiquem o canal de comunicação entre eles. O fluxo de mensagens em um Pipe é:<br />
*'''unidirecional''': sobre um mesmo pipe, apenas um processo envia mensagens e um processo recebe mensagens;<br />
*'''FIFO''': as mensagens são entregues na ordem de envio;<br />
*'''não-estruturado''': não há estrutura pré-definida para o formato da mensagem.<br />
No UNIX, pipes são inicializados através da '''SystemCall''' ''pipe'', que possui a seguinte sintaxe:<br />
*''int pipe(int pipefd[2])'': ''pipe'' inicializa um novo pipe no sistema e retorna, no array pipefd, os descritores identificando cada uma das pontas do pipe. A primeira posição do array, i.e. pipefd[0], recebe o descritor que pode ser aberto apenas para leitura, enquanto a segunda posição do array, i.e. pipefd[1], recebe o descritor que pode ser aberto apenas para escrita. A função retorna zero no caso de sucesso, ou -1 se ocorrer erro.<br />
As primitivas send/receive para uso de um pipe no UNIX são implementadas por '''SystemCalls''' read/write, conforme segue:<br />
*''ssize_t read(int fd, void *buf, size_t count)'': “puxa” dados do pipe identificado pelo descritor fd. Os dados recebidos são os apontados pelo ponteiro buf, sendo count a quantidade máxima de bytes a serem recebidos. A função retorna o número de bytes recebidos.<br />
*''ssize_t write(int fd, const void *buf, size_t count)'': “empurra” dados no pipe identificado pelo descritor fd. Os dados transmitidos são os apontados pelo ponteiro buf, sendo count a quantidade de bytes a serem transmitidos. A função retorna o número de bytes transmitidos.<br />
<br />
*Exemplo 1: Transmitindo e recebendo pelo próprio processo<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main()<br />
{<br />
int fd[2];<br />
char *ptr = "Alo eu mesmo";<br />
char *ptr_alvo;<br />
int tamanho_dados, ret;<br />
<br />
tamanho_dados = strlen(ptr)+1;<br />
<br />
if (pipe(fd)==-1){<br />
printf ("erro criação pipe\n");<br />
exit(-1);<br />
}<br />
printf("Transmitido %d bytes\n", tamanho_dados);<br />
write (fd[1], ptr, tamanho_dados);<br />
<br />
ptr_alvo = malloc(tamanho_dados);<br />
<br />
ret=read(fd[0],ptr_alvo,tamanho_dados);<br />
<br />
printf("ret = %d dados => %s\n", ret, ptr_alvo); <br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
*Exemplo 2: Abaixo há um exemplo de programa criando um pipe e compartilhando os descritores entre dois processos (criados via ''fork()'').<br />
<syntaxhighlight lang=c><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
<br />
char *message = "This is a message!!!" ;<br />
<br />
main()<br />
{<br />
char buf[1024] ;<br />
int fd[2];<br />
pipe(fd); /*create pipe*/<br />
if (fork() != 0) { /* I am the parent */<br />
write(fd[1], message, strlen (message) + 1) ;<br />
}<br />
else { /*Child code */<br />
read(fd[0], buf, 1024) ;<br />
printf("Got this from MaMa!!: %s\n", buf) ;<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
*'''Exercício 1: construa um “pipeline”'''. Crie um programa que conecta 4 processos através de 3 pipes. Utilize ''fork()'' para criar vários processos.<br />
<br />
<syntaxhighlight lang=cpp><br />
<br />
//Solução possível<br />
<br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
pipe(fd);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
<br />
</syntaxhighlight><br />
<br />
*'''Exercício 3: Modifique o exercício anterior para que o processo D, através de um novo pipe, mande uma mensagem diretamente para o pai de todos.<br />
<br />
<!--<br />
<code><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
int fd_retorno[2];<br />
<br />
pipe(fd);<br />
pipe(fd_retorno);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size);<br />
read(fd_retorno[0], buf, size);<br />
printf("PAI:%s\n", buf); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
char *ptr_msg_ret="Ok msg de D para o pai";<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
write(fd_retorno[1],ptr_msg_ret,strlen(ptr_msg_ret)+1);<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
*'''Exercício 3: Consultor de Login de Acesso:'''. Estude o link https://www.geeksforgeeks.org/named-pipe-fifo-example-c-program/ e projete um programa cliente servidor da seguinte forma: (i) O servidor possui uma tabela de usuários (userid). O user_id é de tamanho fixo de 7 caracteres. O servidor espera por consultas para verificar se um usuário está na tabela. Se estiver responde com o caracter 'S' senão com 'N'. (ii) O cliente espera por user_id no teclado e consulta o servidor sobre sua existência na tabela. O cliente imprime na tabela a existência ou não do usuário.<br />
<br />
*'''Exercício 4: cópia de arquivo'''. Projete um programa de cópia de arquivos chamado FileCopy usando pipes comuns. Esse programa receberá dois parâmetros: o primeiro é o nome do arquivo a ser copiado e o segundo é o nome do arquivo copiado. Em seguida, o programa criará um pipe comum e gravará nele o conteúdo do arquivo a ser copiado. O processo filho lerá esse arquivo do pipe e o gravará no arquivo de destino. Por exemplo, se chamarmos o programa como descrito a seguir:<br />
:<syntaxhighlight lang=bash><br />
$ FileCopy entrada.txt copia.txt<br />
</syntaxhighlight><br />
:o arquivo ''entrada.txt'' será gravado no pipe. O processo filho lerá o conteúdo desse arquivo e o gravará no arquivo de destino ''copia.txt''. Escreva o programa usando os pipes da API POSIX no Linux.<br />
<br />
<br />
{{collapse bottom}}<br />
<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Exercícios sobre Memória Compartilhada}}<br />
<br />
==SHARED MEMORY: Produtor (pai) - Consumidor (filho) - ==<br />
<br />
<!-- Parou aki 20/08<br />
<br />
<br />
*'''Experimento 2:''' Complete o código a seguir para que os processos pai e filho possam compartilhar um segmento de memória. O filho escreve no segmento e o pai imprime na tela o conteúdo da mensagem.<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
char *ptr_msg = "alo pai, tudo bem?"; <br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
//completar aqui<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
<!--<br />
<code><br />
<br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/types.h><br />
#include <string.h><br />
#include <stdlib.h><br />
<br />
int main(void)<br />
{<br />
int fd[2], pipe_ret, filho;<br />
char string[] = "Hello, pipe!\n";<br />
char buffer[20];<br />
<br />
pipe(fd);<br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
/*Mandar string para a extremidade do pipe*/<br />
write(fd[1], string, (strlen(string)+1));<br />
exit(0);<br />
}<br />
else<br />
{<br />
<br />
/* Read in a string from the pipe */<br />
pipe_ret = read(fd[0], buffer, (20*sizeof(char)));<br />
printf("Recebi este texto %s", buffer);<br />
}<br />
<br />
return(0);<br />
}<br />
<br />
<br />
<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
key = ftok("teste_sh.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644 | IPC_CREAT));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
<br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
strncpy(segmento, "mensagem compartilhada", SHM_SIZE); <br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
--><br />
<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Memória Compartilhada}}<br />
*'''Experimento Shared Memory:''' Complete o código a seguir para que os processos pai e filho possam compartilhar um segmento de memória. O filho escreve no segmento e o pai imprime na tela o conteúdo da mensagem.<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
char *ptr_msg = "alo pai, tudo bem?"; <br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
//completar aqui strcpy(segmento, ptr_msg); //aqui deveria testar a cpacidade da área...<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exemplo com ftok:<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
key = ftok("./teste.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644 | IPC_CREAT));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
<br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
strncpy(segmento, "mensagem compartilhada", SHM_SIZE); <br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exemplo com ftok entre processos sem parentesco:<br />
<br />
Criar um arquivo teste.txt e em um terminal executar:<br />
<br />
<syntaxhighlight lang=c><br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
int modo,filho;<br />
<br />
struct minha_struct {<br />
char flag;<br />
int numero;<br />
} *ptr;<br />
<br />
<br />
key = ftok("./teste.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644 | IPC_CREAT));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
ptr = (struct minha_struct *) shmat(shmid, (void *)0, 0);<br />
if ((char *)ptr == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
ptr->flag =0;<br />
ptr->numero = 0;<br />
while (ptr->flag==0) { <br />
printf("%d\n", ptr->numero);<br />
sleep(1);<br />
} <br />
<br />
if (shmdt(ptr) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Em outro terminal executar:<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
struct minha_struct {<br />
char flag;<br />
int numero;<br />
} *ptr;<br />
<br />
<br />
key = ftok("./teste.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
ptr = (struct minha_struct *) shmat(shmid, (void *)0, 0);<br />
if ((char *)ptr == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
<br />
<br />
while (ptr->numero++<10)<br />
sleep(1);<br />
<br />
ptr->flag = 1;<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Exercício Desafio: Implementar o problema do buffer circular usando memória compartilhada.<br />
<br />
{{collapse bottom}}<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Exercício (Algoritmo de Peterson)}}<br />
<br />
== Exercício (Algoritmo de Peterson) ==<br />
<br />
<br />
'''Exercício 1''': Sincronize o código a seguir, de maneira que o processo pai imprima apenas os números impares e o processo filho os números pares. Para isso utilize o algoritmo de '''Peterson''' visto em aula. '''Utilize memória compartilhada''' para comunicação entre os processos.<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
main()<br />
{ <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int i; <br />
<br />
for(i = 0;i < 10;i=i+2){ <br />
printf("Processo pai %d \n", i); <br />
<br />
} <br />
<br />
<br />
}<br />
<br />
else { /*Child code */<br />
int i; <br />
for(i = 1;i < 10;i=i+2){ <br />
printf("Processo filho %d \n", i); <br />
<br />
}<br />
<br />
<br />
}<br />
<br />
exit(0);<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
'''Exercício 2''': Considerando o exercício anterior faça a mesma sincronização, no entanto desta vez utilize a modelagem em software do TSL. <br />
* Em sua experiência, depois de testar diversas vezes as execuções de suas soluções baseadas no algoritmo de '''Peterson''' e '''Tsl''', qual sua opinião sobre as abordagens?<br />
Explique seu raciocínio. <br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Exercício (Semáforos)}}<br />
== Exercício (Semáforos) ==<br />
<br />
<br />
'''Exercício 1''': Sincronize o código a seguir, de maneira que o processo pai imprima apenas os números impares e o processo filho os números pares. Para isso utilize '''Semáforos''' de acordo com a implementação em '''semaforo.h'''. '''Utilize memória compartilhada''' para comunicação entre os processos.<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
main()<br />
{ <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int i; <br />
<br />
for(i = 0;i < 10;i=i+2){ <br />
printf("Processo pai %d \n", i); <br />
sleep(1);<br />
<br />
} <br />
<br />
<br />
}<br />
<br />
else { /*Child code */<br />
int i; <br />
for(i = 1;i < 10;i=i+2){ <br />
printf("Processo filho %d \n", i); <br />
<br />
}<br />
<br />
<br />
}<br />
<br />
exit(0);<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
SEMAFORO.H<br />
<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <sys/sem.h><br />
<br />
<br />
int criar_semaforo(int val, int chave) <br />
{<br />
int semid ;<br />
<br />
union semun {<br />
int val;<br />
struct semid_ds *buf ;<br />
ushort array[1];<br />
} arg_ctl ;<br />
<br />
key_t ft = ftok("/tmp", chave);<br />
<br />
semid = semget(ft,1,IPC_CREAT|IPC_EXCL|0666);<br />
if (semid == -1) {<br />
semid = semget(ft,1,0666); <br />
if (semid == -1) {<br />
perror("Erro semget()");<br />
exit(1) ;<br />
}<br />
}<br />
<br />
arg_ctl.val = val; //valor de início<br />
if (semctl(semid,0,SETVAL,arg_ctl) == -1) {<br />
perror("Erro inicializacao semaforo");<br />
exit(1);<br />
}<br />
return(semid) ;<br />
}<br />
<br />
void P(int semid){<br />
<br />
struct sembuf *sops = malloc(10*sizeof(int));<br />
sops->sem_num = 0;<br />
sops->sem_op = -1;<br />
sops->sem_flg = 0;<br />
semop(semid, sops, 1); <br />
free(sops);<br />
<br />
}<br />
<br />
<br />
void V(int semid){<br />
<br />
struct sembuf *sops = malloc(10*sizeof(int));<br />
sops->sem_num = 0;<br />
sops->sem_op = 1;<br />
sops->sem_flg = 0; <br />
semop(semid, sops, 1); <br />
free(sops);<br />
<br />
} <br />
<br />
<br />
<br />
void sem_delete(int semid) <br />
{<br />
<br />
if (semctl(semid,0,IPC_RMID,0) == -1)<br />
perror("Erro na destruicao do semaforo");<br />
}<br />
<br />
<br />
<br />
<br />
</syntaxhighlight><br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Programação concorrente}}<br />
<br />
== Programação concorrente ==<br />
<br />
;POSIX Threads<br />
A 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):<br />
*''pthread_create'': cria uma thread;<br />
*''pthread_kill'': força a terminação de uma thread;<br />
*''pthread_join'': sincroniza o final de uma thread (qual a diferença/semelhança com o ''wait'' que usamos para processos?);<br />
*''pthread_exit'': finaliza uma thread.<br />
Para utilizar estas funções é necessário linkar o programa à libpthread (''-lpthread''). <br />
<br />
<br />
;POSIX pthread mutex<br />
<br />
A biblioteca pthread implementa um tipo ''pthread_mutex_t'', que garante a exclusão mútua entre threads. Estes mutex são manipulados através das funções (acesse as man-pages das chamadas para maiores detalhes):<br />
*''pthread_mutex_lock'': acessa um mutex.<br />
*''pthread_mutex_trylock'': tenta acessar um mutex (retorna valor indicando sucesso ou falha no lock).<br />
*''pthread_mutex_unlock'': libera um mutex.<br />
<br />
<br />
<br />
<br />
;POSIX Semaphores<br />
<br />
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):<br />
*''sem_init'': inicializa um semáforo;<br />
*''sem_destroy'': destroy um semáforo;<br />
*''sem_wait'': implementa a operação ''p'';<br />
*''sem_post'': implementa a operação ''v''.<br />
Para utilizar estas funções é necessário linkar o programa à librt ou à libpthread (''-lrt'' ou ''-lpthread'').<br />
<br />
;Exercício 1<br />
<br />
O programa abaixo cria 5 threads, e cada uma destas threads atualiza uma variável global (memória compartilhada).<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include <pthread.h><br />
#include <signal.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
pthread_mutex_t mut;<br />
<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
}<br />
</syntaxhighlight><br />
<br />
# Compile este programa. <br />
# Execute este programa várias vezes. Ele funciona? Será que ele gera as saídas esperadas?<br />
# Identifique as '''seções críticas''' do programa.<br />
# Corrija o programa utilizando '''mutex'''. <br />
# Analise a função ''AtualizaSaldo()'' com a sua solução. Lembre-se que o uso do mutex implica em apenas uma thread acessar a seção crítica por vez, enquanto outras threads ficam bloqueadas, esperando. Disso vem que, quanto menor o trecho de código entre um ''lock'' e um ''unlock'', menos tempo uma thread necessita ficar esperando.<br />
# Modifique o programa para usar um semáforo binário ao invés de um mutex em sua solução.<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <cstring><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
<br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
sem_t sem;<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
int value;<br />
sem_wait(&sem);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
sem_getvalue(&sem, &value);<br />
printf("valor sem = %d\n", value);<br />
sem_post(&sem);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
sem_init(&sem,0,1);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
sem_destroy(&sem);<br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
<br />
;Exercício 2<br />
Refaça o exercício 3 usando processos criados com fork e exec. O semáforo deve ser criado em uma região de memória compartilhada.<br />
<br />
;Exercício 3<br />
Implemente com pthreads e semáforos/mutex a solução do produtor/comsumidor.<br />
<br />
;Exercício 4<br />
<br />
O programa abaixo manipula uma matriz de tamanho MxN (veja os defines para o tamanho da matriz). A função ''SumValues'' soma todos os valores em uma linha da matriz. A linha a ser somada é identificada pela variável ''i''. Modifique o programa principal (''main'') nos locais indicados para:<br />
# Criar N threads, uma para somar os valores de cada linha.<br />
# Receber o resultado do somatório de cada linha e gerar o somatório total da matriz.<br />
# Analise o programa: há problemas de sincronização que precisam ser resolvidos? Se sim, resolva-os.<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include "thread.h"<br />
<br />
/* number of matrix columns and rows */<br />
#define M 5<br />
#define N 10<br />
<br />
using namespace std;<br />
<br />
int matrix[N][M];<br />
Thread *threads[N];<br />
<br />
<br />
/* thread function; it sums the values of the matrix in the row */<br />
int SumValues(int i)<br />
{<br />
int n = i; /* number of row */<br />
int total = 0; /* the total of the values in the row */<br />
int j;<br />
for (j = 0; j < M; j++) /* sum values in the "n" row */<br />
total += matrix[n][j];<br />
cout << "The total in row" << n << " is " << total << "." << endl;<br />
/* terminate a thread and return a total in the row */<br />
exit(total);<br />
}<br />
<br />
int main(int argc, char *argv[])<br />
{<br />
int i, j;<br />
int total = 0; /* the total of the values in the matrix */<br />
<br />
/* initialize the matrix */<br />
for (i = 0; i < N; i++)<br />
for (j = 0; j < M; j++)<br />
matrix[i][j] = i * M + j;<br />
<br />
/* create threads */<br />
/* COLOQUE SEU CÓDIGO PARA CRIAR AS THREADS AQUI! */<br />
<br />
/* wait for terminate a threads */<br />
/* COLOQUE SEU CÓDIGO PARA PEGAR O SOMATÓRIO DE LINHAS E TOTALIZAR A SOMA DA MATRIZ AQUI! */<br />
<br />
cout << "The total values in the matrix is " << total << endl;<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Lista de exercícios "Revisão para Prova" }}<br />
<br />
== Lista de exercícios/Revisão para Prova ==<br />
<br />
A lista de exercícios referente a primeira prova (Parte introdutória + Processos) segue neste LINK [http://docente.ifsc.edu.br/andre.damato/sop2018/lista_rev1.pdf | Lista de exercícios]. <br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Primeiro trabalho}}<br />
== JOGO DA VIDA DE CONWAY e JANTAR DOS FILÓSOFOS==<br />
<br />
;Referências<br />
<br />
* [https://www.open-mpi.org/doc/current/ MPI]<br />
<br />
* [https://quark.phy.bnl.gov/~creutz/qcdoc/mpi/mpi.h Tipos de dados MPI]<br />
<br />
* [https://pt.wikipedia.org/wiki/Jogo_da_vida Jogo da Vida]<br />
<br />
<br />
<br />
<br />
A partir da implementação sequencial do Game of Life apresentada a seguir, estude o código e transforme esta implementação em uma implementação paralela utilizando o protocolo de passagem de mensagens MPI.<br />
Perceba que a impĺementação mencionada utiliza como parâmetros de entrada um aquivo contendo o estado inicial do jogo, e o número de gerações que o usuário deseja rodar. A evolução do estado inicial <br />
é impressa na tela passo a passo. Sendo assim, a partir disso:<br />
<br />
*'''1: Elabore uma implementação com 2 processos para o jogo da vida utilizando o protocolo MPI, de maneira que um processo execute uma geração i qualquer e o outro execute a geração seguinte i+1''' <br />
<br />
*'''2: (0,7) Os processos deverão se comunicar utilizando as funções do protocolo MPI.''' <br />
<br />
*'''3: (0,3) Relatório simplificado explicando a sua solução. Utilize diagramas para representar a comunicação entre os processos, explicando como a matriz do jogo é transferida entre os processos. ''' <br />
<br />
*'''4: Entregue o Relatório e o código fonte do trabalho em um pacote compactado via e-mail (PRAZO 19/10). <br />
<br />
<br />
<br />
* ''' Compilar o código com MPI '''<br />
<code><br />
mpicc -o nomeApp arquivo.c<br />
</syntaxhighlight><br />
<br />
* ''' Rodar rodar programa utilizando MPI '''<br />
<code><br />
mpirun -np numeroDeProcessos ./nomeApp entrada.txt gerações<br />
</syntaxhighlight><br />
<br />
* (int) -np: Quantidade de processos que você deseja executar <br />
<br />
* entrada.txt: Arquivo de entrada com estado inicial do jogo <br />
<br />
* (int) gerações: número de gerações que você deseja rodar<br />
<br />
* [http://docente.ifsc.edu.br/andre.damato/sop2018/entrada.txt Arquivo de entrada para Testes]<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
<br />
<br />
<br />
/*<br />
<br />
Conway's Game of Life<br />
<br />
Compilar código com MPI<br />
mpicc -o nomeApp arquivo.c<br />
<br />
<br />
Rodar rodar programa utilizando MPI<br />
<br />
mpirun -np numeroDeProcessos ./nomeApp entrada.txt gerações<br />
<br />
(int) -np: Quantidade de processos que você deseja executar <br />
entrada.txt: Arquivo de entrada com estado inicial do jogo <br />
(int) gerações: número de gerações que você deseja rodar<br />
<br />
<br />
*/<br />
<br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h><br />
#include "mpi.h"<br />
<br />
<br />
//Numero de linhas e colunas<br />
#define nLinhas 32<br />
#define nColunas 82 <br />
<br />
char *matriz[nLinhas];<br />
char *entrada[nLinhas];<br />
<br />
<br />
void iniciar() {<br />
<br />
int i;<br />
<br />
//Alocar espaço em memória para as matrizes<br />
for (i = 0; i < nLinhas; i++ ) <br />
matriz[i] = (char *) malloc((nColunas) * sizeof( char )); <br />
<br />
<br />
}<br />
<br />
int adjacente(char **matriz, int i, int j){<br />
<br />
int x,y, initX, initY, limitX, limitY;<br />
int vizinhos = 0;<br />
<br />
if(i == 0)<br />
initX = 0;<br />
else <br />
initX = -1;<br />
<br />
if(i == (nLinhas-1)) <br />
limitX = 1;<br />
else<br />
limitX = 2;<br />
<br />
<br />
if(y == 0)<br />
initY = 0;<br />
else <br />
initY = -1;<br />
<br />
if(y == (nColunas-3)) <br />
limitY = 1;<br />
else<br />
limitY = 2;<br />
<br />
for(x = initX ; x < limitX; x++){<br />
for(y = initY; y < limitY; y++){<br />
if(matriz[i+x][j+y] == '#') <br />
vizinhos++; <br />
} <br />
}<br />
<br />
<br />
if(matriz[i][j] == '#') <br />
return (vizinhos-1);<br />
else <br />
return vizinhos;<br />
<br />
}<br />
<br />
<br />
void calculoGeracao(char **matriz, int ger) {<br />
<br />
int i, j, a;<br />
char novaGeracao[nLinhas][nColunas];<br />
<br />
/* Aplicando as regras do jogo da vida */<br />
for (i=0; i < nLinhas; i++){ <br />
for (j=0; j < nColunas; j++) {<br />
<br />
a = adjacente(matriz, i, j);<br />
<br />
if (a == 2) novaGeracao[i][j] = matriz[i][j];<br />
if (a == 3) novaGeracao[i][j] = '#';<br />
if (a < 2) novaGeracao[i][j] = ' ';<br />
if (a > 3) novaGeracao[i][j] = ' ';<br />
<br />
if (j == 0)<br />
novaGeracao[i][j] = '"';<br />
} <br />
<br />
novaGeracao[i][79] = '"';<br />
novaGeracao[i][80] = '\n';<br />
<br />
<br />
}<br />
<br />
/* Passando o resultado da nova geração para a matriz de entrada */<br />
for (i=0; i < nLinhas; i++){ <br />
for (j=0; j < nColunas; j++) <br />
matriz[i][j] = novaGeracao[i][j];<br />
}<br />
}<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
main(int argc, char *argv[2]){<br />
<br />
/* Para uso com MPI<br />
<br />
<br />
//Variáveis para uso com MPI<br />
int numeroDeProcessos = 0;<br />
int rank = 0;<br />
MPI_Status status; <br />
<br />
//Iniciar MPI---<br />
MPI_Init( &argc, &argv );<br />
<br />
//Atribui a variável numeroDeProcessos o número de processos passado como parâmetro em -np <br />
MPI_Comm_size( MPI_COMM_WORLD, &numeroDeProcessos );<br />
<br />
//Pega o valor do rank (processo)<br />
MPI_Comm_rank( MPI_COMM_WORLD, &rank );<br />
*/<br />
<br />
<br />
FILE *matrizEntrada;<br />
matrizEntrada = fopen(argv[1], "r");<br />
iniciar();<br />
<br />
<br />
if (matrizEntrada == NULL)<br />
printf ("Não posso abrir o arquivo \"%s\"\n", argv[1]);<br />
<br />
<br />
char str[nColunas];<br />
int linha = 0;<br />
<br />
<br />
<br />
//Lendo o estado inicial do jogo a partir do arquivo<br />
while((fgets(str, nColunas, matrizEntrada) != NULL)&&(linha < nLinhas)){<br />
strcat(matriz[linha], str);<br />
linha++;<br />
}<br />
<br />
int i,gens; <br />
<br />
<br />
for(gens = 0; gens < atoi(argv[2]); gens++){ //Gens é o número de gerações especificado no segundo parâmetro <br />
<br />
calculoGeracao(matriz, gens);<br />
printf("%c[2J",27); // Esta linha serve para limpar a tela antes de imprimir o resultado de uma geração <br />
<br />
//Lendo o estado do jogo e imprime na tela <br />
for(i = 0; i < nLinhas; i++)<br />
printf("%s", matriz[i]); <br />
<br />
sleep(1);<br />
<br />
}<br />
<br />
<br />
for(i = 0; i < nLinhas; i++) <br />
free(matriz[i]); <br />
<br />
<br />
<br />
/* Finaliza o MPI */ <br />
//MPI_Finalize();<br />
<br />
exit(0);<br />
} <br />
<br />
<br />
</syntaxhighlight><br />
<br />
<br />
;Jantar dos Filósofos<br />
O problema clássico Jantar dos Filósofos consiste em que n fluxos (n filósofos) disputam n recursos (n talheres). No problema, para conseguir "jantar" (ou executar), cada filósofo precisa pegar dois talheres adjascentes a ele. Cada recurso é compartilhado por dois filósofos.<br />
*[http://www.doc.ic.ac.uk/~jnm/concurrency/classes/Diners/Diners.html Veja esta simulação]<br />
*[http://en.wikipedia.org/wiki/Dining_philosophers_problem Veja esta descrição do problema]<br />
<br />
<br />
* ''' (0,7) programa abaixo implementa um Jantar dos Filósofos utilizando semáforos para sincronização. Contudo, as chamadas para as operações ''v'' e ''p'' foram removidas, conforme comentários no código. Re-insira as operações no código e analise a solução. Esta modificação é suficiente para garantir que não haverá deadlock? Se sim, mostre o porque. Se não, proponha uma solução completa. '''<br />
<br />
<br />
*''' (0,3) Relatório simplificado explicando a sua solução. ''' <br />
<br />
*''' Entregue o Relatório e o código fonte do trabalho em um pacote compactado via e-mail (PRAZO 19/10). <br />
<br />
<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include "thread.h"<br />
#include "semaphore.h"<br />
<br />
using namespace std;<br />
<br />
const int DELAY = 10000000;<br />
const int ITERATIONS = 5;<br />
<br />
Semaphore chopstick[5];<br />
<br />
int philosopher(int n)<br />
{<br />
cout << "Philosopher " << n << " was born!\n";<br />
<br />
int first = (n < 4)? n : 0; // left for phil 0 .. 3, right for phil 4<br />
int second = (n < 4)? n + 1 : 4; // right for phil 0 .. 3, left for phil 4<br />
<br />
// Foram removidos do laço abaixo:<br />
// - uma chamada para chopstick[first].p()<br />
// - uma chamada para chopstick[second].p()<br />
// - uma chamada para chopstick[first].v()<br />
// - uma chamada para chopstick[second].v()<br />
for(int i = 0; i < ITERATIONS; i++) {<br />
cout << "Philosopher " << n << " thinking ...\n";<br />
for(int i = 0; i < DELAY * 10; i++);<br />
<br />
cout << "Philosopher " << n << " eating ...\n";<br />
for(int i = 0; i < DELAY; i++);<br />
}<br />
<br />
return n;<br />
}<br />
<br />
int main()<br />
{<br />
cout << "The Dining-Philosophers Problem\n";<br />
<br />
Thread * phil[5];<br />
for(int i = 0; i < 5; i++)<br />
phil[i] = new Thread(&philosopher, i);<br />
<br />
int status;<br />
for(int i = 0; i < 5; i++) {<br />
phil[i]->join(&status);<br />
if(status == i)<br />
cout << "Philosopher " << i << " went to heaven!\n";<br />
else<br />
cout << "Philosopher " << i << " went to hell!\n";<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Softwares básicos, caso Hello Word! (Trabalho 2) Entrega dia 09/11}}<br />
<br />
== Softwares básicos, caso Hello Word! ==<br />
<br />
O objetivo do experimento de hoje é pesquisar e entender os processos de atribuição de endereços de programas realizados em tempo de compilação pelos softwares básicos como: compilador, linker, e assembler. Sendo assim, neste experimento vamos utilizar os seguintes softwares para criação e análise de código:<br />
<br />
*'''GCC''': compilador para gerar código objeto a partir de um código de programa escrito na linguagem c;<br />
*'''GNU Linker (LD)''': Para vincular os códigos (módulos) objetos do programa;<br />
*[https://linux.die.net/man/1/ld| Linker ] <br />
*'''GNU Assembler''': Para gerar o código executável a partir do código objeto;<br />
*[https://linux.die.net/man/1/as | assembler]<br />
* '''OBJDUMP''': Para mostrar informações do código;<br />
*[https://linux.die.net/man/1/objdump | Objdump ]<br />
<br />
<br />
A seguir segue descrito o programa a ser utilizado no exercício 1:<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
int main()<br />
{<br />
printf("Hello, World!");<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
Trata-se do programa hello word, este programa apenas exibe uma mensagem na tela. No entanto, vamos analisar como são as etapas confecção do executável a partir deste código ''simples''. <br />
<br />
Exercício 1: <br />
* Compile o programa hello word, e o transforme em código objeto utilizando o programa GCC. Para esta tarefa execute o seguinte comando:<br />
<code><br />
gcc -o hello hello.c <br />
</syntaxhighlight><br />
* Agora abra o código objeto utilizando o programa OBJDUMP.<br />
<code><br />
objdump -D hello<br />
</syntaxhighlight><br />
* Identifique quais são as seções de código obtidas a partir do '''hello.c'''.<br />
* Pesquise e entenda o significado das seções de código: .bss, .txt, .data, .init.<br />
* Faça uma análise e identifique o endereço de memória que o programa ''hello world'' vai ser carregado. <br />
* Este código objeto é relocável? Justifique sua resposta.<br />
* Agora gere o código assembly do hello world.<br />
<code><br />
gcc -S hello.c<br />
</syntaxhighlight> <br />
*Agora gere o código executável utilizando o programa '''AS''' e o programa '''LD'''.<br />
<code><br />
as -o hello.o hello.s<br />
</syntaxhighlight><br />
* Como a etapa de linkagem para a construção do código executável está sendo executada sem o auxílio do '''GCC''', necessitamos vincular manualmente as bibliotecas necessárias. Para criar apropriadamente o executável vamos precisar das bibliotecas '''ld-linux-x86-64.so.2''', '''crt1.o''', '''crti.o''', '''crtn.o'''.<br />
* Para descobrir suas respectivas localizações use o comando '''LOCATE'''. Por exemplo:<br />
<code><br />
<br />
locate crti.o <br />
<br />
</syntaxhighlight><br />
<br />
ou <br />
<br />
<code><br />
<br />
find /usr/ -name crti*<br />
<br />
</syntaxhighlight><br />
<br />
* Agora que já sabemos a localização das bibliotecas necessárias vamos vincular essas a nossa aplicação.<br />
<code><br />
ld --dynamic-linker /caminho/ld-linux-x86-64.so.2 /caminho/crt1.o /caminho/crti.o /caminho/crtn.o hello.o -lc -o hello.exe<br />
</syntaxhighlight><br />
<br />
* Agora abra o código objeto utilizando o programa OBJDUMP.<br />
* Faça uma análise e identifique o endereço de memória em que o programa ''hello world'' inicializa suas estruturas na memória.<br />
* Dica!<br />
<code><br />
objdump -D -s -j .init hello.exe<br />
</syntaxhighlight><br />
* Houve diferença entre os endereços do programa executável em relação ao código objeto? Explique.<br />
* Explique as principais diferenças entre o arquivo objeto .o e o executável final. (dica utilize o objdump para fazer essa análise)<br />
{{collapse bottom}}<br />
<ol><br />
<li> Estudar e executar o código em http://cs.lmu.edu/~ray/notes/gasexamples/ <br />
Detalhes das chamadas na arquitetura x86_64 ver em https://lwn.net/Articles/604287/ <br />
<li>Estudar e executar o código usando a função (em conformidade com a API POSIX) write() para o ''hello world'':<br />
<code><br />
#include <unistd.h> <br />
<br />
main()<br />
{<br />
write(1,"Alo Mundo\n",10);<br />
}<br />
</syntaxhighlight><br />
</li><br />
<li> Use o comando strace para verificar todas as chamadas de sistema dos programas acima.<br />
</li><br />
<li><br />
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:<br />
<code><br />
main()<br />
{<br />
meu_hello_world();<br />
}<br />
</syntaxhighlight><br />
</li><br />
Gere o assembly do código em C e discuta a diferença entre uma chamada de função e uma chamada de sistema.<br />
<li><br />
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:<br />
<code><br />
#include <string.h><br />
main()<br />
{<br />
char *p="Tudo bem com vocês?";<br />
meu_hello_world(p, strlen(p));<br />
}<br />
</syntaxhighlight><br />
Solução:<br />
{{collapse top|Solução}}<br />
<code><br />
modificado de http://cs.lmu.edu/~ray/notes/gasexamples/<br />
.global meu_hello_world<br />
<br />
.text<br />
meu_hello_world:<br />
<br />
push %rdi # salva primeiro parâmetro<br />
push %rsi # salva segundo parâmetro<br />
mov $1, %rax # system call 1 é write<br />
mov $1, %rdi # file handle 1 é stdout<br />
mov $message, %rsi # endereço da string<br />
mov $13, %rdx # número de bytes da string<br />
syscall # chamada ao sistema<br />
<br />
pop %rdx # o que havia sido passado em rsi (número de bytes) é colocado em rdx<br />
pop %rsi # o que havia sido colocado em rdi (endereço da string) é colocado em rsi<br />
mov $1, %rax # system call 1 is write<br />
mov $1, %rdi # file handle 1 é stdout<br />
syscall # nova chamada ao sistema<br />
<br />
ret<br />
<br />
message:<br />
.ascii "Hello, World\n"<br />
</syntaxhighlight><br />
</li><br />
</ol><br />
{{collapse bottom}}</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=SOP29005-2019-2&diff=162034SOP29005-2019-22019-10-04T12:19:16Z<p>127.0.0.1: /* PARTE 3 - POSIX Semaphores */</p>
<hr />
<div>=AULA 1 - Dia 30/07/2019=<br />
<br />
===Objetivos/Conteúdos===<br />
<br />
*Apresentação do Plano de Ensino<br />
**Objetivos e Conteúdo Programático da Disciplina (ver SIGAA)<br />
**Forma de Avaliação (ver SIGAA)<br />
<br />
*Introdução a Sistemas Operacionais (Cap1. do Silberschatz)<br />
**O que faz um sistema operacional (1.1)<br />
**Organização e Arquitetura de um Sistema Computacional (1.2 e 1.3)<br />
***Importância da Interrupção e Timers (1.2.1)<br />
***Estrutura de Armazenamento (1.2.2)<br />
***Estrutura de IO (1.2.3)<br />
**Estrutura e Operações de um Sistema Operacional (1.4 e 1.5)<br />
<br />
===Material de Referência===<br />
<br />
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte1.pdf Apresentação sobre histórico visão geral e estruturas básicas de um SO]<br />
* [http://codex.cs.yale.edu/avi/os-book/OSE1/slide-dir/index.html Slides Silberschatz Oitava Edição]<br />
* [http://professor.unisinos.br/barbosa/SO/ch1br.ppt Tradução Slides Silberschatz Cap1]<br />
* [http://professor.unisinos.br/barbosa/SO/ch2br.ppt Tradução Slides Silberschatz Cap2]<br />
* [http://professor.unisinos.br/barbosa/SO/ch3br.ppt Tradução Slides Silberschatz Cap3]<br />
* [http://professor.unisinos.br/barbosa/SO/ch4br.ppt Tradução Slides Silberschatz Cap4]<br />
* [http://wiki.inf.ufpr.br/maziero/doku.php?id=so:livro_de_sistemas_operacionais Livro do Prof.Maziero]<br />
* [http://deptinfo.unice.fr/~rr/l3systres/ Université Nice Sophia Antipolis]<br />
<br />
Arliones:<br />
<br />
*[https://www.dropbox.com/s/dt80g3tml65rpmg/SOP29005-parte6.odp?dl=0]<br />
*[https://www.dropbox.com/s/7lneavq0go9kz2t/SOP29005-parte7.odp?dl=0]<br />
<br />
===Leitura Recomendada===<br />
<br />
*Cap.1 do Silberschatz principalmente:<br />
**1.1 a 1.9<br />
<br />
===Exercícios Práticos de Apoio a Aula===<br />
<br />
Na sequência. com fins motivacionais, são apresentados alguns exercícios ilustrando conceitos de processos, arquivos e permissionamento.<br />
<br />
<ol><br />
<li><br />
Comando para ver todos os processos no linux:<br />
<code><br />
$ ps aux<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Colocar 2 processos se executando no contexto de um terminal e verificar número dos processos e então "destruí-los":<br />
<code><br />
$ yes > /dev/null<br />
$ yes > /dev/null<br />
$ ps <br />
$ kill -9 <pid_yes><br />
$ kill -9 <pid_yes><br />
</syntaxhighlight><br />
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.<br />
</li><br />
<li><br />
Criar um terminal adicional<br />
<code><br />
$ xterm<br />
</syntaxhighlight><br />
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:<br />
<code><br />
$ echo Alo Terminal > /dev/pts/2<br />
$ kill -9 <pid_terminal><br />
</syntaxhighlight><br />
</li><br />
<li><br />
Comunicação entre processos:<br />
<code><br />
$ cat /etc/passwd | grep home | wc -l<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Retirando a permissão de leitura de um arquivo em nível de usuário proprietário:<br />
<code><br />
$ echo Alo Mundo > alfa.txt<br />
$ ls -l alfa.txt<br />
$ cat alfa.txt<br />
$ chmod u-r alfa.txt<br />
$ cat alfa.txt<br />
$ chmod u+r alfa.txt<br />
$ cat alfa.txt <br />
</syntaxhighlight><br />
</li><br />
</ol><br />
<br />
=AULA 2 - Dia 2/08/2019=<br />
<br />
===Objetivos/Conteúdos===<br />
<br />
*Continuação da Aula<br />
*Estruturas do Sistema Operacional (cap.2)<br />
**Serviços do Sistema Operacional (2.1)<br />
**Interfaces com Usuários (2.2)<br />
**Chamadas do Sistema (2.3)<br />
**Tipos de Chamadas de Sistema (2.4) ver Fig.2.8<br />
***Chamadas de Controle de Processos<br />
**Arquiteturas e Estruturas de Sistemas Operacionais (2.7)<br />
**Máquinas Virtuais (2.8)<br />
<br />
===Material de Referência===<br />
<br />
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte1.pdf Apresentação sobre histórico visão geral<br />
* [http://www.fil.univ-lille1.fr/~sedoglav/OS/TP.html ]<br />
<br />
===Leitura Recomendada===<br />
<br />
*Cap.2 do Silberschatz principalmente:<br />
**2.1 a 2.8<br />
<br />
===Exercícios===<br />
<br />
=AULA 3 - Dia 7/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*Continuação da aula anterior<br />
**Chamadas do Sistema (2.3)<br />
**Tipos de Chamadas de Sistema (2.4) ver Fig.2.8<br />
***Chamadas de Controle de Processos<br />
**Arquiteturas e Estruturas de Sistemas Operacionais (2.7)<br />
**Máquinas Virtuais (2.8)<br />
<br />
===Exercícios===<br />
<br />
<ol><br />
<li> Estudar e executar o código em http://cs.lmu.edu/~ray/notes/gasexamples/ <br />
Detalhes das chamadas na arquitetura x86_64 ver em https://lwn.net/Articles/604287/ <br />
<li>Estudar (usar o man) e executar o código usando a função (em conformidade com a API POSIX) write() para o ''hello world'':<br />
<code><br />
#include <unistd.h> <br />
<br />
main()<br />
{<br />
write(1,"Alo Mundo\n",10);<br />
}<br />
</syntaxhighlight><br />
</li><br />
<li> Use o comando strace para verificar todas as chamadas de sistema dos programas acima.<br />
</li><br />
<li><br />
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() 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:<br />
<code><br />
void meu_hello();<br />
<br />
int main()<br />
{<br />
meu_hello();<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
</li><br />
Gere o assembly do código em C e discuta a diferença entre uma chamada de função e uma chamada de sistema.<br />
<li><br />
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:<br />
<code><br />
#include <string.h><br />
main()<br />
{<br />
char *p="Tudo bem com vocês?";<br />
meu_hello_world(p, strlen(p));<br />
}<br />
</syntaxhighlight><br />
Solução:<br />
{{collapse top|Solução}}<br />
<code><br />
modificado de http://cs.lmu.edu/~ray/notes/gasexamples/<br />
.global meu_hello_world<br />
<br />
.text<br />
meu_hello_world:<br />
<br />
push %rdi # salva primeiro parâmetro<br />
push %rsi # salva segundo parâmetro<br />
mov $1, %rax # system call 1 é write<br />
mov $1, %rdi # file handle 1 é stdout<br />
mov $message, %rsi # endereço da string<br />
mov $13, %rdx # número de bytes da string<br />
syscall # chamada ao sistema<br />
<br />
pop %rdx # o que havia sido passado em rsi (número de bytes) é colocado em rdx<br />
pop %rsi # o que havia sido colocado em rdi (endereço da string) é colocado em rsi<br />
mov $1, %rax # system call 1 is write<br />
mov $1, %rdi # file handle 1 é stdout<br />
syscall # nova chamada ao sistema<br />
<br />
ret<br />
<br />
message:<br />
.ascii "Hello, World\n"<br />
</syntaxhighlight><br />
</li><br />
</ol><br />
{{collapse bottom}}<br />
<br />
=AULA 4 - Dia 9/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*PARTE 2A: Gerenciamento de Processos (cap.3)<br />
*3.1.Conceito de Processo<br />
*3.2.Escalonamento de Processos<br />
*3.3.Operações sobre Processos (Laboratório Operações sobre Processos no Linux: Fork/Exec/Wait)<br />
<br />
===Material de Referência===<br />
<br />
*Slides do Cap.3 - Silberschatz<br />
*Laboratório Fork/Exec/Wait<br />
<br />
=== Exercícios de Demonstração===<br />
<br />
#Executar em um terminal o comando top. Em um outro terminal executar:<br />
yes > /dev/null &<br />
yes > /dev/null &<br />
#Parar um dos processos yes<br />
kill -STOP <pid_yes><br />
#Continuar o processo<br />
kill -CONT <pid_yes><br />
#Destruir todos<br />
killall yes<br />
<br />
=AULA 5 - Dia 14/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*Ainda Processos<br />
*Cap.3.2..Escalonamento de Processos<br />
*Cap.2.3.Operaçṍes sobre processos<br />
*Finalização do Laboratório Fork/Exec/Wait<br />
<br />
===Adendo===<br />
<br />
*Estudar e comentar [https://www.geeksforgeeks.org/wait-system-call-c/]<br />
<br />
=AULA 6 - Dia 16/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*Comunicação Interprocessos (3.4 e 3.5)<br />
*Laboratório de Memória Compartilhada<br />
<br />
=AULA 7 - Dia 21/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Comunicação Interprocessos: Troca de Mensagens (3.6)<br />
*Laboratório de Pipes<br />
<br />
=AULA 8 - Dia 23/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Finalização Lab. pipes nomeados.<br />
*Threads ((cap.4.1, 4.2)<br />
*Lab.Threads de Aplicação<br />
<br />
=AULA 9 - Dia 28/08/2019=<br />
<br />
*Laboratório: Ainda Threads - Um escalonador semi-automático<br />
<br />
<br />
=AULA 10 - Dia 30/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Repassar um primeiro estudo sobre o RTOS<br />
*Revisar Processos e Threads<br />
<br />
==Questionário - Processos==<br />
<br />
#Conceitue processo. Descreva e explique cada uma das seções de um processo na memória.<br />
#Faça um diagrama e explique os possíveis estados de um processo no sistema. O que produz a transição entre estados?<br />
#O que é um Bloco de Controle de Processo? Quais informações ficam armazenadas neste bloco?<br />
#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.<br />
#Explique o que é multiprogramação e escalonamento de processos.<br />
#O que é a fila de processos prontos?<br />
#Diferencie um processo limitado por IO de um processo limitado por CPU.<br />
#Diferencie escalonamento de longo prazo de escalonamento de curto prazo.<br />
#Discuta o papel da interrupção na troca de contexto entre processos.<br />
#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?<br />
#Explique como funciona a chamada exec no UNIX/Linux<br />
#Explique como funciona a chamada wait no UNIX/Linux e como é possível retornar valores de um filho para o pai.<br />
#Faça um esqueleto de um programa UNIX/Linux que ao se tornar processo cria 3 filhos e espera pela execução dos mesmos.<br />
<br />
==Questionário - Comunicação entre Processos==<br />
<br />
#Diferenciar processos independentes de processos cooperantes.<br />
#Enumere e explique quatro razões para cooperação entre processos.<br />
#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.<br />
#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.<br />
#A memória compartilhada requer chamada ao sistema na sua operação? Discuta.<br />
#Por que o processo de troca de mensagem deve ser mais lento que a memória compartilhada?<br />
#Apresente em pseudocódigo uma proposta de funcionamento do problema do produtor consumidor usando memória compartilhada.<br />
#A construção de uma solução para o problema produtor consumidor pode ser facilitado pelo uso da memória compartilhada? Discuta.<br />
#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?<br />
#Enumere três métodos de implementação de uma lógica de ligação (link) entre processos.<br />
#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.<br />
#Descreva a variante assimétrica da troca direta de mensagens. O que muda em termos de primitiva de comunicação?<br />
#Descreva o problema de hard-coding associado a nomeação direta e como pode ser contornado através da nomeação/comunicação indireta?<br />
#O que é uma caixa postal? Como o Posix identifica uma caixa postal no caso de fila de mensagens?<br />
#Dois processos podem usar mais do que uma caixa postal para se comunicar? Qual a condição para que isto ocorra?<br />
#Descreva as duas operações básicas para a troca de mensagens com Caixa Postal.<br />
#Descreva na comunicação indireta via Caixa Postal as 3 propriedades básicas.<br />
#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.<br />
#De que forma a caixa postal estando no espaço de endereçamento de um processo (propriedade) afeta a recepção por mensagens? Descreva.<br />
#Quais as operações sobre uma caixa postal criada no espaço do sistema operacional deverão ser disponíveis? Descreva.<br />
#A transmissão de mensagem pode ser com e sem bloqueio. Descreva as 4 possibilidades (síncrona/assíncrona).<br />
#Discuta as 3 possibilidades de armazenamento de mensagens em buffer. Em que condições um remetente pode ser bloqueado?<br />
<br />
==ETAPA 1 - Projeto Final==<br />
<br />
*Apresentação (slides) sobre a parte de gerenciamento de tarefas no RTOS;<br />
*apresentação dia 18/09/2019<br />
<br />
==Referências==<br />
<br />
*[https://www.freertos.org/RTOS.html Site do FreeRTOS] ver Mastering the FreeRTOS Real Time Kernel - a Hands On Tutorial Guide <br />
*[https://www.embarcados.com.br/rtos-sistema-operacional-de-tempo-real/]<br />
*[https://github.com/feilipu/avrfreertos]<br />
<br />
=AULA 11 - Dia 4/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Pico de CPU X Pico de IO <br />
*Preempção X Não Preempção<br />
*Escalonamento de Processos: Escalonamento FCFS<br />
<br />
<br />
=AULA 12 - Dia 6/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Escalonamento de Processos: <br />
**Shortest Job First (preemptivo e não preemptivo)<br />
**Prioridade (preemptivo e não preemptivo)<br />
**Round-Robin: Preemptivo<br />
*Lab.Round Robin<br />
<br />
==Material de Referência==<br />
<br />
http://docente.ifsc.edu.br/andre.damato/sop2018/SOP2018-parte2.pdf<br />
<br />
<br />
=AULA 13 - Dia 13/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Sincronização entre Processos<br />
*Laboratório do Esquema de Peterson<br />
<br />
==Material de Referência==<br />
<br />
*Livro Silberchatz<br />
*https://www.os-book.com/OSE1/slide-dir/PPT-dir/ch6.ppt<br />
<br />
=AULA 14 - Dia 18/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Sincronização entre Processos<br />
*Lock de Hardware<br />
*Laboratório do TSL<br />
<br />
==Laboratório Proposto==<br />
<br />
*Refazer o problema proposto usando uma instrução simualada de test and set. Prever um liite superior para entrada de um processo na região crítica.<br />
<br />
==Material de Referência==<br />
<br />
*Livro Silberchatz<br />
*https://www.os-book.com/OSE1/slide-dir/PPT-dir/ch6.ppt<br />
<br />
<br />
=AULA 15 - Dia 20/08/2019=<br />
<br />
==O ATmega238 usado no Arduino UNO==<br />
<br />
Ver [https://pt.wikipedia.org/wiki/ATmega328]<br />
<br />
==O Arduino UNO==<br />
<br />
Ver [https://pt.wikipedia.org/wiki/Arduino]<br />
Ver [https://github.com/feilipu/Arduino_FreeRTOS_Library]<br />
<br />
==O FreeRtos para o Arduino==<br />
<br />
Ver [https://github.com/feilipu/Arduino_FreeRTOS_Library]<br />
<br />
Para instalar no IDE:<br />
*Baixar o ZIP do link acima<br />
*No IDE importar a biblioteca:<br />
**sketch->IncluirBiblioteca->Adicionar do arquivo ZIP<br />
<br />
<br />
==Código Experimental==<br />
<br />
Este código demonstra a ocorrência de "race condition".<br />
<br />
<syntaxhighlight lang=c><br />
// Code based on Examples of Arduino and examples <br />
// from https://github.com/feilipu/Arduino_FreeRTOS_Library<br />
<br />
#include <Arduino_FreeRTOS.h><br />
#include <FreeRTOSVariant.h><br />
#include <task.h><br />
#include <semphr.h><br />
<br />
#define TAM_BUFF 10<br />
<br />
volatile unsigned long race_flag=0xFFEEDDCC;<br />
volatile unsigned long int cont;<br />
int task_cont=0;<br />
<br />
void PrintSerial( void *pvParameters ); // Task para imprimir valor de race_flag<br />
void TaskBlink( void *pvParameters );<br />
void TaskSetarace_flag(void *pvParameters); //Task que atribui race_flag=0xFFEEDDCC<br />
void TaskZerarace_flag(void *pvParameters); //Task que atribui race_flag=0xAA0000AA<br />
<br />
// função de setup<br />
<br />
void setup() {<br />
<br />
Serial.begin(9600);<br />
<br />
while (!Serial) {<br />
; // wait for serial port to connect. Needed for native USB, on LEONARDO, MICRO, YUN, and other 32u4 based boards.<br />
}<br />
<br />
<br />
// criar as 2 tarefas<br />
<br />
xTaskCreate(<br />
TaskBlink<br />
, (const portCHAR *)"Blink" // A name just for humans<br />
, 128 // This stack size can be checked & adjusted by reading the Stack Highwater<br />
, NULL<br />
, 1 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.<br />
, NULL );<br />
<br />
xTaskCreate(<br />
TaskPrintSerial<br />
, (const portCHAR *) "PrintSerial"<br />
, 128 // Stack size<br />
, NULL<br />
, 1 // Priority<br />
, NULL );<br />
<br />
xTaskCreate(<br />
TaskSetarace_flag<br />
, (const portCHAR *) "Setarace_flag"<br />
, 128 // Stack size<br />
, NULL<br />
, 1 // Priority<br />
, NULL );<br />
<br />
xTaskCreate(<br />
TaskZerarace_flag<br />
, (const portCHAR *) "Zerarace_flag"<br />
, 128 // Stack size<br />
, NULL<br />
, 1 // Priority<br />
, NULL );<br />
<br />
cont = race_flag;<br />
<br />
// escalonador toma conta a partir daqui<br />
<br />
}<br />
<br />
void loop()<br />
{<br />
// nada a fazer aqui<br />
}<br />
<br />
/*--------------------------------------------------*/<br />
/*---------------------- Tasks ---------------------*/<br />
/*--------------------------------------------------*/<br />
<br />
void TaskBlink(void *pvParameters) // This is a task.<br />
{<br />
(void) pvParameters;<br />
<br />
/*<br />
Blink<br />
Turns on an LED on for one second, then off for one second, repeatedly.<br />
<br />
Most Arduinos have an on-board LED you can control. On the UNO, LEONARDO, MEGA, and ZERO <br />
it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN takes care <br />
of use the correct LED pin whatever is the board used.<br />
<br />
The MICRO does not have a LED_BUILTIN available. For the MICRO board please substitute<br />
the LED_BUILTIN definition with either LED_BUILTIN_RX or LED_BUILTIN_TX.<br />
e.g. pinMode(LED_BUILTIN_RX, OUTPUT); etc.<br />
<br />
If you want to know what pin the on-board LED is connected to on your Arduino model, check<br />
the Technical Specs of your board at https://www.arduino.cc/en/Main/Products<br />
<br />
This example code is in the public domain.<br />
<br />
modified 8 May 2014<br />
by Scott Fitzgerald<br />
<br />
modified 2 Sep 2016<br />
by Arturo Guadalupi<br />
*/<br />
<br />
// initialize digital LED_BUILTIN on pin 13 as an output.<br />
pinMode(LED_BUILTIN, OUTPUT);<br />
<br />
for (;;) // A Task shall never return or exit.<br />
{<br />
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)<br />
vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second<br />
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW<br />
vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second<br />
}<br />
}<br />
<br />
<br />
<br />
<br />
void TaskPrintSerial(void *pvParameters) // Task que imprime na serial - must be improved...<br />
{<br />
(void) pvParameters;<br />
/*<br />
<br />
*/<br />
<br />
<br />
for (;;)<br />
{ <br />
while (cont==0xAA0000AA || cont==0xFFEEDDCC)<br />
cont = race_flag;<br />
;<br />
<br />
Serial.println("Problemas: valor race_flag é");<br />
Serial.println(cont, HEX);<br />
<br />
vTaskDelay(5); // one tick delay (15ms) in between reads for stability - b<br />
cont = race_flag;<br />
}<br />
}<br />
<br />
void TaskSetarace_flag(void *pvParameters) <br />
{<br />
(void) pvParameters;<br />
const TickType_t xMaxBlockTimeTicks = 0x20;<br />
/*<br />
<br />
*/<br />
<br />
race_flag=0xAA0000AA;<br />
for (;;)<br />
{<br />
race_flag=0xAA0000AA;<br />
//Serial.println("Produtor");<br />
vTaskDelay( ( rand() %xMaxBlockTimeTicks) ); <br />
} <br />
<br />
}<br />
<br />
void TaskZerarace_flag(void *pvParameters) <br />
{<br />
(void) pvParameters;<br />
const TickType_t xMaxBlockTimeTicks = 0x20;<br />
/*<br />
<br />
*/<br />
race_flag=0xFFEEDDCC;<br />
<br />
for (;;)<br />
{<br />
race_flag=0xFFEEDDCC;<br />
vTaskDelay( ( rand() %xMaxBlockTimeTicks) ); <br />
if(task_cont++==100) {<br />
delay(1);<br />
Serial.println("Fim TaskZera - valor race_flag ");<br />
Serial.println(race_flag, HEX);<br />
for(;;);<br />
} <br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=AULA 16 - Dia 25/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Preparação de exemplos de RTOS sobre Arduíno para apresentação na sexta;<br />
<br />
=Laboratórios Propostos= <br />
<br />
Considere o código abaixo. Observe que a região de dados compartilhada shared_data é zerada pelo pai e setada pelo processo filho. O pai detecta inconsistências nos dados que operou. Tente corrigir usando o esquema de Peterson para acesso a região crítica. Crie uma função de entrada e de saída da região crítica.<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
<br />
<br />
#define BUFFER_SIZE 4096<br />
char *shared_data;<br />
char reference_data[BUFFER_SIZE];<br />
<br />
main()<br />
{ <br />
key_t key;<br />
int shmid;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, BUFFER_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
shared_data = shmat(shmid, (void *)0, 0);<br />
<br />
if (shared_data == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int count=0; <br />
memset(reference_data,0,BUFFER_SIZE); <br />
for(;;){ <br />
memset(shared_data,0,BUFFER_SIZE);<br />
if (memcmp(shared_data, reference_data, BUFFER_SIZE)!=0) {<br />
count++;<br />
if (count%1000000==0)<br />
printf("Processo pai detectou algo errado nos dados %d\n", count); <br />
} <br />
} <br />
<br />
<br />
}<br />
else { /*Child code */<br />
<br />
for(;;){ <br />
memset(shared_data,1,BUFFER_SIZE); <br />
}<br />
<br />
}<br />
<br />
if (shmdt(shared_data) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
Possível solução:<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
#include <unistd.h><br />
<br />
#define BUFFER_SIZE 4096<br />
#define ID_PAI 0<br />
#define ID_FILHO 1<br />
#define FALSE 0<br />
#define TRUE 1<br />
<br />
char *shared_data;<br />
char reference_data[BUFFER_SIZE];<br />
<br />
struct tipo_peterson{<br />
char flag[2];<br />
char turn;<br />
} *pet_struct;<br />
<br />
void ent_sec_crit(int id)<br />
{<br />
char id_outro = (id+1)%2;<br />
<br />
pet_struct->flag[id] = TRUE; // indica que o processo deseja entrar na região crítica<br />
pet_struct->turn = id_outro; // o processo sinaliza para o outrao entrar, <br />
// caso o outro esteja entrando<br />
// este ponto é uma race condition: turn pode ser 0 ou 1 <br />
while ( (pet_struct->flag[id_outro]==TRUE) && (pet_struct->turn == id_outro) )<br />
;<br />
}<br />
<br />
void sai_sec_crit(int id)<br />
{<br />
pet_struct->flag[id] = FALSE;<br />
}<br />
<br />
int main()<br />
{ <br />
key_t key;<br />
int shmid;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, BUFFER_SIZE+sizeof(struct tipo_peterson), S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
shared_data = shmat(shmid, (void *)0, 0);<br />
pet_struct = (struct tipo_peterson *) (shared_data + BUFFER_SIZE); <br />
<br />
if (shared_data == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int count=0; <br />
memset(reference_data,0,BUFFER_SIZE); <br />
for(;;){ <br />
ent_sec_crit(ID_PAI);<br />
memset(shared_data,0,BUFFER_SIZE);<br />
if (memcmp(shared_data, reference_data, BUFFER_SIZE)!=0) {<br />
count++;<br />
if (count%1000000==0)<br />
printf("Processo pai detectou algo errado nos dados %d\n", count); <br />
} <br />
sai_sec_crit(ID_PAI);<br />
} <br />
<br />
<br />
}<br />
else { /*Child code */<br />
<br />
for(;;){<br />
ent_sec_crit(ID_FILHO); <br />
memset(shared_data,1,BUFFER_SIZE);<br />
sai_sec_crit(ID_FILHO); <br />
}<br />
<br />
}<br />
<br />
if (shmdt(shared_data) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
=AULA 17 - Dia 27/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Apresentação dos Trabalhos<br />
*Definição da próxima etapa<br />
<br />
=AULA 18 - Dia 02/10/2019=<br />
<br />
==Objetivos==<br />
<br />
*Semáforos, Deadlock e o Problema da Inversão de Prioridade<br />
*Laboratório de Pthreads e Mutex;<br />
<br />
==Laboratório Proposto==<br />
<br />
*Lab. Programação concorrente - Parte 1<br />
<br />
==Materia de Referência==<br />
<br />
*[https://www.os-book.com/OSE1/slide-dir/PDF-dir/ch6.pdf]<br />
<br />
==Desafio==<br />
<br />
Usar <br />
ps -T aux | grep ex1vA<br />
<br />
Para ver os threads dormindo...<br />
<br />
Otimizar o programa abaixo<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <pthread.h><br />
#include <stdlib.h><br />
#include <unistd.h><br />
#include <time.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
pthread_mutex_t mut;<br />
<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
<br />
<br />
long long i;<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
usleep(5000000);<br />
printf("Novo saldo = %d\n",novo_saldo);<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d\n", (i+1));<br />
exit(-1);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
printf("Saldo final é %d\n", saldo);<br />
}<br />
</syntaxhighlight><br />
<br />
=AULA 19 - Dia 04/10/2019=<br />
<br />
==Objetivos==<br />
<br />
*Ainda Semáforos, Deadlock e o Problema da Inversão de Prioridade<br />
*Laboratório de Pthreads com semáforo binário;<br />
*Laboratório de Pthreads com semáforos contador como solução do problema do produtor e consumidor.<br />
<br />
<br />
==Material de Referência==<br />
<br />
*ver laboraratório de Programação concorrente<br />
<br />
==Laboratório Proposto==<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Programação concorrente}}<br />
<br />
== Programação concorrente ==<br />
<br />
<br />
===PARTE 1 - Mutex e Biblioteca libpthreads===<br />
<br />
;POSIX Threads<br />
A 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):<br />
*''pthread_create'': cria uma thread;<br />
*''pthread_kill'': força a terminação de uma thread;<br />
*''pthread_join'': sincroniza o final de uma thread (qual a diferença/semelhança com o ''wait'' que usamos para processos?);<br />
*''pthread_exit'': finaliza uma thread.<br />
Para utilizar estas funções é necessário linkar o programa à libpthread (''-lpthread''). <br />
<br />
<br />
;POSIX pthread mutex<br />
<br />
A biblioteca pthread implementa um tipo ''pthread_mutex_t'', que garante a exclusão mútua entre threads. Estes mutex são manipulados através das funções (acesse as man-pages das chamadas para maiores detalhes):<br />
*''pthread_mutex_lock'': acessa um mutex.<br />
*''pthread_mutex_trylock'': tenta acessar um mutex (retorna valor indicando sucesso ou falha no lock).<br />
*''pthread_mutex_unlock'': libera um mutex.<br />
<br />
<br />
<br />
;Exercício 1<br />
<br />
O programa abaixo cria 5 threads, e cada uma destas threads atualiza uma variável global (memória compartilhada).<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
#include <pthread.h><br />
#include <stdlib.h><br />
#include <unistd.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
pthread_mutex_t mut;<br />
<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
long long i;<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
sleep(1);<br />
printf("Novo saldo = %d\n",novo_saldo);<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d\n", (i+1));<br />
exit(-1);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
printf("Saldo final é %d\n", saldo);<br />
}<br />
</syntaxhighlight><br />
<br />
# Compile este programa. <br />
# Execute este programa várias vezes. Ele funciona? Será que ele gera as saídas esperadas?<br />
# Identifique as '''seções críticas''' do programa.<br />
# Corrija o programa utilizando '''mutex'''. <br />
# Analise a função ''AtualizaSaldo()'' com a sua solução. Lembre-se que o uso do mutex implica em apenas uma thread acessar a seção crítica por vez, enquanto outras threads ficam bloqueadas, esperando. Disso vem que, quanto menor o trecho de código entre um ''lock'' e um ''unlock'', menos tempo uma thread necessita ficar esperando.<br />
<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <cstring><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
<br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
sem_t sem;<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
int value;<br />
sem_wait(&sem);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
sem_getvalue(&sem, &value);<br />
printf("valor sem = %d\n", value);<br />
sem_post(&sem);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
sem_init(&sem,0,1);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
sem_destroy(&sem);<br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
===PARTE 2 - POSIX Semaphores Binários===<br />
<br />
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):<br />
*''sem_init'': inicializa um semáforo;<br />
*''sem_destroy'': destroy um semáforo;<br />
*''sem_wait'': implementa a operação ''p'';<br />
*''sem_post'': implementa a operação ''v''.<br />
Para utilizar estas funções é necessário linkar o programa à librt ou à libpthread (''-lrt'' ou ''-lpthread'').<br />
<br />
;Exercício 1<br />
Modifique o programa para usar um semáforo binário ao invés de um mutex em sua solução.<br />
<br />
;Exercício 2 - Fazer em casa<br />
Refaça o exercício 3 usando processos criados com fork e exec. O semáforo deve ser criado em uma região de memória compartilhada.<br />
<br />
===PARTE 3 - POSIX Semaphores===<br />
<br />
;Exercício 3<br />
Implemente com pthreads e semáforos/mutex a solução do produtor/comsumidor conforme sugerido no livro do Silberchatz. USe dois semáforos: (i) um para controlar o numero de itens vazios no buffer (semáforo empty - quando zero o thread produtor deve parar de produzir). (ii) um semáforo para controlar o numero de itens ocupados no buffer (semáforo full - quando zero o consumidor deve parar de consumir).<br />
<br />
===PARTE 4 - POSIX Semaphores===<br />
<br />
;Exercício 4<br />
<br />
O programa abaixo manipula uma matriz de tamanho MxN (veja os defines para o tamanho da matriz). A função ''SumValues'' soma todos os valores em uma linha da matriz. A linha a ser somada é identificada pela variável ''i''. Modifique o programa principal (''main'') nos locais indicados para:<br />
# Criar N threads, uma para somar os valores de cada linha.<br />
# Receber o resultado do somatório de cada linha e gerar o somatório total da matriz.<br />
# Analise o programa: há problemas de sincronização que precisam ser resolvidos? Se sim, resolva-os.<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include "thread.h"<br />
<br />
/* number of matrix columns and rows */<br />
#define M 5<br />
#define N 10<br />
<br />
using namespace std;<br />
<br />
int matrix[N][M];<br />
Thread *threads[N];<br />
<br />
<br />
/* thread function; it sums the values of the matrix in the row */<br />
int SumValues(int i)<br />
{<br />
int n = i; /* number of row */<br />
int total = 0; /* the total of the values in the row */<br />
int j;<br />
for (j = 0; j < M; j++) /* sum values in the "n" row */<br />
total += matrix[n][j];<br />
cout << "The total in row" << n << " is " << total << "." << endl;<br />
/* terminate a thread and return a total in the row */<br />
exit(total);<br />
}<br />
<br />
int main(int argc, char *argv[])<br />
{<br />
int i, j;<br />
int total = 0; /* the total of the values in the matrix */<br />
<br />
/* initialize the matrix */<br />
for (i = 0; i < N; i++)<br />
for (j = 0; j < M; j++)<br />
matrix[i][j] = i * M + j;<br />
<br />
/* create threads */<br />
/* COLOQUE SEU CÓDIGO PARA CRIAR AS THREADS AQUI! */<br />
<br />
/* wait for terminate a threads */<br />
/* COLOQUE SEU CÓDIGO PARA PEGAR O SOMATÓRIO DE LINHAS E TOTALIZAR A SOMA DA MATRIZ AQUI! */<br />
<br />
cout << "The total values in the matrix is " << total << endl;<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
{{collapse bottom}}<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Escalonamento Round Robin e FCFS para Threads"}}<br />
<br />
== Escalonamento Round-Robin ==<br />
<br />
OBS: ver https://www.quora.com/What-exactly-does-typedef-do-in-C<br />
<br />
O Exemplo abaixo mostra a implementação de um esquema de escalonamento Round Robin do exercício anterior.<br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
Modificado por Eraldo <br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 5<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
void runA(void) {<br />
for (;;) {<br />
printf("running A\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runB(void) {<br />
for (;;) {<br />
printf("running B\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 1<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
<br />
void scheduler_rr();<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void yield_thread()<br />
{<br />
scheduler_rr();<br />
}<br />
<br />
void delete_thread()<br />
{<br />
delete curr_thread;<br />
curr_thread=NULL;<br />
scheduler_rr();<br />
}<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
struct delta{<br />
long alfa;<br />
char epson[1000];<br />
long beta;<br />
} shar;<br />
<br />
int turn;<br />
int flag[2];<br />
<br />
#define TRUE 1<br />
#define FALSE 0<br />
<br />
void ent_rc(int p, int vt)<br />
{<br />
flag[p]=TRUE;<br />
turn = vt;<br />
if(p) p=0; else p=1;<br />
while (flag[p] && turn == vt);<br />
//printf("Thread %d: esperando para acessar a região crítica\n", p);<br />
}<br />
<br />
void sai_rc(int p)<br />
{<br />
flag[p]=FALSE;<br />
}<br />
<br />
void runA(void) {<br />
struct delta x = {0, 100};<br />
<br />
for (;;) {<br />
x.alfa=0;x.beta=0;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0);<br />
x.alfa=100;x.beta=100;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0); <br />
}<br />
}<br />
<br />
void runB(void) {<br />
<br />
for (;;) {<br />
ent_rc(1,0);<br />
printf("shar alfa = %ld shar beta = %ld \n",shar.alfa, shar.beta); // regiao crítica<br />
sai_rc(1);<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runC(void) {<br />
int i;<br />
for (i=0;i<10;i++) {<br />
printf("Thread C - parte 1\n");<br />
yield_thread();<br />
printf("Thread C - parte 2\n");<br />
yield_thread();<br />
}<br />
delete_thread();<br />
}<br />
<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
add_thread(runC);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
{{collapse bottom}}<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Um escalonador semi-automático"}}<br />
<br />
== Ainda Threads - Um escalonador semi-automático usando sinais ==<br />
<br />
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.<br />
<br />
===Exemplo 1:===<br />
<br />
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. <br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
<br />
void sig_handler(int signo)<br />
{<br />
int x;<br />
printf("Turma de SOP: recebido SIGUSR1\n");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
// Loop eterno dormindo 1s<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Fazer no terminal:<br />
ps aux<br />
anotar o pid do processo e enviar o sinal:<br />
kill -USR1 pid<br />
<br />
===Exemplo 2:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// loop eterno que nunca é executado<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Enviar o sinal USR1 para ver o efeito. <br />
<br />
===Exemplo 3:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void prepara_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void prepara_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
prepara_contexto_ping();<br />
prepara_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// A long long wait so that we can easily issue a signal to this process<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Exercício: Use o comando htop para verificar como estes threads são vistos pelo SOP.<br />
<br />
Exercício: Tente analisar as pilhas dos threads e verificar sob qual pilha o handler se executa.<br />
<br />
<br />
===Exercício 4:===<br />
<br />
Neste ponto associamos um timer ao handler com o apoio do sinal ALRM. Agora os threads são escalonados automaticamente.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
===Exercício Proposto 5===<br />
<br />
Colocar 3 threads rodando.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void preparar_contexto_ping(ucontext_t *pContext, char *p)<br />
{<br />
char *stack;<br />
<br />
getcontext(pContext);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
(*pContext).uc_stack.ss_sp = stack ;<br />
(*pContext).uc_stack.ss_size = STACKSIZE;<br />
(*pContext).uc_stack.ss_flags = 0;<br />
(*pContext).uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(pContext, (void*)(*f_ping), 1, p);<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping(&cPing, "ping");<br />
preparar_contexto_ping(&cPong, "pong");<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Threads de aplicação}}<br />
<br />
== Threads de aplicação ==<br />
<br />
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:<br />
*'''getcontext(&a)''': salva o contexto na variável '''a''';<br />
*'''setcontext(&a)''': restaura um contexto salvo anteriormente na variável '''a''';<br />
*'''swapcontext(&a,&b)''': salva o contexto atual na variável '''a''' e restaura o contexto salvo anteriormente na variável '''b''';<br />
*'''makecontext(&a, ...)''': ajusta parâmetros internos do contexto salvo em '''a''';<br />
*'''ucontext_t''': as variáveis '''a''' e '''b''' são do tipo '''ucontext_t'''. Este tipo armazena um contexto.<br />
<br />
Busque mais informações sobre estas funções utilizando o programa manpage do Linux (ex.: man getcontext).<br />
<br />
Estude o código no arquivo pingpong.c abaixo e explique seu funcionamento.<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
*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.<br />
*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.<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain, cFnew;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_new(void * arg1, void * arg2,void * arg3,void * arg4) <br />
{<br />
printf ("%s: Primeira string %s %s %s\n",(char*) arg1,(char*) arg2,(char*) arg3, (char*) arg4);<br />
swapcontext(&cFnew, &cMain); <br />
}<br />
<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
<br />
getcontext(&cFnew);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cFnew.uc_stack.ss_sp = stack ;<br />
cFnew.uc_stack.ss_size = STACKSIZE;<br />
cFnew.uc_stack.ss_flags = 0;<br />
cFnew.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cFnew, (void*)(*f_new), 4, "\tF_new", "\tAlo", "\tMundo","\tReal");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
swapcontext(&cMain, &cFnew);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
--><br />
Exercício 3: O que acontece se um dos threads é colocado para dormir? Todos os demais threads param a sua execução.<br />
<br />
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/<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Processos no Linux}}<br />
<br />
== Processos no Linux - Modificado por Eraldo ==<br />
<br />
<blockquote style="background: lime; border: 1px solid black; padding: 1em;"><br />
Processos no Linux<br />
</blockquote><br />
<br />
*Exercícios propostos pelo Prof.Arliones e Modificados por Eraldo<br />
<br />
<br />
[[imagem:DesenhoForkExec.png|border|650px]]<br />
<br />
<br />
;Syscall FORK<br />
<br />
* Em um terminal, execute "man fork"<br />
** 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'''.<br />
** O '''código''' dos dois processos (pai e filho) são '''idênticos''';<br />
** Os '''dados''' dos dois processos (pai e filho) são '''idênticos NO MOMENTO DA CRIAÇÃO''';<br />
** Execução do processo filho inicia na próxima instrução do programa (no retorno da chamada FORK);<br />
** Não é possível saber qual dos processos (pai ou filho) retormará a execução primeiro - isto fica a cargo do excalonador do SO;<br />
** Valores de retorno da chamada FORK:<br />
*** (-1): erro na criação do processo (ex.: memória insuficiente);<br />
*** (0): em caso de sucesso, este é o valor de retorno recebido pelo processo filho;<br />
*** (>0): em caso de sucesso, este é o valor de retorno recebido pelo processo pai;<br />
<br />
;Syscall JOIN<br />
<br />
* A syscall JOIN é implementada no POSIX pela função '''wait()'''. Execute "man wait".<br />
** Além da função '''wait()''', há também '''waitpid()''' e '''waitid()''';<br />
** 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);<br />
** A chamada wait também libera os recursos do processo filho que termina;<br />
** '''wait()''': esta função suspende a execução do processo chamador até que UM DOS SEUS FILHOS finalize;<br />
** '''waitpid()''': suspende a execução do processo chamador até que UM FILHO ESPECÍFICO finalize;<br />
<br />
;Syscall EXEC<br />
<br />
* A syscall EXEC é implementada no POSIX pela família de funções '''exec()'''. Execute "man exec".<br />
** As principais funções da família são '''execl()''', '''execlp()''' e '''execvp()''';<br />
** 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;<br />
** 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;<br />
<br />
<br />
;Exemplos POSIX utilizando fork/wait/exec<br />
<br />
*Exemplo 1: fork/wait básico<br />
<syntaxhighlight lang=c><br />
// ex1: fork/wait básico<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
printf("processo filho\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
printf("processo pai\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
arliones@socrates:~/tmp$ gcc ex1.c -o ex1 <br />
arliones@socrates:~/tmp$ ./ex1 <br />
processo filho pid: 27858 pid pai: 27857<br />
processo pai pid: 27857 pid pai: 5337<br />
arliones@socrates:~/tmp$ <br />
</syntaxhighlight><br />
<br />
* Exemplo 2: processos pai e filho compartilham código, mas não dados.<br />
<syntaxhighlight lang=c><br />
// ex2: fork/wait "compartilhando" dados<br />
// ex2: fork/wait "compartilhando" dados<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status, k=0;<br />
printf("processo %d\t antes do fork\n", getpid());<br />
pid = fork();<br />
printf("processo %d\t depois do fork\n", getpid());<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
k += 1000;<br />
printf("processo filho\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status); // espera o filho terminar<br />
k += 10;<br />
printf("processo pai\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
k += 1000;<br />
printf("FIM processo %d\t K: %d\n", getpid(), k); <br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
processo 17056 antes do fork<br />
processo 17056 depois do fork<br />
processo 17057 depois do fork<br />
processo filho pid: 17057 K: 1000 endereço K: 0x7ffd8923e318<br />
processo pai pid: 17056 K: 10 endereço K: 0x7ffd8923e318<br />
</syntaxhighlight><br />
<br />
* Modificação no código: comentar linhas 23 e 30<br />
<br />
<syntaxhighlight lang=bash><br />
<br />
</syntaxhighlight><br />
<br />
* Analise os resultados e busque entender a diferença.<br />
*Perguntas e desafios.:<br />
#Analisando os valores impressos de k pode-se dizer que os dados são compartilhados entre os dois processos?<br />
#O endereço de k impresso é o mesmo nos dois processos. ISto não contradiz a afirmação anterior?<br />
#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.<br />
<br />
<br />
;Exercício fork/wait<br />
<br />
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.<br />
<br />
*Use o comando pstree para verificar a árvore de processos criada.<br />
<br />
{{collapse top|Solução}}<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
<!--<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
--><br />
<br />
;DESAFIO: fork/wait<br />
<br />
Reimplementar o exercício anterior de criação de uma árvore de 3 processos, generalizando a criação de N processos onde N é repassado na linha de comando do programa. SUGESTÃO: usar um comando for, mas lembrar que se existe um fork dentro do for, então cada filho gerado dará continuidade a execução do for. É necessário que o processo faça um exit ou retorne neste momento.<br />
<br />
;DESAFIO: Exercício status/wait<br />
<br />
O ''status'' passado como parâmetro à função ''wait(&status)'' é, na verdade, o mecanismo de retorno de resultado do ''wait/waitpid''. Ao retornar, esta variável contém informações sobre o resultado da execução do processo filho. Por exemplo, se um processo terminou normalmente (i.e., chamou ''exit''), o comando ''WIFEXITED(status)'' retorna ''true''. Este comando retorna ''false'' se o processo foi abortado (e.g., ''segmentation fault'') ou morto (e.g., ''kill''). Investigue no manual do wait no Linux (''man wait'') o funcionamento do comando WEXITSTATUS(status). <br />
Imagine um problema de busca de dados armazenados na forma de uma matriz de inteiros 4x30. Você está interessado em saber quantas ocorrências de um determinado número existe em cada linha da matriz. Note que que são tarefas que podem ser paralelizadas e usufruir de um sistema capaz de executá-las em paralelo. Faça uma implementação paralelizando 4 processos filhos a partir de um pai, onde cada processo é responsável por uma busca. A quantidade de ocorrências do número buscado é retornada e capturada através de WEXITSTATUS.<br />
<br />
;Syscall EXEC<br />
<br />
*Exemplo exec()<br />
<br />
<syntaxhighlight lang=c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
execl("/bin/ls","ls","-l", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 1: Modificar o código para mostrar que o exec() não retorna (colocar um printf após o exec).<br />
<br />
*Exercício 2: Criar um exemplo (dois programas ) para demonstrar que o exec não cria novo processo. <br />
**Crie um primeiro programa (prog1) que imprime o seu pid e depois faz um exec do segundo programa.<br />
**Crie o segundo programa que simplesmente imprime o pid.<br />
<br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU ANTES DO EXEC: Meu pid é %d\n", getpid());<br />
execl("./prog2","prog2", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU DEPOIS DO EXEC:Meu pid é %d\n", getpid());<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 3: Criar um exemplo usando fork/exec mostrando que um processo pai cria um filho e espera por sua execução. O filho executa o comando "ps aux". Ambos devem mostrar seus pids.<br />
<br />
{{collapse bottom}} <br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Laboratório Memória Compartilhada entre Pai e Filho - Produtor Consumidor}}<br />
<br />
Baseado no Lab. do Prof.Arliones<br />
<br />
=== Objetivo ===<br />
<br />
*Familiarizar o aluno com o conceito de Memória Compartilhada entre Processos Pai e Filho<br />
*Familizarizar o aluno com o conceito de Produtor Consumidor<br />
<br />
=== Referencial Teórico-Prático ===<br />
<br />
* Silberchatz - 3.4 e 3.5<br />
* man nos comandos shmat e shmget<br />
<br />
=== Exemplo de Funcionamento ===<br />
<br />
No exemplo abaixo um processo pai compartilha uma área de memória com o processo filho. O processo filho escreve uma mensagem para o pai na área de memória compartilhada e termina. O processo pai é desbloqueado no wait e imprime a mensagem escrita.<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
char *ptr_msg = "alo pai, tudo bem?"; <br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
strcpy(segmento, ptr_msg);<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(&filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
=== Desafio a ser Implementado em Sala ===<br />
<br />
Construir um programa em que um processo pai atua como produtor e o processo filho atua como consumidor. O buffer circular compartilhado é um buffer de inteiro de tamanho 5. O pai alimentará o buffer com 50 itens gerados aleatóriamente entre 1 e 100. A cada escrita/leitura no buffer o produtor/consumidor deve esperar alguns milisegundos de forma a acontecer situações de buffer cheio e vazio. <br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
#include <unistd.h><br />
#include <time.h><br />
#include <sys/types.h><br />
#include <sys/wait.h><br />
<br />
<br />
<br />
#define SHM_SIZE 1024 <br />
<br />
#define BUFF_COMP_SIZE 5<br />
<br />
struct buff_comp {<br />
int buffer[BUFF_COMP_SIZE];<br />
int in,out;<br />
};<br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
struct buff_comp *p; <br />
<br />
/* initialize random seed: */<br />
srand ( time(NULL) );<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
p = (struct buff_comp *) shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
p->out = p->in = 0;<br />
<br />
if((filho = fork()) == -1)<br />
{<br />
<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
int i;<br />
for(i=0;i<50;i++) {<br />
while (p->in==p->out) {<br />
printf("FILHO: BUFFER VAZIO !!!!!!!\n");<br />
usleep(rand() % 10000 + 1);<br />
}<br />
printf("FILHO: item lido = %d\n", p->buffer[p->out]);<br />
p->out = (p->out+1)%BUFF_COMP_SIZE;<br />
}<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
int i; <br />
<br />
for(i=0;i<50;i++) {<br />
while (((p->in+1)%BUFF_COMP_SIZE) == p->out) {<br />
printf("PAI: BUFFER CHEIO !!!!!!!\n");<br />
usleep(rand() % 10000 + 1);<br />
}<br />
p->buffer[p->in] = rand() % 100 + 1;<br />
printf("PAI: item produzido = %d\n", p->buffer[p->in]);<br />
p->in = (p->in+1)%BUFF_COMP_SIZE;<br />
<br />
}<br />
wait(&filho); <br />
<br />
}<br />
<br />
<br />
if (shmdt(p) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Trocas de mensagens com pipes}}<br />
<br />
= Trocas de mensagens com pipes =<br />
<br />
;Troca de mensagens<br />
Um mecanismo disponibilizado por sistemas UNIX para troca de mensagens entre processos é o PIPE. Pipes são mecanismos de comunicação indireta onde mensagens são trocadas através de ''mailboxes''. Cada ''mailbox'' possui um identificador único, permitindo que processos identifiquem o canal de comunicação entre eles. O fluxo de mensagens em um Pipe é:<br />
*'''unidirecional''': sobre um mesmo pipe, apenas um processo envia mensagens e um processo recebe mensagens;<br />
*'''FIFO''': as mensagens são entregues na ordem de envio;<br />
*'''não-estruturado''': não há estrutura pré-definida para o formato da mensagem.<br />
No UNIX, pipes são inicializados através da '''SystemCall''' ''pipe'', que possui a seguinte sintaxe:<br />
*''int pipe(int pipefd[2])'': ''pipe'' inicializa um novo pipe no sistema e retorna, no array pipefd, os descritores identificando cada uma das pontas do pipe. A primeira posição do array, i.e. pipefd[0], recebe o descritor que pode ser aberto apenas para leitura, enquanto a segunda posição do array, i.e. pipefd[1], recebe o descritor que pode ser aberto apenas para escrita. A função retorna zero no caso de sucesso, ou -1 se ocorrer erro.<br />
As primitivas send/receive para uso de um pipe no UNIX são implementadas por '''SystemCalls''' read/write, conforme segue:<br />
*''ssize_t read(int fd, void *buf, size_t count)'': “puxa” dados do pipe identificado pelo descritor fd. Os dados recebidos são os apontados pelo ponteiro buf, sendo count a quantidade máxima de bytes a serem recebidos. A função retorna o número de bytes recebidos.<br />
*''ssize_t write(int fd, const void *buf, size_t count)'': “empurra” dados no pipe identificado pelo descritor fd. Os dados transmitidos são os apontados pelo ponteiro buf, sendo count a quantidade de bytes a serem transmitidos. A função retorna o número de bytes transmitidos.<br />
<br />
*Exemplo 1: Transmitindo e recebendo pelo próprio processo<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main()<br />
{<br />
int fd[2];<br />
char *ptr = "Alo eu mesmo";<br />
char *ptr_alvo;<br />
int tamanho_dados, ret;<br />
<br />
tamanho_dados = strlen(ptr)+1;<br />
<br />
if (pipe(fd)==-1){<br />
printf ("erro criação pipe\n");<br />
exit(-1);<br />
}<br />
printf("Transmitido %d bytes\n", tamanho_dados);<br />
write (fd[1], ptr, tamanho_dados);<br />
<br />
ptr_alvo = malloc(tamanho_dados);<br />
<br />
ret=read(fd[0],ptr_alvo,tamanho_dados);<br />
<br />
printf("ret = %d dados => %s\n", ret, ptr_alvo); <br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
*Exemplo 2: Abaixo há um exemplo de programa criando um pipe e compartilhando os descritores entre dois processos (criados via ''fork()'').<br />
<syntaxhighlight lang=c><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
<br />
char *message = "This is a message!!!" ;<br />
<br />
main()<br />
{<br />
char buf[1024] ;<br />
int fd[2];<br />
pipe(fd); /*create pipe*/<br />
if (fork() != 0) { /* I am the parent */<br />
write(fd[1], message, strlen (message) + 1) ;<br />
}<br />
else { /*Child code */<br />
read(fd[0], buf, 1024) ;<br />
printf("Got this from MaMa!!: %s\n", buf) ;<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
*'''Exercício 1: construa um “pipeline”'''. Crie um programa que conecta 4 processos através de 3 pipes. Utilize ''fork()'' para criar vários processos.<br />
<br />
<syntaxhighlight lang=cpp><br />
<br />
//Solução possível<br />
<br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
pipe(fd);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
<br />
</syntaxhighlight><br />
<br />
*'''Exercício 2: Modifique o exercício anterior para que o processo D, através de um novo pipe, mande uma mensagem diretamente para o pai de todos.<br />
<br />
<!--<br />
<code><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
int fd_retorno[2];<br />
<br />
pipe(fd);<br />
pipe(fd_retorno);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size);<br />
read(fd_retorno[0], buf, size);<br />
printf("PAI:%s\n", buf); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
char *ptr_msg_ret="Ok msg de D para o pai";<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
write(fd_retorno[1],ptr_msg_ret,strlen(ptr_msg_ret)+1);<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
*'''Exercício 3: Consultor de Login de Acesso:'''. Estude o link https://www.geeksforgeeks.org/named-pipe-fifo-example-c-program/ e projete um programa cliente servidor da seguinte forma: (i) O servidor possui uma tabela de usuários (userid). O user_id é de tamanho fixo de 7 caracteres. O servidor espera por consultas para verificar se um usuário está na tabela. Se estiver responde com o caracter 'S' senão com 'N'. (ii) O cliente espera por user_id no teclado e consulta o servidor sobre sua existência na tabela. O cliente imprime na tabela a existência ou não do usuário.<br />
<br />
*'''Exercício 4: cópia de arquivo'''. Projete um programa de cópia de arquivos chamado FileCopy usando pipes comuns. Esse programa receberá dois parâmetros: o primeiro é o nome do arquivo a ser copiado e o segundo é o nome do arquivo copiado. Em seguida, o programa criará um pipe comum e gravará nele o conteúdo do arquivo a ser copiado. O processo filho lerá esse arquivo do pipe e o gravará no arquivo de destino. Por exemplo, se chamarmos o programa como descrito a seguir:<br />
:<syntaxhighlight lang=bash><br />
$ FileCopy entrada.txt copia.txt<br />
</syntaxhighlight><br />
:o arquivo ''entrada.txt'' será gravado no pipe. O processo filho lerá o conteúdo desse arquivo e o gravará no arquivo de destino ''copia.txt''. Escreva o programa usando os pipes da API POSIX no Linux.<br />
<br />
<br />
{{collapse bottom}}<br />
<br />
=Laboratórios Disponíveis= <br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Escalonamento Round Robin e FCFS para Threads"}}<br />
<br />
<br />
== Escalonamento Round-Robin preemptivo ==<br />
<br />
OBS: ver https://www.quora.com/What-exactly-does-typedef-do-in-C<br />
<br />
A fazer: <br />
<br />
*primitiva de término de processo (destrutor do objeto); <br />
*primitiva de yield<br />
*isolar o escalonador em uma função;<br />
*isolar o dispatcher em uma função; <br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
Modificado por Eraldo <br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 5<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
void runA(void) {<br />
for (;;) {<br />
printf("running A\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runB(void) {<br />
for (;;) {<br />
printf("running B\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 1<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
<br />
void scheduler_rr();<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void yield_thread()<br />
{<br />
scheduler_rr();<br />
}<br />
<br />
void delete_thread()<br />
{<br />
delete curr_thread;<br />
curr_thread=NULL;<br />
scheduler_rr();<br />
}<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
struct delta{<br />
long alfa;<br />
char epson[1000];<br />
long beta;<br />
} shar;<br />
<br />
int turn;<br />
int flag[2];<br />
<br />
#define TRUE 1<br />
#define FALSE 0<br />
<br />
void ent_rc(int p, int vt)<br />
{<br />
flag[p]=TRUE;<br />
turn = vt;<br />
if(p) p=0; else p=1;<br />
while (flag[p] && turn == vt);<br />
//printf("Thread %d: esperando para acessar a região crítica\n", p);<br />
}<br />
<br />
void sai_rc(int p)<br />
{<br />
flag[p]=FALSE;<br />
}<br />
<br />
void runA(void) {<br />
struct delta x = {0, 100};<br />
<br />
for (;;) {<br />
x.alfa=0;x.beta=0;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0);<br />
x.alfa=100;x.beta=100;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0); <br />
}<br />
}<br />
<br />
void runB(void) {<br />
<br />
for (;;) {<br />
ent_rc(1,0);<br />
printf("shar alfa = %ld shar beta = %ld \n",shar.alfa, shar.beta); // regiao crítica<br />
sai_rc(1);<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runC(void) {<br />
int i;<br />
for (i=0;i<10;i++) {<br />
printf("Thread C - parte 1\n");<br />
yield_thread();<br />
printf("Thread C - parte 2\n");<br />
yield_thread();<br />
}<br />
delete_thread();<br />
}<br />
<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
add_thread(runC);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Um escalonador semi-automático"}}<br />
<br />
== Ainda Threads - Um escalonador semi-automático usando sinais ==<br />
<br />
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.<br />
<br />
===Exemplo 1:===<br />
<br />
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. <br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
<br />
void sig_handler(int signo)<br />
{<br />
int x;<br />
printf("Turma de SOP: recebido SIGUSR1\n");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
// Loop eterno dormindo 1s<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Fazer no terminal:<br />
ps aux<br />
anotar o pid do processo e enviar o sinal:<br />
kill -USR1 pid<br />
<br />
===Exemplo 2:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// loop eterno que nunca é executado<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Enviar o sinal USR1 para ver o efeito. <br />
<br />
===Exemplo 3:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void prepara_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void prepara_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
prepara_contexto_ping();<br />
prepara_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// A long long wait so that we can easily issue a signal to this process<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
Exercício: Tente analisar as pilhas dos threads e verificar sob qual pilha o handler se executa.<br />
<br />
===Exercício 4:===<br />
<br />
Neste ponto associamos um timer ao handler com o apoio do sinal ALRM. Agora os threads são escalonados automaticamente.<br />
<br />
<code><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void preparar_contexto_ping(ucontext_t *pContext, char *p)<br />
{<br />
char *stack;<br />
<br />
getcontext(pContext);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
(*pContext).uc_stack.ss_sp = stack ;<br />
(*pContext).uc_stack.ss_size = STACKSIZE;<br />
(*pContext).uc_stack.ss_flags = 0;<br />
(*pContext).uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(pContext, (void*)(*f_ping), 1, p);<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping(&cPing, "ping");<br />
preparar_contexto_ping(&cPong, "pong");<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Um Exemplo de Uso "API Padrão POSIX"}}<br />
<br />
== Um Exemplo de Uso "API Padrão POSIX" ==<br />
<br />
;Referências<br />
* Referência http://man7.org/linux/man-pages/man2/mmap.2.html<br />
<br />
<br />
Crie uma função soma que receba 2 ponteiros referenciando posições na memória, criadas utilizando nmap(), de maneira que estas posições armazenem números inteiros. A função soma deverá retornar a soma dos números apontados em regiões da memória sem a utilização de nenhuma rotina da biblioteca do C, que não sejam definidas por APIs posix, para criação destas <br />
regiões na memória (malloc, alloc, calloc). Após retornar o resultado da soma os devidos ponteiros deverão ser extintos da memória.<br />
<br />
<br />
*'''Experimento 1:''' Aumente o tamanho da memória alocada até quando for possível.<br />
<br />
Qual o tamanho limite da memória que você conseguiu alocar?<br />
<br />
*'''Experimento 2:''' Mude o escopo para PROT_NONE, após executar e depurar o código explique o que aconteceu.<br />
<br />
Em sua opinião NMAP trata-se de uma syscall ou de uma API? Afinal API e syscall são a mesma coisa? Explique.<br />
<br />
<syntaxhighlight lang=cpp><br />
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);<br />
int munmap(void *addr, size_t length);<br />
<br />
addr = Valor do início do mapeamento.<br />
length = valor do tamanho da região a ser alocada.<br />
prot = especificações de proteção da região alocada (consultar http://man7.org/linux/man-pages/man2/mmap.2.html).<br />
flags = especificação do escopo e do tipo da região criada (exemplo publica ou privada, se é anônima ou não). <br />
</syntaxhighlight><br />
<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
void* meu_malloc(size_t tamanho) {<br />
void* addr = mmap(0, // addr<br />
tamanho, // len<br />
PROT_READ | PROT_WRITE, // prot<br />
MAP_ANON | MAP_PRIVATE, // flags<br />
-1, // filedes<br />
0); // off<br />
*(size_t*)addr = tamanho;<br />
return addr;<br />
}<br />
<br />
int meu_free(void* addr) {<br />
return munmap(addr - sizeof(size_t), (size_t) addr);<br />
}<br />
<br />
<br />
int soma(int *N1, int *N2){<br />
<br />
return (*N1+*N2);<br />
<br />
}<br />
<br />
<br />
int main(int argc, char* argv[]) {<br />
<br />
int* numero1 = meu_malloc(sizeof(int));<br />
int* numero2 = meu_malloc(sizeof(int)); <br />
<br />
<br />
*numero1 = 10;<br />
*numero2 = 20; <br />
<br />
int resultado = soma(numero1, numero2);<br />
<br />
printf("\n\n O resultado da soma é %d \n\n",resultado); <br />
<br />
meu_free(numero1);<br />
meu_free(numero2);<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Processos no Linux}}<br />
<br />
== Processos no Linux - Modificado por Eraldo ==<br />
<br />
<blockquote style="background: lime; border: 1px solid black; padding: 1em;"><br />
Processos no Linux<br />
</blockquote><br />
<br />
*Exercícios propostos pelo Prof.Arliones e Modificados por Eraldo<br />
<br />
<br />
[[imagem:DesenhoForkExec.png|border|650px]]<br />
<br />
<br />
;Syscall FORK<br />
<br />
* Em um terminal, execute "man fork"<br />
** 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'''.<br />
** O '''código''' dos dois processos (pai e filho) são '''idênticos''';<br />
** Os '''dados''' dos dois processos (pai e filho) são '''idênticos NO MOMENTO DA CRIAÇÃO''';<br />
** Execução do processo filho inicia na próxima instrução do programa (no retorno da chamada FORK);<br />
** Não é possível saber qual dos processos (pai ou filho) retormará a execução primeiro - isto fica a cargo do excalonador do SO;<br />
** Valores de retorno da chamada FORK:<br />
*** (-1): erro na criação do processo (ex.: memória insuficiente);<br />
*** (0): em caso de sucesso, este é o valor de retorno recebido pelo processo filho;<br />
*** (>0): em caso de sucesso, este é o valor de retorno recebido pelo processo pai;<br />
<br />
;Syscall JOIN<br />
<br />
* A syscall JOIN é implementada no POSIX pela função '''wait()'''. Execute "man wait".<br />
** Além da função '''wait()''', há também '''waitpid()''' e '''waitid()''';<br />
** 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);<br />
** A chamada wait também libera os recursos do processo filho que termina;<br />
** '''wait()''': esta função suspende a execução do processo chamador até que UM DOS SEUS FILHOS finalize;<br />
** '''waitpid()''': suspende a execução do processo chamador até que UM FILHO ESPECÍFICO finalize;<br />
<br />
;Syscall EXEC<br />
<br />
* A syscall EXEC é implementada no POSIX pela família de funções '''exec()'''. Execute "man exec".<br />
** As principais funções da família são '''execl()''', '''execlp()''' e '''execvp()''';<br />
** 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;<br />
** 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;<br />
<br />
<br />
;Exemplos POSIX utilizando fork/wait/exec<br />
<br />
*Exemplo 1: fork/wait básico<br />
<syntaxhighlight lang=c><br />
// ex1: fork/wait básico<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
printf("processo filho\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
printf("processo pai\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
arliones@socrates:~/tmp$ gcc ex1.c -o ex1 <br />
arliones@socrates:~/tmp$ ./ex1 <br />
processo filho pid: 27858 pid pai: 27857<br />
processo pai pid: 27857 pid pai: 5337<br />
arliones@socrates:~/tmp$ <br />
</syntaxhighlight><br />
<br />
* Exemplo 2: processos pai e filho compartilham código, mas não dados.<br />
<syntaxhighlight lang=c><br />
// ex2: fork/wait "compartilhando" dados<br />
// ex2: fork/wait "compartilhando" dados<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status, k=0;<br />
printf("processo %d\t antes do fork\n", getpid());<br />
pid = fork();<br />
printf("processo %d\t depois do fork\n", getpid());<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
k += 1000;<br />
printf("processo filho\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status); // espera o filho terminar<br />
k += 10;<br />
printf("processo pai\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
k += 1000;<br />
printf("FIM processo %d\t K: %d\n", getpid(), k); <br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
processo 17056 antes do fork<br />
processo 17056 depois do fork<br />
processo 17057 depois do fork<br />
processo filho pid: 17057 K: 1000 endereço K: 0x7ffd8923e318<br />
processo pai pid: 17056 K: 10 endereço K: 0x7ffd8923e318<br />
</syntaxhighlight><br />
<br />
* Modificação no código: comentar linhas 23 e 30<br />
<br />
<syntaxhighlight lang=bash><br />
<br />
</syntaxhighlight><br />
<br />
* Analise os resultados e busque entender a diferença.<br />
*Perguntas e desafios.:<br />
#Analisando os valores impressos de k pode-se dizer que os dados são compartilhados entre os dois processos?<br />
#O endereço de k impresso é o mesmo nos dois processos. ISto não contradiz a afirmação anterior?<br />
#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.<br />
<br />
<br />
;Exercício fork/wait<br />
<br />
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.<br />
<br />
*Use o comando pstree para verificar a árvore de processos criada.<br />
<br />
{{collapse top|Solução}}<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
<!--<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
--><br />
<br />
;DESAFIO: fork/wait<br />
<br />
Reimplementar o exercício anterior de criação de uma árvore de 3 processos, generalizando a criação de N processos onde N é repassado na linha de comando do programa. SUGESTÃO: usar um comando for, mas lembrar que se existe um fork dentro do for, então cada filho gerado dará continuidade a execução do for. É necessário que o processo faça um exit ou retorne neste momento.<br />
<br />
;DESAFIO: Exercício status/wait<br />
<br />
O ''status'' passado como parâmetro à função ''wait(&status)'' é, na verdade, o mecanismo de retorno de resultado do ''wait/waitpid''. Ao retornar, esta variável contém informações sobre o resultado da execução do processo filho. Por exemplo, se um processo terminou normalmente (i.e., chamou ''exit''), o comando ''WIFEXITED(status)'' retorna ''true''. Este comando retorna ''false'' se o processo foi abortado (e.g., ''segmentation fault'') ou morto (e.g., ''kill''). Investigue no manual do wait no Linux (''man wait'') o funcionamento do comando WEXITSTATUS(status). <br />
Imagine um problema de busca de dados armazenados na forma de uma matriz de inteiros 4x30. Você está interessado em saber quantas ocorrências de um determinado número existe em cada linha da matriz. Note que que são tarefas que podem ser paralelizadas e usufruir de um sistema capaz de executá-las em paralelo. Faça uma implementação paralelizando 4 processos filhos a partir de um pai, onde cada processo é responsável por uma busca. A quantidade de ocorrências do número buscado é retornada e capturada através de WEXITSTATUS.<br />
<br />
;Syscall EXEC<br />
<br />
*Exemplo exec()<br />
<br />
<syntaxhighlight lang=c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
execl("/bin/ls","ls","-l", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 1: Modificar o código para mostrar que o exec() não retorna (colocar um printf após o exec).<br />
<br />
*Exercício 2: Criar um exemplo (dois programas ) para demonstrar que o exec não cria novo processo. <br />
**Crie um primeiro programa (prog1) que imprime o seu pid e depois faz um exec do segundo programa.<br />
**Crie o segundo programa que simplesmente imprime o pid.<br />
<br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU ANTES DO EXEC: Meu pid é %d\n", getpid());<br />
execl("./prog2","prog2", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU DEPOIS DO EXEC:Meu pid é %d\n", getpid());<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 3: Criar um exemplo usando fork/exec mostrando que um processo pai cria um filho e espera por sua execução. O filho executa o comando "ps aux". Ambos devem mostrar seus pids.<br />
<br />
{{collapse bottom}} <br />
{{collapse top| bg=lightyellow | expandir=true | Threads de aplicação}}<br />
<br />
== Threads de aplicação ==<br />
<br />
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:<br />
*'''getcontext(&a)''': salva o contexto na variável '''a''';<br />
*'''setcontext(&a)''': restaura um contexto salvo anteriormente na variável '''a''';<br />
*'''swapcontext(&a,&b)''': salva o contexto atual na variável '''a''' e restaura o contexto salvo anteriormente na variável '''b''';<br />
*'''makecontext(&a, ...)''': ajusta parâmetros internos do contexto salvo em '''a''';<br />
*'''ucontext_t''': as variáveis '''a''' e '''b''' são do tipo '''ucontext_t'''. Este tipo armazena um contexto.<br />
<br />
Busque mais informações sobre estas funções utilizando o programa manpage do Linux (ex.: man getcontext).<br />
<br />
Estude o código no arquivo pingpong.c abaixo e explique seu funcionamento.<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
*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.<br />
*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.<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain, cFnew;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_new(void * arg1, void * arg2,void * arg3,void * arg4) <br />
{<br />
printf ("%s: Primeira string %s %s %s\n",(char*) arg1,(char*) arg2,(char*) arg3, (char*) arg4);<br />
swapcontext(&cFnew, &cMain); <br />
}<br />
<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
<br />
getcontext(&cFnew);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cFnew.uc_stack.ss_sp = stack ;<br />
cFnew.uc_stack.ss_size = STACKSIZE;<br />
cFnew.uc_stack.ss_flags = 0;<br />
cFnew.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cFnew, (void*)(*f_new), 4, "\tF_new", "\tAlo", "\tMundo","\tReal");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
swapcontext(&cMain, &cFnew);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
--><br />
Exercício 3: O que acontece se um dos threads é colocado para dormir? Todos os demais threads param a sua execução.<br />
<br />
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/<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Trocas de mensagens com pipes}}<br />
<br />
== Trocas de mensagens com pipes ==<br />
<br />
;Troca de mensagens<br />
Um mecanismo disponibilizado por sistemas UNIX para troca de mensagens entre processos é o PIPE. Pipes são mecanismos de comunicação indireta onde mensagens são trocadas através de ''mailboxes''. Cada ''mailbox'' possui um identificador único, permitindo que processos identifiquem o canal de comunicação entre eles. O fluxo de mensagens em um Pipe é:<br />
*'''unidirecional''': sobre um mesmo pipe, apenas um processo envia mensagens e um processo recebe mensagens;<br />
*'''FIFO''': as mensagens são entregues na ordem de envio;<br />
*'''não-estruturado''': não há estrutura pré-definida para o formato da mensagem.<br />
No UNIX, pipes são inicializados através da '''SystemCall''' ''pipe'', que possui a seguinte sintaxe:<br />
*''int pipe(int pipefd[2])'': ''pipe'' inicializa um novo pipe no sistema e retorna, no array pipefd, os descritores identificando cada uma das pontas do pipe. A primeira posição do array, i.e. pipefd[0], recebe o descritor que pode ser aberto apenas para leitura, enquanto a segunda posição do array, i.e. pipefd[1], recebe o descritor que pode ser aberto apenas para escrita. A função retorna zero no caso de sucesso, ou -1 se ocorrer erro.<br />
As primitivas send/receive para uso de um pipe no UNIX são implementadas por '''SystemCalls''' read/write, conforme segue:<br />
*''ssize_t read(int fd, void *buf, size_t count)'': “puxa” dados do pipe identificado pelo descritor fd. Os dados recebidos são os apontados pelo ponteiro buf, sendo count a quantidade máxima de bytes a serem recebidos. A função retorna o número de bytes recebidos.<br />
*''ssize_t write(int fd, const void *buf, size_t count)'': “empurra” dados no pipe identificado pelo descritor fd. Os dados transmitidos são os apontados pelo ponteiro buf, sendo count a quantidade de bytes a serem transmitidos. A função retorna o número de bytes transmitidos.<br />
<br />
*Exemplo 1: Transmitindo e recebendo pelo próprio processo<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main()<br />
{<br />
int fd[2];<br />
char *ptr = "Alo eu mesmo";<br />
char *ptr_alvo;<br />
int tamanho_dados, ret;<br />
<br />
tamanho_dados = strlen(ptr)+1;<br />
<br />
if (pipe(fd)==-1){<br />
printf ("erro criação pipe\n");<br />
exit(-1);<br />
}<br />
printf("Transmitido %d bytes\n", tamanho_dados);<br />
write (fd[1], ptr, tamanho_dados);<br />
<br />
ptr_alvo = malloc(tamanho_dados);<br />
<br />
ret=read(fd[0],ptr_alvo,tamanho_dados);<br />
<br />
printf("ret = %d dados => %s\n", ret, ptr_alvo); <br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
*Exemplo 2: Abaixo há um exemplo de programa criando um pipe e compartilhando os descritores entre dois processos (criados via ''fork()'').<br />
<syntaxhighlight lang=c><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
<br />
char *message = "This is a message!!!" ;<br />
<br />
main()<br />
{<br />
char buf[1024] ;<br />
int fd[2];<br />
pipe(fd); /*create pipe*/<br />
if (fork() != 0) { /* I am the parent */<br />
write(fd[1], message, strlen (message) + 1) ;<br />
}<br />
else { /*Child code */<br />
read(fd[0], buf, 1024) ;<br />
printf("Got this from MaMa!!: %s\n", buf) ;<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
*'''Exercício 1: construa um “pipeline”'''. Crie um programa que conecta 4 processos através de 3 pipes. Utilize ''fork()'' para criar vários processos.<br />
<br />
<syntaxhighlight lang=cpp><br />
<br />
//Solução possível<br />
<br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
pipe(fd);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
<br />
</syntaxhighlight><br />
<br />
*'''Exercício 3: Modifique o exercício anterior para que o processo D, através de um novo pipe, mande uma mensagem diretamente para o pai de todos.<br />
<br />
<!--<br />
<code><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
int fd_retorno[2];<br />
<br />
pipe(fd);<br />
pipe(fd_retorno);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size);<br />
read(fd_retorno[0], buf, size);<br />
printf("PAI:%s\n", buf); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
char *ptr_msg_ret="Ok msg de D para o pai";<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
write(fd_retorno[1],ptr_msg_ret,strlen(ptr_msg_ret)+1);<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
*'''Exercício 3: Consultor de Login de Acesso:'''. Estude o link https://www.geeksforgeeks.org/named-pipe-fifo-example-c-program/ e projete um programa cliente servidor da seguinte forma: (i) O servidor possui uma tabela de usuários (userid). O user_id é de tamanho fixo de 7 caracteres. O servidor espera por consultas para verificar se um usuário está na tabela. Se estiver responde com o caracter 'S' senão com 'N'. (ii) O cliente espera por user_id no teclado e consulta o servidor sobre sua existência na tabela. O cliente imprime na tabela a existência ou não do usuário.<br />
<br />
*'''Exercício 4: cópia de arquivo'''. Projete um programa de cópia de arquivos chamado FileCopy usando pipes comuns. Esse programa receberá dois parâmetros: o primeiro é o nome do arquivo a ser copiado e o segundo é o nome do arquivo copiado. Em seguida, o programa criará um pipe comum e gravará nele o conteúdo do arquivo a ser copiado. O processo filho lerá esse arquivo do pipe e o gravará no arquivo de destino. Por exemplo, se chamarmos o programa como descrito a seguir:<br />
:<syntaxhighlight lang=bash><br />
$ FileCopy entrada.txt copia.txt<br />
</syntaxhighlight><br />
:o arquivo ''entrada.txt'' será gravado no pipe. O processo filho lerá o conteúdo desse arquivo e o gravará no arquivo de destino ''copia.txt''. Escreva o programa usando os pipes da API POSIX no Linux.<br />
<br />
<br />
{{collapse bottom}}<br />
<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Exercícios sobre Memória Compartilhada}}<br />
<br />
==SHARED MEMORY: Produtor (pai) - Consumidor (filho) - ==<br />
<br />
<!-- Parou aki 20/08<br />
<br />
<br />
*'''Experimento 2:''' Complete o código a seguir para que os processos pai e filho possam compartilhar um segmento de memória. O filho escreve no segmento e o pai imprime na tela o conteúdo da mensagem.<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
char *ptr_msg = "alo pai, tudo bem?"; <br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
//completar aqui<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
<!--<br />
<code><br />
<br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/types.h><br />
#include <string.h><br />
#include <stdlib.h><br />
<br />
int main(void)<br />
{<br />
int fd[2], pipe_ret, filho;<br />
char string[] = "Hello, pipe!\n";<br />
char buffer[20];<br />
<br />
pipe(fd);<br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
/*Mandar string para a extremidade do pipe*/<br />
write(fd[1], string, (strlen(string)+1));<br />
exit(0);<br />
}<br />
else<br />
{<br />
<br />
/* Read in a string from the pipe */<br />
pipe_ret = read(fd[0], buffer, (20*sizeof(char)));<br />
printf("Recebi este texto %s", buffer);<br />
}<br />
<br />
return(0);<br />
}<br />
<br />
<br />
<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
key = ftok("teste_sh.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644 | IPC_CREAT));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
<br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
strncpy(segmento, "mensagem compartilhada", SHM_SIZE); <br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
--><br />
<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Memória Compartilhada}}<br />
*'''Experimento Shared Memory:''' Complete o código a seguir para que os processos pai e filho possam compartilhar um segmento de memória. O filho escreve no segmento e o pai imprime na tela o conteúdo da mensagem.<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
char *ptr_msg = "alo pai, tudo bem?"; <br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
//completar aqui strcpy(segmento, ptr_msg); //aqui deveria testar a cpacidade da área...<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exemplo com ftok:<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
key = ftok("./teste.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644 | IPC_CREAT));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
<br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
strncpy(segmento, "mensagem compartilhada", SHM_SIZE); <br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exemplo com ftok entre processos sem parentesco:<br />
<br />
Criar um arquivo teste.txt e em um terminal executar:<br />
<br />
<syntaxhighlight lang=c><br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
int modo,filho;<br />
<br />
struct minha_struct {<br />
char flag;<br />
int numero;<br />
} *ptr;<br />
<br />
<br />
key = ftok("./teste.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644 | IPC_CREAT));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
ptr = (struct minha_struct *) shmat(shmid, (void *)0, 0);<br />
if ((char *)ptr == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
ptr->flag =0;<br />
ptr->numero = 0;<br />
while (ptr->flag==0) { <br />
printf("%d\n", ptr->numero);<br />
sleep(1);<br />
} <br />
<br />
if (shmdt(ptr) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Em outro terminal executar:<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
struct minha_struct {<br />
char flag;<br />
int numero;<br />
} *ptr;<br />
<br />
<br />
key = ftok("./teste.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
ptr = (struct minha_struct *) shmat(shmid, (void *)0, 0);<br />
if ((char *)ptr == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
<br />
<br />
while (ptr->numero++<10)<br />
sleep(1);<br />
<br />
ptr->flag = 1;<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Exercício Desafio: Implementar o problema do buffer circular usando memória compartilhada.<br />
<br />
{{collapse bottom}}<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Exercício (Algoritmo de Peterson)}}<br />
<br />
== Exercício (Algoritmo de Peterson) ==<br />
<br />
<br />
'''Exercício 1''': Sincronize o código a seguir, de maneira que o processo pai imprima apenas os números impares e o processo filho os números pares. Para isso utilize o algoritmo de '''Peterson''' visto em aula. '''Utilize memória compartilhada''' para comunicação entre os processos.<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
main()<br />
{ <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int i; <br />
<br />
for(i = 0;i < 10;i=i+2){ <br />
printf("Processo pai %d \n", i); <br />
<br />
} <br />
<br />
<br />
}<br />
<br />
else { /*Child code */<br />
int i; <br />
for(i = 1;i < 10;i=i+2){ <br />
printf("Processo filho %d \n", i); <br />
<br />
}<br />
<br />
<br />
}<br />
<br />
exit(0);<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
'''Exercício 2''': Considerando o exercício anterior faça a mesma sincronização, no entanto desta vez utilize a modelagem em software do TSL. <br />
* Em sua experiência, depois de testar diversas vezes as execuções de suas soluções baseadas no algoritmo de '''Peterson''' e '''Tsl''', qual sua opinião sobre as abordagens?<br />
Explique seu raciocínio. <br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Exercício (Semáforos)}}<br />
== Exercício (Semáforos) ==<br />
<br />
<br />
'''Exercício 1''': Sincronize o código a seguir, de maneira que o processo pai imprima apenas os números impares e o processo filho os números pares. Para isso utilize '''Semáforos''' de acordo com a implementação em '''semaforo.h'''. '''Utilize memória compartilhada''' para comunicação entre os processos.<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
main()<br />
{ <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int i; <br />
<br />
for(i = 0;i < 10;i=i+2){ <br />
printf("Processo pai %d \n", i); <br />
sleep(1);<br />
<br />
} <br />
<br />
<br />
}<br />
<br />
else { /*Child code */<br />
int i; <br />
for(i = 1;i < 10;i=i+2){ <br />
printf("Processo filho %d \n", i); <br />
<br />
}<br />
<br />
<br />
}<br />
<br />
exit(0);<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
SEMAFORO.H<br />
<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <sys/sem.h><br />
<br />
<br />
int criar_semaforo(int val, int chave) <br />
{<br />
int semid ;<br />
<br />
union semun {<br />
int val;<br />
struct semid_ds *buf ;<br />
ushort array[1];<br />
} arg_ctl ;<br />
<br />
key_t ft = ftok("/tmp", chave);<br />
<br />
semid = semget(ft,1,IPC_CREAT|IPC_EXCL|0666);<br />
if (semid == -1) {<br />
semid = semget(ft,1,0666); <br />
if (semid == -1) {<br />
perror("Erro semget()");<br />
exit(1) ;<br />
}<br />
}<br />
<br />
arg_ctl.val = val; //valor de início<br />
if (semctl(semid,0,SETVAL,arg_ctl) == -1) {<br />
perror("Erro inicializacao semaforo");<br />
exit(1);<br />
}<br />
return(semid) ;<br />
}<br />
<br />
void P(int semid){<br />
<br />
struct sembuf *sops = malloc(10*sizeof(int));<br />
sops->sem_num = 0;<br />
sops->sem_op = -1;<br />
sops->sem_flg = 0;<br />
semop(semid, sops, 1); <br />
free(sops);<br />
<br />
}<br />
<br />
<br />
void V(int semid){<br />
<br />
struct sembuf *sops = malloc(10*sizeof(int));<br />
sops->sem_num = 0;<br />
sops->sem_op = 1;<br />
sops->sem_flg = 0; <br />
semop(semid, sops, 1); <br />
free(sops);<br />
<br />
} <br />
<br />
<br />
<br />
void sem_delete(int semid) <br />
{<br />
<br />
if (semctl(semid,0,IPC_RMID,0) == -1)<br />
perror("Erro na destruicao do semaforo");<br />
}<br />
<br />
<br />
<br />
<br />
</syntaxhighlight><br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Programação concorrente}}<br />
<br />
== Programação concorrente ==<br />
<br />
;POSIX Threads<br />
A 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):<br />
*''pthread_create'': cria uma thread;<br />
*''pthread_kill'': força a terminação de uma thread;<br />
*''pthread_join'': sincroniza o final de uma thread (qual a diferença/semelhança com o ''wait'' que usamos para processos?);<br />
*''pthread_exit'': finaliza uma thread.<br />
Para utilizar estas funções é necessário linkar o programa à libpthread (''-lpthread''). <br />
<br />
<br />
;POSIX pthread mutex<br />
<br />
A biblioteca pthread implementa um tipo ''pthread_mutex_t'', que garante a exclusão mútua entre threads. Estes mutex são manipulados através das funções (acesse as man-pages das chamadas para maiores detalhes):<br />
*''pthread_mutex_lock'': acessa um mutex.<br />
*''pthread_mutex_trylock'': tenta acessar um mutex (retorna valor indicando sucesso ou falha no lock).<br />
*''pthread_mutex_unlock'': libera um mutex.<br />
<br />
<br />
<br />
<br />
;POSIX Semaphores<br />
<br />
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):<br />
*''sem_init'': inicializa um semáforo;<br />
*''sem_destroy'': destroy um semáforo;<br />
*''sem_wait'': implementa a operação ''p'';<br />
*''sem_post'': implementa a operação ''v''.<br />
Para utilizar estas funções é necessário linkar o programa à librt ou à libpthread (''-lrt'' ou ''-lpthread'').<br />
<br />
;Exercício 1<br />
<br />
O programa abaixo cria 5 threads, e cada uma destas threads atualiza uma variável global (memória compartilhada).<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include <pthread.h><br />
#include <signal.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
pthread_mutex_t mut;<br />
<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
}<br />
</syntaxhighlight><br />
<br />
# Compile este programa. <br />
# Execute este programa várias vezes. Ele funciona? Será que ele gera as saídas esperadas?<br />
# Identifique as '''seções críticas''' do programa.<br />
# Corrija o programa utilizando '''mutex'''. <br />
# Analise a função ''AtualizaSaldo()'' com a sua solução. Lembre-se que o uso do mutex implica em apenas uma thread acessar a seção crítica por vez, enquanto outras threads ficam bloqueadas, esperando. Disso vem que, quanto menor o trecho de código entre um ''lock'' e um ''unlock'', menos tempo uma thread necessita ficar esperando.<br />
# Modifique o programa para usar um semáforo binário ao invés de um mutex em sua solução.<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <cstring><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
<br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
sem_t sem;<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
int value;<br />
sem_wait(&sem);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
sem_getvalue(&sem, &value);<br />
printf("valor sem = %d\n", value);<br />
sem_post(&sem);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
sem_init(&sem,0,1);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
sem_destroy(&sem);<br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
<br />
;Exercício 2<br />
Refaça o exercício 3 usando processos criados com fork e exec. O semáforo deve ser criado em uma região de memória compartilhada.<br />
<br />
;Exercício 3<br />
Implemente com pthreads e semáforos/mutex a solução do produtor/comsumidor.<br />
<br />
;Exercício 4<br />
<br />
O programa abaixo manipula uma matriz de tamanho MxN (veja os defines para o tamanho da matriz). A função ''SumValues'' soma todos os valores em uma linha da matriz. A linha a ser somada é identificada pela variável ''i''. Modifique o programa principal (''main'') nos locais indicados para:<br />
# Criar N threads, uma para somar os valores de cada linha.<br />
# Receber o resultado do somatório de cada linha e gerar o somatório total da matriz.<br />
# Analise o programa: há problemas de sincronização que precisam ser resolvidos? Se sim, resolva-os.<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include "thread.h"<br />
<br />
/* number of matrix columns and rows */<br />
#define M 5<br />
#define N 10<br />
<br />
using namespace std;<br />
<br />
int matrix[N][M];<br />
Thread *threads[N];<br />
<br />
<br />
/* thread function; it sums the values of the matrix in the row */<br />
int SumValues(int i)<br />
{<br />
int n = i; /* number of row */<br />
int total = 0; /* the total of the values in the row */<br />
int j;<br />
for (j = 0; j < M; j++) /* sum values in the "n" row */<br />
total += matrix[n][j];<br />
cout << "The total in row" << n << " is " << total << "." << endl;<br />
/* terminate a thread and return a total in the row */<br />
exit(total);<br />
}<br />
<br />
int main(int argc, char *argv[])<br />
{<br />
int i, j;<br />
int total = 0; /* the total of the values in the matrix */<br />
<br />
/* initialize the matrix */<br />
for (i = 0; i < N; i++)<br />
for (j = 0; j < M; j++)<br />
matrix[i][j] = i * M + j;<br />
<br />
/* create threads */<br />
/* COLOQUE SEU CÓDIGO PARA CRIAR AS THREADS AQUI! */<br />
<br />
/* wait for terminate a threads */<br />
/* COLOQUE SEU CÓDIGO PARA PEGAR O SOMATÓRIO DE LINHAS E TOTALIZAR A SOMA DA MATRIZ AQUI! */<br />
<br />
cout << "The total values in the matrix is " << total << endl;<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Lista de exercícios "Revisão para Prova" }}<br />
<br />
== Lista de exercícios/Revisão para Prova ==<br />
<br />
A lista de exercícios referente a primeira prova (Parte introdutória + Processos) segue neste LINK [http://docente.ifsc.edu.br/andre.damato/sop2018/lista_rev1.pdf | Lista de exercícios]. <br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Primeiro trabalho}}<br />
== JOGO DA VIDA DE CONWAY e JANTAR DOS FILÓSOFOS==<br />
<br />
;Referências<br />
<br />
* [https://www.open-mpi.org/doc/current/ MPI]<br />
<br />
* [https://quark.phy.bnl.gov/~creutz/qcdoc/mpi/mpi.h Tipos de dados MPI]<br />
<br />
* [https://pt.wikipedia.org/wiki/Jogo_da_vida Jogo da Vida]<br />
<br />
<br />
<br />
<br />
A partir da implementação sequencial do Game of Life apresentada a seguir, estude o código e transforme esta implementação em uma implementação paralela utilizando o protocolo de passagem de mensagens MPI.<br />
Perceba que a impĺementação mencionada utiliza como parâmetros de entrada um aquivo contendo o estado inicial do jogo, e o número de gerações que o usuário deseja rodar. A evolução do estado inicial <br />
é impressa na tela passo a passo. Sendo assim, a partir disso:<br />
<br />
*'''1: Elabore uma implementação com 2 processos para o jogo da vida utilizando o protocolo MPI, de maneira que um processo execute uma geração i qualquer e o outro execute a geração seguinte i+1''' <br />
<br />
*'''2: (0,7) Os processos deverão se comunicar utilizando as funções do protocolo MPI.''' <br />
<br />
*'''3: (0,3) Relatório simplificado explicando a sua solução. Utilize diagramas para representar a comunicação entre os processos, explicando como a matriz do jogo é transferida entre os processos. ''' <br />
<br />
*'''4: Entregue o Relatório e o código fonte do trabalho em um pacote compactado via e-mail (PRAZO 19/10). <br />
<br />
<br />
<br />
* ''' Compilar o código com MPI '''<br />
<code><br />
mpicc -o nomeApp arquivo.c<br />
</syntaxhighlight><br />
<br />
* ''' Rodar rodar programa utilizando MPI '''<br />
<code><br />
mpirun -np numeroDeProcessos ./nomeApp entrada.txt gerações<br />
</syntaxhighlight><br />
<br />
* (int) -np: Quantidade de processos que você deseja executar <br />
<br />
* entrada.txt: Arquivo de entrada com estado inicial do jogo <br />
<br />
* (int) gerações: número de gerações que você deseja rodar<br />
<br />
* [http://docente.ifsc.edu.br/andre.damato/sop2018/entrada.txt Arquivo de entrada para Testes]<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
<br />
<br />
<br />
/*<br />
<br />
Conway's Game of Life<br />
<br />
Compilar código com MPI<br />
mpicc -o nomeApp arquivo.c<br />
<br />
<br />
Rodar rodar programa utilizando MPI<br />
<br />
mpirun -np numeroDeProcessos ./nomeApp entrada.txt gerações<br />
<br />
(int) -np: Quantidade de processos que você deseja executar <br />
entrada.txt: Arquivo de entrada com estado inicial do jogo <br />
(int) gerações: número de gerações que você deseja rodar<br />
<br />
<br />
*/<br />
<br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h><br />
#include "mpi.h"<br />
<br />
<br />
//Numero de linhas e colunas<br />
#define nLinhas 32<br />
#define nColunas 82 <br />
<br />
char *matriz[nLinhas];<br />
char *entrada[nLinhas];<br />
<br />
<br />
void iniciar() {<br />
<br />
int i;<br />
<br />
//Alocar espaço em memória para as matrizes<br />
for (i = 0; i < nLinhas; i++ ) <br />
matriz[i] = (char *) malloc((nColunas) * sizeof( char )); <br />
<br />
<br />
}<br />
<br />
int adjacente(char **matriz, int i, int j){<br />
<br />
int x,y, initX, initY, limitX, limitY;<br />
int vizinhos = 0;<br />
<br />
if(i == 0)<br />
initX = 0;<br />
else <br />
initX = -1;<br />
<br />
if(i == (nLinhas-1)) <br />
limitX = 1;<br />
else<br />
limitX = 2;<br />
<br />
<br />
if(y == 0)<br />
initY = 0;<br />
else <br />
initY = -1;<br />
<br />
if(y == (nColunas-3)) <br />
limitY = 1;<br />
else<br />
limitY = 2;<br />
<br />
for(x = initX ; x < limitX; x++){<br />
for(y = initY; y < limitY; y++){<br />
if(matriz[i+x][j+y] == '#') <br />
vizinhos++; <br />
} <br />
}<br />
<br />
<br />
if(matriz[i][j] == '#') <br />
return (vizinhos-1);<br />
else <br />
return vizinhos;<br />
<br />
}<br />
<br />
<br />
void calculoGeracao(char **matriz, int ger) {<br />
<br />
int i, j, a;<br />
char novaGeracao[nLinhas][nColunas];<br />
<br />
/* Aplicando as regras do jogo da vida */<br />
for (i=0; i < nLinhas; i++){ <br />
for (j=0; j < nColunas; j++) {<br />
<br />
a = adjacente(matriz, i, j);<br />
<br />
if (a == 2) novaGeracao[i][j] = matriz[i][j];<br />
if (a == 3) novaGeracao[i][j] = '#';<br />
if (a < 2) novaGeracao[i][j] = ' ';<br />
if (a > 3) novaGeracao[i][j] = ' ';<br />
<br />
if (j == 0)<br />
novaGeracao[i][j] = '"';<br />
} <br />
<br />
novaGeracao[i][79] = '"';<br />
novaGeracao[i][80] = '\n';<br />
<br />
<br />
}<br />
<br />
/* Passando o resultado da nova geração para a matriz de entrada */<br />
for (i=0; i < nLinhas; i++){ <br />
for (j=0; j < nColunas; j++) <br />
matriz[i][j] = novaGeracao[i][j];<br />
}<br />
}<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
main(int argc, char *argv[2]){<br />
<br />
/* Para uso com MPI<br />
<br />
<br />
//Variáveis para uso com MPI<br />
int numeroDeProcessos = 0;<br />
int rank = 0;<br />
MPI_Status status; <br />
<br />
//Iniciar MPI---<br />
MPI_Init( &argc, &argv );<br />
<br />
//Atribui a variável numeroDeProcessos o número de processos passado como parâmetro em -np <br />
MPI_Comm_size( MPI_COMM_WORLD, &numeroDeProcessos );<br />
<br />
//Pega o valor do rank (processo)<br />
MPI_Comm_rank( MPI_COMM_WORLD, &rank );<br />
*/<br />
<br />
<br />
FILE *matrizEntrada;<br />
matrizEntrada = fopen(argv[1], "r");<br />
iniciar();<br />
<br />
<br />
if (matrizEntrada == NULL)<br />
printf ("Não posso abrir o arquivo \"%s\"\n", argv[1]);<br />
<br />
<br />
char str[nColunas];<br />
int linha = 0;<br />
<br />
<br />
<br />
//Lendo o estado inicial do jogo a partir do arquivo<br />
while((fgets(str, nColunas, matrizEntrada) != NULL)&&(linha < nLinhas)){<br />
strcat(matriz[linha], str);<br />
linha++;<br />
}<br />
<br />
int i,gens; <br />
<br />
<br />
for(gens = 0; gens < atoi(argv[2]); gens++){ //Gens é o número de gerações especificado no segundo parâmetro <br />
<br />
calculoGeracao(matriz, gens);<br />
printf("%c[2J",27); // Esta linha serve para limpar a tela antes de imprimir o resultado de uma geração <br />
<br />
//Lendo o estado do jogo e imprime na tela <br />
for(i = 0; i < nLinhas; i++)<br />
printf("%s", matriz[i]); <br />
<br />
sleep(1);<br />
<br />
}<br />
<br />
<br />
for(i = 0; i < nLinhas; i++) <br />
free(matriz[i]); <br />
<br />
<br />
<br />
/* Finaliza o MPI */ <br />
//MPI_Finalize();<br />
<br />
exit(0);<br />
} <br />
<br />
<br />
</syntaxhighlight><br />
<br />
<br />
;Jantar dos Filósofos<br />
O problema clássico Jantar dos Filósofos consiste em que n fluxos (n filósofos) disputam n recursos (n talheres). No problema, para conseguir "jantar" (ou executar), cada filósofo precisa pegar dois talheres adjascentes a ele. Cada recurso é compartilhado por dois filósofos.<br />
*[http://www.doc.ic.ac.uk/~jnm/concurrency/classes/Diners/Diners.html Veja esta simulação]<br />
*[http://en.wikipedia.org/wiki/Dining_philosophers_problem Veja esta descrição do problema]<br />
<br />
<br />
* ''' (0,7) programa abaixo implementa um Jantar dos Filósofos utilizando semáforos para sincronização. Contudo, as chamadas para as operações ''v'' e ''p'' foram removidas, conforme comentários no código. Re-insira as operações no código e analise a solução. Esta modificação é suficiente para garantir que não haverá deadlock? Se sim, mostre o porque. Se não, proponha uma solução completa. '''<br />
<br />
<br />
*''' (0,3) Relatório simplificado explicando a sua solução. ''' <br />
<br />
*''' Entregue o Relatório e o código fonte do trabalho em um pacote compactado via e-mail (PRAZO 19/10). <br />
<br />
<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include "thread.h"<br />
#include "semaphore.h"<br />
<br />
using namespace std;<br />
<br />
const int DELAY = 10000000;<br />
const int ITERATIONS = 5;<br />
<br />
Semaphore chopstick[5];<br />
<br />
int philosopher(int n)<br />
{<br />
cout << "Philosopher " << n << " was born!\n";<br />
<br />
int first = (n < 4)? n : 0; // left for phil 0 .. 3, right for phil 4<br />
int second = (n < 4)? n + 1 : 4; // right for phil 0 .. 3, left for phil 4<br />
<br />
// Foram removidos do laço abaixo:<br />
// - uma chamada para chopstick[first].p()<br />
// - uma chamada para chopstick[second].p()<br />
// - uma chamada para chopstick[first].v()<br />
// - uma chamada para chopstick[second].v()<br />
for(int i = 0; i < ITERATIONS; i++) {<br />
cout << "Philosopher " << n << " thinking ...\n";<br />
for(int i = 0; i < DELAY * 10; i++);<br />
<br />
cout << "Philosopher " << n << " eating ...\n";<br />
for(int i = 0; i < DELAY; i++);<br />
}<br />
<br />
return n;<br />
}<br />
<br />
int main()<br />
{<br />
cout << "The Dining-Philosophers Problem\n";<br />
<br />
Thread * phil[5];<br />
for(int i = 0; i < 5; i++)<br />
phil[i] = new Thread(&philosopher, i);<br />
<br />
int status;<br />
for(int i = 0; i < 5; i++) {<br />
phil[i]->join(&status);<br />
if(status == i)<br />
cout << "Philosopher " << i << " went to heaven!\n";<br />
else<br />
cout << "Philosopher " << i << " went to hell!\n";<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Softwares básicos, caso Hello Word! (Trabalho 2) Entrega dia 09/11}}<br />
<br />
== Softwares básicos, caso Hello Word! ==<br />
<br />
O objetivo do experimento de hoje é pesquisar e entender os processos de atribuição de endereços de programas realizados em tempo de compilação pelos softwares básicos como: compilador, linker, e assembler. Sendo assim, neste experimento vamos utilizar os seguintes softwares para criação e análise de código:<br />
<br />
*'''GCC''': compilador para gerar código objeto a partir de um código de programa escrito na linguagem c;<br />
*'''GNU Linker (LD)''': Para vincular os códigos (módulos) objetos do programa;<br />
*[https://linux.die.net/man/1/ld| Linker ] <br />
*'''GNU Assembler''': Para gerar o código executável a partir do código objeto;<br />
*[https://linux.die.net/man/1/as | assembler]<br />
* '''OBJDUMP''': Para mostrar informações do código;<br />
*[https://linux.die.net/man/1/objdump | Objdump ]<br />
<br />
<br />
A seguir segue descrito o programa a ser utilizado no exercício 1:<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
int main()<br />
{<br />
printf("Hello, World!");<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
Trata-se do programa hello word, este programa apenas exibe uma mensagem na tela. No entanto, vamos analisar como são as etapas confecção do executável a partir deste código ''simples''. <br />
<br />
Exercício 1: <br />
* Compile o programa hello word, e o transforme em código objeto utilizando o programa GCC. Para esta tarefa execute o seguinte comando:<br />
<code><br />
gcc -o hello hello.c <br />
</syntaxhighlight><br />
* Agora abra o código objeto utilizando o programa OBJDUMP.<br />
<code><br />
objdump -D hello<br />
</syntaxhighlight><br />
* Identifique quais são as seções de código obtidas a partir do '''hello.c'''.<br />
* Pesquise e entenda o significado das seções de código: .bss, .txt, .data, .init.<br />
* Faça uma análise e identifique o endereço de memória que o programa ''hello world'' vai ser carregado. <br />
* Este código objeto é relocável? Justifique sua resposta.<br />
* Agora gere o código assembly do hello world.<br />
<code><br />
gcc -S hello.c<br />
</syntaxhighlight> <br />
*Agora gere o código executável utilizando o programa '''AS''' e o programa '''LD'''.<br />
<code><br />
as -o hello.o hello.s<br />
</syntaxhighlight><br />
* Como a etapa de linkagem para a construção do código executável está sendo executada sem o auxílio do '''GCC''', necessitamos vincular manualmente as bibliotecas necessárias. Para criar apropriadamente o executável vamos precisar das bibliotecas '''ld-linux-x86-64.so.2''', '''crt1.o''', '''crti.o''', '''crtn.o'''.<br />
* Para descobrir suas respectivas localizações use o comando '''LOCATE'''. Por exemplo:<br />
<code><br />
<br />
locate crti.o <br />
<br />
</syntaxhighlight><br />
<br />
ou <br />
<br />
<code><br />
<br />
find /usr/ -name crti*<br />
<br />
</syntaxhighlight><br />
<br />
* Agora que já sabemos a localização das bibliotecas necessárias vamos vincular essas a nossa aplicação.<br />
<code><br />
ld --dynamic-linker /caminho/ld-linux-x86-64.so.2 /caminho/crt1.o /caminho/crti.o /caminho/crtn.o hello.o -lc -o hello.exe<br />
</syntaxhighlight><br />
<br />
* Agora abra o código objeto utilizando o programa OBJDUMP.<br />
* Faça uma análise e identifique o endereço de memória em que o programa ''hello world'' inicializa suas estruturas na memória.<br />
* Dica!<br />
<code><br />
objdump -D -s -j .init hello.exe<br />
</syntaxhighlight><br />
* Houve diferença entre os endereços do programa executável em relação ao código objeto? Explique.<br />
* Explique as principais diferenças entre o arquivo objeto .o e o executável final. (dica utilize o objdump para fazer essa análise)<br />
{{collapse bottom}}<br />
<ol><br />
<li> Estudar e executar o código em http://cs.lmu.edu/~ray/notes/gasexamples/ <br />
Detalhes das chamadas na arquitetura x86_64 ver em https://lwn.net/Articles/604287/ <br />
<li>Estudar e executar o código usando a função (em conformidade com a API POSIX) write() para o ''hello world'':<br />
<code><br />
#include <unistd.h> <br />
<br />
main()<br />
{<br />
write(1,"Alo Mundo\n",10);<br />
}<br />
</syntaxhighlight><br />
</li><br />
<li> Use o comando strace para verificar todas as chamadas de sistema dos programas acima.<br />
</li><br />
<li><br />
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:<br />
<code><br />
main()<br />
{<br />
meu_hello_world();<br />
}<br />
</syntaxhighlight><br />
</li><br />
Gere o assembly do código em C e discuta a diferença entre uma chamada de função e uma chamada de sistema.<br />
<li><br />
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:<br />
<code><br />
#include <string.h><br />
main()<br />
{<br />
char *p="Tudo bem com vocês?";<br />
meu_hello_world(p, strlen(p));<br />
}<br />
</syntaxhighlight><br />
Solução:<br />
{{collapse top|Solução}}<br />
<code><br />
modificado de http://cs.lmu.edu/~ray/notes/gasexamples/<br />
.global meu_hello_world<br />
<br />
.text<br />
meu_hello_world:<br />
<br />
push %rdi # salva primeiro parâmetro<br />
push %rsi # salva segundo parâmetro<br />
mov $1, %rax # system call 1 é write<br />
mov $1, %rdi # file handle 1 é stdout<br />
mov $message, %rsi # endereço da string<br />
mov $13, %rdx # número de bytes da string<br />
syscall # chamada ao sistema<br />
<br />
pop %rdx # o que havia sido passado em rsi (número de bytes) é colocado em rdx<br />
pop %rsi # o que havia sido colocado em rdi (endereço da string) é colocado em rsi<br />
mov $1, %rax # system call 1 is write<br />
mov $1, %rdi # file handle 1 é stdout<br />
syscall # nova chamada ao sistema<br />
<br />
ret<br />
<br />
message:<br />
.ascii "Hello, World\n"<br />
</syntaxhighlight><br />
</li><br />
</ol><br />
{{collapse bottom}}</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=SOP29005-2019-2&diff=162033SOP29005-2019-22019-10-04T12:17:21Z<p>127.0.0.1: /* Objetivos */</p>
<hr />
<div>=AULA 1 - Dia 30/07/2019=<br />
<br />
===Objetivos/Conteúdos===<br />
<br />
*Apresentação do Plano de Ensino<br />
**Objetivos e Conteúdo Programático da Disciplina (ver SIGAA)<br />
**Forma de Avaliação (ver SIGAA)<br />
<br />
*Introdução a Sistemas Operacionais (Cap1. do Silberschatz)<br />
**O que faz um sistema operacional (1.1)<br />
**Organização e Arquitetura de um Sistema Computacional (1.2 e 1.3)<br />
***Importância da Interrupção e Timers (1.2.1)<br />
***Estrutura de Armazenamento (1.2.2)<br />
***Estrutura de IO (1.2.3)<br />
**Estrutura e Operações de um Sistema Operacional (1.4 e 1.5)<br />
<br />
===Material de Referência===<br />
<br />
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte1.pdf Apresentação sobre histórico visão geral e estruturas básicas de um SO]<br />
* [http://codex.cs.yale.edu/avi/os-book/OSE1/slide-dir/index.html Slides Silberschatz Oitava Edição]<br />
* [http://professor.unisinos.br/barbosa/SO/ch1br.ppt Tradução Slides Silberschatz Cap1]<br />
* [http://professor.unisinos.br/barbosa/SO/ch2br.ppt Tradução Slides Silberschatz Cap2]<br />
* [http://professor.unisinos.br/barbosa/SO/ch3br.ppt Tradução Slides Silberschatz Cap3]<br />
* [http://professor.unisinos.br/barbosa/SO/ch4br.ppt Tradução Slides Silberschatz Cap4]<br />
* [http://wiki.inf.ufpr.br/maziero/doku.php?id=so:livro_de_sistemas_operacionais Livro do Prof.Maziero]<br />
* [http://deptinfo.unice.fr/~rr/l3systres/ Université Nice Sophia Antipolis]<br />
<br />
Arliones:<br />
<br />
*[https://www.dropbox.com/s/dt80g3tml65rpmg/SOP29005-parte6.odp?dl=0]<br />
*[https://www.dropbox.com/s/7lneavq0go9kz2t/SOP29005-parte7.odp?dl=0]<br />
<br />
===Leitura Recomendada===<br />
<br />
*Cap.1 do Silberschatz principalmente:<br />
**1.1 a 1.9<br />
<br />
===Exercícios Práticos de Apoio a Aula===<br />
<br />
Na sequência. com fins motivacionais, são apresentados alguns exercícios ilustrando conceitos de processos, arquivos e permissionamento.<br />
<br />
<ol><br />
<li><br />
Comando para ver todos os processos no linux:<br />
<code><br />
$ ps aux<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Colocar 2 processos se executando no contexto de um terminal e verificar número dos processos e então "destruí-los":<br />
<code><br />
$ yes > /dev/null<br />
$ yes > /dev/null<br />
$ ps <br />
$ kill -9 <pid_yes><br />
$ kill -9 <pid_yes><br />
</syntaxhighlight><br />
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.<br />
</li><br />
<li><br />
Criar um terminal adicional<br />
<code><br />
$ xterm<br />
</syntaxhighlight><br />
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:<br />
<code><br />
$ echo Alo Terminal > /dev/pts/2<br />
$ kill -9 <pid_terminal><br />
</syntaxhighlight><br />
</li><br />
<li><br />
Comunicação entre processos:<br />
<code><br />
$ cat /etc/passwd | grep home | wc -l<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Retirando a permissão de leitura de um arquivo em nível de usuário proprietário:<br />
<code><br />
$ echo Alo Mundo > alfa.txt<br />
$ ls -l alfa.txt<br />
$ cat alfa.txt<br />
$ chmod u-r alfa.txt<br />
$ cat alfa.txt<br />
$ chmod u+r alfa.txt<br />
$ cat alfa.txt <br />
</syntaxhighlight><br />
</li><br />
</ol><br />
<br />
=AULA 2 - Dia 2/08/2019=<br />
<br />
===Objetivos/Conteúdos===<br />
<br />
*Continuação da Aula<br />
*Estruturas do Sistema Operacional (cap.2)<br />
**Serviços do Sistema Operacional (2.1)<br />
**Interfaces com Usuários (2.2)<br />
**Chamadas do Sistema (2.3)<br />
**Tipos de Chamadas de Sistema (2.4) ver Fig.2.8<br />
***Chamadas de Controle de Processos<br />
**Arquiteturas e Estruturas de Sistemas Operacionais (2.7)<br />
**Máquinas Virtuais (2.8)<br />
<br />
===Material de Referência===<br />
<br />
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte1.pdf Apresentação sobre histórico visão geral<br />
* [http://www.fil.univ-lille1.fr/~sedoglav/OS/TP.html ]<br />
<br />
===Leitura Recomendada===<br />
<br />
*Cap.2 do Silberschatz principalmente:<br />
**2.1 a 2.8<br />
<br />
===Exercícios===<br />
<br />
=AULA 3 - Dia 7/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*Continuação da aula anterior<br />
**Chamadas do Sistema (2.3)<br />
**Tipos de Chamadas de Sistema (2.4) ver Fig.2.8<br />
***Chamadas de Controle de Processos<br />
**Arquiteturas e Estruturas de Sistemas Operacionais (2.7)<br />
**Máquinas Virtuais (2.8)<br />
<br />
===Exercícios===<br />
<br />
<ol><br />
<li> Estudar e executar o código em http://cs.lmu.edu/~ray/notes/gasexamples/ <br />
Detalhes das chamadas na arquitetura x86_64 ver em https://lwn.net/Articles/604287/ <br />
<li>Estudar (usar o man) e executar o código usando a função (em conformidade com a API POSIX) write() para o ''hello world'':<br />
<code><br />
#include <unistd.h> <br />
<br />
main()<br />
{<br />
write(1,"Alo Mundo\n",10);<br />
}<br />
</syntaxhighlight><br />
</li><br />
<li> Use o comando strace para verificar todas as chamadas de sistema dos programas acima.<br />
</li><br />
<li><br />
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() 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:<br />
<code><br />
void meu_hello();<br />
<br />
int main()<br />
{<br />
meu_hello();<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
</li><br />
Gere o assembly do código em C e discuta a diferença entre uma chamada de função e uma chamada de sistema.<br />
<li><br />
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:<br />
<code><br />
#include <string.h><br />
main()<br />
{<br />
char *p="Tudo bem com vocês?";<br />
meu_hello_world(p, strlen(p));<br />
}<br />
</syntaxhighlight><br />
Solução:<br />
{{collapse top|Solução}}<br />
<code><br />
modificado de http://cs.lmu.edu/~ray/notes/gasexamples/<br />
.global meu_hello_world<br />
<br />
.text<br />
meu_hello_world:<br />
<br />
push %rdi # salva primeiro parâmetro<br />
push %rsi # salva segundo parâmetro<br />
mov $1, %rax # system call 1 é write<br />
mov $1, %rdi # file handle 1 é stdout<br />
mov $message, %rsi # endereço da string<br />
mov $13, %rdx # número de bytes da string<br />
syscall # chamada ao sistema<br />
<br />
pop %rdx # o que havia sido passado em rsi (número de bytes) é colocado em rdx<br />
pop %rsi # o que havia sido colocado em rdi (endereço da string) é colocado em rsi<br />
mov $1, %rax # system call 1 is write<br />
mov $1, %rdi # file handle 1 é stdout<br />
syscall # nova chamada ao sistema<br />
<br />
ret<br />
<br />
message:<br />
.ascii "Hello, World\n"<br />
</syntaxhighlight><br />
</li><br />
</ol><br />
{{collapse bottom}}<br />
<br />
=AULA 4 - Dia 9/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*PARTE 2A: Gerenciamento de Processos (cap.3)<br />
*3.1.Conceito de Processo<br />
*3.2.Escalonamento de Processos<br />
*3.3.Operações sobre Processos (Laboratório Operações sobre Processos no Linux: Fork/Exec/Wait)<br />
<br />
===Material de Referência===<br />
<br />
*Slides do Cap.3 - Silberschatz<br />
*Laboratório Fork/Exec/Wait<br />
<br />
=== Exercícios de Demonstração===<br />
<br />
#Executar em um terminal o comando top. Em um outro terminal executar:<br />
yes > /dev/null &<br />
yes > /dev/null &<br />
#Parar um dos processos yes<br />
kill -STOP <pid_yes><br />
#Continuar o processo<br />
kill -CONT <pid_yes><br />
#Destruir todos<br />
killall yes<br />
<br />
=AULA 5 - Dia 14/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*Ainda Processos<br />
*Cap.3.2..Escalonamento de Processos<br />
*Cap.2.3.Operaçṍes sobre processos<br />
*Finalização do Laboratório Fork/Exec/Wait<br />
<br />
===Adendo===<br />
<br />
*Estudar e comentar [https://www.geeksforgeeks.org/wait-system-call-c/]<br />
<br />
=AULA 6 - Dia 16/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*Comunicação Interprocessos (3.4 e 3.5)<br />
*Laboratório de Memória Compartilhada<br />
<br />
=AULA 7 - Dia 21/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Comunicação Interprocessos: Troca de Mensagens (3.6)<br />
*Laboratório de Pipes<br />
<br />
=AULA 8 - Dia 23/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Finalização Lab. pipes nomeados.<br />
*Threads ((cap.4.1, 4.2)<br />
*Lab.Threads de Aplicação<br />
<br />
=AULA 9 - Dia 28/08/2019=<br />
<br />
*Laboratório: Ainda Threads - Um escalonador semi-automático<br />
<br />
<br />
=AULA 10 - Dia 30/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Repassar um primeiro estudo sobre o RTOS<br />
*Revisar Processos e Threads<br />
<br />
==Questionário - Processos==<br />
<br />
#Conceitue processo. Descreva e explique cada uma das seções de um processo na memória.<br />
#Faça um diagrama e explique os possíveis estados de um processo no sistema. O que produz a transição entre estados?<br />
#O que é um Bloco de Controle de Processo? Quais informações ficam armazenadas neste bloco?<br />
#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.<br />
#Explique o que é multiprogramação e escalonamento de processos.<br />
#O que é a fila de processos prontos?<br />
#Diferencie um processo limitado por IO de um processo limitado por CPU.<br />
#Diferencie escalonamento de longo prazo de escalonamento de curto prazo.<br />
#Discuta o papel da interrupção na troca de contexto entre processos.<br />
#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?<br />
#Explique como funciona a chamada exec no UNIX/Linux<br />
#Explique como funciona a chamada wait no UNIX/Linux e como é possível retornar valores de um filho para o pai.<br />
#Faça um esqueleto de um programa UNIX/Linux que ao se tornar processo cria 3 filhos e espera pela execução dos mesmos.<br />
<br />
==Questionário - Comunicação entre Processos==<br />
<br />
#Diferenciar processos independentes de processos cooperantes.<br />
#Enumere e explique quatro razões para cooperação entre processos.<br />
#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.<br />
#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.<br />
#A memória compartilhada requer chamada ao sistema na sua operação? Discuta.<br />
#Por que o processo de troca de mensagem deve ser mais lento que a memória compartilhada?<br />
#Apresente em pseudocódigo uma proposta de funcionamento do problema do produtor consumidor usando memória compartilhada.<br />
#A construção de uma solução para o problema produtor consumidor pode ser facilitado pelo uso da memória compartilhada? Discuta.<br />
#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?<br />
#Enumere três métodos de implementação de uma lógica de ligação (link) entre processos.<br />
#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.<br />
#Descreva a variante assimétrica da troca direta de mensagens. O que muda em termos de primitiva de comunicação?<br />
#Descreva o problema de hard-coding associado a nomeação direta e como pode ser contornado através da nomeação/comunicação indireta?<br />
#O que é uma caixa postal? Como o Posix identifica uma caixa postal no caso de fila de mensagens?<br />
#Dois processos podem usar mais do que uma caixa postal para se comunicar? Qual a condição para que isto ocorra?<br />
#Descreva as duas operações básicas para a troca de mensagens com Caixa Postal.<br />
#Descreva na comunicação indireta via Caixa Postal as 3 propriedades básicas.<br />
#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.<br />
#De que forma a caixa postal estando no espaço de endereçamento de um processo (propriedade) afeta a recepção por mensagens? Descreva.<br />
#Quais as operações sobre uma caixa postal criada no espaço do sistema operacional deverão ser disponíveis? Descreva.<br />
#A transmissão de mensagem pode ser com e sem bloqueio. Descreva as 4 possibilidades (síncrona/assíncrona).<br />
#Discuta as 3 possibilidades de armazenamento de mensagens em buffer. Em que condições um remetente pode ser bloqueado?<br />
<br />
==ETAPA 1 - Projeto Final==<br />
<br />
*Apresentação (slides) sobre a parte de gerenciamento de tarefas no RTOS;<br />
*apresentação dia 18/09/2019<br />
<br />
==Referências==<br />
<br />
*[https://www.freertos.org/RTOS.html Site do FreeRTOS] ver Mastering the FreeRTOS Real Time Kernel - a Hands On Tutorial Guide <br />
*[https://www.embarcados.com.br/rtos-sistema-operacional-de-tempo-real/]<br />
*[https://github.com/feilipu/avrfreertos]<br />
<br />
=AULA 11 - Dia 4/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Pico de CPU X Pico de IO <br />
*Preempção X Não Preempção<br />
*Escalonamento de Processos: Escalonamento FCFS<br />
<br />
<br />
=AULA 12 - Dia 6/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Escalonamento de Processos: <br />
**Shortest Job First (preemptivo e não preemptivo)<br />
**Prioridade (preemptivo e não preemptivo)<br />
**Round-Robin: Preemptivo<br />
*Lab.Round Robin<br />
<br />
==Material de Referência==<br />
<br />
http://docente.ifsc.edu.br/andre.damato/sop2018/SOP2018-parte2.pdf<br />
<br />
<br />
=AULA 13 - Dia 13/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Sincronização entre Processos<br />
*Laboratório do Esquema de Peterson<br />
<br />
==Material de Referência==<br />
<br />
*Livro Silberchatz<br />
*https://www.os-book.com/OSE1/slide-dir/PPT-dir/ch6.ppt<br />
<br />
=AULA 14 - Dia 18/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Sincronização entre Processos<br />
*Lock de Hardware<br />
*Laboratório do TSL<br />
<br />
==Laboratório Proposto==<br />
<br />
*Refazer o problema proposto usando uma instrução simualada de test and set. Prever um liite superior para entrada de um processo na região crítica.<br />
<br />
==Material de Referência==<br />
<br />
*Livro Silberchatz<br />
*https://www.os-book.com/OSE1/slide-dir/PPT-dir/ch6.ppt<br />
<br />
<br />
=AULA 15 - Dia 20/08/2019=<br />
<br />
==O ATmega238 usado no Arduino UNO==<br />
<br />
Ver [https://pt.wikipedia.org/wiki/ATmega328]<br />
<br />
==O Arduino UNO==<br />
<br />
Ver [https://pt.wikipedia.org/wiki/Arduino]<br />
Ver [https://github.com/feilipu/Arduino_FreeRTOS_Library]<br />
<br />
==O FreeRtos para o Arduino==<br />
<br />
Ver [https://github.com/feilipu/Arduino_FreeRTOS_Library]<br />
<br />
Para instalar no IDE:<br />
*Baixar o ZIP do link acima<br />
*No IDE importar a biblioteca:<br />
**sketch->IncluirBiblioteca->Adicionar do arquivo ZIP<br />
<br />
<br />
==Código Experimental==<br />
<br />
Este código demonstra a ocorrência de "race condition".<br />
<br />
<syntaxhighlight lang=c><br />
// Code based on Examples of Arduino and examples <br />
// from https://github.com/feilipu/Arduino_FreeRTOS_Library<br />
<br />
#include <Arduino_FreeRTOS.h><br />
#include <FreeRTOSVariant.h><br />
#include <task.h><br />
#include <semphr.h><br />
<br />
#define TAM_BUFF 10<br />
<br />
volatile unsigned long race_flag=0xFFEEDDCC;<br />
volatile unsigned long int cont;<br />
int task_cont=0;<br />
<br />
void PrintSerial( void *pvParameters ); // Task para imprimir valor de race_flag<br />
void TaskBlink( void *pvParameters );<br />
void TaskSetarace_flag(void *pvParameters); //Task que atribui race_flag=0xFFEEDDCC<br />
void TaskZerarace_flag(void *pvParameters); //Task que atribui race_flag=0xAA0000AA<br />
<br />
// função de setup<br />
<br />
void setup() {<br />
<br />
Serial.begin(9600);<br />
<br />
while (!Serial) {<br />
; // wait for serial port to connect. Needed for native USB, on LEONARDO, MICRO, YUN, and other 32u4 based boards.<br />
}<br />
<br />
<br />
// criar as 2 tarefas<br />
<br />
xTaskCreate(<br />
TaskBlink<br />
, (const portCHAR *)"Blink" // A name just for humans<br />
, 128 // This stack size can be checked & adjusted by reading the Stack Highwater<br />
, NULL<br />
, 1 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.<br />
, NULL );<br />
<br />
xTaskCreate(<br />
TaskPrintSerial<br />
, (const portCHAR *) "PrintSerial"<br />
, 128 // Stack size<br />
, NULL<br />
, 1 // Priority<br />
, NULL );<br />
<br />
xTaskCreate(<br />
TaskSetarace_flag<br />
, (const portCHAR *) "Setarace_flag"<br />
, 128 // Stack size<br />
, NULL<br />
, 1 // Priority<br />
, NULL );<br />
<br />
xTaskCreate(<br />
TaskZerarace_flag<br />
, (const portCHAR *) "Zerarace_flag"<br />
, 128 // Stack size<br />
, NULL<br />
, 1 // Priority<br />
, NULL );<br />
<br />
cont = race_flag;<br />
<br />
// escalonador toma conta a partir daqui<br />
<br />
}<br />
<br />
void loop()<br />
{<br />
// nada a fazer aqui<br />
}<br />
<br />
/*--------------------------------------------------*/<br />
/*---------------------- Tasks ---------------------*/<br />
/*--------------------------------------------------*/<br />
<br />
void TaskBlink(void *pvParameters) // This is a task.<br />
{<br />
(void) pvParameters;<br />
<br />
/*<br />
Blink<br />
Turns on an LED on for one second, then off for one second, repeatedly.<br />
<br />
Most Arduinos have an on-board LED you can control. On the UNO, LEONARDO, MEGA, and ZERO <br />
it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN takes care <br />
of use the correct LED pin whatever is the board used.<br />
<br />
The MICRO does not have a LED_BUILTIN available. For the MICRO board please substitute<br />
the LED_BUILTIN definition with either LED_BUILTIN_RX or LED_BUILTIN_TX.<br />
e.g. pinMode(LED_BUILTIN_RX, OUTPUT); etc.<br />
<br />
If you want to know what pin the on-board LED is connected to on your Arduino model, check<br />
the Technical Specs of your board at https://www.arduino.cc/en/Main/Products<br />
<br />
This example code is in the public domain.<br />
<br />
modified 8 May 2014<br />
by Scott Fitzgerald<br />
<br />
modified 2 Sep 2016<br />
by Arturo Guadalupi<br />
*/<br />
<br />
// initialize digital LED_BUILTIN on pin 13 as an output.<br />
pinMode(LED_BUILTIN, OUTPUT);<br />
<br />
for (;;) // A Task shall never return or exit.<br />
{<br />
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)<br />
vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second<br />
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW<br />
vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second<br />
}<br />
}<br />
<br />
<br />
<br />
<br />
void TaskPrintSerial(void *pvParameters) // Task que imprime na serial - must be improved...<br />
{<br />
(void) pvParameters;<br />
/*<br />
<br />
*/<br />
<br />
<br />
for (;;)<br />
{ <br />
while (cont==0xAA0000AA || cont==0xFFEEDDCC)<br />
cont = race_flag;<br />
;<br />
<br />
Serial.println("Problemas: valor race_flag é");<br />
Serial.println(cont, HEX);<br />
<br />
vTaskDelay(5); // one tick delay (15ms) in between reads for stability - b<br />
cont = race_flag;<br />
}<br />
}<br />
<br />
void TaskSetarace_flag(void *pvParameters) <br />
{<br />
(void) pvParameters;<br />
const TickType_t xMaxBlockTimeTicks = 0x20;<br />
/*<br />
<br />
*/<br />
<br />
race_flag=0xAA0000AA;<br />
for (;;)<br />
{<br />
race_flag=0xAA0000AA;<br />
//Serial.println("Produtor");<br />
vTaskDelay( ( rand() %xMaxBlockTimeTicks) ); <br />
} <br />
<br />
}<br />
<br />
void TaskZerarace_flag(void *pvParameters) <br />
{<br />
(void) pvParameters;<br />
const TickType_t xMaxBlockTimeTicks = 0x20;<br />
/*<br />
<br />
*/<br />
race_flag=0xFFEEDDCC;<br />
<br />
for (;;)<br />
{<br />
race_flag=0xFFEEDDCC;<br />
vTaskDelay( ( rand() %xMaxBlockTimeTicks) ); <br />
if(task_cont++==100) {<br />
delay(1);<br />
Serial.println("Fim TaskZera - valor race_flag ");<br />
Serial.println(race_flag, HEX);<br />
for(;;);<br />
} <br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=AULA 16 - Dia 25/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Preparação de exemplos de RTOS sobre Arduíno para apresentação na sexta;<br />
<br />
=Laboratórios Propostos= <br />
<br />
Considere o código abaixo. Observe que a região de dados compartilhada shared_data é zerada pelo pai e setada pelo processo filho. O pai detecta inconsistências nos dados que operou. Tente corrigir usando o esquema de Peterson para acesso a região crítica. Crie uma função de entrada e de saída da região crítica.<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
<br />
<br />
#define BUFFER_SIZE 4096<br />
char *shared_data;<br />
char reference_data[BUFFER_SIZE];<br />
<br />
main()<br />
{ <br />
key_t key;<br />
int shmid;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, BUFFER_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
shared_data = shmat(shmid, (void *)0, 0);<br />
<br />
if (shared_data == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int count=0; <br />
memset(reference_data,0,BUFFER_SIZE); <br />
for(;;){ <br />
memset(shared_data,0,BUFFER_SIZE);<br />
if (memcmp(shared_data, reference_data, BUFFER_SIZE)!=0) {<br />
count++;<br />
if (count%1000000==0)<br />
printf("Processo pai detectou algo errado nos dados %d\n", count); <br />
} <br />
} <br />
<br />
<br />
}<br />
else { /*Child code */<br />
<br />
for(;;){ <br />
memset(shared_data,1,BUFFER_SIZE); <br />
}<br />
<br />
}<br />
<br />
if (shmdt(shared_data) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
Possível solução:<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
#include <unistd.h><br />
<br />
#define BUFFER_SIZE 4096<br />
#define ID_PAI 0<br />
#define ID_FILHO 1<br />
#define FALSE 0<br />
#define TRUE 1<br />
<br />
char *shared_data;<br />
char reference_data[BUFFER_SIZE];<br />
<br />
struct tipo_peterson{<br />
char flag[2];<br />
char turn;<br />
} *pet_struct;<br />
<br />
void ent_sec_crit(int id)<br />
{<br />
char id_outro = (id+1)%2;<br />
<br />
pet_struct->flag[id] = TRUE; // indica que o processo deseja entrar na região crítica<br />
pet_struct->turn = id_outro; // o processo sinaliza para o outrao entrar, <br />
// caso o outro esteja entrando<br />
// este ponto é uma race condition: turn pode ser 0 ou 1 <br />
while ( (pet_struct->flag[id_outro]==TRUE) && (pet_struct->turn == id_outro) )<br />
;<br />
}<br />
<br />
void sai_sec_crit(int id)<br />
{<br />
pet_struct->flag[id] = FALSE;<br />
}<br />
<br />
int main()<br />
{ <br />
key_t key;<br />
int shmid;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, BUFFER_SIZE+sizeof(struct tipo_peterson), S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
shared_data = shmat(shmid, (void *)0, 0);<br />
pet_struct = (struct tipo_peterson *) (shared_data + BUFFER_SIZE); <br />
<br />
if (shared_data == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int count=0; <br />
memset(reference_data,0,BUFFER_SIZE); <br />
for(;;){ <br />
ent_sec_crit(ID_PAI);<br />
memset(shared_data,0,BUFFER_SIZE);<br />
if (memcmp(shared_data, reference_data, BUFFER_SIZE)!=0) {<br />
count++;<br />
if (count%1000000==0)<br />
printf("Processo pai detectou algo errado nos dados %d\n", count); <br />
} <br />
sai_sec_crit(ID_PAI);<br />
} <br />
<br />
<br />
}<br />
else { /*Child code */<br />
<br />
for(;;){<br />
ent_sec_crit(ID_FILHO); <br />
memset(shared_data,1,BUFFER_SIZE);<br />
sai_sec_crit(ID_FILHO); <br />
}<br />
<br />
}<br />
<br />
if (shmdt(shared_data) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
=AULA 17 - Dia 27/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Apresentação dos Trabalhos<br />
*Definição da próxima etapa<br />
<br />
=AULA 18 - Dia 02/10/2019=<br />
<br />
==Objetivos==<br />
<br />
*Semáforos, Deadlock e o Problema da Inversão de Prioridade<br />
*Laboratório de Pthreads e Mutex;<br />
<br />
==Laboratório Proposto==<br />
<br />
*Lab. Programação concorrente - Parte 1<br />
<br />
==Materia de Referência==<br />
<br />
*[https://www.os-book.com/OSE1/slide-dir/PDF-dir/ch6.pdf]<br />
<br />
==Desafio==<br />
<br />
Usar <br />
ps -T aux | grep ex1vA<br />
<br />
Para ver os threads dormindo...<br />
<br />
Otimizar o programa abaixo<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <pthread.h><br />
#include <stdlib.h><br />
#include <unistd.h><br />
#include <time.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
pthread_mutex_t mut;<br />
<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
<br />
<br />
long long i;<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
usleep(5000000);<br />
printf("Novo saldo = %d\n",novo_saldo);<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d\n", (i+1));<br />
exit(-1);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
printf("Saldo final é %d\n", saldo);<br />
}<br />
</syntaxhighlight><br />
<br />
=AULA 19 - Dia 04/10/2019=<br />
<br />
==Objetivos==<br />
<br />
*Ainda Semáforos, Deadlock e o Problema da Inversão de Prioridade<br />
*Laboratório de Pthreads com semáforo binário;<br />
*Laboratório de Pthreads com semáforos contador como solução do problema do produtor e consumidor.<br />
<br />
<br />
==Material de Referência==<br />
<br />
*ver laboraratório de Programação concorrente<br />
<br />
==Laboratório Proposto==<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Programação concorrente}}<br />
<br />
== Programação concorrente ==<br />
<br />
<br />
===PARTE 1 - Mutex e Biblioteca libpthreads===<br />
<br />
;POSIX Threads<br />
A 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):<br />
*''pthread_create'': cria uma thread;<br />
*''pthread_kill'': força a terminação de uma thread;<br />
*''pthread_join'': sincroniza o final de uma thread (qual a diferença/semelhança com o ''wait'' que usamos para processos?);<br />
*''pthread_exit'': finaliza uma thread.<br />
Para utilizar estas funções é necessário linkar o programa à libpthread (''-lpthread''). <br />
<br />
<br />
;POSIX pthread mutex<br />
<br />
A biblioteca pthread implementa um tipo ''pthread_mutex_t'', que garante a exclusão mútua entre threads. Estes mutex são manipulados através das funções (acesse as man-pages das chamadas para maiores detalhes):<br />
*''pthread_mutex_lock'': acessa um mutex.<br />
*''pthread_mutex_trylock'': tenta acessar um mutex (retorna valor indicando sucesso ou falha no lock).<br />
*''pthread_mutex_unlock'': libera um mutex.<br />
<br />
<br />
<br />
;Exercício 1<br />
<br />
O programa abaixo cria 5 threads, e cada uma destas threads atualiza uma variável global (memória compartilhada).<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
#include <pthread.h><br />
#include <stdlib.h><br />
#include <unistd.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
pthread_mutex_t mut;<br />
<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
long long i;<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
sleep(1);<br />
printf("Novo saldo = %d\n",novo_saldo);<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d\n", (i+1));<br />
exit(-1);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
printf("Saldo final é %d\n", saldo);<br />
}<br />
</syntaxhighlight><br />
<br />
# Compile este programa. <br />
# Execute este programa várias vezes. Ele funciona? Será que ele gera as saídas esperadas?<br />
# Identifique as '''seções críticas''' do programa.<br />
# Corrija o programa utilizando '''mutex'''. <br />
# Analise a função ''AtualizaSaldo()'' com a sua solução. Lembre-se que o uso do mutex implica em apenas uma thread acessar a seção crítica por vez, enquanto outras threads ficam bloqueadas, esperando. Disso vem que, quanto menor o trecho de código entre um ''lock'' e um ''unlock'', menos tempo uma thread necessita ficar esperando.<br />
<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <cstring><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
<br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
sem_t sem;<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
int value;<br />
sem_wait(&sem);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
sem_getvalue(&sem, &value);<br />
printf("valor sem = %d\n", value);<br />
sem_post(&sem);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
sem_init(&sem,0,1);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
sem_destroy(&sem);<br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
===PARTE 2 - POSIX Semaphores Binários===<br />
<br />
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):<br />
*''sem_init'': inicializa um semáforo;<br />
*''sem_destroy'': destroy um semáforo;<br />
*''sem_wait'': implementa a operação ''p'';<br />
*''sem_post'': implementa a operação ''v''.<br />
Para utilizar estas funções é necessário linkar o programa à librt ou à libpthread (''-lrt'' ou ''-lpthread'').<br />
<br />
;Exercício 1<br />
Modifique o programa para usar um semáforo binário ao invés de um mutex em sua solução.<br />
<br />
;Exercício 2 - Fazer em casa<br />
Refaça o exercício 3 usando processos criados com fork e exec. O semáforo deve ser criado em uma região de memória compartilhada.<br />
<br />
===PARTE 3 - POSIX Semaphores===<br />
<br />
;Exercício 3<br />
Implemente com pthreads e semáforos/mutex a solução do produtor/comsumidor conforme sugerido no livro do Silberchatz. USe dois semáforos: (i) um para controlar o numero de itens vazios no buffer (semáforo empty - quando zero o thread produtor deve parar de produzir). (ii) um semáforo para controlar o numero de itens ocupados no buffer (semáforo full - quando zero o consumidor deve parar de consumir).<br />
<br />
<br />
===PARTE 4 - POSIX Semaphores===<br />
<br />
;Exercício 4<br />
<br />
O programa abaixo manipula uma matriz de tamanho MxN (veja os defines para o tamanho da matriz). A função ''SumValues'' soma todos os valores em uma linha da matriz. A linha a ser somada é identificada pela variável ''i''. Modifique o programa principal (''main'') nos locais indicados para:<br />
# Criar N threads, uma para somar os valores de cada linha.<br />
# Receber o resultado do somatório de cada linha e gerar o somatório total da matriz.<br />
# Analise o programa: há problemas de sincronização que precisam ser resolvidos? Se sim, resolva-os.<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include "thread.h"<br />
<br />
/* number of matrix columns and rows */<br />
#define M 5<br />
#define N 10<br />
<br />
using namespace std;<br />
<br />
int matrix[N][M];<br />
Thread *threads[N];<br />
<br />
<br />
/* thread function; it sums the values of the matrix in the row */<br />
int SumValues(int i)<br />
{<br />
int n = i; /* number of row */<br />
int total = 0; /* the total of the values in the row */<br />
int j;<br />
for (j = 0; j < M; j++) /* sum values in the "n" row */<br />
total += matrix[n][j];<br />
cout << "The total in row" << n << " is " << total << "." << endl;<br />
/* terminate a thread and return a total in the row */<br />
exit(total);<br />
}<br />
<br />
int main(int argc, char *argv[])<br />
{<br />
int i, j;<br />
int total = 0; /* the total of the values in the matrix */<br />
<br />
/* initialize the matrix */<br />
for (i = 0; i < N; i++)<br />
for (j = 0; j < M; j++)<br />
matrix[i][j] = i * M + j;<br />
<br />
/* create threads */<br />
/* COLOQUE SEU CÓDIGO PARA CRIAR AS THREADS AQUI! */<br />
<br />
/* wait for terminate a threads */<br />
/* COLOQUE SEU CÓDIGO PARA PEGAR O SOMATÓRIO DE LINHAS E TOTALIZAR A SOMA DA MATRIZ AQUI! */<br />
<br />
cout << "The total values in the matrix is " << total << endl;<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
{{collapse bottom}}<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Escalonamento Round Robin e FCFS para Threads"}}<br />
<br />
== Escalonamento Round-Robin ==<br />
<br />
OBS: ver https://www.quora.com/What-exactly-does-typedef-do-in-C<br />
<br />
O Exemplo abaixo mostra a implementação de um esquema de escalonamento Round Robin do exercício anterior.<br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
Modificado por Eraldo <br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 5<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
void runA(void) {<br />
for (;;) {<br />
printf("running A\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runB(void) {<br />
for (;;) {<br />
printf("running B\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 1<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
<br />
void scheduler_rr();<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void yield_thread()<br />
{<br />
scheduler_rr();<br />
}<br />
<br />
void delete_thread()<br />
{<br />
delete curr_thread;<br />
curr_thread=NULL;<br />
scheduler_rr();<br />
}<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
struct delta{<br />
long alfa;<br />
char epson[1000];<br />
long beta;<br />
} shar;<br />
<br />
int turn;<br />
int flag[2];<br />
<br />
#define TRUE 1<br />
#define FALSE 0<br />
<br />
void ent_rc(int p, int vt)<br />
{<br />
flag[p]=TRUE;<br />
turn = vt;<br />
if(p) p=0; else p=1;<br />
while (flag[p] && turn == vt);<br />
//printf("Thread %d: esperando para acessar a região crítica\n", p);<br />
}<br />
<br />
void sai_rc(int p)<br />
{<br />
flag[p]=FALSE;<br />
}<br />
<br />
void runA(void) {<br />
struct delta x = {0, 100};<br />
<br />
for (;;) {<br />
x.alfa=0;x.beta=0;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0);<br />
x.alfa=100;x.beta=100;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0); <br />
}<br />
}<br />
<br />
void runB(void) {<br />
<br />
for (;;) {<br />
ent_rc(1,0);<br />
printf("shar alfa = %ld shar beta = %ld \n",shar.alfa, shar.beta); // regiao crítica<br />
sai_rc(1);<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runC(void) {<br />
int i;<br />
for (i=0;i<10;i++) {<br />
printf("Thread C - parte 1\n");<br />
yield_thread();<br />
printf("Thread C - parte 2\n");<br />
yield_thread();<br />
}<br />
delete_thread();<br />
}<br />
<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
add_thread(runC);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
{{collapse bottom}}<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Um escalonador semi-automático"}}<br />
<br />
== Ainda Threads - Um escalonador semi-automático usando sinais ==<br />
<br />
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.<br />
<br />
===Exemplo 1:===<br />
<br />
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. <br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
<br />
void sig_handler(int signo)<br />
{<br />
int x;<br />
printf("Turma de SOP: recebido SIGUSR1\n");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
// Loop eterno dormindo 1s<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Fazer no terminal:<br />
ps aux<br />
anotar o pid do processo e enviar o sinal:<br />
kill -USR1 pid<br />
<br />
===Exemplo 2:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// loop eterno que nunca é executado<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Enviar o sinal USR1 para ver o efeito. <br />
<br />
===Exemplo 3:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void prepara_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void prepara_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
prepara_contexto_ping();<br />
prepara_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// A long long wait so that we can easily issue a signal to this process<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Exercício: Use o comando htop para verificar como estes threads são vistos pelo SOP.<br />
<br />
Exercício: Tente analisar as pilhas dos threads e verificar sob qual pilha o handler se executa.<br />
<br />
<br />
===Exercício 4:===<br />
<br />
Neste ponto associamos um timer ao handler com o apoio do sinal ALRM. Agora os threads são escalonados automaticamente.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
===Exercício Proposto 5===<br />
<br />
Colocar 3 threads rodando.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void preparar_contexto_ping(ucontext_t *pContext, char *p)<br />
{<br />
char *stack;<br />
<br />
getcontext(pContext);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
(*pContext).uc_stack.ss_sp = stack ;<br />
(*pContext).uc_stack.ss_size = STACKSIZE;<br />
(*pContext).uc_stack.ss_flags = 0;<br />
(*pContext).uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(pContext, (void*)(*f_ping), 1, p);<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping(&cPing, "ping");<br />
preparar_contexto_ping(&cPong, "pong");<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Threads de aplicação}}<br />
<br />
== Threads de aplicação ==<br />
<br />
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:<br />
*'''getcontext(&a)''': salva o contexto na variável '''a''';<br />
*'''setcontext(&a)''': restaura um contexto salvo anteriormente na variável '''a''';<br />
*'''swapcontext(&a,&b)''': salva o contexto atual na variável '''a''' e restaura o contexto salvo anteriormente na variável '''b''';<br />
*'''makecontext(&a, ...)''': ajusta parâmetros internos do contexto salvo em '''a''';<br />
*'''ucontext_t''': as variáveis '''a''' e '''b''' são do tipo '''ucontext_t'''. Este tipo armazena um contexto.<br />
<br />
Busque mais informações sobre estas funções utilizando o programa manpage do Linux (ex.: man getcontext).<br />
<br />
Estude o código no arquivo pingpong.c abaixo e explique seu funcionamento.<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
*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.<br />
*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.<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain, cFnew;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_new(void * arg1, void * arg2,void * arg3,void * arg4) <br />
{<br />
printf ("%s: Primeira string %s %s %s\n",(char*) arg1,(char*) arg2,(char*) arg3, (char*) arg4);<br />
swapcontext(&cFnew, &cMain); <br />
}<br />
<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
<br />
getcontext(&cFnew);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cFnew.uc_stack.ss_sp = stack ;<br />
cFnew.uc_stack.ss_size = STACKSIZE;<br />
cFnew.uc_stack.ss_flags = 0;<br />
cFnew.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cFnew, (void*)(*f_new), 4, "\tF_new", "\tAlo", "\tMundo","\tReal");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
swapcontext(&cMain, &cFnew);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
--><br />
Exercício 3: O que acontece se um dos threads é colocado para dormir? Todos os demais threads param a sua execução.<br />
<br />
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/<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Processos no Linux}}<br />
<br />
== Processos no Linux - Modificado por Eraldo ==<br />
<br />
<blockquote style="background: lime; border: 1px solid black; padding: 1em;"><br />
Processos no Linux<br />
</blockquote><br />
<br />
*Exercícios propostos pelo Prof.Arliones e Modificados por Eraldo<br />
<br />
<br />
[[imagem:DesenhoForkExec.png|border|650px]]<br />
<br />
<br />
;Syscall FORK<br />
<br />
* Em um terminal, execute "man fork"<br />
** 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'''.<br />
** O '''código''' dos dois processos (pai e filho) são '''idênticos''';<br />
** Os '''dados''' dos dois processos (pai e filho) são '''idênticos NO MOMENTO DA CRIAÇÃO''';<br />
** Execução do processo filho inicia na próxima instrução do programa (no retorno da chamada FORK);<br />
** Não é possível saber qual dos processos (pai ou filho) retormará a execução primeiro - isto fica a cargo do excalonador do SO;<br />
** Valores de retorno da chamada FORK:<br />
*** (-1): erro na criação do processo (ex.: memória insuficiente);<br />
*** (0): em caso de sucesso, este é o valor de retorno recebido pelo processo filho;<br />
*** (>0): em caso de sucesso, este é o valor de retorno recebido pelo processo pai;<br />
<br />
;Syscall JOIN<br />
<br />
* A syscall JOIN é implementada no POSIX pela função '''wait()'''. Execute "man wait".<br />
** Além da função '''wait()''', há também '''waitpid()''' e '''waitid()''';<br />
** 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);<br />
** A chamada wait também libera os recursos do processo filho que termina;<br />
** '''wait()''': esta função suspende a execução do processo chamador até que UM DOS SEUS FILHOS finalize;<br />
** '''waitpid()''': suspende a execução do processo chamador até que UM FILHO ESPECÍFICO finalize;<br />
<br />
;Syscall EXEC<br />
<br />
* A syscall EXEC é implementada no POSIX pela família de funções '''exec()'''. Execute "man exec".<br />
** As principais funções da família são '''execl()''', '''execlp()''' e '''execvp()''';<br />
** 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;<br />
** 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;<br />
<br />
<br />
;Exemplos POSIX utilizando fork/wait/exec<br />
<br />
*Exemplo 1: fork/wait básico<br />
<syntaxhighlight lang=c><br />
// ex1: fork/wait básico<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
printf("processo filho\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
printf("processo pai\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
arliones@socrates:~/tmp$ gcc ex1.c -o ex1 <br />
arliones@socrates:~/tmp$ ./ex1 <br />
processo filho pid: 27858 pid pai: 27857<br />
processo pai pid: 27857 pid pai: 5337<br />
arliones@socrates:~/tmp$ <br />
</syntaxhighlight><br />
<br />
* Exemplo 2: processos pai e filho compartilham código, mas não dados.<br />
<syntaxhighlight lang=c><br />
// ex2: fork/wait "compartilhando" dados<br />
// ex2: fork/wait "compartilhando" dados<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status, k=0;<br />
printf("processo %d\t antes do fork\n", getpid());<br />
pid = fork();<br />
printf("processo %d\t depois do fork\n", getpid());<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
k += 1000;<br />
printf("processo filho\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status); // espera o filho terminar<br />
k += 10;<br />
printf("processo pai\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
k += 1000;<br />
printf("FIM processo %d\t K: %d\n", getpid(), k); <br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
processo 17056 antes do fork<br />
processo 17056 depois do fork<br />
processo 17057 depois do fork<br />
processo filho pid: 17057 K: 1000 endereço K: 0x7ffd8923e318<br />
processo pai pid: 17056 K: 10 endereço K: 0x7ffd8923e318<br />
</syntaxhighlight><br />
<br />
* Modificação no código: comentar linhas 23 e 30<br />
<br />
<syntaxhighlight lang=bash><br />
<br />
</syntaxhighlight><br />
<br />
* Analise os resultados e busque entender a diferença.<br />
*Perguntas e desafios.:<br />
#Analisando os valores impressos de k pode-se dizer que os dados são compartilhados entre os dois processos?<br />
#O endereço de k impresso é o mesmo nos dois processos. ISto não contradiz a afirmação anterior?<br />
#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.<br />
<br />
<br />
;Exercício fork/wait<br />
<br />
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.<br />
<br />
*Use o comando pstree para verificar a árvore de processos criada.<br />
<br />
{{collapse top|Solução}}<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
<!--<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
--><br />
<br />
;DESAFIO: fork/wait<br />
<br />
Reimplementar o exercício anterior de criação de uma árvore de 3 processos, generalizando a criação de N processos onde N é repassado na linha de comando do programa. SUGESTÃO: usar um comando for, mas lembrar que se existe um fork dentro do for, então cada filho gerado dará continuidade a execução do for. É necessário que o processo faça um exit ou retorne neste momento.<br />
<br />
;DESAFIO: Exercício status/wait<br />
<br />
O ''status'' passado como parâmetro à função ''wait(&status)'' é, na verdade, o mecanismo de retorno de resultado do ''wait/waitpid''. Ao retornar, esta variável contém informações sobre o resultado da execução do processo filho. Por exemplo, se um processo terminou normalmente (i.e., chamou ''exit''), o comando ''WIFEXITED(status)'' retorna ''true''. Este comando retorna ''false'' se o processo foi abortado (e.g., ''segmentation fault'') ou morto (e.g., ''kill''). Investigue no manual do wait no Linux (''man wait'') o funcionamento do comando WEXITSTATUS(status). <br />
Imagine um problema de busca de dados armazenados na forma de uma matriz de inteiros 4x30. Você está interessado em saber quantas ocorrências de um determinado número existe em cada linha da matriz. Note que que são tarefas que podem ser paralelizadas e usufruir de um sistema capaz de executá-las em paralelo. Faça uma implementação paralelizando 4 processos filhos a partir de um pai, onde cada processo é responsável por uma busca. A quantidade de ocorrências do número buscado é retornada e capturada através de WEXITSTATUS.<br />
<br />
;Syscall EXEC<br />
<br />
*Exemplo exec()<br />
<br />
<syntaxhighlight lang=c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
execl("/bin/ls","ls","-l", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 1: Modificar o código para mostrar que o exec() não retorna (colocar um printf após o exec).<br />
<br />
*Exercício 2: Criar um exemplo (dois programas ) para demonstrar que o exec não cria novo processo. <br />
**Crie um primeiro programa (prog1) que imprime o seu pid e depois faz um exec do segundo programa.<br />
**Crie o segundo programa que simplesmente imprime o pid.<br />
<br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU ANTES DO EXEC: Meu pid é %d\n", getpid());<br />
execl("./prog2","prog2", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU DEPOIS DO EXEC:Meu pid é %d\n", getpid());<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 3: Criar um exemplo usando fork/exec mostrando que um processo pai cria um filho e espera por sua execução. O filho executa o comando "ps aux". Ambos devem mostrar seus pids.<br />
<br />
{{collapse bottom}} <br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Laboratório Memória Compartilhada entre Pai e Filho - Produtor Consumidor}}<br />
<br />
Baseado no Lab. do Prof.Arliones<br />
<br />
=== Objetivo ===<br />
<br />
*Familiarizar o aluno com o conceito de Memória Compartilhada entre Processos Pai e Filho<br />
*Familizarizar o aluno com o conceito de Produtor Consumidor<br />
<br />
=== Referencial Teórico-Prático ===<br />
<br />
* Silberchatz - 3.4 e 3.5<br />
* man nos comandos shmat e shmget<br />
<br />
=== Exemplo de Funcionamento ===<br />
<br />
No exemplo abaixo um processo pai compartilha uma área de memória com o processo filho. O processo filho escreve uma mensagem para o pai na área de memória compartilhada e termina. O processo pai é desbloqueado no wait e imprime a mensagem escrita.<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
char *ptr_msg = "alo pai, tudo bem?"; <br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
strcpy(segmento, ptr_msg);<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(&filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
=== Desafio a ser Implementado em Sala ===<br />
<br />
Construir um programa em que um processo pai atua como produtor e o processo filho atua como consumidor. O buffer circular compartilhado é um buffer de inteiro de tamanho 5. O pai alimentará o buffer com 50 itens gerados aleatóriamente entre 1 e 100. A cada escrita/leitura no buffer o produtor/consumidor deve esperar alguns milisegundos de forma a acontecer situações de buffer cheio e vazio. <br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
#include <unistd.h><br />
#include <time.h><br />
#include <sys/types.h><br />
#include <sys/wait.h><br />
<br />
<br />
<br />
#define SHM_SIZE 1024 <br />
<br />
#define BUFF_COMP_SIZE 5<br />
<br />
struct buff_comp {<br />
int buffer[BUFF_COMP_SIZE];<br />
int in,out;<br />
};<br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
struct buff_comp *p; <br />
<br />
/* initialize random seed: */<br />
srand ( time(NULL) );<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
p = (struct buff_comp *) shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
p->out = p->in = 0;<br />
<br />
if((filho = fork()) == -1)<br />
{<br />
<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
int i;<br />
for(i=0;i<50;i++) {<br />
while (p->in==p->out) {<br />
printf("FILHO: BUFFER VAZIO !!!!!!!\n");<br />
usleep(rand() % 10000 + 1);<br />
}<br />
printf("FILHO: item lido = %d\n", p->buffer[p->out]);<br />
p->out = (p->out+1)%BUFF_COMP_SIZE;<br />
}<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
int i; <br />
<br />
for(i=0;i<50;i++) {<br />
while (((p->in+1)%BUFF_COMP_SIZE) == p->out) {<br />
printf("PAI: BUFFER CHEIO !!!!!!!\n");<br />
usleep(rand() % 10000 + 1);<br />
}<br />
p->buffer[p->in] = rand() % 100 + 1;<br />
printf("PAI: item produzido = %d\n", p->buffer[p->in]);<br />
p->in = (p->in+1)%BUFF_COMP_SIZE;<br />
<br />
}<br />
wait(&filho); <br />
<br />
}<br />
<br />
<br />
if (shmdt(p) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Trocas de mensagens com pipes}}<br />
<br />
= Trocas de mensagens com pipes =<br />
<br />
;Troca de mensagens<br />
Um mecanismo disponibilizado por sistemas UNIX para troca de mensagens entre processos é o PIPE. Pipes são mecanismos de comunicação indireta onde mensagens são trocadas através de ''mailboxes''. Cada ''mailbox'' possui um identificador único, permitindo que processos identifiquem o canal de comunicação entre eles. O fluxo de mensagens em um Pipe é:<br />
*'''unidirecional''': sobre um mesmo pipe, apenas um processo envia mensagens e um processo recebe mensagens;<br />
*'''FIFO''': as mensagens são entregues na ordem de envio;<br />
*'''não-estruturado''': não há estrutura pré-definida para o formato da mensagem.<br />
No UNIX, pipes são inicializados através da '''SystemCall''' ''pipe'', que possui a seguinte sintaxe:<br />
*''int pipe(int pipefd[2])'': ''pipe'' inicializa um novo pipe no sistema e retorna, no array pipefd, os descritores identificando cada uma das pontas do pipe. A primeira posição do array, i.e. pipefd[0], recebe o descritor que pode ser aberto apenas para leitura, enquanto a segunda posição do array, i.e. pipefd[1], recebe o descritor que pode ser aberto apenas para escrita. A função retorna zero no caso de sucesso, ou -1 se ocorrer erro.<br />
As primitivas send/receive para uso de um pipe no UNIX são implementadas por '''SystemCalls''' read/write, conforme segue:<br />
*''ssize_t read(int fd, void *buf, size_t count)'': “puxa” dados do pipe identificado pelo descritor fd. Os dados recebidos são os apontados pelo ponteiro buf, sendo count a quantidade máxima de bytes a serem recebidos. A função retorna o número de bytes recebidos.<br />
*''ssize_t write(int fd, const void *buf, size_t count)'': “empurra” dados no pipe identificado pelo descritor fd. Os dados transmitidos são os apontados pelo ponteiro buf, sendo count a quantidade de bytes a serem transmitidos. A função retorna o número de bytes transmitidos.<br />
<br />
*Exemplo 1: Transmitindo e recebendo pelo próprio processo<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main()<br />
{<br />
int fd[2];<br />
char *ptr = "Alo eu mesmo";<br />
char *ptr_alvo;<br />
int tamanho_dados, ret;<br />
<br />
tamanho_dados = strlen(ptr)+1;<br />
<br />
if (pipe(fd)==-1){<br />
printf ("erro criação pipe\n");<br />
exit(-1);<br />
}<br />
printf("Transmitido %d bytes\n", tamanho_dados);<br />
write (fd[1], ptr, tamanho_dados);<br />
<br />
ptr_alvo = malloc(tamanho_dados);<br />
<br />
ret=read(fd[0],ptr_alvo,tamanho_dados);<br />
<br />
printf("ret = %d dados => %s\n", ret, ptr_alvo); <br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
*Exemplo 2: Abaixo há um exemplo de programa criando um pipe e compartilhando os descritores entre dois processos (criados via ''fork()'').<br />
<syntaxhighlight lang=c><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
<br />
char *message = "This is a message!!!" ;<br />
<br />
main()<br />
{<br />
char buf[1024] ;<br />
int fd[2];<br />
pipe(fd); /*create pipe*/<br />
if (fork() != 0) { /* I am the parent */<br />
write(fd[1], message, strlen (message) + 1) ;<br />
}<br />
else { /*Child code */<br />
read(fd[0], buf, 1024) ;<br />
printf("Got this from MaMa!!: %s\n", buf) ;<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
*'''Exercício 1: construa um “pipeline”'''. Crie um programa que conecta 4 processos através de 3 pipes. Utilize ''fork()'' para criar vários processos.<br />
<br />
<syntaxhighlight lang=cpp><br />
<br />
//Solução possível<br />
<br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
pipe(fd);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
<br />
</syntaxhighlight><br />
<br />
*'''Exercício 2: Modifique o exercício anterior para que o processo D, através de um novo pipe, mande uma mensagem diretamente para o pai de todos.<br />
<br />
<!--<br />
<code><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
int fd_retorno[2];<br />
<br />
pipe(fd);<br />
pipe(fd_retorno);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size);<br />
read(fd_retorno[0], buf, size);<br />
printf("PAI:%s\n", buf); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
char *ptr_msg_ret="Ok msg de D para o pai";<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
write(fd_retorno[1],ptr_msg_ret,strlen(ptr_msg_ret)+1);<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
*'''Exercício 3: Consultor de Login de Acesso:'''. Estude o link https://www.geeksforgeeks.org/named-pipe-fifo-example-c-program/ e projete um programa cliente servidor da seguinte forma: (i) O servidor possui uma tabela de usuários (userid). O user_id é de tamanho fixo de 7 caracteres. O servidor espera por consultas para verificar se um usuário está na tabela. Se estiver responde com o caracter 'S' senão com 'N'. (ii) O cliente espera por user_id no teclado e consulta o servidor sobre sua existência na tabela. O cliente imprime na tabela a existência ou não do usuário.<br />
<br />
*'''Exercício 4: cópia de arquivo'''. Projete um programa de cópia de arquivos chamado FileCopy usando pipes comuns. Esse programa receberá dois parâmetros: o primeiro é o nome do arquivo a ser copiado e o segundo é o nome do arquivo copiado. Em seguida, o programa criará um pipe comum e gravará nele o conteúdo do arquivo a ser copiado. O processo filho lerá esse arquivo do pipe e o gravará no arquivo de destino. Por exemplo, se chamarmos o programa como descrito a seguir:<br />
:<syntaxhighlight lang=bash><br />
$ FileCopy entrada.txt copia.txt<br />
</syntaxhighlight><br />
:o arquivo ''entrada.txt'' será gravado no pipe. O processo filho lerá o conteúdo desse arquivo e o gravará no arquivo de destino ''copia.txt''. Escreva o programa usando os pipes da API POSIX no Linux.<br />
<br />
<br />
{{collapse bottom}}<br />
<br />
=Laboratórios Disponíveis= <br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Escalonamento Round Robin e FCFS para Threads"}}<br />
<br />
<br />
== Escalonamento Round-Robin preemptivo ==<br />
<br />
OBS: ver https://www.quora.com/What-exactly-does-typedef-do-in-C<br />
<br />
A fazer: <br />
<br />
*primitiva de término de processo (destrutor do objeto); <br />
*primitiva de yield<br />
*isolar o escalonador em uma função;<br />
*isolar o dispatcher em uma função; <br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
Modificado por Eraldo <br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 5<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
void runA(void) {<br />
for (;;) {<br />
printf("running A\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runB(void) {<br />
for (;;) {<br />
printf("running B\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 1<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
<br />
void scheduler_rr();<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void yield_thread()<br />
{<br />
scheduler_rr();<br />
}<br />
<br />
void delete_thread()<br />
{<br />
delete curr_thread;<br />
curr_thread=NULL;<br />
scheduler_rr();<br />
}<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
struct delta{<br />
long alfa;<br />
char epson[1000];<br />
long beta;<br />
} shar;<br />
<br />
int turn;<br />
int flag[2];<br />
<br />
#define TRUE 1<br />
#define FALSE 0<br />
<br />
void ent_rc(int p, int vt)<br />
{<br />
flag[p]=TRUE;<br />
turn = vt;<br />
if(p) p=0; else p=1;<br />
while (flag[p] && turn == vt);<br />
//printf("Thread %d: esperando para acessar a região crítica\n", p);<br />
}<br />
<br />
void sai_rc(int p)<br />
{<br />
flag[p]=FALSE;<br />
}<br />
<br />
void runA(void) {<br />
struct delta x = {0, 100};<br />
<br />
for (;;) {<br />
x.alfa=0;x.beta=0;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0);<br />
x.alfa=100;x.beta=100;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0); <br />
}<br />
}<br />
<br />
void runB(void) {<br />
<br />
for (;;) {<br />
ent_rc(1,0);<br />
printf("shar alfa = %ld shar beta = %ld \n",shar.alfa, shar.beta); // regiao crítica<br />
sai_rc(1);<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runC(void) {<br />
int i;<br />
for (i=0;i<10;i++) {<br />
printf("Thread C - parte 1\n");<br />
yield_thread();<br />
printf("Thread C - parte 2\n");<br />
yield_thread();<br />
}<br />
delete_thread();<br />
}<br />
<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
add_thread(runC);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Um escalonador semi-automático"}}<br />
<br />
== Ainda Threads - Um escalonador semi-automático usando sinais ==<br />
<br />
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.<br />
<br />
===Exemplo 1:===<br />
<br />
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. <br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
<br />
void sig_handler(int signo)<br />
{<br />
int x;<br />
printf("Turma de SOP: recebido SIGUSR1\n");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
// Loop eterno dormindo 1s<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Fazer no terminal:<br />
ps aux<br />
anotar o pid do processo e enviar o sinal:<br />
kill -USR1 pid<br />
<br />
===Exemplo 2:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// loop eterno que nunca é executado<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Enviar o sinal USR1 para ver o efeito. <br />
<br />
===Exemplo 3:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void prepara_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void prepara_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
prepara_contexto_ping();<br />
prepara_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// A long long wait so that we can easily issue a signal to this process<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
Exercício: Tente analisar as pilhas dos threads e verificar sob qual pilha o handler se executa.<br />
<br />
===Exercício 4:===<br />
<br />
Neste ponto associamos um timer ao handler com o apoio do sinal ALRM. Agora os threads são escalonados automaticamente.<br />
<br />
<code><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void preparar_contexto_ping(ucontext_t *pContext, char *p)<br />
{<br />
char *stack;<br />
<br />
getcontext(pContext);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
(*pContext).uc_stack.ss_sp = stack ;<br />
(*pContext).uc_stack.ss_size = STACKSIZE;<br />
(*pContext).uc_stack.ss_flags = 0;<br />
(*pContext).uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(pContext, (void*)(*f_ping), 1, p);<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping(&cPing, "ping");<br />
preparar_contexto_ping(&cPong, "pong");<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Um Exemplo de Uso "API Padrão POSIX"}}<br />
<br />
== Um Exemplo de Uso "API Padrão POSIX" ==<br />
<br />
;Referências<br />
* Referência http://man7.org/linux/man-pages/man2/mmap.2.html<br />
<br />
<br />
Crie uma função soma que receba 2 ponteiros referenciando posições na memória, criadas utilizando nmap(), de maneira que estas posições armazenem números inteiros. A função soma deverá retornar a soma dos números apontados em regiões da memória sem a utilização de nenhuma rotina da biblioteca do C, que não sejam definidas por APIs posix, para criação destas <br />
regiões na memória (malloc, alloc, calloc). Após retornar o resultado da soma os devidos ponteiros deverão ser extintos da memória.<br />
<br />
<br />
*'''Experimento 1:''' Aumente o tamanho da memória alocada até quando for possível.<br />
<br />
Qual o tamanho limite da memória que você conseguiu alocar?<br />
<br />
*'''Experimento 2:''' Mude o escopo para PROT_NONE, após executar e depurar o código explique o que aconteceu.<br />
<br />
Em sua opinião NMAP trata-se de uma syscall ou de uma API? Afinal API e syscall são a mesma coisa? Explique.<br />
<br />
<syntaxhighlight lang=cpp><br />
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);<br />
int munmap(void *addr, size_t length);<br />
<br />
addr = Valor do início do mapeamento.<br />
length = valor do tamanho da região a ser alocada.<br />
prot = especificações de proteção da região alocada (consultar http://man7.org/linux/man-pages/man2/mmap.2.html).<br />
flags = especificação do escopo e do tipo da região criada (exemplo publica ou privada, se é anônima ou não). <br />
</syntaxhighlight><br />
<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
void* meu_malloc(size_t tamanho) {<br />
void* addr = mmap(0, // addr<br />
tamanho, // len<br />
PROT_READ | PROT_WRITE, // prot<br />
MAP_ANON | MAP_PRIVATE, // flags<br />
-1, // filedes<br />
0); // off<br />
*(size_t*)addr = tamanho;<br />
return addr;<br />
}<br />
<br />
int meu_free(void* addr) {<br />
return munmap(addr - sizeof(size_t), (size_t) addr);<br />
}<br />
<br />
<br />
int soma(int *N1, int *N2){<br />
<br />
return (*N1+*N2);<br />
<br />
}<br />
<br />
<br />
int main(int argc, char* argv[]) {<br />
<br />
int* numero1 = meu_malloc(sizeof(int));<br />
int* numero2 = meu_malloc(sizeof(int)); <br />
<br />
<br />
*numero1 = 10;<br />
*numero2 = 20; <br />
<br />
int resultado = soma(numero1, numero2);<br />
<br />
printf("\n\n O resultado da soma é %d \n\n",resultado); <br />
<br />
meu_free(numero1);<br />
meu_free(numero2);<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Processos no Linux}}<br />
<br />
== Processos no Linux - Modificado por Eraldo ==<br />
<br />
<blockquote style="background: lime; border: 1px solid black; padding: 1em;"><br />
Processos no Linux<br />
</blockquote><br />
<br />
*Exercícios propostos pelo Prof.Arliones e Modificados por Eraldo<br />
<br />
<br />
[[imagem:DesenhoForkExec.png|border|650px]]<br />
<br />
<br />
;Syscall FORK<br />
<br />
* Em um terminal, execute "man fork"<br />
** 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'''.<br />
** O '''código''' dos dois processos (pai e filho) são '''idênticos''';<br />
** Os '''dados''' dos dois processos (pai e filho) são '''idênticos NO MOMENTO DA CRIAÇÃO''';<br />
** Execução do processo filho inicia na próxima instrução do programa (no retorno da chamada FORK);<br />
** Não é possível saber qual dos processos (pai ou filho) retormará a execução primeiro - isto fica a cargo do excalonador do SO;<br />
** Valores de retorno da chamada FORK:<br />
*** (-1): erro na criação do processo (ex.: memória insuficiente);<br />
*** (0): em caso de sucesso, este é o valor de retorno recebido pelo processo filho;<br />
*** (>0): em caso de sucesso, este é o valor de retorno recebido pelo processo pai;<br />
<br />
;Syscall JOIN<br />
<br />
* A syscall JOIN é implementada no POSIX pela função '''wait()'''. Execute "man wait".<br />
** Além da função '''wait()''', há também '''waitpid()''' e '''waitid()''';<br />
** 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);<br />
** A chamada wait também libera os recursos do processo filho que termina;<br />
** '''wait()''': esta função suspende a execução do processo chamador até que UM DOS SEUS FILHOS finalize;<br />
** '''waitpid()''': suspende a execução do processo chamador até que UM FILHO ESPECÍFICO finalize;<br />
<br />
;Syscall EXEC<br />
<br />
* A syscall EXEC é implementada no POSIX pela família de funções '''exec()'''. Execute "man exec".<br />
** As principais funções da família são '''execl()''', '''execlp()''' e '''execvp()''';<br />
** 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;<br />
** 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;<br />
<br />
<br />
;Exemplos POSIX utilizando fork/wait/exec<br />
<br />
*Exemplo 1: fork/wait básico<br />
<syntaxhighlight lang=c><br />
// ex1: fork/wait básico<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
printf("processo filho\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
printf("processo pai\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
arliones@socrates:~/tmp$ gcc ex1.c -o ex1 <br />
arliones@socrates:~/tmp$ ./ex1 <br />
processo filho pid: 27858 pid pai: 27857<br />
processo pai pid: 27857 pid pai: 5337<br />
arliones@socrates:~/tmp$ <br />
</syntaxhighlight><br />
<br />
* Exemplo 2: processos pai e filho compartilham código, mas não dados.<br />
<syntaxhighlight lang=c><br />
// ex2: fork/wait "compartilhando" dados<br />
// ex2: fork/wait "compartilhando" dados<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status, k=0;<br />
printf("processo %d\t antes do fork\n", getpid());<br />
pid = fork();<br />
printf("processo %d\t depois do fork\n", getpid());<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
k += 1000;<br />
printf("processo filho\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status); // espera o filho terminar<br />
k += 10;<br />
printf("processo pai\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
k += 1000;<br />
printf("FIM processo %d\t K: %d\n", getpid(), k); <br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
processo 17056 antes do fork<br />
processo 17056 depois do fork<br />
processo 17057 depois do fork<br />
processo filho pid: 17057 K: 1000 endereço K: 0x7ffd8923e318<br />
processo pai pid: 17056 K: 10 endereço K: 0x7ffd8923e318<br />
</syntaxhighlight><br />
<br />
* Modificação no código: comentar linhas 23 e 30<br />
<br />
<syntaxhighlight lang=bash><br />
<br />
</syntaxhighlight><br />
<br />
* Analise os resultados e busque entender a diferença.<br />
*Perguntas e desafios.:<br />
#Analisando os valores impressos de k pode-se dizer que os dados são compartilhados entre os dois processos?<br />
#O endereço de k impresso é o mesmo nos dois processos. ISto não contradiz a afirmação anterior?<br />
#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.<br />
<br />
<br />
;Exercício fork/wait<br />
<br />
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.<br />
<br />
*Use o comando pstree para verificar a árvore de processos criada.<br />
<br />
{{collapse top|Solução}}<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
<!--<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
--><br />
<br />
;DESAFIO: fork/wait<br />
<br />
Reimplementar o exercício anterior de criação de uma árvore de 3 processos, generalizando a criação de N processos onde N é repassado na linha de comando do programa. SUGESTÃO: usar um comando for, mas lembrar que se existe um fork dentro do for, então cada filho gerado dará continuidade a execução do for. É necessário que o processo faça um exit ou retorne neste momento.<br />
<br />
;DESAFIO: Exercício status/wait<br />
<br />
O ''status'' passado como parâmetro à função ''wait(&status)'' é, na verdade, o mecanismo de retorno de resultado do ''wait/waitpid''. Ao retornar, esta variável contém informações sobre o resultado da execução do processo filho. Por exemplo, se um processo terminou normalmente (i.e., chamou ''exit''), o comando ''WIFEXITED(status)'' retorna ''true''. Este comando retorna ''false'' se o processo foi abortado (e.g., ''segmentation fault'') ou morto (e.g., ''kill''). Investigue no manual do wait no Linux (''man wait'') o funcionamento do comando WEXITSTATUS(status). <br />
Imagine um problema de busca de dados armazenados na forma de uma matriz de inteiros 4x30. Você está interessado em saber quantas ocorrências de um determinado número existe em cada linha da matriz. Note que que são tarefas que podem ser paralelizadas e usufruir de um sistema capaz de executá-las em paralelo. Faça uma implementação paralelizando 4 processos filhos a partir de um pai, onde cada processo é responsável por uma busca. A quantidade de ocorrências do número buscado é retornada e capturada através de WEXITSTATUS.<br />
<br />
;Syscall EXEC<br />
<br />
*Exemplo exec()<br />
<br />
<syntaxhighlight lang=c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
execl("/bin/ls","ls","-l", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 1: Modificar o código para mostrar que o exec() não retorna (colocar um printf após o exec).<br />
<br />
*Exercício 2: Criar um exemplo (dois programas ) para demonstrar que o exec não cria novo processo. <br />
**Crie um primeiro programa (prog1) que imprime o seu pid e depois faz um exec do segundo programa.<br />
**Crie o segundo programa que simplesmente imprime o pid.<br />
<br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU ANTES DO EXEC: Meu pid é %d\n", getpid());<br />
execl("./prog2","prog2", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU DEPOIS DO EXEC:Meu pid é %d\n", getpid());<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 3: Criar um exemplo usando fork/exec mostrando que um processo pai cria um filho e espera por sua execução. O filho executa o comando "ps aux". Ambos devem mostrar seus pids.<br />
<br />
{{collapse bottom}} <br />
{{collapse top| bg=lightyellow | expandir=true | Threads de aplicação}}<br />
<br />
== Threads de aplicação ==<br />
<br />
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:<br />
*'''getcontext(&a)''': salva o contexto na variável '''a''';<br />
*'''setcontext(&a)''': restaura um contexto salvo anteriormente na variável '''a''';<br />
*'''swapcontext(&a,&b)''': salva o contexto atual na variável '''a''' e restaura o contexto salvo anteriormente na variável '''b''';<br />
*'''makecontext(&a, ...)''': ajusta parâmetros internos do contexto salvo em '''a''';<br />
*'''ucontext_t''': as variáveis '''a''' e '''b''' são do tipo '''ucontext_t'''. Este tipo armazena um contexto.<br />
<br />
Busque mais informações sobre estas funções utilizando o programa manpage do Linux (ex.: man getcontext).<br />
<br />
Estude o código no arquivo pingpong.c abaixo e explique seu funcionamento.<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
*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.<br />
*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.<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain, cFnew;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_new(void * arg1, void * arg2,void * arg3,void * arg4) <br />
{<br />
printf ("%s: Primeira string %s %s %s\n",(char*) arg1,(char*) arg2,(char*) arg3, (char*) arg4);<br />
swapcontext(&cFnew, &cMain); <br />
}<br />
<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
<br />
getcontext(&cFnew);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cFnew.uc_stack.ss_sp = stack ;<br />
cFnew.uc_stack.ss_size = STACKSIZE;<br />
cFnew.uc_stack.ss_flags = 0;<br />
cFnew.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cFnew, (void*)(*f_new), 4, "\tF_new", "\tAlo", "\tMundo","\tReal");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
swapcontext(&cMain, &cFnew);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
--><br />
Exercício 3: O que acontece se um dos threads é colocado para dormir? Todos os demais threads param a sua execução.<br />
<br />
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/<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Trocas de mensagens com pipes}}<br />
<br />
== Trocas de mensagens com pipes ==<br />
<br />
;Troca de mensagens<br />
Um mecanismo disponibilizado por sistemas UNIX para troca de mensagens entre processos é o PIPE. Pipes são mecanismos de comunicação indireta onde mensagens são trocadas através de ''mailboxes''. Cada ''mailbox'' possui um identificador único, permitindo que processos identifiquem o canal de comunicação entre eles. O fluxo de mensagens em um Pipe é:<br />
*'''unidirecional''': sobre um mesmo pipe, apenas um processo envia mensagens e um processo recebe mensagens;<br />
*'''FIFO''': as mensagens são entregues na ordem de envio;<br />
*'''não-estruturado''': não há estrutura pré-definida para o formato da mensagem.<br />
No UNIX, pipes são inicializados através da '''SystemCall''' ''pipe'', que possui a seguinte sintaxe:<br />
*''int pipe(int pipefd[2])'': ''pipe'' inicializa um novo pipe no sistema e retorna, no array pipefd, os descritores identificando cada uma das pontas do pipe. A primeira posição do array, i.e. pipefd[0], recebe o descritor que pode ser aberto apenas para leitura, enquanto a segunda posição do array, i.e. pipefd[1], recebe o descritor que pode ser aberto apenas para escrita. A função retorna zero no caso de sucesso, ou -1 se ocorrer erro.<br />
As primitivas send/receive para uso de um pipe no UNIX são implementadas por '''SystemCalls''' read/write, conforme segue:<br />
*''ssize_t read(int fd, void *buf, size_t count)'': “puxa” dados do pipe identificado pelo descritor fd. Os dados recebidos são os apontados pelo ponteiro buf, sendo count a quantidade máxima de bytes a serem recebidos. A função retorna o número de bytes recebidos.<br />
*''ssize_t write(int fd, const void *buf, size_t count)'': “empurra” dados no pipe identificado pelo descritor fd. Os dados transmitidos são os apontados pelo ponteiro buf, sendo count a quantidade de bytes a serem transmitidos. A função retorna o número de bytes transmitidos.<br />
<br />
*Exemplo 1: Transmitindo e recebendo pelo próprio processo<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main()<br />
{<br />
int fd[2];<br />
char *ptr = "Alo eu mesmo";<br />
char *ptr_alvo;<br />
int tamanho_dados, ret;<br />
<br />
tamanho_dados = strlen(ptr)+1;<br />
<br />
if (pipe(fd)==-1){<br />
printf ("erro criação pipe\n");<br />
exit(-1);<br />
}<br />
printf("Transmitido %d bytes\n", tamanho_dados);<br />
write (fd[1], ptr, tamanho_dados);<br />
<br />
ptr_alvo = malloc(tamanho_dados);<br />
<br />
ret=read(fd[0],ptr_alvo,tamanho_dados);<br />
<br />
printf("ret = %d dados => %s\n", ret, ptr_alvo); <br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
*Exemplo 2: Abaixo há um exemplo de programa criando um pipe e compartilhando os descritores entre dois processos (criados via ''fork()'').<br />
<syntaxhighlight lang=c><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
<br />
char *message = "This is a message!!!" ;<br />
<br />
main()<br />
{<br />
char buf[1024] ;<br />
int fd[2];<br />
pipe(fd); /*create pipe*/<br />
if (fork() != 0) { /* I am the parent */<br />
write(fd[1], message, strlen (message) + 1) ;<br />
}<br />
else { /*Child code */<br />
read(fd[0], buf, 1024) ;<br />
printf("Got this from MaMa!!: %s\n", buf) ;<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
*'''Exercício 1: construa um “pipeline”'''. Crie um programa que conecta 4 processos através de 3 pipes. Utilize ''fork()'' para criar vários processos.<br />
<br />
<syntaxhighlight lang=cpp><br />
<br />
//Solução possível<br />
<br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
pipe(fd);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
<br />
</syntaxhighlight><br />
<br />
*'''Exercício 3: Modifique o exercício anterior para que o processo D, através de um novo pipe, mande uma mensagem diretamente para o pai de todos.<br />
<br />
<!--<br />
<code><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
int fd_retorno[2];<br />
<br />
pipe(fd);<br />
pipe(fd_retorno);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size);<br />
read(fd_retorno[0], buf, size);<br />
printf("PAI:%s\n", buf); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
char *ptr_msg_ret="Ok msg de D para o pai";<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
write(fd_retorno[1],ptr_msg_ret,strlen(ptr_msg_ret)+1);<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
*'''Exercício 3: Consultor de Login de Acesso:'''. Estude o link https://www.geeksforgeeks.org/named-pipe-fifo-example-c-program/ e projete um programa cliente servidor da seguinte forma: (i) O servidor possui uma tabela de usuários (userid). O user_id é de tamanho fixo de 7 caracteres. O servidor espera por consultas para verificar se um usuário está na tabela. Se estiver responde com o caracter 'S' senão com 'N'. (ii) O cliente espera por user_id no teclado e consulta o servidor sobre sua existência na tabela. O cliente imprime na tabela a existência ou não do usuário.<br />
<br />
*'''Exercício 4: cópia de arquivo'''. Projete um programa de cópia de arquivos chamado FileCopy usando pipes comuns. Esse programa receberá dois parâmetros: o primeiro é o nome do arquivo a ser copiado e o segundo é o nome do arquivo copiado. Em seguida, o programa criará um pipe comum e gravará nele o conteúdo do arquivo a ser copiado. O processo filho lerá esse arquivo do pipe e o gravará no arquivo de destino. Por exemplo, se chamarmos o programa como descrito a seguir:<br />
:<syntaxhighlight lang=bash><br />
$ FileCopy entrada.txt copia.txt<br />
</syntaxhighlight><br />
:o arquivo ''entrada.txt'' será gravado no pipe. O processo filho lerá o conteúdo desse arquivo e o gravará no arquivo de destino ''copia.txt''. Escreva o programa usando os pipes da API POSIX no Linux.<br />
<br />
<br />
{{collapse bottom}}<br />
<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Exercícios sobre Memória Compartilhada}}<br />
<br />
==SHARED MEMORY: Produtor (pai) - Consumidor (filho) - ==<br />
<br />
<!-- Parou aki 20/08<br />
<br />
<br />
*'''Experimento 2:''' Complete o código a seguir para que os processos pai e filho possam compartilhar um segmento de memória. O filho escreve no segmento e o pai imprime na tela o conteúdo da mensagem.<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
char *ptr_msg = "alo pai, tudo bem?"; <br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
//completar aqui<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
<!--<br />
<code><br />
<br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/types.h><br />
#include <string.h><br />
#include <stdlib.h><br />
<br />
int main(void)<br />
{<br />
int fd[2], pipe_ret, filho;<br />
char string[] = "Hello, pipe!\n";<br />
char buffer[20];<br />
<br />
pipe(fd);<br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
/*Mandar string para a extremidade do pipe*/<br />
write(fd[1], string, (strlen(string)+1));<br />
exit(0);<br />
}<br />
else<br />
{<br />
<br />
/* Read in a string from the pipe */<br />
pipe_ret = read(fd[0], buffer, (20*sizeof(char)));<br />
printf("Recebi este texto %s", buffer);<br />
}<br />
<br />
return(0);<br />
}<br />
<br />
<br />
<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
key = ftok("teste_sh.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644 | IPC_CREAT));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
<br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
strncpy(segmento, "mensagem compartilhada", SHM_SIZE); <br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
--><br />
<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Memória Compartilhada}}<br />
*'''Experimento Shared Memory:''' Complete o código a seguir para que os processos pai e filho possam compartilhar um segmento de memória. O filho escreve no segmento e o pai imprime na tela o conteúdo da mensagem.<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
char *ptr_msg = "alo pai, tudo bem?"; <br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
//completar aqui strcpy(segmento, ptr_msg); //aqui deveria testar a cpacidade da área...<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exemplo com ftok:<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
key = ftok("./teste.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644 | IPC_CREAT));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
<br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
strncpy(segmento, "mensagem compartilhada", SHM_SIZE); <br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exemplo com ftok entre processos sem parentesco:<br />
<br />
Criar um arquivo teste.txt e em um terminal executar:<br />
<br />
<syntaxhighlight lang=c><br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
int modo,filho;<br />
<br />
struct minha_struct {<br />
char flag;<br />
int numero;<br />
} *ptr;<br />
<br />
<br />
key = ftok("./teste.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644 | IPC_CREAT));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
ptr = (struct minha_struct *) shmat(shmid, (void *)0, 0);<br />
if ((char *)ptr == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
ptr->flag =0;<br />
ptr->numero = 0;<br />
while (ptr->flag==0) { <br />
printf("%d\n", ptr->numero);<br />
sleep(1);<br />
} <br />
<br />
if (shmdt(ptr) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Em outro terminal executar:<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
struct minha_struct {<br />
char flag;<br />
int numero;<br />
} *ptr;<br />
<br />
<br />
key = ftok("./teste.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
ptr = (struct minha_struct *) shmat(shmid, (void *)0, 0);<br />
if ((char *)ptr == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
<br />
<br />
while (ptr->numero++<10)<br />
sleep(1);<br />
<br />
ptr->flag = 1;<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Exercício Desafio: Implementar o problema do buffer circular usando memória compartilhada.<br />
<br />
{{collapse bottom}}<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Exercício (Algoritmo de Peterson)}}<br />
<br />
== Exercício (Algoritmo de Peterson) ==<br />
<br />
<br />
'''Exercício 1''': Sincronize o código a seguir, de maneira que o processo pai imprima apenas os números impares e o processo filho os números pares. Para isso utilize o algoritmo de '''Peterson''' visto em aula. '''Utilize memória compartilhada''' para comunicação entre os processos.<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
main()<br />
{ <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int i; <br />
<br />
for(i = 0;i < 10;i=i+2){ <br />
printf("Processo pai %d \n", i); <br />
<br />
} <br />
<br />
<br />
}<br />
<br />
else { /*Child code */<br />
int i; <br />
for(i = 1;i < 10;i=i+2){ <br />
printf("Processo filho %d \n", i); <br />
<br />
}<br />
<br />
<br />
}<br />
<br />
exit(0);<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
'''Exercício 2''': Considerando o exercício anterior faça a mesma sincronização, no entanto desta vez utilize a modelagem em software do TSL. <br />
* Em sua experiência, depois de testar diversas vezes as execuções de suas soluções baseadas no algoritmo de '''Peterson''' e '''Tsl''', qual sua opinião sobre as abordagens?<br />
Explique seu raciocínio. <br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Exercício (Semáforos)}}<br />
== Exercício (Semáforos) ==<br />
<br />
<br />
'''Exercício 1''': Sincronize o código a seguir, de maneira que o processo pai imprima apenas os números impares e o processo filho os números pares. Para isso utilize '''Semáforos''' de acordo com a implementação em '''semaforo.h'''. '''Utilize memória compartilhada''' para comunicação entre os processos.<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
main()<br />
{ <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int i; <br />
<br />
for(i = 0;i < 10;i=i+2){ <br />
printf("Processo pai %d \n", i); <br />
sleep(1);<br />
<br />
} <br />
<br />
<br />
}<br />
<br />
else { /*Child code */<br />
int i; <br />
for(i = 1;i < 10;i=i+2){ <br />
printf("Processo filho %d \n", i); <br />
<br />
}<br />
<br />
<br />
}<br />
<br />
exit(0);<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
SEMAFORO.H<br />
<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <sys/sem.h><br />
<br />
<br />
int criar_semaforo(int val, int chave) <br />
{<br />
int semid ;<br />
<br />
union semun {<br />
int val;<br />
struct semid_ds *buf ;<br />
ushort array[1];<br />
} arg_ctl ;<br />
<br />
key_t ft = ftok("/tmp", chave);<br />
<br />
semid = semget(ft,1,IPC_CREAT|IPC_EXCL|0666);<br />
if (semid == -1) {<br />
semid = semget(ft,1,0666); <br />
if (semid == -1) {<br />
perror("Erro semget()");<br />
exit(1) ;<br />
}<br />
}<br />
<br />
arg_ctl.val = val; //valor de início<br />
if (semctl(semid,0,SETVAL,arg_ctl) == -1) {<br />
perror("Erro inicializacao semaforo");<br />
exit(1);<br />
}<br />
return(semid) ;<br />
}<br />
<br />
void P(int semid){<br />
<br />
struct sembuf *sops = malloc(10*sizeof(int));<br />
sops->sem_num = 0;<br />
sops->sem_op = -1;<br />
sops->sem_flg = 0;<br />
semop(semid, sops, 1); <br />
free(sops);<br />
<br />
}<br />
<br />
<br />
void V(int semid){<br />
<br />
struct sembuf *sops = malloc(10*sizeof(int));<br />
sops->sem_num = 0;<br />
sops->sem_op = 1;<br />
sops->sem_flg = 0; <br />
semop(semid, sops, 1); <br />
free(sops);<br />
<br />
} <br />
<br />
<br />
<br />
void sem_delete(int semid) <br />
{<br />
<br />
if (semctl(semid,0,IPC_RMID,0) == -1)<br />
perror("Erro na destruicao do semaforo");<br />
}<br />
<br />
<br />
<br />
<br />
</syntaxhighlight><br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Programação concorrente}}<br />
<br />
== Programação concorrente ==<br />
<br />
;POSIX Threads<br />
A 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):<br />
*''pthread_create'': cria uma thread;<br />
*''pthread_kill'': força a terminação de uma thread;<br />
*''pthread_join'': sincroniza o final de uma thread (qual a diferença/semelhança com o ''wait'' que usamos para processos?);<br />
*''pthread_exit'': finaliza uma thread.<br />
Para utilizar estas funções é necessário linkar o programa à libpthread (''-lpthread''). <br />
<br />
<br />
;POSIX pthread mutex<br />
<br />
A biblioteca pthread implementa um tipo ''pthread_mutex_t'', que garante a exclusão mútua entre threads. Estes mutex são manipulados através das funções (acesse as man-pages das chamadas para maiores detalhes):<br />
*''pthread_mutex_lock'': acessa um mutex.<br />
*''pthread_mutex_trylock'': tenta acessar um mutex (retorna valor indicando sucesso ou falha no lock).<br />
*''pthread_mutex_unlock'': libera um mutex.<br />
<br />
<br />
<br />
<br />
;POSIX Semaphores<br />
<br />
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):<br />
*''sem_init'': inicializa um semáforo;<br />
*''sem_destroy'': destroy um semáforo;<br />
*''sem_wait'': implementa a operação ''p'';<br />
*''sem_post'': implementa a operação ''v''.<br />
Para utilizar estas funções é necessário linkar o programa à librt ou à libpthread (''-lrt'' ou ''-lpthread'').<br />
<br />
;Exercício 1<br />
<br />
O programa abaixo cria 5 threads, e cada uma destas threads atualiza uma variável global (memória compartilhada).<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include <pthread.h><br />
#include <signal.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
pthread_mutex_t mut;<br />
<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
}<br />
</syntaxhighlight><br />
<br />
# Compile este programa. <br />
# Execute este programa várias vezes. Ele funciona? Será que ele gera as saídas esperadas?<br />
# Identifique as '''seções críticas''' do programa.<br />
# Corrija o programa utilizando '''mutex'''. <br />
# Analise a função ''AtualizaSaldo()'' com a sua solução. Lembre-se que o uso do mutex implica em apenas uma thread acessar a seção crítica por vez, enquanto outras threads ficam bloqueadas, esperando. Disso vem que, quanto menor o trecho de código entre um ''lock'' e um ''unlock'', menos tempo uma thread necessita ficar esperando.<br />
# Modifique o programa para usar um semáforo binário ao invés de um mutex em sua solução.<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <cstring><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
<br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
sem_t sem;<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
int value;<br />
sem_wait(&sem);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
sem_getvalue(&sem, &value);<br />
printf("valor sem = %d\n", value);<br />
sem_post(&sem);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
sem_init(&sem,0,1);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
sem_destroy(&sem);<br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
<br />
;Exercício 2<br />
Refaça o exercício 3 usando processos criados com fork e exec. O semáforo deve ser criado em uma região de memória compartilhada.<br />
<br />
;Exercício 3<br />
Implemente com pthreads e semáforos/mutex a solução do produtor/comsumidor.<br />
<br />
;Exercício 4<br />
<br />
O programa abaixo manipula uma matriz de tamanho MxN (veja os defines para o tamanho da matriz). A função ''SumValues'' soma todos os valores em uma linha da matriz. A linha a ser somada é identificada pela variável ''i''. Modifique o programa principal (''main'') nos locais indicados para:<br />
# Criar N threads, uma para somar os valores de cada linha.<br />
# Receber o resultado do somatório de cada linha e gerar o somatório total da matriz.<br />
# Analise o programa: há problemas de sincronização que precisam ser resolvidos? Se sim, resolva-os.<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include "thread.h"<br />
<br />
/* number of matrix columns and rows */<br />
#define M 5<br />
#define N 10<br />
<br />
using namespace std;<br />
<br />
int matrix[N][M];<br />
Thread *threads[N];<br />
<br />
<br />
/* thread function; it sums the values of the matrix in the row */<br />
int SumValues(int i)<br />
{<br />
int n = i; /* number of row */<br />
int total = 0; /* the total of the values in the row */<br />
int j;<br />
for (j = 0; j < M; j++) /* sum values in the "n" row */<br />
total += matrix[n][j];<br />
cout << "The total in row" << n << " is " << total << "." << endl;<br />
/* terminate a thread and return a total in the row */<br />
exit(total);<br />
}<br />
<br />
int main(int argc, char *argv[])<br />
{<br />
int i, j;<br />
int total = 0; /* the total of the values in the matrix */<br />
<br />
/* initialize the matrix */<br />
for (i = 0; i < N; i++)<br />
for (j = 0; j < M; j++)<br />
matrix[i][j] = i * M + j;<br />
<br />
/* create threads */<br />
/* COLOQUE SEU CÓDIGO PARA CRIAR AS THREADS AQUI! */<br />
<br />
/* wait for terminate a threads */<br />
/* COLOQUE SEU CÓDIGO PARA PEGAR O SOMATÓRIO DE LINHAS E TOTALIZAR A SOMA DA MATRIZ AQUI! */<br />
<br />
cout << "The total values in the matrix is " << total << endl;<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Lista de exercícios "Revisão para Prova" }}<br />
<br />
== Lista de exercícios/Revisão para Prova ==<br />
<br />
A lista de exercícios referente a primeira prova (Parte introdutória + Processos) segue neste LINK [http://docente.ifsc.edu.br/andre.damato/sop2018/lista_rev1.pdf | Lista de exercícios]. <br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Primeiro trabalho}}<br />
== JOGO DA VIDA DE CONWAY e JANTAR DOS FILÓSOFOS==<br />
<br />
;Referências<br />
<br />
* [https://www.open-mpi.org/doc/current/ MPI]<br />
<br />
* [https://quark.phy.bnl.gov/~creutz/qcdoc/mpi/mpi.h Tipos de dados MPI]<br />
<br />
* [https://pt.wikipedia.org/wiki/Jogo_da_vida Jogo da Vida]<br />
<br />
<br />
<br />
<br />
A partir da implementação sequencial do Game of Life apresentada a seguir, estude o código e transforme esta implementação em uma implementação paralela utilizando o protocolo de passagem de mensagens MPI.<br />
Perceba que a impĺementação mencionada utiliza como parâmetros de entrada um aquivo contendo o estado inicial do jogo, e o número de gerações que o usuário deseja rodar. A evolução do estado inicial <br />
é impressa na tela passo a passo. Sendo assim, a partir disso:<br />
<br />
*'''1: Elabore uma implementação com 2 processos para o jogo da vida utilizando o protocolo MPI, de maneira que um processo execute uma geração i qualquer e o outro execute a geração seguinte i+1''' <br />
<br />
*'''2: (0,7) Os processos deverão se comunicar utilizando as funções do protocolo MPI.''' <br />
<br />
*'''3: (0,3) Relatório simplificado explicando a sua solução. Utilize diagramas para representar a comunicação entre os processos, explicando como a matriz do jogo é transferida entre os processos. ''' <br />
<br />
*'''4: Entregue o Relatório e o código fonte do trabalho em um pacote compactado via e-mail (PRAZO 19/10). <br />
<br />
<br />
<br />
* ''' Compilar o código com MPI '''<br />
<code><br />
mpicc -o nomeApp arquivo.c<br />
</syntaxhighlight><br />
<br />
* ''' Rodar rodar programa utilizando MPI '''<br />
<code><br />
mpirun -np numeroDeProcessos ./nomeApp entrada.txt gerações<br />
</syntaxhighlight><br />
<br />
* (int) -np: Quantidade de processos que você deseja executar <br />
<br />
* entrada.txt: Arquivo de entrada com estado inicial do jogo <br />
<br />
* (int) gerações: número de gerações que você deseja rodar<br />
<br />
* [http://docente.ifsc.edu.br/andre.damato/sop2018/entrada.txt Arquivo de entrada para Testes]<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
<br />
<br />
<br />
/*<br />
<br />
Conway's Game of Life<br />
<br />
Compilar código com MPI<br />
mpicc -o nomeApp arquivo.c<br />
<br />
<br />
Rodar rodar programa utilizando MPI<br />
<br />
mpirun -np numeroDeProcessos ./nomeApp entrada.txt gerações<br />
<br />
(int) -np: Quantidade de processos que você deseja executar <br />
entrada.txt: Arquivo de entrada com estado inicial do jogo <br />
(int) gerações: número de gerações que você deseja rodar<br />
<br />
<br />
*/<br />
<br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h><br />
#include "mpi.h"<br />
<br />
<br />
//Numero de linhas e colunas<br />
#define nLinhas 32<br />
#define nColunas 82 <br />
<br />
char *matriz[nLinhas];<br />
char *entrada[nLinhas];<br />
<br />
<br />
void iniciar() {<br />
<br />
int i;<br />
<br />
//Alocar espaço em memória para as matrizes<br />
for (i = 0; i < nLinhas; i++ ) <br />
matriz[i] = (char *) malloc((nColunas) * sizeof( char )); <br />
<br />
<br />
}<br />
<br />
int adjacente(char **matriz, int i, int j){<br />
<br />
int x,y, initX, initY, limitX, limitY;<br />
int vizinhos = 0;<br />
<br />
if(i == 0)<br />
initX = 0;<br />
else <br />
initX = -1;<br />
<br />
if(i == (nLinhas-1)) <br />
limitX = 1;<br />
else<br />
limitX = 2;<br />
<br />
<br />
if(y == 0)<br />
initY = 0;<br />
else <br />
initY = -1;<br />
<br />
if(y == (nColunas-3)) <br />
limitY = 1;<br />
else<br />
limitY = 2;<br />
<br />
for(x = initX ; x < limitX; x++){<br />
for(y = initY; y < limitY; y++){<br />
if(matriz[i+x][j+y] == '#') <br />
vizinhos++; <br />
} <br />
}<br />
<br />
<br />
if(matriz[i][j] == '#') <br />
return (vizinhos-1);<br />
else <br />
return vizinhos;<br />
<br />
}<br />
<br />
<br />
void calculoGeracao(char **matriz, int ger) {<br />
<br />
int i, j, a;<br />
char novaGeracao[nLinhas][nColunas];<br />
<br />
/* Aplicando as regras do jogo da vida */<br />
for (i=0; i < nLinhas; i++){ <br />
for (j=0; j < nColunas; j++) {<br />
<br />
a = adjacente(matriz, i, j);<br />
<br />
if (a == 2) novaGeracao[i][j] = matriz[i][j];<br />
if (a == 3) novaGeracao[i][j] = '#';<br />
if (a < 2) novaGeracao[i][j] = ' ';<br />
if (a > 3) novaGeracao[i][j] = ' ';<br />
<br />
if (j == 0)<br />
novaGeracao[i][j] = '"';<br />
} <br />
<br />
novaGeracao[i][79] = '"';<br />
novaGeracao[i][80] = '\n';<br />
<br />
<br />
}<br />
<br />
/* Passando o resultado da nova geração para a matriz de entrada */<br />
for (i=0; i < nLinhas; i++){ <br />
for (j=0; j < nColunas; j++) <br />
matriz[i][j] = novaGeracao[i][j];<br />
}<br />
}<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
main(int argc, char *argv[2]){<br />
<br />
/* Para uso com MPI<br />
<br />
<br />
//Variáveis para uso com MPI<br />
int numeroDeProcessos = 0;<br />
int rank = 0;<br />
MPI_Status status; <br />
<br />
//Iniciar MPI---<br />
MPI_Init( &argc, &argv );<br />
<br />
//Atribui a variável numeroDeProcessos o número de processos passado como parâmetro em -np <br />
MPI_Comm_size( MPI_COMM_WORLD, &numeroDeProcessos );<br />
<br />
//Pega o valor do rank (processo)<br />
MPI_Comm_rank( MPI_COMM_WORLD, &rank );<br />
*/<br />
<br />
<br />
FILE *matrizEntrada;<br />
matrizEntrada = fopen(argv[1], "r");<br />
iniciar();<br />
<br />
<br />
if (matrizEntrada == NULL)<br />
printf ("Não posso abrir o arquivo \"%s\"\n", argv[1]);<br />
<br />
<br />
char str[nColunas];<br />
int linha = 0;<br />
<br />
<br />
<br />
//Lendo o estado inicial do jogo a partir do arquivo<br />
while((fgets(str, nColunas, matrizEntrada) != NULL)&&(linha < nLinhas)){<br />
strcat(matriz[linha], str);<br />
linha++;<br />
}<br />
<br />
int i,gens; <br />
<br />
<br />
for(gens = 0; gens < atoi(argv[2]); gens++){ //Gens é o número de gerações especificado no segundo parâmetro <br />
<br />
calculoGeracao(matriz, gens);<br />
printf("%c[2J",27); // Esta linha serve para limpar a tela antes de imprimir o resultado de uma geração <br />
<br />
//Lendo o estado do jogo e imprime na tela <br />
for(i = 0; i < nLinhas; i++)<br />
printf("%s", matriz[i]); <br />
<br />
sleep(1);<br />
<br />
}<br />
<br />
<br />
for(i = 0; i < nLinhas; i++) <br />
free(matriz[i]); <br />
<br />
<br />
<br />
/* Finaliza o MPI */ <br />
//MPI_Finalize();<br />
<br />
exit(0);<br />
} <br />
<br />
<br />
</syntaxhighlight><br />
<br />
<br />
;Jantar dos Filósofos<br />
O problema clássico Jantar dos Filósofos consiste em que n fluxos (n filósofos) disputam n recursos (n talheres). No problema, para conseguir "jantar" (ou executar), cada filósofo precisa pegar dois talheres adjascentes a ele. Cada recurso é compartilhado por dois filósofos.<br />
*[http://www.doc.ic.ac.uk/~jnm/concurrency/classes/Diners/Diners.html Veja esta simulação]<br />
*[http://en.wikipedia.org/wiki/Dining_philosophers_problem Veja esta descrição do problema]<br />
<br />
<br />
* ''' (0,7) programa abaixo implementa um Jantar dos Filósofos utilizando semáforos para sincronização. Contudo, as chamadas para as operações ''v'' e ''p'' foram removidas, conforme comentários no código. Re-insira as operações no código e analise a solução. Esta modificação é suficiente para garantir que não haverá deadlock? Se sim, mostre o porque. Se não, proponha uma solução completa. '''<br />
<br />
<br />
*''' (0,3) Relatório simplificado explicando a sua solução. ''' <br />
<br />
*''' Entregue o Relatório e o código fonte do trabalho em um pacote compactado via e-mail (PRAZO 19/10). <br />
<br />
<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include "thread.h"<br />
#include "semaphore.h"<br />
<br />
using namespace std;<br />
<br />
const int DELAY = 10000000;<br />
const int ITERATIONS = 5;<br />
<br />
Semaphore chopstick[5];<br />
<br />
int philosopher(int n)<br />
{<br />
cout << "Philosopher " << n << " was born!\n";<br />
<br />
int first = (n < 4)? n : 0; // left for phil 0 .. 3, right for phil 4<br />
int second = (n < 4)? n + 1 : 4; // right for phil 0 .. 3, left for phil 4<br />
<br />
// Foram removidos do laço abaixo:<br />
// - uma chamada para chopstick[first].p()<br />
// - uma chamada para chopstick[second].p()<br />
// - uma chamada para chopstick[first].v()<br />
// - uma chamada para chopstick[second].v()<br />
for(int i = 0; i < ITERATIONS; i++) {<br />
cout << "Philosopher " << n << " thinking ...\n";<br />
for(int i = 0; i < DELAY * 10; i++);<br />
<br />
cout << "Philosopher " << n << " eating ...\n";<br />
for(int i = 0; i < DELAY; i++);<br />
}<br />
<br />
return n;<br />
}<br />
<br />
int main()<br />
{<br />
cout << "The Dining-Philosophers Problem\n";<br />
<br />
Thread * phil[5];<br />
for(int i = 0; i < 5; i++)<br />
phil[i] = new Thread(&philosopher, i);<br />
<br />
int status;<br />
for(int i = 0; i < 5; i++) {<br />
phil[i]->join(&status);<br />
if(status == i)<br />
cout << "Philosopher " << i << " went to heaven!\n";<br />
else<br />
cout << "Philosopher " << i << " went to hell!\n";<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Softwares básicos, caso Hello Word! (Trabalho 2) Entrega dia 09/11}}<br />
<br />
== Softwares básicos, caso Hello Word! ==<br />
<br />
O objetivo do experimento de hoje é pesquisar e entender os processos de atribuição de endereços de programas realizados em tempo de compilação pelos softwares básicos como: compilador, linker, e assembler. Sendo assim, neste experimento vamos utilizar os seguintes softwares para criação e análise de código:<br />
<br />
*'''GCC''': compilador para gerar código objeto a partir de um código de programa escrito na linguagem c;<br />
*'''GNU Linker (LD)''': Para vincular os códigos (módulos) objetos do programa;<br />
*[https://linux.die.net/man/1/ld| Linker ] <br />
*'''GNU Assembler''': Para gerar o código executável a partir do código objeto;<br />
*[https://linux.die.net/man/1/as | assembler]<br />
* '''OBJDUMP''': Para mostrar informações do código;<br />
*[https://linux.die.net/man/1/objdump | Objdump ]<br />
<br />
<br />
A seguir segue descrito o programa a ser utilizado no exercício 1:<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
int main()<br />
{<br />
printf("Hello, World!");<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
Trata-se do programa hello word, este programa apenas exibe uma mensagem na tela. No entanto, vamos analisar como são as etapas confecção do executável a partir deste código ''simples''. <br />
<br />
Exercício 1: <br />
* Compile o programa hello word, e o transforme em código objeto utilizando o programa GCC. Para esta tarefa execute o seguinte comando:<br />
<code><br />
gcc -o hello hello.c <br />
</syntaxhighlight><br />
* Agora abra o código objeto utilizando o programa OBJDUMP.<br />
<code><br />
objdump -D hello<br />
</syntaxhighlight><br />
* Identifique quais são as seções de código obtidas a partir do '''hello.c'''.<br />
* Pesquise e entenda o significado das seções de código: .bss, .txt, .data, .init.<br />
* Faça uma análise e identifique o endereço de memória que o programa ''hello world'' vai ser carregado. <br />
* Este código objeto é relocável? Justifique sua resposta.<br />
* Agora gere o código assembly do hello world.<br />
<code><br />
gcc -S hello.c<br />
</syntaxhighlight> <br />
*Agora gere o código executável utilizando o programa '''AS''' e o programa '''LD'''.<br />
<code><br />
as -o hello.o hello.s<br />
</syntaxhighlight><br />
* Como a etapa de linkagem para a construção do código executável está sendo executada sem o auxílio do '''GCC''', necessitamos vincular manualmente as bibliotecas necessárias. Para criar apropriadamente o executável vamos precisar das bibliotecas '''ld-linux-x86-64.so.2''', '''crt1.o''', '''crti.o''', '''crtn.o'''.<br />
* Para descobrir suas respectivas localizações use o comando '''LOCATE'''. Por exemplo:<br />
<code><br />
<br />
locate crti.o <br />
<br />
</syntaxhighlight><br />
<br />
ou <br />
<br />
<code><br />
<br />
find /usr/ -name crti*<br />
<br />
</syntaxhighlight><br />
<br />
* Agora que já sabemos a localização das bibliotecas necessárias vamos vincular essas a nossa aplicação.<br />
<code><br />
ld --dynamic-linker /caminho/ld-linux-x86-64.so.2 /caminho/crt1.o /caminho/crti.o /caminho/crtn.o hello.o -lc -o hello.exe<br />
</syntaxhighlight><br />
<br />
* Agora abra o código objeto utilizando o programa OBJDUMP.<br />
* Faça uma análise e identifique o endereço de memória em que o programa ''hello world'' inicializa suas estruturas na memória.<br />
* Dica!<br />
<code><br />
objdump -D -s -j .init hello.exe<br />
</syntaxhighlight><br />
* Houve diferença entre os endereços do programa executável em relação ao código objeto? Explique.<br />
* Explique as principais diferenças entre o arquivo objeto .o e o executável final. (dica utilize o objdump para fazer essa análise)<br />
{{collapse bottom}}<br />
<ol><br />
<li> Estudar e executar o código em http://cs.lmu.edu/~ray/notes/gasexamples/ <br />
Detalhes das chamadas na arquitetura x86_64 ver em https://lwn.net/Articles/604287/ <br />
<li>Estudar e executar o código usando a função (em conformidade com a API POSIX) write() para o ''hello world'':<br />
<code><br />
#include <unistd.h> <br />
<br />
main()<br />
{<br />
write(1,"Alo Mundo\n",10);<br />
}<br />
</syntaxhighlight><br />
</li><br />
<li> Use o comando strace para verificar todas as chamadas de sistema dos programas acima.<br />
</li><br />
<li><br />
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:<br />
<code><br />
main()<br />
{<br />
meu_hello_world();<br />
}<br />
</syntaxhighlight><br />
</li><br />
Gere o assembly do código em C e discuta a diferença entre uma chamada de função e uma chamada de sistema.<br />
<li><br />
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:<br />
<code><br />
#include <string.h><br />
main()<br />
{<br />
char *p="Tudo bem com vocês?";<br />
meu_hello_world(p, strlen(p));<br />
}<br />
</syntaxhighlight><br />
Solução:<br />
{{collapse top|Solução}}<br />
<code><br />
modificado de http://cs.lmu.edu/~ray/notes/gasexamples/<br />
.global meu_hello_world<br />
<br />
.text<br />
meu_hello_world:<br />
<br />
push %rdi # salva primeiro parâmetro<br />
push %rsi # salva segundo parâmetro<br />
mov $1, %rax # system call 1 é write<br />
mov $1, %rdi # file handle 1 é stdout<br />
mov $message, %rsi # endereço da string<br />
mov $13, %rdx # número de bytes da string<br />
syscall # chamada ao sistema<br />
<br />
pop %rdx # o que havia sido passado em rsi (número de bytes) é colocado em rdx<br />
pop %rsi # o que havia sido colocado em rdi (endereço da string) é colocado em rsi<br />
mov $1, %rax # system call 1 is write<br />
mov $1, %rdi # file handle 1 é stdout<br />
syscall # nova chamada ao sistema<br />
<br />
ret<br />
<br />
message:<br />
.ascii "Hello, World\n"<br />
</syntaxhighlight><br />
</li><br />
</ol><br />
{{collapse bottom}}</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=SOP29005-2019-2&diff=162032SOP29005-2019-22019-10-04T12:14:07Z<p>127.0.0.1: /* PARTE 2 - POSIX Semaphores */</p>
<hr />
<div>=AULA 1 - Dia 30/07/2019=<br />
<br />
===Objetivos/Conteúdos===<br />
<br />
*Apresentação do Plano de Ensino<br />
**Objetivos e Conteúdo Programático da Disciplina (ver SIGAA)<br />
**Forma de Avaliação (ver SIGAA)<br />
<br />
*Introdução a Sistemas Operacionais (Cap1. do Silberschatz)<br />
**O que faz um sistema operacional (1.1)<br />
**Organização e Arquitetura de um Sistema Computacional (1.2 e 1.3)<br />
***Importância da Interrupção e Timers (1.2.1)<br />
***Estrutura de Armazenamento (1.2.2)<br />
***Estrutura de IO (1.2.3)<br />
**Estrutura e Operações de um Sistema Operacional (1.4 e 1.5)<br />
<br />
===Material de Referência===<br />
<br />
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte1.pdf Apresentação sobre histórico visão geral e estruturas básicas de um SO]<br />
* [http://codex.cs.yale.edu/avi/os-book/OSE1/slide-dir/index.html Slides Silberschatz Oitava Edição]<br />
* [http://professor.unisinos.br/barbosa/SO/ch1br.ppt Tradução Slides Silberschatz Cap1]<br />
* [http://professor.unisinos.br/barbosa/SO/ch2br.ppt Tradução Slides Silberschatz Cap2]<br />
* [http://professor.unisinos.br/barbosa/SO/ch3br.ppt Tradução Slides Silberschatz Cap3]<br />
* [http://professor.unisinos.br/barbosa/SO/ch4br.ppt Tradução Slides Silberschatz Cap4]<br />
* [http://wiki.inf.ufpr.br/maziero/doku.php?id=so:livro_de_sistemas_operacionais Livro do Prof.Maziero]<br />
* [http://deptinfo.unice.fr/~rr/l3systres/ Université Nice Sophia Antipolis]<br />
<br />
Arliones:<br />
<br />
*[https://www.dropbox.com/s/dt80g3tml65rpmg/SOP29005-parte6.odp?dl=0]<br />
*[https://www.dropbox.com/s/7lneavq0go9kz2t/SOP29005-parte7.odp?dl=0]<br />
<br />
===Leitura Recomendada===<br />
<br />
*Cap.1 do Silberschatz principalmente:<br />
**1.1 a 1.9<br />
<br />
===Exercícios Práticos de Apoio a Aula===<br />
<br />
Na sequência. com fins motivacionais, são apresentados alguns exercícios ilustrando conceitos de processos, arquivos e permissionamento.<br />
<br />
<ol><br />
<li><br />
Comando para ver todos os processos no linux:<br />
<code><br />
$ ps aux<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Colocar 2 processos se executando no contexto de um terminal e verificar número dos processos e então "destruí-los":<br />
<code><br />
$ yes > /dev/null<br />
$ yes > /dev/null<br />
$ ps <br />
$ kill -9 <pid_yes><br />
$ kill -9 <pid_yes><br />
</syntaxhighlight><br />
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.<br />
</li><br />
<li><br />
Criar um terminal adicional<br />
<code><br />
$ xterm<br />
</syntaxhighlight><br />
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:<br />
<code><br />
$ echo Alo Terminal > /dev/pts/2<br />
$ kill -9 <pid_terminal><br />
</syntaxhighlight><br />
</li><br />
<li><br />
Comunicação entre processos:<br />
<code><br />
$ cat /etc/passwd | grep home | wc -l<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Retirando a permissão de leitura de um arquivo em nível de usuário proprietário:<br />
<code><br />
$ echo Alo Mundo > alfa.txt<br />
$ ls -l alfa.txt<br />
$ cat alfa.txt<br />
$ chmod u-r alfa.txt<br />
$ cat alfa.txt<br />
$ chmod u+r alfa.txt<br />
$ cat alfa.txt <br />
</syntaxhighlight><br />
</li><br />
</ol><br />
<br />
=AULA 2 - Dia 2/08/2019=<br />
<br />
===Objetivos/Conteúdos===<br />
<br />
*Continuação da Aula<br />
*Estruturas do Sistema Operacional (cap.2)<br />
**Serviços do Sistema Operacional (2.1)<br />
**Interfaces com Usuários (2.2)<br />
**Chamadas do Sistema (2.3)<br />
**Tipos de Chamadas de Sistema (2.4) ver Fig.2.8<br />
***Chamadas de Controle de Processos<br />
**Arquiteturas e Estruturas de Sistemas Operacionais (2.7)<br />
**Máquinas Virtuais (2.8)<br />
<br />
===Material de Referência===<br />
<br />
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte1.pdf Apresentação sobre histórico visão geral<br />
* [http://www.fil.univ-lille1.fr/~sedoglav/OS/TP.html ]<br />
<br />
===Leitura Recomendada===<br />
<br />
*Cap.2 do Silberschatz principalmente:<br />
**2.1 a 2.8<br />
<br />
===Exercícios===<br />
<br />
=AULA 3 - Dia 7/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*Continuação da aula anterior<br />
**Chamadas do Sistema (2.3)<br />
**Tipos de Chamadas de Sistema (2.4) ver Fig.2.8<br />
***Chamadas de Controle de Processos<br />
**Arquiteturas e Estruturas de Sistemas Operacionais (2.7)<br />
**Máquinas Virtuais (2.8)<br />
<br />
===Exercícios===<br />
<br />
<ol><br />
<li> Estudar e executar o código em http://cs.lmu.edu/~ray/notes/gasexamples/ <br />
Detalhes das chamadas na arquitetura x86_64 ver em https://lwn.net/Articles/604287/ <br />
<li>Estudar (usar o man) e executar o código usando a função (em conformidade com a API POSIX) write() para o ''hello world'':<br />
<code><br />
#include <unistd.h> <br />
<br />
main()<br />
{<br />
write(1,"Alo Mundo\n",10);<br />
}<br />
</syntaxhighlight><br />
</li><br />
<li> Use o comando strace para verificar todas as chamadas de sistema dos programas acima.<br />
</li><br />
<li><br />
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() 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:<br />
<code><br />
void meu_hello();<br />
<br />
int main()<br />
{<br />
meu_hello();<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
</li><br />
Gere o assembly do código em C e discuta a diferença entre uma chamada de função e uma chamada de sistema.<br />
<li><br />
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:<br />
<code><br />
#include <string.h><br />
main()<br />
{<br />
char *p="Tudo bem com vocês?";<br />
meu_hello_world(p, strlen(p));<br />
}<br />
</syntaxhighlight><br />
Solução:<br />
{{collapse top|Solução}}<br />
<code><br />
modificado de http://cs.lmu.edu/~ray/notes/gasexamples/<br />
.global meu_hello_world<br />
<br />
.text<br />
meu_hello_world:<br />
<br />
push %rdi # salva primeiro parâmetro<br />
push %rsi # salva segundo parâmetro<br />
mov $1, %rax # system call 1 é write<br />
mov $1, %rdi # file handle 1 é stdout<br />
mov $message, %rsi # endereço da string<br />
mov $13, %rdx # número de bytes da string<br />
syscall # chamada ao sistema<br />
<br />
pop %rdx # o que havia sido passado em rsi (número de bytes) é colocado em rdx<br />
pop %rsi # o que havia sido colocado em rdi (endereço da string) é colocado em rsi<br />
mov $1, %rax # system call 1 is write<br />
mov $1, %rdi # file handle 1 é stdout<br />
syscall # nova chamada ao sistema<br />
<br />
ret<br />
<br />
message:<br />
.ascii "Hello, World\n"<br />
</syntaxhighlight><br />
</li><br />
</ol><br />
{{collapse bottom}}<br />
<br />
=AULA 4 - Dia 9/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*PARTE 2A: Gerenciamento de Processos (cap.3)<br />
*3.1.Conceito de Processo<br />
*3.2.Escalonamento de Processos<br />
*3.3.Operações sobre Processos (Laboratório Operações sobre Processos no Linux: Fork/Exec/Wait)<br />
<br />
===Material de Referência===<br />
<br />
*Slides do Cap.3 - Silberschatz<br />
*Laboratório Fork/Exec/Wait<br />
<br />
=== Exercícios de Demonstração===<br />
<br />
#Executar em um terminal o comando top. Em um outro terminal executar:<br />
yes > /dev/null &<br />
yes > /dev/null &<br />
#Parar um dos processos yes<br />
kill -STOP <pid_yes><br />
#Continuar o processo<br />
kill -CONT <pid_yes><br />
#Destruir todos<br />
killall yes<br />
<br />
=AULA 5 - Dia 14/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*Ainda Processos<br />
*Cap.3.2..Escalonamento de Processos<br />
*Cap.2.3.Operaçṍes sobre processos<br />
*Finalização do Laboratório Fork/Exec/Wait<br />
<br />
===Adendo===<br />
<br />
*Estudar e comentar [https://www.geeksforgeeks.org/wait-system-call-c/]<br />
<br />
=AULA 6 - Dia 16/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*Comunicação Interprocessos (3.4 e 3.5)<br />
*Laboratório de Memória Compartilhada<br />
<br />
=AULA 7 - Dia 21/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Comunicação Interprocessos: Troca de Mensagens (3.6)<br />
*Laboratório de Pipes<br />
<br />
=AULA 8 - Dia 23/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Finalização Lab. pipes nomeados.<br />
*Threads ((cap.4.1, 4.2)<br />
*Lab.Threads de Aplicação<br />
<br />
=AULA 9 - Dia 28/08/2019=<br />
<br />
*Laboratório: Ainda Threads - Um escalonador semi-automático<br />
<br />
<br />
=AULA 10 - Dia 30/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Repassar um primeiro estudo sobre o RTOS<br />
*Revisar Processos e Threads<br />
<br />
==Questionário - Processos==<br />
<br />
#Conceitue processo. Descreva e explique cada uma das seções de um processo na memória.<br />
#Faça um diagrama e explique os possíveis estados de um processo no sistema. O que produz a transição entre estados?<br />
#O que é um Bloco de Controle de Processo? Quais informações ficam armazenadas neste bloco?<br />
#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.<br />
#Explique o que é multiprogramação e escalonamento de processos.<br />
#O que é a fila de processos prontos?<br />
#Diferencie um processo limitado por IO de um processo limitado por CPU.<br />
#Diferencie escalonamento de longo prazo de escalonamento de curto prazo.<br />
#Discuta o papel da interrupção na troca de contexto entre processos.<br />
#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?<br />
#Explique como funciona a chamada exec no UNIX/Linux<br />
#Explique como funciona a chamada wait no UNIX/Linux e como é possível retornar valores de um filho para o pai.<br />
#Faça um esqueleto de um programa UNIX/Linux que ao se tornar processo cria 3 filhos e espera pela execução dos mesmos.<br />
<br />
==Questionário - Comunicação entre Processos==<br />
<br />
#Diferenciar processos independentes de processos cooperantes.<br />
#Enumere e explique quatro razões para cooperação entre processos.<br />
#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.<br />
#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.<br />
#A memória compartilhada requer chamada ao sistema na sua operação? Discuta.<br />
#Por que o processo de troca de mensagem deve ser mais lento que a memória compartilhada?<br />
#Apresente em pseudocódigo uma proposta de funcionamento do problema do produtor consumidor usando memória compartilhada.<br />
#A construção de uma solução para o problema produtor consumidor pode ser facilitado pelo uso da memória compartilhada? Discuta.<br />
#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?<br />
#Enumere três métodos de implementação de uma lógica de ligação (link) entre processos.<br />
#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.<br />
#Descreva a variante assimétrica da troca direta de mensagens. O que muda em termos de primitiva de comunicação?<br />
#Descreva o problema de hard-coding associado a nomeação direta e como pode ser contornado através da nomeação/comunicação indireta?<br />
#O que é uma caixa postal? Como o Posix identifica uma caixa postal no caso de fila de mensagens?<br />
#Dois processos podem usar mais do que uma caixa postal para se comunicar? Qual a condição para que isto ocorra?<br />
#Descreva as duas operações básicas para a troca de mensagens com Caixa Postal.<br />
#Descreva na comunicação indireta via Caixa Postal as 3 propriedades básicas.<br />
#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.<br />
#De que forma a caixa postal estando no espaço de endereçamento de um processo (propriedade) afeta a recepção por mensagens? Descreva.<br />
#Quais as operações sobre uma caixa postal criada no espaço do sistema operacional deverão ser disponíveis? Descreva.<br />
#A transmissão de mensagem pode ser com e sem bloqueio. Descreva as 4 possibilidades (síncrona/assíncrona).<br />
#Discuta as 3 possibilidades de armazenamento de mensagens em buffer. Em que condições um remetente pode ser bloqueado?<br />
<br />
==ETAPA 1 - Projeto Final==<br />
<br />
*Apresentação (slides) sobre a parte de gerenciamento de tarefas no RTOS;<br />
*apresentação dia 18/09/2019<br />
<br />
==Referências==<br />
<br />
*[https://www.freertos.org/RTOS.html Site do FreeRTOS] ver Mastering the FreeRTOS Real Time Kernel - a Hands On Tutorial Guide <br />
*[https://www.embarcados.com.br/rtos-sistema-operacional-de-tempo-real/]<br />
*[https://github.com/feilipu/avrfreertos]<br />
<br />
=AULA 11 - Dia 4/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Pico de CPU X Pico de IO <br />
*Preempção X Não Preempção<br />
*Escalonamento de Processos: Escalonamento FCFS<br />
<br />
<br />
=AULA 12 - Dia 6/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Escalonamento de Processos: <br />
**Shortest Job First (preemptivo e não preemptivo)<br />
**Prioridade (preemptivo e não preemptivo)<br />
**Round-Robin: Preemptivo<br />
*Lab.Round Robin<br />
<br />
==Material de Referência==<br />
<br />
http://docente.ifsc.edu.br/andre.damato/sop2018/SOP2018-parte2.pdf<br />
<br />
<br />
=AULA 13 - Dia 13/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Sincronização entre Processos<br />
*Laboratório do Esquema de Peterson<br />
<br />
==Material de Referência==<br />
<br />
*Livro Silberchatz<br />
*https://www.os-book.com/OSE1/slide-dir/PPT-dir/ch6.ppt<br />
<br />
=AULA 14 - Dia 18/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Sincronização entre Processos<br />
*Lock de Hardware<br />
*Laboratório do TSL<br />
<br />
==Laboratório Proposto==<br />
<br />
*Refazer o problema proposto usando uma instrução simualada de test and set. Prever um liite superior para entrada de um processo na região crítica.<br />
<br />
==Material de Referência==<br />
<br />
*Livro Silberchatz<br />
*https://www.os-book.com/OSE1/slide-dir/PPT-dir/ch6.ppt<br />
<br />
<br />
=AULA 15 - Dia 20/08/2019=<br />
<br />
==O ATmega238 usado no Arduino UNO==<br />
<br />
Ver [https://pt.wikipedia.org/wiki/ATmega328]<br />
<br />
==O Arduino UNO==<br />
<br />
Ver [https://pt.wikipedia.org/wiki/Arduino]<br />
Ver [https://github.com/feilipu/Arduino_FreeRTOS_Library]<br />
<br />
==O FreeRtos para o Arduino==<br />
<br />
Ver [https://github.com/feilipu/Arduino_FreeRTOS_Library]<br />
<br />
Para instalar no IDE:<br />
*Baixar o ZIP do link acima<br />
*No IDE importar a biblioteca:<br />
**sketch->IncluirBiblioteca->Adicionar do arquivo ZIP<br />
<br />
<br />
==Código Experimental==<br />
<br />
Este código demonstra a ocorrência de "race condition".<br />
<br />
<syntaxhighlight lang=c><br />
// Code based on Examples of Arduino and examples <br />
// from https://github.com/feilipu/Arduino_FreeRTOS_Library<br />
<br />
#include <Arduino_FreeRTOS.h><br />
#include <FreeRTOSVariant.h><br />
#include <task.h><br />
#include <semphr.h><br />
<br />
#define TAM_BUFF 10<br />
<br />
volatile unsigned long race_flag=0xFFEEDDCC;<br />
volatile unsigned long int cont;<br />
int task_cont=0;<br />
<br />
void PrintSerial( void *pvParameters ); // Task para imprimir valor de race_flag<br />
void TaskBlink( void *pvParameters );<br />
void TaskSetarace_flag(void *pvParameters); //Task que atribui race_flag=0xFFEEDDCC<br />
void TaskZerarace_flag(void *pvParameters); //Task que atribui race_flag=0xAA0000AA<br />
<br />
// função de setup<br />
<br />
void setup() {<br />
<br />
Serial.begin(9600);<br />
<br />
while (!Serial) {<br />
; // wait for serial port to connect. Needed for native USB, on LEONARDO, MICRO, YUN, and other 32u4 based boards.<br />
}<br />
<br />
<br />
// criar as 2 tarefas<br />
<br />
xTaskCreate(<br />
TaskBlink<br />
, (const portCHAR *)"Blink" // A name just for humans<br />
, 128 // This stack size can be checked & adjusted by reading the Stack Highwater<br />
, NULL<br />
, 1 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.<br />
, NULL );<br />
<br />
xTaskCreate(<br />
TaskPrintSerial<br />
, (const portCHAR *) "PrintSerial"<br />
, 128 // Stack size<br />
, NULL<br />
, 1 // Priority<br />
, NULL );<br />
<br />
xTaskCreate(<br />
TaskSetarace_flag<br />
, (const portCHAR *) "Setarace_flag"<br />
, 128 // Stack size<br />
, NULL<br />
, 1 // Priority<br />
, NULL );<br />
<br />
xTaskCreate(<br />
TaskZerarace_flag<br />
, (const portCHAR *) "Zerarace_flag"<br />
, 128 // Stack size<br />
, NULL<br />
, 1 // Priority<br />
, NULL );<br />
<br />
cont = race_flag;<br />
<br />
// escalonador toma conta a partir daqui<br />
<br />
}<br />
<br />
void loop()<br />
{<br />
// nada a fazer aqui<br />
}<br />
<br />
/*--------------------------------------------------*/<br />
/*---------------------- Tasks ---------------------*/<br />
/*--------------------------------------------------*/<br />
<br />
void TaskBlink(void *pvParameters) // This is a task.<br />
{<br />
(void) pvParameters;<br />
<br />
/*<br />
Blink<br />
Turns on an LED on for one second, then off for one second, repeatedly.<br />
<br />
Most Arduinos have an on-board LED you can control. On the UNO, LEONARDO, MEGA, and ZERO <br />
it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN takes care <br />
of use the correct LED pin whatever is the board used.<br />
<br />
The MICRO does not have a LED_BUILTIN available. For the MICRO board please substitute<br />
the LED_BUILTIN definition with either LED_BUILTIN_RX or LED_BUILTIN_TX.<br />
e.g. pinMode(LED_BUILTIN_RX, OUTPUT); etc.<br />
<br />
If you want to know what pin the on-board LED is connected to on your Arduino model, check<br />
the Technical Specs of your board at https://www.arduino.cc/en/Main/Products<br />
<br />
This example code is in the public domain.<br />
<br />
modified 8 May 2014<br />
by Scott Fitzgerald<br />
<br />
modified 2 Sep 2016<br />
by Arturo Guadalupi<br />
*/<br />
<br />
// initialize digital LED_BUILTIN on pin 13 as an output.<br />
pinMode(LED_BUILTIN, OUTPUT);<br />
<br />
for (;;) // A Task shall never return or exit.<br />
{<br />
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)<br />
vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second<br />
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW<br />
vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second<br />
}<br />
}<br />
<br />
<br />
<br />
<br />
void TaskPrintSerial(void *pvParameters) // Task que imprime na serial - must be improved...<br />
{<br />
(void) pvParameters;<br />
/*<br />
<br />
*/<br />
<br />
<br />
for (;;)<br />
{ <br />
while (cont==0xAA0000AA || cont==0xFFEEDDCC)<br />
cont = race_flag;<br />
;<br />
<br />
Serial.println("Problemas: valor race_flag é");<br />
Serial.println(cont, HEX);<br />
<br />
vTaskDelay(5); // one tick delay (15ms) in between reads for stability - b<br />
cont = race_flag;<br />
}<br />
}<br />
<br />
void TaskSetarace_flag(void *pvParameters) <br />
{<br />
(void) pvParameters;<br />
const TickType_t xMaxBlockTimeTicks = 0x20;<br />
/*<br />
<br />
*/<br />
<br />
race_flag=0xAA0000AA;<br />
for (;;)<br />
{<br />
race_flag=0xAA0000AA;<br />
//Serial.println("Produtor");<br />
vTaskDelay( ( rand() %xMaxBlockTimeTicks) ); <br />
} <br />
<br />
}<br />
<br />
void TaskZerarace_flag(void *pvParameters) <br />
{<br />
(void) pvParameters;<br />
const TickType_t xMaxBlockTimeTicks = 0x20;<br />
/*<br />
<br />
*/<br />
race_flag=0xFFEEDDCC;<br />
<br />
for (;;)<br />
{<br />
race_flag=0xFFEEDDCC;<br />
vTaskDelay( ( rand() %xMaxBlockTimeTicks) ); <br />
if(task_cont++==100) {<br />
delay(1);<br />
Serial.println("Fim TaskZera - valor race_flag ");<br />
Serial.println(race_flag, HEX);<br />
for(;;);<br />
} <br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=AULA 16 - Dia 25/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Preparação de exemplos de RTOS sobre Arduíno para apresentação na sexta;<br />
<br />
=Laboratórios Propostos= <br />
<br />
Considere o código abaixo. Observe que a região de dados compartilhada shared_data é zerada pelo pai e setada pelo processo filho. O pai detecta inconsistências nos dados que operou. Tente corrigir usando o esquema de Peterson para acesso a região crítica. Crie uma função de entrada e de saída da região crítica.<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
<br />
<br />
#define BUFFER_SIZE 4096<br />
char *shared_data;<br />
char reference_data[BUFFER_SIZE];<br />
<br />
main()<br />
{ <br />
key_t key;<br />
int shmid;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, BUFFER_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
shared_data = shmat(shmid, (void *)0, 0);<br />
<br />
if (shared_data == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int count=0; <br />
memset(reference_data,0,BUFFER_SIZE); <br />
for(;;){ <br />
memset(shared_data,0,BUFFER_SIZE);<br />
if (memcmp(shared_data, reference_data, BUFFER_SIZE)!=0) {<br />
count++;<br />
if (count%1000000==0)<br />
printf("Processo pai detectou algo errado nos dados %d\n", count); <br />
} <br />
} <br />
<br />
<br />
}<br />
else { /*Child code */<br />
<br />
for(;;){ <br />
memset(shared_data,1,BUFFER_SIZE); <br />
}<br />
<br />
}<br />
<br />
if (shmdt(shared_data) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
Possível solução:<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
#include <unistd.h><br />
<br />
#define BUFFER_SIZE 4096<br />
#define ID_PAI 0<br />
#define ID_FILHO 1<br />
#define FALSE 0<br />
#define TRUE 1<br />
<br />
char *shared_data;<br />
char reference_data[BUFFER_SIZE];<br />
<br />
struct tipo_peterson{<br />
char flag[2];<br />
char turn;<br />
} *pet_struct;<br />
<br />
void ent_sec_crit(int id)<br />
{<br />
char id_outro = (id+1)%2;<br />
<br />
pet_struct->flag[id] = TRUE; // indica que o processo deseja entrar na região crítica<br />
pet_struct->turn = id_outro; // o processo sinaliza para o outrao entrar, <br />
// caso o outro esteja entrando<br />
// este ponto é uma race condition: turn pode ser 0 ou 1 <br />
while ( (pet_struct->flag[id_outro]==TRUE) && (pet_struct->turn == id_outro) )<br />
;<br />
}<br />
<br />
void sai_sec_crit(int id)<br />
{<br />
pet_struct->flag[id] = FALSE;<br />
}<br />
<br />
int main()<br />
{ <br />
key_t key;<br />
int shmid;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, BUFFER_SIZE+sizeof(struct tipo_peterson), S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
shared_data = shmat(shmid, (void *)0, 0);<br />
pet_struct = (struct tipo_peterson *) (shared_data + BUFFER_SIZE); <br />
<br />
if (shared_data == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int count=0; <br />
memset(reference_data,0,BUFFER_SIZE); <br />
for(;;){ <br />
ent_sec_crit(ID_PAI);<br />
memset(shared_data,0,BUFFER_SIZE);<br />
if (memcmp(shared_data, reference_data, BUFFER_SIZE)!=0) {<br />
count++;<br />
if (count%1000000==0)<br />
printf("Processo pai detectou algo errado nos dados %d\n", count); <br />
} <br />
sai_sec_crit(ID_PAI);<br />
} <br />
<br />
<br />
}<br />
else { /*Child code */<br />
<br />
for(;;){<br />
ent_sec_crit(ID_FILHO); <br />
memset(shared_data,1,BUFFER_SIZE);<br />
sai_sec_crit(ID_FILHO); <br />
}<br />
<br />
}<br />
<br />
if (shmdt(shared_data) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
=AULA 17 - Dia 27/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Apresentação dos Trabalhos<br />
*Definição da próxima etapa<br />
<br />
=AULA 18 - Dia 02/10/2019=<br />
<br />
==Objetivos==<br />
<br />
*Semáforos, Deadlock e o Problema da Inversão de Prioridade<br />
*Laboratório de Pthreads e Mutex;<br />
<br />
==Laboratório Proposto==<br />
<br />
*Lab. Programação concorrente - Parte 1<br />
<br />
==Materia de Referência==<br />
<br />
*[https://www.os-book.com/OSE1/slide-dir/PDF-dir/ch6.pdf]<br />
<br />
==Desafio==<br />
<br />
Usar <br />
ps -T aux | grep ex1vA<br />
<br />
Para ver os threads dormindo...<br />
<br />
Otimizar o programa abaixo<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <pthread.h><br />
#include <stdlib.h><br />
#include <unistd.h><br />
#include <time.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
pthread_mutex_t mut;<br />
<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
<br />
<br />
long long i;<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
usleep(5000000);<br />
printf("Novo saldo = %d\n",novo_saldo);<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d\n", (i+1));<br />
exit(-1);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
printf("Saldo final é %d\n", saldo);<br />
}<br />
</syntaxhighlight><br />
<br />
=AULA 19 - Dia 04/10/2019=<br />
<br />
==Objetivos==<br />
<br />
*Ainda Semáforos, Deadlock e o Problema da Inversão de Prioridade<br />
*Laboratório de Pthreads com semáforo binário;<br />
*Laboratório de Pthreads com produtor e consumidor<br />
<br />
<br />
==Laboratório Proposto==<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Programação concorrente}}<br />
<br />
== Programação concorrente ==<br />
<br />
<br />
===PARTE 1 - Mutex e Biblioteca libpthreads===<br />
<br />
;POSIX Threads<br />
A 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):<br />
*''pthread_create'': cria uma thread;<br />
*''pthread_kill'': força a terminação de uma thread;<br />
*''pthread_join'': sincroniza o final de uma thread (qual a diferença/semelhança com o ''wait'' que usamos para processos?);<br />
*''pthread_exit'': finaliza uma thread.<br />
Para utilizar estas funções é necessário linkar o programa à libpthread (''-lpthread''). <br />
<br />
<br />
;POSIX pthread mutex<br />
<br />
A biblioteca pthread implementa um tipo ''pthread_mutex_t'', que garante a exclusão mútua entre threads. Estes mutex são manipulados através das funções (acesse as man-pages das chamadas para maiores detalhes):<br />
*''pthread_mutex_lock'': acessa um mutex.<br />
*''pthread_mutex_trylock'': tenta acessar um mutex (retorna valor indicando sucesso ou falha no lock).<br />
*''pthread_mutex_unlock'': libera um mutex.<br />
<br />
<br />
<br />
;Exercício 1<br />
<br />
O programa abaixo cria 5 threads, e cada uma destas threads atualiza uma variável global (memória compartilhada).<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
#include <pthread.h><br />
#include <stdlib.h><br />
#include <unistd.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
pthread_mutex_t mut;<br />
<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
long long i;<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
sleep(1);<br />
printf("Novo saldo = %d\n",novo_saldo);<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d\n", (i+1));<br />
exit(-1);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
printf("Saldo final é %d\n", saldo);<br />
}<br />
</syntaxhighlight><br />
<br />
# Compile este programa. <br />
# Execute este programa várias vezes. Ele funciona? Será que ele gera as saídas esperadas?<br />
# Identifique as '''seções críticas''' do programa.<br />
# Corrija o programa utilizando '''mutex'''. <br />
# Analise a função ''AtualizaSaldo()'' com a sua solução. Lembre-se que o uso do mutex implica em apenas uma thread acessar a seção crítica por vez, enquanto outras threads ficam bloqueadas, esperando. Disso vem que, quanto menor o trecho de código entre um ''lock'' e um ''unlock'', menos tempo uma thread necessita ficar esperando.<br />
<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <cstring><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
<br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
sem_t sem;<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
int value;<br />
sem_wait(&sem);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
sem_getvalue(&sem, &value);<br />
printf("valor sem = %d\n", value);<br />
sem_post(&sem);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
sem_init(&sem,0,1);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
sem_destroy(&sem);<br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
===PARTE 2 - POSIX Semaphores Binários===<br />
<br />
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):<br />
*''sem_init'': inicializa um semáforo;<br />
*''sem_destroy'': destroy um semáforo;<br />
*''sem_wait'': implementa a operação ''p'';<br />
*''sem_post'': implementa a operação ''v''.<br />
Para utilizar estas funções é necessário linkar o programa à librt ou à libpthread (''-lrt'' ou ''-lpthread'').<br />
<br />
;Exercício 1<br />
Modifique o programa para usar um semáforo binário ao invés de um mutex em sua solução.<br />
<br />
;Exercício 2 - Fazer em casa<br />
Refaça o exercício 3 usando processos criados com fork e exec. O semáforo deve ser criado em uma região de memória compartilhada.<br />
<br />
===PARTE 3 - POSIX Semaphores===<br />
<br />
;Exercício 3<br />
Implemente com pthreads e semáforos/mutex a solução do produtor/comsumidor conforme sugerido no livro do Silberchatz. USe dois semáforos: (i) um para controlar o numero de itens vazios no buffer (semáforo empty - quando zero o thread produtor deve parar de produzir). (ii) um semáforo para controlar o numero de itens ocupados no buffer (semáforo full - quando zero o consumidor deve parar de consumir).<br />
<br />
<br />
===PARTE 4 - POSIX Semaphores===<br />
<br />
;Exercício 4<br />
<br />
O programa abaixo manipula uma matriz de tamanho MxN (veja os defines para o tamanho da matriz). A função ''SumValues'' soma todos os valores em uma linha da matriz. A linha a ser somada é identificada pela variável ''i''. Modifique o programa principal (''main'') nos locais indicados para:<br />
# Criar N threads, uma para somar os valores de cada linha.<br />
# Receber o resultado do somatório de cada linha e gerar o somatório total da matriz.<br />
# Analise o programa: há problemas de sincronização que precisam ser resolvidos? Se sim, resolva-os.<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include "thread.h"<br />
<br />
/* number of matrix columns and rows */<br />
#define M 5<br />
#define N 10<br />
<br />
using namespace std;<br />
<br />
int matrix[N][M];<br />
Thread *threads[N];<br />
<br />
<br />
/* thread function; it sums the values of the matrix in the row */<br />
int SumValues(int i)<br />
{<br />
int n = i; /* number of row */<br />
int total = 0; /* the total of the values in the row */<br />
int j;<br />
for (j = 0; j < M; j++) /* sum values in the "n" row */<br />
total += matrix[n][j];<br />
cout << "The total in row" << n << " is " << total << "." << endl;<br />
/* terminate a thread and return a total in the row */<br />
exit(total);<br />
}<br />
<br />
int main(int argc, char *argv[])<br />
{<br />
int i, j;<br />
int total = 0; /* the total of the values in the matrix */<br />
<br />
/* initialize the matrix */<br />
for (i = 0; i < N; i++)<br />
for (j = 0; j < M; j++)<br />
matrix[i][j] = i * M + j;<br />
<br />
/* create threads */<br />
/* COLOQUE SEU CÓDIGO PARA CRIAR AS THREADS AQUI! */<br />
<br />
/* wait for terminate a threads */<br />
/* COLOQUE SEU CÓDIGO PARA PEGAR O SOMATÓRIO DE LINHAS E TOTALIZAR A SOMA DA MATRIZ AQUI! */<br />
<br />
cout << "The total values in the matrix is " << total << endl;<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
{{collapse bottom}}<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Escalonamento Round Robin e FCFS para Threads"}}<br />
<br />
== Escalonamento Round-Robin ==<br />
<br />
OBS: ver https://www.quora.com/What-exactly-does-typedef-do-in-C<br />
<br />
O Exemplo abaixo mostra a implementação de um esquema de escalonamento Round Robin do exercício anterior.<br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
Modificado por Eraldo <br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 5<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
void runA(void) {<br />
for (;;) {<br />
printf("running A\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runB(void) {<br />
for (;;) {<br />
printf("running B\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 1<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
<br />
void scheduler_rr();<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void yield_thread()<br />
{<br />
scheduler_rr();<br />
}<br />
<br />
void delete_thread()<br />
{<br />
delete curr_thread;<br />
curr_thread=NULL;<br />
scheduler_rr();<br />
}<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
struct delta{<br />
long alfa;<br />
char epson[1000];<br />
long beta;<br />
} shar;<br />
<br />
int turn;<br />
int flag[2];<br />
<br />
#define TRUE 1<br />
#define FALSE 0<br />
<br />
void ent_rc(int p, int vt)<br />
{<br />
flag[p]=TRUE;<br />
turn = vt;<br />
if(p) p=0; else p=1;<br />
while (flag[p] && turn == vt);<br />
//printf("Thread %d: esperando para acessar a região crítica\n", p);<br />
}<br />
<br />
void sai_rc(int p)<br />
{<br />
flag[p]=FALSE;<br />
}<br />
<br />
void runA(void) {<br />
struct delta x = {0, 100};<br />
<br />
for (;;) {<br />
x.alfa=0;x.beta=0;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0);<br />
x.alfa=100;x.beta=100;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0); <br />
}<br />
}<br />
<br />
void runB(void) {<br />
<br />
for (;;) {<br />
ent_rc(1,0);<br />
printf("shar alfa = %ld shar beta = %ld \n",shar.alfa, shar.beta); // regiao crítica<br />
sai_rc(1);<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runC(void) {<br />
int i;<br />
for (i=0;i<10;i++) {<br />
printf("Thread C - parte 1\n");<br />
yield_thread();<br />
printf("Thread C - parte 2\n");<br />
yield_thread();<br />
}<br />
delete_thread();<br />
}<br />
<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
add_thread(runC);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
{{collapse bottom}}<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Um escalonador semi-automático"}}<br />
<br />
== Ainda Threads - Um escalonador semi-automático usando sinais ==<br />
<br />
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.<br />
<br />
===Exemplo 1:===<br />
<br />
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. <br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
<br />
void sig_handler(int signo)<br />
{<br />
int x;<br />
printf("Turma de SOP: recebido SIGUSR1\n");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
// Loop eterno dormindo 1s<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Fazer no terminal:<br />
ps aux<br />
anotar o pid do processo e enviar o sinal:<br />
kill -USR1 pid<br />
<br />
===Exemplo 2:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// loop eterno que nunca é executado<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Enviar o sinal USR1 para ver o efeito. <br />
<br />
===Exemplo 3:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void prepara_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void prepara_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
prepara_contexto_ping();<br />
prepara_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// A long long wait so that we can easily issue a signal to this process<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Exercício: Use o comando htop para verificar como estes threads são vistos pelo SOP.<br />
<br />
Exercício: Tente analisar as pilhas dos threads e verificar sob qual pilha o handler se executa.<br />
<br />
<br />
===Exercício 4:===<br />
<br />
Neste ponto associamos um timer ao handler com o apoio do sinal ALRM. Agora os threads são escalonados automaticamente.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
===Exercício Proposto 5===<br />
<br />
Colocar 3 threads rodando.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void preparar_contexto_ping(ucontext_t *pContext, char *p)<br />
{<br />
char *stack;<br />
<br />
getcontext(pContext);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
(*pContext).uc_stack.ss_sp = stack ;<br />
(*pContext).uc_stack.ss_size = STACKSIZE;<br />
(*pContext).uc_stack.ss_flags = 0;<br />
(*pContext).uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(pContext, (void*)(*f_ping), 1, p);<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping(&cPing, "ping");<br />
preparar_contexto_ping(&cPong, "pong");<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Threads de aplicação}}<br />
<br />
== Threads de aplicação ==<br />
<br />
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:<br />
*'''getcontext(&a)''': salva o contexto na variável '''a''';<br />
*'''setcontext(&a)''': restaura um contexto salvo anteriormente na variável '''a''';<br />
*'''swapcontext(&a,&b)''': salva o contexto atual na variável '''a''' e restaura o contexto salvo anteriormente na variável '''b''';<br />
*'''makecontext(&a, ...)''': ajusta parâmetros internos do contexto salvo em '''a''';<br />
*'''ucontext_t''': as variáveis '''a''' e '''b''' são do tipo '''ucontext_t'''. Este tipo armazena um contexto.<br />
<br />
Busque mais informações sobre estas funções utilizando o programa manpage do Linux (ex.: man getcontext).<br />
<br />
Estude o código no arquivo pingpong.c abaixo e explique seu funcionamento.<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
*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.<br />
*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.<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain, cFnew;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_new(void * arg1, void * arg2,void * arg3,void * arg4) <br />
{<br />
printf ("%s: Primeira string %s %s %s\n",(char*) arg1,(char*) arg2,(char*) arg3, (char*) arg4);<br />
swapcontext(&cFnew, &cMain); <br />
}<br />
<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
<br />
getcontext(&cFnew);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cFnew.uc_stack.ss_sp = stack ;<br />
cFnew.uc_stack.ss_size = STACKSIZE;<br />
cFnew.uc_stack.ss_flags = 0;<br />
cFnew.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cFnew, (void*)(*f_new), 4, "\tF_new", "\tAlo", "\tMundo","\tReal");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
swapcontext(&cMain, &cFnew);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
--><br />
Exercício 3: O que acontece se um dos threads é colocado para dormir? Todos os demais threads param a sua execução.<br />
<br />
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/<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Processos no Linux}}<br />
<br />
== Processos no Linux - Modificado por Eraldo ==<br />
<br />
<blockquote style="background: lime; border: 1px solid black; padding: 1em;"><br />
Processos no Linux<br />
</blockquote><br />
<br />
*Exercícios propostos pelo Prof.Arliones e Modificados por Eraldo<br />
<br />
<br />
[[imagem:DesenhoForkExec.png|border|650px]]<br />
<br />
<br />
;Syscall FORK<br />
<br />
* Em um terminal, execute "man fork"<br />
** 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'''.<br />
** O '''código''' dos dois processos (pai e filho) são '''idênticos''';<br />
** Os '''dados''' dos dois processos (pai e filho) são '''idênticos NO MOMENTO DA CRIAÇÃO''';<br />
** Execução do processo filho inicia na próxima instrução do programa (no retorno da chamada FORK);<br />
** Não é possível saber qual dos processos (pai ou filho) retormará a execução primeiro - isto fica a cargo do excalonador do SO;<br />
** Valores de retorno da chamada FORK:<br />
*** (-1): erro na criação do processo (ex.: memória insuficiente);<br />
*** (0): em caso de sucesso, este é o valor de retorno recebido pelo processo filho;<br />
*** (>0): em caso de sucesso, este é o valor de retorno recebido pelo processo pai;<br />
<br />
;Syscall JOIN<br />
<br />
* A syscall JOIN é implementada no POSIX pela função '''wait()'''. Execute "man wait".<br />
** Além da função '''wait()''', há também '''waitpid()''' e '''waitid()''';<br />
** 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);<br />
** A chamada wait também libera os recursos do processo filho que termina;<br />
** '''wait()''': esta função suspende a execução do processo chamador até que UM DOS SEUS FILHOS finalize;<br />
** '''waitpid()''': suspende a execução do processo chamador até que UM FILHO ESPECÍFICO finalize;<br />
<br />
;Syscall EXEC<br />
<br />
* A syscall EXEC é implementada no POSIX pela família de funções '''exec()'''. Execute "man exec".<br />
** As principais funções da família são '''execl()''', '''execlp()''' e '''execvp()''';<br />
** 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;<br />
** 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;<br />
<br />
<br />
;Exemplos POSIX utilizando fork/wait/exec<br />
<br />
*Exemplo 1: fork/wait básico<br />
<syntaxhighlight lang=c><br />
// ex1: fork/wait básico<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
printf("processo filho\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
printf("processo pai\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
arliones@socrates:~/tmp$ gcc ex1.c -o ex1 <br />
arliones@socrates:~/tmp$ ./ex1 <br />
processo filho pid: 27858 pid pai: 27857<br />
processo pai pid: 27857 pid pai: 5337<br />
arliones@socrates:~/tmp$ <br />
</syntaxhighlight><br />
<br />
* Exemplo 2: processos pai e filho compartilham código, mas não dados.<br />
<syntaxhighlight lang=c><br />
// ex2: fork/wait "compartilhando" dados<br />
// ex2: fork/wait "compartilhando" dados<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status, k=0;<br />
printf("processo %d\t antes do fork\n", getpid());<br />
pid = fork();<br />
printf("processo %d\t depois do fork\n", getpid());<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
k += 1000;<br />
printf("processo filho\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status); // espera o filho terminar<br />
k += 10;<br />
printf("processo pai\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
k += 1000;<br />
printf("FIM processo %d\t K: %d\n", getpid(), k); <br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
processo 17056 antes do fork<br />
processo 17056 depois do fork<br />
processo 17057 depois do fork<br />
processo filho pid: 17057 K: 1000 endereço K: 0x7ffd8923e318<br />
processo pai pid: 17056 K: 10 endereço K: 0x7ffd8923e318<br />
</syntaxhighlight><br />
<br />
* Modificação no código: comentar linhas 23 e 30<br />
<br />
<syntaxhighlight lang=bash><br />
<br />
</syntaxhighlight><br />
<br />
* Analise os resultados e busque entender a diferença.<br />
*Perguntas e desafios.:<br />
#Analisando os valores impressos de k pode-se dizer que os dados são compartilhados entre os dois processos?<br />
#O endereço de k impresso é o mesmo nos dois processos. ISto não contradiz a afirmação anterior?<br />
#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.<br />
<br />
<br />
;Exercício fork/wait<br />
<br />
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.<br />
<br />
*Use o comando pstree para verificar a árvore de processos criada.<br />
<br />
{{collapse top|Solução}}<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
<!--<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
--><br />
<br />
;DESAFIO: fork/wait<br />
<br />
Reimplementar o exercício anterior de criação de uma árvore de 3 processos, generalizando a criação de N processos onde N é repassado na linha de comando do programa. SUGESTÃO: usar um comando for, mas lembrar que se existe um fork dentro do for, então cada filho gerado dará continuidade a execução do for. É necessário que o processo faça um exit ou retorne neste momento.<br />
<br />
;DESAFIO: Exercício status/wait<br />
<br />
O ''status'' passado como parâmetro à função ''wait(&status)'' é, na verdade, o mecanismo de retorno de resultado do ''wait/waitpid''. Ao retornar, esta variável contém informações sobre o resultado da execução do processo filho. Por exemplo, se um processo terminou normalmente (i.e., chamou ''exit''), o comando ''WIFEXITED(status)'' retorna ''true''. Este comando retorna ''false'' se o processo foi abortado (e.g., ''segmentation fault'') ou morto (e.g., ''kill''). Investigue no manual do wait no Linux (''man wait'') o funcionamento do comando WEXITSTATUS(status). <br />
Imagine um problema de busca de dados armazenados na forma de uma matriz de inteiros 4x30. Você está interessado em saber quantas ocorrências de um determinado número existe em cada linha da matriz. Note que que são tarefas que podem ser paralelizadas e usufruir de um sistema capaz de executá-las em paralelo. Faça uma implementação paralelizando 4 processos filhos a partir de um pai, onde cada processo é responsável por uma busca. A quantidade de ocorrências do número buscado é retornada e capturada através de WEXITSTATUS.<br />
<br />
;Syscall EXEC<br />
<br />
*Exemplo exec()<br />
<br />
<syntaxhighlight lang=c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
execl("/bin/ls","ls","-l", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 1: Modificar o código para mostrar que o exec() não retorna (colocar um printf após o exec).<br />
<br />
*Exercício 2: Criar um exemplo (dois programas ) para demonstrar que o exec não cria novo processo. <br />
**Crie um primeiro programa (prog1) que imprime o seu pid e depois faz um exec do segundo programa.<br />
**Crie o segundo programa que simplesmente imprime o pid.<br />
<br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU ANTES DO EXEC: Meu pid é %d\n", getpid());<br />
execl("./prog2","prog2", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU DEPOIS DO EXEC:Meu pid é %d\n", getpid());<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 3: Criar um exemplo usando fork/exec mostrando que um processo pai cria um filho e espera por sua execução. O filho executa o comando "ps aux". Ambos devem mostrar seus pids.<br />
<br />
{{collapse bottom}} <br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Laboratório Memória Compartilhada entre Pai e Filho - Produtor Consumidor}}<br />
<br />
Baseado no Lab. do Prof.Arliones<br />
<br />
=== Objetivo ===<br />
<br />
*Familiarizar o aluno com o conceito de Memória Compartilhada entre Processos Pai e Filho<br />
*Familizarizar o aluno com o conceito de Produtor Consumidor<br />
<br />
=== Referencial Teórico-Prático ===<br />
<br />
* Silberchatz - 3.4 e 3.5<br />
* man nos comandos shmat e shmget<br />
<br />
=== Exemplo de Funcionamento ===<br />
<br />
No exemplo abaixo um processo pai compartilha uma área de memória com o processo filho. O processo filho escreve uma mensagem para o pai na área de memória compartilhada e termina. O processo pai é desbloqueado no wait e imprime a mensagem escrita.<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
char *ptr_msg = "alo pai, tudo bem?"; <br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
strcpy(segmento, ptr_msg);<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(&filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
=== Desafio a ser Implementado em Sala ===<br />
<br />
Construir um programa em que um processo pai atua como produtor e o processo filho atua como consumidor. O buffer circular compartilhado é um buffer de inteiro de tamanho 5. O pai alimentará o buffer com 50 itens gerados aleatóriamente entre 1 e 100. A cada escrita/leitura no buffer o produtor/consumidor deve esperar alguns milisegundos de forma a acontecer situações de buffer cheio e vazio. <br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
#include <unistd.h><br />
#include <time.h><br />
#include <sys/types.h><br />
#include <sys/wait.h><br />
<br />
<br />
<br />
#define SHM_SIZE 1024 <br />
<br />
#define BUFF_COMP_SIZE 5<br />
<br />
struct buff_comp {<br />
int buffer[BUFF_COMP_SIZE];<br />
int in,out;<br />
};<br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
struct buff_comp *p; <br />
<br />
/* initialize random seed: */<br />
srand ( time(NULL) );<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
p = (struct buff_comp *) shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
p->out = p->in = 0;<br />
<br />
if((filho = fork()) == -1)<br />
{<br />
<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
int i;<br />
for(i=0;i<50;i++) {<br />
while (p->in==p->out) {<br />
printf("FILHO: BUFFER VAZIO !!!!!!!\n");<br />
usleep(rand() % 10000 + 1);<br />
}<br />
printf("FILHO: item lido = %d\n", p->buffer[p->out]);<br />
p->out = (p->out+1)%BUFF_COMP_SIZE;<br />
}<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
int i; <br />
<br />
for(i=0;i<50;i++) {<br />
while (((p->in+1)%BUFF_COMP_SIZE) == p->out) {<br />
printf("PAI: BUFFER CHEIO !!!!!!!\n");<br />
usleep(rand() % 10000 + 1);<br />
}<br />
p->buffer[p->in] = rand() % 100 + 1;<br />
printf("PAI: item produzido = %d\n", p->buffer[p->in]);<br />
p->in = (p->in+1)%BUFF_COMP_SIZE;<br />
<br />
}<br />
wait(&filho); <br />
<br />
}<br />
<br />
<br />
if (shmdt(p) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Trocas de mensagens com pipes}}<br />
<br />
= Trocas de mensagens com pipes =<br />
<br />
;Troca de mensagens<br />
Um mecanismo disponibilizado por sistemas UNIX para troca de mensagens entre processos é o PIPE. Pipes são mecanismos de comunicação indireta onde mensagens são trocadas através de ''mailboxes''. Cada ''mailbox'' possui um identificador único, permitindo que processos identifiquem o canal de comunicação entre eles. O fluxo de mensagens em um Pipe é:<br />
*'''unidirecional''': sobre um mesmo pipe, apenas um processo envia mensagens e um processo recebe mensagens;<br />
*'''FIFO''': as mensagens são entregues na ordem de envio;<br />
*'''não-estruturado''': não há estrutura pré-definida para o formato da mensagem.<br />
No UNIX, pipes são inicializados através da '''SystemCall''' ''pipe'', que possui a seguinte sintaxe:<br />
*''int pipe(int pipefd[2])'': ''pipe'' inicializa um novo pipe no sistema e retorna, no array pipefd, os descritores identificando cada uma das pontas do pipe. A primeira posição do array, i.e. pipefd[0], recebe o descritor que pode ser aberto apenas para leitura, enquanto a segunda posição do array, i.e. pipefd[1], recebe o descritor que pode ser aberto apenas para escrita. A função retorna zero no caso de sucesso, ou -1 se ocorrer erro.<br />
As primitivas send/receive para uso de um pipe no UNIX são implementadas por '''SystemCalls''' read/write, conforme segue:<br />
*''ssize_t read(int fd, void *buf, size_t count)'': “puxa” dados do pipe identificado pelo descritor fd. Os dados recebidos são os apontados pelo ponteiro buf, sendo count a quantidade máxima de bytes a serem recebidos. A função retorna o número de bytes recebidos.<br />
*''ssize_t write(int fd, const void *buf, size_t count)'': “empurra” dados no pipe identificado pelo descritor fd. Os dados transmitidos são os apontados pelo ponteiro buf, sendo count a quantidade de bytes a serem transmitidos. A função retorna o número de bytes transmitidos.<br />
<br />
*Exemplo 1: Transmitindo e recebendo pelo próprio processo<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main()<br />
{<br />
int fd[2];<br />
char *ptr = "Alo eu mesmo";<br />
char *ptr_alvo;<br />
int tamanho_dados, ret;<br />
<br />
tamanho_dados = strlen(ptr)+1;<br />
<br />
if (pipe(fd)==-1){<br />
printf ("erro criação pipe\n");<br />
exit(-1);<br />
}<br />
printf("Transmitido %d bytes\n", tamanho_dados);<br />
write (fd[1], ptr, tamanho_dados);<br />
<br />
ptr_alvo = malloc(tamanho_dados);<br />
<br />
ret=read(fd[0],ptr_alvo,tamanho_dados);<br />
<br />
printf("ret = %d dados => %s\n", ret, ptr_alvo); <br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
*Exemplo 2: Abaixo há um exemplo de programa criando um pipe e compartilhando os descritores entre dois processos (criados via ''fork()'').<br />
<syntaxhighlight lang=c><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
<br />
char *message = "This is a message!!!" ;<br />
<br />
main()<br />
{<br />
char buf[1024] ;<br />
int fd[2];<br />
pipe(fd); /*create pipe*/<br />
if (fork() != 0) { /* I am the parent */<br />
write(fd[1], message, strlen (message) + 1) ;<br />
}<br />
else { /*Child code */<br />
read(fd[0], buf, 1024) ;<br />
printf("Got this from MaMa!!: %s\n", buf) ;<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
*'''Exercício 1: construa um “pipeline”'''. Crie um programa que conecta 4 processos através de 3 pipes. Utilize ''fork()'' para criar vários processos.<br />
<br />
<syntaxhighlight lang=cpp><br />
<br />
//Solução possível<br />
<br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
pipe(fd);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
<br />
</syntaxhighlight><br />
<br />
*'''Exercício 2: Modifique o exercício anterior para que o processo D, através de um novo pipe, mande uma mensagem diretamente para o pai de todos.<br />
<br />
<!--<br />
<code><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
int fd_retorno[2];<br />
<br />
pipe(fd);<br />
pipe(fd_retorno);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size);<br />
read(fd_retorno[0], buf, size);<br />
printf("PAI:%s\n", buf); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
char *ptr_msg_ret="Ok msg de D para o pai";<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
write(fd_retorno[1],ptr_msg_ret,strlen(ptr_msg_ret)+1);<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
*'''Exercício 3: Consultor de Login de Acesso:'''. Estude o link https://www.geeksforgeeks.org/named-pipe-fifo-example-c-program/ e projete um programa cliente servidor da seguinte forma: (i) O servidor possui uma tabela de usuários (userid). O user_id é de tamanho fixo de 7 caracteres. O servidor espera por consultas para verificar se um usuário está na tabela. Se estiver responde com o caracter 'S' senão com 'N'. (ii) O cliente espera por user_id no teclado e consulta o servidor sobre sua existência na tabela. O cliente imprime na tabela a existência ou não do usuário.<br />
<br />
*'''Exercício 4: cópia de arquivo'''. Projete um programa de cópia de arquivos chamado FileCopy usando pipes comuns. Esse programa receberá dois parâmetros: o primeiro é o nome do arquivo a ser copiado e o segundo é o nome do arquivo copiado. Em seguida, o programa criará um pipe comum e gravará nele o conteúdo do arquivo a ser copiado. O processo filho lerá esse arquivo do pipe e o gravará no arquivo de destino. Por exemplo, se chamarmos o programa como descrito a seguir:<br />
:<syntaxhighlight lang=bash><br />
$ FileCopy entrada.txt copia.txt<br />
</syntaxhighlight><br />
:o arquivo ''entrada.txt'' será gravado no pipe. O processo filho lerá o conteúdo desse arquivo e o gravará no arquivo de destino ''copia.txt''. Escreva o programa usando os pipes da API POSIX no Linux.<br />
<br />
<br />
{{collapse bottom}}<br />
<br />
=Laboratórios Disponíveis= <br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Escalonamento Round Robin e FCFS para Threads"}}<br />
<br />
<br />
== Escalonamento Round-Robin preemptivo ==<br />
<br />
OBS: ver https://www.quora.com/What-exactly-does-typedef-do-in-C<br />
<br />
A fazer: <br />
<br />
*primitiva de término de processo (destrutor do objeto); <br />
*primitiva de yield<br />
*isolar o escalonador em uma função;<br />
*isolar o dispatcher em uma função; <br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
Modificado por Eraldo <br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 5<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
void runA(void) {<br />
for (;;) {<br />
printf("running A\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runB(void) {<br />
for (;;) {<br />
printf("running B\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 1<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
<br />
void scheduler_rr();<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void yield_thread()<br />
{<br />
scheduler_rr();<br />
}<br />
<br />
void delete_thread()<br />
{<br />
delete curr_thread;<br />
curr_thread=NULL;<br />
scheduler_rr();<br />
}<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
struct delta{<br />
long alfa;<br />
char epson[1000];<br />
long beta;<br />
} shar;<br />
<br />
int turn;<br />
int flag[2];<br />
<br />
#define TRUE 1<br />
#define FALSE 0<br />
<br />
void ent_rc(int p, int vt)<br />
{<br />
flag[p]=TRUE;<br />
turn = vt;<br />
if(p) p=0; else p=1;<br />
while (flag[p] && turn == vt);<br />
//printf("Thread %d: esperando para acessar a região crítica\n", p);<br />
}<br />
<br />
void sai_rc(int p)<br />
{<br />
flag[p]=FALSE;<br />
}<br />
<br />
void runA(void) {<br />
struct delta x = {0, 100};<br />
<br />
for (;;) {<br />
x.alfa=0;x.beta=0;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0);<br />
x.alfa=100;x.beta=100;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0); <br />
}<br />
}<br />
<br />
void runB(void) {<br />
<br />
for (;;) {<br />
ent_rc(1,0);<br />
printf("shar alfa = %ld shar beta = %ld \n",shar.alfa, shar.beta); // regiao crítica<br />
sai_rc(1);<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runC(void) {<br />
int i;<br />
for (i=0;i<10;i++) {<br />
printf("Thread C - parte 1\n");<br />
yield_thread();<br />
printf("Thread C - parte 2\n");<br />
yield_thread();<br />
}<br />
delete_thread();<br />
}<br />
<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
add_thread(runC);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Um escalonador semi-automático"}}<br />
<br />
== Ainda Threads - Um escalonador semi-automático usando sinais ==<br />
<br />
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.<br />
<br />
===Exemplo 1:===<br />
<br />
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. <br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
<br />
void sig_handler(int signo)<br />
{<br />
int x;<br />
printf("Turma de SOP: recebido SIGUSR1\n");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
// Loop eterno dormindo 1s<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Fazer no terminal:<br />
ps aux<br />
anotar o pid do processo e enviar o sinal:<br />
kill -USR1 pid<br />
<br />
===Exemplo 2:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// loop eterno que nunca é executado<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Enviar o sinal USR1 para ver o efeito. <br />
<br />
===Exemplo 3:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void prepara_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void prepara_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
prepara_contexto_ping();<br />
prepara_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// A long long wait so that we can easily issue a signal to this process<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
Exercício: Tente analisar as pilhas dos threads e verificar sob qual pilha o handler se executa.<br />
<br />
===Exercício 4:===<br />
<br />
Neste ponto associamos um timer ao handler com o apoio do sinal ALRM. Agora os threads são escalonados automaticamente.<br />
<br />
<code><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void preparar_contexto_ping(ucontext_t *pContext, char *p)<br />
{<br />
char *stack;<br />
<br />
getcontext(pContext);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
(*pContext).uc_stack.ss_sp = stack ;<br />
(*pContext).uc_stack.ss_size = STACKSIZE;<br />
(*pContext).uc_stack.ss_flags = 0;<br />
(*pContext).uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(pContext, (void*)(*f_ping), 1, p);<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping(&cPing, "ping");<br />
preparar_contexto_ping(&cPong, "pong");<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Um Exemplo de Uso "API Padrão POSIX"}}<br />
<br />
== Um Exemplo de Uso "API Padrão POSIX" ==<br />
<br />
;Referências<br />
* Referência http://man7.org/linux/man-pages/man2/mmap.2.html<br />
<br />
<br />
Crie uma função soma que receba 2 ponteiros referenciando posições na memória, criadas utilizando nmap(), de maneira que estas posições armazenem números inteiros. A função soma deverá retornar a soma dos números apontados em regiões da memória sem a utilização de nenhuma rotina da biblioteca do C, que não sejam definidas por APIs posix, para criação destas <br />
regiões na memória (malloc, alloc, calloc). Após retornar o resultado da soma os devidos ponteiros deverão ser extintos da memória.<br />
<br />
<br />
*'''Experimento 1:''' Aumente o tamanho da memória alocada até quando for possível.<br />
<br />
Qual o tamanho limite da memória que você conseguiu alocar?<br />
<br />
*'''Experimento 2:''' Mude o escopo para PROT_NONE, após executar e depurar o código explique o que aconteceu.<br />
<br />
Em sua opinião NMAP trata-se de uma syscall ou de uma API? Afinal API e syscall são a mesma coisa? Explique.<br />
<br />
<syntaxhighlight lang=cpp><br />
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);<br />
int munmap(void *addr, size_t length);<br />
<br />
addr = Valor do início do mapeamento.<br />
length = valor do tamanho da região a ser alocada.<br />
prot = especificações de proteção da região alocada (consultar http://man7.org/linux/man-pages/man2/mmap.2.html).<br />
flags = especificação do escopo e do tipo da região criada (exemplo publica ou privada, se é anônima ou não). <br />
</syntaxhighlight><br />
<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
void* meu_malloc(size_t tamanho) {<br />
void* addr = mmap(0, // addr<br />
tamanho, // len<br />
PROT_READ | PROT_WRITE, // prot<br />
MAP_ANON | MAP_PRIVATE, // flags<br />
-1, // filedes<br />
0); // off<br />
*(size_t*)addr = tamanho;<br />
return addr;<br />
}<br />
<br />
int meu_free(void* addr) {<br />
return munmap(addr - sizeof(size_t), (size_t) addr);<br />
}<br />
<br />
<br />
int soma(int *N1, int *N2){<br />
<br />
return (*N1+*N2);<br />
<br />
}<br />
<br />
<br />
int main(int argc, char* argv[]) {<br />
<br />
int* numero1 = meu_malloc(sizeof(int));<br />
int* numero2 = meu_malloc(sizeof(int)); <br />
<br />
<br />
*numero1 = 10;<br />
*numero2 = 20; <br />
<br />
int resultado = soma(numero1, numero2);<br />
<br />
printf("\n\n O resultado da soma é %d \n\n",resultado); <br />
<br />
meu_free(numero1);<br />
meu_free(numero2);<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Processos no Linux}}<br />
<br />
== Processos no Linux - Modificado por Eraldo ==<br />
<br />
<blockquote style="background: lime; border: 1px solid black; padding: 1em;"><br />
Processos no Linux<br />
</blockquote><br />
<br />
*Exercícios propostos pelo Prof.Arliones e Modificados por Eraldo<br />
<br />
<br />
[[imagem:DesenhoForkExec.png|border|650px]]<br />
<br />
<br />
;Syscall FORK<br />
<br />
* Em um terminal, execute "man fork"<br />
** 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'''.<br />
** O '''código''' dos dois processos (pai e filho) são '''idênticos''';<br />
** Os '''dados''' dos dois processos (pai e filho) são '''idênticos NO MOMENTO DA CRIAÇÃO''';<br />
** Execução do processo filho inicia na próxima instrução do programa (no retorno da chamada FORK);<br />
** Não é possível saber qual dos processos (pai ou filho) retormará a execução primeiro - isto fica a cargo do excalonador do SO;<br />
** Valores de retorno da chamada FORK:<br />
*** (-1): erro na criação do processo (ex.: memória insuficiente);<br />
*** (0): em caso de sucesso, este é o valor de retorno recebido pelo processo filho;<br />
*** (>0): em caso de sucesso, este é o valor de retorno recebido pelo processo pai;<br />
<br />
;Syscall JOIN<br />
<br />
* A syscall JOIN é implementada no POSIX pela função '''wait()'''. Execute "man wait".<br />
** Além da função '''wait()''', há também '''waitpid()''' e '''waitid()''';<br />
** 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);<br />
** A chamada wait também libera os recursos do processo filho que termina;<br />
** '''wait()''': esta função suspende a execução do processo chamador até que UM DOS SEUS FILHOS finalize;<br />
** '''waitpid()''': suspende a execução do processo chamador até que UM FILHO ESPECÍFICO finalize;<br />
<br />
;Syscall EXEC<br />
<br />
* A syscall EXEC é implementada no POSIX pela família de funções '''exec()'''. Execute "man exec".<br />
** As principais funções da família são '''execl()''', '''execlp()''' e '''execvp()''';<br />
** 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;<br />
** 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;<br />
<br />
<br />
;Exemplos POSIX utilizando fork/wait/exec<br />
<br />
*Exemplo 1: fork/wait básico<br />
<syntaxhighlight lang=c><br />
// ex1: fork/wait básico<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
printf("processo filho\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
printf("processo pai\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
arliones@socrates:~/tmp$ gcc ex1.c -o ex1 <br />
arliones@socrates:~/tmp$ ./ex1 <br />
processo filho pid: 27858 pid pai: 27857<br />
processo pai pid: 27857 pid pai: 5337<br />
arliones@socrates:~/tmp$ <br />
</syntaxhighlight><br />
<br />
* Exemplo 2: processos pai e filho compartilham código, mas não dados.<br />
<syntaxhighlight lang=c><br />
// ex2: fork/wait "compartilhando" dados<br />
// ex2: fork/wait "compartilhando" dados<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status, k=0;<br />
printf("processo %d\t antes do fork\n", getpid());<br />
pid = fork();<br />
printf("processo %d\t depois do fork\n", getpid());<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
k += 1000;<br />
printf("processo filho\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status); // espera o filho terminar<br />
k += 10;<br />
printf("processo pai\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
k += 1000;<br />
printf("FIM processo %d\t K: %d\n", getpid(), k); <br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
processo 17056 antes do fork<br />
processo 17056 depois do fork<br />
processo 17057 depois do fork<br />
processo filho pid: 17057 K: 1000 endereço K: 0x7ffd8923e318<br />
processo pai pid: 17056 K: 10 endereço K: 0x7ffd8923e318<br />
</syntaxhighlight><br />
<br />
* Modificação no código: comentar linhas 23 e 30<br />
<br />
<syntaxhighlight lang=bash><br />
<br />
</syntaxhighlight><br />
<br />
* Analise os resultados e busque entender a diferença.<br />
*Perguntas e desafios.:<br />
#Analisando os valores impressos de k pode-se dizer que os dados são compartilhados entre os dois processos?<br />
#O endereço de k impresso é o mesmo nos dois processos. ISto não contradiz a afirmação anterior?<br />
#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.<br />
<br />
<br />
;Exercício fork/wait<br />
<br />
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.<br />
<br />
*Use o comando pstree para verificar a árvore de processos criada.<br />
<br />
{{collapse top|Solução}}<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
<!--<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
--><br />
<br />
;DESAFIO: fork/wait<br />
<br />
Reimplementar o exercício anterior de criação de uma árvore de 3 processos, generalizando a criação de N processos onde N é repassado na linha de comando do programa. SUGESTÃO: usar um comando for, mas lembrar que se existe um fork dentro do for, então cada filho gerado dará continuidade a execução do for. É necessário que o processo faça um exit ou retorne neste momento.<br />
<br />
;DESAFIO: Exercício status/wait<br />
<br />
O ''status'' passado como parâmetro à função ''wait(&status)'' é, na verdade, o mecanismo de retorno de resultado do ''wait/waitpid''. Ao retornar, esta variável contém informações sobre o resultado da execução do processo filho. Por exemplo, se um processo terminou normalmente (i.e., chamou ''exit''), o comando ''WIFEXITED(status)'' retorna ''true''. Este comando retorna ''false'' se o processo foi abortado (e.g., ''segmentation fault'') ou morto (e.g., ''kill''). Investigue no manual do wait no Linux (''man wait'') o funcionamento do comando WEXITSTATUS(status). <br />
Imagine um problema de busca de dados armazenados na forma de uma matriz de inteiros 4x30. Você está interessado em saber quantas ocorrências de um determinado número existe em cada linha da matriz. Note que que são tarefas que podem ser paralelizadas e usufruir de um sistema capaz de executá-las em paralelo. Faça uma implementação paralelizando 4 processos filhos a partir de um pai, onde cada processo é responsável por uma busca. A quantidade de ocorrências do número buscado é retornada e capturada através de WEXITSTATUS.<br />
<br />
;Syscall EXEC<br />
<br />
*Exemplo exec()<br />
<br />
<syntaxhighlight lang=c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
execl("/bin/ls","ls","-l", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 1: Modificar o código para mostrar que o exec() não retorna (colocar um printf após o exec).<br />
<br />
*Exercício 2: Criar um exemplo (dois programas ) para demonstrar que o exec não cria novo processo. <br />
**Crie um primeiro programa (prog1) que imprime o seu pid e depois faz um exec do segundo programa.<br />
**Crie o segundo programa que simplesmente imprime o pid.<br />
<br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU ANTES DO EXEC: Meu pid é %d\n", getpid());<br />
execl("./prog2","prog2", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU DEPOIS DO EXEC:Meu pid é %d\n", getpid());<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 3: Criar um exemplo usando fork/exec mostrando que um processo pai cria um filho e espera por sua execução. O filho executa o comando "ps aux". Ambos devem mostrar seus pids.<br />
<br />
{{collapse bottom}} <br />
{{collapse top| bg=lightyellow | expandir=true | Threads de aplicação}}<br />
<br />
== Threads de aplicação ==<br />
<br />
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:<br />
*'''getcontext(&a)''': salva o contexto na variável '''a''';<br />
*'''setcontext(&a)''': restaura um contexto salvo anteriormente na variável '''a''';<br />
*'''swapcontext(&a,&b)''': salva o contexto atual na variável '''a''' e restaura o contexto salvo anteriormente na variável '''b''';<br />
*'''makecontext(&a, ...)''': ajusta parâmetros internos do contexto salvo em '''a''';<br />
*'''ucontext_t''': as variáveis '''a''' e '''b''' são do tipo '''ucontext_t'''. Este tipo armazena um contexto.<br />
<br />
Busque mais informações sobre estas funções utilizando o programa manpage do Linux (ex.: man getcontext).<br />
<br />
Estude o código no arquivo pingpong.c abaixo e explique seu funcionamento.<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
*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.<br />
*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.<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain, cFnew;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_new(void * arg1, void * arg2,void * arg3,void * arg4) <br />
{<br />
printf ("%s: Primeira string %s %s %s\n",(char*) arg1,(char*) arg2,(char*) arg3, (char*) arg4);<br />
swapcontext(&cFnew, &cMain); <br />
}<br />
<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
<br />
getcontext(&cFnew);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cFnew.uc_stack.ss_sp = stack ;<br />
cFnew.uc_stack.ss_size = STACKSIZE;<br />
cFnew.uc_stack.ss_flags = 0;<br />
cFnew.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cFnew, (void*)(*f_new), 4, "\tF_new", "\tAlo", "\tMundo","\tReal");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
swapcontext(&cMain, &cFnew);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
--><br />
Exercício 3: O que acontece se um dos threads é colocado para dormir? Todos os demais threads param a sua execução.<br />
<br />
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/<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Trocas de mensagens com pipes}}<br />
<br />
== Trocas de mensagens com pipes ==<br />
<br />
;Troca de mensagens<br />
Um mecanismo disponibilizado por sistemas UNIX para troca de mensagens entre processos é o PIPE. Pipes são mecanismos de comunicação indireta onde mensagens são trocadas através de ''mailboxes''. Cada ''mailbox'' possui um identificador único, permitindo que processos identifiquem o canal de comunicação entre eles. O fluxo de mensagens em um Pipe é:<br />
*'''unidirecional''': sobre um mesmo pipe, apenas um processo envia mensagens e um processo recebe mensagens;<br />
*'''FIFO''': as mensagens são entregues na ordem de envio;<br />
*'''não-estruturado''': não há estrutura pré-definida para o formato da mensagem.<br />
No UNIX, pipes são inicializados através da '''SystemCall''' ''pipe'', que possui a seguinte sintaxe:<br />
*''int pipe(int pipefd[2])'': ''pipe'' inicializa um novo pipe no sistema e retorna, no array pipefd, os descritores identificando cada uma das pontas do pipe. A primeira posição do array, i.e. pipefd[0], recebe o descritor que pode ser aberto apenas para leitura, enquanto a segunda posição do array, i.e. pipefd[1], recebe o descritor que pode ser aberto apenas para escrita. A função retorna zero no caso de sucesso, ou -1 se ocorrer erro.<br />
As primitivas send/receive para uso de um pipe no UNIX são implementadas por '''SystemCalls''' read/write, conforme segue:<br />
*''ssize_t read(int fd, void *buf, size_t count)'': “puxa” dados do pipe identificado pelo descritor fd. Os dados recebidos são os apontados pelo ponteiro buf, sendo count a quantidade máxima de bytes a serem recebidos. A função retorna o número de bytes recebidos.<br />
*''ssize_t write(int fd, const void *buf, size_t count)'': “empurra” dados no pipe identificado pelo descritor fd. Os dados transmitidos são os apontados pelo ponteiro buf, sendo count a quantidade de bytes a serem transmitidos. A função retorna o número de bytes transmitidos.<br />
<br />
*Exemplo 1: Transmitindo e recebendo pelo próprio processo<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main()<br />
{<br />
int fd[2];<br />
char *ptr = "Alo eu mesmo";<br />
char *ptr_alvo;<br />
int tamanho_dados, ret;<br />
<br />
tamanho_dados = strlen(ptr)+1;<br />
<br />
if (pipe(fd)==-1){<br />
printf ("erro criação pipe\n");<br />
exit(-1);<br />
}<br />
printf("Transmitido %d bytes\n", tamanho_dados);<br />
write (fd[1], ptr, tamanho_dados);<br />
<br />
ptr_alvo = malloc(tamanho_dados);<br />
<br />
ret=read(fd[0],ptr_alvo,tamanho_dados);<br />
<br />
printf("ret = %d dados => %s\n", ret, ptr_alvo); <br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
*Exemplo 2: Abaixo há um exemplo de programa criando um pipe e compartilhando os descritores entre dois processos (criados via ''fork()'').<br />
<syntaxhighlight lang=c><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
<br />
char *message = "This is a message!!!" ;<br />
<br />
main()<br />
{<br />
char buf[1024] ;<br />
int fd[2];<br />
pipe(fd); /*create pipe*/<br />
if (fork() != 0) { /* I am the parent */<br />
write(fd[1], message, strlen (message) + 1) ;<br />
}<br />
else { /*Child code */<br />
read(fd[0], buf, 1024) ;<br />
printf("Got this from MaMa!!: %s\n", buf) ;<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
*'''Exercício 1: construa um “pipeline”'''. Crie um programa que conecta 4 processos através de 3 pipes. Utilize ''fork()'' para criar vários processos.<br />
<br />
<syntaxhighlight lang=cpp><br />
<br />
//Solução possível<br />
<br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
pipe(fd);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
<br />
</syntaxhighlight><br />
<br />
*'''Exercício 3: Modifique o exercício anterior para que o processo D, através de um novo pipe, mande uma mensagem diretamente para o pai de todos.<br />
<br />
<!--<br />
<code><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
int fd_retorno[2];<br />
<br />
pipe(fd);<br />
pipe(fd_retorno);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size);<br />
read(fd_retorno[0], buf, size);<br />
printf("PAI:%s\n", buf); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
char *ptr_msg_ret="Ok msg de D para o pai";<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
write(fd_retorno[1],ptr_msg_ret,strlen(ptr_msg_ret)+1);<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
*'''Exercício 3: Consultor de Login de Acesso:'''. Estude o link https://www.geeksforgeeks.org/named-pipe-fifo-example-c-program/ e projete um programa cliente servidor da seguinte forma: (i) O servidor possui uma tabela de usuários (userid). O user_id é de tamanho fixo de 7 caracteres. O servidor espera por consultas para verificar se um usuário está na tabela. Se estiver responde com o caracter 'S' senão com 'N'. (ii) O cliente espera por user_id no teclado e consulta o servidor sobre sua existência na tabela. O cliente imprime na tabela a existência ou não do usuário.<br />
<br />
*'''Exercício 4: cópia de arquivo'''. Projete um programa de cópia de arquivos chamado FileCopy usando pipes comuns. Esse programa receberá dois parâmetros: o primeiro é o nome do arquivo a ser copiado e o segundo é o nome do arquivo copiado. Em seguida, o programa criará um pipe comum e gravará nele o conteúdo do arquivo a ser copiado. O processo filho lerá esse arquivo do pipe e o gravará no arquivo de destino. Por exemplo, se chamarmos o programa como descrito a seguir:<br />
:<syntaxhighlight lang=bash><br />
$ FileCopy entrada.txt copia.txt<br />
</syntaxhighlight><br />
:o arquivo ''entrada.txt'' será gravado no pipe. O processo filho lerá o conteúdo desse arquivo e o gravará no arquivo de destino ''copia.txt''. Escreva o programa usando os pipes da API POSIX no Linux.<br />
<br />
<br />
{{collapse bottom}}<br />
<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Exercícios sobre Memória Compartilhada}}<br />
<br />
==SHARED MEMORY: Produtor (pai) - Consumidor (filho) - ==<br />
<br />
<!-- Parou aki 20/08<br />
<br />
<br />
*'''Experimento 2:''' Complete o código a seguir para que os processos pai e filho possam compartilhar um segmento de memória. O filho escreve no segmento e o pai imprime na tela o conteúdo da mensagem.<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
char *ptr_msg = "alo pai, tudo bem?"; <br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
//completar aqui<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
<!--<br />
<code><br />
<br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/types.h><br />
#include <string.h><br />
#include <stdlib.h><br />
<br />
int main(void)<br />
{<br />
int fd[2], pipe_ret, filho;<br />
char string[] = "Hello, pipe!\n";<br />
char buffer[20];<br />
<br />
pipe(fd);<br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
/*Mandar string para a extremidade do pipe*/<br />
write(fd[1], string, (strlen(string)+1));<br />
exit(0);<br />
}<br />
else<br />
{<br />
<br />
/* Read in a string from the pipe */<br />
pipe_ret = read(fd[0], buffer, (20*sizeof(char)));<br />
printf("Recebi este texto %s", buffer);<br />
}<br />
<br />
return(0);<br />
}<br />
<br />
<br />
<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
key = ftok("teste_sh.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644 | IPC_CREAT));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
<br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
strncpy(segmento, "mensagem compartilhada", SHM_SIZE); <br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
--><br />
<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Memória Compartilhada}}<br />
*'''Experimento Shared Memory:''' Complete o código a seguir para que os processos pai e filho possam compartilhar um segmento de memória. O filho escreve no segmento e o pai imprime na tela o conteúdo da mensagem.<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
char *ptr_msg = "alo pai, tudo bem?"; <br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
//completar aqui strcpy(segmento, ptr_msg); //aqui deveria testar a cpacidade da área...<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exemplo com ftok:<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
key = ftok("./teste.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644 | IPC_CREAT));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
<br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
strncpy(segmento, "mensagem compartilhada", SHM_SIZE); <br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exemplo com ftok entre processos sem parentesco:<br />
<br />
Criar um arquivo teste.txt e em um terminal executar:<br />
<br />
<syntaxhighlight lang=c><br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
int modo,filho;<br />
<br />
struct minha_struct {<br />
char flag;<br />
int numero;<br />
} *ptr;<br />
<br />
<br />
key = ftok("./teste.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644 | IPC_CREAT));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
ptr = (struct minha_struct *) shmat(shmid, (void *)0, 0);<br />
if ((char *)ptr == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
ptr->flag =0;<br />
ptr->numero = 0;<br />
while (ptr->flag==0) { <br />
printf("%d\n", ptr->numero);<br />
sleep(1);<br />
} <br />
<br />
if (shmdt(ptr) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Em outro terminal executar:<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
struct minha_struct {<br />
char flag;<br />
int numero;<br />
} *ptr;<br />
<br />
<br />
key = ftok("./teste.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
ptr = (struct minha_struct *) shmat(shmid, (void *)0, 0);<br />
if ((char *)ptr == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
<br />
<br />
while (ptr->numero++<10)<br />
sleep(1);<br />
<br />
ptr->flag = 1;<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Exercício Desafio: Implementar o problema do buffer circular usando memória compartilhada.<br />
<br />
{{collapse bottom}}<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Exercício (Algoritmo de Peterson)}}<br />
<br />
== Exercício (Algoritmo de Peterson) ==<br />
<br />
<br />
'''Exercício 1''': Sincronize o código a seguir, de maneira que o processo pai imprima apenas os números impares e o processo filho os números pares. Para isso utilize o algoritmo de '''Peterson''' visto em aula. '''Utilize memória compartilhada''' para comunicação entre os processos.<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
main()<br />
{ <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int i; <br />
<br />
for(i = 0;i < 10;i=i+2){ <br />
printf("Processo pai %d \n", i); <br />
<br />
} <br />
<br />
<br />
}<br />
<br />
else { /*Child code */<br />
int i; <br />
for(i = 1;i < 10;i=i+2){ <br />
printf("Processo filho %d \n", i); <br />
<br />
}<br />
<br />
<br />
}<br />
<br />
exit(0);<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
'''Exercício 2''': Considerando o exercício anterior faça a mesma sincronização, no entanto desta vez utilize a modelagem em software do TSL. <br />
* Em sua experiência, depois de testar diversas vezes as execuções de suas soluções baseadas no algoritmo de '''Peterson''' e '''Tsl''', qual sua opinião sobre as abordagens?<br />
Explique seu raciocínio. <br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Exercício (Semáforos)}}<br />
== Exercício (Semáforos) ==<br />
<br />
<br />
'''Exercício 1''': Sincronize o código a seguir, de maneira que o processo pai imprima apenas os números impares e o processo filho os números pares. Para isso utilize '''Semáforos''' de acordo com a implementação em '''semaforo.h'''. '''Utilize memória compartilhada''' para comunicação entre os processos.<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
main()<br />
{ <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int i; <br />
<br />
for(i = 0;i < 10;i=i+2){ <br />
printf("Processo pai %d \n", i); <br />
sleep(1);<br />
<br />
} <br />
<br />
<br />
}<br />
<br />
else { /*Child code */<br />
int i; <br />
for(i = 1;i < 10;i=i+2){ <br />
printf("Processo filho %d \n", i); <br />
<br />
}<br />
<br />
<br />
}<br />
<br />
exit(0);<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
SEMAFORO.H<br />
<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <sys/sem.h><br />
<br />
<br />
int criar_semaforo(int val, int chave) <br />
{<br />
int semid ;<br />
<br />
union semun {<br />
int val;<br />
struct semid_ds *buf ;<br />
ushort array[1];<br />
} arg_ctl ;<br />
<br />
key_t ft = ftok("/tmp", chave);<br />
<br />
semid = semget(ft,1,IPC_CREAT|IPC_EXCL|0666);<br />
if (semid == -1) {<br />
semid = semget(ft,1,0666); <br />
if (semid == -1) {<br />
perror("Erro semget()");<br />
exit(1) ;<br />
}<br />
}<br />
<br />
arg_ctl.val = val; //valor de início<br />
if (semctl(semid,0,SETVAL,arg_ctl) == -1) {<br />
perror("Erro inicializacao semaforo");<br />
exit(1);<br />
}<br />
return(semid) ;<br />
}<br />
<br />
void P(int semid){<br />
<br />
struct sembuf *sops = malloc(10*sizeof(int));<br />
sops->sem_num = 0;<br />
sops->sem_op = -1;<br />
sops->sem_flg = 0;<br />
semop(semid, sops, 1); <br />
free(sops);<br />
<br />
}<br />
<br />
<br />
void V(int semid){<br />
<br />
struct sembuf *sops = malloc(10*sizeof(int));<br />
sops->sem_num = 0;<br />
sops->sem_op = 1;<br />
sops->sem_flg = 0; <br />
semop(semid, sops, 1); <br />
free(sops);<br />
<br />
} <br />
<br />
<br />
<br />
void sem_delete(int semid) <br />
{<br />
<br />
if (semctl(semid,0,IPC_RMID,0) == -1)<br />
perror("Erro na destruicao do semaforo");<br />
}<br />
<br />
<br />
<br />
<br />
</syntaxhighlight><br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Programação concorrente}}<br />
<br />
== Programação concorrente ==<br />
<br />
;POSIX Threads<br />
A 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):<br />
*''pthread_create'': cria uma thread;<br />
*''pthread_kill'': força a terminação de uma thread;<br />
*''pthread_join'': sincroniza o final de uma thread (qual a diferença/semelhança com o ''wait'' que usamos para processos?);<br />
*''pthread_exit'': finaliza uma thread.<br />
Para utilizar estas funções é necessário linkar o programa à libpthread (''-lpthread''). <br />
<br />
<br />
;POSIX pthread mutex<br />
<br />
A biblioteca pthread implementa um tipo ''pthread_mutex_t'', que garante a exclusão mútua entre threads. Estes mutex são manipulados através das funções (acesse as man-pages das chamadas para maiores detalhes):<br />
*''pthread_mutex_lock'': acessa um mutex.<br />
*''pthread_mutex_trylock'': tenta acessar um mutex (retorna valor indicando sucesso ou falha no lock).<br />
*''pthread_mutex_unlock'': libera um mutex.<br />
<br />
<br />
<br />
<br />
;POSIX Semaphores<br />
<br />
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):<br />
*''sem_init'': inicializa um semáforo;<br />
*''sem_destroy'': destroy um semáforo;<br />
*''sem_wait'': implementa a operação ''p'';<br />
*''sem_post'': implementa a operação ''v''.<br />
Para utilizar estas funções é necessário linkar o programa à librt ou à libpthread (''-lrt'' ou ''-lpthread'').<br />
<br />
;Exercício 1<br />
<br />
O programa abaixo cria 5 threads, e cada uma destas threads atualiza uma variável global (memória compartilhada).<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include <pthread.h><br />
#include <signal.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
pthread_mutex_t mut;<br />
<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
}<br />
</syntaxhighlight><br />
<br />
# Compile este programa. <br />
# Execute este programa várias vezes. Ele funciona? Será que ele gera as saídas esperadas?<br />
# Identifique as '''seções críticas''' do programa.<br />
# Corrija o programa utilizando '''mutex'''. <br />
# Analise a função ''AtualizaSaldo()'' com a sua solução. Lembre-se que o uso do mutex implica em apenas uma thread acessar a seção crítica por vez, enquanto outras threads ficam bloqueadas, esperando. Disso vem que, quanto menor o trecho de código entre um ''lock'' e um ''unlock'', menos tempo uma thread necessita ficar esperando.<br />
# Modifique o programa para usar um semáforo binário ao invés de um mutex em sua solução.<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <cstring><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
<br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
sem_t sem;<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
int value;<br />
sem_wait(&sem);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
sem_getvalue(&sem, &value);<br />
printf("valor sem = %d\n", value);<br />
sem_post(&sem);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
sem_init(&sem,0,1);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
sem_destroy(&sem);<br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
<br />
;Exercício 2<br />
Refaça o exercício 3 usando processos criados com fork e exec. O semáforo deve ser criado em uma região de memória compartilhada.<br />
<br />
;Exercício 3<br />
Implemente com pthreads e semáforos/mutex a solução do produtor/comsumidor.<br />
<br />
;Exercício 4<br />
<br />
O programa abaixo manipula uma matriz de tamanho MxN (veja os defines para o tamanho da matriz). A função ''SumValues'' soma todos os valores em uma linha da matriz. A linha a ser somada é identificada pela variável ''i''. Modifique o programa principal (''main'') nos locais indicados para:<br />
# Criar N threads, uma para somar os valores de cada linha.<br />
# Receber o resultado do somatório de cada linha e gerar o somatório total da matriz.<br />
# Analise o programa: há problemas de sincronização que precisam ser resolvidos? Se sim, resolva-os.<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include "thread.h"<br />
<br />
/* number of matrix columns and rows */<br />
#define M 5<br />
#define N 10<br />
<br />
using namespace std;<br />
<br />
int matrix[N][M];<br />
Thread *threads[N];<br />
<br />
<br />
/* thread function; it sums the values of the matrix in the row */<br />
int SumValues(int i)<br />
{<br />
int n = i; /* number of row */<br />
int total = 0; /* the total of the values in the row */<br />
int j;<br />
for (j = 0; j < M; j++) /* sum values in the "n" row */<br />
total += matrix[n][j];<br />
cout << "The total in row" << n << " is " << total << "." << endl;<br />
/* terminate a thread and return a total in the row */<br />
exit(total);<br />
}<br />
<br />
int main(int argc, char *argv[])<br />
{<br />
int i, j;<br />
int total = 0; /* the total of the values in the matrix */<br />
<br />
/* initialize the matrix */<br />
for (i = 0; i < N; i++)<br />
for (j = 0; j < M; j++)<br />
matrix[i][j] = i * M + j;<br />
<br />
/* create threads */<br />
/* COLOQUE SEU CÓDIGO PARA CRIAR AS THREADS AQUI! */<br />
<br />
/* wait for terminate a threads */<br />
/* COLOQUE SEU CÓDIGO PARA PEGAR O SOMATÓRIO DE LINHAS E TOTALIZAR A SOMA DA MATRIZ AQUI! */<br />
<br />
cout << "The total values in the matrix is " << total << endl;<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Lista de exercícios "Revisão para Prova" }}<br />
<br />
== Lista de exercícios/Revisão para Prova ==<br />
<br />
A lista de exercícios referente a primeira prova (Parte introdutória + Processos) segue neste LINK [http://docente.ifsc.edu.br/andre.damato/sop2018/lista_rev1.pdf | Lista de exercícios]. <br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Primeiro trabalho}}<br />
== JOGO DA VIDA DE CONWAY e JANTAR DOS FILÓSOFOS==<br />
<br />
;Referências<br />
<br />
* [https://www.open-mpi.org/doc/current/ MPI]<br />
<br />
* [https://quark.phy.bnl.gov/~creutz/qcdoc/mpi/mpi.h Tipos de dados MPI]<br />
<br />
* [https://pt.wikipedia.org/wiki/Jogo_da_vida Jogo da Vida]<br />
<br />
<br />
<br />
<br />
A partir da implementação sequencial do Game of Life apresentada a seguir, estude o código e transforme esta implementação em uma implementação paralela utilizando o protocolo de passagem de mensagens MPI.<br />
Perceba que a impĺementação mencionada utiliza como parâmetros de entrada um aquivo contendo o estado inicial do jogo, e o número de gerações que o usuário deseja rodar. A evolução do estado inicial <br />
é impressa na tela passo a passo. Sendo assim, a partir disso:<br />
<br />
*'''1: Elabore uma implementação com 2 processos para o jogo da vida utilizando o protocolo MPI, de maneira que um processo execute uma geração i qualquer e o outro execute a geração seguinte i+1''' <br />
<br />
*'''2: (0,7) Os processos deverão se comunicar utilizando as funções do protocolo MPI.''' <br />
<br />
*'''3: (0,3) Relatório simplificado explicando a sua solução. Utilize diagramas para representar a comunicação entre os processos, explicando como a matriz do jogo é transferida entre os processos. ''' <br />
<br />
*'''4: Entregue o Relatório e o código fonte do trabalho em um pacote compactado via e-mail (PRAZO 19/10). <br />
<br />
<br />
<br />
* ''' Compilar o código com MPI '''<br />
<code><br />
mpicc -o nomeApp arquivo.c<br />
</syntaxhighlight><br />
<br />
* ''' Rodar rodar programa utilizando MPI '''<br />
<code><br />
mpirun -np numeroDeProcessos ./nomeApp entrada.txt gerações<br />
</syntaxhighlight><br />
<br />
* (int) -np: Quantidade de processos que você deseja executar <br />
<br />
* entrada.txt: Arquivo de entrada com estado inicial do jogo <br />
<br />
* (int) gerações: número de gerações que você deseja rodar<br />
<br />
* [http://docente.ifsc.edu.br/andre.damato/sop2018/entrada.txt Arquivo de entrada para Testes]<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
<br />
<br />
<br />
/*<br />
<br />
Conway's Game of Life<br />
<br />
Compilar código com MPI<br />
mpicc -o nomeApp arquivo.c<br />
<br />
<br />
Rodar rodar programa utilizando MPI<br />
<br />
mpirun -np numeroDeProcessos ./nomeApp entrada.txt gerações<br />
<br />
(int) -np: Quantidade de processos que você deseja executar <br />
entrada.txt: Arquivo de entrada com estado inicial do jogo <br />
(int) gerações: número de gerações que você deseja rodar<br />
<br />
<br />
*/<br />
<br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h><br />
#include "mpi.h"<br />
<br />
<br />
//Numero de linhas e colunas<br />
#define nLinhas 32<br />
#define nColunas 82 <br />
<br />
char *matriz[nLinhas];<br />
char *entrada[nLinhas];<br />
<br />
<br />
void iniciar() {<br />
<br />
int i;<br />
<br />
//Alocar espaço em memória para as matrizes<br />
for (i = 0; i < nLinhas; i++ ) <br />
matriz[i] = (char *) malloc((nColunas) * sizeof( char )); <br />
<br />
<br />
}<br />
<br />
int adjacente(char **matriz, int i, int j){<br />
<br />
int x,y, initX, initY, limitX, limitY;<br />
int vizinhos = 0;<br />
<br />
if(i == 0)<br />
initX = 0;<br />
else <br />
initX = -1;<br />
<br />
if(i == (nLinhas-1)) <br />
limitX = 1;<br />
else<br />
limitX = 2;<br />
<br />
<br />
if(y == 0)<br />
initY = 0;<br />
else <br />
initY = -1;<br />
<br />
if(y == (nColunas-3)) <br />
limitY = 1;<br />
else<br />
limitY = 2;<br />
<br />
for(x = initX ; x < limitX; x++){<br />
for(y = initY; y < limitY; y++){<br />
if(matriz[i+x][j+y] == '#') <br />
vizinhos++; <br />
} <br />
}<br />
<br />
<br />
if(matriz[i][j] == '#') <br />
return (vizinhos-1);<br />
else <br />
return vizinhos;<br />
<br />
}<br />
<br />
<br />
void calculoGeracao(char **matriz, int ger) {<br />
<br />
int i, j, a;<br />
char novaGeracao[nLinhas][nColunas];<br />
<br />
/* Aplicando as regras do jogo da vida */<br />
for (i=0; i < nLinhas; i++){ <br />
for (j=0; j < nColunas; j++) {<br />
<br />
a = adjacente(matriz, i, j);<br />
<br />
if (a == 2) novaGeracao[i][j] = matriz[i][j];<br />
if (a == 3) novaGeracao[i][j] = '#';<br />
if (a < 2) novaGeracao[i][j] = ' ';<br />
if (a > 3) novaGeracao[i][j] = ' ';<br />
<br />
if (j == 0)<br />
novaGeracao[i][j] = '"';<br />
} <br />
<br />
novaGeracao[i][79] = '"';<br />
novaGeracao[i][80] = '\n';<br />
<br />
<br />
}<br />
<br />
/* Passando o resultado da nova geração para a matriz de entrada */<br />
for (i=0; i < nLinhas; i++){ <br />
for (j=0; j < nColunas; j++) <br />
matriz[i][j] = novaGeracao[i][j];<br />
}<br />
}<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
main(int argc, char *argv[2]){<br />
<br />
/* Para uso com MPI<br />
<br />
<br />
//Variáveis para uso com MPI<br />
int numeroDeProcessos = 0;<br />
int rank = 0;<br />
MPI_Status status; <br />
<br />
//Iniciar MPI---<br />
MPI_Init( &argc, &argv );<br />
<br />
//Atribui a variável numeroDeProcessos o número de processos passado como parâmetro em -np <br />
MPI_Comm_size( MPI_COMM_WORLD, &numeroDeProcessos );<br />
<br />
//Pega o valor do rank (processo)<br />
MPI_Comm_rank( MPI_COMM_WORLD, &rank );<br />
*/<br />
<br />
<br />
FILE *matrizEntrada;<br />
matrizEntrada = fopen(argv[1], "r");<br />
iniciar();<br />
<br />
<br />
if (matrizEntrada == NULL)<br />
printf ("Não posso abrir o arquivo \"%s\"\n", argv[1]);<br />
<br />
<br />
char str[nColunas];<br />
int linha = 0;<br />
<br />
<br />
<br />
//Lendo o estado inicial do jogo a partir do arquivo<br />
while((fgets(str, nColunas, matrizEntrada) != NULL)&&(linha < nLinhas)){<br />
strcat(matriz[linha], str);<br />
linha++;<br />
}<br />
<br />
int i,gens; <br />
<br />
<br />
for(gens = 0; gens < atoi(argv[2]); gens++){ //Gens é o número de gerações especificado no segundo parâmetro <br />
<br />
calculoGeracao(matriz, gens);<br />
printf("%c[2J",27); // Esta linha serve para limpar a tela antes de imprimir o resultado de uma geração <br />
<br />
//Lendo o estado do jogo e imprime na tela <br />
for(i = 0; i < nLinhas; i++)<br />
printf("%s", matriz[i]); <br />
<br />
sleep(1);<br />
<br />
}<br />
<br />
<br />
for(i = 0; i < nLinhas; i++) <br />
free(matriz[i]); <br />
<br />
<br />
<br />
/* Finaliza o MPI */ <br />
//MPI_Finalize();<br />
<br />
exit(0);<br />
} <br />
<br />
<br />
</syntaxhighlight><br />
<br />
<br />
;Jantar dos Filósofos<br />
O problema clássico Jantar dos Filósofos consiste em que n fluxos (n filósofos) disputam n recursos (n talheres). No problema, para conseguir "jantar" (ou executar), cada filósofo precisa pegar dois talheres adjascentes a ele. Cada recurso é compartilhado por dois filósofos.<br />
*[http://www.doc.ic.ac.uk/~jnm/concurrency/classes/Diners/Diners.html Veja esta simulação]<br />
*[http://en.wikipedia.org/wiki/Dining_philosophers_problem Veja esta descrição do problema]<br />
<br />
<br />
* ''' (0,7) programa abaixo implementa um Jantar dos Filósofos utilizando semáforos para sincronização. Contudo, as chamadas para as operações ''v'' e ''p'' foram removidas, conforme comentários no código. Re-insira as operações no código e analise a solução. Esta modificação é suficiente para garantir que não haverá deadlock? Se sim, mostre o porque. Se não, proponha uma solução completa. '''<br />
<br />
<br />
*''' (0,3) Relatório simplificado explicando a sua solução. ''' <br />
<br />
*''' Entregue o Relatório e o código fonte do trabalho em um pacote compactado via e-mail (PRAZO 19/10). <br />
<br />
<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include "thread.h"<br />
#include "semaphore.h"<br />
<br />
using namespace std;<br />
<br />
const int DELAY = 10000000;<br />
const int ITERATIONS = 5;<br />
<br />
Semaphore chopstick[5];<br />
<br />
int philosopher(int n)<br />
{<br />
cout << "Philosopher " << n << " was born!\n";<br />
<br />
int first = (n < 4)? n : 0; // left for phil 0 .. 3, right for phil 4<br />
int second = (n < 4)? n + 1 : 4; // right for phil 0 .. 3, left for phil 4<br />
<br />
// Foram removidos do laço abaixo:<br />
// - uma chamada para chopstick[first].p()<br />
// - uma chamada para chopstick[second].p()<br />
// - uma chamada para chopstick[first].v()<br />
// - uma chamada para chopstick[second].v()<br />
for(int i = 0; i < ITERATIONS; i++) {<br />
cout << "Philosopher " << n << " thinking ...\n";<br />
for(int i = 0; i < DELAY * 10; i++);<br />
<br />
cout << "Philosopher " << n << " eating ...\n";<br />
for(int i = 0; i < DELAY; i++);<br />
}<br />
<br />
return n;<br />
}<br />
<br />
int main()<br />
{<br />
cout << "The Dining-Philosophers Problem\n";<br />
<br />
Thread * phil[5];<br />
for(int i = 0; i < 5; i++)<br />
phil[i] = new Thread(&philosopher, i);<br />
<br />
int status;<br />
for(int i = 0; i < 5; i++) {<br />
phil[i]->join(&status);<br />
if(status == i)<br />
cout << "Philosopher " << i << " went to heaven!\n";<br />
else<br />
cout << "Philosopher " << i << " went to hell!\n";<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Softwares básicos, caso Hello Word! (Trabalho 2) Entrega dia 09/11}}<br />
<br />
== Softwares básicos, caso Hello Word! ==<br />
<br />
O objetivo do experimento de hoje é pesquisar e entender os processos de atribuição de endereços de programas realizados em tempo de compilação pelos softwares básicos como: compilador, linker, e assembler. Sendo assim, neste experimento vamos utilizar os seguintes softwares para criação e análise de código:<br />
<br />
*'''GCC''': compilador para gerar código objeto a partir de um código de programa escrito na linguagem c;<br />
*'''GNU Linker (LD)''': Para vincular os códigos (módulos) objetos do programa;<br />
*[https://linux.die.net/man/1/ld| Linker ] <br />
*'''GNU Assembler''': Para gerar o código executável a partir do código objeto;<br />
*[https://linux.die.net/man/1/as | assembler]<br />
* '''OBJDUMP''': Para mostrar informações do código;<br />
*[https://linux.die.net/man/1/objdump | Objdump ]<br />
<br />
<br />
A seguir segue descrito o programa a ser utilizado no exercício 1:<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
int main()<br />
{<br />
printf("Hello, World!");<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
Trata-se do programa hello word, este programa apenas exibe uma mensagem na tela. No entanto, vamos analisar como são as etapas confecção do executável a partir deste código ''simples''. <br />
<br />
Exercício 1: <br />
* Compile o programa hello word, e o transforme em código objeto utilizando o programa GCC. Para esta tarefa execute o seguinte comando:<br />
<code><br />
gcc -o hello hello.c <br />
</syntaxhighlight><br />
* Agora abra o código objeto utilizando o programa OBJDUMP.<br />
<code><br />
objdump -D hello<br />
</syntaxhighlight><br />
* Identifique quais são as seções de código obtidas a partir do '''hello.c'''.<br />
* Pesquise e entenda o significado das seções de código: .bss, .txt, .data, .init.<br />
* Faça uma análise e identifique o endereço de memória que o programa ''hello world'' vai ser carregado. <br />
* Este código objeto é relocável? Justifique sua resposta.<br />
* Agora gere o código assembly do hello world.<br />
<code><br />
gcc -S hello.c<br />
</syntaxhighlight> <br />
*Agora gere o código executável utilizando o programa '''AS''' e o programa '''LD'''.<br />
<code><br />
as -o hello.o hello.s<br />
</syntaxhighlight><br />
* Como a etapa de linkagem para a construção do código executável está sendo executada sem o auxílio do '''GCC''', necessitamos vincular manualmente as bibliotecas necessárias. Para criar apropriadamente o executável vamos precisar das bibliotecas '''ld-linux-x86-64.so.2''', '''crt1.o''', '''crti.o''', '''crtn.o'''.<br />
* Para descobrir suas respectivas localizações use o comando '''LOCATE'''. Por exemplo:<br />
<code><br />
<br />
locate crti.o <br />
<br />
</syntaxhighlight><br />
<br />
ou <br />
<br />
<code><br />
<br />
find /usr/ -name crti*<br />
<br />
</syntaxhighlight><br />
<br />
* Agora que já sabemos a localização das bibliotecas necessárias vamos vincular essas a nossa aplicação.<br />
<code><br />
ld --dynamic-linker /caminho/ld-linux-x86-64.so.2 /caminho/crt1.o /caminho/crti.o /caminho/crtn.o hello.o -lc -o hello.exe<br />
</syntaxhighlight><br />
<br />
* Agora abra o código objeto utilizando o programa OBJDUMP.<br />
* Faça uma análise e identifique o endereço de memória em que o programa ''hello world'' inicializa suas estruturas na memória.<br />
* Dica!<br />
<code><br />
objdump -D -s -j .init hello.exe<br />
</syntaxhighlight><br />
* Houve diferença entre os endereços do programa executável em relação ao código objeto? Explique.<br />
* Explique as principais diferenças entre o arquivo objeto .o e o executável final. (dica utilize o objdump para fazer essa análise)<br />
{{collapse bottom}}<br />
<ol><br />
<li> Estudar e executar o código em http://cs.lmu.edu/~ray/notes/gasexamples/ <br />
Detalhes das chamadas na arquitetura x86_64 ver em https://lwn.net/Articles/604287/ <br />
<li>Estudar e executar o código usando a função (em conformidade com a API POSIX) write() para o ''hello world'':<br />
<code><br />
#include <unistd.h> <br />
<br />
main()<br />
{<br />
write(1,"Alo Mundo\n",10);<br />
}<br />
</syntaxhighlight><br />
</li><br />
<li> Use o comando strace para verificar todas as chamadas de sistema dos programas acima.<br />
</li><br />
<li><br />
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:<br />
<code><br />
main()<br />
{<br />
meu_hello_world();<br />
}<br />
</syntaxhighlight><br />
</li><br />
Gere o assembly do código em C e discuta a diferença entre uma chamada de função e uma chamada de sistema.<br />
<li><br />
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:<br />
<code><br />
#include <string.h><br />
main()<br />
{<br />
char *p="Tudo bem com vocês?";<br />
meu_hello_world(p, strlen(p));<br />
}<br />
</syntaxhighlight><br />
Solução:<br />
{{collapse top|Solução}}<br />
<code><br />
modificado de http://cs.lmu.edu/~ray/notes/gasexamples/<br />
.global meu_hello_world<br />
<br />
.text<br />
meu_hello_world:<br />
<br />
push %rdi # salva primeiro parâmetro<br />
push %rsi # salva segundo parâmetro<br />
mov $1, %rax # system call 1 é write<br />
mov $1, %rdi # file handle 1 é stdout<br />
mov $message, %rsi # endereço da string<br />
mov $13, %rdx # número de bytes da string<br />
syscall # chamada ao sistema<br />
<br />
pop %rdx # o que havia sido passado em rsi (número de bytes) é colocado em rdx<br />
pop %rsi # o que havia sido colocado em rdi (endereço da string) é colocado em rsi<br />
mov $1, %rax # system call 1 is write<br />
mov $1, %rdi # file handle 1 é stdout<br />
syscall # nova chamada ao sistema<br />
<br />
ret<br />
<br />
message:<br />
.ascii "Hello, World\n"<br />
</syntaxhighlight><br />
</li><br />
</ol><br />
{{collapse bottom}}</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=SOP29005-2019-2&diff=162031SOP29005-2019-22019-10-04T12:07:01Z<p>127.0.0.1: /* AULA 18 - Dia 02/10/2019 */</p>
<hr />
<div>=AULA 1 - Dia 30/07/2019=<br />
<br />
===Objetivos/Conteúdos===<br />
<br />
*Apresentação do Plano de Ensino<br />
**Objetivos e Conteúdo Programático da Disciplina (ver SIGAA)<br />
**Forma de Avaliação (ver SIGAA)<br />
<br />
*Introdução a Sistemas Operacionais (Cap1. do Silberschatz)<br />
**O que faz um sistema operacional (1.1)<br />
**Organização e Arquitetura de um Sistema Computacional (1.2 e 1.3)<br />
***Importância da Interrupção e Timers (1.2.1)<br />
***Estrutura de Armazenamento (1.2.2)<br />
***Estrutura de IO (1.2.3)<br />
**Estrutura e Operações de um Sistema Operacional (1.4 e 1.5)<br />
<br />
===Material de Referência===<br />
<br />
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte1.pdf Apresentação sobre histórico visão geral e estruturas básicas de um SO]<br />
* [http://codex.cs.yale.edu/avi/os-book/OSE1/slide-dir/index.html Slides Silberschatz Oitava Edição]<br />
* [http://professor.unisinos.br/barbosa/SO/ch1br.ppt Tradução Slides Silberschatz Cap1]<br />
* [http://professor.unisinos.br/barbosa/SO/ch2br.ppt Tradução Slides Silberschatz Cap2]<br />
* [http://professor.unisinos.br/barbosa/SO/ch3br.ppt Tradução Slides Silberschatz Cap3]<br />
* [http://professor.unisinos.br/barbosa/SO/ch4br.ppt Tradução Slides Silberschatz Cap4]<br />
* [http://wiki.inf.ufpr.br/maziero/doku.php?id=so:livro_de_sistemas_operacionais Livro do Prof.Maziero]<br />
* [http://deptinfo.unice.fr/~rr/l3systres/ Université Nice Sophia Antipolis]<br />
<br />
Arliones:<br />
<br />
*[https://www.dropbox.com/s/dt80g3tml65rpmg/SOP29005-parte6.odp?dl=0]<br />
*[https://www.dropbox.com/s/7lneavq0go9kz2t/SOP29005-parte7.odp?dl=0]<br />
<br />
===Leitura Recomendada===<br />
<br />
*Cap.1 do Silberschatz principalmente:<br />
**1.1 a 1.9<br />
<br />
===Exercícios Práticos de Apoio a Aula===<br />
<br />
Na sequência. com fins motivacionais, são apresentados alguns exercícios ilustrando conceitos de processos, arquivos e permissionamento.<br />
<br />
<ol><br />
<li><br />
Comando para ver todos os processos no linux:<br />
<code><br />
$ ps aux<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Colocar 2 processos se executando no contexto de um terminal e verificar número dos processos e então "destruí-los":<br />
<code><br />
$ yes > /dev/null<br />
$ yes > /dev/null<br />
$ ps <br />
$ kill -9 <pid_yes><br />
$ kill -9 <pid_yes><br />
</syntaxhighlight><br />
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.<br />
</li><br />
<li><br />
Criar um terminal adicional<br />
<code><br />
$ xterm<br />
</syntaxhighlight><br />
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:<br />
<code><br />
$ echo Alo Terminal > /dev/pts/2<br />
$ kill -9 <pid_terminal><br />
</syntaxhighlight><br />
</li><br />
<li><br />
Comunicação entre processos:<br />
<code><br />
$ cat /etc/passwd | grep home | wc -l<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Retirando a permissão de leitura de um arquivo em nível de usuário proprietário:<br />
<code><br />
$ echo Alo Mundo > alfa.txt<br />
$ ls -l alfa.txt<br />
$ cat alfa.txt<br />
$ chmod u-r alfa.txt<br />
$ cat alfa.txt<br />
$ chmod u+r alfa.txt<br />
$ cat alfa.txt <br />
</syntaxhighlight><br />
</li><br />
</ol><br />
<br />
=AULA 2 - Dia 2/08/2019=<br />
<br />
===Objetivos/Conteúdos===<br />
<br />
*Continuação da Aula<br />
*Estruturas do Sistema Operacional (cap.2)<br />
**Serviços do Sistema Operacional (2.1)<br />
**Interfaces com Usuários (2.2)<br />
**Chamadas do Sistema (2.3)<br />
**Tipos de Chamadas de Sistema (2.4) ver Fig.2.8<br />
***Chamadas de Controle de Processos<br />
**Arquiteturas e Estruturas de Sistemas Operacionais (2.7)<br />
**Máquinas Virtuais (2.8)<br />
<br />
===Material de Referência===<br />
<br />
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte1.pdf Apresentação sobre histórico visão geral<br />
* [http://www.fil.univ-lille1.fr/~sedoglav/OS/TP.html ]<br />
<br />
===Leitura Recomendada===<br />
<br />
*Cap.2 do Silberschatz principalmente:<br />
**2.1 a 2.8<br />
<br />
===Exercícios===<br />
<br />
=AULA 3 - Dia 7/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*Continuação da aula anterior<br />
**Chamadas do Sistema (2.3)<br />
**Tipos de Chamadas de Sistema (2.4) ver Fig.2.8<br />
***Chamadas de Controle de Processos<br />
**Arquiteturas e Estruturas de Sistemas Operacionais (2.7)<br />
**Máquinas Virtuais (2.8)<br />
<br />
===Exercícios===<br />
<br />
<ol><br />
<li> Estudar e executar o código em http://cs.lmu.edu/~ray/notes/gasexamples/ <br />
Detalhes das chamadas na arquitetura x86_64 ver em https://lwn.net/Articles/604287/ <br />
<li>Estudar (usar o man) e executar o código usando a função (em conformidade com a API POSIX) write() para o ''hello world'':<br />
<code><br />
#include <unistd.h> <br />
<br />
main()<br />
{<br />
write(1,"Alo Mundo\n",10);<br />
}<br />
</syntaxhighlight><br />
</li><br />
<li> Use o comando strace para verificar todas as chamadas de sistema dos programas acima.<br />
</li><br />
<li><br />
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() 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:<br />
<code><br />
void meu_hello();<br />
<br />
int main()<br />
{<br />
meu_hello();<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
</li><br />
Gere o assembly do código em C e discuta a diferença entre uma chamada de função e uma chamada de sistema.<br />
<li><br />
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:<br />
<code><br />
#include <string.h><br />
main()<br />
{<br />
char *p="Tudo bem com vocês?";<br />
meu_hello_world(p, strlen(p));<br />
}<br />
</syntaxhighlight><br />
Solução:<br />
{{collapse top|Solução}}<br />
<code><br />
modificado de http://cs.lmu.edu/~ray/notes/gasexamples/<br />
.global meu_hello_world<br />
<br />
.text<br />
meu_hello_world:<br />
<br />
push %rdi # salva primeiro parâmetro<br />
push %rsi # salva segundo parâmetro<br />
mov $1, %rax # system call 1 é write<br />
mov $1, %rdi # file handle 1 é stdout<br />
mov $message, %rsi # endereço da string<br />
mov $13, %rdx # número de bytes da string<br />
syscall # chamada ao sistema<br />
<br />
pop %rdx # o que havia sido passado em rsi (número de bytes) é colocado em rdx<br />
pop %rsi # o que havia sido colocado em rdi (endereço da string) é colocado em rsi<br />
mov $1, %rax # system call 1 is write<br />
mov $1, %rdi # file handle 1 é stdout<br />
syscall # nova chamada ao sistema<br />
<br />
ret<br />
<br />
message:<br />
.ascii "Hello, World\n"<br />
</syntaxhighlight><br />
</li><br />
</ol><br />
{{collapse bottom}}<br />
<br />
=AULA 4 - Dia 9/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*PARTE 2A: Gerenciamento de Processos (cap.3)<br />
*3.1.Conceito de Processo<br />
*3.2.Escalonamento de Processos<br />
*3.3.Operações sobre Processos (Laboratório Operações sobre Processos no Linux: Fork/Exec/Wait)<br />
<br />
===Material de Referência===<br />
<br />
*Slides do Cap.3 - Silberschatz<br />
*Laboratório Fork/Exec/Wait<br />
<br />
=== Exercícios de Demonstração===<br />
<br />
#Executar em um terminal o comando top. Em um outro terminal executar:<br />
yes > /dev/null &<br />
yes > /dev/null &<br />
#Parar um dos processos yes<br />
kill -STOP <pid_yes><br />
#Continuar o processo<br />
kill -CONT <pid_yes><br />
#Destruir todos<br />
killall yes<br />
<br />
=AULA 5 - Dia 14/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*Ainda Processos<br />
*Cap.3.2..Escalonamento de Processos<br />
*Cap.2.3.Operaçṍes sobre processos<br />
*Finalização do Laboratório Fork/Exec/Wait<br />
<br />
===Adendo===<br />
<br />
*Estudar e comentar [https://www.geeksforgeeks.org/wait-system-call-c/]<br />
<br />
=AULA 6 - Dia 16/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*Comunicação Interprocessos (3.4 e 3.5)<br />
*Laboratório de Memória Compartilhada<br />
<br />
=AULA 7 - Dia 21/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Comunicação Interprocessos: Troca de Mensagens (3.6)<br />
*Laboratório de Pipes<br />
<br />
=AULA 8 - Dia 23/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Finalização Lab. pipes nomeados.<br />
*Threads ((cap.4.1, 4.2)<br />
*Lab.Threads de Aplicação<br />
<br />
=AULA 9 - Dia 28/08/2019=<br />
<br />
*Laboratório: Ainda Threads - Um escalonador semi-automático<br />
<br />
<br />
=AULA 10 - Dia 30/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Repassar um primeiro estudo sobre o RTOS<br />
*Revisar Processos e Threads<br />
<br />
==Questionário - Processos==<br />
<br />
#Conceitue processo. Descreva e explique cada uma das seções de um processo na memória.<br />
#Faça um diagrama e explique os possíveis estados de um processo no sistema. O que produz a transição entre estados?<br />
#O que é um Bloco de Controle de Processo? Quais informações ficam armazenadas neste bloco?<br />
#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.<br />
#Explique o que é multiprogramação e escalonamento de processos.<br />
#O que é a fila de processos prontos?<br />
#Diferencie um processo limitado por IO de um processo limitado por CPU.<br />
#Diferencie escalonamento de longo prazo de escalonamento de curto prazo.<br />
#Discuta o papel da interrupção na troca de contexto entre processos.<br />
#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?<br />
#Explique como funciona a chamada exec no UNIX/Linux<br />
#Explique como funciona a chamada wait no UNIX/Linux e como é possível retornar valores de um filho para o pai.<br />
#Faça um esqueleto de um programa UNIX/Linux que ao se tornar processo cria 3 filhos e espera pela execução dos mesmos.<br />
<br />
==Questionário - Comunicação entre Processos==<br />
<br />
#Diferenciar processos independentes de processos cooperantes.<br />
#Enumere e explique quatro razões para cooperação entre processos.<br />
#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.<br />
#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.<br />
#A memória compartilhada requer chamada ao sistema na sua operação? Discuta.<br />
#Por que o processo de troca de mensagem deve ser mais lento que a memória compartilhada?<br />
#Apresente em pseudocódigo uma proposta de funcionamento do problema do produtor consumidor usando memória compartilhada.<br />
#A construção de uma solução para o problema produtor consumidor pode ser facilitado pelo uso da memória compartilhada? Discuta.<br />
#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?<br />
#Enumere três métodos de implementação de uma lógica de ligação (link) entre processos.<br />
#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.<br />
#Descreva a variante assimétrica da troca direta de mensagens. O que muda em termos de primitiva de comunicação?<br />
#Descreva o problema de hard-coding associado a nomeação direta e como pode ser contornado através da nomeação/comunicação indireta?<br />
#O que é uma caixa postal? Como o Posix identifica uma caixa postal no caso de fila de mensagens?<br />
#Dois processos podem usar mais do que uma caixa postal para se comunicar? Qual a condição para que isto ocorra?<br />
#Descreva as duas operações básicas para a troca de mensagens com Caixa Postal.<br />
#Descreva na comunicação indireta via Caixa Postal as 3 propriedades básicas.<br />
#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.<br />
#De que forma a caixa postal estando no espaço de endereçamento de um processo (propriedade) afeta a recepção por mensagens? Descreva.<br />
#Quais as operações sobre uma caixa postal criada no espaço do sistema operacional deverão ser disponíveis? Descreva.<br />
#A transmissão de mensagem pode ser com e sem bloqueio. Descreva as 4 possibilidades (síncrona/assíncrona).<br />
#Discuta as 3 possibilidades de armazenamento de mensagens em buffer. Em que condições um remetente pode ser bloqueado?<br />
<br />
==ETAPA 1 - Projeto Final==<br />
<br />
*Apresentação (slides) sobre a parte de gerenciamento de tarefas no RTOS;<br />
*apresentação dia 18/09/2019<br />
<br />
==Referências==<br />
<br />
*[https://www.freertos.org/RTOS.html Site do FreeRTOS] ver Mastering the FreeRTOS Real Time Kernel - a Hands On Tutorial Guide <br />
*[https://www.embarcados.com.br/rtos-sistema-operacional-de-tempo-real/]<br />
*[https://github.com/feilipu/avrfreertos]<br />
<br />
=AULA 11 - Dia 4/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Pico de CPU X Pico de IO <br />
*Preempção X Não Preempção<br />
*Escalonamento de Processos: Escalonamento FCFS<br />
<br />
<br />
=AULA 12 - Dia 6/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Escalonamento de Processos: <br />
**Shortest Job First (preemptivo e não preemptivo)<br />
**Prioridade (preemptivo e não preemptivo)<br />
**Round-Robin: Preemptivo<br />
*Lab.Round Robin<br />
<br />
==Material de Referência==<br />
<br />
http://docente.ifsc.edu.br/andre.damato/sop2018/SOP2018-parte2.pdf<br />
<br />
<br />
=AULA 13 - Dia 13/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Sincronização entre Processos<br />
*Laboratório do Esquema de Peterson<br />
<br />
==Material de Referência==<br />
<br />
*Livro Silberchatz<br />
*https://www.os-book.com/OSE1/slide-dir/PPT-dir/ch6.ppt<br />
<br />
=AULA 14 - Dia 18/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Sincronização entre Processos<br />
*Lock de Hardware<br />
*Laboratório do TSL<br />
<br />
==Laboratório Proposto==<br />
<br />
*Refazer o problema proposto usando uma instrução simualada de test and set. Prever um liite superior para entrada de um processo na região crítica.<br />
<br />
==Material de Referência==<br />
<br />
*Livro Silberchatz<br />
*https://www.os-book.com/OSE1/slide-dir/PPT-dir/ch6.ppt<br />
<br />
<br />
=AULA 15 - Dia 20/08/2019=<br />
<br />
==O ATmega238 usado no Arduino UNO==<br />
<br />
Ver [https://pt.wikipedia.org/wiki/ATmega328]<br />
<br />
==O Arduino UNO==<br />
<br />
Ver [https://pt.wikipedia.org/wiki/Arduino]<br />
Ver [https://github.com/feilipu/Arduino_FreeRTOS_Library]<br />
<br />
==O FreeRtos para o Arduino==<br />
<br />
Ver [https://github.com/feilipu/Arduino_FreeRTOS_Library]<br />
<br />
Para instalar no IDE:<br />
*Baixar o ZIP do link acima<br />
*No IDE importar a biblioteca:<br />
**sketch->IncluirBiblioteca->Adicionar do arquivo ZIP<br />
<br />
<br />
==Código Experimental==<br />
<br />
Este código demonstra a ocorrência de "race condition".<br />
<br />
<syntaxhighlight lang=c><br />
// Code based on Examples of Arduino and examples <br />
// from https://github.com/feilipu/Arduino_FreeRTOS_Library<br />
<br />
#include <Arduino_FreeRTOS.h><br />
#include <FreeRTOSVariant.h><br />
#include <task.h><br />
#include <semphr.h><br />
<br />
#define TAM_BUFF 10<br />
<br />
volatile unsigned long race_flag=0xFFEEDDCC;<br />
volatile unsigned long int cont;<br />
int task_cont=0;<br />
<br />
void PrintSerial( void *pvParameters ); // Task para imprimir valor de race_flag<br />
void TaskBlink( void *pvParameters );<br />
void TaskSetarace_flag(void *pvParameters); //Task que atribui race_flag=0xFFEEDDCC<br />
void TaskZerarace_flag(void *pvParameters); //Task que atribui race_flag=0xAA0000AA<br />
<br />
// função de setup<br />
<br />
void setup() {<br />
<br />
Serial.begin(9600);<br />
<br />
while (!Serial) {<br />
; // wait for serial port to connect. Needed for native USB, on LEONARDO, MICRO, YUN, and other 32u4 based boards.<br />
}<br />
<br />
<br />
// criar as 2 tarefas<br />
<br />
xTaskCreate(<br />
TaskBlink<br />
, (const portCHAR *)"Blink" // A name just for humans<br />
, 128 // This stack size can be checked & adjusted by reading the Stack Highwater<br />
, NULL<br />
, 1 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.<br />
, NULL );<br />
<br />
xTaskCreate(<br />
TaskPrintSerial<br />
, (const portCHAR *) "PrintSerial"<br />
, 128 // Stack size<br />
, NULL<br />
, 1 // Priority<br />
, NULL );<br />
<br />
xTaskCreate(<br />
TaskSetarace_flag<br />
, (const portCHAR *) "Setarace_flag"<br />
, 128 // Stack size<br />
, NULL<br />
, 1 // Priority<br />
, NULL );<br />
<br />
xTaskCreate(<br />
TaskZerarace_flag<br />
, (const portCHAR *) "Zerarace_flag"<br />
, 128 // Stack size<br />
, NULL<br />
, 1 // Priority<br />
, NULL );<br />
<br />
cont = race_flag;<br />
<br />
// escalonador toma conta a partir daqui<br />
<br />
}<br />
<br />
void loop()<br />
{<br />
// nada a fazer aqui<br />
}<br />
<br />
/*--------------------------------------------------*/<br />
/*---------------------- Tasks ---------------------*/<br />
/*--------------------------------------------------*/<br />
<br />
void TaskBlink(void *pvParameters) // This is a task.<br />
{<br />
(void) pvParameters;<br />
<br />
/*<br />
Blink<br />
Turns on an LED on for one second, then off for one second, repeatedly.<br />
<br />
Most Arduinos have an on-board LED you can control. On the UNO, LEONARDO, MEGA, and ZERO <br />
it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN takes care <br />
of use the correct LED pin whatever is the board used.<br />
<br />
The MICRO does not have a LED_BUILTIN available. For the MICRO board please substitute<br />
the LED_BUILTIN definition with either LED_BUILTIN_RX or LED_BUILTIN_TX.<br />
e.g. pinMode(LED_BUILTIN_RX, OUTPUT); etc.<br />
<br />
If you want to know what pin the on-board LED is connected to on your Arduino model, check<br />
the Technical Specs of your board at https://www.arduino.cc/en/Main/Products<br />
<br />
This example code is in the public domain.<br />
<br />
modified 8 May 2014<br />
by Scott Fitzgerald<br />
<br />
modified 2 Sep 2016<br />
by Arturo Guadalupi<br />
*/<br />
<br />
// initialize digital LED_BUILTIN on pin 13 as an output.<br />
pinMode(LED_BUILTIN, OUTPUT);<br />
<br />
for (;;) // A Task shall never return or exit.<br />
{<br />
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)<br />
vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second<br />
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW<br />
vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second<br />
}<br />
}<br />
<br />
<br />
<br />
<br />
void TaskPrintSerial(void *pvParameters) // Task que imprime na serial - must be improved...<br />
{<br />
(void) pvParameters;<br />
/*<br />
<br />
*/<br />
<br />
<br />
for (;;)<br />
{ <br />
while (cont==0xAA0000AA || cont==0xFFEEDDCC)<br />
cont = race_flag;<br />
;<br />
<br />
Serial.println("Problemas: valor race_flag é");<br />
Serial.println(cont, HEX);<br />
<br />
vTaskDelay(5); // one tick delay (15ms) in between reads for stability - b<br />
cont = race_flag;<br />
}<br />
}<br />
<br />
void TaskSetarace_flag(void *pvParameters) <br />
{<br />
(void) pvParameters;<br />
const TickType_t xMaxBlockTimeTicks = 0x20;<br />
/*<br />
<br />
*/<br />
<br />
race_flag=0xAA0000AA;<br />
for (;;)<br />
{<br />
race_flag=0xAA0000AA;<br />
//Serial.println("Produtor");<br />
vTaskDelay( ( rand() %xMaxBlockTimeTicks) ); <br />
} <br />
<br />
}<br />
<br />
void TaskZerarace_flag(void *pvParameters) <br />
{<br />
(void) pvParameters;<br />
const TickType_t xMaxBlockTimeTicks = 0x20;<br />
/*<br />
<br />
*/<br />
race_flag=0xFFEEDDCC;<br />
<br />
for (;;)<br />
{<br />
race_flag=0xFFEEDDCC;<br />
vTaskDelay( ( rand() %xMaxBlockTimeTicks) ); <br />
if(task_cont++==100) {<br />
delay(1);<br />
Serial.println("Fim TaskZera - valor race_flag ");<br />
Serial.println(race_flag, HEX);<br />
for(;;);<br />
} <br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=AULA 16 - Dia 25/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Preparação de exemplos de RTOS sobre Arduíno para apresentação na sexta;<br />
<br />
=Laboratórios Propostos= <br />
<br />
Considere o código abaixo. Observe que a região de dados compartilhada shared_data é zerada pelo pai e setada pelo processo filho. O pai detecta inconsistências nos dados que operou. Tente corrigir usando o esquema de Peterson para acesso a região crítica. Crie uma função de entrada e de saída da região crítica.<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
<br />
<br />
#define BUFFER_SIZE 4096<br />
char *shared_data;<br />
char reference_data[BUFFER_SIZE];<br />
<br />
main()<br />
{ <br />
key_t key;<br />
int shmid;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, BUFFER_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
shared_data = shmat(shmid, (void *)0, 0);<br />
<br />
if (shared_data == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int count=0; <br />
memset(reference_data,0,BUFFER_SIZE); <br />
for(;;){ <br />
memset(shared_data,0,BUFFER_SIZE);<br />
if (memcmp(shared_data, reference_data, BUFFER_SIZE)!=0) {<br />
count++;<br />
if (count%1000000==0)<br />
printf("Processo pai detectou algo errado nos dados %d\n", count); <br />
} <br />
} <br />
<br />
<br />
}<br />
else { /*Child code */<br />
<br />
for(;;){ <br />
memset(shared_data,1,BUFFER_SIZE); <br />
}<br />
<br />
}<br />
<br />
if (shmdt(shared_data) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
Possível solução:<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
#include <unistd.h><br />
<br />
#define BUFFER_SIZE 4096<br />
#define ID_PAI 0<br />
#define ID_FILHO 1<br />
#define FALSE 0<br />
#define TRUE 1<br />
<br />
char *shared_data;<br />
char reference_data[BUFFER_SIZE];<br />
<br />
struct tipo_peterson{<br />
char flag[2];<br />
char turn;<br />
} *pet_struct;<br />
<br />
void ent_sec_crit(int id)<br />
{<br />
char id_outro = (id+1)%2;<br />
<br />
pet_struct->flag[id] = TRUE; // indica que o processo deseja entrar na região crítica<br />
pet_struct->turn = id_outro; // o processo sinaliza para o outrao entrar, <br />
// caso o outro esteja entrando<br />
// este ponto é uma race condition: turn pode ser 0 ou 1 <br />
while ( (pet_struct->flag[id_outro]==TRUE) && (pet_struct->turn == id_outro) )<br />
;<br />
}<br />
<br />
void sai_sec_crit(int id)<br />
{<br />
pet_struct->flag[id] = FALSE;<br />
}<br />
<br />
int main()<br />
{ <br />
key_t key;<br />
int shmid;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, BUFFER_SIZE+sizeof(struct tipo_peterson), S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
shared_data = shmat(shmid, (void *)0, 0);<br />
pet_struct = (struct tipo_peterson *) (shared_data + BUFFER_SIZE); <br />
<br />
if (shared_data == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int count=0; <br />
memset(reference_data,0,BUFFER_SIZE); <br />
for(;;){ <br />
ent_sec_crit(ID_PAI);<br />
memset(shared_data,0,BUFFER_SIZE);<br />
if (memcmp(shared_data, reference_data, BUFFER_SIZE)!=0) {<br />
count++;<br />
if (count%1000000==0)<br />
printf("Processo pai detectou algo errado nos dados %d\n", count); <br />
} <br />
sai_sec_crit(ID_PAI);<br />
} <br />
<br />
<br />
}<br />
else { /*Child code */<br />
<br />
for(;;){<br />
ent_sec_crit(ID_FILHO); <br />
memset(shared_data,1,BUFFER_SIZE);<br />
sai_sec_crit(ID_FILHO); <br />
}<br />
<br />
}<br />
<br />
if (shmdt(shared_data) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
=AULA 17 - Dia 27/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Apresentação dos Trabalhos<br />
*Definição da próxima etapa<br />
<br />
=AULA 18 - Dia 02/10/2019=<br />
<br />
==Objetivos==<br />
<br />
*Semáforos, Deadlock e o Problema da Inversão de Prioridade<br />
*Laboratório de Pthreads e Mutex;<br />
<br />
==Laboratório Proposto==<br />
<br />
*Lab. Programação concorrente - Parte 1<br />
<br />
==Materia de Referência==<br />
<br />
*[https://www.os-book.com/OSE1/slide-dir/PDF-dir/ch6.pdf]<br />
<br />
==Desafio==<br />
<br />
Usar <br />
ps -T aux | grep ex1vA<br />
<br />
Para ver os threads dormindo...<br />
<br />
Otimizar o programa abaixo<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <pthread.h><br />
#include <stdlib.h><br />
#include <unistd.h><br />
#include <time.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
pthread_mutex_t mut;<br />
<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
<br />
<br />
long long i;<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
usleep(5000000);<br />
printf("Novo saldo = %d\n",novo_saldo);<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d\n", (i+1));<br />
exit(-1);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
printf("Saldo final é %d\n", saldo);<br />
}<br />
</syntaxhighlight><br />
<br />
=AULA 19 - Dia 04/10/2019=<br />
<br />
==Objetivos==<br />
<br />
*Ainda Semáforos, Deadlock e o Problema da Inversão de Prioridade<br />
*Laboratório de Pthreads com semáforo binário;<br />
*Laboratório de Pthreads com produtor e consumidor<br />
<br />
<br />
==Laboratório Proposto==<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Programação concorrente}}<br />
<br />
== Programação concorrente ==<br />
<br />
<br />
===PARTE 1 - Mutex e Biblioteca libpthreads===<br />
<br />
;POSIX Threads<br />
A 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):<br />
*''pthread_create'': cria uma thread;<br />
*''pthread_kill'': força a terminação de uma thread;<br />
*''pthread_join'': sincroniza o final de uma thread (qual a diferença/semelhança com o ''wait'' que usamos para processos?);<br />
*''pthread_exit'': finaliza uma thread.<br />
Para utilizar estas funções é necessário linkar o programa à libpthread (''-lpthread''). <br />
<br />
<br />
;POSIX pthread mutex<br />
<br />
A biblioteca pthread implementa um tipo ''pthread_mutex_t'', que garante a exclusão mútua entre threads. Estes mutex são manipulados através das funções (acesse as man-pages das chamadas para maiores detalhes):<br />
*''pthread_mutex_lock'': acessa um mutex.<br />
*''pthread_mutex_trylock'': tenta acessar um mutex (retorna valor indicando sucesso ou falha no lock).<br />
*''pthread_mutex_unlock'': libera um mutex.<br />
<br />
<br />
<br />
;Exercício 1<br />
<br />
O programa abaixo cria 5 threads, e cada uma destas threads atualiza uma variável global (memória compartilhada).<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
#include <pthread.h><br />
#include <stdlib.h><br />
#include <unistd.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
pthread_mutex_t mut;<br />
<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
long long i;<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
sleep(1);<br />
printf("Novo saldo = %d\n",novo_saldo);<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d\n", (i+1));<br />
exit(-1);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
printf("Saldo final é %d\n", saldo);<br />
}<br />
</syntaxhighlight><br />
<br />
# Compile este programa. <br />
# Execute este programa várias vezes. Ele funciona? Será que ele gera as saídas esperadas?<br />
# Identifique as '''seções críticas''' do programa.<br />
# Corrija o programa utilizando '''mutex'''. <br />
# Analise a função ''AtualizaSaldo()'' com a sua solução. Lembre-se que o uso do mutex implica em apenas uma thread acessar a seção crítica por vez, enquanto outras threads ficam bloqueadas, esperando. Disso vem que, quanto menor o trecho de código entre um ''lock'' e um ''unlock'', menos tempo uma thread necessita ficar esperando.<br />
<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <cstring><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
<br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
sem_t sem;<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
int value;<br />
sem_wait(&sem);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
sem_getvalue(&sem, &value);<br />
printf("valor sem = %d\n", value);<br />
sem_post(&sem);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
sem_init(&sem,0,1);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
sem_destroy(&sem);<br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
===PARTE 2 - POSIX Semaphores===<br />
<br />
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):<br />
*''sem_init'': inicializa um semáforo;<br />
*''sem_destroy'': destroy um semáforo;<br />
*''sem_wait'': implementa a operação ''p'';<br />
*''sem_post'': implementa a operação ''v''.<br />
Para utilizar estas funções é necessário linkar o programa à librt ou à libpthread (''-lrt'' ou ''-lpthread'').<br />
<br />
;Exercício 1<br />
Modifique o programa para usar um semáforo binário ao invés de um mutex em sua solução.<br />
<br />
;Exercício 2<br />
Refaça o exercício 3 usando processos criados com fork e exec. O semáforo deve ser criado em uma região de memória compartilhada.<br />
<br />
;Exercício 3<br />
Implemente com pthreads e semáforos/mutex a solução do produtor/comsumidor.<br />
<br />
;Exercício 4<br />
<br />
O programa abaixo manipula uma matriz de tamanho MxN (veja os defines para o tamanho da matriz). A função ''SumValues'' soma todos os valores em uma linha da matriz. A linha a ser somada é identificada pela variável ''i''. Modifique o programa principal (''main'') nos locais indicados para:<br />
# Criar N threads, uma para somar os valores de cada linha.<br />
# Receber o resultado do somatório de cada linha e gerar o somatório total da matriz.<br />
# Analise o programa: há problemas de sincronização que precisam ser resolvidos? Se sim, resolva-os.<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include "thread.h"<br />
<br />
/* number of matrix columns and rows */<br />
#define M 5<br />
#define N 10<br />
<br />
using namespace std;<br />
<br />
int matrix[N][M];<br />
Thread *threads[N];<br />
<br />
<br />
/* thread function; it sums the values of the matrix in the row */<br />
int SumValues(int i)<br />
{<br />
int n = i; /* number of row */<br />
int total = 0; /* the total of the values in the row */<br />
int j;<br />
for (j = 0; j < M; j++) /* sum values in the "n" row */<br />
total += matrix[n][j];<br />
cout << "The total in row" << n << " is " << total << "." << endl;<br />
/* terminate a thread and return a total in the row */<br />
exit(total);<br />
}<br />
<br />
int main(int argc, char *argv[])<br />
{<br />
int i, j;<br />
int total = 0; /* the total of the values in the matrix */<br />
<br />
/* initialize the matrix */<br />
for (i = 0; i < N; i++)<br />
for (j = 0; j < M; j++)<br />
matrix[i][j] = i * M + j;<br />
<br />
/* create threads */<br />
/* COLOQUE SEU CÓDIGO PARA CRIAR AS THREADS AQUI! */<br />
<br />
/* wait for terminate a threads */<br />
/* COLOQUE SEU CÓDIGO PARA PEGAR O SOMATÓRIO DE LINHAS E TOTALIZAR A SOMA DA MATRIZ AQUI! */<br />
<br />
cout << "The total values in the matrix is " << total << endl;<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
{{collapse bottom}}<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Escalonamento Round Robin e FCFS para Threads"}}<br />
<br />
== Escalonamento Round-Robin ==<br />
<br />
OBS: ver https://www.quora.com/What-exactly-does-typedef-do-in-C<br />
<br />
O Exemplo abaixo mostra a implementação de um esquema de escalonamento Round Robin do exercício anterior.<br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
Modificado por Eraldo <br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 5<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
void runA(void) {<br />
for (;;) {<br />
printf("running A\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runB(void) {<br />
for (;;) {<br />
printf("running B\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 1<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
<br />
void scheduler_rr();<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void yield_thread()<br />
{<br />
scheduler_rr();<br />
}<br />
<br />
void delete_thread()<br />
{<br />
delete curr_thread;<br />
curr_thread=NULL;<br />
scheduler_rr();<br />
}<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
struct delta{<br />
long alfa;<br />
char epson[1000];<br />
long beta;<br />
} shar;<br />
<br />
int turn;<br />
int flag[2];<br />
<br />
#define TRUE 1<br />
#define FALSE 0<br />
<br />
void ent_rc(int p, int vt)<br />
{<br />
flag[p]=TRUE;<br />
turn = vt;<br />
if(p) p=0; else p=1;<br />
while (flag[p] && turn == vt);<br />
//printf("Thread %d: esperando para acessar a região crítica\n", p);<br />
}<br />
<br />
void sai_rc(int p)<br />
{<br />
flag[p]=FALSE;<br />
}<br />
<br />
void runA(void) {<br />
struct delta x = {0, 100};<br />
<br />
for (;;) {<br />
x.alfa=0;x.beta=0;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0);<br />
x.alfa=100;x.beta=100;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0); <br />
}<br />
}<br />
<br />
void runB(void) {<br />
<br />
for (;;) {<br />
ent_rc(1,0);<br />
printf("shar alfa = %ld shar beta = %ld \n",shar.alfa, shar.beta); // regiao crítica<br />
sai_rc(1);<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runC(void) {<br />
int i;<br />
for (i=0;i<10;i++) {<br />
printf("Thread C - parte 1\n");<br />
yield_thread();<br />
printf("Thread C - parte 2\n");<br />
yield_thread();<br />
}<br />
delete_thread();<br />
}<br />
<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
add_thread(runC);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
{{collapse bottom}}<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Um escalonador semi-automático"}}<br />
<br />
== Ainda Threads - Um escalonador semi-automático usando sinais ==<br />
<br />
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.<br />
<br />
===Exemplo 1:===<br />
<br />
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. <br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
<br />
void sig_handler(int signo)<br />
{<br />
int x;<br />
printf("Turma de SOP: recebido SIGUSR1\n");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
// Loop eterno dormindo 1s<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Fazer no terminal:<br />
ps aux<br />
anotar o pid do processo e enviar o sinal:<br />
kill -USR1 pid<br />
<br />
===Exemplo 2:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// loop eterno que nunca é executado<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Enviar o sinal USR1 para ver o efeito. <br />
<br />
===Exemplo 3:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void prepara_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void prepara_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
prepara_contexto_ping();<br />
prepara_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// A long long wait so that we can easily issue a signal to this process<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Exercício: Use o comando htop para verificar como estes threads são vistos pelo SOP.<br />
<br />
Exercício: Tente analisar as pilhas dos threads e verificar sob qual pilha o handler se executa.<br />
<br />
<br />
===Exercício 4:===<br />
<br />
Neste ponto associamos um timer ao handler com o apoio do sinal ALRM. Agora os threads são escalonados automaticamente.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
===Exercício Proposto 5===<br />
<br />
Colocar 3 threads rodando.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void preparar_contexto_ping(ucontext_t *pContext, char *p)<br />
{<br />
char *stack;<br />
<br />
getcontext(pContext);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
(*pContext).uc_stack.ss_sp = stack ;<br />
(*pContext).uc_stack.ss_size = STACKSIZE;<br />
(*pContext).uc_stack.ss_flags = 0;<br />
(*pContext).uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(pContext, (void*)(*f_ping), 1, p);<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping(&cPing, "ping");<br />
preparar_contexto_ping(&cPong, "pong");<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Threads de aplicação}}<br />
<br />
== Threads de aplicação ==<br />
<br />
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:<br />
*'''getcontext(&a)''': salva o contexto na variável '''a''';<br />
*'''setcontext(&a)''': restaura um contexto salvo anteriormente na variável '''a''';<br />
*'''swapcontext(&a,&b)''': salva o contexto atual na variável '''a''' e restaura o contexto salvo anteriormente na variável '''b''';<br />
*'''makecontext(&a, ...)''': ajusta parâmetros internos do contexto salvo em '''a''';<br />
*'''ucontext_t''': as variáveis '''a''' e '''b''' são do tipo '''ucontext_t'''. Este tipo armazena um contexto.<br />
<br />
Busque mais informações sobre estas funções utilizando o programa manpage do Linux (ex.: man getcontext).<br />
<br />
Estude o código no arquivo pingpong.c abaixo e explique seu funcionamento.<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
*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.<br />
*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.<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain, cFnew;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_new(void * arg1, void * arg2,void * arg3,void * arg4) <br />
{<br />
printf ("%s: Primeira string %s %s %s\n",(char*) arg1,(char*) arg2,(char*) arg3, (char*) arg4);<br />
swapcontext(&cFnew, &cMain); <br />
}<br />
<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
<br />
getcontext(&cFnew);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cFnew.uc_stack.ss_sp = stack ;<br />
cFnew.uc_stack.ss_size = STACKSIZE;<br />
cFnew.uc_stack.ss_flags = 0;<br />
cFnew.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cFnew, (void*)(*f_new), 4, "\tF_new", "\tAlo", "\tMundo","\tReal");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
swapcontext(&cMain, &cFnew);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
--><br />
Exercício 3: O que acontece se um dos threads é colocado para dormir? Todos os demais threads param a sua execução.<br />
<br />
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/<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Processos no Linux}}<br />
<br />
== Processos no Linux - Modificado por Eraldo ==<br />
<br />
<blockquote style="background: lime; border: 1px solid black; padding: 1em;"><br />
Processos no Linux<br />
</blockquote><br />
<br />
*Exercícios propostos pelo Prof.Arliones e Modificados por Eraldo<br />
<br />
<br />
[[imagem:DesenhoForkExec.png|border|650px]]<br />
<br />
<br />
;Syscall FORK<br />
<br />
* Em um terminal, execute "man fork"<br />
** 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'''.<br />
** O '''código''' dos dois processos (pai e filho) são '''idênticos''';<br />
** Os '''dados''' dos dois processos (pai e filho) são '''idênticos NO MOMENTO DA CRIAÇÃO''';<br />
** Execução do processo filho inicia na próxima instrução do programa (no retorno da chamada FORK);<br />
** Não é possível saber qual dos processos (pai ou filho) retormará a execução primeiro - isto fica a cargo do excalonador do SO;<br />
** Valores de retorno da chamada FORK:<br />
*** (-1): erro na criação do processo (ex.: memória insuficiente);<br />
*** (0): em caso de sucesso, este é o valor de retorno recebido pelo processo filho;<br />
*** (>0): em caso de sucesso, este é o valor de retorno recebido pelo processo pai;<br />
<br />
;Syscall JOIN<br />
<br />
* A syscall JOIN é implementada no POSIX pela função '''wait()'''. Execute "man wait".<br />
** Além da função '''wait()''', há também '''waitpid()''' e '''waitid()''';<br />
** 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);<br />
** A chamada wait também libera os recursos do processo filho que termina;<br />
** '''wait()''': esta função suspende a execução do processo chamador até que UM DOS SEUS FILHOS finalize;<br />
** '''waitpid()''': suspende a execução do processo chamador até que UM FILHO ESPECÍFICO finalize;<br />
<br />
;Syscall EXEC<br />
<br />
* A syscall EXEC é implementada no POSIX pela família de funções '''exec()'''. Execute "man exec".<br />
** As principais funções da família são '''execl()''', '''execlp()''' e '''execvp()''';<br />
** 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;<br />
** 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;<br />
<br />
<br />
;Exemplos POSIX utilizando fork/wait/exec<br />
<br />
*Exemplo 1: fork/wait básico<br />
<syntaxhighlight lang=c><br />
// ex1: fork/wait básico<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
printf("processo filho\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
printf("processo pai\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
arliones@socrates:~/tmp$ gcc ex1.c -o ex1 <br />
arliones@socrates:~/tmp$ ./ex1 <br />
processo filho pid: 27858 pid pai: 27857<br />
processo pai pid: 27857 pid pai: 5337<br />
arliones@socrates:~/tmp$ <br />
</syntaxhighlight><br />
<br />
* Exemplo 2: processos pai e filho compartilham código, mas não dados.<br />
<syntaxhighlight lang=c><br />
// ex2: fork/wait "compartilhando" dados<br />
// ex2: fork/wait "compartilhando" dados<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status, k=0;<br />
printf("processo %d\t antes do fork\n", getpid());<br />
pid = fork();<br />
printf("processo %d\t depois do fork\n", getpid());<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
k += 1000;<br />
printf("processo filho\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status); // espera o filho terminar<br />
k += 10;<br />
printf("processo pai\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
k += 1000;<br />
printf("FIM processo %d\t K: %d\n", getpid(), k); <br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
processo 17056 antes do fork<br />
processo 17056 depois do fork<br />
processo 17057 depois do fork<br />
processo filho pid: 17057 K: 1000 endereço K: 0x7ffd8923e318<br />
processo pai pid: 17056 K: 10 endereço K: 0x7ffd8923e318<br />
</syntaxhighlight><br />
<br />
* Modificação no código: comentar linhas 23 e 30<br />
<br />
<syntaxhighlight lang=bash><br />
<br />
</syntaxhighlight><br />
<br />
* Analise os resultados e busque entender a diferença.<br />
*Perguntas e desafios.:<br />
#Analisando os valores impressos de k pode-se dizer que os dados são compartilhados entre os dois processos?<br />
#O endereço de k impresso é o mesmo nos dois processos. ISto não contradiz a afirmação anterior?<br />
#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.<br />
<br />
<br />
;Exercício fork/wait<br />
<br />
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.<br />
<br />
*Use o comando pstree para verificar a árvore de processos criada.<br />
<br />
{{collapse top|Solução}}<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
<!--<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
--><br />
<br />
;DESAFIO: fork/wait<br />
<br />
Reimplementar o exercício anterior de criação de uma árvore de 3 processos, generalizando a criação de N processos onde N é repassado na linha de comando do programa. SUGESTÃO: usar um comando for, mas lembrar que se existe um fork dentro do for, então cada filho gerado dará continuidade a execução do for. É necessário que o processo faça um exit ou retorne neste momento.<br />
<br />
;DESAFIO: Exercício status/wait<br />
<br />
O ''status'' passado como parâmetro à função ''wait(&status)'' é, na verdade, o mecanismo de retorno de resultado do ''wait/waitpid''. Ao retornar, esta variável contém informações sobre o resultado da execução do processo filho. Por exemplo, se um processo terminou normalmente (i.e., chamou ''exit''), o comando ''WIFEXITED(status)'' retorna ''true''. Este comando retorna ''false'' se o processo foi abortado (e.g., ''segmentation fault'') ou morto (e.g., ''kill''). Investigue no manual do wait no Linux (''man wait'') o funcionamento do comando WEXITSTATUS(status). <br />
Imagine um problema de busca de dados armazenados na forma de uma matriz de inteiros 4x30. Você está interessado em saber quantas ocorrências de um determinado número existe em cada linha da matriz. Note que que são tarefas que podem ser paralelizadas e usufruir de um sistema capaz de executá-las em paralelo. Faça uma implementação paralelizando 4 processos filhos a partir de um pai, onde cada processo é responsável por uma busca. A quantidade de ocorrências do número buscado é retornada e capturada através de WEXITSTATUS.<br />
<br />
;Syscall EXEC<br />
<br />
*Exemplo exec()<br />
<br />
<syntaxhighlight lang=c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
execl("/bin/ls","ls","-l", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 1: Modificar o código para mostrar que o exec() não retorna (colocar um printf após o exec).<br />
<br />
*Exercício 2: Criar um exemplo (dois programas ) para demonstrar que o exec não cria novo processo. <br />
**Crie um primeiro programa (prog1) que imprime o seu pid e depois faz um exec do segundo programa.<br />
**Crie o segundo programa que simplesmente imprime o pid.<br />
<br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU ANTES DO EXEC: Meu pid é %d\n", getpid());<br />
execl("./prog2","prog2", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU DEPOIS DO EXEC:Meu pid é %d\n", getpid());<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 3: Criar um exemplo usando fork/exec mostrando que um processo pai cria um filho e espera por sua execução. O filho executa o comando "ps aux". Ambos devem mostrar seus pids.<br />
<br />
{{collapse bottom}} <br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Laboratório Memória Compartilhada entre Pai e Filho - Produtor Consumidor}}<br />
<br />
Baseado no Lab. do Prof.Arliones<br />
<br />
=== Objetivo ===<br />
<br />
*Familiarizar o aluno com o conceito de Memória Compartilhada entre Processos Pai e Filho<br />
*Familizarizar o aluno com o conceito de Produtor Consumidor<br />
<br />
=== Referencial Teórico-Prático ===<br />
<br />
* Silberchatz - 3.4 e 3.5<br />
* man nos comandos shmat e shmget<br />
<br />
=== Exemplo de Funcionamento ===<br />
<br />
No exemplo abaixo um processo pai compartilha uma área de memória com o processo filho. O processo filho escreve uma mensagem para o pai na área de memória compartilhada e termina. O processo pai é desbloqueado no wait e imprime a mensagem escrita.<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
char *ptr_msg = "alo pai, tudo bem?"; <br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
strcpy(segmento, ptr_msg);<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(&filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
=== Desafio a ser Implementado em Sala ===<br />
<br />
Construir um programa em que um processo pai atua como produtor e o processo filho atua como consumidor. O buffer circular compartilhado é um buffer de inteiro de tamanho 5. O pai alimentará o buffer com 50 itens gerados aleatóriamente entre 1 e 100. A cada escrita/leitura no buffer o produtor/consumidor deve esperar alguns milisegundos de forma a acontecer situações de buffer cheio e vazio. <br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
#include <unistd.h><br />
#include <time.h><br />
#include <sys/types.h><br />
#include <sys/wait.h><br />
<br />
<br />
<br />
#define SHM_SIZE 1024 <br />
<br />
#define BUFF_COMP_SIZE 5<br />
<br />
struct buff_comp {<br />
int buffer[BUFF_COMP_SIZE];<br />
int in,out;<br />
};<br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
struct buff_comp *p; <br />
<br />
/* initialize random seed: */<br />
srand ( time(NULL) );<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
p = (struct buff_comp *) shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
p->out = p->in = 0;<br />
<br />
if((filho = fork()) == -1)<br />
{<br />
<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
int i;<br />
for(i=0;i<50;i++) {<br />
while (p->in==p->out) {<br />
printf("FILHO: BUFFER VAZIO !!!!!!!\n");<br />
usleep(rand() % 10000 + 1);<br />
}<br />
printf("FILHO: item lido = %d\n", p->buffer[p->out]);<br />
p->out = (p->out+1)%BUFF_COMP_SIZE;<br />
}<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
int i; <br />
<br />
for(i=0;i<50;i++) {<br />
while (((p->in+1)%BUFF_COMP_SIZE) == p->out) {<br />
printf("PAI: BUFFER CHEIO !!!!!!!\n");<br />
usleep(rand() % 10000 + 1);<br />
}<br />
p->buffer[p->in] = rand() % 100 + 1;<br />
printf("PAI: item produzido = %d\n", p->buffer[p->in]);<br />
p->in = (p->in+1)%BUFF_COMP_SIZE;<br />
<br />
}<br />
wait(&filho); <br />
<br />
}<br />
<br />
<br />
if (shmdt(p) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Trocas de mensagens com pipes}}<br />
<br />
= Trocas de mensagens com pipes =<br />
<br />
;Troca de mensagens<br />
Um mecanismo disponibilizado por sistemas UNIX para troca de mensagens entre processos é o PIPE. Pipes são mecanismos de comunicação indireta onde mensagens são trocadas através de ''mailboxes''. Cada ''mailbox'' possui um identificador único, permitindo que processos identifiquem o canal de comunicação entre eles. O fluxo de mensagens em um Pipe é:<br />
*'''unidirecional''': sobre um mesmo pipe, apenas um processo envia mensagens e um processo recebe mensagens;<br />
*'''FIFO''': as mensagens são entregues na ordem de envio;<br />
*'''não-estruturado''': não há estrutura pré-definida para o formato da mensagem.<br />
No UNIX, pipes são inicializados através da '''SystemCall''' ''pipe'', que possui a seguinte sintaxe:<br />
*''int pipe(int pipefd[2])'': ''pipe'' inicializa um novo pipe no sistema e retorna, no array pipefd, os descritores identificando cada uma das pontas do pipe. A primeira posição do array, i.e. pipefd[0], recebe o descritor que pode ser aberto apenas para leitura, enquanto a segunda posição do array, i.e. pipefd[1], recebe o descritor que pode ser aberto apenas para escrita. A função retorna zero no caso de sucesso, ou -1 se ocorrer erro.<br />
As primitivas send/receive para uso de um pipe no UNIX são implementadas por '''SystemCalls''' read/write, conforme segue:<br />
*''ssize_t read(int fd, void *buf, size_t count)'': “puxa” dados do pipe identificado pelo descritor fd. Os dados recebidos são os apontados pelo ponteiro buf, sendo count a quantidade máxima de bytes a serem recebidos. A função retorna o número de bytes recebidos.<br />
*''ssize_t write(int fd, const void *buf, size_t count)'': “empurra” dados no pipe identificado pelo descritor fd. Os dados transmitidos são os apontados pelo ponteiro buf, sendo count a quantidade de bytes a serem transmitidos. A função retorna o número de bytes transmitidos.<br />
<br />
*Exemplo 1: Transmitindo e recebendo pelo próprio processo<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main()<br />
{<br />
int fd[2];<br />
char *ptr = "Alo eu mesmo";<br />
char *ptr_alvo;<br />
int tamanho_dados, ret;<br />
<br />
tamanho_dados = strlen(ptr)+1;<br />
<br />
if (pipe(fd)==-1){<br />
printf ("erro criação pipe\n");<br />
exit(-1);<br />
}<br />
printf("Transmitido %d bytes\n", tamanho_dados);<br />
write (fd[1], ptr, tamanho_dados);<br />
<br />
ptr_alvo = malloc(tamanho_dados);<br />
<br />
ret=read(fd[0],ptr_alvo,tamanho_dados);<br />
<br />
printf("ret = %d dados => %s\n", ret, ptr_alvo); <br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
*Exemplo 2: Abaixo há um exemplo de programa criando um pipe e compartilhando os descritores entre dois processos (criados via ''fork()'').<br />
<syntaxhighlight lang=c><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
<br />
char *message = "This is a message!!!" ;<br />
<br />
main()<br />
{<br />
char buf[1024] ;<br />
int fd[2];<br />
pipe(fd); /*create pipe*/<br />
if (fork() != 0) { /* I am the parent */<br />
write(fd[1], message, strlen (message) + 1) ;<br />
}<br />
else { /*Child code */<br />
read(fd[0], buf, 1024) ;<br />
printf("Got this from MaMa!!: %s\n", buf) ;<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
*'''Exercício 1: construa um “pipeline”'''. Crie um programa que conecta 4 processos através de 3 pipes. Utilize ''fork()'' para criar vários processos.<br />
<br />
<syntaxhighlight lang=cpp><br />
<br />
//Solução possível<br />
<br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
pipe(fd);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
<br />
</syntaxhighlight><br />
<br />
*'''Exercício 2: Modifique o exercício anterior para que o processo D, através de um novo pipe, mande uma mensagem diretamente para o pai de todos.<br />
<br />
<!--<br />
<code><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
int fd_retorno[2];<br />
<br />
pipe(fd);<br />
pipe(fd_retorno);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size);<br />
read(fd_retorno[0], buf, size);<br />
printf("PAI:%s\n", buf); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
char *ptr_msg_ret="Ok msg de D para o pai";<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
write(fd_retorno[1],ptr_msg_ret,strlen(ptr_msg_ret)+1);<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
*'''Exercício 3: Consultor de Login de Acesso:'''. Estude o link https://www.geeksforgeeks.org/named-pipe-fifo-example-c-program/ e projete um programa cliente servidor da seguinte forma: (i) O servidor possui uma tabela de usuários (userid). O user_id é de tamanho fixo de 7 caracteres. O servidor espera por consultas para verificar se um usuário está na tabela. Se estiver responde com o caracter 'S' senão com 'N'. (ii) O cliente espera por user_id no teclado e consulta o servidor sobre sua existência na tabela. O cliente imprime na tabela a existência ou não do usuário.<br />
<br />
*'''Exercício 4: cópia de arquivo'''. Projete um programa de cópia de arquivos chamado FileCopy usando pipes comuns. Esse programa receberá dois parâmetros: o primeiro é o nome do arquivo a ser copiado e o segundo é o nome do arquivo copiado. Em seguida, o programa criará um pipe comum e gravará nele o conteúdo do arquivo a ser copiado. O processo filho lerá esse arquivo do pipe e o gravará no arquivo de destino. Por exemplo, se chamarmos o programa como descrito a seguir:<br />
:<syntaxhighlight lang=bash><br />
$ FileCopy entrada.txt copia.txt<br />
</syntaxhighlight><br />
:o arquivo ''entrada.txt'' será gravado no pipe. O processo filho lerá o conteúdo desse arquivo e o gravará no arquivo de destino ''copia.txt''. Escreva o programa usando os pipes da API POSIX no Linux.<br />
<br />
<br />
{{collapse bottom}}<br />
<br />
=Laboratórios Disponíveis= <br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Escalonamento Round Robin e FCFS para Threads"}}<br />
<br />
<br />
== Escalonamento Round-Robin preemptivo ==<br />
<br />
OBS: ver https://www.quora.com/What-exactly-does-typedef-do-in-C<br />
<br />
A fazer: <br />
<br />
*primitiva de término de processo (destrutor do objeto); <br />
*primitiva de yield<br />
*isolar o escalonador em uma função;<br />
*isolar o dispatcher em uma função; <br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
Modificado por Eraldo <br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 5<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
void runA(void) {<br />
for (;;) {<br />
printf("running A\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runB(void) {<br />
for (;;) {<br />
printf("running B\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 1<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
<br />
void scheduler_rr();<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void yield_thread()<br />
{<br />
scheduler_rr();<br />
}<br />
<br />
void delete_thread()<br />
{<br />
delete curr_thread;<br />
curr_thread=NULL;<br />
scheduler_rr();<br />
}<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
struct delta{<br />
long alfa;<br />
char epson[1000];<br />
long beta;<br />
} shar;<br />
<br />
int turn;<br />
int flag[2];<br />
<br />
#define TRUE 1<br />
#define FALSE 0<br />
<br />
void ent_rc(int p, int vt)<br />
{<br />
flag[p]=TRUE;<br />
turn = vt;<br />
if(p) p=0; else p=1;<br />
while (flag[p] && turn == vt);<br />
//printf("Thread %d: esperando para acessar a região crítica\n", p);<br />
}<br />
<br />
void sai_rc(int p)<br />
{<br />
flag[p]=FALSE;<br />
}<br />
<br />
void runA(void) {<br />
struct delta x = {0, 100};<br />
<br />
for (;;) {<br />
x.alfa=0;x.beta=0;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0);<br />
x.alfa=100;x.beta=100;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0); <br />
}<br />
}<br />
<br />
void runB(void) {<br />
<br />
for (;;) {<br />
ent_rc(1,0);<br />
printf("shar alfa = %ld shar beta = %ld \n",shar.alfa, shar.beta); // regiao crítica<br />
sai_rc(1);<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runC(void) {<br />
int i;<br />
for (i=0;i<10;i++) {<br />
printf("Thread C - parte 1\n");<br />
yield_thread();<br />
printf("Thread C - parte 2\n");<br />
yield_thread();<br />
}<br />
delete_thread();<br />
}<br />
<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
add_thread(runC);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Um escalonador semi-automático"}}<br />
<br />
== Ainda Threads - Um escalonador semi-automático usando sinais ==<br />
<br />
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.<br />
<br />
===Exemplo 1:===<br />
<br />
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. <br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
<br />
void sig_handler(int signo)<br />
{<br />
int x;<br />
printf("Turma de SOP: recebido SIGUSR1\n");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
// Loop eterno dormindo 1s<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Fazer no terminal:<br />
ps aux<br />
anotar o pid do processo e enviar o sinal:<br />
kill -USR1 pid<br />
<br />
===Exemplo 2:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// loop eterno que nunca é executado<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Enviar o sinal USR1 para ver o efeito. <br />
<br />
===Exemplo 3:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void prepara_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void prepara_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
prepara_contexto_ping();<br />
prepara_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// A long long wait so that we can easily issue a signal to this process<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
Exercício: Tente analisar as pilhas dos threads e verificar sob qual pilha o handler se executa.<br />
<br />
===Exercício 4:===<br />
<br />
Neste ponto associamos um timer ao handler com o apoio do sinal ALRM. Agora os threads são escalonados automaticamente.<br />
<br />
<code><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void preparar_contexto_ping(ucontext_t *pContext, char *p)<br />
{<br />
char *stack;<br />
<br />
getcontext(pContext);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
(*pContext).uc_stack.ss_sp = stack ;<br />
(*pContext).uc_stack.ss_size = STACKSIZE;<br />
(*pContext).uc_stack.ss_flags = 0;<br />
(*pContext).uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(pContext, (void*)(*f_ping), 1, p);<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping(&cPing, "ping");<br />
preparar_contexto_ping(&cPong, "pong");<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Um Exemplo de Uso "API Padrão POSIX"}}<br />
<br />
== Um Exemplo de Uso "API Padrão POSIX" ==<br />
<br />
;Referências<br />
* Referência http://man7.org/linux/man-pages/man2/mmap.2.html<br />
<br />
<br />
Crie uma função soma que receba 2 ponteiros referenciando posições na memória, criadas utilizando nmap(), de maneira que estas posições armazenem números inteiros. A função soma deverá retornar a soma dos números apontados em regiões da memória sem a utilização de nenhuma rotina da biblioteca do C, que não sejam definidas por APIs posix, para criação destas <br />
regiões na memória (malloc, alloc, calloc). Após retornar o resultado da soma os devidos ponteiros deverão ser extintos da memória.<br />
<br />
<br />
*'''Experimento 1:''' Aumente o tamanho da memória alocada até quando for possível.<br />
<br />
Qual o tamanho limite da memória que você conseguiu alocar?<br />
<br />
*'''Experimento 2:''' Mude o escopo para PROT_NONE, após executar e depurar o código explique o que aconteceu.<br />
<br />
Em sua opinião NMAP trata-se de uma syscall ou de uma API? Afinal API e syscall são a mesma coisa? Explique.<br />
<br />
<syntaxhighlight lang=cpp><br />
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);<br />
int munmap(void *addr, size_t length);<br />
<br />
addr = Valor do início do mapeamento.<br />
length = valor do tamanho da região a ser alocada.<br />
prot = especificações de proteção da região alocada (consultar http://man7.org/linux/man-pages/man2/mmap.2.html).<br />
flags = especificação do escopo e do tipo da região criada (exemplo publica ou privada, se é anônima ou não). <br />
</syntaxhighlight><br />
<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
void* meu_malloc(size_t tamanho) {<br />
void* addr = mmap(0, // addr<br />
tamanho, // len<br />
PROT_READ | PROT_WRITE, // prot<br />
MAP_ANON | MAP_PRIVATE, // flags<br />
-1, // filedes<br />
0); // off<br />
*(size_t*)addr = tamanho;<br />
return addr;<br />
}<br />
<br />
int meu_free(void* addr) {<br />
return munmap(addr - sizeof(size_t), (size_t) addr);<br />
}<br />
<br />
<br />
int soma(int *N1, int *N2){<br />
<br />
return (*N1+*N2);<br />
<br />
}<br />
<br />
<br />
int main(int argc, char* argv[]) {<br />
<br />
int* numero1 = meu_malloc(sizeof(int));<br />
int* numero2 = meu_malloc(sizeof(int)); <br />
<br />
<br />
*numero1 = 10;<br />
*numero2 = 20; <br />
<br />
int resultado = soma(numero1, numero2);<br />
<br />
printf("\n\n O resultado da soma é %d \n\n",resultado); <br />
<br />
meu_free(numero1);<br />
meu_free(numero2);<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Processos no Linux}}<br />
<br />
== Processos no Linux - Modificado por Eraldo ==<br />
<br />
<blockquote style="background: lime; border: 1px solid black; padding: 1em;"><br />
Processos no Linux<br />
</blockquote><br />
<br />
*Exercícios propostos pelo Prof.Arliones e Modificados por Eraldo<br />
<br />
<br />
[[imagem:DesenhoForkExec.png|border|650px]]<br />
<br />
<br />
;Syscall FORK<br />
<br />
* Em um terminal, execute "man fork"<br />
** 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'''.<br />
** O '''código''' dos dois processos (pai e filho) são '''idênticos''';<br />
** Os '''dados''' dos dois processos (pai e filho) são '''idênticos NO MOMENTO DA CRIAÇÃO''';<br />
** Execução do processo filho inicia na próxima instrução do programa (no retorno da chamada FORK);<br />
** Não é possível saber qual dos processos (pai ou filho) retormará a execução primeiro - isto fica a cargo do excalonador do SO;<br />
** Valores de retorno da chamada FORK:<br />
*** (-1): erro na criação do processo (ex.: memória insuficiente);<br />
*** (0): em caso de sucesso, este é o valor de retorno recebido pelo processo filho;<br />
*** (>0): em caso de sucesso, este é o valor de retorno recebido pelo processo pai;<br />
<br />
;Syscall JOIN<br />
<br />
* A syscall JOIN é implementada no POSIX pela função '''wait()'''. Execute "man wait".<br />
** Além da função '''wait()''', há também '''waitpid()''' e '''waitid()''';<br />
** 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);<br />
** A chamada wait também libera os recursos do processo filho que termina;<br />
** '''wait()''': esta função suspende a execução do processo chamador até que UM DOS SEUS FILHOS finalize;<br />
** '''waitpid()''': suspende a execução do processo chamador até que UM FILHO ESPECÍFICO finalize;<br />
<br />
;Syscall EXEC<br />
<br />
* A syscall EXEC é implementada no POSIX pela família de funções '''exec()'''. Execute "man exec".<br />
** As principais funções da família são '''execl()''', '''execlp()''' e '''execvp()''';<br />
** 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;<br />
** 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;<br />
<br />
<br />
;Exemplos POSIX utilizando fork/wait/exec<br />
<br />
*Exemplo 1: fork/wait básico<br />
<syntaxhighlight lang=c><br />
// ex1: fork/wait básico<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
printf("processo filho\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
printf("processo pai\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
arliones@socrates:~/tmp$ gcc ex1.c -o ex1 <br />
arliones@socrates:~/tmp$ ./ex1 <br />
processo filho pid: 27858 pid pai: 27857<br />
processo pai pid: 27857 pid pai: 5337<br />
arliones@socrates:~/tmp$ <br />
</syntaxhighlight><br />
<br />
* Exemplo 2: processos pai e filho compartilham código, mas não dados.<br />
<syntaxhighlight lang=c><br />
// ex2: fork/wait "compartilhando" dados<br />
// ex2: fork/wait "compartilhando" dados<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status, k=0;<br />
printf("processo %d\t antes do fork\n", getpid());<br />
pid = fork();<br />
printf("processo %d\t depois do fork\n", getpid());<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
k += 1000;<br />
printf("processo filho\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status); // espera o filho terminar<br />
k += 10;<br />
printf("processo pai\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
k += 1000;<br />
printf("FIM processo %d\t K: %d\n", getpid(), k); <br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
processo 17056 antes do fork<br />
processo 17056 depois do fork<br />
processo 17057 depois do fork<br />
processo filho pid: 17057 K: 1000 endereço K: 0x7ffd8923e318<br />
processo pai pid: 17056 K: 10 endereço K: 0x7ffd8923e318<br />
</syntaxhighlight><br />
<br />
* Modificação no código: comentar linhas 23 e 30<br />
<br />
<syntaxhighlight lang=bash><br />
<br />
</syntaxhighlight><br />
<br />
* Analise os resultados e busque entender a diferença.<br />
*Perguntas e desafios.:<br />
#Analisando os valores impressos de k pode-se dizer que os dados são compartilhados entre os dois processos?<br />
#O endereço de k impresso é o mesmo nos dois processos. ISto não contradiz a afirmação anterior?<br />
#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.<br />
<br />
<br />
;Exercício fork/wait<br />
<br />
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.<br />
<br />
*Use o comando pstree para verificar a árvore de processos criada.<br />
<br />
{{collapse top|Solução}}<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
<!--<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
--><br />
<br />
;DESAFIO: fork/wait<br />
<br />
Reimplementar o exercício anterior de criação de uma árvore de 3 processos, generalizando a criação de N processos onde N é repassado na linha de comando do programa. SUGESTÃO: usar um comando for, mas lembrar que se existe um fork dentro do for, então cada filho gerado dará continuidade a execução do for. É necessário que o processo faça um exit ou retorne neste momento.<br />
<br />
;DESAFIO: Exercício status/wait<br />
<br />
O ''status'' passado como parâmetro à função ''wait(&status)'' é, na verdade, o mecanismo de retorno de resultado do ''wait/waitpid''. Ao retornar, esta variável contém informações sobre o resultado da execução do processo filho. Por exemplo, se um processo terminou normalmente (i.e., chamou ''exit''), o comando ''WIFEXITED(status)'' retorna ''true''. Este comando retorna ''false'' se o processo foi abortado (e.g., ''segmentation fault'') ou morto (e.g., ''kill''). Investigue no manual do wait no Linux (''man wait'') o funcionamento do comando WEXITSTATUS(status). <br />
Imagine um problema de busca de dados armazenados na forma de uma matriz de inteiros 4x30. Você está interessado em saber quantas ocorrências de um determinado número existe em cada linha da matriz. Note que que são tarefas que podem ser paralelizadas e usufruir de um sistema capaz de executá-las em paralelo. Faça uma implementação paralelizando 4 processos filhos a partir de um pai, onde cada processo é responsável por uma busca. A quantidade de ocorrências do número buscado é retornada e capturada através de WEXITSTATUS.<br />
<br />
;Syscall EXEC<br />
<br />
*Exemplo exec()<br />
<br />
<syntaxhighlight lang=c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
execl("/bin/ls","ls","-l", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 1: Modificar o código para mostrar que o exec() não retorna (colocar um printf após o exec).<br />
<br />
*Exercício 2: Criar um exemplo (dois programas ) para demonstrar que o exec não cria novo processo. <br />
**Crie um primeiro programa (prog1) que imprime o seu pid e depois faz um exec do segundo programa.<br />
**Crie o segundo programa que simplesmente imprime o pid.<br />
<br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU ANTES DO EXEC: Meu pid é %d\n", getpid());<br />
execl("./prog2","prog2", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU DEPOIS DO EXEC:Meu pid é %d\n", getpid());<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 3: Criar um exemplo usando fork/exec mostrando que um processo pai cria um filho e espera por sua execução. O filho executa o comando "ps aux". Ambos devem mostrar seus pids.<br />
<br />
{{collapse bottom}} <br />
{{collapse top| bg=lightyellow | expandir=true | Threads de aplicação}}<br />
<br />
== Threads de aplicação ==<br />
<br />
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:<br />
*'''getcontext(&a)''': salva o contexto na variável '''a''';<br />
*'''setcontext(&a)''': restaura um contexto salvo anteriormente na variável '''a''';<br />
*'''swapcontext(&a,&b)''': salva o contexto atual na variável '''a''' e restaura o contexto salvo anteriormente na variável '''b''';<br />
*'''makecontext(&a, ...)''': ajusta parâmetros internos do contexto salvo em '''a''';<br />
*'''ucontext_t''': as variáveis '''a''' e '''b''' são do tipo '''ucontext_t'''. Este tipo armazena um contexto.<br />
<br />
Busque mais informações sobre estas funções utilizando o programa manpage do Linux (ex.: man getcontext).<br />
<br />
Estude o código no arquivo pingpong.c abaixo e explique seu funcionamento.<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
*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.<br />
*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.<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain, cFnew;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_new(void * arg1, void * arg2,void * arg3,void * arg4) <br />
{<br />
printf ("%s: Primeira string %s %s %s\n",(char*) arg1,(char*) arg2,(char*) arg3, (char*) arg4);<br />
swapcontext(&cFnew, &cMain); <br />
}<br />
<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
<br />
getcontext(&cFnew);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cFnew.uc_stack.ss_sp = stack ;<br />
cFnew.uc_stack.ss_size = STACKSIZE;<br />
cFnew.uc_stack.ss_flags = 0;<br />
cFnew.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cFnew, (void*)(*f_new), 4, "\tF_new", "\tAlo", "\tMundo","\tReal");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
swapcontext(&cMain, &cFnew);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
--><br />
Exercício 3: O que acontece se um dos threads é colocado para dormir? Todos os demais threads param a sua execução.<br />
<br />
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/<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Trocas de mensagens com pipes}}<br />
<br />
== Trocas de mensagens com pipes ==<br />
<br />
;Troca de mensagens<br />
Um mecanismo disponibilizado por sistemas UNIX para troca de mensagens entre processos é o PIPE. Pipes são mecanismos de comunicação indireta onde mensagens são trocadas através de ''mailboxes''. Cada ''mailbox'' possui um identificador único, permitindo que processos identifiquem o canal de comunicação entre eles. O fluxo de mensagens em um Pipe é:<br />
*'''unidirecional''': sobre um mesmo pipe, apenas um processo envia mensagens e um processo recebe mensagens;<br />
*'''FIFO''': as mensagens são entregues na ordem de envio;<br />
*'''não-estruturado''': não há estrutura pré-definida para o formato da mensagem.<br />
No UNIX, pipes são inicializados através da '''SystemCall''' ''pipe'', que possui a seguinte sintaxe:<br />
*''int pipe(int pipefd[2])'': ''pipe'' inicializa um novo pipe no sistema e retorna, no array pipefd, os descritores identificando cada uma das pontas do pipe. A primeira posição do array, i.e. pipefd[0], recebe o descritor que pode ser aberto apenas para leitura, enquanto a segunda posição do array, i.e. pipefd[1], recebe o descritor que pode ser aberto apenas para escrita. A função retorna zero no caso de sucesso, ou -1 se ocorrer erro.<br />
As primitivas send/receive para uso de um pipe no UNIX são implementadas por '''SystemCalls''' read/write, conforme segue:<br />
*''ssize_t read(int fd, void *buf, size_t count)'': “puxa” dados do pipe identificado pelo descritor fd. Os dados recebidos são os apontados pelo ponteiro buf, sendo count a quantidade máxima de bytes a serem recebidos. A função retorna o número de bytes recebidos.<br />
*''ssize_t write(int fd, const void *buf, size_t count)'': “empurra” dados no pipe identificado pelo descritor fd. Os dados transmitidos são os apontados pelo ponteiro buf, sendo count a quantidade de bytes a serem transmitidos. A função retorna o número de bytes transmitidos.<br />
<br />
*Exemplo 1: Transmitindo e recebendo pelo próprio processo<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main()<br />
{<br />
int fd[2];<br />
char *ptr = "Alo eu mesmo";<br />
char *ptr_alvo;<br />
int tamanho_dados, ret;<br />
<br />
tamanho_dados = strlen(ptr)+1;<br />
<br />
if (pipe(fd)==-1){<br />
printf ("erro criação pipe\n");<br />
exit(-1);<br />
}<br />
printf("Transmitido %d bytes\n", tamanho_dados);<br />
write (fd[1], ptr, tamanho_dados);<br />
<br />
ptr_alvo = malloc(tamanho_dados);<br />
<br />
ret=read(fd[0],ptr_alvo,tamanho_dados);<br />
<br />
printf("ret = %d dados => %s\n", ret, ptr_alvo); <br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
*Exemplo 2: Abaixo há um exemplo de programa criando um pipe e compartilhando os descritores entre dois processos (criados via ''fork()'').<br />
<syntaxhighlight lang=c><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
<br />
char *message = "This is a message!!!" ;<br />
<br />
main()<br />
{<br />
char buf[1024] ;<br />
int fd[2];<br />
pipe(fd); /*create pipe*/<br />
if (fork() != 0) { /* I am the parent */<br />
write(fd[1], message, strlen (message) + 1) ;<br />
}<br />
else { /*Child code */<br />
read(fd[0], buf, 1024) ;<br />
printf("Got this from MaMa!!: %s\n", buf) ;<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
*'''Exercício 1: construa um “pipeline”'''. Crie um programa que conecta 4 processos através de 3 pipes. Utilize ''fork()'' para criar vários processos.<br />
<br />
<syntaxhighlight lang=cpp><br />
<br />
//Solução possível<br />
<br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
pipe(fd);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
<br />
</syntaxhighlight><br />
<br />
*'''Exercício 3: Modifique o exercício anterior para que o processo D, através de um novo pipe, mande uma mensagem diretamente para o pai de todos.<br />
<br />
<!--<br />
<code><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
int fd_retorno[2];<br />
<br />
pipe(fd);<br />
pipe(fd_retorno);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size);<br />
read(fd_retorno[0], buf, size);<br />
printf("PAI:%s\n", buf); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
char *ptr_msg_ret="Ok msg de D para o pai";<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
write(fd_retorno[1],ptr_msg_ret,strlen(ptr_msg_ret)+1);<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
*'''Exercício 3: Consultor de Login de Acesso:'''. Estude o link https://www.geeksforgeeks.org/named-pipe-fifo-example-c-program/ e projete um programa cliente servidor da seguinte forma: (i) O servidor possui uma tabela de usuários (userid). O user_id é de tamanho fixo de 7 caracteres. O servidor espera por consultas para verificar se um usuário está na tabela. Se estiver responde com o caracter 'S' senão com 'N'. (ii) O cliente espera por user_id no teclado e consulta o servidor sobre sua existência na tabela. O cliente imprime na tabela a existência ou não do usuário.<br />
<br />
*'''Exercício 4: cópia de arquivo'''. Projete um programa de cópia de arquivos chamado FileCopy usando pipes comuns. Esse programa receberá dois parâmetros: o primeiro é o nome do arquivo a ser copiado e o segundo é o nome do arquivo copiado. Em seguida, o programa criará um pipe comum e gravará nele o conteúdo do arquivo a ser copiado. O processo filho lerá esse arquivo do pipe e o gravará no arquivo de destino. Por exemplo, se chamarmos o programa como descrito a seguir:<br />
:<syntaxhighlight lang=bash><br />
$ FileCopy entrada.txt copia.txt<br />
</syntaxhighlight><br />
:o arquivo ''entrada.txt'' será gravado no pipe. O processo filho lerá o conteúdo desse arquivo e o gravará no arquivo de destino ''copia.txt''. Escreva o programa usando os pipes da API POSIX no Linux.<br />
<br />
<br />
{{collapse bottom}}<br />
<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Exercícios sobre Memória Compartilhada}}<br />
<br />
==SHARED MEMORY: Produtor (pai) - Consumidor (filho) - ==<br />
<br />
<!-- Parou aki 20/08<br />
<br />
<br />
*'''Experimento 2:''' Complete o código a seguir para que os processos pai e filho possam compartilhar um segmento de memória. O filho escreve no segmento e o pai imprime na tela o conteúdo da mensagem.<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
char *ptr_msg = "alo pai, tudo bem?"; <br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
//completar aqui<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
<!--<br />
<code><br />
<br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/types.h><br />
#include <string.h><br />
#include <stdlib.h><br />
<br />
int main(void)<br />
{<br />
int fd[2], pipe_ret, filho;<br />
char string[] = "Hello, pipe!\n";<br />
char buffer[20];<br />
<br />
pipe(fd);<br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
/*Mandar string para a extremidade do pipe*/<br />
write(fd[1], string, (strlen(string)+1));<br />
exit(0);<br />
}<br />
else<br />
{<br />
<br />
/* Read in a string from the pipe */<br />
pipe_ret = read(fd[0], buffer, (20*sizeof(char)));<br />
printf("Recebi este texto %s", buffer);<br />
}<br />
<br />
return(0);<br />
}<br />
<br />
<br />
<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
key = ftok("teste_sh.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644 | IPC_CREAT));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
<br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
strncpy(segmento, "mensagem compartilhada", SHM_SIZE); <br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
--><br />
<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Memória Compartilhada}}<br />
*'''Experimento Shared Memory:''' Complete o código a seguir para que os processos pai e filho possam compartilhar um segmento de memória. O filho escreve no segmento e o pai imprime na tela o conteúdo da mensagem.<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
char *ptr_msg = "alo pai, tudo bem?"; <br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
//completar aqui strcpy(segmento, ptr_msg); //aqui deveria testar a cpacidade da área...<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exemplo com ftok:<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
key = ftok("./teste.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644 | IPC_CREAT));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
<br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
strncpy(segmento, "mensagem compartilhada", SHM_SIZE); <br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exemplo com ftok entre processos sem parentesco:<br />
<br />
Criar um arquivo teste.txt e em um terminal executar:<br />
<br />
<syntaxhighlight lang=c><br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
int modo,filho;<br />
<br />
struct minha_struct {<br />
char flag;<br />
int numero;<br />
} *ptr;<br />
<br />
<br />
key = ftok("./teste.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644 | IPC_CREAT));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
ptr = (struct minha_struct *) shmat(shmid, (void *)0, 0);<br />
if ((char *)ptr == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
ptr->flag =0;<br />
ptr->numero = 0;<br />
while (ptr->flag==0) { <br />
printf("%d\n", ptr->numero);<br />
sleep(1);<br />
} <br />
<br />
if (shmdt(ptr) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Em outro terminal executar:<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
struct minha_struct {<br />
char flag;<br />
int numero;<br />
} *ptr;<br />
<br />
<br />
key = ftok("./teste.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
ptr = (struct minha_struct *) shmat(shmid, (void *)0, 0);<br />
if ((char *)ptr == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
<br />
<br />
while (ptr->numero++<10)<br />
sleep(1);<br />
<br />
ptr->flag = 1;<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Exercício Desafio: Implementar o problema do buffer circular usando memória compartilhada.<br />
<br />
{{collapse bottom}}<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Exercício (Algoritmo de Peterson)}}<br />
<br />
== Exercício (Algoritmo de Peterson) ==<br />
<br />
<br />
'''Exercício 1''': Sincronize o código a seguir, de maneira que o processo pai imprima apenas os números impares e o processo filho os números pares. Para isso utilize o algoritmo de '''Peterson''' visto em aula. '''Utilize memória compartilhada''' para comunicação entre os processos.<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
main()<br />
{ <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int i; <br />
<br />
for(i = 0;i < 10;i=i+2){ <br />
printf("Processo pai %d \n", i); <br />
<br />
} <br />
<br />
<br />
}<br />
<br />
else { /*Child code */<br />
int i; <br />
for(i = 1;i < 10;i=i+2){ <br />
printf("Processo filho %d \n", i); <br />
<br />
}<br />
<br />
<br />
}<br />
<br />
exit(0);<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
'''Exercício 2''': Considerando o exercício anterior faça a mesma sincronização, no entanto desta vez utilize a modelagem em software do TSL. <br />
* Em sua experiência, depois de testar diversas vezes as execuções de suas soluções baseadas no algoritmo de '''Peterson''' e '''Tsl''', qual sua opinião sobre as abordagens?<br />
Explique seu raciocínio. <br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Exercício (Semáforos)}}<br />
== Exercício (Semáforos) ==<br />
<br />
<br />
'''Exercício 1''': Sincronize o código a seguir, de maneira que o processo pai imprima apenas os números impares e o processo filho os números pares. Para isso utilize '''Semáforos''' de acordo com a implementação em '''semaforo.h'''. '''Utilize memória compartilhada''' para comunicação entre os processos.<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
main()<br />
{ <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int i; <br />
<br />
for(i = 0;i < 10;i=i+2){ <br />
printf("Processo pai %d \n", i); <br />
sleep(1);<br />
<br />
} <br />
<br />
<br />
}<br />
<br />
else { /*Child code */<br />
int i; <br />
for(i = 1;i < 10;i=i+2){ <br />
printf("Processo filho %d \n", i); <br />
<br />
}<br />
<br />
<br />
}<br />
<br />
exit(0);<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
SEMAFORO.H<br />
<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <sys/sem.h><br />
<br />
<br />
int criar_semaforo(int val, int chave) <br />
{<br />
int semid ;<br />
<br />
union semun {<br />
int val;<br />
struct semid_ds *buf ;<br />
ushort array[1];<br />
} arg_ctl ;<br />
<br />
key_t ft = ftok("/tmp", chave);<br />
<br />
semid = semget(ft,1,IPC_CREAT|IPC_EXCL|0666);<br />
if (semid == -1) {<br />
semid = semget(ft,1,0666); <br />
if (semid == -1) {<br />
perror("Erro semget()");<br />
exit(1) ;<br />
}<br />
}<br />
<br />
arg_ctl.val = val; //valor de início<br />
if (semctl(semid,0,SETVAL,arg_ctl) == -1) {<br />
perror("Erro inicializacao semaforo");<br />
exit(1);<br />
}<br />
return(semid) ;<br />
}<br />
<br />
void P(int semid){<br />
<br />
struct sembuf *sops = malloc(10*sizeof(int));<br />
sops->sem_num = 0;<br />
sops->sem_op = -1;<br />
sops->sem_flg = 0;<br />
semop(semid, sops, 1); <br />
free(sops);<br />
<br />
}<br />
<br />
<br />
void V(int semid){<br />
<br />
struct sembuf *sops = malloc(10*sizeof(int));<br />
sops->sem_num = 0;<br />
sops->sem_op = 1;<br />
sops->sem_flg = 0; <br />
semop(semid, sops, 1); <br />
free(sops);<br />
<br />
} <br />
<br />
<br />
<br />
void sem_delete(int semid) <br />
{<br />
<br />
if (semctl(semid,0,IPC_RMID,0) == -1)<br />
perror("Erro na destruicao do semaforo");<br />
}<br />
<br />
<br />
<br />
<br />
</syntaxhighlight><br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Programação concorrente}}<br />
<br />
== Programação concorrente ==<br />
<br />
;POSIX Threads<br />
A 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):<br />
*''pthread_create'': cria uma thread;<br />
*''pthread_kill'': força a terminação de uma thread;<br />
*''pthread_join'': sincroniza o final de uma thread (qual a diferença/semelhança com o ''wait'' que usamos para processos?);<br />
*''pthread_exit'': finaliza uma thread.<br />
Para utilizar estas funções é necessário linkar o programa à libpthread (''-lpthread''). <br />
<br />
<br />
;POSIX pthread mutex<br />
<br />
A biblioteca pthread implementa um tipo ''pthread_mutex_t'', que garante a exclusão mútua entre threads. Estes mutex são manipulados através das funções (acesse as man-pages das chamadas para maiores detalhes):<br />
*''pthread_mutex_lock'': acessa um mutex.<br />
*''pthread_mutex_trylock'': tenta acessar um mutex (retorna valor indicando sucesso ou falha no lock).<br />
*''pthread_mutex_unlock'': libera um mutex.<br />
<br />
<br />
<br />
<br />
;POSIX Semaphores<br />
<br />
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):<br />
*''sem_init'': inicializa um semáforo;<br />
*''sem_destroy'': destroy um semáforo;<br />
*''sem_wait'': implementa a operação ''p'';<br />
*''sem_post'': implementa a operação ''v''.<br />
Para utilizar estas funções é necessário linkar o programa à librt ou à libpthread (''-lrt'' ou ''-lpthread'').<br />
<br />
;Exercício 1<br />
<br />
O programa abaixo cria 5 threads, e cada uma destas threads atualiza uma variável global (memória compartilhada).<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include <pthread.h><br />
#include <signal.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
pthread_mutex_t mut;<br />
<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
}<br />
</syntaxhighlight><br />
<br />
# Compile este programa. <br />
# Execute este programa várias vezes. Ele funciona? Será que ele gera as saídas esperadas?<br />
# Identifique as '''seções críticas''' do programa.<br />
# Corrija o programa utilizando '''mutex'''. <br />
# Analise a função ''AtualizaSaldo()'' com a sua solução. Lembre-se que o uso do mutex implica em apenas uma thread acessar a seção crítica por vez, enquanto outras threads ficam bloqueadas, esperando. Disso vem que, quanto menor o trecho de código entre um ''lock'' e um ''unlock'', menos tempo uma thread necessita ficar esperando.<br />
# Modifique o programa para usar um semáforo binário ao invés de um mutex em sua solução.<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <cstring><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
<br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
sem_t sem;<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
int value;<br />
sem_wait(&sem);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
sem_getvalue(&sem, &value);<br />
printf("valor sem = %d\n", value);<br />
sem_post(&sem);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
sem_init(&sem,0,1);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
sem_destroy(&sem);<br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
<br />
;Exercício 2<br />
Refaça o exercício 3 usando processos criados com fork e exec. O semáforo deve ser criado em uma região de memória compartilhada.<br />
<br />
;Exercício 3<br />
Implemente com pthreads e semáforos/mutex a solução do produtor/comsumidor.<br />
<br />
;Exercício 4<br />
<br />
O programa abaixo manipula uma matriz de tamanho MxN (veja os defines para o tamanho da matriz). A função ''SumValues'' soma todos os valores em uma linha da matriz. A linha a ser somada é identificada pela variável ''i''. Modifique o programa principal (''main'') nos locais indicados para:<br />
# Criar N threads, uma para somar os valores de cada linha.<br />
# Receber o resultado do somatório de cada linha e gerar o somatório total da matriz.<br />
# Analise o programa: há problemas de sincronização que precisam ser resolvidos? Se sim, resolva-os.<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include "thread.h"<br />
<br />
/* number of matrix columns and rows */<br />
#define M 5<br />
#define N 10<br />
<br />
using namespace std;<br />
<br />
int matrix[N][M];<br />
Thread *threads[N];<br />
<br />
<br />
/* thread function; it sums the values of the matrix in the row */<br />
int SumValues(int i)<br />
{<br />
int n = i; /* number of row */<br />
int total = 0; /* the total of the values in the row */<br />
int j;<br />
for (j = 0; j < M; j++) /* sum values in the "n" row */<br />
total += matrix[n][j];<br />
cout << "The total in row" << n << " is " << total << "." << endl;<br />
/* terminate a thread and return a total in the row */<br />
exit(total);<br />
}<br />
<br />
int main(int argc, char *argv[])<br />
{<br />
int i, j;<br />
int total = 0; /* the total of the values in the matrix */<br />
<br />
/* initialize the matrix */<br />
for (i = 0; i < N; i++)<br />
for (j = 0; j < M; j++)<br />
matrix[i][j] = i * M + j;<br />
<br />
/* create threads */<br />
/* COLOQUE SEU CÓDIGO PARA CRIAR AS THREADS AQUI! */<br />
<br />
/* wait for terminate a threads */<br />
/* COLOQUE SEU CÓDIGO PARA PEGAR O SOMATÓRIO DE LINHAS E TOTALIZAR A SOMA DA MATRIZ AQUI! */<br />
<br />
cout << "The total values in the matrix is " << total << endl;<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Lista de exercícios "Revisão para Prova" }}<br />
<br />
== Lista de exercícios/Revisão para Prova ==<br />
<br />
A lista de exercícios referente a primeira prova (Parte introdutória + Processos) segue neste LINK [http://docente.ifsc.edu.br/andre.damato/sop2018/lista_rev1.pdf | Lista de exercícios]. <br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Primeiro trabalho}}<br />
== JOGO DA VIDA DE CONWAY e JANTAR DOS FILÓSOFOS==<br />
<br />
;Referências<br />
<br />
* [https://www.open-mpi.org/doc/current/ MPI]<br />
<br />
* [https://quark.phy.bnl.gov/~creutz/qcdoc/mpi/mpi.h Tipos de dados MPI]<br />
<br />
* [https://pt.wikipedia.org/wiki/Jogo_da_vida Jogo da Vida]<br />
<br />
<br />
<br />
<br />
A partir da implementação sequencial do Game of Life apresentada a seguir, estude o código e transforme esta implementação em uma implementação paralela utilizando o protocolo de passagem de mensagens MPI.<br />
Perceba que a impĺementação mencionada utiliza como parâmetros de entrada um aquivo contendo o estado inicial do jogo, e o número de gerações que o usuário deseja rodar. A evolução do estado inicial <br />
é impressa na tela passo a passo. Sendo assim, a partir disso:<br />
<br />
*'''1: Elabore uma implementação com 2 processos para o jogo da vida utilizando o protocolo MPI, de maneira que um processo execute uma geração i qualquer e o outro execute a geração seguinte i+1''' <br />
<br />
*'''2: (0,7) Os processos deverão se comunicar utilizando as funções do protocolo MPI.''' <br />
<br />
*'''3: (0,3) Relatório simplificado explicando a sua solução. Utilize diagramas para representar a comunicação entre os processos, explicando como a matriz do jogo é transferida entre os processos. ''' <br />
<br />
*'''4: Entregue o Relatório e o código fonte do trabalho em um pacote compactado via e-mail (PRAZO 19/10). <br />
<br />
<br />
<br />
* ''' Compilar o código com MPI '''<br />
<code><br />
mpicc -o nomeApp arquivo.c<br />
</syntaxhighlight><br />
<br />
* ''' Rodar rodar programa utilizando MPI '''<br />
<code><br />
mpirun -np numeroDeProcessos ./nomeApp entrada.txt gerações<br />
</syntaxhighlight><br />
<br />
* (int) -np: Quantidade de processos que você deseja executar <br />
<br />
* entrada.txt: Arquivo de entrada com estado inicial do jogo <br />
<br />
* (int) gerações: número de gerações que você deseja rodar<br />
<br />
* [http://docente.ifsc.edu.br/andre.damato/sop2018/entrada.txt Arquivo de entrada para Testes]<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
<br />
<br />
<br />
/*<br />
<br />
Conway's Game of Life<br />
<br />
Compilar código com MPI<br />
mpicc -o nomeApp arquivo.c<br />
<br />
<br />
Rodar rodar programa utilizando MPI<br />
<br />
mpirun -np numeroDeProcessos ./nomeApp entrada.txt gerações<br />
<br />
(int) -np: Quantidade de processos que você deseja executar <br />
entrada.txt: Arquivo de entrada com estado inicial do jogo <br />
(int) gerações: número de gerações que você deseja rodar<br />
<br />
<br />
*/<br />
<br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h><br />
#include "mpi.h"<br />
<br />
<br />
//Numero de linhas e colunas<br />
#define nLinhas 32<br />
#define nColunas 82 <br />
<br />
char *matriz[nLinhas];<br />
char *entrada[nLinhas];<br />
<br />
<br />
void iniciar() {<br />
<br />
int i;<br />
<br />
//Alocar espaço em memória para as matrizes<br />
for (i = 0; i < nLinhas; i++ ) <br />
matriz[i] = (char *) malloc((nColunas) * sizeof( char )); <br />
<br />
<br />
}<br />
<br />
int adjacente(char **matriz, int i, int j){<br />
<br />
int x,y, initX, initY, limitX, limitY;<br />
int vizinhos = 0;<br />
<br />
if(i == 0)<br />
initX = 0;<br />
else <br />
initX = -1;<br />
<br />
if(i == (nLinhas-1)) <br />
limitX = 1;<br />
else<br />
limitX = 2;<br />
<br />
<br />
if(y == 0)<br />
initY = 0;<br />
else <br />
initY = -1;<br />
<br />
if(y == (nColunas-3)) <br />
limitY = 1;<br />
else<br />
limitY = 2;<br />
<br />
for(x = initX ; x < limitX; x++){<br />
for(y = initY; y < limitY; y++){<br />
if(matriz[i+x][j+y] == '#') <br />
vizinhos++; <br />
} <br />
}<br />
<br />
<br />
if(matriz[i][j] == '#') <br />
return (vizinhos-1);<br />
else <br />
return vizinhos;<br />
<br />
}<br />
<br />
<br />
void calculoGeracao(char **matriz, int ger) {<br />
<br />
int i, j, a;<br />
char novaGeracao[nLinhas][nColunas];<br />
<br />
/* Aplicando as regras do jogo da vida */<br />
for (i=0; i < nLinhas; i++){ <br />
for (j=0; j < nColunas; j++) {<br />
<br />
a = adjacente(matriz, i, j);<br />
<br />
if (a == 2) novaGeracao[i][j] = matriz[i][j];<br />
if (a == 3) novaGeracao[i][j] = '#';<br />
if (a < 2) novaGeracao[i][j] = ' ';<br />
if (a > 3) novaGeracao[i][j] = ' ';<br />
<br />
if (j == 0)<br />
novaGeracao[i][j] = '"';<br />
} <br />
<br />
novaGeracao[i][79] = '"';<br />
novaGeracao[i][80] = '\n';<br />
<br />
<br />
}<br />
<br />
/* Passando o resultado da nova geração para a matriz de entrada */<br />
for (i=0; i < nLinhas; i++){ <br />
for (j=0; j < nColunas; j++) <br />
matriz[i][j] = novaGeracao[i][j];<br />
}<br />
}<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
main(int argc, char *argv[2]){<br />
<br />
/* Para uso com MPI<br />
<br />
<br />
//Variáveis para uso com MPI<br />
int numeroDeProcessos = 0;<br />
int rank = 0;<br />
MPI_Status status; <br />
<br />
//Iniciar MPI---<br />
MPI_Init( &argc, &argv );<br />
<br />
//Atribui a variável numeroDeProcessos o número de processos passado como parâmetro em -np <br />
MPI_Comm_size( MPI_COMM_WORLD, &numeroDeProcessos );<br />
<br />
//Pega o valor do rank (processo)<br />
MPI_Comm_rank( MPI_COMM_WORLD, &rank );<br />
*/<br />
<br />
<br />
FILE *matrizEntrada;<br />
matrizEntrada = fopen(argv[1], "r");<br />
iniciar();<br />
<br />
<br />
if (matrizEntrada == NULL)<br />
printf ("Não posso abrir o arquivo \"%s\"\n", argv[1]);<br />
<br />
<br />
char str[nColunas];<br />
int linha = 0;<br />
<br />
<br />
<br />
//Lendo o estado inicial do jogo a partir do arquivo<br />
while((fgets(str, nColunas, matrizEntrada) != NULL)&&(linha < nLinhas)){<br />
strcat(matriz[linha], str);<br />
linha++;<br />
}<br />
<br />
int i,gens; <br />
<br />
<br />
for(gens = 0; gens < atoi(argv[2]); gens++){ //Gens é o número de gerações especificado no segundo parâmetro <br />
<br />
calculoGeracao(matriz, gens);<br />
printf("%c[2J",27); // Esta linha serve para limpar a tela antes de imprimir o resultado de uma geração <br />
<br />
//Lendo o estado do jogo e imprime na tela <br />
for(i = 0; i < nLinhas; i++)<br />
printf("%s", matriz[i]); <br />
<br />
sleep(1);<br />
<br />
}<br />
<br />
<br />
for(i = 0; i < nLinhas; i++) <br />
free(matriz[i]); <br />
<br />
<br />
<br />
/* Finaliza o MPI */ <br />
//MPI_Finalize();<br />
<br />
exit(0);<br />
} <br />
<br />
<br />
</syntaxhighlight><br />
<br />
<br />
;Jantar dos Filósofos<br />
O problema clássico Jantar dos Filósofos consiste em que n fluxos (n filósofos) disputam n recursos (n talheres). No problema, para conseguir "jantar" (ou executar), cada filósofo precisa pegar dois talheres adjascentes a ele. Cada recurso é compartilhado por dois filósofos.<br />
*[http://www.doc.ic.ac.uk/~jnm/concurrency/classes/Diners/Diners.html Veja esta simulação]<br />
*[http://en.wikipedia.org/wiki/Dining_philosophers_problem Veja esta descrição do problema]<br />
<br />
<br />
* ''' (0,7) programa abaixo implementa um Jantar dos Filósofos utilizando semáforos para sincronização. Contudo, as chamadas para as operações ''v'' e ''p'' foram removidas, conforme comentários no código. Re-insira as operações no código e analise a solução. Esta modificação é suficiente para garantir que não haverá deadlock? Se sim, mostre o porque. Se não, proponha uma solução completa. '''<br />
<br />
<br />
*''' (0,3) Relatório simplificado explicando a sua solução. ''' <br />
<br />
*''' Entregue o Relatório e o código fonte do trabalho em um pacote compactado via e-mail (PRAZO 19/10). <br />
<br />
<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include "thread.h"<br />
#include "semaphore.h"<br />
<br />
using namespace std;<br />
<br />
const int DELAY = 10000000;<br />
const int ITERATIONS = 5;<br />
<br />
Semaphore chopstick[5];<br />
<br />
int philosopher(int n)<br />
{<br />
cout << "Philosopher " << n << " was born!\n";<br />
<br />
int first = (n < 4)? n : 0; // left for phil 0 .. 3, right for phil 4<br />
int second = (n < 4)? n + 1 : 4; // right for phil 0 .. 3, left for phil 4<br />
<br />
// Foram removidos do laço abaixo:<br />
// - uma chamada para chopstick[first].p()<br />
// - uma chamada para chopstick[second].p()<br />
// - uma chamada para chopstick[first].v()<br />
// - uma chamada para chopstick[second].v()<br />
for(int i = 0; i < ITERATIONS; i++) {<br />
cout << "Philosopher " << n << " thinking ...\n";<br />
for(int i = 0; i < DELAY * 10; i++);<br />
<br />
cout << "Philosopher " << n << " eating ...\n";<br />
for(int i = 0; i < DELAY; i++);<br />
}<br />
<br />
return n;<br />
}<br />
<br />
int main()<br />
{<br />
cout << "The Dining-Philosophers Problem\n";<br />
<br />
Thread * phil[5];<br />
for(int i = 0; i < 5; i++)<br />
phil[i] = new Thread(&philosopher, i);<br />
<br />
int status;<br />
for(int i = 0; i < 5; i++) {<br />
phil[i]->join(&status);<br />
if(status == i)<br />
cout << "Philosopher " << i << " went to heaven!\n";<br />
else<br />
cout << "Philosopher " << i << " went to hell!\n";<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Softwares básicos, caso Hello Word! (Trabalho 2) Entrega dia 09/11}}<br />
<br />
== Softwares básicos, caso Hello Word! ==<br />
<br />
O objetivo do experimento de hoje é pesquisar e entender os processos de atribuição de endereços de programas realizados em tempo de compilação pelos softwares básicos como: compilador, linker, e assembler. Sendo assim, neste experimento vamos utilizar os seguintes softwares para criação e análise de código:<br />
<br />
*'''GCC''': compilador para gerar código objeto a partir de um código de programa escrito na linguagem c;<br />
*'''GNU Linker (LD)''': Para vincular os códigos (módulos) objetos do programa;<br />
*[https://linux.die.net/man/1/ld| Linker ] <br />
*'''GNU Assembler''': Para gerar o código executável a partir do código objeto;<br />
*[https://linux.die.net/man/1/as | assembler]<br />
* '''OBJDUMP''': Para mostrar informações do código;<br />
*[https://linux.die.net/man/1/objdump | Objdump ]<br />
<br />
<br />
A seguir segue descrito o programa a ser utilizado no exercício 1:<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
int main()<br />
{<br />
printf("Hello, World!");<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
Trata-se do programa hello word, este programa apenas exibe uma mensagem na tela. No entanto, vamos analisar como são as etapas confecção do executável a partir deste código ''simples''. <br />
<br />
Exercício 1: <br />
* Compile o programa hello word, e o transforme em código objeto utilizando o programa GCC. Para esta tarefa execute o seguinte comando:<br />
<code><br />
gcc -o hello hello.c <br />
</syntaxhighlight><br />
* Agora abra o código objeto utilizando o programa OBJDUMP.<br />
<code><br />
objdump -D hello<br />
</syntaxhighlight><br />
* Identifique quais são as seções de código obtidas a partir do '''hello.c'''.<br />
* Pesquise e entenda o significado das seções de código: .bss, .txt, .data, .init.<br />
* Faça uma análise e identifique o endereço de memória que o programa ''hello world'' vai ser carregado. <br />
* Este código objeto é relocável? Justifique sua resposta.<br />
* Agora gere o código assembly do hello world.<br />
<code><br />
gcc -S hello.c<br />
</syntaxhighlight> <br />
*Agora gere o código executável utilizando o programa '''AS''' e o programa '''LD'''.<br />
<code><br />
as -o hello.o hello.s<br />
</syntaxhighlight><br />
* Como a etapa de linkagem para a construção do código executável está sendo executada sem o auxílio do '''GCC''', necessitamos vincular manualmente as bibliotecas necessárias. Para criar apropriadamente o executável vamos precisar das bibliotecas '''ld-linux-x86-64.so.2''', '''crt1.o''', '''crti.o''', '''crtn.o'''.<br />
* Para descobrir suas respectivas localizações use o comando '''LOCATE'''. Por exemplo:<br />
<code><br />
<br />
locate crti.o <br />
<br />
</syntaxhighlight><br />
<br />
ou <br />
<br />
<code><br />
<br />
find /usr/ -name crti*<br />
<br />
</syntaxhighlight><br />
<br />
* Agora que já sabemos a localização das bibliotecas necessárias vamos vincular essas a nossa aplicação.<br />
<code><br />
ld --dynamic-linker /caminho/ld-linux-x86-64.so.2 /caminho/crt1.o /caminho/crti.o /caminho/crtn.o hello.o -lc -o hello.exe<br />
</syntaxhighlight><br />
<br />
* Agora abra o código objeto utilizando o programa OBJDUMP.<br />
* Faça uma análise e identifique o endereço de memória em que o programa ''hello world'' inicializa suas estruturas na memória.<br />
* Dica!<br />
<code><br />
objdump -D -s -j .init hello.exe<br />
</syntaxhighlight><br />
* Houve diferença entre os endereços do programa executável em relação ao código objeto? Explique.<br />
* Explique as principais diferenças entre o arquivo objeto .o e o executável final. (dica utilize o objdump para fazer essa análise)<br />
{{collapse bottom}}<br />
<ol><br />
<li> Estudar e executar o código em http://cs.lmu.edu/~ray/notes/gasexamples/ <br />
Detalhes das chamadas na arquitetura x86_64 ver em https://lwn.net/Articles/604287/ <br />
<li>Estudar e executar o código usando a função (em conformidade com a API POSIX) write() para o ''hello world'':<br />
<code><br />
#include <unistd.h> <br />
<br />
main()<br />
{<br />
write(1,"Alo Mundo\n",10);<br />
}<br />
</syntaxhighlight><br />
</li><br />
<li> Use o comando strace para verificar todas as chamadas de sistema dos programas acima.<br />
</li><br />
<li><br />
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:<br />
<code><br />
main()<br />
{<br />
meu_hello_world();<br />
}<br />
</syntaxhighlight><br />
</li><br />
Gere o assembly do código em C e discuta a diferença entre uma chamada de função e uma chamada de sistema.<br />
<li><br />
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:<br />
<code><br />
#include <string.h><br />
main()<br />
{<br />
char *p="Tudo bem com vocês?";<br />
meu_hello_world(p, strlen(p));<br />
}<br />
</syntaxhighlight><br />
Solução:<br />
{{collapse top|Solução}}<br />
<code><br />
modificado de http://cs.lmu.edu/~ray/notes/gasexamples/<br />
.global meu_hello_world<br />
<br />
.text<br />
meu_hello_world:<br />
<br />
push %rdi # salva primeiro parâmetro<br />
push %rsi # salva segundo parâmetro<br />
mov $1, %rax # system call 1 é write<br />
mov $1, %rdi # file handle 1 é stdout<br />
mov $message, %rsi # endereço da string<br />
mov $13, %rdx # número de bytes da string<br />
syscall # chamada ao sistema<br />
<br />
pop %rdx # o que havia sido passado em rsi (número de bytes) é colocado em rdx<br />
pop %rsi # o que havia sido colocado em rdi (endereço da string) é colocado em rsi<br />
mov $1, %rax # system call 1 is write<br />
mov $1, %rdi # file handle 1 é stdout<br />
syscall # nova chamada ao sistema<br />
<br />
ret<br />
<br />
message:<br />
.ascii "Hello, World\n"<br />
</syntaxhighlight><br />
</li><br />
</ol><br />
{{collapse bottom}}</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=SOP29005-2019-2&diff=162030SOP29005-2019-22019-10-04T12:04:37Z<p>127.0.0.1: /* Objetivos */</p>
<hr />
<div>=AULA 1 - Dia 30/07/2019=<br />
<br />
===Objetivos/Conteúdos===<br />
<br />
*Apresentação do Plano de Ensino<br />
**Objetivos e Conteúdo Programático da Disciplina (ver SIGAA)<br />
**Forma de Avaliação (ver SIGAA)<br />
<br />
*Introdução a Sistemas Operacionais (Cap1. do Silberschatz)<br />
**O que faz um sistema operacional (1.1)<br />
**Organização e Arquitetura de um Sistema Computacional (1.2 e 1.3)<br />
***Importância da Interrupção e Timers (1.2.1)<br />
***Estrutura de Armazenamento (1.2.2)<br />
***Estrutura de IO (1.2.3)<br />
**Estrutura e Operações de um Sistema Operacional (1.4 e 1.5)<br />
<br />
===Material de Referência===<br />
<br />
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte1.pdf Apresentação sobre histórico visão geral e estruturas básicas de um SO]<br />
* [http://codex.cs.yale.edu/avi/os-book/OSE1/slide-dir/index.html Slides Silberschatz Oitava Edição]<br />
* [http://professor.unisinos.br/barbosa/SO/ch1br.ppt Tradução Slides Silberschatz Cap1]<br />
* [http://professor.unisinos.br/barbosa/SO/ch2br.ppt Tradução Slides Silberschatz Cap2]<br />
* [http://professor.unisinos.br/barbosa/SO/ch3br.ppt Tradução Slides Silberschatz Cap3]<br />
* [http://professor.unisinos.br/barbosa/SO/ch4br.ppt Tradução Slides Silberschatz Cap4]<br />
* [http://wiki.inf.ufpr.br/maziero/doku.php?id=so:livro_de_sistemas_operacionais Livro do Prof.Maziero]<br />
* [http://deptinfo.unice.fr/~rr/l3systres/ Université Nice Sophia Antipolis]<br />
<br />
Arliones:<br />
<br />
*[https://www.dropbox.com/s/dt80g3tml65rpmg/SOP29005-parte6.odp?dl=0]<br />
*[https://www.dropbox.com/s/7lneavq0go9kz2t/SOP29005-parte7.odp?dl=0]<br />
<br />
===Leitura Recomendada===<br />
<br />
*Cap.1 do Silberschatz principalmente:<br />
**1.1 a 1.9<br />
<br />
===Exercícios Práticos de Apoio a Aula===<br />
<br />
Na sequência. com fins motivacionais, são apresentados alguns exercícios ilustrando conceitos de processos, arquivos e permissionamento.<br />
<br />
<ol><br />
<li><br />
Comando para ver todos os processos no linux:<br />
<code><br />
$ ps aux<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Colocar 2 processos se executando no contexto de um terminal e verificar número dos processos e então "destruí-los":<br />
<code><br />
$ yes > /dev/null<br />
$ yes > /dev/null<br />
$ ps <br />
$ kill -9 <pid_yes><br />
$ kill -9 <pid_yes><br />
</syntaxhighlight><br />
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.<br />
</li><br />
<li><br />
Criar um terminal adicional<br />
<code><br />
$ xterm<br />
</syntaxhighlight><br />
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:<br />
<code><br />
$ echo Alo Terminal > /dev/pts/2<br />
$ kill -9 <pid_terminal><br />
</syntaxhighlight><br />
</li><br />
<li><br />
Comunicação entre processos:<br />
<code><br />
$ cat /etc/passwd | grep home | wc -l<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Retirando a permissão de leitura de um arquivo em nível de usuário proprietário:<br />
<code><br />
$ echo Alo Mundo > alfa.txt<br />
$ ls -l alfa.txt<br />
$ cat alfa.txt<br />
$ chmod u-r alfa.txt<br />
$ cat alfa.txt<br />
$ chmod u+r alfa.txt<br />
$ cat alfa.txt <br />
</syntaxhighlight><br />
</li><br />
</ol><br />
<br />
=AULA 2 - Dia 2/08/2019=<br />
<br />
===Objetivos/Conteúdos===<br />
<br />
*Continuação da Aula<br />
*Estruturas do Sistema Operacional (cap.2)<br />
**Serviços do Sistema Operacional (2.1)<br />
**Interfaces com Usuários (2.2)<br />
**Chamadas do Sistema (2.3)<br />
**Tipos de Chamadas de Sistema (2.4) ver Fig.2.8<br />
***Chamadas de Controle de Processos<br />
**Arquiteturas e Estruturas de Sistemas Operacionais (2.7)<br />
**Máquinas Virtuais (2.8)<br />
<br />
===Material de Referência===<br />
<br />
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte1.pdf Apresentação sobre histórico visão geral<br />
* [http://www.fil.univ-lille1.fr/~sedoglav/OS/TP.html ]<br />
<br />
===Leitura Recomendada===<br />
<br />
*Cap.2 do Silberschatz principalmente:<br />
**2.1 a 2.8<br />
<br />
===Exercícios===<br />
<br />
=AULA 3 - Dia 7/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*Continuação da aula anterior<br />
**Chamadas do Sistema (2.3)<br />
**Tipos de Chamadas de Sistema (2.4) ver Fig.2.8<br />
***Chamadas de Controle de Processos<br />
**Arquiteturas e Estruturas de Sistemas Operacionais (2.7)<br />
**Máquinas Virtuais (2.8)<br />
<br />
===Exercícios===<br />
<br />
<ol><br />
<li> Estudar e executar o código em http://cs.lmu.edu/~ray/notes/gasexamples/ <br />
Detalhes das chamadas na arquitetura x86_64 ver em https://lwn.net/Articles/604287/ <br />
<li>Estudar (usar o man) e executar o código usando a função (em conformidade com a API POSIX) write() para o ''hello world'':<br />
<code><br />
#include <unistd.h> <br />
<br />
main()<br />
{<br />
write(1,"Alo Mundo\n",10);<br />
}<br />
</syntaxhighlight><br />
</li><br />
<li> Use o comando strace para verificar todas as chamadas de sistema dos programas acima.<br />
</li><br />
<li><br />
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() 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:<br />
<code><br />
void meu_hello();<br />
<br />
int main()<br />
{<br />
meu_hello();<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
</li><br />
Gere o assembly do código em C e discuta a diferença entre uma chamada de função e uma chamada de sistema.<br />
<li><br />
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:<br />
<code><br />
#include <string.h><br />
main()<br />
{<br />
char *p="Tudo bem com vocês?";<br />
meu_hello_world(p, strlen(p));<br />
}<br />
</syntaxhighlight><br />
Solução:<br />
{{collapse top|Solução}}<br />
<code><br />
modificado de http://cs.lmu.edu/~ray/notes/gasexamples/<br />
.global meu_hello_world<br />
<br />
.text<br />
meu_hello_world:<br />
<br />
push %rdi # salva primeiro parâmetro<br />
push %rsi # salva segundo parâmetro<br />
mov $1, %rax # system call 1 é write<br />
mov $1, %rdi # file handle 1 é stdout<br />
mov $message, %rsi # endereço da string<br />
mov $13, %rdx # número de bytes da string<br />
syscall # chamada ao sistema<br />
<br />
pop %rdx # o que havia sido passado em rsi (número de bytes) é colocado em rdx<br />
pop %rsi # o que havia sido colocado em rdi (endereço da string) é colocado em rsi<br />
mov $1, %rax # system call 1 is write<br />
mov $1, %rdi # file handle 1 é stdout<br />
syscall # nova chamada ao sistema<br />
<br />
ret<br />
<br />
message:<br />
.ascii "Hello, World\n"<br />
</syntaxhighlight><br />
</li><br />
</ol><br />
{{collapse bottom}}<br />
<br />
=AULA 4 - Dia 9/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*PARTE 2A: Gerenciamento de Processos (cap.3)<br />
*3.1.Conceito de Processo<br />
*3.2.Escalonamento de Processos<br />
*3.3.Operações sobre Processos (Laboratório Operações sobre Processos no Linux: Fork/Exec/Wait)<br />
<br />
===Material de Referência===<br />
<br />
*Slides do Cap.3 - Silberschatz<br />
*Laboratório Fork/Exec/Wait<br />
<br />
=== Exercícios de Demonstração===<br />
<br />
#Executar em um terminal o comando top. Em um outro terminal executar:<br />
yes > /dev/null &<br />
yes > /dev/null &<br />
#Parar um dos processos yes<br />
kill -STOP <pid_yes><br />
#Continuar o processo<br />
kill -CONT <pid_yes><br />
#Destruir todos<br />
killall yes<br />
<br />
=AULA 5 - Dia 14/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*Ainda Processos<br />
*Cap.3.2..Escalonamento de Processos<br />
*Cap.2.3.Operaçṍes sobre processos<br />
*Finalização do Laboratório Fork/Exec/Wait<br />
<br />
===Adendo===<br />
<br />
*Estudar e comentar [https://www.geeksforgeeks.org/wait-system-call-c/]<br />
<br />
=AULA 6 - Dia 16/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*Comunicação Interprocessos (3.4 e 3.5)<br />
*Laboratório de Memória Compartilhada<br />
<br />
=AULA 7 - Dia 21/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Comunicação Interprocessos: Troca de Mensagens (3.6)<br />
*Laboratório de Pipes<br />
<br />
=AULA 8 - Dia 23/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Finalização Lab. pipes nomeados.<br />
*Threads ((cap.4.1, 4.2)<br />
*Lab.Threads de Aplicação<br />
<br />
=AULA 9 - Dia 28/08/2019=<br />
<br />
*Laboratório: Ainda Threads - Um escalonador semi-automático<br />
<br />
<br />
=AULA 10 - Dia 30/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Repassar um primeiro estudo sobre o RTOS<br />
*Revisar Processos e Threads<br />
<br />
==Questionário - Processos==<br />
<br />
#Conceitue processo. Descreva e explique cada uma das seções de um processo na memória.<br />
#Faça um diagrama e explique os possíveis estados de um processo no sistema. O que produz a transição entre estados?<br />
#O que é um Bloco de Controle de Processo? Quais informações ficam armazenadas neste bloco?<br />
#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.<br />
#Explique o que é multiprogramação e escalonamento de processos.<br />
#O que é a fila de processos prontos?<br />
#Diferencie um processo limitado por IO de um processo limitado por CPU.<br />
#Diferencie escalonamento de longo prazo de escalonamento de curto prazo.<br />
#Discuta o papel da interrupção na troca de contexto entre processos.<br />
#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?<br />
#Explique como funciona a chamada exec no UNIX/Linux<br />
#Explique como funciona a chamada wait no UNIX/Linux e como é possível retornar valores de um filho para o pai.<br />
#Faça um esqueleto de um programa UNIX/Linux que ao se tornar processo cria 3 filhos e espera pela execução dos mesmos.<br />
<br />
==Questionário - Comunicação entre Processos==<br />
<br />
#Diferenciar processos independentes de processos cooperantes.<br />
#Enumere e explique quatro razões para cooperação entre processos.<br />
#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.<br />
#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.<br />
#A memória compartilhada requer chamada ao sistema na sua operação? Discuta.<br />
#Por que o processo de troca de mensagem deve ser mais lento que a memória compartilhada?<br />
#Apresente em pseudocódigo uma proposta de funcionamento do problema do produtor consumidor usando memória compartilhada.<br />
#A construção de uma solução para o problema produtor consumidor pode ser facilitado pelo uso da memória compartilhada? Discuta.<br />
#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?<br />
#Enumere três métodos de implementação de uma lógica de ligação (link) entre processos.<br />
#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.<br />
#Descreva a variante assimétrica da troca direta de mensagens. O que muda em termos de primitiva de comunicação?<br />
#Descreva o problema de hard-coding associado a nomeação direta e como pode ser contornado através da nomeação/comunicação indireta?<br />
#O que é uma caixa postal? Como o Posix identifica uma caixa postal no caso de fila de mensagens?<br />
#Dois processos podem usar mais do que uma caixa postal para se comunicar? Qual a condição para que isto ocorra?<br />
#Descreva as duas operações básicas para a troca de mensagens com Caixa Postal.<br />
#Descreva na comunicação indireta via Caixa Postal as 3 propriedades básicas.<br />
#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.<br />
#De que forma a caixa postal estando no espaço de endereçamento de um processo (propriedade) afeta a recepção por mensagens? Descreva.<br />
#Quais as operações sobre uma caixa postal criada no espaço do sistema operacional deverão ser disponíveis? Descreva.<br />
#A transmissão de mensagem pode ser com e sem bloqueio. Descreva as 4 possibilidades (síncrona/assíncrona).<br />
#Discuta as 3 possibilidades de armazenamento de mensagens em buffer. Em que condições um remetente pode ser bloqueado?<br />
<br />
==ETAPA 1 - Projeto Final==<br />
<br />
*Apresentação (slides) sobre a parte de gerenciamento de tarefas no RTOS;<br />
*apresentação dia 18/09/2019<br />
<br />
==Referências==<br />
<br />
*[https://www.freertos.org/RTOS.html Site do FreeRTOS] ver Mastering the FreeRTOS Real Time Kernel - a Hands On Tutorial Guide <br />
*[https://www.embarcados.com.br/rtos-sistema-operacional-de-tempo-real/]<br />
*[https://github.com/feilipu/avrfreertos]<br />
<br />
=AULA 11 - Dia 4/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Pico de CPU X Pico de IO <br />
*Preempção X Não Preempção<br />
*Escalonamento de Processos: Escalonamento FCFS<br />
<br />
<br />
=AULA 12 - Dia 6/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Escalonamento de Processos: <br />
**Shortest Job First (preemptivo e não preemptivo)<br />
**Prioridade (preemptivo e não preemptivo)<br />
**Round-Robin: Preemptivo<br />
*Lab.Round Robin<br />
<br />
==Material de Referência==<br />
<br />
http://docente.ifsc.edu.br/andre.damato/sop2018/SOP2018-parte2.pdf<br />
<br />
<br />
=AULA 13 - Dia 13/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Sincronização entre Processos<br />
*Laboratório do Esquema de Peterson<br />
<br />
==Material de Referência==<br />
<br />
*Livro Silberchatz<br />
*https://www.os-book.com/OSE1/slide-dir/PPT-dir/ch6.ppt<br />
<br />
=AULA 14 - Dia 18/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Sincronização entre Processos<br />
*Lock de Hardware<br />
*Laboratório do TSL<br />
<br />
==Laboratório Proposto==<br />
<br />
*Refazer o problema proposto usando uma instrução simualada de test and set. Prever um liite superior para entrada de um processo na região crítica.<br />
<br />
==Material de Referência==<br />
<br />
*Livro Silberchatz<br />
*https://www.os-book.com/OSE1/slide-dir/PPT-dir/ch6.ppt<br />
<br />
<br />
=AULA 15 - Dia 20/08/2019=<br />
<br />
==O ATmega238 usado no Arduino UNO==<br />
<br />
Ver [https://pt.wikipedia.org/wiki/ATmega328]<br />
<br />
==O Arduino UNO==<br />
<br />
Ver [https://pt.wikipedia.org/wiki/Arduino]<br />
Ver [https://github.com/feilipu/Arduino_FreeRTOS_Library]<br />
<br />
==O FreeRtos para o Arduino==<br />
<br />
Ver [https://github.com/feilipu/Arduino_FreeRTOS_Library]<br />
<br />
Para instalar no IDE:<br />
*Baixar o ZIP do link acima<br />
*No IDE importar a biblioteca:<br />
**sketch->IncluirBiblioteca->Adicionar do arquivo ZIP<br />
<br />
<br />
==Código Experimental==<br />
<br />
Este código demonstra a ocorrência de "race condition".<br />
<br />
<syntaxhighlight lang=c><br />
// Code based on Examples of Arduino and examples <br />
// from https://github.com/feilipu/Arduino_FreeRTOS_Library<br />
<br />
#include <Arduino_FreeRTOS.h><br />
#include <FreeRTOSVariant.h><br />
#include <task.h><br />
#include <semphr.h><br />
<br />
#define TAM_BUFF 10<br />
<br />
volatile unsigned long race_flag=0xFFEEDDCC;<br />
volatile unsigned long int cont;<br />
int task_cont=0;<br />
<br />
void PrintSerial( void *pvParameters ); // Task para imprimir valor de race_flag<br />
void TaskBlink( void *pvParameters );<br />
void TaskSetarace_flag(void *pvParameters); //Task que atribui race_flag=0xFFEEDDCC<br />
void TaskZerarace_flag(void *pvParameters); //Task que atribui race_flag=0xAA0000AA<br />
<br />
// função de setup<br />
<br />
void setup() {<br />
<br />
Serial.begin(9600);<br />
<br />
while (!Serial) {<br />
; // wait for serial port to connect. Needed for native USB, on LEONARDO, MICRO, YUN, and other 32u4 based boards.<br />
}<br />
<br />
<br />
// criar as 2 tarefas<br />
<br />
xTaskCreate(<br />
TaskBlink<br />
, (const portCHAR *)"Blink" // A name just for humans<br />
, 128 // This stack size can be checked & adjusted by reading the Stack Highwater<br />
, NULL<br />
, 1 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.<br />
, NULL );<br />
<br />
xTaskCreate(<br />
TaskPrintSerial<br />
, (const portCHAR *) "PrintSerial"<br />
, 128 // Stack size<br />
, NULL<br />
, 1 // Priority<br />
, NULL );<br />
<br />
xTaskCreate(<br />
TaskSetarace_flag<br />
, (const portCHAR *) "Setarace_flag"<br />
, 128 // Stack size<br />
, NULL<br />
, 1 // Priority<br />
, NULL );<br />
<br />
xTaskCreate(<br />
TaskZerarace_flag<br />
, (const portCHAR *) "Zerarace_flag"<br />
, 128 // Stack size<br />
, NULL<br />
, 1 // Priority<br />
, NULL );<br />
<br />
cont = race_flag;<br />
<br />
// escalonador toma conta a partir daqui<br />
<br />
}<br />
<br />
void loop()<br />
{<br />
// nada a fazer aqui<br />
}<br />
<br />
/*--------------------------------------------------*/<br />
/*---------------------- Tasks ---------------------*/<br />
/*--------------------------------------------------*/<br />
<br />
void TaskBlink(void *pvParameters) // This is a task.<br />
{<br />
(void) pvParameters;<br />
<br />
/*<br />
Blink<br />
Turns on an LED on for one second, then off for one second, repeatedly.<br />
<br />
Most Arduinos have an on-board LED you can control. On the UNO, LEONARDO, MEGA, and ZERO <br />
it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN takes care <br />
of use the correct LED pin whatever is the board used.<br />
<br />
The MICRO does not have a LED_BUILTIN available. For the MICRO board please substitute<br />
the LED_BUILTIN definition with either LED_BUILTIN_RX or LED_BUILTIN_TX.<br />
e.g. pinMode(LED_BUILTIN_RX, OUTPUT); etc.<br />
<br />
If you want to know what pin the on-board LED is connected to on your Arduino model, check<br />
the Technical Specs of your board at https://www.arduino.cc/en/Main/Products<br />
<br />
This example code is in the public domain.<br />
<br />
modified 8 May 2014<br />
by Scott Fitzgerald<br />
<br />
modified 2 Sep 2016<br />
by Arturo Guadalupi<br />
*/<br />
<br />
// initialize digital LED_BUILTIN on pin 13 as an output.<br />
pinMode(LED_BUILTIN, OUTPUT);<br />
<br />
for (;;) // A Task shall never return or exit.<br />
{<br />
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)<br />
vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second<br />
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW<br />
vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second<br />
}<br />
}<br />
<br />
<br />
<br />
<br />
void TaskPrintSerial(void *pvParameters) // Task que imprime na serial - must be improved...<br />
{<br />
(void) pvParameters;<br />
/*<br />
<br />
*/<br />
<br />
<br />
for (;;)<br />
{ <br />
while (cont==0xAA0000AA || cont==0xFFEEDDCC)<br />
cont = race_flag;<br />
;<br />
<br />
Serial.println("Problemas: valor race_flag é");<br />
Serial.println(cont, HEX);<br />
<br />
vTaskDelay(5); // one tick delay (15ms) in between reads for stability - b<br />
cont = race_flag;<br />
}<br />
}<br />
<br />
void TaskSetarace_flag(void *pvParameters) <br />
{<br />
(void) pvParameters;<br />
const TickType_t xMaxBlockTimeTicks = 0x20;<br />
/*<br />
<br />
*/<br />
<br />
race_flag=0xAA0000AA;<br />
for (;;)<br />
{<br />
race_flag=0xAA0000AA;<br />
//Serial.println("Produtor");<br />
vTaskDelay( ( rand() %xMaxBlockTimeTicks) ); <br />
} <br />
<br />
}<br />
<br />
void TaskZerarace_flag(void *pvParameters) <br />
{<br />
(void) pvParameters;<br />
const TickType_t xMaxBlockTimeTicks = 0x20;<br />
/*<br />
<br />
*/<br />
race_flag=0xFFEEDDCC;<br />
<br />
for (;;)<br />
{<br />
race_flag=0xFFEEDDCC;<br />
vTaskDelay( ( rand() %xMaxBlockTimeTicks) ); <br />
if(task_cont++==100) {<br />
delay(1);<br />
Serial.println("Fim TaskZera - valor race_flag ");<br />
Serial.println(race_flag, HEX);<br />
for(;;);<br />
} <br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=AULA 16 - Dia 25/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Preparação de exemplos de RTOS sobre Arduíno para apresentação na sexta;<br />
<br />
=Laboratórios Propostos= <br />
<br />
Considere o código abaixo. Observe que a região de dados compartilhada shared_data é zerada pelo pai e setada pelo processo filho. O pai detecta inconsistências nos dados que operou. Tente corrigir usando o esquema de Peterson para acesso a região crítica. Crie uma função de entrada e de saída da região crítica.<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
<br />
<br />
#define BUFFER_SIZE 4096<br />
char *shared_data;<br />
char reference_data[BUFFER_SIZE];<br />
<br />
main()<br />
{ <br />
key_t key;<br />
int shmid;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, BUFFER_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
shared_data = shmat(shmid, (void *)0, 0);<br />
<br />
if (shared_data == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int count=0; <br />
memset(reference_data,0,BUFFER_SIZE); <br />
for(;;){ <br />
memset(shared_data,0,BUFFER_SIZE);<br />
if (memcmp(shared_data, reference_data, BUFFER_SIZE)!=0) {<br />
count++;<br />
if (count%1000000==0)<br />
printf("Processo pai detectou algo errado nos dados %d\n", count); <br />
} <br />
} <br />
<br />
<br />
}<br />
else { /*Child code */<br />
<br />
for(;;){ <br />
memset(shared_data,1,BUFFER_SIZE); <br />
}<br />
<br />
}<br />
<br />
if (shmdt(shared_data) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
Possível solução:<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
#include <unistd.h><br />
<br />
#define BUFFER_SIZE 4096<br />
#define ID_PAI 0<br />
#define ID_FILHO 1<br />
#define FALSE 0<br />
#define TRUE 1<br />
<br />
char *shared_data;<br />
char reference_data[BUFFER_SIZE];<br />
<br />
struct tipo_peterson{<br />
char flag[2];<br />
char turn;<br />
} *pet_struct;<br />
<br />
void ent_sec_crit(int id)<br />
{<br />
char id_outro = (id+1)%2;<br />
<br />
pet_struct->flag[id] = TRUE; // indica que o processo deseja entrar na região crítica<br />
pet_struct->turn = id_outro; // o processo sinaliza para o outrao entrar, <br />
// caso o outro esteja entrando<br />
// este ponto é uma race condition: turn pode ser 0 ou 1 <br />
while ( (pet_struct->flag[id_outro]==TRUE) && (pet_struct->turn == id_outro) )<br />
;<br />
}<br />
<br />
void sai_sec_crit(int id)<br />
{<br />
pet_struct->flag[id] = FALSE;<br />
}<br />
<br />
int main()<br />
{ <br />
key_t key;<br />
int shmid;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, BUFFER_SIZE+sizeof(struct tipo_peterson), S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
shared_data = shmat(shmid, (void *)0, 0);<br />
pet_struct = (struct tipo_peterson *) (shared_data + BUFFER_SIZE); <br />
<br />
if (shared_data == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int count=0; <br />
memset(reference_data,0,BUFFER_SIZE); <br />
for(;;){ <br />
ent_sec_crit(ID_PAI);<br />
memset(shared_data,0,BUFFER_SIZE);<br />
if (memcmp(shared_data, reference_data, BUFFER_SIZE)!=0) {<br />
count++;<br />
if (count%1000000==0)<br />
printf("Processo pai detectou algo errado nos dados %d\n", count); <br />
} <br />
sai_sec_crit(ID_PAI);<br />
} <br />
<br />
<br />
}<br />
else { /*Child code */<br />
<br />
for(;;){<br />
ent_sec_crit(ID_FILHO); <br />
memset(shared_data,1,BUFFER_SIZE);<br />
sai_sec_crit(ID_FILHO); <br />
}<br />
<br />
}<br />
<br />
if (shmdt(shared_data) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
=AULA 17 - Dia 27/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Apresentação dos Trabalhos<br />
*Definição da próxima etapa<br />
<br />
=AULA 18 - Dia 02/10/2019=<br />
<br />
==Objetivos==<br />
<br />
*Semáforos, Deadlock e o Problema da Inversão de Prioridade<br />
*Laboratório de Pthreads e Mutex;<br />
<br />
==Laboratório Proposto==<br />
<br />
*Lab. Programação concorrente - Parte 1<br />
<br />
==Materia de Referência==<br />
<br />
*[https://www.os-book.com/OSE1/slide-dir/PDF-dir/ch6.pdf]<br />
<br />
==Desafio==<br />
<br />
Usar <br />
ps -T aux | grep ex1vA<br />
<br />
Para ver os threads dormindo...<br />
<br />
Otimizar o programa abaixo<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <pthread.h><br />
#include <stdlib.h><br />
#include <unistd.h><br />
#include <time.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
pthread_mutex_t mut;<br />
<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
<br />
<br />
long long i;<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
usleep(5000000);<br />
printf("Novo saldo = %d\n",novo_saldo);<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d\n", (i+1));<br />
exit(-1);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
printf("Saldo final é %d\n", saldo);<br />
}<br />
</syntaxhighlight><br />
<br />
==Laboratório Proposto==<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Programação concorrente}}<br />
<br />
== Programação concorrente ==<br />
<br />
<br />
===PARTE 1 - Mutex e Biblioteca libpthreads===<br />
<br />
;POSIX Threads<br />
A 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):<br />
*''pthread_create'': cria uma thread;<br />
*''pthread_kill'': força a terminação de uma thread;<br />
*''pthread_join'': sincroniza o final de uma thread (qual a diferença/semelhança com o ''wait'' que usamos para processos?);<br />
*''pthread_exit'': finaliza uma thread.<br />
Para utilizar estas funções é necessário linkar o programa à libpthread (''-lpthread''). <br />
<br />
<br />
;POSIX pthread mutex<br />
<br />
A biblioteca pthread implementa um tipo ''pthread_mutex_t'', que garante a exclusão mútua entre threads. Estes mutex são manipulados através das funções (acesse as man-pages das chamadas para maiores detalhes):<br />
*''pthread_mutex_lock'': acessa um mutex.<br />
*''pthread_mutex_trylock'': tenta acessar um mutex (retorna valor indicando sucesso ou falha no lock).<br />
*''pthread_mutex_unlock'': libera um mutex.<br />
<br />
<br />
<br />
;Exercício 1<br />
<br />
O programa abaixo cria 5 threads, e cada uma destas threads atualiza uma variável global (memória compartilhada).<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
#include <pthread.h><br />
#include <stdlib.h><br />
#include <unistd.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
pthread_mutex_t mut;<br />
<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
long long i;<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
sleep(1);<br />
printf("Novo saldo = %d\n",novo_saldo);<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d\n", (i+1));<br />
exit(-1);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
printf("Saldo final é %d\n", saldo);<br />
}<br />
</syntaxhighlight><br />
<br />
# Compile este programa. <br />
# Execute este programa várias vezes. Ele funciona? Será que ele gera as saídas esperadas?<br />
# Identifique as '''seções críticas''' do programa.<br />
# Corrija o programa utilizando '''mutex'''. <br />
# Analise a função ''AtualizaSaldo()'' com a sua solução. Lembre-se que o uso do mutex implica em apenas uma thread acessar a seção crítica por vez, enquanto outras threads ficam bloqueadas, esperando. Disso vem que, quanto menor o trecho de código entre um ''lock'' e um ''unlock'', menos tempo uma thread necessita ficar esperando.<br />
<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <cstring><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
<br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
sem_t sem;<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
int value;<br />
sem_wait(&sem);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
sem_getvalue(&sem, &value);<br />
printf("valor sem = %d\n", value);<br />
sem_post(&sem);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
sem_init(&sem,0,1);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
sem_destroy(&sem);<br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
===PARTE 2 - POSIX Semaphores===<br />
<br />
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):<br />
*''sem_init'': inicializa um semáforo;<br />
*''sem_destroy'': destroy um semáforo;<br />
*''sem_wait'': implementa a operação ''p'';<br />
*''sem_post'': implementa a operação ''v''.<br />
Para utilizar estas funções é necessário linkar o programa à librt ou à libpthread (''-lrt'' ou ''-lpthread'').<br />
<br />
;Exercício 1<br />
Modifique o programa para usar um semáforo binário ao invés de um mutex em sua solução.<br />
<br />
;Exercício 2<br />
Refaça o exercício 3 usando processos criados com fork e exec. O semáforo deve ser criado em uma região de memória compartilhada.<br />
<br />
;Exercício 3<br />
Implemente com pthreads e semáforos/mutex a solução do produtor/comsumidor.<br />
<br />
;Exercício 4<br />
<br />
O programa abaixo manipula uma matriz de tamanho MxN (veja os defines para o tamanho da matriz). A função ''SumValues'' soma todos os valores em uma linha da matriz. A linha a ser somada é identificada pela variável ''i''. Modifique o programa principal (''main'') nos locais indicados para:<br />
# Criar N threads, uma para somar os valores de cada linha.<br />
# Receber o resultado do somatório de cada linha e gerar o somatório total da matriz.<br />
# Analise o programa: há problemas de sincronização que precisam ser resolvidos? Se sim, resolva-os.<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include "thread.h"<br />
<br />
/* number of matrix columns and rows */<br />
#define M 5<br />
#define N 10<br />
<br />
using namespace std;<br />
<br />
int matrix[N][M];<br />
Thread *threads[N];<br />
<br />
<br />
/* thread function; it sums the values of the matrix in the row */<br />
int SumValues(int i)<br />
{<br />
int n = i; /* number of row */<br />
int total = 0; /* the total of the values in the row */<br />
int j;<br />
for (j = 0; j < M; j++) /* sum values in the "n" row */<br />
total += matrix[n][j];<br />
cout << "The total in row" << n << " is " << total << "." << endl;<br />
/* terminate a thread and return a total in the row */<br />
exit(total);<br />
}<br />
<br />
int main(int argc, char *argv[])<br />
{<br />
int i, j;<br />
int total = 0; /* the total of the values in the matrix */<br />
<br />
/* initialize the matrix */<br />
for (i = 0; i < N; i++)<br />
for (j = 0; j < M; j++)<br />
matrix[i][j] = i * M + j;<br />
<br />
/* create threads */<br />
/* COLOQUE SEU CÓDIGO PARA CRIAR AS THREADS AQUI! */<br />
<br />
/* wait for terminate a threads */<br />
/* COLOQUE SEU CÓDIGO PARA PEGAR O SOMATÓRIO DE LINHAS E TOTALIZAR A SOMA DA MATRIZ AQUI! */<br />
<br />
cout << "The total values in the matrix is " << total << endl;<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
{{collapse bottom}}<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Escalonamento Round Robin e FCFS para Threads"}}<br />
<br />
== Escalonamento Round-Robin ==<br />
<br />
OBS: ver https://www.quora.com/What-exactly-does-typedef-do-in-C<br />
<br />
O Exemplo abaixo mostra a implementação de um esquema de escalonamento Round Robin do exercício anterior.<br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
Modificado por Eraldo <br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 5<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
void runA(void) {<br />
for (;;) {<br />
printf("running A\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runB(void) {<br />
for (;;) {<br />
printf("running B\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 1<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
<br />
void scheduler_rr();<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void yield_thread()<br />
{<br />
scheduler_rr();<br />
}<br />
<br />
void delete_thread()<br />
{<br />
delete curr_thread;<br />
curr_thread=NULL;<br />
scheduler_rr();<br />
}<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
struct delta{<br />
long alfa;<br />
char epson[1000];<br />
long beta;<br />
} shar;<br />
<br />
int turn;<br />
int flag[2];<br />
<br />
#define TRUE 1<br />
#define FALSE 0<br />
<br />
void ent_rc(int p, int vt)<br />
{<br />
flag[p]=TRUE;<br />
turn = vt;<br />
if(p) p=0; else p=1;<br />
while (flag[p] && turn == vt);<br />
//printf("Thread %d: esperando para acessar a região crítica\n", p);<br />
}<br />
<br />
void sai_rc(int p)<br />
{<br />
flag[p]=FALSE;<br />
}<br />
<br />
void runA(void) {<br />
struct delta x = {0, 100};<br />
<br />
for (;;) {<br />
x.alfa=0;x.beta=0;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0);<br />
x.alfa=100;x.beta=100;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0); <br />
}<br />
}<br />
<br />
void runB(void) {<br />
<br />
for (;;) {<br />
ent_rc(1,0);<br />
printf("shar alfa = %ld shar beta = %ld \n",shar.alfa, shar.beta); // regiao crítica<br />
sai_rc(1);<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runC(void) {<br />
int i;<br />
for (i=0;i<10;i++) {<br />
printf("Thread C - parte 1\n");<br />
yield_thread();<br />
printf("Thread C - parte 2\n");<br />
yield_thread();<br />
}<br />
delete_thread();<br />
}<br />
<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
add_thread(runC);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
{{collapse bottom}}<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Um escalonador semi-automático"}}<br />
<br />
== Ainda Threads - Um escalonador semi-automático usando sinais ==<br />
<br />
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.<br />
<br />
===Exemplo 1:===<br />
<br />
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. <br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
<br />
void sig_handler(int signo)<br />
{<br />
int x;<br />
printf("Turma de SOP: recebido SIGUSR1\n");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
// Loop eterno dormindo 1s<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Fazer no terminal:<br />
ps aux<br />
anotar o pid do processo e enviar o sinal:<br />
kill -USR1 pid<br />
<br />
===Exemplo 2:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// loop eterno que nunca é executado<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Enviar o sinal USR1 para ver o efeito. <br />
<br />
===Exemplo 3:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void prepara_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void prepara_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
prepara_contexto_ping();<br />
prepara_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// A long long wait so that we can easily issue a signal to this process<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Exercício: Use o comando htop para verificar como estes threads são vistos pelo SOP.<br />
<br />
Exercício: Tente analisar as pilhas dos threads e verificar sob qual pilha o handler se executa.<br />
<br />
<br />
===Exercício 4:===<br />
<br />
Neste ponto associamos um timer ao handler com o apoio do sinal ALRM. Agora os threads são escalonados automaticamente.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
===Exercício Proposto 5===<br />
<br />
Colocar 3 threads rodando.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void preparar_contexto_ping(ucontext_t *pContext, char *p)<br />
{<br />
char *stack;<br />
<br />
getcontext(pContext);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
(*pContext).uc_stack.ss_sp = stack ;<br />
(*pContext).uc_stack.ss_size = STACKSIZE;<br />
(*pContext).uc_stack.ss_flags = 0;<br />
(*pContext).uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(pContext, (void*)(*f_ping), 1, p);<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping(&cPing, "ping");<br />
preparar_contexto_ping(&cPong, "pong");<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Threads de aplicação}}<br />
<br />
== Threads de aplicação ==<br />
<br />
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:<br />
*'''getcontext(&a)''': salva o contexto na variável '''a''';<br />
*'''setcontext(&a)''': restaura um contexto salvo anteriormente na variável '''a''';<br />
*'''swapcontext(&a,&b)''': salva o contexto atual na variável '''a''' e restaura o contexto salvo anteriormente na variável '''b''';<br />
*'''makecontext(&a, ...)''': ajusta parâmetros internos do contexto salvo em '''a''';<br />
*'''ucontext_t''': as variáveis '''a''' e '''b''' são do tipo '''ucontext_t'''. Este tipo armazena um contexto.<br />
<br />
Busque mais informações sobre estas funções utilizando o programa manpage do Linux (ex.: man getcontext).<br />
<br />
Estude o código no arquivo pingpong.c abaixo e explique seu funcionamento.<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
*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.<br />
*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.<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain, cFnew;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_new(void * arg1, void * arg2,void * arg3,void * arg4) <br />
{<br />
printf ("%s: Primeira string %s %s %s\n",(char*) arg1,(char*) arg2,(char*) arg3, (char*) arg4);<br />
swapcontext(&cFnew, &cMain); <br />
}<br />
<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
<br />
getcontext(&cFnew);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cFnew.uc_stack.ss_sp = stack ;<br />
cFnew.uc_stack.ss_size = STACKSIZE;<br />
cFnew.uc_stack.ss_flags = 0;<br />
cFnew.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cFnew, (void*)(*f_new), 4, "\tF_new", "\tAlo", "\tMundo","\tReal");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
swapcontext(&cMain, &cFnew);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
--><br />
Exercício 3: O que acontece se um dos threads é colocado para dormir? Todos os demais threads param a sua execução.<br />
<br />
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/<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Processos no Linux}}<br />
<br />
== Processos no Linux - Modificado por Eraldo ==<br />
<br />
<blockquote style="background: lime; border: 1px solid black; padding: 1em;"><br />
Processos no Linux<br />
</blockquote><br />
<br />
*Exercícios propostos pelo Prof.Arliones e Modificados por Eraldo<br />
<br />
<br />
[[imagem:DesenhoForkExec.png|border|650px]]<br />
<br />
<br />
;Syscall FORK<br />
<br />
* Em um terminal, execute "man fork"<br />
** 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'''.<br />
** O '''código''' dos dois processos (pai e filho) são '''idênticos''';<br />
** Os '''dados''' dos dois processos (pai e filho) são '''idênticos NO MOMENTO DA CRIAÇÃO''';<br />
** Execução do processo filho inicia na próxima instrução do programa (no retorno da chamada FORK);<br />
** Não é possível saber qual dos processos (pai ou filho) retormará a execução primeiro - isto fica a cargo do excalonador do SO;<br />
** Valores de retorno da chamada FORK:<br />
*** (-1): erro na criação do processo (ex.: memória insuficiente);<br />
*** (0): em caso de sucesso, este é o valor de retorno recebido pelo processo filho;<br />
*** (>0): em caso de sucesso, este é o valor de retorno recebido pelo processo pai;<br />
<br />
;Syscall JOIN<br />
<br />
* A syscall JOIN é implementada no POSIX pela função '''wait()'''. Execute "man wait".<br />
** Além da função '''wait()''', há também '''waitpid()''' e '''waitid()''';<br />
** 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);<br />
** A chamada wait também libera os recursos do processo filho que termina;<br />
** '''wait()''': esta função suspende a execução do processo chamador até que UM DOS SEUS FILHOS finalize;<br />
** '''waitpid()''': suspende a execução do processo chamador até que UM FILHO ESPECÍFICO finalize;<br />
<br />
;Syscall EXEC<br />
<br />
* A syscall EXEC é implementada no POSIX pela família de funções '''exec()'''. Execute "man exec".<br />
** As principais funções da família são '''execl()''', '''execlp()''' e '''execvp()''';<br />
** 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;<br />
** 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;<br />
<br />
<br />
;Exemplos POSIX utilizando fork/wait/exec<br />
<br />
*Exemplo 1: fork/wait básico<br />
<syntaxhighlight lang=c><br />
// ex1: fork/wait básico<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
printf("processo filho\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
printf("processo pai\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
arliones@socrates:~/tmp$ gcc ex1.c -o ex1 <br />
arliones@socrates:~/tmp$ ./ex1 <br />
processo filho pid: 27858 pid pai: 27857<br />
processo pai pid: 27857 pid pai: 5337<br />
arliones@socrates:~/tmp$ <br />
</syntaxhighlight><br />
<br />
* Exemplo 2: processos pai e filho compartilham código, mas não dados.<br />
<syntaxhighlight lang=c><br />
// ex2: fork/wait "compartilhando" dados<br />
// ex2: fork/wait "compartilhando" dados<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status, k=0;<br />
printf("processo %d\t antes do fork\n", getpid());<br />
pid = fork();<br />
printf("processo %d\t depois do fork\n", getpid());<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
k += 1000;<br />
printf("processo filho\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status); // espera o filho terminar<br />
k += 10;<br />
printf("processo pai\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
k += 1000;<br />
printf("FIM processo %d\t K: %d\n", getpid(), k); <br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
processo 17056 antes do fork<br />
processo 17056 depois do fork<br />
processo 17057 depois do fork<br />
processo filho pid: 17057 K: 1000 endereço K: 0x7ffd8923e318<br />
processo pai pid: 17056 K: 10 endereço K: 0x7ffd8923e318<br />
</syntaxhighlight><br />
<br />
* Modificação no código: comentar linhas 23 e 30<br />
<br />
<syntaxhighlight lang=bash><br />
<br />
</syntaxhighlight><br />
<br />
* Analise os resultados e busque entender a diferença.<br />
*Perguntas e desafios.:<br />
#Analisando os valores impressos de k pode-se dizer que os dados são compartilhados entre os dois processos?<br />
#O endereço de k impresso é o mesmo nos dois processos. ISto não contradiz a afirmação anterior?<br />
#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.<br />
<br />
<br />
;Exercício fork/wait<br />
<br />
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.<br />
<br />
*Use o comando pstree para verificar a árvore de processos criada.<br />
<br />
{{collapse top|Solução}}<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
<!--<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
--><br />
<br />
;DESAFIO: fork/wait<br />
<br />
Reimplementar o exercício anterior de criação de uma árvore de 3 processos, generalizando a criação de N processos onde N é repassado na linha de comando do programa. SUGESTÃO: usar um comando for, mas lembrar que se existe um fork dentro do for, então cada filho gerado dará continuidade a execução do for. É necessário que o processo faça um exit ou retorne neste momento.<br />
<br />
;DESAFIO: Exercício status/wait<br />
<br />
O ''status'' passado como parâmetro à função ''wait(&status)'' é, na verdade, o mecanismo de retorno de resultado do ''wait/waitpid''. Ao retornar, esta variável contém informações sobre o resultado da execução do processo filho. Por exemplo, se um processo terminou normalmente (i.e., chamou ''exit''), o comando ''WIFEXITED(status)'' retorna ''true''. Este comando retorna ''false'' se o processo foi abortado (e.g., ''segmentation fault'') ou morto (e.g., ''kill''). Investigue no manual do wait no Linux (''man wait'') o funcionamento do comando WEXITSTATUS(status). <br />
Imagine um problema de busca de dados armazenados na forma de uma matriz de inteiros 4x30. Você está interessado em saber quantas ocorrências de um determinado número existe em cada linha da matriz. Note que que são tarefas que podem ser paralelizadas e usufruir de um sistema capaz de executá-las em paralelo. Faça uma implementação paralelizando 4 processos filhos a partir de um pai, onde cada processo é responsável por uma busca. A quantidade de ocorrências do número buscado é retornada e capturada através de WEXITSTATUS.<br />
<br />
;Syscall EXEC<br />
<br />
*Exemplo exec()<br />
<br />
<syntaxhighlight lang=c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
execl("/bin/ls","ls","-l", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 1: Modificar o código para mostrar que o exec() não retorna (colocar um printf após o exec).<br />
<br />
*Exercício 2: Criar um exemplo (dois programas ) para demonstrar que o exec não cria novo processo. <br />
**Crie um primeiro programa (prog1) que imprime o seu pid e depois faz um exec do segundo programa.<br />
**Crie o segundo programa que simplesmente imprime o pid.<br />
<br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU ANTES DO EXEC: Meu pid é %d\n", getpid());<br />
execl("./prog2","prog2", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU DEPOIS DO EXEC:Meu pid é %d\n", getpid());<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 3: Criar um exemplo usando fork/exec mostrando que um processo pai cria um filho e espera por sua execução. O filho executa o comando "ps aux". Ambos devem mostrar seus pids.<br />
<br />
{{collapse bottom}} <br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Laboratório Memória Compartilhada entre Pai e Filho - Produtor Consumidor}}<br />
<br />
Baseado no Lab. do Prof.Arliones<br />
<br />
=== Objetivo ===<br />
<br />
*Familiarizar o aluno com o conceito de Memória Compartilhada entre Processos Pai e Filho<br />
*Familizarizar o aluno com o conceito de Produtor Consumidor<br />
<br />
=== Referencial Teórico-Prático ===<br />
<br />
* Silberchatz - 3.4 e 3.5<br />
* man nos comandos shmat e shmget<br />
<br />
=== Exemplo de Funcionamento ===<br />
<br />
No exemplo abaixo um processo pai compartilha uma área de memória com o processo filho. O processo filho escreve uma mensagem para o pai na área de memória compartilhada e termina. O processo pai é desbloqueado no wait e imprime a mensagem escrita.<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
char *ptr_msg = "alo pai, tudo bem?"; <br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
strcpy(segmento, ptr_msg);<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(&filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
=== Desafio a ser Implementado em Sala ===<br />
<br />
Construir um programa em que um processo pai atua como produtor e o processo filho atua como consumidor. O buffer circular compartilhado é um buffer de inteiro de tamanho 5. O pai alimentará o buffer com 50 itens gerados aleatóriamente entre 1 e 100. A cada escrita/leitura no buffer o produtor/consumidor deve esperar alguns milisegundos de forma a acontecer situações de buffer cheio e vazio. <br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
#include <unistd.h><br />
#include <time.h><br />
#include <sys/types.h><br />
#include <sys/wait.h><br />
<br />
<br />
<br />
#define SHM_SIZE 1024 <br />
<br />
#define BUFF_COMP_SIZE 5<br />
<br />
struct buff_comp {<br />
int buffer[BUFF_COMP_SIZE];<br />
int in,out;<br />
};<br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
struct buff_comp *p; <br />
<br />
/* initialize random seed: */<br />
srand ( time(NULL) );<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
p = (struct buff_comp *) shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
p->out = p->in = 0;<br />
<br />
if((filho = fork()) == -1)<br />
{<br />
<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
int i;<br />
for(i=0;i<50;i++) {<br />
while (p->in==p->out) {<br />
printf("FILHO: BUFFER VAZIO !!!!!!!\n");<br />
usleep(rand() % 10000 + 1);<br />
}<br />
printf("FILHO: item lido = %d\n", p->buffer[p->out]);<br />
p->out = (p->out+1)%BUFF_COMP_SIZE;<br />
}<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
int i; <br />
<br />
for(i=0;i<50;i++) {<br />
while (((p->in+1)%BUFF_COMP_SIZE) == p->out) {<br />
printf("PAI: BUFFER CHEIO !!!!!!!\n");<br />
usleep(rand() % 10000 + 1);<br />
}<br />
p->buffer[p->in] = rand() % 100 + 1;<br />
printf("PAI: item produzido = %d\n", p->buffer[p->in]);<br />
p->in = (p->in+1)%BUFF_COMP_SIZE;<br />
<br />
}<br />
wait(&filho); <br />
<br />
}<br />
<br />
<br />
if (shmdt(p) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Trocas de mensagens com pipes}}<br />
<br />
= Trocas de mensagens com pipes =<br />
<br />
;Troca de mensagens<br />
Um mecanismo disponibilizado por sistemas UNIX para troca de mensagens entre processos é o PIPE. Pipes são mecanismos de comunicação indireta onde mensagens são trocadas através de ''mailboxes''. Cada ''mailbox'' possui um identificador único, permitindo que processos identifiquem o canal de comunicação entre eles. O fluxo de mensagens em um Pipe é:<br />
*'''unidirecional''': sobre um mesmo pipe, apenas um processo envia mensagens e um processo recebe mensagens;<br />
*'''FIFO''': as mensagens são entregues na ordem de envio;<br />
*'''não-estruturado''': não há estrutura pré-definida para o formato da mensagem.<br />
No UNIX, pipes são inicializados através da '''SystemCall''' ''pipe'', que possui a seguinte sintaxe:<br />
*''int pipe(int pipefd[2])'': ''pipe'' inicializa um novo pipe no sistema e retorna, no array pipefd, os descritores identificando cada uma das pontas do pipe. A primeira posição do array, i.e. pipefd[0], recebe o descritor que pode ser aberto apenas para leitura, enquanto a segunda posição do array, i.e. pipefd[1], recebe o descritor que pode ser aberto apenas para escrita. A função retorna zero no caso de sucesso, ou -1 se ocorrer erro.<br />
As primitivas send/receive para uso de um pipe no UNIX são implementadas por '''SystemCalls''' read/write, conforme segue:<br />
*''ssize_t read(int fd, void *buf, size_t count)'': “puxa” dados do pipe identificado pelo descritor fd. Os dados recebidos são os apontados pelo ponteiro buf, sendo count a quantidade máxima de bytes a serem recebidos. A função retorna o número de bytes recebidos.<br />
*''ssize_t write(int fd, const void *buf, size_t count)'': “empurra” dados no pipe identificado pelo descritor fd. Os dados transmitidos são os apontados pelo ponteiro buf, sendo count a quantidade de bytes a serem transmitidos. A função retorna o número de bytes transmitidos.<br />
<br />
*Exemplo 1: Transmitindo e recebendo pelo próprio processo<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main()<br />
{<br />
int fd[2];<br />
char *ptr = "Alo eu mesmo";<br />
char *ptr_alvo;<br />
int tamanho_dados, ret;<br />
<br />
tamanho_dados = strlen(ptr)+1;<br />
<br />
if (pipe(fd)==-1){<br />
printf ("erro criação pipe\n");<br />
exit(-1);<br />
}<br />
printf("Transmitido %d bytes\n", tamanho_dados);<br />
write (fd[1], ptr, tamanho_dados);<br />
<br />
ptr_alvo = malloc(tamanho_dados);<br />
<br />
ret=read(fd[0],ptr_alvo,tamanho_dados);<br />
<br />
printf("ret = %d dados => %s\n", ret, ptr_alvo); <br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
*Exemplo 2: Abaixo há um exemplo de programa criando um pipe e compartilhando os descritores entre dois processos (criados via ''fork()'').<br />
<syntaxhighlight lang=c><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
<br />
char *message = "This is a message!!!" ;<br />
<br />
main()<br />
{<br />
char buf[1024] ;<br />
int fd[2];<br />
pipe(fd); /*create pipe*/<br />
if (fork() != 0) { /* I am the parent */<br />
write(fd[1], message, strlen (message) + 1) ;<br />
}<br />
else { /*Child code */<br />
read(fd[0], buf, 1024) ;<br />
printf("Got this from MaMa!!: %s\n", buf) ;<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
*'''Exercício 1: construa um “pipeline”'''. Crie um programa que conecta 4 processos através de 3 pipes. Utilize ''fork()'' para criar vários processos.<br />
<br />
<syntaxhighlight lang=cpp><br />
<br />
//Solução possível<br />
<br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
pipe(fd);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
<br />
</syntaxhighlight><br />
<br />
*'''Exercício 2: Modifique o exercício anterior para que o processo D, através de um novo pipe, mande uma mensagem diretamente para o pai de todos.<br />
<br />
<!--<br />
<code><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
int fd_retorno[2];<br />
<br />
pipe(fd);<br />
pipe(fd_retorno);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size);<br />
read(fd_retorno[0], buf, size);<br />
printf("PAI:%s\n", buf); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
char *ptr_msg_ret="Ok msg de D para o pai";<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
write(fd_retorno[1],ptr_msg_ret,strlen(ptr_msg_ret)+1);<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
*'''Exercício 3: Consultor de Login de Acesso:'''. Estude o link https://www.geeksforgeeks.org/named-pipe-fifo-example-c-program/ e projete um programa cliente servidor da seguinte forma: (i) O servidor possui uma tabela de usuários (userid). O user_id é de tamanho fixo de 7 caracteres. O servidor espera por consultas para verificar se um usuário está na tabela. Se estiver responde com o caracter 'S' senão com 'N'. (ii) O cliente espera por user_id no teclado e consulta o servidor sobre sua existência na tabela. O cliente imprime na tabela a existência ou não do usuário.<br />
<br />
*'''Exercício 4: cópia de arquivo'''. Projete um programa de cópia de arquivos chamado FileCopy usando pipes comuns. Esse programa receberá dois parâmetros: o primeiro é o nome do arquivo a ser copiado e o segundo é o nome do arquivo copiado. Em seguida, o programa criará um pipe comum e gravará nele o conteúdo do arquivo a ser copiado. O processo filho lerá esse arquivo do pipe e o gravará no arquivo de destino. Por exemplo, se chamarmos o programa como descrito a seguir:<br />
:<syntaxhighlight lang=bash><br />
$ FileCopy entrada.txt copia.txt<br />
</syntaxhighlight><br />
:o arquivo ''entrada.txt'' será gravado no pipe. O processo filho lerá o conteúdo desse arquivo e o gravará no arquivo de destino ''copia.txt''. Escreva o programa usando os pipes da API POSIX no Linux.<br />
<br />
<br />
{{collapse bottom}}<br />
<br />
=Laboratórios Disponíveis= <br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Escalonamento Round Robin e FCFS para Threads"}}<br />
<br />
<br />
== Escalonamento Round-Robin preemptivo ==<br />
<br />
OBS: ver https://www.quora.com/What-exactly-does-typedef-do-in-C<br />
<br />
A fazer: <br />
<br />
*primitiva de término de processo (destrutor do objeto); <br />
*primitiva de yield<br />
*isolar o escalonador em uma função;<br />
*isolar o dispatcher em uma função; <br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
Modificado por Eraldo <br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 5<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
void runA(void) {<br />
for (;;) {<br />
printf("running A\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runB(void) {<br />
for (;;) {<br />
printf("running B\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 1<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
<br />
void scheduler_rr();<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void yield_thread()<br />
{<br />
scheduler_rr();<br />
}<br />
<br />
void delete_thread()<br />
{<br />
delete curr_thread;<br />
curr_thread=NULL;<br />
scheduler_rr();<br />
}<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
struct delta{<br />
long alfa;<br />
char epson[1000];<br />
long beta;<br />
} shar;<br />
<br />
int turn;<br />
int flag[2];<br />
<br />
#define TRUE 1<br />
#define FALSE 0<br />
<br />
void ent_rc(int p, int vt)<br />
{<br />
flag[p]=TRUE;<br />
turn = vt;<br />
if(p) p=0; else p=1;<br />
while (flag[p] && turn == vt);<br />
//printf("Thread %d: esperando para acessar a região crítica\n", p);<br />
}<br />
<br />
void sai_rc(int p)<br />
{<br />
flag[p]=FALSE;<br />
}<br />
<br />
void runA(void) {<br />
struct delta x = {0, 100};<br />
<br />
for (;;) {<br />
x.alfa=0;x.beta=0;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0);<br />
x.alfa=100;x.beta=100;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0); <br />
}<br />
}<br />
<br />
void runB(void) {<br />
<br />
for (;;) {<br />
ent_rc(1,0);<br />
printf("shar alfa = %ld shar beta = %ld \n",shar.alfa, shar.beta); // regiao crítica<br />
sai_rc(1);<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runC(void) {<br />
int i;<br />
for (i=0;i<10;i++) {<br />
printf("Thread C - parte 1\n");<br />
yield_thread();<br />
printf("Thread C - parte 2\n");<br />
yield_thread();<br />
}<br />
delete_thread();<br />
}<br />
<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
add_thread(runC);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Um escalonador semi-automático"}}<br />
<br />
== Ainda Threads - Um escalonador semi-automático usando sinais ==<br />
<br />
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.<br />
<br />
===Exemplo 1:===<br />
<br />
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. <br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
<br />
void sig_handler(int signo)<br />
{<br />
int x;<br />
printf("Turma de SOP: recebido SIGUSR1\n");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
// Loop eterno dormindo 1s<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Fazer no terminal:<br />
ps aux<br />
anotar o pid do processo e enviar o sinal:<br />
kill -USR1 pid<br />
<br />
===Exemplo 2:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// loop eterno que nunca é executado<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Enviar o sinal USR1 para ver o efeito. <br />
<br />
===Exemplo 3:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void prepara_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void prepara_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
prepara_contexto_ping();<br />
prepara_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// A long long wait so that we can easily issue a signal to this process<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
Exercício: Tente analisar as pilhas dos threads e verificar sob qual pilha o handler se executa.<br />
<br />
===Exercício 4:===<br />
<br />
Neste ponto associamos um timer ao handler com o apoio do sinal ALRM. Agora os threads são escalonados automaticamente.<br />
<br />
<code><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void preparar_contexto_ping(ucontext_t *pContext, char *p)<br />
{<br />
char *stack;<br />
<br />
getcontext(pContext);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
(*pContext).uc_stack.ss_sp = stack ;<br />
(*pContext).uc_stack.ss_size = STACKSIZE;<br />
(*pContext).uc_stack.ss_flags = 0;<br />
(*pContext).uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(pContext, (void*)(*f_ping), 1, p);<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping(&cPing, "ping");<br />
preparar_contexto_ping(&cPong, "pong");<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Um Exemplo de Uso "API Padrão POSIX"}}<br />
<br />
== Um Exemplo de Uso "API Padrão POSIX" ==<br />
<br />
;Referências<br />
* Referência http://man7.org/linux/man-pages/man2/mmap.2.html<br />
<br />
<br />
Crie uma função soma que receba 2 ponteiros referenciando posições na memória, criadas utilizando nmap(), de maneira que estas posições armazenem números inteiros. A função soma deverá retornar a soma dos números apontados em regiões da memória sem a utilização de nenhuma rotina da biblioteca do C, que não sejam definidas por APIs posix, para criação destas <br />
regiões na memória (malloc, alloc, calloc). Após retornar o resultado da soma os devidos ponteiros deverão ser extintos da memória.<br />
<br />
<br />
*'''Experimento 1:''' Aumente o tamanho da memória alocada até quando for possível.<br />
<br />
Qual o tamanho limite da memória que você conseguiu alocar?<br />
<br />
*'''Experimento 2:''' Mude o escopo para PROT_NONE, após executar e depurar o código explique o que aconteceu.<br />
<br />
Em sua opinião NMAP trata-se de uma syscall ou de uma API? Afinal API e syscall são a mesma coisa? Explique.<br />
<br />
<syntaxhighlight lang=cpp><br />
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);<br />
int munmap(void *addr, size_t length);<br />
<br />
addr = Valor do início do mapeamento.<br />
length = valor do tamanho da região a ser alocada.<br />
prot = especificações de proteção da região alocada (consultar http://man7.org/linux/man-pages/man2/mmap.2.html).<br />
flags = especificação do escopo e do tipo da região criada (exemplo publica ou privada, se é anônima ou não). <br />
</syntaxhighlight><br />
<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
void* meu_malloc(size_t tamanho) {<br />
void* addr = mmap(0, // addr<br />
tamanho, // len<br />
PROT_READ | PROT_WRITE, // prot<br />
MAP_ANON | MAP_PRIVATE, // flags<br />
-1, // filedes<br />
0); // off<br />
*(size_t*)addr = tamanho;<br />
return addr;<br />
}<br />
<br />
int meu_free(void* addr) {<br />
return munmap(addr - sizeof(size_t), (size_t) addr);<br />
}<br />
<br />
<br />
int soma(int *N1, int *N2){<br />
<br />
return (*N1+*N2);<br />
<br />
}<br />
<br />
<br />
int main(int argc, char* argv[]) {<br />
<br />
int* numero1 = meu_malloc(sizeof(int));<br />
int* numero2 = meu_malloc(sizeof(int)); <br />
<br />
<br />
*numero1 = 10;<br />
*numero2 = 20; <br />
<br />
int resultado = soma(numero1, numero2);<br />
<br />
printf("\n\n O resultado da soma é %d \n\n",resultado); <br />
<br />
meu_free(numero1);<br />
meu_free(numero2);<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Processos no Linux}}<br />
<br />
== Processos no Linux - Modificado por Eraldo ==<br />
<br />
<blockquote style="background: lime; border: 1px solid black; padding: 1em;"><br />
Processos no Linux<br />
</blockquote><br />
<br />
*Exercícios propostos pelo Prof.Arliones e Modificados por Eraldo<br />
<br />
<br />
[[imagem:DesenhoForkExec.png|border|650px]]<br />
<br />
<br />
;Syscall FORK<br />
<br />
* Em um terminal, execute "man fork"<br />
** 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'''.<br />
** O '''código''' dos dois processos (pai e filho) são '''idênticos''';<br />
** Os '''dados''' dos dois processos (pai e filho) são '''idênticos NO MOMENTO DA CRIAÇÃO''';<br />
** Execução do processo filho inicia na próxima instrução do programa (no retorno da chamada FORK);<br />
** Não é possível saber qual dos processos (pai ou filho) retormará a execução primeiro - isto fica a cargo do excalonador do SO;<br />
** Valores de retorno da chamada FORK:<br />
*** (-1): erro na criação do processo (ex.: memória insuficiente);<br />
*** (0): em caso de sucesso, este é o valor de retorno recebido pelo processo filho;<br />
*** (>0): em caso de sucesso, este é o valor de retorno recebido pelo processo pai;<br />
<br />
;Syscall JOIN<br />
<br />
* A syscall JOIN é implementada no POSIX pela função '''wait()'''. Execute "man wait".<br />
** Além da função '''wait()''', há também '''waitpid()''' e '''waitid()''';<br />
** 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);<br />
** A chamada wait também libera os recursos do processo filho que termina;<br />
** '''wait()''': esta função suspende a execução do processo chamador até que UM DOS SEUS FILHOS finalize;<br />
** '''waitpid()''': suspende a execução do processo chamador até que UM FILHO ESPECÍFICO finalize;<br />
<br />
;Syscall EXEC<br />
<br />
* A syscall EXEC é implementada no POSIX pela família de funções '''exec()'''. Execute "man exec".<br />
** As principais funções da família são '''execl()''', '''execlp()''' e '''execvp()''';<br />
** 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;<br />
** 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;<br />
<br />
<br />
;Exemplos POSIX utilizando fork/wait/exec<br />
<br />
*Exemplo 1: fork/wait básico<br />
<syntaxhighlight lang=c><br />
// ex1: fork/wait básico<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
printf("processo filho\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
printf("processo pai\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
arliones@socrates:~/tmp$ gcc ex1.c -o ex1 <br />
arliones@socrates:~/tmp$ ./ex1 <br />
processo filho pid: 27858 pid pai: 27857<br />
processo pai pid: 27857 pid pai: 5337<br />
arliones@socrates:~/tmp$ <br />
</syntaxhighlight><br />
<br />
* Exemplo 2: processos pai e filho compartilham código, mas não dados.<br />
<syntaxhighlight lang=c><br />
// ex2: fork/wait "compartilhando" dados<br />
// ex2: fork/wait "compartilhando" dados<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status, k=0;<br />
printf("processo %d\t antes do fork\n", getpid());<br />
pid = fork();<br />
printf("processo %d\t depois do fork\n", getpid());<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
k += 1000;<br />
printf("processo filho\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status); // espera o filho terminar<br />
k += 10;<br />
printf("processo pai\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
k += 1000;<br />
printf("FIM processo %d\t K: %d\n", getpid(), k); <br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
processo 17056 antes do fork<br />
processo 17056 depois do fork<br />
processo 17057 depois do fork<br />
processo filho pid: 17057 K: 1000 endereço K: 0x7ffd8923e318<br />
processo pai pid: 17056 K: 10 endereço K: 0x7ffd8923e318<br />
</syntaxhighlight><br />
<br />
* Modificação no código: comentar linhas 23 e 30<br />
<br />
<syntaxhighlight lang=bash><br />
<br />
</syntaxhighlight><br />
<br />
* Analise os resultados e busque entender a diferença.<br />
*Perguntas e desafios.:<br />
#Analisando os valores impressos de k pode-se dizer que os dados são compartilhados entre os dois processos?<br />
#O endereço de k impresso é o mesmo nos dois processos. ISto não contradiz a afirmação anterior?<br />
#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.<br />
<br />
<br />
;Exercício fork/wait<br />
<br />
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.<br />
<br />
*Use o comando pstree para verificar a árvore de processos criada.<br />
<br />
{{collapse top|Solução}}<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
<!--<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
--><br />
<br />
;DESAFIO: fork/wait<br />
<br />
Reimplementar o exercício anterior de criação de uma árvore de 3 processos, generalizando a criação de N processos onde N é repassado na linha de comando do programa. SUGESTÃO: usar um comando for, mas lembrar que se existe um fork dentro do for, então cada filho gerado dará continuidade a execução do for. É necessário que o processo faça um exit ou retorne neste momento.<br />
<br />
;DESAFIO: Exercício status/wait<br />
<br />
O ''status'' passado como parâmetro à função ''wait(&status)'' é, na verdade, o mecanismo de retorno de resultado do ''wait/waitpid''. Ao retornar, esta variável contém informações sobre o resultado da execução do processo filho. Por exemplo, se um processo terminou normalmente (i.e., chamou ''exit''), o comando ''WIFEXITED(status)'' retorna ''true''. Este comando retorna ''false'' se o processo foi abortado (e.g., ''segmentation fault'') ou morto (e.g., ''kill''). Investigue no manual do wait no Linux (''man wait'') o funcionamento do comando WEXITSTATUS(status). <br />
Imagine um problema de busca de dados armazenados na forma de uma matriz de inteiros 4x30. Você está interessado em saber quantas ocorrências de um determinado número existe em cada linha da matriz. Note que que são tarefas que podem ser paralelizadas e usufruir de um sistema capaz de executá-las em paralelo. Faça uma implementação paralelizando 4 processos filhos a partir de um pai, onde cada processo é responsável por uma busca. A quantidade de ocorrências do número buscado é retornada e capturada através de WEXITSTATUS.<br />
<br />
;Syscall EXEC<br />
<br />
*Exemplo exec()<br />
<br />
<syntaxhighlight lang=c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
execl("/bin/ls","ls","-l", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 1: Modificar o código para mostrar que o exec() não retorna (colocar um printf após o exec).<br />
<br />
*Exercício 2: Criar um exemplo (dois programas ) para demonstrar que o exec não cria novo processo. <br />
**Crie um primeiro programa (prog1) que imprime o seu pid e depois faz um exec do segundo programa.<br />
**Crie o segundo programa que simplesmente imprime o pid.<br />
<br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU ANTES DO EXEC: Meu pid é %d\n", getpid());<br />
execl("./prog2","prog2", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU DEPOIS DO EXEC:Meu pid é %d\n", getpid());<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 3: Criar um exemplo usando fork/exec mostrando que um processo pai cria um filho e espera por sua execução. O filho executa o comando "ps aux". Ambos devem mostrar seus pids.<br />
<br />
{{collapse bottom}} <br />
{{collapse top| bg=lightyellow | expandir=true | Threads de aplicação}}<br />
<br />
== Threads de aplicação ==<br />
<br />
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:<br />
*'''getcontext(&a)''': salva o contexto na variável '''a''';<br />
*'''setcontext(&a)''': restaura um contexto salvo anteriormente na variável '''a''';<br />
*'''swapcontext(&a,&b)''': salva o contexto atual na variável '''a''' e restaura o contexto salvo anteriormente na variável '''b''';<br />
*'''makecontext(&a, ...)''': ajusta parâmetros internos do contexto salvo em '''a''';<br />
*'''ucontext_t''': as variáveis '''a''' e '''b''' são do tipo '''ucontext_t'''. Este tipo armazena um contexto.<br />
<br />
Busque mais informações sobre estas funções utilizando o programa manpage do Linux (ex.: man getcontext).<br />
<br />
Estude o código no arquivo pingpong.c abaixo e explique seu funcionamento.<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
*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.<br />
*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.<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain, cFnew;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_new(void * arg1, void * arg2,void * arg3,void * arg4) <br />
{<br />
printf ("%s: Primeira string %s %s %s\n",(char*) arg1,(char*) arg2,(char*) arg3, (char*) arg4);<br />
swapcontext(&cFnew, &cMain); <br />
}<br />
<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
<br />
getcontext(&cFnew);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cFnew.uc_stack.ss_sp = stack ;<br />
cFnew.uc_stack.ss_size = STACKSIZE;<br />
cFnew.uc_stack.ss_flags = 0;<br />
cFnew.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cFnew, (void*)(*f_new), 4, "\tF_new", "\tAlo", "\tMundo","\tReal");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
swapcontext(&cMain, &cFnew);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
--><br />
Exercício 3: O que acontece se um dos threads é colocado para dormir? Todos os demais threads param a sua execução.<br />
<br />
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/<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Trocas de mensagens com pipes}}<br />
<br />
== Trocas de mensagens com pipes ==<br />
<br />
;Troca de mensagens<br />
Um mecanismo disponibilizado por sistemas UNIX para troca de mensagens entre processos é o PIPE. Pipes são mecanismos de comunicação indireta onde mensagens são trocadas através de ''mailboxes''. Cada ''mailbox'' possui um identificador único, permitindo que processos identifiquem o canal de comunicação entre eles. O fluxo de mensagens em um Pipe é:<br />
*'''unidirecional''': sobre um mesmo pipe, apenas um processo envia mensagens e um processo recebe mensagens;<br />
*'''FIFO''': as mensagens são entregues na ordem de envio;<br />
*'''não-estruturado''': não há estrutura pré-definida para o formato da mensagem.<br />
No UNIX, pipes são inicializados através da '''SystemCall''' ''pipe'', que possui a seguinte sintaxe:<br />
*''int pipe(int pipefd[2])'': ''pipe'' inicializa um novo pipe no sistema e retorna, no array pipefd, os descritores identificando cada uma das pontas do pipe. A primeira posição do array, i.e. pipefd[0], recebe o descritor que pode ser aberto apenas para leitura, enquanto a segunda posição do array, i.e. pipefd[1], recebe o descritor que pode ser aberto apenas para escrita. A função retorna zero no caso de sucesso, ou -1 se ocorrer erro.<br />
As primitivas send/receive para uso de um pipe no UNIX são implementadas por '''SystemCalls''' read/write, conforme segue:<br />
*''ssize_t read(int fd, void *buf, size_t count)'': “puxa” dados do pipe identificado pelo descritor fd. Os dados recebidos são os apontados pelo ponteiro buf, sendo count a quantidade máxima de bytes a serem recebidos. A função retorna o número de bytes recebidos.<br />
*''ssize_t write(int fd, const void *buf, size_t count)'': “empurra” dados no pipe identificado pelo descritor fd. Os dados transmitidos são os apontados pelo ponteiro buf, sendo count a quantidade de bytes a serem transmitidos. A função retorna o número de bytes transmitidos.<br />
<br />
*Exemplo 1: Transmitindo e recebendo pelo próprio processo<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main()<br />
{<br />
int fd[2];<br />
char *ptr = "Alo eu mesmo";<br />
char *ptr_alvo;<br />
int tamanho_dados, ret;<br />
<br />
tamanho_dados = strlen(ptr)+1;<br />
<br />
if (pipe(fd)==-1){<br />
printf ("erro criação pipe\n");<br />
exit(-1);<br />
}<br />
printf("Transmitido %d bytes\n", tamanho_dados);<br />
write (fd[1], ptr, tamanho_dados);<br />
<br />
ptr_alvo = malloc(tamanho_dados);<br />
<br />
ret=read(fd[0],ptr_alvo,tamanho_dados);<br />
<br />
printf("ret = %d dados => %s\n", ret, ptr_alvo); <br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
*Exemplo 2: Abaixo há um exemplo de programa criando um pipe e compartilhando os descritores entre dois processos (criados via ''fork()'').<br />
<syntaxhighlight lang=c><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
<br />
char *message = "This is a message!!!" ;<br />
<br />
main()<br />
{<br />
char buf[1024] ;<br />
int fd[2];<br />
pipe(fd); /*create pipe*/<br />
if (fork() != 0) { /* I am the parent */<br />
write(fd[1], message, strlen (message) + 1) ;<br />
}<br />
else { /*Child code */<br />
read(fd[0], buf, 1024) ;<br />
printf("Got this from MaMa!!: %s\n", buf) ;<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
*'''Exercício 1: construa um “pipeline”'''. Crie um programa que conecta 4 processos através de 3 pipes. Utilize ''fork()'' para criar vários processos.<br />
<br />
<syntaxhighlight lang=cpp><br />
<br />
//Solução possível<br />
<br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
pipe(fd);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
<br />
</syntaxhighlight><br />
<br />
*'''Exercício 3: Modifique o exercício anterior para que o processo D, através de um novo pipe, mande uma mensagem diretamente para o pai de todos.<br />
<br />
<!--<br />
<code><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
int fd_retorno[2];<br />
<br />
pipe(fd);<br />
pipe(fd_retorno);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size);<br />
read(fd_retorno[0], buf, size);<br />
printf("PAI:%s\n", buf); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
char *ptr_msg_ret="Ok msg de D para o pai";<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
write(fd_retorno[1],ptr_msg_ret,strlen(ptr_msg_ret)+1);<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
*'''Exercício 3: Consultor de Login de Acesso:'''. Estude o link https://www.geeksforgeeks.org/named-pipe-fifo-example-c-program/ e projete um programa cliente servidor da seguinte forma: (i) O servidor possui uma tabela de usuários (userid). O user_id é de tamanho fixo de 7 caracteres. O servidor espera por consultas para verificar se um usuário está na tabela. Se estiver responde com o caracter 'S' senão com 'N'. (ii) O cliente espera por user_id no teclado e consulta o servidor sobre sua existência na tabela. O cliente imprime na tabela a existência ou não do usuário.<br />
<br />
*'''Exercício 4: cópia de arquivo'''. Projete um programa de cópia de arquivos chamado FileCopy usando pipes comuns. Esse programa receberá dois parâmetros: o primeiro é o nome do arquivo a ser copiado e o segundo é o nome do arquivo copiado. Em seguida, o programa criará um pipe comum e gravará nele o conteúdo do arquivo a ser copiado. O processo filho lerá esse arquivo do pipe e o gravará no arquivo de destino. Por exemplo, se chamarmos o programa como descrito a seguir:<br />
:<syntaxhighlight lang=bash><br />
$ FileCopy entrada.txt copia.txt<br />
</syntaxhighlight><br />
:o arquivo ''entrada.txt'' será gravado no pipe. O processo filho lerá o conteúdo desse arquivo e o gravará no arquivo de destino ''copia.txt''. Escreva o programa usando os pipes da API POSIX no Linux.<br />
<br />
<br />
{{collapse bottom}}<br />
<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Exercícios sobre Memória Compartilhada}}<br />
<br />
==SHARED MEMORY: Produtor (pai) - Consumidor (filho) - ==<br />
<br />
<!-- Parou aki 20/08<br />
<br />
<br />
*'''Experimento 2:''' Complete o código a seguir para que os processos pai e filho possam compartilhar um segmento de memória. O filho escreve no segmento e o pai imprime na tela o conteúdo da mensagem.<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
char *ptr_msg = "alo pai, tudo bem?"; <br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
//completar aqui<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
<!--<br />
<code><br />
<br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/types.h><br />
#include <string.h><br />
#include <stdlib.h><br />
<br />
int main(void)<br />
{<br />
int fd[2], pipe_ret, filho;<br />
char string[] = "Hello, pipe!\n";<br />
char buffer[20];<br />
<br />
pipe(fd);<br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
/*Mandar string para a extremidade do pipe*/<br />
write(fd[1], string, (strlen(string)+1));<br />
exit(0);<br />
}<br />
else<br />
{<br />
<br />
/* Read in a string from the pipe */<br />
pipe_ret = read(fd[0], buffer, (20*sizeof(char)));<br />
printf("Recebi este texto %s", buffer);<br />
}<br />
<br />
return(0);<br />
}<br />
<br />
<br />
<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
key = ftok("teste_sh.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644 | IPC_CREAT));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
<br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
strncpy(segmento, "mensagem compartilhada", SHM_SIZE); <br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
--><br />
<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Memória Compartilhada}}<br />
*'''Experimento Shared Memory:''' Complete o código a seguir para que os processos pai e filho possam compartilhar um segmento de memória. O filho escreve no segmento e o pai imprime na tela o conteúdo da mensagem.<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
char *ptr_msg = "alo pai, tudo bem?"; <br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
//completar aqui strcpy(segmento, ptr_msg); //aqui deveria testar a cpacidade da área...<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exemplo com ftok:<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
key = ftok("./teste.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644 | IPC_CREAT));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
<br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
strncpy(segmento, "mensagem compartilhada", SHM_SIZE); <br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exemplo com ftok entre processos sem parentesco:<br />
<br />
Criar um arquivo teste.txt e em um terminal executar:<br />
<br />
<syntaxhighlight lang=c><br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
int modo,filho;<br />
<br />
struct minha_struct {<br />
char flag;<br />
int numero;<br />
} *ptr;<br />
<br />
<br />
key = ftok("./teste.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644 | IPC_CREAT));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
ptr = (struct minha_struct *) shmat(shmid, (void *)0, 0);<br />
if ((char *)ptr == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
ptr->flag =0;<br />
ptr->numero = 0;<br />
while (ptr->flag==0) { <br />
printf("%d\n", ptr->numero);<br />
sleep(1);<br />
} <br />
<br />
if (shmdt(ptr) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Em outro terminal executar:<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
struct minha_struct {<br />
char flag;<br />
int numero;<br />
} *ptr;<br />
<br />
<br />
key = ftok("./teste.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
ptr = (struct minha_struct *) shmat(shmid, (void *)0, 0);<br />
if ((char *)ptr == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
<br />
<br />
while (ptr->numero++<10)<br />
sleep(1);<br />
<br />
ptr->flag = 1;<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Exercício Desafio: Implementar o problema do buffer circular usando memória compartilhada.<br />
<br />
{{collapse bottom}}<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Exercício (Algoritmo de Peterson)}}<br />
<br />
== Exercício (Algoritmo de Peterson) ==<br />
<br />
<br />
'''Exercício 1''': Sincronize o código a seguir, de maneira que o processo pai imprima apenas os números impares e o processo filho os números pares. Para isso utilize o algoritmo de '''Peterson''' visto em aula. '''Utilize memória compartilhada''' para comunicação entre os processos.<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
main()<br />
{ <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int i; <br />
<br />
for(i = 0;i < 10;i=i+2){ <br />
printf("Processo pai %d \n", i); <br />
<br />
} <br />
<br />
<br />
}<br />
<br />
else { /*Child code */<br />
int i; <br />
for(i = 1;i < 10;i=i+2){ <br />
printf("Processo filho %d \n", i); <br />
<br />
}<br />
<br />
<br />
}<br />
<br />
exit(0);<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
'''Exercício 2''': Considerando o exercício anterior faça a mesma sincronização, no entanto desta vez utilize a modelagem em software do TSL. <br />
* Em sua experiência, depois de testar diversas vezes as execuções de suas soluções baseadas no algoritmo de '''Peterson''' e '''Tsl''', qual sua opinião sobre as abordagens?<br />
Explique seu raciocínio. <br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Exercício (Semáforos)}}<br />
== Exercício (Semáforos) ==<br />
<br />
<br />
'''Exercício 1''': Sincronize o código a seguir, de maneira que o processo pai imprima apenas os números impares e o processo filho os números pares. Para isso utilize '''Semáforos''' de acordo com a implementação em '''semaforo.h'''. '''Utilize memória compartilhada''' para comunicação entre os processos.<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
main()<br />
{ <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int i; <br />
<br />
for(i = 0;i < 10;i=i+2){ <br />
printf("Processo pai %d \n", i); <br />
sleep(1);<br />
<br />
} <br />
<br />
<br />
}<br />
<br />
else { /*Child code */<br />
int i; <br />
for(i = 1;i < 10;i=i+2){ <br />
printf("Processo filho %d \n", i); <br />
<br />
}<br />
<br />
<br />
}<br />
<br />
exit(0);<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
SEMAFORO.H<br />
<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <sys/sem.h><br />
<br />
<br />
int criar_semaforo(int val, int chave) <br />
{<br />
int semid ;<br />
<br />
union semun {<br />
int val;<br />
struct semid_ds *buf ;<br />
ushort array[1];<br />
} arg_ctl ;<br />
<br />
key_t ft = ftok("/tmp", chave);<br />
<br />
semid = semget(ft,1,IPC_CREAT|IPC_EXCL|0666);<br />
if (semid == -1) {<br />
semid = semget(ft,1,0666); <br />
if (semid == -1) {<br />
perror("Erro semget()");<br />
exit(1) ;<br />
}<br />
}<br />
<br />
arg_ctl.val = val; //valor de início<br />
if (semctl(semid,0,SETVAL,arg_ctl) == -1) {<br />
perror("Erro inicializacao semaforo");<br />
exit(1);<br />
}<br />
return(semid) ;<br />
}<br />
<br />
void P(int semid){<br />
<br />
struct sembuf *sops = malloc(10*sizeof(int));<br />
sops->sem_num = 0;<br />
sops->sem_op = -1;<br />
sops->sem_flg = 0;<br />
semop(semid, sops, 1); <br />
free(sops);<br />
<br />
}<br />
<br />
<br />
void V(int semid){<br />
<br />
struct sembuf *sops = malloc(10*sizeof(int));<br />
sops->sem_num = 0;<br />
sops->sem_op = 1;<br />
sops->sem_flg = 0; <br />
semop(semid, sops, 1); <br />
free(sops);<br />
<br />
} <br />
<br />
<br />
<br />
void sem_delete(int semid) <br />
{<br />
<br />
if (semctl(semid,0,IPC_RMID,0) == -1)<br />
perror("Erro na destruicao do semaforo");<br />
}<br />
<br />
<br />
<br />
<br />
</syntaxhighlight><br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Programação concorrente}}<br />
<br />
== Programação concorrente ==<br />
<br />
;POSIX Threads<br />
A 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):<br />
*''pthread_create'': cria uma thread;<br />
*''pthread_kill'': força a terminação de uma thread;<br />
*''pthread_join'': sincroniza o final de uma thread (qual a diferença/semelhança com o ''wait'' que usamos para processos?);<br />
*''pthread_exit'': finaliza uma thread.<br />
Para utilizar estas funções é necessário linkar o programa à libpthread (''-lpthread''). <br />
<br />
<br />
;POSIX pthread mutex<br />
<br />
A biblioteca pthread implementa um tipo ''pthread_mutex_t'', que garante a exclusão mútua entre threads. Estes mutex são manipulados através das funções (acesse as man-pages das chamadas para maiores detalhes):<br />
*''pthread_mutex_lock'': acessa um mutex.<br />
*''pthread_mutex_trylock'': tenta acessar um mutex (retorna valor indicando sucesso ou falha no lock).<br />
*''pthread_mutex_unlock'': libera um mutex.<br />
<br />
<br />
<br />
<br />
;POSIX Semaphores<br />
<br />
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):<br />
*''sem_init'': inicializa um semáforo;<br />
*''sem_destroy'': destroy um semáforo;<br />
*''sem_wait'': implementa a operação ''p'';<br />
*''sem_post'': implementa a operação ''v''.<br />
Para utilizar estas funções é necessário linkar o programa à librt ou à libpthread (''-lrt'' ou ''-lpthread'').<br />
<br />
;Exercício 1<br />
<br />
O programa abaixo cria 5 threads, e cada uma destas threads atualiza uma variável global (memória compartilhada).<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include <pthread.h><br />
#include <signal.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
pthread_mutex_t mut;<br />
<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
}<br />
</syntaxhighlight><br />
<br />
# Compile este programa. <br />
# Execute este programa várias vezes. Ele funciona? Será que ele gera as saídas esperadas?<br />
# Identifique as '''seções críticas''' do programa.<br />
# Corrija o programa utilizando '''mutex'''. <br />
# Analise a função ''AtualizaSaldo()'' com a sua solução. Lembre-se que o uso do mutex implica em apenas uma thread acessar a seção crítica por vez, enquanto outras threads ficam bloqueadas, esperando. Disso vem que, quanto menor o trecho de código entre um ''lock'' e um ''unlock'', menos tempo uma thread necessita ficar esperando.<br />
# Modifique o programa para usar um semáforo binário ao invés de um mutex em sua solução.<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <cstring><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
<br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
sem_t sem;<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
int value;<br />
sem_wait(&sem);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
sem_getvalue(&sem, &value);<br />
printf("valor sem = %d\n", value);<br />
sem_post(&sem);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
sem_init(&sem,0,1);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
sem_destroy(&sem);<br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
<br />
;Exercício 2<br />
Refaça o exercício 3 usando processos criados com fork e exec. O semáforo deve ser criado em uma região de memória compartilhada.<br />
<br />
;Exercício 3<br />
Implemente com pthreads e semáforos/mutex a solução do produtor/comsumidor.<br />
<br />
;Exercício 4<br />
<br />
O programa abaixo manipula uma matriz de tamanho MxN (veja os defines para o tamanho da matriz). A função ''SumValues'' soma todos os valores em uma linha da matriz. A linha a ser somada é identificada pela variável ''i''. Modifique o programa principal (''main'') nos locais indicados para:<br />
# Criar N threads, uma para somar os valores de cada linha.<br />
# Receber o resultado do somatório de cada linha e gerar o somatório total da matriz.<br />
# Analise o programa: há problemas de sincronização que precisam ser resolvidos? Se sim, resolva-os.<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include "thread.h"<br />
<br />
/* number of matrix columns and rows */<br />
#define M 5<br />
#define N 10<br />
<br />
using namespace std;<br />
<br />
int matrix[N][M];<br />
Thread *threads[N];<br />
<br />
<br />
/* thread function; it sums the values of the matrix in the row */<br />
int SumValues(int i)<br />
{<br />
int n = i; /* number of row */<br />
int total = 0; /* the total of the values in the row */<br />
int j;<br />
for (j = 0; j < M; j++) /* sum values in the "n" row */<br />
total += matrix[n][j];<br />
cout << "The total in row" << n << " is " << total << "." << endl;<br />
/* terminate a thread and return a total in the row */<br />
exit(total);<br />
}<br />
<br />
int main(int argc, char *argv[])<br />
{<br />
int i, j;<br />
int total = 0; /* the total of the values in the matrix */<br />
<br />
/* initialize the matrix */<br />
for (i = 0; i < N; i++)<br />
for (j = 0; j < M; j++)<br />
matrix[i][j] = i * M + j;<br />
<br />
/* create threads */<br />
/* COLOQUE SEU CÓDIGO PARA CRIAR AS THREADS AQUI! */<br />
<br />
/* wait for terminate a threads */<br />
/* COLOQUE SEU CÓDIGO PARA PEGAR O SOMATÓRIO DE LINHAS E TOTALIZAR A SOMA DA MATRIZ AQUI! */<br />
<br />
cout << "The total values in the matrix is " << total << endl;<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Lista de exercícios "Revisão para Prova" }}<br />
<br />
== Lista de exercícios/Revisão para Prova ==<br />
<br />
A lista de exercícios referente a primeira prova (Parte introdutória + Processos) segue neste LINK [http://docente.ifsc.edu.br/andre.damato/sop2018/lista_rev1.pdf | Lista de exercícios]. <br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Primeiro trabalho}}<br />
== JOGO DA VIDA DE CONWAY e JANTAR DOS FILÓSOFOS==<br />
<br />
;Referências<br />
<br />
* [https://www.open-mpi.org/doc/current/ MPI]<br />
<br />
* [https://quark.phy.bnl.gov/~creutz/qcdoc/mpi/mpi.h Tipos de dados MPI]<br />
<br />
* [https://pt.wikipedia.org/wiki/Jogo_da_vida Jogo da Vida]<br />
<br />
<br />
<br />
<br />
A partir da implementação sequencial do Game of Life apresentada a seguir, estude o código e transforme esta implementação em uma implementação paralela utilizando o protocolo de passagem de mensagens MPI.<br />
Perceba que a impĺementação mencionada utiliza como parâmetros de entrada um aquivo contendo o estado inicial do jogo, e o número de gerações que o usuário deseja rodar. A evolução do estado inicial <br />
é impressa na tela passo a passo. Sendo assim, a partir disso:<br />
<br />
*'''1: Elabore uma implementação com 2 processos para o jogo da vida utilizando o protocolo MPI, de maneira que um processo execute uma geração i qualquer e o outro execute a geração seguinte i+1''' <br />
<br />
*'''2: (0,7) Os processos deverão se comunicar utilizando as funções do protocolo MPI.''' <br />
<br />
*'''3: (0,3) Relatório simplificado explicando a sua solução. Utilize diagramas para representar a comunicação entre os processos, explicando como a matriz do jogo é transferida entre os processos. ''' <br />
<br />
*'''4: Entregue o Relatório e o código fonte do trabalho em um pacote compactado via e-mail (PRAZO 19/10). <br />
<br />
<br />
<br />
* ''' Compilar o código com MPI '''<br />
<code><br />
mpicc -o nomeApp arquivo.c<br />
</syntaxhighlight><br />
<br />
* ''' Rodar rodar programa utilizando MPI '''<br />
<code><br />
mpirun -np numeroDeProcessos ./nomeApp entrada.txt gerações<br />
</syntaxhighlight><br />
<br />
* (int) -np: Quantidade de processos que você deseja executar <br />
<br />
* entrada.txt: Arquivo de entrada com estado inicial do jogo <br />
<br />
* (int) gerações: número de gerações que você deseja rodar<br />
<br />
* [http://docente.ifsc.edu.br/andre.damato/sop2018/entrada.txt Arquivo de entrada para Testes]<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
<br />
<br />
<br />
/*<br />
<br />
Conway's Game of Life<br />
<br />
Compilar código com MPI<br />
mpicc -o nomeApp arquivo.c<br />
<br />
<br />
Rodar rodar programa utilizando MPI<br />
<br />
mpirun -np numeroDeProcessos ./nomeApp entrada.txt gerações<br />
<br />
(int) -np: Quantidade de processos que você deseja executar <br />
entrada.txt: Arquivo de entrada com estado inicial do jogo <br />
(int) gerações: número de gerações que você deseja rodar<br />
<br />
<br />
*/<br />
<br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h><br />
#include "mpi.h"<br />
<br />
<br />
//Numero de linhas e colunas<br />
#define nLinhas 32<br />
#define nColunas 82 <br />
<br />
char *matriz[nLinhas];<br />
char *entrada[nLinhas];<br />
<br />
<br />
void iniciar() {<br />
<br />
int i;<br />
<br />
//Alocar espaço em memória para as matrizes<br />
for (i = 0; i < nLinhas; i++ ) <br />
matriz[i] = (char *) malloc((nColunas) * sizeof( char )); <br />
<br />
<br />
}<br />
<br />
int adjacente(char **matriz, int i, int j){<br />
<br />
int x,y, initX, initY, limitX, limitY;<br />
int vizinhos = 0;<br />
<br />
if(i == 0)<br />
initX = 0;<br />
else <br />
initX = -1;<br />
<br />
if(i == (nLinhas-1)) <br />
limitX = 1;<br />
else<br />
limitX = 2;<br />
<br />
<br />
if(y == 0)<br />
initY = 0;<br />
else <br />
initY = -1;<br />
<br />
if(y == (nColunas-3)) <br />
limitY = 1;<br />
else<br />
limitY = 2;<br />
<br />
for(x = initX ; x < limitX; x++){<br />
for(y = initY; y < limitY; y++){<br />
if(matriz[i+x][j+y] == '#') <br />
vizinhos++; <br />
} <br />
}<br />
<br />
<br />
if(matriz[i][j] == '#') <br />
return (vizinhos-1);<br />
else <br />
return vizinhos;<br />
<br />
}<br />
<br />
<br />
void calculoGeracao(char **matriz, int ger) {<br />
<br />
int i, j, a;<br />
char novaGeracao[nLinhas][nColunas];<br />
<br />
/* Aplicando as regras do jogo da vida */<br />
for (i=0; i < nLinhas; i++){ <br />
for (j=0; j < nColunas; j++) {<br />
<br />
a = adjacente(matriz, i, j);<br />
<br />
if (a == 2) novaGeracao[i][j] = matriz[i][j];<br />
if (a == 3) novaGeracao[i][j] = '#';<br />
if (a < 2) novaGeracao[i][j] = ' ';<br />
if (a > 3) novaGeracao[i][j] = ' ';<br />
<br />
if (j == 0)<br />
novaGeracao[i][j] = '"';<br />
} <br />
<br />
novaGeracao[i][79] = '"';<br />
novaGeracao[i][80] = '\n';<br />
<br />
<br />
}<br />
<br />
/* Passando o resultado da nova geração para a matriz de entrada */<br />
for (i=0; i < nLinhas; i++){ <br />
for (j=0; j < nColunas; j++) <br />
matriz[i][j] = novaGeracao[i][j];<br />
}<br />
}<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
main(int argc, char *argv[2]){<br />
<br />
/* Para uso com MPI<br />
<br />
<br />
//Variáveis para uso com MPI<br />
int numeroDeProcessos = 0;<br />
int rank = 0;<br />
MPI_Status status; <br />
<br />
//Iniciar MPI---<br />
MPI_Init( &argc, &argv );<br />
<br />
//Atribui a variável numeroDeProcessos o número de processos passado como parâmetro em -np <br />
MPI_Comm_size( MPI_COMM_WORLD, &numeroDeProcessos );<br />
<br />
//Pega o valor do rank (processo)<br />
MPI_Comm_rank( MPI_COMM_WORLD, &rank );<br />
*/<br />
<br />
<br />
FILE *matrizEntrada;<br />
matrizEntrada = fopen(argv[1], "r");<br />
iniciar();<br />
<br />
<br />
if (matrizEntrada == NULL)<br />
printf ("Não posso abrir o arquivo \"%s\"\n", argv[1]);<br />
<br />
<br />
char str[nColunas];<br />
int linha = 0;<br />
<br />
<br />
<br />
//Lendo o estado inicial do jogo a partir do arquivo<br />
while((fgets(str, nColunas, matrizEntrada) != NULL)&&(linha < nLinhas)){<br />
strcat(matriz[linha], str);<br />
linha++;<br />
}<br />
<br />
int i,gens; <br />
<br />
<br />
for(gens = 0; gens < atoi(argv[2]); gens++){ //Gens é o número de gerações especificado no segundo parâmetro <br />
<br />
calculoGeracao(matriz, gens);<br />
printf("%c[2J",27); // Esta linha serve para limpar a tela antes de imprimir o resultado de uma geração <br />
<br />
//Lendo o estado do jogo e imprime na tela <br />
for(i = 0; i < nLinhas; i++)<br />
printf("%s", matriz[i]); <br />
<br />
sleep(1);<br />
<br />
}<br />
<br />
<br />
for(i = 0; i < nLinhas; i++) <br />
free(matriz[i]); <br />
<br />
<br />
<br />
/* Finaliza o MPI */ <br />
//MPI_Finalize();<br />
<br />
exit(0);<br />
} <br />
<br />
<br />
</syntaxhighlight><br />
<br />
<br />
;Jantar dos Filósofos<br />
O problema clássico Jantar dos Filósofos consiste em que n fluxos (n filósofos) disputam n recursos (n talheres). No problema, para conseguir "jantar" (ou executar), cada filósofo precisa pegar dois talheres adjascentes a ele. Cada recurso é compartilhado por dois filósofos.<br />
*[http://www.doc.ic.ac.uk/~jnm/concurrency/classes/Diners/Diners.html Veja esta simulação]<br />
*[http://en.wikipedia.org/wiki/Dining_philosophers_problem Veja esta descrição do problema]<br />
<br />
<br />
* ''' (0,7) programa abaixo implementa um Jantar dos Filósofos utilizando semáforos para sincronização. Contudo, as chamadas para as operações ''v'' e ''p'' foram removidas, conforme comentários no código. Re-insira as operações no código e analise a solução. Esta modificação é suficiente para garantir que não haverá deadlock? Se sim, mostre o porque. Se não, proponha uma solução completa. '''<br />
<br />
<br />
*''' (0,3) Relatório simplificado explicando a sua solução. ''' <br />
<br />
*''' Entregue o Relatório e o código fonte do trabalho em um pacote compactado via e-mail (PRAZO 19/10). <br />
<br />
<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include "thread.h"<br />
#include "semaphore.h"<br />
<br />
using namespace std;<br />
<br />
const int DELAY = 10000000;<br />
const int ITERATIONS = 5;<br />
<br />
Semaphore chopstick[5];<br />
<br />
int philosopher(int n)<br />
{<br />
cout << "Philosopher " << n << " was born!\n";<br />
<br />
int first = (n < 4)? n : 0; // left for phil 0 .. 3, right for phil 4<br />
int second = (n < 4)? n + 1 : 4; // right for phil 0 .. 3, left for phil 4<br />
<br />
// Foram removidos do laço abaixo:<br />
// - uma chamada para chopstick[first].p()<br />
// - uma chamada para chopstick[second].p()<br />
// - uma chamada para chopstick[first].v()<br />
// - uma chamada para chopstick[second].v()<br />
for(int i = 0; i < ITERATIONS; i++) {<br />
cout << "Philosopher " << n << " thinking ...\n";<br />
for(int i = 0; i < DELAY * 10; i++);<br />
<br />
cout << "Philosopher " << n << " eating ...\n";<br />
for(int i = 0; i < DELAY; i++);<br />
}<br />
<br />
return n;<br />
}<br />
<br />
int main()<br />
{<br />
cout << "The Dining-Philosophers Problem\n";<br />
<br />
Thread * phil[5];<br />
for(int i = 0; i < 5; i++)<br />
phil[i] = new Thread(&philosopher, i);<br />
<br />
int status;<br />
for(int i = 0; i < 5; i++) {<br />
phil[i]->join(&status);<br />
if(status == i)<br />
cout << "Philosopher " << i << " went to heaven!\n";<br />
else<br />
cout << "Philosopher " << i << " went to hell!\n";<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Softwares básicos, caso Hello Word! (Trabalho 2) Entrega dia 09/11}}<br />
<br />
== Softwares básicos, caso Hello Word! ==<br />
<br />
O objetivo do experimento de hoje é pesquisar e entender os processos de atribuição de endereços de programas realizados em tempo de compilação pelos softwares básicos como: compilador, linker, e assembler. Sendo assim, neste experimento vamos utilizar os seguintes softwares para criação e análise de código:<br />
<br />
*'''GCC''': compilador para gerar código objeto a partir de um código de programa escrito na linguagem c;<br />
*'''GNU Linker (LD)''': Para vincular os códigos (módulos) objetos do programa;<br />
*[https://linux.die.net/man/1/ld| Linker ] <br />
*'''GNU Assembler''': Para gerar o código executável a partir do código objeto;<br />
*[https://linux.die.net/man/1/as | assembler]<br />
* '''OBJDUMP''': Para mostrar informações do código;<br />
*[https://linux.die.net/man/1/objdump | Objdump ]<br />
<br />
<br />
A seguir segue descrito o programa a ser utilizado no exercício 1:<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
int main()<br />
{<br />
printf("Hello, World!");<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
Trata-se do programa hello word, este programa apenas exibe uma mensagem na tela. No entanto, vamos analisar como são as etapas confecção do executável a partir deste código ''simples''. <br />
<br />
Exercício 1: <br />
* Compile o programa hello word, e o transforme em código objeto utilizando o programa GCC. Para esta tarefa execute o seguinte comando:<br />
<code><br />
gcc -o hello hello.c <br />
</syntaxhighlight><br />
* Agora abra o código objeto utilizando o programa OBJDUMP.<br />
<code><br />
objdump -D hello<br />
</syntaxhighlight><br />
* Identifique quais são as seções de código obtidas a partir do '''hello.c'''.<br />
* Pesquise e entenda o significado das seções de código: .bss, .txt, .data, .init.<br />
* Faça uma análise e identifique o endereço de memória que o programa ''hello world'' vai ser carregado. <br />
* Este código objeto é relocável? Justifique sua resposta.<br />
* Agora gere o código assembly do hello world.<br />
<code><br />
gcc -S hello.c<br />
</syntaxhighlight> <br />
*Agora gere o código executável utilizando o programa '''AS''' e o programa '''LD'''.<br />
<code><br />
as -o hello.o hello.s<br />
</syntaxhighlight><br />
* Como a etapa de linkagem para a construção do código executável está sendo executada sem o auxílio do '''GCC''', necessitamos vincular manualmente as bibliotecas necessárias. Para criar apropriadamente o executável vamos precisar das bibliotecas '''ld-linux-x86-64.so.2''', '''crt1.o''', '''crti.o''', '''crtn.o'''.<br />
* Para descobrir suas respectivas localizações use o comando '''LOCATE'''. Por exemplo:<br />
<code><br />
<br />
locate crti.o <br />
<br />
</syntaxhighlight><br />
<br />
ou <br />
<br />
<code><br />
<br />
find /usr/ -name crti*<br />
<br />
</syntaxhighlight><br />
<br />
* Agora que já sabemos a localização das bibliotecas necessárias vamos vincular essas a nossa aplicação.<br />
<code><br />
ld --dynamic-linker /caminho/ld-linux-x86-64.so.2 /caminho/crt1.o /caminho/crti.o /caminho/crtn.o hello.o -lc -o hello.exe<br />
</syntaxhighlight><br />
<br />
* Agora abra o código objeto utilizando o programa OBJDUMP.<br />
* Faça uma análise e identifique o endereço de memória em que o programa ''hello world'' inicializa suas estruturas na memória.<br />
* Dica!<br />
<code><br />
objdump -D -s -j .init hello.exe<br />
</syntaxhighlight><br />
* Houve diferença entre os endereços do programa executável em relação ao código objeto? Explique.<br />
* Explique as principais diferenças entre o arquivo objeto .o e o executável final. (dica utilize o objdump para fazer essa análise)<br />
{{collapse bottom}}<br />
<ol><br />
<li> Estudar e executar o código em http://cs.lmu.edu/~ray/notes/gasexamples/ <br />
Detalhes das chamadas na arquitetura x86_64 ver em https://lwn.net/Articles/604287/ <br />
<li>Estudar e executar o código usando a função (em conformidade com a API POSIX) write() para o ''hello world'':<br />
<code><br />
#include <unistd.h> <br />
<br />
main()<br />
{<br />
write(1,"Alo Mundo\n",10);<br />
}<br />
</syntaxhighlight><br />
</li><br />
<li> Use o comando strace para verificar todas as chamadas de sistema dos programas acima.<br />
</li><br />
<li><br />
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:<br />
<code><br />
main()<br />
{<br />
meu_hello_world();<br />
}<br />
</syntaxhighlight><br />
</li><br />
Gere o assembly do código em C e discuta a diferença entre uma chamada de função e uma chamada de sistema.<br />
<li><br />
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:<br />
<code><br />
#include <string.h><br />
main()<br />
{<br />
char *p="Tudo bem com vocês?";<br />
meu_hello_world(p, strlen(p));<br />
}<br />
</syntaxhighlight><br />
Solução:<br />
{{collapse top|Solução}}<br />
<code><br />
modificado de http://cs.lmu.edu/~ray/notes/gasexamples/<br />
.global meu_hello_world<br />
<br />
.text<br />
meu_hello_world:<br />
<br />
push %rdi # salva primeiro parâmetro<br />
push %rsi # salva segundo parâmetro<br />
mov $1, %rax # system call 1 é write<br />
mov $1, %rdi # file handle 1 é stdout<br />
mov $message, %rsi # endereço da string<br />
mov $13, %rdx # número de bytes da string<br />
syscall # chamada ao sistema<br />
<br />
pop %rdx # o que havia sido passado em rsi (número de bytes) é colocado em rdx<br />
pop %rsi # o que havia sido colocado em rdi (endereço da string) é colocado em rsi<br />
mov $1, %rax # system call 1 is write<br />
mov $1, %rdi # file handle 1 é stdout<br />
syscall # nova chamada ao sistema<br />
<br />
ret<br />
<br />
message:<br />
.ascii "Hello, World\n"<br />
</syntaxhighlight><br />
</li><br />
</ol><br />
{{collapse bottom}}</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=SOP29005-2019-2&diff=162029SOP29005-2019-22019-10-04T12:02:51Z<p>127.0.0.1: /* Desafio */</p>
<hr />
<div>=AULA 1 - Dia 30/07/2019=<br />
<br />
===Objetivos/Conteúdos===<br />
<br />
*Apresentação do Plano de Ensino<br />
**Objetivos e Conteúdo Programático da Disciplina (ver SIGAA)<br />
**Forma de Avaliação (ver SIGAA)<br />
<br />
*Introdução a Sistemas Operacionais (Cap1. do Silberschatz)<br />
**O que faz um sistema operacional (1.1)<br />
**Organização e Arquitetura de um Sistema Computacional (1.2 e 1.3)<br />
***Importância da Interrupção e Timers (1.2.1)<br />
***Estrutura de Armazenamento (1.2.2)<br />
***Estrutura de IO (1.2.3)<br />
**Estrutura e Operações de um Sistema Operacional (1.4 e 1.5)<br />
<br />
===Material de Referência===<br />
<br />
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte1.pdf Apresentação sobre histórico visão geral e estruturas básicas de um SO]<br />
* [http://codex.cs.yale.edu/avi/os-book/OSE1/slide-dir/index.html Slides Silberschatz Oitava Edição]<br />
* [http://professor.unisinos.br/barbosa/SO/ch1br.ppt Tradução Slides Silberschatz Cap1]<br />
* [http://professor.unisinos.br/barbosa/SO/ch2br.ppt Tradução Slides Silberschatz Cap2]<br />
* [http://professor.unisinos.br/barbosa/SO/ch3br.ppt Tradução Slides Silberschatz Cap3]<br />
* [http://professor.unisinos.br/barbosa/SO/ch4br.ppt Tradução Slides Silberschatz Cap4]<br />
* [http://wiki.inf.ufpr.br/maziero/doku.php?id=so:livro_de_sistemas_operacionais Livro do Prof.Maziero]<br />
* [http://deptinfo.unice.fr/~rr/l3systres/ Université Nice Sophia Antipolis]<br />
<br />
Arliones:<br />
<br />
*[https://www.dropbox.com/s/dt80g3tml65rpmg/SOP29005-parte6.odp?dl=0]<br />
*[https://www.dropbox.com/s/7lneavq0go9kz2t/SOP29005-parte7.odp?dl=0]<br />
<br />
===Leitura Recomendada===<br />
<br />
*Cap.1 do Silberschatz principalmente:<br />
**1.1 a 1.9<br />
<br />
===Exercícios Práticos de Apoio a Aula===<br />
<br />
Na sequência. com fins motivacionais, são apresentados alguns exercícios ilustrando conceitos de processos, arquivos e permissionamento.<br />
<br />
<ol><br />
<li><br />
Comando para ver todos os processos no linux:<br />
<code><br />
$ ps aux<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Colocar 2 processos se executando no contexto de um terminal e verificar número dos processos e então "destruí-los":<br />
<code><br />
$ yes > /dev/null<br />
$ yes > /dev/null<br />
$ ps <br />
$ kill -9 <pid_yes><br />
$ kill -9 <pid_yes><br />
</syntaxhighlight><br />
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.<br />
</li><br />
<li><br />
Criar um terminal adicional<br />
<code><br />
$ xterm<br />
</syntaxhighlight><br />
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:<br />
<code><br />
$ echo Alo Terminal > /dev/pts/2<br />
$ kill -9 <pid_terminal><br />
</syntaxhighlight><br />
</li><br />
<li><br />
Comunicação entre processos:<br />
<code><br />
$ cat /etc/passwd | grep home | wc -l<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Retirando a permissão de leitura de um arquivo em nível de usuário proprietário:<br />
<code><br />
$ echo Alo Mundo > alfa.txt<br />
$ ls -l alfa.txt<br />
$ cat alfa.txt<br />
$ chmod u-r alfa.txt<br />
$ cat alfa.txt<br />
$ chmod u+r alfa.txt<br />
$ cat alfa.txt <br />
</syntaxhighlight><br />
</li><br />
</ol><br />
<br />
=AULA 2 - Dia 2/08/2019=<br />
<br />
===Objetivos/Conteúdos===<br />
<br />
*Continuação da Aula<br />
*Estruturas do Sistema Operacional (cap.2)<br />
**Serviços do Sistema Operacional (2.1)<br />
**Interfaces com Usuários (2.2)<br />
**Chamadas do Sistema (2.3)<br />
**Tipos de Chamadas de Sistema (2.4) ver Fig.2.8<br />
***Chamadas de Controle de Processos<br />
**Arquiteturas e Estruturas de Sistemas Operacionais (2.7)<br />
**Máquinas Virtuais (2.8)<br />
<br />
===Material de Referência===<br />
<br />
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte1.pdf Apresentação sobre histórico visão geral<br />
* [http://www.fil.univ-lille1.fr/~sedoglav/OS/TP.html ]<br />
<br />
===Leitura Recomendada===<br />
<br />
*Cap.2 do Silberschatz principalmente:<br />
**2.1 a 2.8<br />
<br />
===Exercícios===<br />
<br />
=AULA 3 - Dia 7/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*Continuação da aula anterior<br />
**Chamadas do Sistema (2.3)<br />
**Tipos de Chamadas de Sistema (2.4) ver Fig.2.8<br />
***Chamadas de Controle de Processos<br />
**Arquiteturas e Estruturas de Sistemas Operacionais (2.7)<br />
**Máquinas Virtuais (2.8)<br />
<br />
===Exercícios===<br />
<br />
<ol><br />
<li> Estudar e executar o código em http://cs.lmu.edu/~ray/notes/gasexamples/ <br />
Detalhes das chamadas na arquitetura x86_64 ver em https://lwn.net/Articles/604287/ <br />
<li>Estudar (usar o man) e executar o código usando a função (em conformidade com a API POSIX) write() para o ''hello world'':<br />
<code><br />
#include <unistd.h> <br />
<br />
main()<br />
{<br />
write(1,"Alo Mundo\n",10);<br />
}<br />
</syntaxhighlight><br />
</li><br />
<li> Use o comando strace para verificar todas as chamadas de sistema dos programas acima.<br />
</li><br />
<li><br />
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() 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:<br />
<code><br />
void meu_hello();<br />
<br />
int main()<br />
{<br />
meu_hello();<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
</li><br />
Gere o assembly do código em C e discuta a diferença entre uma chamada de função e uma chamada de sistema.<br />
<li><br />
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:<br />
<code><br />
#include <string.h><br />
main()<br />
{<br />
char *p="Tudo bem com vocês?";<br />
meu_hello_world(p, strlen(p));<br />
}<br />
</syntaxhighlight><br />
Solução:<br />
{{collapse top|Solução}}<br />
<code><br />
modificado de http://cs.lmu.edu/~ray/notes/gasexamples/<br />
.global meu_hello_world<br />
<br />
.text<br />
meu_hello_world:<br />
<br />
push %rdi # salva primeiro parâmetro<br />
push %rsi # salva segundo parâmetro<br />
mov $1, %rax # system call 1 é write<br />
mov $1, %rdi # file handle 1 é stdout<br />
mov $message, %rsi # endereço da string<br />
mov $13, %rdx # número de bytes da string<br />
syscall # chamada ao sistema<br />
<br />
pop %rdx # o que havia sido passado em rsi (número de bytes) é colocado em rdx<br />
pop %rsi # o que havia sido colocado em rdi (endereço da string) é colocado em rsi<br />
mov $1, %rax # system call 1 is write<br />
mov $1, %rdi # file handle 1 é stdout<br />
syscall # nova chamada ao sistema<br />
<br />
ret<br />
<br />
message:<br />
.ascii "Hello, World\n"<br />
</syntaxhighlight><br />
</li><br />
</ol><br />
{{collapse bottom}}<br />
<br />
=AULA 4 - Dia 9/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*PARTE 2A: Gerenciamento de Processos (cap.3)<br />
*3.1.Conceito de Processo<br />
*3.2.Escalonamento de Processos<br />
*3.3.Operações sobre Processos (Laboratório Operações sobre Processos no Linux: Fork/Exec/Wait)<br />
<br />
===Material de Referência===<br />
<br />
*Slides do Cap.3 - Silberschatz<br />
*Laboratório Fork/Exec/Wait<br />
<br />
=== Exercícios de Demonstração===<br />
<br />
#Executar em um terminal o comando top. Em um outro terminal executar:<br />
yes > /dev/null &<br />
yes > /dev/null &<br />
#Parar um dos processos yes<br />
kill -STOP <pid_yes><br />
#Continuar o processo<br />
kill -CONT <pid_yes><br />
#Destruir todos<br />
killall yes<br />
<br />
=AULA 5 - Dia 14/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*Ainda Processos<br />
*Cap.3.2..Escalonamento de Processos<br />
*Cap.2.3.Operaçṍes sobre processos<br />
*Finalização do Laboratório Fork/Exec/Wait<br />
<br />
===Adendo===<br />
<br />
*Estudar e comentar [https://www.geeksforgeeks.org/wait-system-call-c/]<br />
<br />
=AULA 6 - Dia 16/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*Comunicação Interprocessos (3.4 e 3.5)<br />
*Laboratório de Memória Compartilhada<br />
<br />
=AULA 7 - Dia 21/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Comunicação Interprocessos: Troca de Mensagens (3.6)<br />
*Laboratório de Pipes<br />
<br />
=AULA 8 - Dia 23/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Finalização Lab. pipes nomeados.<br />
*Threads ((cap.4.1, 4.2)<br />
*Lab.Threads de Aplicação<br />
<br />
=AULA 9 - Dia 28/08/2019=<br />
<br />
*Laboratório: Ainda Threads - Um escalonador semi-automático<br />
<br />
<br />
=AULA 10 - Dia 30/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Repassar um primeiro estudo sobre o RTOS<br />
*Revisar Processos e Threads<br />
<br />
==Questionário - Processos==<br />
<br />
#Conceitue processo. Descreva e explique cada uma das seções de um processo na memória.<br />
#Faça um diagrama e explique os possíveis estados de um processo no sistema. O que produz a transição entre estados?<br />
#O que é um Bloco de Controle de Processo? Quais informações ficam armazenadas neste bloco?<br />
#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.<br />
#Explique o que é multiprogramação e escalonamento de processos.<br />
#O que é a fila de processos prontos?<br />
#Diferencie um processo limitado por IO de um processo limitado por CPU.<br />
#Diferencie escalonamento de longo prazo de escalonamento de curto prazo.<br />
#Discuta o papel da interrupção na troca de contexto entre processos.<br />
#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?<br />
#Explique como funciona a chamada exec no UNIX/Linux<br />
#Explique como funciona a chamada wait no UNIX/Linux e como é possível retornar valores de um filho para o pai.<br />
#Faça um esqueleto de um programa UNIX/Linux que ao se tornar processo cria 3 filhos e espera pela execução dos mesmos.<br />
<br />
==Questionário - Comunicação entre Processos==<br />
<br />
#Diferenciar processos independentes de processos cooperantes.<br />
#Enumere e explique quatro razões para cooperação entre processos.<br />
#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.<br />
#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.<br />
#A memória compartilhada requer chamada ao sistema na sua operação? Discuta.<br />
#Por que o processo de troca de mensagem deve ser mais lento que a memória compartilhada?<br />
#Apresente em pseudocódigo uma proposta de funcionamento do problema do produtor consumidor usando memória compartilhada.<br />
#A construção de uma solução para o problema produtor consumidor pode ser facilitado pelo uso da memória compartilhada? Discuta.<br />
#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?<br />
#Enumere três métodos de implementação de uma lógica de ligação (link) entre processos.<br />
#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.<br />
#Descreva a variante assimétrica da troca direta de mensagens. O que muda em termos de primitiva de comunicação?<br />
#Descreva o problema de hard-coding associado a nomeação direta e como pode ser contornado através da nomeação/comunicação indireta?<br />
#O que é uma caixa postal? Como o Posix identifica uma caixa postal no caso de fila de mensagens?<br />
#Dois processos podem usar mais do que uma caixa postal para se comunicar? Qual a condição para que isto ocorra?<br />
#Descreva as duas operações básicas para a troca de mensagens com Caixa Postal.<br />
#Descreva na comunicação indireta via Caixa Postal as 3 propriedades básicas.<br />
#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.<br />
#De que forma a caixa postal estando no espaço de endereçamento de um processo (propriedade) afeta a recepção por mensagens? Descreva.<br />
#Quais as operações sobre uma caixa postal criada no espaço do sistema operacional deverão ser disponíveis? Descreva.<br />
#A transmissão de mensagem pode ser com e sem bloqueio. Descreva as 4 possibilidades (síncrona/assíncrona).<br />
#Discuta as 3 possibilidades de armazenamento de mensagens em buffer. Em que condições um remetente pode ser bloqueado?<br />
<br />
==ETAPA 1 - Projeto Final==<br />
<br />
*Apresentação (slides) sobre a parte de gerenciamento de tarefas no RTOS;<br />
*apresentação dia 18/09/2019<br />
<br />
==Referências==<br />
<br />
*[https://www.freertos.org/RTOS.html Site do FreeRTOS] ver Mastering the FreeRTOS Real Time Kernel - a Hands On Tutorial Guide <br />
*[https://www.embarcados.com.br/rtos-sistema-operacional-de-tempo-real/]<br />
*[https://github.com/feilipu/avrfreertos]<br />
<br />
=AULA 11 - Dia 4/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Pico de CPU X Pico de IO <br />
*Preempção X Não Preempção<br />
*Escalonamento de Processos: Escalonamento FCFS<br />
<br />
<br />
=AULA 12 - Dia 6/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Escalonamento de Processos: <br />
**Shortest Job First (preemptivo e não preemptivo)<br />
**Prioridade (preemptivo e não preemptivo)<br />
**Round-Robin: Preemptivo<br />
*Lab.Round Robin<br />
<br />
==Material de Referência==<br />
<br />
http://docente.ifsc.edu.br/andre.damato/sop2018/SOP2018-parte2.pdf<br />
<br />
<br />
=AULA 13 - Dia 13/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Sincronização entre Processos<br />
*Laboratório do Esquema de Peterson<br />
<br />
==Material de Referência==<br />
<br />
*Livro Silberchatz<br />
*https://www.os-book.com/OSE1/slide-dir/PPT-dir/ch6.ppt<br />
<br />
=AULA 14 - Dia 18/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Sincronização entre Processos<br />
*Lock de Hardware<br />
*Laboratório do TSL<br />
<br />
==Laboratório Proposto==<br />
<br />
*Refazer o problema proposto usando uma instrução simualada de test and set. Prever um liite superior para entrada de um processo na região crítica.<br />
<br />
==Material de Referência==<br />
<br />
*Livro Silberchatz<br />
*https://www.os-book.com/OSE1/slide-dir/PPT-dir/ch6.ppt<br />
<br />
<br />
=AULA 15 - Dia 20/08/2019=<br />
<br />
==O ATmega238 usado no Arduino UNO==<br />
<br />
Ver [https://pt.wikipedia.org/wiki/ATmega328]<br />
<br />
==O Arduino UNO==<br />
<br />
Ver [https://pt.wikipedia.org/wiki/Arduino]<br />
Ver [https://github.com/feilipu/Arduino_FreeRTOS_Library]<br />
<br />
==O FreeRtos para o Arduino==<br />
<br />
Ver [https://github.com/feilipu/Arduino_FreeRTOS_Library]<br />
<br />
Para instalar no IDE:<br />
*Baixar o ZIP do link acima<br />
*No IDE importar a biblioteca:<br />
**sketch->IncluirBiblioteca->Adicionar do arquivo ZIP<br />
<br />
<br />
==Código Experimental==<br />
<br />
Este código demonstra a ocorrência de "race condition".<br />
<br />
<syntaxhighlight lang=c><br />
// Code based on Examples of Arduino and examples <br />
// from https://github.com/feilipu/Arduino_FreeRTOS_Library<br />
<br />
#include <Arduino_FreeRTOS.h><br />
#include <FreeRTOSVariant.h><br />
#include <task.h><br />
#include <semphr.h><br />
<br />
#define TAM_BUFF 10<br />
<br />
volatile unsigned long race_flag=0xFFEEDDCC;<br />
volatile unsigned long int cont;<br />
int task_cont=0;<br />
<br />
void PrintSerial( void *pvParameters ); // Task para imprimir valor de race_flag<br />
void TaskBlink( void *pvParameters );<br />
void TaskSetarace_flag(void *pvParameters); //Task que atribui race_flag=0xFFEEDDCC<br />
void TaskZerarace_flag(void *pvParameters); //Task que atribui race_flag=0xAA0000AA<br />
<br />
// função de setup<br />
<br />
void setup() {<br />
<br />
Serial.begin(9600);<br />
<br />
while (!Serial) {<br />
; // wait for serial port to connect. Needed for native USB, on LEONARDO, MICRO, YUN, and other 32u4 based boards.<br />
}<br />
<br />
<br />
// criar as 2 tarefas<br />
<br />
xTaskCreate(<br />
TaskBlink<br />
, (const portCHAR *)"Blink" // A name just for humans<br />
, 128 // This stack size can be checked & adjusted by reading the Stack Highwater<br />
, NULL<br />
, 1 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.<br />
, NULL );<br />
<br />
xTaskCreate(<br />
TaskPrintSerial<br />
, (const portCHAR *) "PrintSerial"<br />
, 128 // Stack size<br />
, NULL<br />
, 1 // Priority<br />
, NULL );<br />
<br />
xTaskCreate(<br />
TaskSetarace_flag<br />
, (const portCHAR *) "Setarace_flag"<br />
, 128 // Stack size<br />
, NULL<br />
, 1 // Priority<br />
, NULL );<br />
<br />
xTaskCreate(<br />
TaskZerarace_flag<br />
, (const portCHAR *) "Zerarace_flag"<br />
, 128 // Stack size<br />
, NULL<br />
, 1 // Priority<br />
, NULL );<br />
<br />
cont = race_flag;<br />
<br />
// escalonador toma conta a partir daqui<br />
<br />
}<br />
<br />
void loop()<br />
{<br />
// nada a fazer aqui<br />
}<br />
<br />
/*--------------------------------------------------*/<br />
/*---------------------- Tasks ---------------------*/<br />
/*--------------------------------------------------*/<br />
<br />
void TaskBlink(void *pvParameters) // This is a task.<br />
{<br />
(void) pvParameters;<br />
<br />
/*<br />
Blink<br />
Turns on an LED on for one second, then off for one second, repeatedly.<br />
<br />
Most Arduinos have an on-board LED you can control. On the UNO, LEONARDO, MEGA, and ZERO <br />
it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN takes care <br />
of use the correct LED pin whatever is the board used.<br />
<br />
The MICRO does not have a LED_BUILTIN available. For the MICRO board please substitute<br />
the LED_BUILTIN definition with either LED_BUILTIN_RX or LED_BUILTIN_TX.<br />
e.g. pinMode(LED_BUILTIN_RX, OUTPUT); etc.<br />
<br />
If you want to know what pin the on-board LED is connected to on your Arduino model, check<br />
the Technical Specs of your board at https://www.arduino.cc/en/Main/Products<br />
<br />
This example code is in the public domain.<br />
<br />
modified 8 May 2014<br />
by Scott Fitzgerald<br />
<br />
modified 2 Sep 2016<br />
by Arturo Guadalupi<br />
*/<br />
<br />
// initialize digital LED_BUILTIN on pin 13 as an output.<br />
pinMode(LED_BUILTIN, OUTPUT);<br />
<br />
for (;;) // A Task shall never return or exit.<br />
{<br />
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)<br />
vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second<br />
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW<br />
vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second<br />
}<br />
}<br />
<br />
<br />
<br />
<br />
void TaskPrintSerial(void *pvParameters) // Task que imprime na serial - must be improved...<br />
{<br />
(void) pvParameters;<br />
/*<br />
<br />
*/<br />
<br />
<br />
for (;;)<br />
{ <br />
while (cont==0xAA0000AA || cont==0xFFEEDDCC)<br />
cont = race_flag;<br />
;<br />
<br />
Serial.println("Problemas: valor race_flag é");<br />
Serial.println(cont, HEX);<br />
<br />
vTaskDelay(5); // one tick delay (15ms) in between reads for stability - b<br />
cont = race_flag;<br />
}<br />
}<br />
<br />
void TaskSetarace_flag(void *pvParameters) <br />
{<br />
(void) pvParameters;<br />
const TickType_t xMaxBlockTimeTicks = 0x20;<br />
/*<br />
<br />
*/<br />
<br />
race_flag=0xAA0000AA;<br />
for (;;)<br />
{<br />
race_flag=0xAA0000AA;<br />
//Serial.println("Produtor");<br />
vTaskDelay( ( rand() %xMaxBlockTimeTicks) ); <br />
} <br />
<br />
}<br />
<br />
void TaskZerarace_flag(void *pvParameters) <br />
{<br />
(void) pvParameters;<br />
const TickType_t xMaxBlockTimeTicks = 0x20;<br />
/*<br />
<br />
*/<br />
race_flag=0xFFEEDDCC;<br />
<br />
for (;;)<br />
{<br />
race_flag=0xFFEEDDCC;<br />
vTaskDelay( ( rand() %xMaxBlockTimeTicks) ); <br />
if(task_cont++==100) {<br />
delay(1);<br />
Serial.println("Fim TaskZera - valor race_flag ");<br />
Serial.println(race_flag, HEX);<br />
for(;;);<br />
} <br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=AULA 16 - Dia 25/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Preparação de exemplos de RTOS sobre Arduíno para apresentação na sexta;<br />
<br />
=Laboratórios Propostos= <br />
<br />
Considere o código abaixo. Observe que a região de dados compartilhada shared_data é zerada pelo pai e setada pelo processo filho. O pai detecta inconsistências nos dados que operou. Tente corrigir usando o esquema de Peterson para acesso a região crítica. Crie uma função de entrada e de saída da região crítica.<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
<br />
<br />
#define BUFFER_SIZE 4096<br />
char *shared_data;<br />
char reference_data[BUFFER_SIZE];<br />
<br />
main()<br />
{ <br />
key_t key;<br />
int shmid;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, BUFFER_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
shared_data = shmat(shmid, (void *)0, 0);<br />
<br />
if (shared_data == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int count=0; <br />
memset(reference_data,0,BUFFER_SIZE); <br />
for(;;){ <br />
memset(shared_data,0,BUFFER_SIZE);<br />
if (memcmp(shared_data, reference_data, BUFFER_SIZE)!=0) {<br />
count++;<br />
if (count%1000000==0)<br />
printf("Processo pai detectou algo errado nos dados %d\n", count); <br />
} <br />
} <br />
<br />
<br />
}<br />
else { /*Child code */<br />
<br />
for(;;){ <br />
memset(shared_data,1,BUFFER_SIZE); <br />
}<br />
<br />
}<br />
<br />
if (shmdt(shared_data) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
Possível solução:<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
#include <unistd.h><br />
<br />
#define BUFFER_SIZE 4096<br />
#define ID_PAI 0<br />
#define ID_FILHO 1<br />
#define FALSE 0<br />
#define TRUE 1<br />
<br />
char *shared_data;<br />
char reference_data[BUFFER_SIZE];<br />
<br />
struct tipo_peterson{<br />
char flag[2];<br />
char turn;<br />
} *pet_struct;<br />
<br />
void ent_sec_crit(int id)<br />
{<br />
char id_outro = (id+1)%2;<br />
<br />
pet_struct->flag[id] = TRUE; // indica que o processo deseja entrar na região crítica<br />
pet_struct->turn = id_outro; // o processo sinaliza para o outrao entrar, <br />
// caso o outro esteja entrando<br />
// este ponto é uma race condition: turn pode ser 0 ou 1 <br />
while ( (pet_struct->flag[id_outro]==TRUE) && (pet_struct->turn == id_outro) )<br />
;<br />
}<br />
<br />
void sai_sec_crit(int id)<br />
{<br />
pet_struct->flag[id] = FALSE;<br />
}<br />
<br />
int main()<br />
{ <br />
key_t key;<br />
int shmid;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, BUFFER_SIZE+sizeof(struct tipo_peterson), S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
shared_data = shmat(shmid, (void *)0, 0);<br />
pet_struct = (struct tipo_peterson *) (shared_data + BUFFER_SIZE); <br />
<br />
if (shared_data == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int count=0; <br />
memset(reference_data,0,BUFFER_SIZE); <br />
for(;;){ <br />
ent_sec_crit(ID_PAI);<br />
memset(shared_data,0,BUFFER_SIZE);<br />
if (memcmp(shared_data, reference_data, BUFFER_SIZE)!=0) {<br />
count++;<br />
if (count%1000000==0)<br />
printf("Processo pai detectou algo errado nos dados %d\n", count); <br />
} <br />
sai_sec_crit(ID_PAI);<br />
} <br />
<br />
<br />
}<br />
else { /*Child code */<br />
<br />
for(;;){<br />
ent_sec_crit(ID_FILHO); <br />
memset(shared_data,1,BUFFER_SIZE);<br />
sai_sec_crit(ID_FILHO); <br />
}<br />
<br />
}<br />
<br />
if (shmdt(shared_data) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
=AULA 17 - Dia 27/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Apresentação dos Trabalhos<br />
*Definição da próxima etapa<br />
<br />
=AULA 18 - Dia 02/10/2019=<br />
<br />
==Objetivos==<br />
<br />
*Semáforos, Deadlock e o Problema da Inversão de Prioridade<br />
*Laboratório de Pthreads e Mutex;<br />
<br />
==Materia de Referência==<br />
<br />
*[https://www.os-book.com/OSE1/slide-dir/PDF-dir/ch6.pdf]<br />
<br />
==Desafio==<br />
<br />
Usar <br />
ps -T aux | grep ex1vA<br />
<br />
Para ver os threads dormindo...<br />
<br />
Otimizar o programa abaixo<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <pthread.h><br />
#include <stdlib.h><br />
#include <unistd.h><br />
#include <time.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
pthread_mutex_t mut;<br />
<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
<br />
<br />
long long i;<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
usleep(5000000);<br />
printf("Novo saldo = %d\n",novo_saldo);<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d\n", (i+1));<br />
exit(-1);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
printf("Saldo final é %d\n", saldo);<br />
}<br />
</syntaxhighlight><br />
<br />
==Laboratório Proposto==<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Programação concorrente}}<br />
<br />
== Programação concorrente ==<br />
<br />
<br />
===PARTE 1 - Mutex e Biblioteca libpthreads===<br />
<br />
;POSIX Threads<br />
A 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):<br />
*''pthread_create'': cria uma thread;<br />
*''pthread_kill'': força a terminação de uma thread;<br />
*''pthread_join'': sincroniza o final de uma thread (qual a diferença/semelhança com o ''wait'' que usamos para processos?);<br />
*''pthread_exit'': finaliza uma thread.<br />
Para utilizar estas funções é necessário linkar o programa à libpthread (''-lpthread''). <br />
<br />
<br />
;POSIX pthread mutex<br />
<br />
A biblioteca pthread implementa um tipo ''pthread_mutex_t'', que garante a exclusão mútua entre threads. Estes mutex são manipulados através das funções (acesse as man-pages das chamadas para maiores detalhes):<br />
*''pthread_mutex_lock'': acessa um mutex.<br />
*''pthread_mutex_trylock'': tenta acessar um mutex (retorna valor indicando sucesso ou falha no lock).<br />
*''pthread_mutex_unlock'': libera um mutex.<br />
<br />
<br />
<br />
;Exercício 1<br />
<br />
O programa abaixo cria 5 threads, e cada uma destas threads atualiza uma variável global (memória compartilhada).<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
#include <pthread.h><br />
#include <stdlib.h><br />
#include <unistd.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
pthread_mutex_t mut;<br />
<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
long long i;<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
sleep(1);<br />
printf("Novo saldo = %d\n",novo_saldo);<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d\n", (i+1));<br />
exit(-1);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
printf("Saldo final é %d\n", saldo);<br />
}<br />
</syntaxhighlight><br />
<br />
# Compile este programa. <br />
# Execute este programa várias vezes. Ele funciona? Será que ele gera as saídas esperadas?<br />
# Identifique as '''seções críticas''' do programa.<br />
# Corrija o programa utilizando '''mutex'''. <br />
# Analise a função ''AtualizaSaldo()'' com a sua solução. Lembre-se que o uso do mutex implica em apenas uma thread acessar a seção crítica por vez, enquanto outras threads ficam bloqueadas, esperando. Disso vem que, quanto menor o trecho de código entre um ''lock'' e um ''unlock'', menos tempo uma thread necessita ficar esperando.<br />
<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <cstring><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
<br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
sem_t sem;<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
int value;<br />
sem_wait(&sem);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
sem_getvalue(&sem, &value);<br />
printf("valor sem = %d\n", value);<br />
sem_post(&sem);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
sem_init(&sem,0,1);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
sem_destroy(&sem);<br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
===PARTE 2 - POSIX Semaphores===<br />
<br />
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):<br />
*''sem_init'': inicializa um semáforo;<br />
*''sem_destroy'': destroy um semáforo;<br />
*''sem_wait'': implementa a operação ''p'';<br />
*''sem_post'': implementa a operação ''v''.<br />
Para utilizar estas funções é necessário linkar o programa à librt ou à libpthread (''-lrt'' ou ''-lpthread'').<br />
<br />
;Exercício 1<br />
Modifique o programa para usar um semáforo binário ao invés de um mutex em sua solução.<br />
<br />
;Exercício 2<br />
Refaça o exercício 3 usando processos criados com fork e exec. O semáforo deve ser criado em uma região de memória compartilhada.<br />
<br />
;Exercício 3<br />
Implemente com pthreads e semáforos/mutex a solução do produtor/comsumidor.<br />
<br />
;Exercício 4<br />
<br />
O programa abaixo manipula uma matriz de tamanho MxN (veja os defines para o tamanho da matriz). A função ''SumValues'' soma todos os valores em uma linha da matriz. A linha a ser somada é identificada pela variável ''i''. Modifique o programa principal (''main'') nos locais indicados para:<br />
# Criar N threads, uma para somar os valores de cada linha.<br />
# Receber o resultado do somatório de cada linha e gerar o somatório total da matriz.<br />
# Analise o programa: há problemas de sincronização que precisam ser resolvidos? Se sim, resolva-os.<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include "thread.h"<br />
<br />
/* number of matrix columns and rows */<br />
#define M 5<br />
#define N 10<br />
<br />
using namespace std;<br />
<br />
int matrix[N][M];<br />
Thread *threads[N];<br />
<br />
<br />
/* thread function; it sums the values of the matrix in the row */<br />
int SumValues(int i)<br />
{<br />
int n = i; /* number of row */<br />
int total = 0; /* the total of the values in the row */<br />
int j;<br />
for (j = 0; j < M; j++) /* sum values in the "n" row */<br />
total += matrix[n][j];<br />
cout << "The total in row" << n << " is " << total << "." << endl;<br />
/* terminate a thread and return a total in the row */<br />
exit(total);<br />
}<br />
<br />
int main(int argc, char *argv[])<br />
{<br />
int i, j;<br />
int total = 0; /* the total of the values in the matrix */<br />
<br />
/* initialize the matrix */<br />
for (i = 0; i < N; i++)<br />
for (j = 0; j < M; j++)<br />
matrix[i][j] = i * M + j;<br />
<br />
/* create threads */<br />
/* COLOQUE SEU CÓDIGO PARA CRIAR AS THREADS AQUI! */<br />
<br />
/* wait for terminate a threads */<br />
/* COLOQUE SEU CÓDIGO PARA PEGAR O SOMATÓRIO DE LINHAS E TOTALIZAR A SOMA DA MATRIZ AQUI! */<br />
<br />
cout << "The total values in the matrix is " << total << endl;<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
{{collapse bottom}}<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Escalonamento Round Robin e FCFS para Threads"}}<br />
<br />
== Escalonamento Round-Robin ==<br />
<br />
OBS: ver https://www.quora.com/What-exactly-does-typedef-do-in-C<br />
<br />
O Exemplo abaixo mostra a implementação de um esquema de escalonamento Round Robin do exercício anterior.<br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
Modificado por Eraldo <br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 5<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
void runA(void) {<br />
for (;;) {<br />
printf("running A\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runB(void) {<br />
for (;;) {<br />
printf("running B\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 1<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
<br />
void scheduler_rr();<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void yield_thread()<br />
{<br />
scheduler_rr();<br />
}<br />
<br />
void delete_thread()<br />
{<br />
delete curr_thread;<br />
curr_thread=NULL;<br />
scheduler_rr();<br />
}<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
struct delta{<br />
long alfa;<br />
char epson[1000];<br />
long beta;<br />
} shar;<br />
<br />
int turn;<br />
int flag[2];<br />
<br />
#define TRUE 1<br />
#define FALSE 0<br />
<br />
void ent_rc(int p, int vt)<br />
{<br />
flag[p]=TRUE;<br />
turn = vt;<br />
if(p) p=0; else p=1;<br />
while (flag[p] && turn == vt);<br />
//printf("Thread %d: esperando para acessar a região crítica\n", p);<br />
}<br />
<br />
void sai_rc(int p)<br />
{<br />
flag[p]=FALSE;<br />
}<br />
<br />
void runA(void) {<br />
struct delta x = {0, 100};<br />
<br />
for (;;) {<br />
x.alfa=0;x.beta=0;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0);<br />
x.alfa=100;x.beta=100;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0); <br />
}<br />
}<br />
<br />
void runB(void) {<br />
<br />
for (;;) {<br />
ent_rc(1,0);<br />
printf("shar alfa = %ld shar beta = %ld \n",shar.alfa, shar.beta); // regiao crítica<br />
sai_rc(1);<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runC(void) {<br />
int i;<br />
for (i=0;i<10;i++) {<br />
printf("Thread C - parte 1\n");<br />
yield_thread();<br />
printf("Thread C - parte 2\n");<br />
yield_thread();<br />
}<br />
delete_thread();<br />
}<br />
<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
add_thread(runC);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
{{collapse bottom}}<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Um escalonador semi-automático"}}<br />
<br />
== Ainda Threads - Um escalonador semi-automático usando sinais ==<br />
<br />
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.<br />
<br />
===Exemplo 1:===<br />
<br />
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. <br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
<br />
void sig_handler(int signo)<br />
{<br />
int x;<br />
printf("Turma de SOP: recebido SIGUSR1\n");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
// Loop eterno dormindo 1s<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Fazer no terminal:<br />
ps aux<br />
anotar o pid do processo e enviar o sinal:<br />
kill -USR1 pid<br />
<br />
===Exemplo 2:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// loop eterno que nunca é executado<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Enviar o sinal USR1 para ver o efeito. <br />
<br />
===Exemplo 3:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void prepara_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void prepara_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
prepara_contexto_ping();<br />
prepara_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// A long long wait so that we can easily issue a signal to this process<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Exercício: Use o comando htop para verificar como estes threads são vistos pelo SOP.<br />
<br />
Exercício: Tente analisar as pilhas dos threads e verificar sob qual pilha o handler se executa.<br />
<br />
<br />
===Exercício 4:===<br />
<br />
Neste ponto associamos um timer ao handler com o apoio do sinal ALRM. Agora os threads são escalonados automaticamente.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
===Exercício Proposto 5===<br />
<br />
Colocar 3 threads rodando.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void preparar_contexto_ping(ucontext_t *pContext, char *p)<br />
{<br />
char *stack;<br />
<br />
getcontext(pContext);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
(*pContext).uc_stack.ss_sp = stack ;<br />
(*pContext).uc_stack.ss_size = STACKSIZE;<br />
(*pContext).uc_stack.ss_flags = 0;<br />
(*pContext).uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(pContext, (void*)(*f_ping), 1, p);<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping(&cPing, "ping");<br />
preparar_contexto_ping(&cPong, "pong");<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Threads de aplicação}}<br />
<br />
== Threads de aplicação ==<br />
<br />
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:<br />
*'''getcontext(&a)''': salva o contexto na variável '''a''';<br />
*'''setcontext(&a)''': restaura um contexto salvo anteriormente na variável '''a''';<br />
*'''swapcontext(&a,&b)''': salva o contexto atual na variável '''a''' e restaura o contexto salvo anteriormente na variável '''b''';<br />
*'''makecontext(&a, ...)''': ajusta parâmetros internos do contexto salvo em '''a''';<br />
*'''ucontext_t''': as variáveis '''a''' e '''b''' são do tipo '''ucontext_t'''. Este tipo armazena um contexto.<br />
<br />
Busque mais informações sobre estas funções utilizando o programa manpage do Linux (ex.: man getcontext).<br />
<br />
Estude o código no arquivo pingpong.c abaixo e explique seu funcionamento.<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
*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.<br />
*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.<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain, cFnew;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_new(void * arg1, void * arg2,void * arg3,void * arg4) <br />
{<br />
printf ("%s: Primeira string %s %s %s\n",(char*) arg1,(char*) arg2,(char*) arg3, (char*) arg4);<br />
swapcontext(&cFnew, &cMain); <br />
}<br />
<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
<br />
getcontext(&cFnew);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cFnew.uc_stack.ss_sp = stack ;<br />
cFnew.uc_stack.ss_size = STACKSIZE;<br />
cFnew.uc_stack.ss_flags = 0;<br />
cFnew.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cFnew, (void*)(*f_new), 4, "\tF_new", "\tAlo", "\tMundo","\tReal");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
swapcontext(&cMain, &cFnew);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
--><br />
Exercício 3: O que acontece se um dos threads é colocado para dormir? Todos os demais threads param a sua execução.<br />
<br />
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/<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Processos no Linux}}<br />
<br />
== Processos no Linux - Modificado por Eraldo ==<br />
<br />
<blockquote style="background: lime; border: 1px solid black; padding: 1em;"><br />
Processos no Linux<br />
</blockquote><br />
<br />
*Exercícios propostos pelo Prof.Arliones e Modificados por Eraldo<br />
<br />
<br />
[[imagem:DesenhoForkExec.png|border|650px]]<br />
<br />
<br />
;Syscall FORK<br />
<br />
* Em um terminal, execute "man fork"<br />
** 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'''.<br />
** O '''código''' dos dois processos (pai e filho) são '''idênticos''';<br />
** Os '''dados''' dos dois processos (pai e filho) são '''idênticos NO MOMENTO DA CRIAÇÃO''';<br />
** Execução do processo filho inicia na próxima instrução do programa (no retorno da chamada FORK);<br />
** Não é possível saber qual dos processos (pai ou filho) retormará a execução primeiro - isto fica a cargo do excalonador do SO;<br />
** Valores de retorno da chamada FORK:<br />
*** (-1): erro na criação do processo (ex.: memória insuficiente);<br />
*** (0): em caso de sucesso, este é o valor de retorno recebido pelo processo filho;<br />
*** (>0): em caso de sucesso, este é o valor de retorno recebido pelo processo pai;<br />
<br />
;Syscall JOIN<br />
<br />
* A syscall JOIN é implementada no POSIX pela função '''wait()'''. Execute "man wait".<br />
** Além da função '''wait()''', há também '''waitpid()''' e '''waitid()''';<br />
** 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);<br />
** A chamada wait também libera os recursos do processo filho que termina;<br />
** '''wait()''': esta função suspende a execução do processo chamador até que UM DOS SEUS FILHOS finalize;<br />
** '''waitpid()''': suspende a execução do processo chamador até que UM FILHO ESPECÍFICO finalize;<br />
<br />
;Syscall EXEC<br />
<br />
* A syscall EXEC é implementada no POSIX pela família de funções '''exec()'''. Execute "man exec".<br />
** As principais funções da família são '''execl()''', '''execlp()''' e '''execvp()''';<br />
** 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;<br />
** 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;<br />
<br />
<br />
;Exemplos POSIX utilizando fork/wait/exec<br />
<br />
*Exemplo 1: fork/wait básico<br />
<syntaxhighlight lang=c><br />
// ex1: fork/wait básico<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
printf("processo filho\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
printf("processo pai\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
arliones@socrates:~/tmp$ gcc ex1.c -o ex1 <br />
arliones@socrates:~/tmp$ ./ex1 <br />
processo filho pid: 27858 pid pai: 27857<br />
processo pai pid: 27857 pid pai: 5337<br />
arliones@socrates:~/tmp$ <br />
</syntaxhighlight><br />
<br />
* Exemplo 2: processos pai e filho compartilham código, mas não dados.<br />
<syntaxhighlight lang=c><br />
// ex2: fork/wait "compartilhando" dados<br />
// ex2: fork/wait "compartilhando" dados<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status, k=0;<br />
printf("processo %d\t antes do fork\n", getpid());<br />
pid = fork();<br />
printf("processo %d\t depois do fork\n", getpid());<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
k += 1000;<br />
printf("processo filho\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status); // espera o filho terminar<br />
k += 10;<br />
printf("processo pai\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
k += 1000;<br />
printf("FIM processo %d\t K: %d\n", getpid(), k); <br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
processo 17056 antes do fork<br />
processo 17056 depois do fork<br />
processo 17057 depois do fork<br />
processo filho pid: 17057 K: 1000 endereço K: 0x7ffd8923e318<br />
processo pai pid: 17056 K: 10 endereço K: 0x7ffd8923e318<br />
</syntaxhighlight><br />
<br />
* Modificação no código: comentar linhas 23 e 30<br />
<br />
<syntaxhighlight lang=bash><br />
<br />
</syntaxhighlight><br />
<br />
* Analise os resultados e busque entender a diferença.<br />
*Perguntas e desafios.:<br />
#Analisando os valores impressos de k pode-se dizer que os dados são compartilhados entre os dois processos?<br />
#O endereço de k impresso é o mesmo nos dois processos. ISto não contradiz a afirmação anterior?<br />
#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.<br />
<br />
<br />
;Exercício fork/wait<br />
<br />
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.<br />
<br />
*Use o comando pstree para verificar a árvore de processos criada.<br />
<br />
{{collapse top|Solução}}<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
<!--<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
--><br />
<br />
;DESAFIO: fork/wait<br />
<br />
Reimplementar o exercício anterior de criação de uma árvore de 3 processos, generalizando a criação de N processos onde N é repassado na linha de comando do programa. SUGESTÃO: usar um comando for, mas lembrar que se existe um fork dentro do for, então cada filho gerado dará continuidade a execução do for. É necessário que o processo faça um exit ou retorne neste momento.<br />
<br />
;DESAFIO: Exercício status/wait<br />
<br />
O ''status'' passado como parâmetro à função ''wait(&status)'' é, na verdade, o mecanismo de retorno de resultado do ''wait/waitpid''. Ao retornar, esta variável contém informações sobre o resultado da execução do processo filho. Por exemplo, se um processo terminou normalmente (i.e., chamou ''exit''), o comando ''WIFEXITED(status)'' retorna ''true''. Este comando retorna ''false'' se o processo foi abortado (e.g., ''segmentation fault'') ou morto (e.g., ''kill''). Investigue no manual do wait no Linux (''man wait'') o funcionamento do comando WEXITSTATUS(status). <br />
Imagine um problema de busca de dados armazenados na forma de uma matriz de inteiros 4x30. Você está interessado em saber quantas ocorrências de um determinado número existe em cada linha da matriz. Note que que são tarefas que podem ser paralelizadas e usufruir de um sistema capaz de executá-las em paralelo. Faça uma implementação paralelizando 4 processos filhos a partir de um pai, onde cada processo é responsável por uma busca. A quantidade de ocorrências do número buscado é retornada e capturada através de WEXITSTATUS.<br />
<br />
;Syscall EXEC<br />
<br />
*Exemplo exec()<br />
<br />
<syntaxhighlight lang=c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
execl("/bin/ls","ls","-l", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 1: Modificar o código para mostrar que o exec() não retorna (colocar um printf após o exec).<br />
<br />
*Exercício 2: Criar um exemplo (dois programas ) para demonstrar que o exec não cria novo processo. <br />
**Crie um primeiro programa (prog1) que imprime o seu pid e depois faz um exec do segundo programa.<br />
**Crie o segundo programa que simplesmente imprime o pid.<br />
<br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU ANTES DO EXEC: Meu pid é %d\n", getpid());<br />
execl("./prog2","prog2", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU DEPOIS DO EXEC:Meu pid é %d\n", getpid());<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 3: Criar um exemplo usando fork/exec mostrando que um processo pai cria um filho e espera por sua execução. O filho executa o comando "ps aux". Ambos devem mostrar seus pids.<br />
<br />
{{collapse bottom}} <br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Laboratório Memória Compartilhada entre Pai e Filho - Produtor Consumidor}}<br />
<br />
Baseado no Lab. do Prof.Arliones<br />
<br />
=== Objetivo ===<br />
<br />
*Familiarizar o aluno com o conceito de Memória Compartilhada entre Processos Pai e Filho<br />
*Familizarizar o aluno com o conceito de Produtor Consumidor<br />
<br />
=== Referencial Teórico-Prático ===<br />
<br />
* Silberchatz - 3.4 e 3.5<br />
* man nos comandos shmat e shmget<br />
<br />
=== Exemplo de Funcionamento ===<br />
<br />
No exemplo abaixo um processo pai compartilha uma área de memória com o processo filho. O processo filho escreve uma mensagem para o pai na área de memória compartilhada e termina. O processo pai é desbloqueado no wait e imprime a mensagem escrita.<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
char *ptr_msg = "alo pai, tudo bem?"; <br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
strcpy(segmento, ptr_msg);<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(&filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
=== Desafio a ser Implementado em Sala ===<br />
<br />
Construir um programa em que um processo pai atua como produtor e o processo filho atua como consumidor. O buffer circular compartilhado é um buffer de inteiro de tamanho 5. O pai alimentará o buffer com 50 itens gerados aleatóriamente entre 1 e 100. A cada escrita/leitura no buffer o produtor/consumidor deve esperar alguns milisegundos de forma a acontecer situações de buffer cheio e vazio. <br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
#include <unistd.h><br />
#include <time.h><br />
#include <sys/types.h><br />
#include <sys/wait.h><br />
<br />
<br />
<br />
#define SHM_SIZE 1024 <br />
<br />
#define BUFF_COMP_SIZE 5<br />
<br />
struct buff_comp {<br />
int buffer[BUFF_COMP_SIZE];<br />
int in,out;<br />
};<br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
struct buff_comp *p; <br />
<br />
/* initialize random seed: */<br />
srand ( time(NULL) );<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
p = (struct buff_comp *) shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
p->out = p->in = 0;<br />
<br />
if((filho = fork()) == -1)<br />
{<br />
<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
int i;<br />
for(i=0;i<50;i++) {<br />
while (p->in==p->out) {<br />
printf("FILHO: BUFFER VAZIO !!!!!!!\n");<br />
usleep(rand() % 10000 + 1);<br />
}<br />
printf("FILHO: item lido = %d\n", p->buffer[p->out]);<br />
p->out = (p->out+1)%BUFF_COMP_SIZE;<br />
}<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
int i; <br />
<br />
for(i=0;i<50;i++) {<br />
while (((p->in+1)%BUFF_COMP_SIZE) == p->out) {<br />
printf("PAI: BUFFER CHEIO !!!!!!!\n");<br />
usleep(rand() % 10000 + 1);<br />
}<br />
p->buffer[p->in] = rand() % 100 + 1;<br />
printf("PAI: item produzido = %d\n", p->buffer[p->in]);<br />
p->in = (p->in+1)%BUFF_COMP_SIZE;<br />
<br />
}<br />
wait(&filho); <br />
<br />
}<br />
<br />
<br />
if (shmdt(p) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Trocas de mensagens com pipes}}<br />
<br />
= Trocas de mensagens com pipes =<br />
<br />
;Troca de mensagens<br />
Um mecanismo disponibilizado por sistemas UNIX para troca de mensagens entre processos é o PIPE. Pipes são mecanismos de comunicação indireta onde mensagens são trocadas através de ''mailboxes''. Cada ''mailbox'' possui um identificador único, permitindo que processos identifiquem o canal de comunicação entre eles. O fluxo de mensagens em um Pipe é:<br />
*'''unidirecional''': sobre um mesmo pipe, apenas um processo envia mensagens e um processo recebe mensagens;<br />
*'''FIFO''': as mensagens são entregues na ordem de envio;<br />
*'''não-estruturado''': não há estrutura pré-definida para o formato da mensagem.<br />
No UNIX, pipes são inicializados através da '''SystemCall''' ''pipe'', que possui a seguinte sintaxe:<br />
*''int pipe(int pipefd[2])'': ''pipe'' inicializa um novo pipe no sistema e retorna, no array pipefd, os descritores identificando cada uma das pontas do pipe. A primeira posição do array, i.e. pipefd[0], recebe o descritor que pode ser aberto apenas para leitura, enquanto a segunda posição do array, i.e. pipefd[1], recebe o descritor que pode ser aberto apenas para escrita. A função retorna zero no caso de sucesso, ou -1 se ocorrer erro.<br />
As primitivas send/receive para uso de um pipe no UNIX são implementadas por '''SystemCalls''' read/write, conforme segue:<br />
*''ssize_t read(int fd, void *buf, size_t count)'': “puxa” dados do pipe identificado pelo descritor fd. Os dados recebidos são os apontados pelo ponteiro buf, sendo count a quantidade máxima de bytes a serem recebidos. A função retorna o número de bytes recebidos.<br />
*''ssize_t write(int fd, const void *buf, size_t count)'': “empurra” dados no pipe identificado pelo descritor fd. Os dados transmitidos são os apontados pelo ponteiro buf, sendo count a quantidade de bytes a serem transmitidos. A função retorna o número de bytes transmitidos.<br />
<br />
*Exemplo 1: Transmitindo e recebendo pelo próprio processo<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main()<br />
{<br />
int fd[2];<br />
char *ptr = "Alo eu mesmo";<br />
char *ptr_alvo;<br />
int tamanho_dados, ret;<br />
<br />
tamanho_dados = strlen(ptr)+1;<br />
<br />
if (pipe(fd)==-1){<br />
printf ("erro criação pipe\n");<br />
exit(-1);<br />
}<br />
printf("Transmitido %d bytes\n", tamanho_dados);<br />
write (fd[1], ptr, tamanho_dados);<br />
<br />
ptr_alvo = malloc(tamanho_dados);<br />
<br />
ret=read(fd[0],ptr_alvo,tamanho_dados);<br />
<br />
printf("ret = %d dados => %s\n", ret, ptr_alvo); <br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
*Exemplo 2: Abaixo há um exemplo de programa criando um pipe e compartilhando os descritores entre dois processos (criados via ''fork()'').<br />
<syntaxhighlight lang=c><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
<br />
char *message = "This is a message!!!" ;<br />
<br />
main()<br />
{<br />
char buf[1024] ;<br />
int fd[2];<br />
pipe(fd); /*create pipe*/<br />
if (fork() != 0) { /* I am the parent */<br />
write(fd[1], message, strlen (message) + 1) ;<br />
}<br />
else { /*Child code */<br />
read(fd[0], buf, 1024) ;<br />
printf("Got this from MaMa!!: %s\n", buf) ;<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
*'''Exercício 1: construa um “pipeline”'''. Crie um programa que conecta 4 processos através de 3 pipes. Utilize ''fork()'' para criar vários processos.<br />
<br />
<syntaxhighlight lang=cpp><br />
<br />
//Solução possível<br />
<br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
pipe(fd);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
<br />
</syntaxhighlight><br />
<br />
*'''Exercício 2: Modifique o exercício anterior para que o processo D, através de um novo pipe, mande uma mensagem diretamente para o pai de todos.<br />
<br />
<!--<br />
<code><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
int fd_retorno[2];<br />
<br />
pipe(fd);<br />
pipe(fd_retorno);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size);<br />
read(fd_retorno[0], buf, size);<br />
printf("PAI:%s\n", buf); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
char *ptr_msg_ret="Ok msg de D para o pai";<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
write(fd_retorno[1],ptr_msg_ret,strlen(ptr_msg_ret)+1);<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
*'''Exercício 3: Consultor de Login de Acesso:'''. Estude o link https://www.geeksforgeeks.org/named-pipe-fifo-example-c-program/ e projete um programa cliente servidor da seguinte forma: (i) O servidor possui uma tabela de usuários (userid). O user_id é de tamanho fixo de 7 caracteres. O servidor espera por consultas para verificar se um usuário está na tabela. Se estiver responde com o caracter 'S' senão com 'N'. (ii) O cliente espera por user_id no teclado e consulta o servidor sobre sua existência na tabela. O cliente imprime na tabela a existência ou não do usuário.<br />
<br />
*'''Exercício 4: cópia de arquivo'''. Projete um programa de cópia de arquivos chamado FileCopy usando pipes comuns. Esse programa receberá dois parâmetros: o primeiro é o nome do arquivo a ser copiado e o segundo é o nome do arquivo copiado. Em seguida, o programa criará um pipe comum e gravará nele o conteúdo do arquivo a ser copiado. O processo filho lerá esse arquivo do pipe e o gravará no arquivo de destino. Por exemplo, se chamarmos o programa como descrito a seguir:<br />
:<syntaxhighlight lang=bash><br />
$ FileCopy entrada.txt copia.txt<br />
</syntaxhighlight><br />
:o arquivo ''entrada.txt'' será gravado no pipe. O processo filho lerá o conteúdo desse arquivo e o gravará no arquivo de destino ''copia.txt''. Escreva o programa usando os pipes da API POSIX no Linux.<br />
<br />
<br />
{{collapse bottom}}<br />
<br />
=Laboratórios Disponíveis= <br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Escalonamento Round Robin e FCFS para Threads"}}<br />
<br />
<br />
== Escalonamento Round-Robin preemptivo ==<br />
<br />
OBS: ver https://www.quora.com/What-exactly-does-typedef-do-in-C<br />
<br />
A fazer: <br />
<br />
*primitiva de término de processo (destrutor do objeto); <br />
*primitiva de yield<br />
*isolar o escalonador em uma função;<br />
*isolar o dispatcher em uma função; <br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
Modificado por Eraldo <br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 5<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
void runA(void) {<br />
for (;;) {<br />
printf("running A\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runB(void) {<br />
for (;;) {<br />
printf("running B\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 1<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
<br />
void scheduler_rr();<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void yield_thread()<br />
{<br />
scheduler_rr();<br />
}<br />
<br />
void delete_thread()<br />
{<br />
delete curr_thread;<br />
curr_thread=NULL;<br />
scheduler_rr();<br />
}<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
struct delta{<br />
long alfa;<br />
char epson[1000];<br />
long beta;<br />
} shar;<br />
<br />
int turn;<br />
int flag[2];<br />
<br />
#define TRUE 1<br />
#define FALSE 0<br />
<br />
void ent_rc(int p, int vt)<br />
{<br />
flag[p]=TRUE;<br />
turn = vt;<br />
if(p) p=0; else p=1;<br />
while (flag[p] && turn == vt);<br />
//printf("Thread %d: esperando para acessar a região crítica\n", p);<br />
}<br />
<br />
void sai_rc(int p)<br />
{<br />
flag[p]=FALSE;<br />
}<br />
<br />
void runA(void) {<br />
struct delta x = {0, 100};<br />
<br />
for (;;) {<br />
x.alfa=0;x.beta=0;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0);<br />
x.alfa=100;x.beta=100;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0); <br />
}<br />
}<br />
<br />
void runB(void) {<br />
<br />
for (;;) {<br />
ent_rc(1,0);<br />
printf("shar alfa = %ld shar beta = %ld \n",shar.alfa, shar.beta); // regiao crítica<br />
sai_rc(1);<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runC(void) {<br />
int i;<br />
for (i=0;i<10;i++) {<br />
printf("Thread C - parte 1\n");<br />
yield_thread();<br />
printf("Thread C - parte 2\n");<br />
yield_thread();<br />
}<br />
delete_thread();<br />
}<br />
<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
add_thread(runC);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Um escalonador semi-automático"}}<br />
<br />
== Ainda Threads - Um escalonador semi-automático usando sinais ==<br />
<br />
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.<br />
<br />
===Exemplo 1:===<br />
<br />
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. <br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
<br />
void sig_handler(int signo)<br />
{<br />
int x;<br />
printf("Turma de SOP: recebido SIGUSR1\n");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
// Loop eterno dormindo 1s<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Fazer no terminal:<br />
ps aux<br />
anotar o pid do processo e enviar o sinal:<br />
kill -USR1 pid<br />
<br />
===Exemplo 2:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// loop eterno que nunca é executado<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Enviar o sinal USR1 para ver o efeito. <br />
<br />
===Exemplo 3:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void prepara_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void prepara_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
prepara_contexto_ping();<br />
prepara_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// A long long wait so that we can easily issue a signal to this process<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
Exercício: Tente analisar as pilhas dos threads e verificar sob qual pilha o handler se executa.<br />
<br />
===Exercício 4:===<br />
<br />
Neste ponto associamos um timer ao handler com o apoio do sinal ALRM. Agora os threads são escalonados automaticamente.<br />
<br />
<code><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void preparar_contexto_ping(ucontext_t *pContext, char *p)<br />
{<br />
char *stack;<br />
<br />
getcontext(pContext);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
(*pContext).uc_stack.ss_sp = stack ;<br />
(*pContext).uc_stack.ss_size = STACKSIZE;<br />
(*pContext).uc_stack.ss_flags = 0;<br />
(*pContext).uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(pContext, (void*)(*f_ping), 1, p);<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping(&cPing, "ping");<br />
preparar_contexto_ping(&cPong, "pong");<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Um Exemplo de Uso "API Padrão POSIX"}}<br />
<br />
== Um Exemplo de Uso "API Padrão POSIX" ==<br />
<br />
;Referências<br />
* Referência http://man7.org/linux/man-pages/man2/mmap.2.html<br />
<br />
<br />
Crie uma função soma que receba 2 ponteiros referenciando posições na memória, criadas utilizando nmap(), de maneira que estas posições armazenem números inteiros. A função soma deverá retornar a soma dos números apontados em regiões da memória sem a utilização de nenhuma rotina da biblioteca do C, que não sejam definidas por APIs posix, para criação destas <br />
regiões na memória (malloc, alloc, calloc). Após retornar o resultado da soma os devidos ponteiros deverão ser extintos da memória.<br />
<br />
<br />
*'''Experimento 1:''' Aumente o tamanho da memória alocada até quando for possível.<br />
<br />
Qual o tamanho limite da memória que você conseguiu alocar?<br />
<br />
*'''Experimento 2:''' Mude o escopo para PROT_NONE, após executar e depurar o código explique o que aconteceu.<br />
<br />
Em sua opinião NMAP trata-se de uma syscall ou de uma API? Afinal API e syscall são a mesma coisa? Explique.<br />
<br />
<syntaxhighlight lang=cpp><br />
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);<br />
int munmap(void *addr, size_t length);<br />
<br />
addr = Valor do início do mapeamento.<br />
length = valor do tamanho da região a ser alocada.<br />
prot = especificações de proteção da região alocada (consultar http://man7.org/linux/man-pages/man2/mmap.2.html).<br />
flags = especificação do escopo e do tipo da região criada (exemplo publica ou privada, se é anônima ou não). <br />
</syntaxhighlight><br />
<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
void* meu_malloc(size_t tamanho) {<br />
void* addr = mmap(0, // addr<br />
tamanho, // len<br />
PROT_READ | PROT_WRITE, // prot<br />
MAP_ANON | MAP_PRIVATE, // flags<br />
-1, // filedes<br />
0); // off<br />
*(size_t*)addr = tamanho;<br />
return addr;<br />
}<br />
<br />
int meu_free(void* addr) {<br />
return munmap(addr - sizeof(size_t), (size_t) addr);<br />
}<br />
<br />
<br />
int soma(int *N1, int *N2){<br />
<br />
return (*N1+*N2);<br />
<br />
}<br />
<br />
<br />
int main(int argc, char* argv[]) {<br />
<br />
int* numero1 = meu_malloc(sizeof(int));<br />
int* numero2 = meu_malloc(sizeof(int)); <br />
<br />
<br />
*numero1 = 10;<br />
*numero2 = 20; <br />
<br />
int resultado = soma(numero1, numero2);<br />
<br />
printf("\n\n O resultado da soma é %d \n\n",resultado); <br />
<br />
meu_free(numero1);<br />
meu_free(numero2);<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Processos no Linux}}<br />
<br />
== Processos no Linux - Modificado por Eraldo ==<br />
<br />
<blockquote style="background: lime; border: 1px solid black; padding: 1em;"><br />
Processos no Linux<br />
</blockquote><br />
<br />
*Exercícios propostos pelo Prof.Arliones e Modificados por Eraldo<br />
<br />
<br />
[[imagem:DesenhoForkExec.png|border|650px]]<br />
<br />
<br />
;Syscall FORK<br />
<br />
* Em um terminal, execute "man fork"<br />
** 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'''.<br />
** O '''código''' dos dois processos (pai e filho) são '''idênticos''';<br />
** Os '''dados''' dos dois processos (pai e filho) são '''idênticos NO MOMENTO DA CRIAÇÃO''';<br />
** Execução do processo filho inicia na próxima instrução do programa (no retorno da chamada FORK);<br />
** Não é possível saber qual dos processos (pai ou filho) retormará a execução primeiro - isto fica a cargo do excalonador do SO;<br />
** Valores de retorno da chamada FORK:<br />
*** (-1): erro na criação do processo (ex.: memória insuficiente);<br />
*** (0): em caso de sucesso, este é o valor de retorno recebido pelo processo filho;<br />
*** (>0): em caso de sucesso, este é o valor de retorno recebido pelo processo pai;<br />
<br />
;Syscall JOIN<br />
<br />
* A syscall JOIN é implementada no POSIX pela função '''wait()'''. Execute "man wait".<br />
** Além da função '''wait()''', há também '''waitpid()''' e '''waitid()''';<br />
** 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);<br />
** A chamada wait também libera os recursos do processo filho que termina;<br />
** '''wait()''': esta função suspende a execução do processo chamador até que UM DOS SEUS FILHOS finalize;<br />
** '''waitpid()''': suspende a execução do processo chamador até que UM FILHO ESPECÍFICO finalize;<br />
<br />
;Syscall EXEC<br />
<br />
* A syscall EXEC é implementada no POSIX pela família de funções '''exec()'''. Execute "man exec".<br />
** As principais funções da família são '''execl()''', '''execlp()''' e '''execvp()''';<br />
** 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;<br />
** 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;<br />
<br />
<br />
;Exemplos POSIX utilizando fork/wait/exec<br />
<br />
*Exemplo 1: fork/wait básico<br />
<syntaxhighlight lang=c><br />
// ex1: fork/wait básico<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
printf("processo filho\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
printf("processo pai\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
arliones@socrates:~/tmp$ gcc ex1.c -o ex1 <br />
arliones@socrates:~/tmp$ ./ex1 <br />
processo filho pid: 27858 pid pai: 27857<br />
processo pai pid: 27857 pid pai: 5337<br />
arliones@socrates:~/tmp$ <br />
</syntaxhighlight><br />
<br />
* Exemplo 2: processos pai e filho compartilham código, mas não dados.<br />
<syntaxhighlight lang=c><br />
// ex2: fork/wait "compartilhando" dados<br />
// ex2: fork/wait "compartilhando" dados<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status, k=0;<br />
printf("processo %d\t antes do fork\n", getpid());<br />
pid = fork();<br />
printf("processo %d\t depois do fork\n", getpid());<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
k += 1000;<br />
printf("processo filho\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status); // espera o filho terminar<br />
k += 10;<br />
printf("processo pai\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
k += 1000;<br />
printf("FIM processo %d\t K: %d\n", getpid(), k); <br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
processo 17056 antes do fork<br />
processo 17056 depois do fork<br />
processo 17057 depois do fork<br />
processo filho pid: 17057 K: 1000 endereço K: 0x7ffd8923e318<br />
processo pai pid: 17056 K: 10 endereço K: 0x7ffd8923e318<br />
</syntaxhighlight><br />
<br />
* Modificação no código: comentar linhas 23 e 30<br />
<br />
<syntaxhighlight lang=bash><br />
<br />
</syntaxhighlight><br />
<br />
* Analise os resultados e busque entender a diferença.<br />
*Perguntas e desafios.:<br />
#Analisando os valores impressos de k pode-se dizer que os dados são compartilhados entre os dois processos?<br />
#O endereço de k impresso é o mesmo nos dois processos. ISto não contradiz a afirmação anterior?<br />
#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.<br />
<br />
<br />
;Exercício fork/wait<br />
<br />
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.<br />
<br />
*Use o comando pstree para verificar a árvore de processos criada.<br />
<br />
{{collapse top|Solução}}<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
<!--<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
--><br />
<br />
;DESAFIO: fork/wait<br />
<br />
Reimplementar o exercício anterior de criação de uma árvore de 3 processos, generalizando a criação de N processos onde N é repassado na linha de comando do programa. SUGESTÃO: usar um comando for, mas lembrar que se existe um fork dentro do for, então cada filho gerado dará continuidade a execução do for. É necessário que o processo faça um exit ou retorne neste momento.<br />
<br />
;DESAFIO: Exercício status/wait<br />
<br />
O ''status'' passado como parâmetro à função ''wait(&status)'' é, na verdade, o mecanismo de retorno de resultado do ''wait/waitpid''. Ao retornar, esta variável contém informações sobre o resultado da execução do processo filho. Por exemplo, se um processo terminou normalmente (i.e., chamou ''exit''), o comando ''WIFEXITED(status)'' retorna ''true''. Este comando retorna ''false'' se o processo foi abortado (e.g., ''segmentation fault'') ou morto (e.g., ''kill''). Investigue no manual do wait no Linux (''man wait'') o funcionamento do comando WEXITSTATUS(status). <br />
Imagine um problema de busca de dados armazenados na forma de uma matriz de inteiros 4x30. Você está interessado em saber quantas ocorrências de um determinado número existe em cada linha da matriz. Note que que são tarefas que podem ser paralelizadas e usufruir de um sistema capaz de executá-las em paralelo. Faça uma implementação paralelizando 4 processos filhos a partir de um pai, onde cada processo é responsável por uma busca. A quantidade de ocorrências do número buscado é retornada e capturada através de WEXITSTATUS.<br />
<br />
;Syscall EXEC<br />
<br />
*Exemplo exec()<br />
<br />
<syntaxhighlight lang=c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
execl("/bin/ls","ls","-l", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 1: Modificar o código para mostrar que o exec() não retorna (colocar um printf após o exec).<br />
<br />
*Exercício 2: Criar um exemplo (dois programas ) para demonstrar que o exec não cria novo processo. <br />
**Crie um primeiro programa (prog1) que imprime o seu pid e depois faz um exec do segundo programa.<br />
**Crie o segundo programa que simplesmente imprime o pid.<br />
<br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU ANTES DO EXEC: Meu pid é %d\n", getpid());<br />
execl("./prog2","prog2", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU DEPOIS DO EXEC:Meu pid é %d\n", getpid());<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 3: Criar um exemplo usando fork/exec mostrando que um processo pai cria um filho e espera por sua execução. O filho executa o comando "ps aux". Ambos devem mostrar seus pids.<br />
<br />
{{collapse bottom}} <br />
{{collapse top| bg=lightyellow | expandir=true | Threads de aplicação}}<br />
<br />
== Threads de aplicação ==<br />
<br />
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:<br />
*'''getcontext(&a)''': salva o contexto na variável '''a''';<br />
*'''setcontext(&a)''': restaura um contexto salvo anteriormente na variável '''a''';<br />
*'''swapcontext(&a,&b)''': salva o contexto atual na variável '''a''' e restaura o contexto salvo anteriormente na variável '''b''';<br />
*'''makecontext(&a, ...)''': ajusta parâmetros internos do contexto salvo em '''a''';<br />
*'''ucontext_t''': as variáveis '''a''' e '''b''' são do tipo '''ucontext_t'''. Este tipo armazena um contexto.<br />
<br />
Busque mais informações sobre estas funções utilizando o programa manpage do Linux (ex.: man getcontext).<br />
<br />
Estude o código no arquivo pingpong.c abaixo e explique seu funcionamento.<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
*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.<br />
*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.<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain, cFnew;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_new(void * arg1, void * arg2,void * arg3,void * arg4) <br />
{<br />
printf ("%s: Primeira string %s %s %s\n",(char*) arg1,(char*) arg2,(char*) arg3, (char*) arg4);<br />
swapcontext(&cFnew, &cMain); <br />
}<br />
<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
<br />
getcontext(&cFnew);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cFnew.uc_stack.ss_sp = stack ;<br />
cFnew.uc_stack.ss_size = STACKSIZE;<br />
cFnew.uc_stack.ss_flags = 0;<br />
cFnew.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cFnew, (void*)(*f_new), 4, "\tF_new", "\tAlo", "\tMundo","\tReal");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
swapcontext(&cMain, &cFnew);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
--><br />
Exercício 3: O que acontece se um dos threads é colocado para dormir? Todos os demais threads param a sua execução.<br />
<br />
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/<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Trocas de mensagens com pipes}}<br />
<br />
== Trocas de mensagens com pipes ==<br />
<br />
;Troca de mensagens<br />
Um mecanismo disponibilizado por sistemas UNIX para troca de mensagens entre processos é o PIPE. Pipes são mecanismos de comunicação indireta onde mensagens são trocadas através de ''mailboxes''. Cada ''mailbox'' possui um identificador único, permitindo que processos identifiquem o canal de comunicação entre eles. O fluxo de mensagens em um Pipe é:<br />
*'''unidirecional''': sobre um mesmo pipe, apenas um processo envia mensagens e um processo recebe mensagens;<br />
*'''FIFO''': as mensagens são entregues na ordem de envio;<br />
*'''não-estruturado''': não há estrutura pré-definida para o formato da mensagem.<br />
No UNIX, pipes são inicializados através da '''SystemCall''' ''pipe'', que possui a seguinte sintaxe:<br />
*''int pipe(int pipefd[2])'': ''pipe'' inicializa um novo pipe no sistema e retorna, no array pipefd, os descritores identificando cada uma das pontas do pipe. A primeira posição do array, i.e. pipefd[0], recebe o descritor que pode ser aberto apenas para leitura, enquanto a segunda posição do array, i.e. pipefd[1], recebe o descritor que pode ser aberto apenas para escrita. A função retorna zero no caso de sucesso, ou -1 se ocorrer erro.<br />
As primitivas send/receive para uso de um pipe no UNIX são implementadas por '''SystemCalls''' read/write, conforme segue:<br />
*''ssize_t read(int fd, void *buf, size_t count)'': “puxa” dados do pipe identificado pelo descritor fd. Os dados recebidos são os apontados pelo ponteiro buf, sendo count a quantidade máxima de bytes a serem recebidos. A função retorna o número de bytes recebidos.<br />
*''ssize_t write(int fd, const void *buf, size_t count)'': “empurra” dados no pipe identificado pelo descritor fd. Os dados transmitidos são os apontados pelo ponteiro buf, sendo count a quantidade de bytes a serem transmitidos. A função retorna o número de bytes transmitidos.<br />
<br />
*Exemplo 1: Transmitindo e recebendo pelo próprio processo<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main()<br />
{<br />
int fd[2];<br />
char *ptr = "Alo eu mesmo";<br />
char *ptr_alvo;<br />
int tamanho_dados, ret;<br />
<br />
tamanho_dados = strlen(ptr)+1;<br />
<br />
if (pipe(fd)==-1){<br />
printf ("erro criação pipe\n");<br />
exit(-1);<br />
}<br />
printf("Transmitido %d bytes\n", tamanho_dados);<br />
write (fd[1], ptr, tamanho_dados);<br />
<br />
ptr_alvo = malloc(tamanho_dados);<br />
<br />
ret=read(fd[0],ptr_alvo,tamanho_dados);<br />
<br />
printf("ret = %d dados => %s\n", ret, ptr_alvo); <br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
*Exemplo 2: Abaixo há um exemplo de programa criando um pipe e compartilhando os descritores entre dois processos (criados via ''fork()'').<br />
<syntaxhighlight lang=c><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
<br />
char *message = "This is a message!!!" ;<br />
<br />
main()<br />
{<br />
char buf[1024] ;<br />
int fd[2];<br />
pipe(fd); /*create pipe*/<br />
if (fork() != 0) { /* I am the parent */<br />
write(fd[1], message, strlen (message) + 1) ;<br />
}<br />
else { /*Child code */<br />
read(fd[0], buf, 1024) ;<br />
printf("Got this from MaMa!!: %s\n", buf) ;<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
*'''Exercício 1: construa um “pipeline”'''. Crie um programa que conecta 4 processos através de 3 pipes. Utilize ''fork()'' para criar vários processos.<br />
<br />
<syntaxhighlight lang=cpp><br />
<br />
//Solução possível<br />
<br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
pipe(fd);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
<br />
</syntaxhighlight><br />
<br />
*'''Exercício 3: Modifique o exercício anterior para que o processo D, através de um novo pipe, mande uma mensagem diretamente para o pai de todos.<br />
<br />
<!--<br />
<code><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
int fd_retorno[2];<br />
<br />
pipe(fd);<br />
pipe(fd_retorno);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size);<br />
read(fd_retorno[0], buf, size);<br />
printf("PAI:%s\n", buf); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
char *ptr_msg_ret="Ok msg de D para o pai";<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
write(fd_retorno[1],ptr_msg_ret,strlen(ptr_msg_ret)+1);<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
*'''Exercício 3: Consultor de Login de Acesso:'''. Estude o link https://www.geeksforgeeks.org/named-pipe-fifo-example-c-program/ e projete um programa cliente servidor da seguinte forma: (i) O servidor possui uma tabela de usuários (userid). O user_id é de tamanho fixo de 7 caracteres. O servidor espera por consultas para verificar se um usuário está na tabela. Se estiver responde com o caracter 'S' senão com 'N'. (ii) O cliente espera por user_id no teclado e consulta o servidor sobre sua existência na tabela. O cliente imprime na tabela a existência ou não do usuário.<br />
<br />
*'''Exercício 4: cópia de arquivo'''. Projete um programa de cópia de arquivos chamado FileCopy usando pipes comuns. Esse programa receberá dois parâmetros: o primeiro é o nome do arquivo a ser copiado e o segundo é o nome do arquivo copiado. Em seguida, o programa criará um pipe comum e gravará nele o conteúdo do arquivo a ser copiado. O processo filho lerá esse arquivo do pipe e o gravará no arquivo de destino. Por exemplo, se chamarmos o programa como descrito a seguir:<br />
:<syntaxhighlight lang=bash><br />
$ FileCopy entrada.txt copia.txt<br />
</syntaxhighlight><br />
:o arquivo ''entrada.txt'' será gravado no pipe. O processo filho lerá o conteúdo desse arquivo e o gravará no arquivo de destino ''copia.txt''. Escreva o programa usando os pipes da API POSIX no Linux.<br />
<br />
<br />
{{collapse bottom}}<br />
<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Exercícios sobre Memória Compartilhada}}<br />
<br />
==SHARED MEMORY: Produtor (pai) - Consumidor (filho) - ==<br />
<br />
<!-- Parou aki 20/08<br />
<br />
<br />
*'''Experimento 2:''' Complete o código a seguir para que os processos pai e filho possam compartilhar um segmento de memória. O filho escreve no segmento e o pai imprime na tela o conteúdo da mensagem.<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
char *ptr_msg = "alo pai, tudo bem?"; <br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
//completar aqui<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
<!--<br />
<code><br />
<br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/types.h><br />
#include <string.h><br />
#include <stdlib.h><br />
<br />
int main(void)<br />
{<br />
int fd[2], pipe_ret, filho;<br />
char string[] = "Hello, pipe!\n";<br />
char buffer[20];<br />
<br />
pipe(fd);<br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
/*Mandar string para a extremidade do pipe*/<br />
write(fd[1], string, (strlen(string)+1));<br />
exit(0);<br />
}<br />
else<br />
{<br />
<br />
/* Read in a string from the pipe */<br />
pipe_ret = read(fd[0], buffer, (20*sizeof(char)));<br />
printf("Recebi este texto %s", buffer);<br />
}<br />
<br />
return(0);<br />
}<br />
<br />
<br />
<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
key = ftok("teste_sh.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644 | IPC_CREAT));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
<br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
strncpy(segmento, "mensagem compartilhada", SHM_SIZE); <br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
--><br />
<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Memória Compartilhada}}<br />
*'''Experimento Shared Memory:''' Complete o código a seguir para que os processos pai e filho possam compartilhar um segmento de memória. O filho escreve no segmento e o pai imprime na tela o conteúdo da mensagem.<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
char *ptr_msg = "alo pai, tudo bem?"; <br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
//completar aqui strcpy(segmento, ptr_msg); //aqui deveria testar a cpacidade da área...<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exemplo com ftok:<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
key = ftok("./teste.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644 | IPC_CREAT));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
<br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
strncpy(segmento, "mensagem compartilhada", SHM_SIZE); <br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exemplo com ftok entre processos sem parentesco:<br />
<br />
Criar um arquivo teste.txt e em um terminal executar:<br />
<br />
<syntaxhighlight lang=c><br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
int modo,filho;<br />
<br />
struct minha_struct {<br />
char flag;<br />
int numero;<br />
} *ptr;<br />
<br />
<br />
key = ftok("./teste.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644 | IPC_CREAT));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
ptr = (struct minha_struct *) shmat(shmid, (void *)0, 0);<br />
if ((char *)ptr == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
ptr->flag =0;<br />
ptr->numero = 0;<br />
while (ptr->flag==0) { <br />
printf("%d\n", ptr->numero);<br />
sleep(1);<br />
} <br />
<br />
if (shmdt(ptr) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Em outro terminal executar:<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
struct minha_struct {<br />
char flag;<br />
int numero;<br />
} *ptr;<br />
<br />
<br />
key = ftok("./teste.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
ptr = (struct minha_struct *) shmat(shmid, (void *)0, 0);<br />
if ((char *)ptr == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
<br />
<br />
while (ptr->numero++<10)<br />
sleep(1);<br />
<br />
ptr->flag = 1;<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Exercício Desafio: Implementar o problema do buffer circular usando memória compartilhada.<br />
<br />
{{collapse bottom}}<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Exercício (Algoritmo de Peterson)}}<br />
<br />
== Exercício (Algoritmo de Peterson) ==<br />
<br />
<br />
'''Exercício 1''': Sincronize o código a seguir, de maneira que o processo pai imprima apenas os números impares e o processo filho os números pares. Para isso utilize o algoritmo de '''Peterson''' visto em aula. '''Utilize memória compartilhada''' para comunicação entre os processos.<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
main()<br />
{ <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int i; <br />
<br />
for(i = 0;i < 10;i=i+2){ <br />
printf("Processo pai %d \n", i); <br />
<br />
} <br />
<br />
<br />
}<br />
<br />
else { /*Child code */<br />
int i; <br />
for(i = 1;i < 10;i=i+2){ <br />
printf("Processo filho %d \n", i); <br />
<br />
}<br />
<br />
<br />
}<br />
<br />
exit(0);<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
'''Exercício 2''': Considerando o exercício anterior faça a mesma sincronização, no entanto desta vez utilize a modelagem em software do TSL. <br />
* Em sua experiência, depois de testar diversas vezes as execuções de suas soluções baseadas no algoritmo de '''Peterson''' e '''Tsl''', qual sua opinião sobre as abordagens?<br />
Explique seu raciocínio. <br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Exercício (Semáforos)}}<br />
== Exercício (Semáforos) ==<br />
<br />
<br />
'''Exercício 1''': Sincronize o código a seguir, de maneira que o processo pai imprima apenas os números impares e o processo filho os números pares. Para isso utilize '''Semáforos''' de acordo com a implementação em '''semaforo.h'''. '''Utilize memória compartilhada''' para comunicação entre os processos.<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
main()<br />
{ <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int i; <br />
<br />
for(i = 0;i < 10;i=i+2){ <br />
printf("Processo pai %d \n", i); <br />
sleep(1);<br />
<br />
} <br />
<br />
<br />
}<br />
<br />
else { /*Child code */<br />
int i; <br />
for(i = 1;i < 10;i=i+2){ <br />
printf("Processo filho %d \n", i); <br />
<br />
}<br />
<br />
<br />
}<br />
<br />
exit(0);<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
SEMAFORO.H<br />
<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <sys/sem.h><br />
<br />
<br />
int criar_semaforo(int val, int chave) <br />
{<br />
int semid ;<br />
<br />
union semun {<br />
int val;<br />
struct semid_ds *buf ;<br />
ushort array[1];<br />
} arg_ctl ;<br />
<br />
key_t ft = ftok("/tmp", chave);<br />
<br />
semid = semget(ft,1,IPC_CREAT|IPC_EXCL|0666);<br />
if (semid == -1) {<br />
semid = semget(ft,1,0666); <br />
if (semid == -1) {<br />
perror("Erro semget()");<br />
exit(1) ;<br />
}<br />
}<br />
<br />
arg_ctl.val = val; //valor de início<br />
if (semctl(semid,0,SETVAL,arg_ctl) == -1) {<br />
perror("Erro inicializacao semaforo");<br />
exit(1);<br />
}<br />
return(semid) ;<br />
}<br />
<br />
void P(int semid){<br />
<br />
struct sembuf *sops = malloc(10*sizeof(int));<br />
sops->sem_num = 0;<br />
sops->sem_op = -1;<br />
sops->sem_flg = 0;<br />
semop(semid, sops, 1); <br />
free(sops);<br />
<br />
}<br />
<br />
<br />
void V(int semid){<br />
<br />
struct sembuf *sops = malloc(10*sizeof(int));<br />
sops->sem_num = 0;<br />
sops->sem_op = 1;<br />
sops->sem_flg = 0; <br />
semop(semid, sops, 1); <br />
free(sops);<br />
<br />
} <br />
<br />
<br />
<br />
void sem_delete(int semid) <br />
{<br />
<br />
if (semctl(semid,0,IPC_RMID,0) == -1)<br />
perror("Erro na destruicao do semaforo");<br />
}<br />
<br />
<br />
<br />
<br />
</syntaxhighlight><br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Programação concorrente}}<br />
<br />
== Programação concorrente ==<br />
<br />
;POSIX Threads<br />
A 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):<br />
*''pthread_create'': cria uma thread;<br />
*''pthread_kill'': força a terminação de uma thread;<br />
*''pthread_join'': sincroniza o final de uma thread (qual a diferença/semelhança com o ''wait'' que usamos para processos?);<br />
*''pthread_exit'': finaliza uma thread.<br />
Para utilizar estas funções é necessário linkar o programa à libpthread (''-lpthread''). <br />
<br />
<br />
;POSIX pthread mutex<br />
<br />
A biblioteca pthread implementa um tipo ''pthread_mutex_t'', que garante a exclusão mútua entre threads. Estes mutex são manipulados através das funções (acesse as man-pages das chamadas para maiores detalhes):<br />
*''pthread_mutex_lock'': acessa um mutex.<br />
*''pthread_mutex_trylock'': tenta acessar um mutex (retorna valor indicando sucesso ou falha no lock).<br />
*''pthread_mutex_unlock'': libera um mutex.<br />
<br />
<br />
<br />
<br />
;POSIX Semaphores<br />
<br />
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):<br />
*''sem_init'': inicializa um semáforo;<br />
*''sem_destroy'': destroy um semáforo;<br />
*''sem_wait'': implementa a operação ''p'';<br />
*''sem_post'': implementa a operação ''v''.<br />
Para utilizar estas funções é necessário linkar o programa à librt ou à libpthread (''-lrt'' ou ''-lpthread'').<br />
<br />
;Exercício 1<br />
<br />
O programa abaixo cria 5 threads, e cada uma destas threads atualiza uma variável global (memória compartilhada).<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include <pthread.h><br />
#include <signal.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
pthread_mutex_t mut;<br />
<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
}<br />
</syntaxhighlight><br />
<br />
# Compile este programa. <br />
# Execute este programa várias vezes. Ele funciona? Será que ele gera as saídas esperadas?<br />
# Identifique as '''seções críticas''' do programa.<br />
# Corrija o programa utilizando '''mutex'''. <br />
# Analise a função ''AtualizaSaldo()'' com a sua solução. Lembre-se que o uso do mutex implica em apenas uma thread acessar a seção crítica por vez, enquanto outras threads ficam bloqueadas, esperando. Disso vem que, quanto menor o trecho de código entre um ''lock'' e um ''unlock'', menos tempo uma thread necessita ficar esperando.<br />
# Modifique o programa para usar um semáforo binário ao invés de um mutex em sua solução.<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <cstring><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
<br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
sem_t sem;<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
int value;<br />
sem_wait(&sem);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
sem_getvalue(&sem, &value);<br />
printf("valor sem = %d\n", value);<br />
sem_post(&sem);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
sem_init(&sem,0,1);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
sem_destroy(&sem);<br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
<br />
;Exercício 2<br />
Refaça o exercício 3 usando processos criados com fork e exec. O semáforo deve ser criado em uma região de memória compartilhada.<br />
<br />
;Exercício 3<br />
Implemente com pthreads e semáforos/mutex a solução do produtor/comsumidor.<br />
<br />
;Exercício 4<br />
<br />
O programa abaixo manipula uma matriz de tamanho MxN (veja os defines para o tamanho da matriz). A função ''SumValues'' soma todos os valores em uma linha da matriz. A linha a ser somada é identificada pela variável ''i''. Modifique o programa principal (''main'') nos locais indicados para:<br />
# Criar N threads, uma para somar os valores de cada linha.<br />
# Receber o resultado do somatório de cada linha e gerar o somatório total da matriz.<br />
# Analise o programa: há problemas de sincronização que precisam ser resolvidos? Se sim, resolva-os.<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include "thread.h"<br />
<br />
/* number of matrix columns and rows */<br />
#define M 5<br />
#define N 10<br />
<br />
using namespace std;<br />
<br />
int matrix[N][M];<br />
Thread *threads[N];<br />
<br />
<br />
/* thread function; it sums the values of the matrix in the row */<br />
int SumValues(int i)<br />
{<br />
int n = i; /* number of row */<br />
int total = 0; /* the total of the values in the row */<br />
int j;<br />
for (j = 0; j < M; j++) /* sum values in the "n" row */<br />
total += matrix[n][j];<br />
cout << "The total in row" << n << " is " << total << "." << endl;<br />
/* terminate a thread and return a total in the row */<br />
exit(total);<br />
}<br />
<br />
int main(int argc, char *argv[])<br />
{<br />
int i, j;<br />
int total = 0; /* the total of the values in the matrix */<br />
<br />
/* initialize the matrix */<br />
for (i = 0; i < N; i++)<br />
for (j = 0; j < M; j++)<br />
matrix[i][j] = i * M + j;<br />
<br />
/* create threads */<br />
/* COLOQUE SEU CÓDIGO PARA CRIAR AS THREADS AQUI! */<br />
<br />
/* wait for terminate a threads */<br />
/* COLOQUE SEU CÓDIGO PARA PEGAR O SOMATÓRIO DE LINHAS E TOTALIZAR A SOMA DA MATRIZ AQUI! */<br />
<br />
cout << "The total values in the matrix is " << total << endl;<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Lista de exercícios "Revisão para Prova" }}<br />
<br />
== Lista de exercícios/Revisão para Prova ==<br />
<br />
A lista de exercícios referente a primeira prova (Parte introdutória + Processos) segue neste LINK [http://docente.ifsc.edu.br/andre.damato/sop2018/lista_rev1.pdf | Lista de exercícios]. <br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Primeiro trabalho}}<br />
== JOGO DA VIDA DE CONWAY e JANTAR DOS FILÓSOFOS==<br />
<br />
;Referências<br />
<br />
* [https://www.open-mpi.org/doc/current/ MPI]<br />
<br />
* [https://quark.phy.bnl.gov/~creutz/qcdoc/mpi/mpi.h Tipos de dados MPI]<br />
<br />
* [https://pt.wikipedia.org/wiki/Jogo_da_vida Jogo da Vida]<br />
<br />
<br />
<br />
<br />
A partir da implementação sequencial do Game of Life apresentada a seguir, estude o código e transforme esta implementação em uma implementação paralela utilizando o protocolo de passagem de mensagens MPI.<br />
Perceba que a impĺementação mencionada utiliza como parâmetros de entrada um aquivo contendo o estado inicial do jogo, e o número de gerações que o usuário deseja rodar. A evolução do estado inicial <br />
é impressa na tela passo a passo. Sendo assim, a partir disso:<br />
<br />
*'''1: Elabore uma implementação com 2 processos para o jogo da vida utilizando o protocolo MPI, de maneira que um processo execute uma geração i qualquer e o outro execute a geração seguinte i+1''' <br />
<br />
*'''2: (0,7) Os processos deverão se comunicar utilizando as funções do protocolo MPI.''' <br />
<br />
*'''3: (0,3) Relatório simplificado explicando a sua solução. Utilize diagramas para representar a comunicação entre os processos, explicando como a matriz do jogo é transferida entre os processos. ''' <br />
<br />
*'''4: Entregue o Relatório e o código fonte do trabalho em um pacote compactado via e-mail (PRAZO 19/10). <br />
<br />
<br />
<br />
* ''' Compilar o código com MPI '''<br />
<code><br />
mpicc -o nomeApp arquivo.c<br />
</syntaxhighlight><br />
<br />
* ''' Rodar rodar programa utilizando MPI '''<br />
<code><br />
mpirun -np numeroDeProcessos ./nomeApp entrada.txt gerações<br />
</syntaxhighlight><br />
<br />
* (int) -np: Quantidade de processos que você deseja executar <br />
<br />
* entrada.txt: Arquivo de entrada com estado inicial do jogo <br />
<br />
* (int) gerações: número de gerações que você deseja rodar<br />
<br />
* [http://docente.ifsc.edu.br/andre.damato/sop2018/entrada.txt Arquivo de entrada para Testes]<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
<br />
<br />
<br />
/*<br />
<br />
Conway's Game of Life<br />
<br />
Compilar código com MPI<br />
mpicc -o nomeApp arquivo.c<br />
<br />
<br />
Rodar rodar programa utilizando MPI<br />
<br />
mpirun -np numeroDeProcessos ./nomeApp entrada.txt gerações<br />
<br />
(int) -np: Quantidade de processos que você deseja executar <br />
entrada.txt: Arquivo de entrada com estado inicial do jogo <br />
(int) gerações: número de gerações que você deseja rodar<br />
<br />
<br />
*/<br />
<br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h><br />
#include "mpi.h"<br />
<br />
<br />
//Numero de linhas e colunas<br />
#define nLinhas 32<br />
#define nColunas 82 <br />
<br />
char *matriz[nLinhas];<br />
char *entrada[nLinhas];<br />
<br />
<br />
void iniciar() {<br />
<br />
int i;<br />
<br />
//Alocar espaço em memória para as matrizes<br />
for (i = 0; i < nLinhas; i++ ) <br />
matriz[i] = (char *) malloc((nColunas) * sizeof( char )); <br />
<br />
<br />
}<br />
<br />
int adjacente(char **matriz, int i, int j){<br />
<br />
int x,y, initX, initY, limitX, limitY;<br />
int vizinhos = 0;<br />
<br />
if(i == 0)<br />
initX = 0;<br />
else <br />
initX = -1;<br />
<br />
if(i == (nLinhas-1)) <br />
limitX = 1;<br />
else<br />
limitX = 2;<br />
<br />
<br />
if(y == 0)<br />
initY = 0;<br />
else <br />
initY = -1;<br />
<br />
if(y == (nColunas-3)) <br />
limitY = 1;<br />
else<br />
limitY = 2;<br />
<br />
for(x = initX ; x < limitX; x++){<br />
for(y = initY; y < limitY; y++){<br />
if(matriz[i+x][j+y] == '#') <br />
vizinhos++; <br />
} <br />
}<br />
<br />
<br />
if(matriz[i][j] == '#') <br />
return (vizinhos-1);<br />
else <br />
return vizinhos;<br />
<br />
}<br />
<br />
<br />
void calculoGeracao(char **matriz, int ger) {<br />
<br />
int i, j, a;<br />
char novaGeracao[nLinhas][nColunas];<br />
<br />
/* Aplicando as regras do jogo da vida */<br />
for (i=0; i < nLinhas; i++){ <br />
for (j=0; j < nColunas; j++) {<br />
<br />
a = adjacente(matriz, i, j);<br />
<br />
if (a == 2) novaGeracao[i][j] = matriz[i][j];<br />
if (a == 3) novaGeracao[i][j] = '#';<br />
if (a < 2) novaGeracao[i][j] = ' ';<br />
if (a > 3) novaGeracao[i][j] = ' ';<br />
<br />
if (j == 0)<br />
novaGeracao[i][j] = '"';<br />
} <br />
<br />
novaGeracao[i][79] = '"';<br />
novaGeracao[i][80] = '\n';<br />
<br />
<br />
}<br />
<br />
/* Passando o resultado da nova geração para a matriz de entrada */<br />
for (i=0; i < nLinhas; i++){ <br />
for (j=0; j < nColunas; j++) <br />
matriz[i][j] = novaGeracao[i][j];<br />
}<br />
}<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
main(int argc, char *argv[2]){<br />
<br />
/* Para uso com MPI<br />
<br />
<br />
//Variáveis para uso com MPI<br />
int numeroDeProcessos = 0;<br />
int rank = 0;<br />
MPI_Status status; <br />
<br />
//Iniciar MPI---<br />
MPI_Init( &argc, &argv );<br />
<br />
//Atribui a variável numeroDeProcessos o número de processos passado como parâmetro em -np <br />
MPI_Comm_size( MPI_COMM_WORLD, &numeroDeProcessos );<br />
<br />
//Pega o valor do rank (processo)<br />
MPI_Comm_rank( MPI_COMM_WORLD, &rank );<br />
*/<br />
<br />
<br />
FILE *matrizEntrada;<br />
matrizEntrada = fopen(argv[1], "r");<br />
iniciar();<br />
<br />
<br />
if (matrizEntrada == NULL)<br />
printf ("Não posso abrir o arquivo \"%s\"\n", argv[1]);<br />
<br />
<br />
char str[nColunas];<br />
int linha = 0;<br />
<br />
<br />
<br />
//Lendo o estado inicial do jogo a partir do arquivo<br />
while((fgets(str, nColunas, matrizEntrada) != NULL)&&(linha < nLinhas)){<br />
strcat(matriz[linha], str);<br />
linha++;<br />
}<br />
<br />
int i,gens; <br />
<br />
<br />
for(gens = 0; gens < atoi(argv[2]); gens++){ //Gens é o número de gerações especificado no segundo parâmetro <br />
<br />
calculoGeracao(matriz, gens);<br />
printf("%c[2J",27); // Esta linha serve para limpar a tela antes de imprimir o resultado de uma geração <br />
<br />
//Lendo o estado do jogo e imprime na tela <br />
for(i = 0; i < nLinhas; i++)<br />
printf("%s", matriz[i]); <br />
<br />
sleep(1);<br />
<br />
}<br />
<br />
<br />
for(i = 0; i < nLinhas; i++) <br />
free(matriz[i]); <br />
<br />
<br />
<br />
/* Finaliza o MPI */ <br />
//MPI_Finalize();<br />
<br />
exit(0);<br />
} <br />
<br />
<br />
</syntaxhighlight><br />
<br />
<br />
;Jantar dos Filósofos<br />
O problema clássico Jantar dos Filósofos consiste em que n fluxos (n filósofos) disputam n recursos (n talheres). No problema, para conseguir "jantar" (ou executar), cada filósofo precisa pegar dois talheres adjascentes a ele. Cada recurso é compartilhado por dois filósofos.<br />
*[http://www.doc.ic.ac.uk/~jnm/concurrency/classes/Diners/Diners.html Veja esta simulação]<br />
*[http://en.wikipedia.org/wiki/Dining_philosophers_problem Veja esta descrição do problema]<br />
<br />
<br />
* ''' (0,7) programa abaixo implementa um Jantar dos Filósofos utilizando semáforos para sincronização. Contudo, as chamadas para as operações ''v'' e ''p'' foram removidas, conforme comentários no código. Re-insira as operações no código e analise a solução. Esta modificação é suficiente para garantir que não haverá deadlock? Se sim, mostre o porque. Se não, proponha uma solução completa. '''<br />
<br />
<br />
*''' (0,3) Relatório simplificado explicando a sua solução. ''' <br />
<br />
*''' Entregue o Relatório e o código fonte do trabalho em um pacote compactado via e-mail (PRAZO 19/10). <br />
<br />
<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include "thread.h"<br />
#include "semaphore.h"<br />
<br />
using namespace std;<br />
<br />
const int DELAY = 10000000;<br />
const int ITERATIONS = 5;<br />
<br />
Semaphore chopstick[5];<br />
<br />
int philosopher(int n)<br />
{<br />
cout << "Philosopher " << n << " was born!\n";<br />
<br />
int first = (n < 4)? n : 0; // left for phil 0 .. 3, right for phil 4<br />
int second = (n < 4)? n + 1 : 4; // right for phil 0 .. 3, left for phil 4<br />
<br />
// Foram removidos do laço abaixo:<br />
// - uma chamada para chopstick[first].p()<br />
// - uma chamada para chopstick[second].p()<br />
// - uma chamada para chopstick[first].v()<br />
// - uma chamada para chopstick[second].v()<br />
for(int i = 0; i < ITERATIONS; i++) {<br />
cout << "Philosopher " << n << " thinking ...\n";<br />
for(int i = 0; i < DELAY * 10; i++);<br />
<br />
cout << "Philosopher " << n << " eating ...\n";<br />
for(int i = 0; i < DELAY; i++);<br />
}<br />
<br />
return n;<br />
}<br />
<br />
int main()<br />
{<br />
cout << "The Dining-Philosophers Problem\n";<br />
<br />
Thread * phil[5];<br />
for(int i = 0; i < 5; i++)<br />
phil[i] = new Thread(&philosopher, i);<br />
<br />
int status;<br />
for(int i = 0; i < 5; i++) {<br />
phil[i]->join(&status);<br />
if(status == i)<br />
cout << "Philosopher " << i << " went to heaven!\n";<br />
else<br />
cout << "Philosopher " << i << " went to hell!\n";<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Softwares básicos, caso Hello Word! (Trabalho 2) Entrega dia 09/11}}<br />
<br />
== Softwares básicos, caso Hello Word! ==<br />
<br />
O objetivo do experimento de hoje é pesquisar e entender os processos de atribuição de endereços de programas realizados em tempo de compilação pelos softwares básicos como: compilador, linker, e assembler. Sendo assim, neste experimento vamos utilizar os seguintes softwares para criação e análise de código:<br />
<br />
*'''GCC''': compilador para gerar código objeto a partir de um código de programa escrito na linguagem c;<br />
*'''GNU Linker (LD)''': Para vincular os códigos (módulos) objetos do programa;<br />
*[https://linux.die.net/man/1/ld| Linker ] <br />
*'''GNU Assembler''': Para gerar o código executável a partir do código objeto;<br />
*[https://linux.die.net/man/1/as | assembler]<br />
* '''OBJDUMP''': Para mostrar informações do código;<br />
*[https://linux.die.net/man/1/objdump | Objdump ]<br />
<br />
<br />
A seguir segue descrito o programa a ser utilizado no exercício 1:<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
int main()<br />
{<br />
printf("Hello, World!");<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
Trata-se do programa hello word, este programa apenas exibe uma mensagem na tela. No entanto, vamos analisar como são as etapas confecção do executável a partir deste código ''simples''. <br />
<br />
Exercício 1: <br />
* Compile o programa hello word, e o transforme em código objeto utilizando o programa GCC. Para esta tarefa execute o seguinte comando:<br />
<code><br />
gcc -o hello hello.c <br />
</syntaxhighlight><br />
* Agora abra o código objeto utilizando o programa OBJDUMP.<br />
<code><br />
objdump -D hello<br />
</syntaxhighlight><br />
* Identifique quais são as seções de código obtidas a partir do '''hello.c'''.<br />
* Pesquise e entenda o significado das seções de código: .bss, .txt, .data, .init.<br />
* Faça uma análise e identifique o endereço de memória que o programa ''hello world'' vai ser carregado. <br />
* Este código objeto é relocável? Justifique sua resposta.<br />
* Agora gere o código assembly do hello world.<br />
<code><br />
gcc -S hello.c<br />
</syntaxhighlight> <br />
*Agora gere o código executável utilizando o programa '''AS''' e o programa '''LD'''.<br />
<code><br />
as -o hello.o hello.s<br />
</syntaxhighlight><br />
* Como a etapa de linkagem para a construção do código executável está sendo executada sem o auxílio do '''GCC''', necessitamos vincular manualmente as bibliotecas necessárias. Para criar apropriadamente o executável vamos precisar das bibliotecas '''ld-linux-x86-64.so.2''', '''crt1.o''', '''crti.o''', '''crtn.o'''.<br />
* Para descobrir suas respectivas localizações use o comando '''LOCATE'''. Por exemplo:<br />
<code><br />
<br />
locate crti.o <br />
<br />
</syntaxhighlight><br />
<br />
ou <br />
<br />
<code><br />
<br />
find /usr/ -name crti*<br />
<br />
</syntaxhighlight><br />
<br />
* Agora que já sabemos a localização das bibliotecas necessárias vamos vincular essas a nossa aplicação.<br />
<code><br />
ld --dynamic-linker /caminho/ld-linux-x86-64.so.2 /caminho/crt1.o /caminho/crti.o /caminho/crtn.o hello.o -lc -o hello.exe<br />
</syntaxhighlight><br />
<br />
* Agora abra o código objeto utilizando o programa OBJDUMP.<br />
* Faça uma análise e identifique o endereço de memória em que o programa ''hello world'' inicializa suas estruturas na memória.<br />
* Dica!<br />
<code><br />
objdump -D -s -j .init hello.exe<br />
</syntaxhighlight><br />
* Houve diferença entre os endereços do programa executável em relação ao código objeto? Explique.<br />
* Explique as principais diferenças entre o arquivo objeto .o e o executável final. (dica utilize o objdump para fazer essa análise)<br />
{{collapse bottom}}<br />
<ol><br />
<li> Estudar e executar o código em http://cs.lmu.edu/~ray/notes/gasexamples/ <br />
Detalhes das chamadas na arquitetura x86_64 ver em https://lwn.net/Articles/604287/ <br />
<li>Estudar e executar o código usando a função (em conformidade com a API POSIX) write() para o ''hello world'':<br />
<code><br />
#include <unistd.h> <br />
<br />
main()<br />
{<br />
write(1,"Alo Mundo\n",10);<br />
}<br />
</syntaxhighlight><br />
</li><br />
<li> Use o comando strace para verificar todas as chamadas de sistema dos programas acima.<br />
</li><br />
<li><br />
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:<br />
<code><br />
main()<br />
{<br />
meu_hello_world();<br />
}<br />
</syntaxhighlight><br />
</li><br />
Gere o assembly do código em C e discuta a diferença entre uma chamada de função e uma chamada de sistema.<br />
<li><br />
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:<br />
<code><br />
#include <string.h><br />
main()<br />
{<br />
char *p="Tudo bem com vocês?";<br />
meu_hello_world(p, strlen(p));<br />
}<br />
</syntaxhighlight><br />
Solução:<br />
{{collapse top|Solução}}<br />
<code><br />
modificado de http://cs.lmu.edu/~ray/notes/gasexamples/<br />
.global meu_hello_world<br />
<br />
.text<br />
meu_hello_world:<br />
<br />
push %rdi # salva primeiro parâmetro<br />
push %rsi # salva segundo parâmetro<br />
mov $1, %rax # system call 1 é write<br />
mov $1, %rdi # file handle 1 é stdout<br />
mov $message, %rsi # endereço da string<br />
mov $13, %rdx # número de bytes da string<br />
syscall # chamada ao sistema<br />
<br />
pop %rdx # o que havia sido passado em rsi (número de bytes) é colocado em rdx<br />
pop %rsi # o que havia sido colocado em rdi (endereço da string) é colocado em rsi<br />
mov $1, %rax # system call 1 is write<br />
mov $1, %rdi # file handle 1 é stdout<br />
syscall # nova chamada ao sistema<br />
<br />
ret<br />
<br />
message:<br />
.ascii "Hello, World\n"<br />
</syntaxhighlight><br />
</li><br />
</ol><br />
{{collapse bottom}}</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=SOP29005-2019-2&diff=162028SOP29005-2019-22019-10-04T11:26:27Z<p>127.0.0.1: /* Desafio */</p>
<hr />
<div>=AULA 1 - Dia 30/07/2019=<br />
<br />
===Objetivos/Conteúdos===<br />
<br />
*Apresentação do Plano de Ensino<br />
**Objetivos e Conteúdo Programático da Disciplina (ver SIGAA)<br />
**Forma de Avaliação (ver SIGAA)<br />
<br />
*Introdução a Sistemas Operacionais (Cap1. do Silberschatz)<br />
**O que faz um sistema operacional (1.1)<br />
**Organização e Arquitetura de um Sistema Computacional (1.2 e 1.3)<br />
***Importância da Interrupção e Timers (1.2.1)<br />
***Estrutura de Armazenamento (1.2.2)<br />
***Estrutura de IO (1.2.3)<br />
**Estrutura e Operações de um Sistema Operacional (1.4 e 1.5)<br />
<br />
===Material de Referência===<br />
<br />
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte1.pdf Apresentação sobre histórico visão geral e estruturas básicas de um SO]<br />
* [http://codex.cs.yale.edu/avi/os-book/OSE1/slide-dir/index.html Slides Silberschatz Oitava Edição]<br />
* [http://professor.unisinos.br/barbosa/SO/ch1br.ppt Tradução Slides Silberschatz Cap1]<br />
* [http://professor.unisinos.br/barbosa/SO/ch2br.ppt Tradução Slides Silberschatz Cap2]<br />
* [http://professor.unisinos.br/barbosa/SO/ch3br.ppt Tradução Slides Silberschatz Cap3]<br />
* [http://professor.unisinos.br/barbosa/SO/ch4br.ppt Tradução Slides Silberschatz Cap4]<br />
* [http://wiki.inf.ufpr.br/maziero/doku.php?id=so:livro_de_sistemas_operacionais Livro do Prof.Maziero]<br />
* [http://deptinfo.unice.fr/~rr/l3systres/ Université Nice Sophia Antipolis]<br />
<br />
Arliones:<br />
<br />
*[https://www.dropbox.com/s/dt80g3tml65rpmg/SOP29005-parte6.odp?dl=0]<br />
*[https://www.dropbox.com/s/7lneavq0go9kz2t/SOP29005-parte7.odp?dl=0]<br />
<br />
===Leitura Recomendada===<br />
<br />
*Cap.1 do Silberschatz principalmente:<br />
**1.1 a 1.9<br />
<br />
===Exercícios Práticos de Apoio a Aula===<br />
<br />
Na sequência. com fins motivacionais, são apresentados alguns exercícios ilustrando conceitos de processos, arquivos e permissionamento.<br />
<br />
<ol><br />
<li><br />
Comando para ver todos os processos no linux:<br />
<code><br />
$ ps aux<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Colocar 2 processos se executando no contexto de um terminal e verificar número dos processos e então "destruí-los":<br />
<code><br />
$ yes > /dev/null<br />
$ yes > /dev/null<br />
$ ps <br />
$ kill -9 <pid_yes><br />
$ kill -9 <pid_yes><br />
</syntaxhighlight><br />
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.<br />
</li><br />
<li><br />
Criar um terminal adicional<br />
<code><br />
$ xterm<br />
</syntaxhighlight><br />
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:<br />
<code><br />
$ echo Alo Terminal > /dev/pts/2<br />
$ kill -9 <pid_terminal><br />
</syntaxhighlight><br />
</li><br />
<li><br />
Comunicação entre processos:<br />
<code><br />
$ cat /etc/passwd | grep home | wc -l<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Retirando a permissão de leitura de um arquivo em nível de usuário proprietário:<br />
<code><br />
$ echo Alo Mundo > alfa.txt<br />
$ ls -l alfa.txt<br />
$ cat alfa.txt<br />
$ chmod u-r alfa.txt<br />
$ cat alfa.txt<br />
$ chmod u+r alfa.txt<br />
$ cat alfa.txt <br />
</syntaxhighlight><br />
</li><br />
</ol><br />
<br />
=AULA 2 - Dia 2/08/2019=<br />
<br />
===Objetivos/Conteúdos===<br />
<br />
*Continuação da Aula<br />
*Estruturas do Sistema Operacional (cap.2)<br />
**Serviços do Sistema Operacional (2.1)<br />
**Interfaces com Usuários (2.2)<br />
**Chamadas do Sistema (2.3)<br />
**Tipos de Chamadas de Sistema (2.4) ver Fig.2.8<br />
***Chamadas de Controle de Processos<br />
**Arquiteturas e Estruturas de Sistemas Operacionais (2.7)<br />
**Máquinas Virtuais (2.8)<br />
<br />
===Material de Referência===<br />
<br />
* [http://docente.ifsc.edu.br/arliones.hoeller/sop/slides/SOP29005-parte1.pdf Apresentação sobre histórico visão geral<br />
* [http://www.fil.univ-lille1.fr/~sedoglav/OS/TP.html ]<br />
<br />
===Leitura Recomendada===<br />
<br />
*Cap.2 do Silberschatz principalmente:<br />
**2.1 a 2.8<br />
<br />
===Exercícios===<br />
<br />
=AULA 3 - Dia 7/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*Continuação da aula anterior<br />
**Chamadas do Sistema (2.3)<br />
**Tipos de Chamadas de Sistema (2.4) ver Fig.2.8<br />
***Chamadas de Controle de Processos<br />
**Arquiteturas e Estruturas de Sistemas Operacionais (2.7)<br />
**Máquinas Virtuais (2.8)<br />
<br />
===Exercícios===<br />
<br />
<ol><br />
<li> Estudar e executar o código em http://cs.lmu.edu/~ray/notes/gasexamples/ <br />
Detalhes das chamadas na arquitetura x86_64 ver em https://lwn.net/Articles/604287/ <br />
<li>Estudar (usar o man) e executar o código usando a função (em conformidade com a API POSIX) write() para o ''hello world'':<br />
<code><br />
#include <unistd.h> <br />
<br />
main()<br />
{<br />
write(1,"Alo Mundo\n",10);<br />
}<br />
</syntaxhighlight><br />
</li><br />
<li> Use o comando strace para verificar todas as chamadas de sistema dos programas acima.<br />
</li><br />
<li><br />
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() 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:<br />
<code><br />
void meu_hello();<br />
<br />
int main()<br />
{<br />
meu_hello();<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
</li><br />
Gere o assembly do código em C e discuta a diferença entre uma chamada de função e uma chamada de sistema.<br />
<li><br />
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:<br />
<code><br />
#include <string.h><br />
main()<br />
{<br />
char *p="Tudo bem com vocês?";<br />
meu_hello_world(p, strlen(p));<br />
}<br />
</syntaxhighlight><br />
Solução:<br />
{{collapse top|Solução}}<br />
<code><br />
modificado de http://cs.lmu.edu/~ray/notes/gasexamples/<br />
.global meu_hello_world<br />
<br />
.text<br />
meu_hello_world:<br />
<br />
push %rdi # salva primeiro parâmetro<br />
push %rsi # salva segundo parâmetro<br />
mov $1, %rax # system call 1 é write<br />
mov $1, %rdi # file handle 1 é stdout<br />
mov $message, %rsi # endereço da string<br />
mov $13, %rdx # número de bytes da string<br />
syscall # chamada ao sistema<br />
<br />
pop %rdx # o que havia sido passado em rsi (número de bytes) é colocado em rdx<br />
pop %rsi # o que havia sido colocado em rdi (endereço da string) é colocado em rsi<br />
mov $1, %rax # system call 1 is write<br />
mov $1, %rdi # file handle 1 é stdout<br />
syscall # nova chamada ao sistema<br />
<br />
ret<br />
<br />
message:<br />
.ascii "Hello, World\n"<br />
</syntaxhighlight><br />
</li><br />
</ol><br />
{{collapse bottom}}<br />
<br />
=AULA 4 - Dia 9/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*PARTE 2A: Gerenciamento de Processos (cap.3)<br />
*3.1.Conceito de Processo<br />
*3.2.Escalonamento de Processos<br />
*3.3.Operações sobre Processos (Laboratório Operações sobre Processos no Linux: Fork/Exec/Wait)<br />
<br />
===Material de Referência===<br />
<br />
*Slides do Cap.3 - Silberschatz<br />
*Laboratório Fork/Exec/Wait<br />
<br />
=== Exercícios de Demonstração===<br />
<br />
#Executar em um terminal o comando top. Em um outro terminal executar:<br />
yes > /dev/null &<br />
yes > /dev/null &<br />
#Parar um dos processos yes<br />
kill -STOP <pid_yes><br />
#Continuar o processo<br />
kill -CONT <pid_yes><br />
#Destruir todos<br />
killall yes<br />
<br />
=AULA 5 - Dia 14/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*Ainda Processos<br />
*Cap.3.2..Escalonamento de Processos<br />
*Cap.2.3.Operaçṍes sobre processos<br />
*Finalização do Laboratório Fork/Exec/Wait<br />
<br />
===Adendo===<br />
<br />
*Estudar e comentar [https://www.geeksforgeeks.org/wait-system-call-c/]<br />
<br />
=AULA 6 - Dia 16/08/2019=<br />
<br />
===Objetivos===<br />
<br />
*Comunicação Interprocessos (3.4 e 3.5)<br />
*Laboratório de Memória Compartilhada<br />
<br />
=AULA 7 - Dia 21/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Comunicação Interprocessos: Troca de Mensagens (3.6)<br />
*Laboratório de Pipes<br />
<br />
=AULA 8 - Dia 23/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Finalização Lab. pipes nomeados.<br />
*Threads ((cap.4.1, 4.2)<br />
*Lab.Threads de Aplicação<br />
<br />
=AULA 9 - Dia 28/08/2019=<br />
<br />
*Laboratório: Ainda Threads - Um escalonador semi-automático<br />
<br />
<br />
=AULA 10 - Dia 30/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Repassar um primeiro estudo sobre o RTOS<br />
*Revisar Processos e Threads<br />
<br />
==Questionário - Processos==<br />
<br />
#Conceitue processo. Descreva e explique cada uma das seções de um processo na memória.<br />
#Faça um diagrama e explique os possíveis estados de um processo no sistema. O que produz a transição entre estados?<br />
#O que é um Bloco de Controle de Processo? Quais informações ficam armazenadas neste bloco?<br />
#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.<br />
#Explique o que é multiprogramação e escalonamento de processos.<br />
#O que é a fila de processos prontos?<br />
#Diferencie um processo limitado por IO de um processo limitado por CPU.<br />
#Diferencie escalonamento de longo prazo de escalonamento de curto prazo.<br />
#Discuta o papel da interrupção na troca de contexto entre processos.<br />
#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?<br />
#Explique como funciona a chamada exec no UNIX/Linux<br />
#Explique como funciona a chamada wait no UNIX/Linux e como é possível retornar valores de um filho para o pai.<br />
#Faça um esqueleto de um programa UNIX/Linux que ao se tornar processo cria 3 filhos e espera pela execução dos mesmos.<br />
<br />
==Questionário - Comunicação entre Processos==<br />
<br />
#Diferenciar processos independentes de processos cooperantes.<br />
#Enumere e explique quatro razões para cooperação entre processos.<br />
#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.<br />
#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.<br />
#A memória compartilhada requer chamada ao sistema na sua operação? Discuta.<br />
#Por que o processo de troca de mensagem deve ser mais lento que a memória compartilhada?<br />
#Apresente em pseudocódigo uma proposta de funcionamento do problema do produtor consumidor usando memória compartilhada.<br />
#A construção de uma solução para o problema produtor consumidor pode ser facilitado pelo uso da memória compartilhada? Discuta.<br />
#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?<br />
#Enumere três métodos de implementação de uma lógica de ligação (link) entre processos.<br />
#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.<br />
#Descreva a variante assimétrica da troca direta de mensagens. O que muda em termos de primitiva de comunicação?<br />
#Descreva o problema de hard-coding associado a nomeação direta e como pode ser contornado através da nomeação/comunicação indireta?<br />
#O que é uma caixa postal? Como o Posix identifica uma caixa postal no caso de fila de mensagens?<br />
#Dois processos podem usar mais do que uma caixa postal para se comunicar? Qual a condição para que isto ocorra?<br />
#Descreva as duas operações básicas para a troca de mensagens com Caixa Postal.<br />
#Descreva na comunicação indireta via Caixa Postal as 3 propriedades básicas.<br />
#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.<br />
#De que forma a caixa postal estando no espaço de endereçamento de um processo (propriedade) afeta a recepção por mensagens? Descreva.<br />
#Quais as operações sobre uma caixa postal criada no espaço do sistema operacional deverão ser disponíveis? Descreva.<br />
#A transmissão de mensagem pode ser com e sem bloqueio. Descreva as 4 possibilidades (síncrona/assíncrona).<br />
#Discuta as 3 possibilidades de armazenamento de mensagens em buffer. Em que condições um remetente pode ser bloqueado?<br />
<br />
==ETAPA 1 - Projeto Final==<br />
<br />
*Apresentação (slides) sobre a parte de gerenciamento de tarefas no RTOS;<br />
*apresentação dia 18/09/2019<br />
<br />
==Referências==<br />
<br />
*[https://www.freertos.org/RTOS.html Site do FreeRTOS] ver Mastering the FreeRTOS Real Time Kernel - a Hands On Tutorial Guide <br />
*[https://www.embarcados.com.br/rtos-sistema-operacional-de-tempo-real/]<br />
*[https://github.com/feilipu/avrfreertos]<br />
<br />
=AULA 11 - Dia 4/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Pico de CPU X Pico de IO <br />
*Preempção X Não Preempção<br />
*Escalonamento de Processos: Escalonamento FCFS<br />
<br />
<br />
=AULA 12 - Dia 6/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Escalonamento de Processos: <br />
**Shortest Job First (preemptivo e não preemptivo)<br />
**Prioridade (preemptivo e não preemptivo)<br />
**Round-Robin: Preemptivo<br />
*Lab.Round Robin<br />
<br />
==Material de Referência==<br />
<br />
http://docente.ifsc.edu.br/andre.damato/sop2018/SOP2018-parte2.pdf<br />
<br />
<br />
=AULA 13 - Dia 13/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Sincronização entre Processos<br />
*Laboratório do Esquema de Peterson<br />
<br />
==Material de Referência==<br />
<br />
*Livro Silberchatz<br />
*https://www.os-book.com/OSE1/slide-dir/PPT-dir/ch6.ppt<br />
<br />
=AULA 14 - Dia 18/08/2019=<br />
<br />
==Objetivos==<br />
<br />
*Sincronização entre Processos<br />
*Lock de Hardware<br />
*Laboratório do TSL<br />
<br />
==Laboratório Proposto==<br />
<br />
*Refazer o problema proposto usando uma instrução simualada de test and set. Prever um liite superior para entrada de um processo na região crítica.<br />
<br />
==Material de Referência==<br />
<br />
*Livro Silberchatz<br />
*https://www.os-book.com/OSE1/slide-dir/PPT-dir/ch6.ppt<br />
<br />
<br />
=AULA 15 - Dia 20/08/2019=<br />
<br />
==O ATmega238 usado no Arduino UNO==<br />
<br />
Ver [https://pt.wikipedia.org/wiki/ATmega328]<br />
<br />
==O Arduino UNO==<br />
<br />
Ver [https://pt.wikipedia.org/wiki/Arduino]<br />
Ver [https://github.com/feilipu/Arduino_FreeRTOS_Library]<br />
<br />
==O FreeRtos para o Arduino==<br />
<br />
Ver [https://github.com/feilipu/Arduino_FreeRTOS_Library]<br />
<br />
Para instalar no IDE:<br />
*Baixar o ZIP do link acima<br />
*No IDE importar a biblioteca:<br />
**sketch->IncluirBiblioteca->Adicionar do arquivo ZIP<br />
<br />
<br />
==Código Experimental==<br />
<br />
Este código demonstra a ocorrência de "race condition".<br />
<br />
<syntaxhighlight lang=c><br />
// Code based on Examples of Arduino and examples <br />
// from https://github.com/feilipu/Arduino_FreeRTOS_Library<br />
<br />
#include <Arduino_FreeRTOS.h><br />
#include <FreeRTOSVariant.h><br />
#include <task.h><br />
#include <semphr.h><br />
<br />
#define TAM_BUFF 10<br />
<br />
volatile unsigned long race_flag=0xFFEEDDCC;<br />
volatile unsigned long int cont;<br />
int task_cont=0;<br />
<br />
void PrintSerial( void *pvParameters ); // Task para imprimir valor de race_flag<br />
void TaskBlink( void *pvParameters );<br />
void TaskSetarace_flag(void *pvParameters); //Task que atribui race_flag=0xFFEEDDCC<br />
void TaskZerarace_flag(void *pvParameters); //Task que atribui race_flag=0xAA0000AA<br />
<br />
// função de setup<br />
<br />
void setup() {<br />
<br />
Serial.begin(9600);<br />
<br />
while (!Serial) {<br />
; // wait for serial port to connect. Needed for native USB, on LEONARDO, MICRO, YUN, and other 32u4 based boards.<br />
}<br />
<br />
<br />
// criar as 2 tarefas<br />
<br />
xTaskCreate(<br />
TaskBlink<br />
, (const portCHAR *)"Blink" // A name just for humans<br />
, 128 // This stack size can be checked & adjusted by reading the Stack Highwater<br />
, NULL<br />
, 1 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.<br />
, NULL );<br />
<br />
xTaskCreate(<br />
TaskPrintSerial<br />
, (const portCHAR *) "PrintSerial"<br />
, 128 // Stack size<br />
, NULL<br />
, 1 // Priority<br />
, NULL );<br />
<br />
xTaskCreate(<br />
TaskSetarace_flag<br />
, (const portCHAR *) "Setarace_flag"<br />
, 128 // Stack size<br />
, NULL<br />
, 1 // Priority<br />
, NULL );<br />
<br />
xTaskCreate(<br />
TaskZerarace_flag<br />
, (const portCHAR *) "Zerarace_flag"<br />
, 128 // Stack size<br />
, NULL<br />
, 1 // Priority<br />
, NULL );<br />
<br />
cont = race_flag;<br />
<br />
// escalonador toma conta a partir daqui<br />
<br />
}<br />
<br />
void loop()<br />
{<br />
// nada a fazer aqui<br />
}<br />
<br />
/*--------------------------------------------------*/<br />
/*---------------------- Tasks ---------------------*/<br />
/*--------------------------------------------------*/<br />
<br />
void TaskBlink(void *pvParameters) // This is a task.<br />
{<br />
(void) pvParameters;<br />
<br />
/*<br />
Blink<br />
Turns on an LED on for one second, then off for one second, repeatedly.<br />
<br />
Most Arduinos have an on-board LED you can control. On the UNO, LEONARDO, MEGA, and ZERO <br />
it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN takes care <br />
of use the correct LED pin whatever is the board used.<br />
<br />
The MICRO does not have a LED_BUILTIN available. For the MICRO board please substitute<br />
the LED_BUILTIN definition with either LED_BUILTIN_RX or LED_BUILTIN_TX.<br />
e.g. pinMode(LED_BUILTIN_RX, OUTPUT); etc.<br />
<br />
If you want to know what pin the on-board LED is connected to on your Arduino model, check<br />
the Technical Specs of your board at https://www.arduino.cc/en/Main/Products<br />
<br />
This example code is in the public domain.<br />
<br />
modified 8 May 2014<br />
by Scott Fitzgerald<br />
<br />
modified 2 Sep 2016<br />
by Arturo Guadalupi<br />
*/<br />
<br />
// initialize digital LED_BUILTIN on pin 13 as an output.<br />
pinMode(LED_BUILTIN, OUTPUT);<br />
<br />
for (;;) // A Task shall never return or exit.<br />
{<br />
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)<br />
vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second<br />
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW<br />
vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second<br />
}<br />
}<br />
<br />
<br />
<br />
<br />
void TaskPrintSerial(void *pvParameters) // Task que imprime na serial - must be improved...<br />
{<br />
(void) pvParameters;<br />
/*<br />
<br />
*/<br />
<br />
<br />
for (;;)<br />
{ <br />
while (cont==0xAA0000AA || cont==0xFFEEDDCC)<br />
cont = race_flag;<br />
;<br />
<br />
Serial.println("Problemas: valor race_flag é");<br />
Serial.println(cont, HEX);<br />
<br />
vTaskDelay(5); // one tick delay (15ms) in between reads for stability - b<br />
cont = race_flag;<br />
}<br />
}<br />
<br />
void TaskSetarace_flag(void *pvParameters) <br />
{<br />
(void) pvParameters;<br />
const TickType_t xMaxBlockTimeTicks = 0x20;<br />
/*<br />
<br />
*/<br />
<br />
race_flag=0xAA0000AA;<br />
for (;;)<br />
{<br />
race_flag=0xAA0000AA;<br />
//Serial.println("Produtor");<br />
vTaskDelay( ( rand() %xMaxBlockTimeTicks) ); <br />
} <br />
<br />
}<br />
<br />
void TaskZerarace_flag(void *pvParameters) <br />
{<br />
(void) pvParameters;<br />
const TickType_t xMaxBlockTimeTicks = 0x20;<br />
/*<br />
<br />
*/<br />
race_flag=0xFFEEDDCC;<br />
<br />
for (;;)<br />
{<br />
race_flag=0xFFEEDDCC;<br />
vTaskDelay( ( rand() %xMaxBlockTimeTicks) ); <br />
if(task_cont++==100) {<br />
delay(1);<br />
Serial.println("Fim TaskZera - valor race_flag ");<br />
Serial.println(race_flag, HEX);<br />
for(;;);<br />
} <br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
=AULA 16 - Dia 25/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Preparação de exemplos de RTOS sobre Arduíno para apresentação na sexta;<br />
<br />
=Laboratórios Propostos= <br />
<br />
Considere o código abaixo. Observe que a região de dados compartilhada shared_data é zerada pelo pai e setada pelo processo filho. O pai detecta inconsistências nos dados que operou. Tente corrigir usando o esquema de Peterson para acesso a região crítica. Crie uma função de entrada e de saída da região crítica.<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
<br />
<br />
#define BUFFER_SIZE 4096<br />
char *shared_data;<br />
char reference_data[BUFFER_SIZE];<br />
<br />
main()<br />
{ <br />
key_t key;<br />
int shmid;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, BUFFER_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
shared_data = shmat(shmid, (void *)0, 0);<br />
<br />
if (shared_data == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int count=0; <br />
memset(reference_data,0,BUFFER_SIZE); <br />
for(;;){ <br />
memset(shared_data,0,BUFFER_SIZE);<br />
if (memcmp(shared_data, reference_data, BUFFER_SIZE)!=0) {<br />
count++;<br />
if (count%1000000==0)<br />
printf("Processo pai detectou algo errado nos dados %d\n", count); <br />
} <br />
} <br />
<br />
<br />
}<br />
else { /*Child code */<br />
<br />
for(;;){ <br />
memset(shared_data,1,BUFFER_SIZE); <br />
}<br />
<br />
}<br />
<br />
if (shmdt(shared_data) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
Possível solução:<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
#include <unistd.h><br />
<br />
#define BUFFER_SIZE 4096<br />
#define ID_PAI 0<br />
#define ID_FILHO 1<br />
#define FALSE 0<br />
#define TRUE 1<br />
<br />
char *shared_data;<br />
char reference_data[BUFFER_SIZE];<br />
<br />
struct tipo_peterson{<br />
char flag[2];<br />
char turn;<br />
} *pet_struct;<br />
<br />
void ent_sec_crit(int id)<br />
{<br />
char id_outro = (id+1)%2;<br />
<br />
pet_struct->flag[id] = TRUE; // indica que o processo deseja entrar na região crítica<br />
pet_struct->turn = id_outro; // o processo sinaliza para o outrao entrar, <br />
// caso o outro esteja entrando<br />
// este ponto é uma race condition: turn pode ser 0 ou 1 <br />
while ( (pet_struct->flag[id_outro]==TRUE) && (pet_struct->turn == id_outro) )<br />
;<br />
}<br />
<br />
void sai_sec_crit(int id)<br />
{<br />
pet_struct->flag[id] = FALSE;<br />
}<br />
<br />
int main()<br />
{ <br />
key_t key;<br />
int shmid;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, BUFFER_SIZE+sizeof(struct tipo_peterson), S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
shared_data = shmat(shmid, (void *)0, 0);<br />
pet_struct = (struct tipo_peterson *) (shared_data + BUFFER_SIZE); <br />
<br />
if (shared_data == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int count=0; <br />
memset(reference_data,0,BUFFER_SIZE); <br />
for(;;){ <br />
ent_sec_crit(ID_PAI);<br />
memset(shared_data,0,BUFFER_SIZE);<br />
if (memcmp(shared_data, reference_data, BUFFER_SIZE)!=0) {<br />
count++;<br />
if (count%1000000==0)<br />
printf("Processo pai detectou algo errado nos dados %d\n", count); <br />
} <br />
sai_sec_crit(ID_PAI);<br />
} <br />
<br />
<br />
}<br />
else { /*Child code */<br />
<br />
for(;;){<br />
ent_sec_crit(ID_FILHO); <br />
memset(shared_data,1,BUFFER_SIZE);<br />
sai_sec_crit(ID_FILHO); <br />
}<br />
<br />
}<br />
<br />
if (shmdt(shared_data) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
=AULA 17 - Dia 27/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Apresentação dos Trabalhos<br />
*Definição da próxima etapa<br />
<br />
=AULA 18 - Dia 02/10/2019=<br />
<br />
==Objetivos==<br />
<br />
*Semáforos, Deadlock e o Problema da Inversão de Prioridade<br />
*Laboratório de Pthreads e Mutex;<br />
<br />
==Materia de Referência==<br />
<br />
*[https://www.os-book.com/OSE1/slide-dir/PDF-dir/ch6.pdf]<br />
<br />
==Desafio==<br />
<br />
Usar <br />
ps -T aux | grep ex1vA<br />
<br />
Para ver os threads dormindo...<br />
<br />
Otimizar o programa abaixo<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <pthread.h><br />
#include <stdlib.h><br />
#include <unistd.h><br />
#include <time.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
pthread_mutex_t mut;<br />
<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
<br />
<br />
long long i;<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
usleep(10000000);<br />
printf("Novo saldo = %d\n",novo_saldo);<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d\n", (i+1));<br />
exit(-1);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
printf("Saldo final é %d\n", saldo);<br />
}<br />
</syntaxhighlight><br />
<br />
==Laboratório Proposto==<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Programação concorrente}}<br />
<br />
== Programação concorrente ==<br />
<br />
<br />
===PARTE 1 - Mutex e Biblioteca libpthreads===<br />
<br />
;POSIX Threads<br />
A 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):<br />
*''pthread_create'': cria uma thread;<br />
*''pthread_kill'': força a terminação de uma thread;<br />
*''pthread_join'': sincroniza o final de uma thread (qual a diferença/semelhança com o ''wait'' que usamos para processos?);<br />
*''pthread_exit'': finaliza uma thread.<br />
Para utilizar estas funções é necessário linkar o programa à libpthread (''-lpthread''). <br />
<br />
<br />
;POSIX pthread mutex<br />
<br />
A biblioteca pthread implementa um tipo ''pthread_mutex_t'', que garante a exclusão mútua entre threads. Estes mutex são manipulados através das funções (acesse as man-pages das chamadas para maiores detalhes):<br />
*''pthread_mutex_lock'': acessa um mutex.<br />
*''pthread_mutex_trylock'': tenta acessar um mutex (retorna valor indicando sucesso ou falha no lock).<br />
*''pthread_mutex_unlock'': libera um mutex.<br />
<br />
<br />
<br />
;Exercício 1<br />
<br />
O programa abaixo cria 5 threads, e cada uma destas threads atualiza uma variável global (memória compartilhada).<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
#include <pthread.h><br />
#include <stdlib.h><br />
#include <unistd.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
pthread_mutex_t mut;<br />
<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
long long i;<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
sleep(1);<br />
printf("Novo saldo = %d\n",novo_saldo);<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d\n", (i+1));<br />
exit(-1);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
printf("Saldo final é %d\n", saldo);<br />
}<br />
</syntaxhighlight><br />
<br />
# Compile este programa. <br />
# Execute este programa várias vezes. Ele funciona? Será que ele gera as saídas esperadas?<br />
# Identifique as '''seções críticas''' do programa.<br />
# Corrija o programa utilizando '''mutex'''. <br />
# Analise a função ''AtualizaSaldo()'' com a sua solução. Lembre-se que o uso do mutex implica em apenas uma thread acessar a seção crítica por vez, enquanto outras threads ficam bloqueadas, esperando. Disso vem que, quanto menor o trecho de código entre um ''lock'' e um ''unlock'', menos tempo uma thread necessita ficar esperando.<br />
<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <cstring><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
<br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
sem_t sem;<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
int value;<br />
sem_wait(&sem);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
sem_getvalue(&sem, &value);<br />
printf("valor sem = %d\n", value);<br />
sem_post(&sem);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
sem_init(&sem,0,1);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
sem_destroy(&sem);<br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
===PARTE 2 - POSIX Semaphores===<br />
<br />
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):<br />
*''sem_init'': inicializa um semáforo;<br />
*''sem_destroy'': destroy um semáforo;<br />
*''sem_wait'': implementa a operação ''p'';<br />
*''sem_post'': implementa a operação ''v''.<br />
Para utilizar estas funções é necessário linkar o programa à librt ou à libpthread (''-lrt'' ou ''-lpthread'').<br />
<br />
;Exercício 1<br />
Modifique o programa para usar um semáforo binário ao invés de um mutex em sua solução.<br />
<br />
;Exercício 2<br />
Refaça o exercício 3 usando processos criados com fork e exec. O semáforo deve ser criado em uma região de memória compartilhada.<br />
<br />
;Exercício 3<br />
Implemente com pthreads e semáforos/mutex a solução do produtor/comsumidor.<br />
<br />
;Exercício 4<br />
<br />
O programa abaixo manipula uma matriz de tamanho MxN (veja os defines para o tamanho da matriz). A função ''SumValues'' soma todos os valores em uma linha da matriz. A linha a ser somada é identificada pela variável ''i''. Modifique o programa principal (''main'') nos locais indicados para:<br />
# Criar N threads, uma para somar os valores de cada linha.<br />
# Receber o resultado do somatório de cada linha e gerar o somatório total da matriz.<br />
# Analise o programa: há problemas de sincronização que precisam ser resolvidos? Se sim, resolva-os.<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include "thread.h"<br />
<br />
/* number of matrix columns and rows */<br />
#define M 5<br />
#define N 10<br />
<br />
using namespace std;<br />
<br />
int matrix[N][M];<br />
Thread *threads[N];<br />
<br />
<br />
/* thread function; it sums the values of the matrix in the row */<br />
int SumValues(int i)<br />
{<br />
int n = i; /* number of row */<br />
int total = 0; /* the total of the values in the row */<br />
int j;<br />
for (j = 0; j < M; j++) /* sum values in the "n" row */<br />
total += matrix[n][j];<br />
cout << "The total in row" << n << " is " << total << "." << endl;<br />
/* terminate a thread and return a total in the row */<br />
exit(total);<br />
}<br />
<br />
int main(int argc, char *argv[])<br />
{<br />
int i, j;<br />
int total = 0; /* the total of the values in the matrix */<br />
<br />
/* initialize the matrix */<br />
for (i = 0; i < N; i++)<br />
for (j = 0; j < M; j++)<br />
matrix[i][j] = i * M + j;<br />
<br />
/* create threads */<br />
/* COLOQUE SEU CÓDIGO PARA CRIAR AS THREADS AQUI! */<br />
<br />
/* wait for terminate a threads */<br />
/* COLOQUE SEU CÓDIGO PARA PEGAR O SOMATÓRIO DE LINHAS E TOTALIZAR A SOMA DA MATRIZ AQUI! */<br />
<br />
cout << "The total values in the matrix is " << total << endl;<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
{{collapse bottom}}<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Escalonamento Round Robin e FCFS para Threads"}}<br />
<br />
== Escalonamento Round-Robin ==<br />
<br />
OBS: ver https://www.quora.com/What-exactly-does-typedef-do-in-C<br />
<br />
O Exemplo abaixo mostra a implementação de um esquema de escalonamento Round Robin do exercício anterior.<br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
Modificado por Eraldo <br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 5<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
void runA(void) {<br />
for (;;) {<br />
printf("running A\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runB(void) {<br />
for (;;) {<br />
printf("running B\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 1<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
<br />
void scheduler_rr();<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void yield_thread()<br />
{<br />
scheduler_rr();<br />
}<br />
<br />
void delete_thread()<br />
{<br />
delete curr_thread;<br />
curr_thread=NULL;<br />
scheduler_rr();<br />
}<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
struct delta{<br />
long alfa;<br />
char epson[1000];<br />
long beta;<br />
} shar;<br />
<br />
int turn;<br />
int flag[2];<br />
<br />
#define TRUE 1<br />
#define FALSE 0<br />
<br />
void ent_rc(int p, int vt)<br />
{<br />
flag[p]=TRUE;<br />
turn = vt;<br />
if(p) p=0; else p=1;<br />
while (flag[p] && turn == vt);<br />
//printf("Thread %d: esperando para acessar a região crítica\n", p);<br />
}<br />
<br />
void sai_rc(int p)<br />
{<br />
flag[p]=FALSE;<br />
}<br />
<br />
void runA(void) {<br />
struct delta x = {0, 100};<br />
<br />
for (;;) {<br />
x.alfa=0;x.beta=0;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0);<br />
x.alfa=100;x.beta=100;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0); <br />
}<br />
}<br />
<br />
void runB(void) {<br />
<br />
for (;;) {<br />
ent_rc(1,0);<br />
printf("shar alfa = %ld shar beta = %ld \n",shar.alfa, shar.beta); // regiao crítica<br />
sai_rc(1);<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runC(void) {<br />
int i;<br />
for (i=0;i<10;i++) {<br />
printf("Thread C - parte 1\n");<br />
yield_thread();<br />
printf("Thread C - parte 2\n");<br />
yield_thread();<br />
}<br />
delete_thread();<br />
}<br />
<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
add_thread(runC);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
{{collapse bottom}}<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Um escalonador semi-automático"}}<br />
<br />
== Ainda Threads - Um escalonador semi-automático usando sinais ==<br />
<br />
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.<br />
<br />
===Exemplo 1:===<br />
<br />
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. <br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
<br />
void sig_handler(int signo)<br />
{<br />
int x;<br />
printf("Turma de SOP: recebido SIGUSR1\n");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
// Loop eterno dormindo 1s<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Fazer no terminal:<br />
ps aux<br />
anotar o pid do processo e enviar o sinal:<br />
kill -USR1 pid<br />
<br />
===Exemplo 2:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// loop eterno que nunca é executado<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Enviar o sinal USR1 para ver o efeito. <br />
<br />
===Exemplo 3:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void prepara_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void prepara_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
prepara_contexto_ping();<br />
prepara_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// A long long wait so that we can easily issue a signal to this process<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Exercício: Use o comando htop para verificar como estes threads são vistos pelo SOP.<br />
<br />
Exercício: Tente analisar as pilhas dos threads e verificar sob qual pilha o handler se executa.<br />
<br />
<br />
===Exercício 4:===<br />
<br />
Neste ponto associamos um timer ao handler com o apoio do sinal ALRM. Agora os threads são escalonados automaticamente.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
===Exercício Proposto 5===<br />
<br />
Colocar 3 threads rodando.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void preparar_contexto_ping(ucontext_t *pContext, char *p)<br />
{<br />
char *stack;<br />
<br />
getcontext(pContext);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
(*pContext).uc_stack.ss_sp = stack ;<br />
(*pContext).uc_stack.ss_size = STACKSIZE;<br />
(*pContext).uc_stack.ss_flags = 0;<br />
(*pContext).uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(pContext, (void*)(*f_ping), 1, p);<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping(&cPing, "ping");<br />
preparar_contexto_ping(&cPong, "pong");<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Threads de aplicação}}<br />
<br />
== Threads de aplicação ==<br />
<br />
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:<br />
*'''getcontext(&a)''': salva o contexto na variável '''a''';<br />
*'''setcontext(&a)''': restaura um contexto salvo anteriormente na variável '''a''';<br />
*'''swapcontext(&a,&b)''': salva o contexto atual na variável '''a''' e restaura o contexto salvo anteriormente na variável '''b''';<br />
*'''makecontext(&a, ...)''': ajusta parâmetros internos do contexto salvo em '''a''';<br />
*'''ucontext_t''': as variáveis '''a''' e '''b''' são do tipo '''ucontext_t'''. Este tipo armazena um contexto.<br />
<br />
Busque mais informações sobre estas funções utilizando o programa manpage do Linux (ex.: man getcontext).<br />
<br />
Estude o código no arquivo pingpong.c abaixo e explique seu funcionamento.<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
*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.<br />
*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.<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain, cFnew;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_new(void * arg1, void * arg2,void * arg3,void * arg4) <br />
{<br />
printf ("%s: Primeira string %s %s %s\n",(char*) arg1,(char*) arg2,(char*) arg3, (char*) arg4);<br />
swapcontext(&cFnew, &cMain); <br />
}<br />
<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
<br />
getcontext(&cFnew);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cFnew.uc_stack.ss_sp = stack ;<br />
cFnew.uc_stack.ss_size = STACKSIZE;<br />
cFnew.uc_stack.ss_flags = 0;<br />
cFnew.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cFnew, (void*)(*f_new), 4, "\tF_new", "\tAlo", "\tMundo","\tReal");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
swapcontext(&cMain, &cFnew);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
--><br />
Exercício 3: O que acontece se um dos threads é colocado para dormir? Todos os demais threads param a sua execução.<br />
<br />
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/<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Processos no Linux}}<br />
<br />
== Processos no Linux - Modificado por Eraldo ==<br />
<br />
<blockquote style="background: lime; border: 1px solid black; padding: 1em;"><br />
Processos no Linux<br />
</blockquote><br />
<br />
*Exercícios propostos pelo Prof.Arliones e Modificados por Eraldo<br />
<br />
<br />
[[imagem:DesenhoForkExec.png|border|650px]]<br />
<br />
<br />
;Syscall FORK<br />
<br />
* Em um terminal, execute "man fork"<br />
** 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'''.<br />
** O '''código''' dos dois processos (pai e filho) são '''idênticos''';<br />
** Os '''dados''' dos dois processos (pai e filho) são '''idênticos NO MOMENTO DA CRIAÇÃO''';<br />
** Execução do processo filho inicia na próxima instrução do programa (no retorno da chamada FORK);<br />
** Não é possível saber qual dos processos (pai ou filho) retormará a execução primeiro - isto fica a cargo do excalonador do SO;<br />
** Valores de retorno da chamada FORK:<br />
*** (-1): erro na criação do processo (ex.: memória insuficiente);<br />
*** (0): em caso de sucesso, este é o valor de retorno recebido pelo processo filho;<br />
*** (>0): em caso de sucesso, este é o valor de retorno recebido pelo processo pai;<br />
<br />
;Syscall JOIN<br />
<br />
* A syscall JOIN é implementada no POSIX pela função '''wait()'''. Execute "man wait".<br />
** Além da função '''wait()''', há também '''waitpid()''' e '''waitid()''';<br />
** 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);<br />
** A chamada wait também libera os recursos do processo filho que termina;<br />
** '''wait()''': esta função suspende a execução do processo chamador até que UM DOS SEUS FILHOS finalize;<br />
** '''waitpid()''': suspende a execução do processo chamador até que UM FILHO ESPECÍFICO finalize;<br />
<br />
;Syscall EXEC<br />
<br />
* A syscall EXEC é implementada no POSIX pela família de funções '''exec()'''. Execute "man exec".<br />
** As principais funções da família são '''execl()''', '''execlp()''' e '''execvp()''';<br />
** 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;<br />
** 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;<br />
<br />
<br />
;Exemplos POSIX utilizando fork/wait/exec<br />
<br />
*Exemplo 1: fork/wait básico<br />
<syntaxhighlight lang=c><br />
// ex1: fork/wait básico<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
printf("processo filho\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
printf("processo pai\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
arliones@socrates:~/tmp$ gcc ex1.c -o ex1 <br />
arliones@socrates:~/tmp$ ./ex1 <br />
processo filho pid: 27858 pid pai: 27857<br />
processo pai pid: 27857 pid pai: 5337<br />
arliones@socrates:~/tmp$ <br />
</syntaxhighlight><br />
<br />
* Exemplo 2: processos pai e filho compartilham código, mas não dados.<br />
<syntaxhighlight lang=c><br />
// ex2: fork/wait "compartilhando" dados<br />
// ex2: fork/wait "compartilhando" dados<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status, k=0;<br />
printf("processo %d\t antes do fork\n", getpid());<br />
pid = fork();<br />
printf("processo %d\t depois do fork\n", getpid());<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
k += 1000;<br />
printf("processo filho\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status); // espera o filho terminar<br />
k += 10;<br />
printf("processo pai\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
k += 1000;<br />
printf("FIM processo %d\t K: %d\n", getpid(), k); <br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
processo 17056 antes do fork<br />
processo 17056 depois do fork<br />
processo 17057 depois do fork<br />
processo filho pid: 17057 K: 1000 endereço K: 0x7ffd8923e318<br />
processo pai pid: 17056 K: 10 endereço K: 0x7ffd8923e318<br />
</syntaxhighlight><br />
<br />
* Modificação no código: comentar linhas 23 e 30<br />
<br />
<syntaxhighlight lang=bash><br />
<br />
</syntaxhighlight><br />
<br />
* Analise os resultados e busque entender a diferença.<br />
*Perguntas e desafios.:<br />
#Analisando os valores impressos de k pode-se dizer que os dados são compartilhados entre os dois processos?<br />
#O endereço de k impresso é o mesmo nos dois processos. ISto não contradiz a afirmação anterior?<br />
#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.<br />
<br />
<br />
;Exercício fork/wait<br />
<br />
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.<br />
<br />
*Use o comando pstree para verificar a árvore de processos criada.<br />
<br />
{{collapse top|Solução}}<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
<!--<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
--><br />
<br />
;DESAFIO: fork/wait<br />
<br />
Reimplementar o exercício anterior de criação de uma árvore de 3 processos, generalizando a criação de N processos onde N é repassado na linha de comando do programa. SUGESTÃO: usar um comando for, mas lembrar que se existe um fork dentro do for, então cada filho gerado dará continuidade a execução do for. É necessário que o processo faça um exit ou retorne neste momento.<br />
<br />
;DESAFIO: Exercício status/wait<br />
<br />
O ''status'' passado como parâmetro à função ''wait(&status)'' é, na verdade, o mecanismo de retorno de resultado do ''wait/waitpid''. Ao retornar, esta variável contém informações sobre o resultado da execução do processo filho. Por exemplo, se um processo terminou normalmente (i.e., chamou ''exit''), o comando ''WIFEXITED(status)'' retorna ''true''. Este comando retorna ''false'' se o processo foi abortado (e.g., ''segmentation fault'') ou morto (e.g., ''kill''). Investigue no manual do wait no Linux (''man wait'') o funcionamento do comando WEXITSTATUS(status). <br />
Imagine um problema de busca de dados armazenados na forma de uma matriz de inteiros 4x30. Você está interessado em saber quantas ocorrências de um determinado número existe em cada linha da matriz. Note que que são tarefas que podem ser paralelizadas e usufruir de um sistema capaz de executá-las em paralelo. Faça uma implementação paralelizando 4 processos filhos a partir de um pai, onde cada processo é responsável por uma busca. A quantidade de ocorrências do número buscado é retornada e capturada através de WEXITSTATUS.<br />
<br />
;Syscall EXEC<br />
<br />
*Exemplo exec()<br />
<br />
<syntaxhighlight lang=c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
execl("/bin/ls","ls","-l", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 1: Modificar o código para mostrar que o exec() não retorna (colocar um printf após o exec).<br />
<br />
*Exercício 2: Criar um exemplo (dois programas ) para demonstrar que o exec não cria novo processo. <br />
**Crie um primeiro programa (prog1) que imprime o seu pid e depois faz um exec do segundo programa.<br />
**Crie o segundo programa que simplesmente imprime o pid.<br />
<br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU ANTES DO EXEC: Meu pid é %d\n", getpid());<br />
execl("./prog2","prog2", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU DEPOIS DO EXEC:Meu pid é %d\n", getpid());<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 3: Criar um exemplo usando fork/exec mostrando que um processo pai cria um filho e espera por sua execução. O filho executa o comando "ps aux". Ambos devem mostrar seus pids.<br />
<br />
{{collapse bottom}} <br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Laboratório Memória Compartilhada entre Pai e Filho - Produtor Consumidor}}<br />
<br />
Baseado no Lab. do Prof.Arliones<br />
<br />
=== Objetivo ===<br />
<br />
*Familiarizar o aluno com o conceito de Memória Compartilhada entre Processos Pai e Filho<br />
*Familizarizar o aluno com o conceito de Produtor Consumidor<br />
<br />
=== Referencial Teórico-Prático ===<br />
<br />
* Silberchatz - 3.4 e 3.5<br />
* man nos comandos shmat e shmget<br />
<br />
=== Exemplo de Funcionamento ===<br />
<br />
No exemplo abaixo um processo pai compartilha uma área de memória com o processo filho. O processo filho escreve uma mensagem para o pai na área de memória compartilhada e termina. O processo pai é desbloqueado no wait e imprime a mensagem escrita.<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
char *ptr_msg = "alo pai, tudo bem?"; <br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
strcpy(segmento, ptr_msg);<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(&filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
=== Desafio a ser Implementado em Sala ===<br />
<br />
Construir um programa em que um processo pai atua como produtor e o processo filho atua como consumidor. O buffer circular compartilhado é um buffer de inteiro de tamanho 5. O pai alimentará o buffer com 50 itens gerados aleatóriamente entre 1 e 100. A cada escrita/leitura no buffer o produtor/consumidor deve esperar alguns milisegundos de forma a acontecer situações de buffer cheio e vazio. <br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
#include <string.h><br />
#include <unistd.h><br />
#include <time.h><br />
#include <sys/types.h><br />
#include <sys/wait.h><br />
<br />
<br />
<br />
#define SHM_SIZE 1024 <br />
<br />
#define BUFF_COMP_SIZE 5<br />
<br />
struct buff_comp {<br />
int buffer[BUFF_COMP_SIZE];<br />
int in,out;<br />
};<br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
struct buff_comp *p; <br />
<br />
/* initialize random seed: */<br />
srand ( time(NULL) );<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
p = (struct buff_comp *) shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
p->out = p->in = 0;<br />
<br />
if((filho = fork()) == -1)<br />
{<br />
<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
int i;<br />
for(i=0;i<50;i++) {<br />
while (p->in==p->out) {<br />
printf("FILHO: BUFFER VAZIO !!!!!!!\n");<br />
usleep(rand() % 10000 + 1);<br />
}<br />
printf("FILHO: item lido = %d\n", p->buffer[p->out]);<br />
p->out = (p->out+1)%BUFF_COMP_SIZE;<br />
}<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
int i; <br />
<br />
for(i=0;i<50;i++) {<br />
while (((p->in+1)%BUFF_COMP_SIZE) == p->out) {<br />
printf("PAI: BUFFER CHEIO !!!!!!!\n");<br />
usleep(rand() % 10000 + 1);<br />
}<br />
p->buffer[p->in] = rand() % 100 + 1;<br />
printf("PAI: item produzido = %d\n", p->buffer[p->in]);<br />
p->in = (p->in+1)%BUFF_COMP_SIZE;<br />
<br />
}<br />
wait(&filho); <br />
<br />
}<br />
<br />
<br />
if (shmdt(p) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Trocas de mensagens com pipes}}<br />
<br />
= Trocas de mensagens com pipes =<br />
<br />
;Troca de mensagens<br />
Um mecanismo disponibilizado por sistemas UNIX para troca de mensagens entre processos é o PIPE. Pipes são mecanismos de comunicação indireta onde mensagens são trocadas através de ''mailboxes''. Cada ''mailbox'' possui um identificador único, permitindo que processos identifiquem o canal de comunicação entre eles. O fluxo de mensagens em um Pipe é:<br />
*'''unidirecional''': sobre um mesmo pipe, apenas um processo envia mensagens e um processo recebe mensagens;<br />
*'''FIFO''': as mensagens são entregues na ordem de envio;<br />
*'''não-estruturado''': não há estrutura pré-definida para o formato da mensagem.<br />
No UNIX, pipes são inicializados através da '''SystemCall''' ''pipe'', que possui a seguinte sintaxe:<br />
*''int pipe(int pipefd[2])'': ''pipe'' inicializa um novo pipe no sistema e retorna, no array pipefd, os descritores identificando cada uma das pontas do pipe. A primeira posição do array, i.e. pipefd[0], recebe o descritor que pode ser aberto apenas para leitura, enquanto a segunda posição do array, i.e. pipefd[1], recebe o descritor que pode ser aberto apenas para escrita. A função retorna zero no caso de sucesso, ou -1 se ocorrer erro.<br />
As primitivas send/receive para uso de um pipe no UNIX são implementadas por '''SystemCalls''' read/write, conforme segue:<br />
*''ssize_t read(int fd, void *buf, size_t count)'': “puxa” dados do pipe identificado pelo descritor fd. Os dados recebidos são os apontados pelo ponteiro buf, sendo count a quantidade máxima de bytes a serem recebidos. A função retorna o número de bytes recebidos.<br />
*''ssize_t write(int fd, const void *buf, size_t count)'': “empurra” dados no pipe identificado pelo descritor fd. Os dados transmitidos são os apontados pelo ponteiro buf, sendo count a quantidade de bytes a serem transmitidos. A função retorna o número de bytes transmitidos.<br />
<br />
*Exemplo 1: Transmitindo e recebendo pelo próprio processo<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main()<br />
{<br />
int fd[2];<br />
char *ptr = "Alo eu mesmo";<br />
char *ptr_alvo;<br />
int tamanho_dados, ret;<br />
<br />
tamanho_dados = strlen(ptr)+1;<br />
<br />
if (pipe(fd)==-1){<br />
printf ("erro criação pipe\n");<br />
exit(-1);<br />
}<br />
printf("Transmitido %d bytes\n", tamanho_dados);<br />
write (fd[1], ptr, tamanho_dados);<br />
<br />
ptr_alvo = malloc(tamanho_dados);<br />
<br />
ret=read(fd[0],ptr_alvo,tamanho_dados);<br />
<br />
printf("ret = %d dados => %s\n", ret, ptr_alvo); <br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
*Exemplo 2: Abaixo há um exemplo de programa criando um pipe e compartilhando os descritores entre dois processos (criados via ''fork()'').<br />
<syntaxhighlight lang=c><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
<br />
char *message = "This is a message!!!" ;<br />
<br />
main()<br />
{<br />
char buf[1024] ;<br />
int fd[2];<br />
pipe(fd); /*create pipe*/<br />
if (fork() != 0) { /* I am the parent */<br />
write(fd[1], message, strlen (message) + 1) ;<br />
}<br />
else { /*Child code */<br />
read(fd[0], buf, 1024) ;<br />
printf("Got this from MaMa!!: %s\n", buf) ;<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
*'''Exercício 1: construa um “pipeline”'''. Crie um programa que conecta 4 processos através de 3 pipes. Utilize ''fork()'' para criar vários processos.<br />
<br />
<syntaxhighlight lang=cpp><br />
<br />
//Solução possível<br />
<br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
pipe(fd);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
<br />
</syntaxhighlight><br />
<br />
*'''Exercício 2: Modifique o exercício anterior para que o processo D, através de um novo pipe, mande uma mensagem diretamente para o pai de todos.<br />
<br />
<!--<br />
<code><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
int fd_retorno[2];<br />
<br />
pipe(fd);<br />
pipe(fd_retorno);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size);<br />
read(fd_retorno[0], buf, size);<br />
printf("PAI:%s\n", buf); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
char *ptr_msg_ret="Ok msg de D para o pai";<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
write(fd_retorno[1],ptr_msg_ret,strlen(ptr_msg_ret)+1);<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
*'''Exercício 3: Consultor de Login de Acesso:'''. Estude o link https://www.geeksforgeeks.org/named-pipe-fifo-example-c-program/ e projete um programa cliente servidor da seguinte forma: (i) O servidor possui uma tabela de usuários (userid). O user_id é de tamanho fixo de 7 caracteres. O servidor espera por consultas para verificar se um usuário está na tabela. Se estiver responde com o caracter 'S' senão com 'N'. (ii) O cliente espera por user_id no teclado e consulta o servidor sobre sua existência na tabela. O cliente imprime na tabela a existência ou não do usuário.<br />
<br />
*'''Exercício 4: cópia de arquivo'''. Projete um programa de cópia de arquivos chamado FileCopy usando pipes comuns. Esse programa receberá dois parâmetros: o primeiro é o nome do arquivo a ser copiado e o segundo é o nome do arquivo copiado. Em seguida, o programa criará um pipe comum e gravará nele o conteúdo do arquivo a ser copiado. O processo filho lerá esse arquivo do pipe e o gravará no arquivo de destino. Por exemplo, se chamarmos o programa como descrito a seguir:<br />
:<syntaxhighlight lang=bash><br />
$ FileCopy entrada.txt copia.txt<br />
</syntaxhighlight><br />
:o arquivo ''entrada.txt'' será gravado no pipe. O processo filho lerá o conteúdo desse arquivo e o gravará no arquivo de destino ''copia.txt''. Escreva o programa usando os pipes da API POSIX no Linux.<br />
<br />
<br />
{{collapse bottom}}<br />
<br />
=Laboratórios Disponíveis= <br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Escalonamento Round Robin e FCFS para Threads"}}<br />
<br />
<br />
== Escalonamento Round-Robin preemptivo ==<br />
<br />
OBS: ver https://www.quora.com/What-exactly-does-typedef-do-in-C<br />
<br />
A fazer: <br />
<br />
*primitiva de término de processo (destrutor do objeto); <br />
*primitiva de yield<br />
*isolar o escalonador em uma função;<br />
*isolar o dispatcher em uma função; <br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
Modificado por Eraldo <br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 5<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
void runA(void) {<br />
for (;;) {<br />
printf("running A\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runB(void) {<br />
for (;;) {<br />
printf("running B\n");<br />
sleep(1);<br />
}<br />
}<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
User-level threads example.<br />
<br />
Orion Sky Lawlor, olawlor@acm.org, 2005/2/18 (Public Domain)<br />
*/<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h> /* for makecontext/swapcontext routines */<br />
#include <queue> /* C++ STL queue structure */<br />
#include <vector><br />
<br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define TIME_SLICE 1<br />
<br />
typedef void (*threadFn)(void);<br />
<br />
class thread_cb {<br />
int id_thread;<br />
public:<br />
ucontext_t contexto;<br />
thread_cb(threadFn p, int id)<br />
{<br />
getcontext(&contexto);<br />
int stackLen=32*1024;<br />
char *stack=new char[stackLen];<br />
contexto.uc_stack.ss_sp=stack;<br />
contexto.uc_stack.ss_size=stackLen;<br />
contexto.uc_stack.ss_flags=0; <br />
id_thread = id;<br />
makecontext(&contexto,p,0);<br />
};<br />
ucontext_t *get_context() {<br />
return &contexto;<br />
};<br />
};<br />
<br />
std::queue<class thread_cb *> ready_pool;<br />
<br />
int id_thread = 0;<br />
<br />
class thread_cb *curr_thread=NULL;<br />
<br />
<br />
void scheduler_rr();<br />
<br />
void add_thread(threadFn func)<br />
{<br />
class thread_cb *p = new thread_cb(func, ++id_thread);<br />
ready_pool.push(p);<br />
}<br />
<br />
<br />
void yield_thread()<br />
{<br />
scheduler_rr();<br />
}<br />
<br />
void delete_thread()<br />
{<br />
delete curr_thread;<br />
curr_thread=NULL;<br />
scheduler_rr();<br />
}<br />
<br />
void dispatcher(ucontext_t *old_task, ucontext_t *new_task)<br />
{<br />
if (old_task!=NULL)<br />
swapcontext(old_task, new_task);<br />
else<br />
setcontext(new_task);<br />
}<br />
<br />
void scheduler_rr()<br />
{<br />
class thread_cb *next,*last;<br />
<br />
<br />
if(curr_thread!=NULL) {<br />
printf("Aqui\n");<br />
ready_pool.push(curr_thread);<br />
last=curr_thread;<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread=next; <br />
dispatcher(last->get_context(), curr_thread->get_context()); <br />
} else {<br />
next=ready_pool.front();<br />
ready_pool.pop();<br />
curr_thread = next;<br />
dispatcher(NULL, next->get_context());<br />
}<br />
}<br />
<br />
void sig_handler(int signo)<br />
{<br />
<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
<br />
if (ready_pool.empty()) {<br />
printf("Nothing more to run!\n");<br />
exit(0);<br />
}<br />
scheduler_rr();<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
struct delta{<br />
long alfa;<br />
char epson[1000];<br />
long beta;<br />
} shar;<br />
<br />
int turn;<br />
int flag[2];<br />
<br />
#define TRUE 1<br />
#define FALSE 0<br />
<br />
void ent_rc(int p, int vt)<br />
{<br />
flag[p]=TRUE;<br />
turn = vt;<br />
if(p) p=0; else p=1;<br />
while (flag[p] && turn == vt);<br />
//printf("Thread %d: esperando para acessar a região crítica\n", p);<br />
}<br />
<br />
void sai_rc(int p)<br />
{<br />
flag[p]=FALSE;<br />
}<br />
<br />
void runA(void) {<br />
struct delta x = {0, 100};<br />
<br />
for (;;) {<br />
x.alfa=0;x.beta=0;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0);<br />
x.alfa=100;x.beta=100;<br />
ent_rc(0,1);<br />
shar=x; // regiao crítica<br />
sai_rc(0); <br />
}<br />
}<br />
<br />
void runB(void) {<br />
<br />
for (;;) {<br />
ent_rc(1,0);<br />
printf("shar alfa = %ld shar beta = %ld \n",shar.alfa, shar.beta); // regiao crítica<br />
sai_rc(1);<br />
sleep(1);<br />
}<br />
}<br />
<br />
void runC(void) {<br />
int i;<br />
for (i=0;i<10;i++) {<br />
printf("Thread C - parte 1\n");<br />
yield_thread();<br />
printf("Thread C - parte 2\n");<br />
yield_thread();<br />
}<br />
delete_thread();<br />
}<br />
<br />
<br />
main()<br />
{<br />
add_thread(runA);<br />
add_thread(runB);<br />
add_thread(runC);<br />
preparar_handler();<br />
for(;;);<br />
}<br />
</syntaxhighlight><br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Ainda Threads - Um escalonador semi-automático"}}<br />
<br />
== Ainda Threads - Um escalonador semi-automático usando sinais ==<br />
<br />
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.<br />
<br />
===Exemplo 1:===<br />
<br />
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. <br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
<br />
void sig_handler(int signo)<br />
{<br />
int x;<br />
printf("Turma de SOP: recebido SIGUSR1\n");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
// Loop eterno dormindo 1s<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Fazer no terminal:<br />
ps aux<br />
anotar o pid do processo e enviar o sinal:<br />
kill -USR1 pid<br />
<br />
===Exemplo 2:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// loop eterno que nunca é executado<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Enviar o sinal USR1 para ver o efeito. <br />
<br />
===Exemplo 3:===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("Turma de SOP: recebido SIGUSR1\n"); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void prepara_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void prepara_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
prepara_contexto_ping();<br />
prepara_contexto_pong();<br />
<br />
if (signal(SIGUSR1, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
<br />
curr_thread=PING_ID;<br />
swapcontext(&cMain, &cPing);<br />
// A long long wait so that we can easily issue a signal to this process<br />
while(1) {<br />
sleep(1);<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
Exercício: Tente analisar as pilhas dos threads e verificar sob qual pilha o handler se executa.<br />
<br />
===Exercício 4:===<br />
<br />
Neste ponto associamos um timer ao handler com o apoio do sinal ALRM. Agora os threads são escalonados automaticamente.<br />
<br />
<code><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
}<br />
<br />
void preparar_contexto_ping()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
}<br />
<br />
void preparar_contexto_pong()<br />
{<br />
char *stack;<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping();<br />
preparar_contexto_pong();<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
#include<stdio.h><br />
#include <stdlib.h><br />
#include<signal.h><br />
#include<unistd.h><br />
#include <ucontext.h><br />
#include <sys/time.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
// number of seconds for setting the interval used by the timer<br />
#define QUANTUM_SEC 0<br />
// number of microseconds for setting the interval used by the timer (0 - 999999)<br />
#define QUANTUM_MICRO_SEC 100000<br />
<br />
#define PING_ID 1<br />
#define PONG_ID 2<br />
#define TIME_SLICE 5<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
int curr_thread;<br />
<br />
/* Handler para tratar o sinal */<br />
void sig_handler(int signo)<br />
{<br />
printf("SOP da Turma 2019-2: recebido SIGALRM\n");<br />
alarm(TIME_SLICE); <br />
if (curr_thread==PING_ID) {<br />
curr_thread=PONG_ID;<br />
swapcontext(&cPing, &cPong); <br />
} else {<br />
curr_thread=PING_ID;<br />
swapcontext(&cPong, &cPing);<br />
}<br />
}<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i=0;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (;;) {<br />
printf("%s %d\n", (char *) arg, i++);<br />
sleep(1);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
<br />
}<br />
<br />
void preparar_contexto_ping(ucontext_t *pContext, char *p)<br />
{<br />
char *stack;<br />
<br />
getcontext(pContext);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
(*pContext).uc_stack.ss_sp = stack ;<br />
(*pContext).uc_stack.ss_size = STACKSIZE;<br />
(*pContext).uc_stack.ss_flags = 0;<br />
(*pContext).uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
makecontext(pContext, (void*)(*f_ping), 1, p);<br />
}<br />
<br />
void preparar_handler()<br />
{<br />
if (signal(SIGALRM, sig_handler) == SIG_ERR) {<br />
printf("\nProblemas com SIGUSR1\n");<br />
exit(-1);<br />
}<br />
alarm(TIME_SLICE);<br />
}<br />
<br />
int main(void)<br />
{<br />
int x;<br />
<br />
printf ("Main INICIO\n");<br />
preparar_contexto_ping(&cPing, "ping");<br />
preparar_contexto_ping(&cPong, "pong");<br />
preparar_handler();<br />
curr_thread=PING_ID; //ajusta primeiro thread<br />
swapcontext(&cMain, &cPing); //nunca mais volta...<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Um Exemplo de Uso "API Padrão POSIX"}}<br />
<br />
== Um Exemplo de Uso "API Padrão POSIX" ==<br />
<br />
;Referências<br />
* Referência http://man7.org/linux/man-pages/man2/mmap.2.html<br />
<br />
<br />
Crie uma função soma que receba 2 ponteiros referenciando posições na memória, criadas utilizando nmap(), de maneira que estas posições armazenem números inteiros. A função soma deverá retornar a soma dos números apontados em regiões da memória sem a utilização de nenhuma rotina da biblioteca do C, que não sejam definidas por APIs posix, para criação destas <br />
regiões na memória (malloc, alloc, calloc). Após retornar o resultado da soma os devidos ponteiros deverão ser extintos da memória.<br />
<br />
<br />
*'''Experimento 1:''' Aumente o tamanho da memória alocada até quando for possível.<br />
<br />
Qual o tamanho limite da memória que você conseguiu alocar?<br />
<br />
*'''Experimento 2:''' Mude o escopo para PROT_NONE, após executar e depurar o código explique o que aconteceu.<br />
<br />
Em sua opinião NMAP trata-se de uma syscall ou de uma API? Afinal API e syscall são a mesma coisa? Explique.<br />
<br />
<syntaxhighlight lang=cpp><br />
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);<br />
int munmap(void *addr, size_t length);<br />
<br />
addr = Valor do início do mapeamento.<br />
length = valor do tamanho da região a ser alocada.<br />
prot = especificações de proteção da região alocada (consultar http://man7.org/linux/man-pages/man2/mmap.2.html).<br />
flags = especificação do escopo e do tipo da região criada (exemplo publica ou privada, se é anônima ou não). <br />
</syntaxhighlight><br />
<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
void* meu_malloc(size_t tamanho) {<br />
void* addr = mmap(0, // addr<br />
tamanho, // len<br />
PROT_READ | PROT_WRITE, // prot<br />
MAP_ANON | MAP_PRIVATE, // flags<br />
-1, // filedes<br />
0); // off<br />
*(size_t*)addr = tamanho;<br />
return addr;<br />
}<br />
<br />
int meu_free(void* addr) {<br />
return munmap(addr - sizeof(size_t), (size_t) addr);<br />
}<br />
<br />
<br />
int soma(int *N1, int *N2){<br />
<br />
return (*N1+*N2);<br />
<br />
}<br />
<br />
<br />
int main(int argc, char* argv[]) {<br />
<br />
int* numero1 = meu_malloc(sizeof(int));<br />
int* numero2 = meu_malloc(sizeof(int)); <br />
<br />
<br />
*numero1 = 10;<br />
*numero2 = 20; <br />
<br />
int resultado = soma(numero1, numero2);<br />
<br />
printf("\n\n O resultado da soma é %d \n\n",resultado); <br />
<br />
meu_free(numero1);<br />
meu_free(numero2);<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Processos no Linux}}<br />
<br />
== Processos no Linux - Modificado por Eraldo ==<br />
<br />
<blockquote style="background: lime; border: 1px solid black; padding: 1em;"><br />
Processos no Linux<br />
</blockquote><br />
<br />
*Exercícios propostos pelo Prof.Arliones e Modificados por Eraldo<br />
<br />
<br />
[[imagem:DesenhoForkExec.png|border|650px]]<br />
<br />
<br />
;Syscall FORK<br />
<br />
* Em um terminal, execute "man fork"<br />
** 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'''.<br />
** O '''código''' dos dois processos (pai e filho) são '''idênticos''';<br />
** Os '''dados''' dos dois processos (pai e filho) são '''idênticos NO MOMENTO DA CRIAÇÃO''';<br />
** Execução do processo filho inicia na próxima instrução do programa (no retorno da chamada FORK);<br />
** Não é possível saber qual dos processos (pai ou filho) retormará a execução primeiro - isto fica a cargo do excalonador do SO;<br />
** Valores de retorno da chamada FORK:<br />
*** (-1): erro na criação do processo (ex.: memória insuficiente);<br />
*** (0): em caso de sucesso, este é o valor de retorno recebido pelo processo filho;<br />
*** (>0): em caso de sucesso, este é o valor de retorno recebido pelo processo pai;<br />
<br />
;Syscall JOIN<br />
<br />
* A syscall JOIN é implementada no POSIX pela função '''wait()'''. Execute "man wait".<br />
** Além da função '''wait()''', há também '''waitpid()''' e '''waitid()''';<br />
** 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);<br />
** A chamada wait também libera os recursos do processo filho que termina;<br />
** '''wait()''': esta função suspende a execução do processo chamador até que UM DOS SEUS FILHOS finalize;<br />
** '''waitpid()''': suspende a execução do processo chamador até que UM FILHO ESPECÍFICO finalize;<br />
<br />
;Syscall EXEC<br />
<br />
* A syscall EXEC é implementada no POSIX pela família de funções '''exec()'''. Execute "man exec".<br />
** As principais funções da família são '''execl()''', '''execlp()''' e '''execvp()''';<br />
** 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;<br />
** 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;<br />
<br />
<br />
;Exemplos POSIX utilizando fork/wait/exec<br />
<br />
*Exemplo 1: fork/wait básico<br />
<syntaxhighlight lang=c><br />
// ex1: fork/wait básico<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
printf("processo filho\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
printf("processo pai\t pid: %d\t pid pai: %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
arliones@socrates:~/tmp$ gcc ex1.c -o ex1 <br />
arliones@socrates:~/tmp$ ./ex1 <br />
processo filho pid: 27858 pid pai: 27857<br />
processo pai pid: 27857 pid pai: 5337<br />
arliones@socrates:~/tmp$ <br />
</syntaxhighlight><br />
<br />
* Exemplo 2: processos pai e filho compartilham código, mas não dados.<br />
<syntaxhighlight lang=c><br />
// ex2: fork/wait "compartilhando" dados<br />
// ex2: fork/wait "compartilhando" dados<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status, k=0;<br />
printf("processo %d\t antes do fork\n", getpid());<br />
pid = fork();<br />
printf("processo %d\t depois do fork\n", getpid());<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
k += 1000;<br />
printf("processo filho\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status); // espera o filho terminar<br />
k += 10;<br />
printf("processo pai\t pid: %d\t K: %d \t endereço K: %p\n", getpid(), k, &k);<br />
exit(0);<br />
}<br />
k += 1000;<br />
printf("FIM processo %d\t K: %d\n", getpid(), k); <br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=bash><br />
processo 17056 antes do fork<br />
processo 17056 depois do fork<br />
processo 17057 depois do fork<br />
processo filho pid: 17057 K: 1000 endereço K: 0x7ffd8923e318<br />
processo pai pid: 17056 K: 10 endereço K: 0x7ffd8923e318<br />
</syntaxhighlight><br />
<br />
* Modificação no código: comentar linhas 23 e 30<br />
<br />
<syntaxhighlight lang=bash><br />
<br />
</syntaxhighlight><br />
<br />
* Analise os resultados e busque entender a diferença.<br />
*Perguntas e desafios.:<br />
#Analisando os valores impressos de k pode-se dizer que os dados são compartilhados entre os dois processos?<br />
#O endereço de k impresso é o mesmo nos dois processos. ISto não contradiz a afirmação anterior?<br />
#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.<br />
<br />
<br />
;Exercício fork/wait<br />
<br />
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.<br />
<br />
*Use o comando pstree para verificar a árvore de processos criada.<br />
<br />
{{collapse top|Solução}}<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/wait.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
<!--<br />
<code><br />
/*<br />
ex3: Excrever um programa C que cria uma arvore de 3 processos, onde o processo<br />
A faz um fork() criando um processo B, o processo B, por sua vez, faz um fork()<br />
criando um processo C. Cada processo deve exibir uma mensagem "Eu sou o<br />
processo XXX, filho de YYY", onde XXX e YYY sao PIDs de processos. Utilizar<br />
wait() para garantir que o processo C imprima sua resposta antes do B, e que o<br />
processo B imprima sua resposta antes do A. Utilizar sleep() (man 3 sleep) para<br />
haver um intervalo de 1 segundo entre cada mensagem impressa.<br />
*/<br />
<br />
#include <sys/types.h><br />
#include <stdlib.h><br />
#include <stdio.h><br />
<br />
int main()<br />
{<br />
int pid, status;<br />
pid = fork();<br />
<br />
if(pid == -1) // fork falhou<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o processo filho<br />
{<br />
pid = fork();<br />
if(pid == -1)<br />
{<br />
perror("fork falhou!");<br />
exit(-1);<br />
}<br />
else if(pid == 0) // Este é o filho do filho<br />
{<br />
sleep(1);<br />
printf("Eu sou o processo C (PID %d), filho de %d\n", getpid(), getppid());<br />
exit (0);<br />
}<br />
else<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo B (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
else // Este é o processo pai<br />
{<br />
wait(&status);<br />
sleep(1);<br />
printf("Eu sou o processo A (PID %d), filho de %d\n", getpid(), getppid());<br />
exit(0);<br />
}<br />
}<br />
<br />
</syntaxhighlight><br />
--><br />
<br />
;DESAFIO: fork/wait<br />
<br />
Reimplementar o exercício anterior de criação de uma árvore de 3 processos, generalizando a criação de N processos onde N é repassado na linha de comando do programa. SUGESTÃO: usar um comando for, mas lembrar que se existe um fork dentro do for, então cada filho gerado dará continuidade a execução do for. É necessário que o processo faça um exit ou retorne neste momento.<br />
<br />
;DESAFIO: Exercício status/wait<br />
<br />
O ''status'' passado como parâmetro à função ''wait(&status)'' é, na verdade, o mecanismo de retorno de resultado do ''wait/waitpid''. Ao retornar, esta variável contém informações sobre o resultado da execução do processo filho. Por exemplo, se um processo terminou normalmente (i.e., chamou ''exit''), o comando ''WIFEXITED(status)'' retorna ''true''. Este comando retorna ''false'' se o processo foi abortado (e.g., ''segmentation fault'') ou morto (e.g., ''kill''). Investigue no manual do wait no Linux (''man wait'') o funcionamento do comando WEXITSTATUS(status). <br />
Imagine um problema de busca de dados armazenados na forma de uma matriz de inteiros 4x30. Você está interessado em saber quantas ocorrências de um determinado número existe em cada linha da matriz. Note que que são tarefas que podem ser paralelizadas e usufruir de um sistema capaz de executá-las em paralelo. Faça uma implementação paralelizando 4 processos filhos a partir de um pai, onde cada processo é responsável por uma busca. A quantidade de ocorrências do número buscado é retornada e capturada através de WEXITSTATUS.<br />
<br />
;Syscall EXEC<br />
<br />
*Exemplo exec()<br />
<br />
<syntaxhighlight lang=c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
execl("/bin/ls","ls","-l", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 1: Modificar o código para mostrar que o exec() não retorna (colocar um printf após o exec).<br />
<br />
*Exercício 2: Criar um exemplo (dois programas ) para demonstrar que o exec não cria novo processo. <br />
**Crie um primeiro programa (prog1) que imprime o seu pid e depois faz um exec do segundo programa.<br />
**Crie o segundo programa que simplesmente imprime o pid.<br />
<br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU ANTES DO EXEC: Meu pid é %d\n", getpid());<br />
execl("./prog2","prog2", NULL);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang= c><br />
#include <sys/types.h><br />
#include <stdio.h><br />
#include <unistd.h><br />
<br />
int main()<br />
{<br />
printf("EU DEPOIS DO EXEC:Meu pid é %d\n", getpid());<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exercício 3: Criar um exemplo usando fork/exec mostrando que um processo pai cria um filho e espera por sua execução. O filho executa o comando "ps aux". Ambos devem mostrar seus pids.<br />
<br />
{{collapse bottom}} <br />
{{collapse top| bg=lightyellow | expandir=true | Threads de aplicação}}<br />
<br />
== Threads de aplicação ==<br />
<br />
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:<br />
*'''getcontext(&a)''': salva o contexto na variável '''a''';<br />
*'''setcontext(&a)''': restaura um contexto salvo anteriormente na variável '''a''';<br />
*'''swapcontext(&a,&b)''': salva o contexto atual na variável '''a''' e restaura o contexto salvo anteriormente na variável '''b''';<br />
*'''makecontext(&a, ...)''': ajusta parâmetros internos do contexto salvo em '''a''';<br />
*'''ucontext_t''': as variáveis '''a''' e '''b''' são do tipo '''ucontext_t'''. Este tipo armazena um contexto.<br />
<br />
Busque mais informações sobre estas funções utilizando o programa manpage do Linux (ex.: man getcontext).<br />
<br />
Estude o código no arquivo pingpong.c abaixo e explique seu funcionamento.<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
<br />
*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.<br />
*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.<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <ucontext.h><br />
<br />
#define STACKSIZE 32768 /* tamanho de pilha das threads */<br />
<br />
/* VARIÁVEIS GLOBAIS */<br />
ucontext_t cPing, cPong, cMain, cFnew;<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_new(void * arg1, void * arg2,void * arg3,void * arg4) <br />
{<br />
printf ("%s: Primeira string %s %s %s\n",(char*) arg1,(char*) arg2,(char*) arg3, (char*) arg4);<br />
swapcontext(&cFnew, &cMain); <br />
}<br />
<br />
<br />
/* Funções-comportamento das Tarefas */<br />
void f_ping(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPing, &cPong);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPing, &cMain);<br />
}<br />
<br />
void f_pong(void * arg) {<br />
int i;<br />
<br />
printf("%s iniciada\n", (char *) arg);<br />
<br />
for (i=0; i<4; i++) {<br />
printf("%s %d\n", (char *) arg, i);<br />
swapcontext(&cPong, &cPing);<br />
}<br />
printf("%s FIM\n", (char *) arg);<br />
<br />
swapcontext(&cPong, &cMain);<br />
}<br />
<br />
/* MAIN */<br />
int main(int argc, char *argv[]) {<br />
char *stack;<br />
<br />
printf ("Main INICIO\n");<br />
<br />
getcontext(&cPing);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPing.uc_stack.ss_sp = stack ;<br />
cPing.uc_stack.ss_size = STACKSIZE;<br />
cPing.uc_stack.ss_flags = 0;<br />
cPing.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext(&cPing, (void*)(*f_ping), 1, "\tPing");<br />
<br />
getcontext(&cPong);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cPong.uc_stack.ss_sp = stack ;<br />
cPong.uc_stack.ss_size = STACKSIZE;<br />
cPong.uc_stack.ss_flags = 0;<br />
cPong.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cPong, (void*)(*f_pong), 1, "\tPong");<br />
<br />
<br />
getcontext(&cFnew);<br />
stack = malloc(STACKSIZE);<br />
if(stack) {<br />
cFnew.uc_stack.ss_sp = stack ;<br />
cFnew.uc_stack.ss_size = STACKSIZE;<br />
cFnew.uc_stack.ss_flags = 0;<br />
cFnew.uc_link = 0;<br />
}<br />
else {<br />
perror("Erro na criação da pilha: ");<br />
exit(1);<br />
}<br />
<br />
makecontext (&cFnew, (void*)(*f_new), 4, "\tF_new", "\tAlo", "\tMundo","\tReal");<br />
<br />
swapcontext(&cMain, &cPing);<br />
swapcontext(&cMain, &cPong);<br />
swapcontext(&cMain, &cFnew);<br />
<br />
printf("Main FIM\n");<br />
<br />
exit(0);<br />
}<br />
</syntaxhighlight><br />
--><br />
Exercício 3: O que acontece se um dos threads é colocado para dormir? Todos os demais threads param a sua execução.<br />
<br />
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/<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Trocas de mensagens com pipes}}<br />
<br />
== Trocas de mensagens com pipes ==<br />
<br />
;Troca de mensagens<br />
Um mecanismo disponibilizado por sistemas UNIX para troca de mensagens entre processos é o PIPE. Pipes são mecanismos de comunicação indireta onde mensagens são trocadas através de ''mailboxes''. Cada ''mailbox'' possui um identificador único, permitindo que processos identifiquem o canal de comunicação entre eles. O fluxo de mensagens em um Pipe é:<br />
*'''unidirecional''': sobre um mesmo pipe, apenas um processo envia mensagens e um processo recebe mensagens;<br />
*'''FIFO''': as mensagens são entregues na ordem de envio;<br />
*'''não-estruturado''': não há estrutura pré-definida para o formato da mensagem.<br />
No UNIX, pipes são inicializados através da '''SystemCall''' ''pipe'', que possui a seguinte sintaxe:<br />
*''int pipe(int pipefd[2])'': ''pipe'' inicializa um novo pipe no sistema e retorna, no array pipefd, os descritores identificando cada uma das pontas do pipe. A primeira posição do array, i.e. pipefd[0], recebe o descritor que pode ser aberto apenas para leitura, enquanto a segunda posição do array, i.e. pipefd[1], recebe o descritor que pode ser aberto apenas para escrita. A função retorna zero no caso de sucesso, ou -1 se ocorrer erro.<br />
As primitivas send/receive para uso de um pipe no UNIX são implementadas por '''SystemCalls''' read/write, conforme segue:<br />
*''ssize_t read(int fd, void *buf, size_t count)'': “puxa” dados do pipe identificado pelo descritor fd. Os dados recebidos são os apontados pelo ponteiro buf, sendo count a quantidade máxima de bytes a serem recebidos. A função retorna o número de bytes recebidos.<br />
*''ssize_t write(int fd, const void *buf, size_t count)'': “empurra” dados no pipe identificado pelo descritor fd. Os dados transmitidos são os apontados pelo ponteiro buf, sendo count a quantidade de bytes a serem transmitidos. A função retorna o número de bytes transmitidos.<br />
<br />
*Exemplo 1: Transmitindo e recebendo pelo próprio processo<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main()<br />
{<br />
int fd[2];<br />
char *ptr = "Alo eu mesmo";<br />
char *ptr_alvo;<br />
int tamanho_dados, ret;<br />
<br />
tamanho_dados = strlen(ptr)+1;<br />
<br />
if (pipe(fd)==-1){<br />
printf ("erro criação pipe\n");<br />
exit(-1);<br />
}<br />
printf("Transmitido %d bytes\n", tamanho_dados);<br />
write (fd[1], ptr, tamanho_dados);<br />
<br />
ptr_alvo = malloc(tamanho_dados);<br />
<br />
ret=read(fd[0],ptr_alvo,tamanho_dados);<br />
<br />
printf("ret = %d dados => %s\n", ret, ptr_alvo); <br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
*Exemplo 2: Abaixo há um exemplo de programa criando um pipe e compartilhando os descritores entre dois processos (criados via ''fork()'').<br />
<syntaxhighlight lang=c><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
<br />
char *message = "This is a message!!!" ;<br />
<br />
main()<br />
{<br />
char buf[1024] ;<br />
int fd[2];<br />
pipe(fd); /*create pipe*/<br />
if (fork() != 0) { /* I am the parent */<br />
write(fd[1], message, strlen (message) + 1) ;<br />
}<br />
else { /*Child code */<br />
read(fd[0], buf, 1024) ;<br />
printf("Got this from MaMa!!: %s\n", buf) ;<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
*'''Exercício 1: construa um “pipeline”'''. Crie um programa que conecta 4 processos através de 3 pipes. Utilize ''fork()'' para criar vários processos.<br />
<br />
<syntaxhighlight lang=cpp><br />
<br />
//Solução possível<br />
<br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
pipe(fd);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
<br />
</syntaxhighlight><br />
<br />
*'''Exercício 3: Modifique o exercício anterior para que o processo D, através de um novo pipe, mande uma mensagem diretamente para o pai de todos.<br />
<br />
<!--<br />
<code><br />
#include <unistd.h> <br />
#include <fcntl.h><br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h> <br />
<br />
char *message = "This is a message to send!!!" ;<br />
<br />
main()<br />
{<br />
<br />
int size = strlen(message)+1;<br />
char buf[size];<br />
char buf1[size];<br />
char buf2[size];<br />
<br />
int status;<br />
int fd[2]; <br />
int fd_retorno[2];<br />
<br />
pipe(fd);<br />
pipe(fd_retorno);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo A PID: %d\n", getpid());<br />
write(fd[1], message, size);<br />
read(fd_retorno[0], buf, size);<br />
printf("PAI:%s\n", buf); <br />
wait(&status);<br />
<br />
}<br />
else { /*Child code */<br />
<br />
int status1;<br />
int fd1[2];<br />
pipe(fd1);<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
<br />
printf("Processo B PID: %d\n", getpid());<br />
read(fd[0], buf, size); <br />
write(fd1[1], buf, size);<br />
wait(&status1);<br />
<br />
}else { /*Child code */<br />
<br />
int status2;<br />
int fd2[2];<br />
pipe(fd2);<br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
printf("Processo C PID: %d\n", getpid());<br />
<br />
read(fd1[0], buf1, size); <br />
write(fd2[1], buf1, size);<br />
wait(&status2);<br />
<br />
<br />
}else { /*Child code */<br />
char *ptr_msg_ret="Ok msg de D para o pai";<br />
printf("Processo D PID: %d\n", getpid());<br />
read(fd2[0], buf2, size);<br />
printf("\n Mensagem -> %s <- \n ", buf2);<br />
write(fd_retorno[1],ptr_msg_ret,strlen(ptr_msg_ret)+1);<br />
} <br />
<br />
} <br />
<br />
} <br />
exit(0); <br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
*'''Exercício 3: Consultor de Login de Acesso:'''. Estude o link https://www.geeksforgeeks.org/named-pipe-fifo-example-c-program/ e projete um programa cliente servidor da seguinte forma: (i) O servidor possui uma tabela de usuários (userid). O user_id é de tamanho fixo de 7 caracteres. O servidor espera por consultas para verificar se um usuário está na tabela. Se estiver responde com o caracter 'S' senão com 'N'. (ii) O cliente espera por user_id no teclado e consulta o servidor sobre sua existência na tabela. O cliente imprime na tabela a existência ou não do usuário.<br />
<br />
*'''Exercício 4: cópia de arquivo'''. Projete um programa de cópia de arquivos chamado FileCopy usando pipes comuns. Esse programa receberá dois parâmetros: o primeiro é o nome do arquivo a ser copiado e o segundo é o nome do arquivo copiado. Em seguida, o programa criará um pipe comum e gravará nele o conteúdo do arquivo a ser copiado. O processo filho lerá esse arquivo do pipe e o gravará no arquivo de destino. Por exemplo, se chamarmos o programa como descrito a seguir:<br />
:<syntaxhighlight lang=bash><br />
$ FileCopy entrada.txt copia.txt<br />
</syntaxhighlight><br />
:o arquivo ''entrada.txt'' será gravado no pipe. O processo filho lerá o conteúdo desse arquivo e o gravará no arquivo de destino ''copia.txt''. Escreva o programa usando os pipes da API POSIX no Linux.<br />
<br />
<br />
{{collapse bottom}}<br />
<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Exercícios sobre Memória Compartilhada}}<br />
<br />
==SHARED MEMORY: Produtor (pai) - Consumidor (filho) - ==<br />
<br />
<!-- Parou aki 20/08<br />
<br />
<br />
*'''Experimento 2:''' Complete o código a seguir para que os processos pai e filho possam compartilhar um segmento de memória. O filho escreve no segmento e o pai imprime na tela o conteúdo da mensagem.<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
char *ptr_msg = "alo pai, tudo bem?"; <br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
//completar aqui<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
<!--<br />
<code><br />
<br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/types.h><br />
#include <string.h><br />
#include <stdlib.h><br />
<br />
int main(void)<br />
{<br />
int fd[2], pipe_ret, filho;<br />
char string[] = "Hello, pipe!\n";<br />
char buffer[20];<br />
<br />
pipe(fd);<br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
/*Mandar string para a extremidade do pipe*/<br />
write(fd[1], string, (strlen(string)+1));<br />
exit(0);<br />
}<br />
else<br />
{<br />
<br />
/* Read in a string from the pipe */<br />
pipe_ret = read(fd[0], buffer, (20*sizeof(char)));<br />
printf("Recebi este texto %s", buffer);<br />
}<br />
<br />
return(0);<br />
}<br />
<br />
<br />
<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
key = ftok("teste_sh.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644 | IPC_CREAT));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
<br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
strncpy(segmento, "mensagem compartilhada", SHM_SIZE); <br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
--><br />
<br />
<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Memória Compartilhada}}<br />
*'''Experimento Shared Memory:''' Complete o código a seguir para que os processos pai e filho possam compartilhar um segmento de memória. O filho escreve no segmento e o pai imprime na tela o conteúdo da mensagem.<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
#include <sys/stat.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
shmid = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR);<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
char *ptr_msg = "alo pai, tudo bem?"; <br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
//completar aqui strcpy(segmento, ptr_msg); //aqui deveria testar a cpacidade da área...<br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exemplo com ftok:<br />
<br />
<syntaxhighlight lang=c><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
<br />
key = ftok("./teste.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644 | IPC_CREAT));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
segmento = shmat(shmid, (void *)0, 0);<br />
if (segmento == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
if((filho = fork()) == -1)<br />
{<br />
perror("fork");<br />
exit(1);<br />
}<br />
<br />
if(filho == 0)<br />
{<br />
<br />
printf("Filho escrevendo no segmento compartilhado\n\n");<br />
strncpy(segmento, "mensagem compartilhada", SHM_SIZE); <br />
<br />
exit(0);<br />
}<br />
else<br />
{<br />
wait(filho); <br />
printf("Mensagem para o pai: %s\n", segmento);<br />
<br />
}<br />
<br />
<br />
if (shmdt(segmento) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
*Exemplo com ftok entre processos sem parentesco:<br />
<br />
Criar um arquivo teste.txt e em um terminal executar:<br />
<br />
<syntaxhighlight lang=c><br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
int modo,filho;<br />
<br />
struct minha_struct {<br />
char flag;<br />
int numero;<br />
} *ptr;<br />
<br />
<br />
key = ftok("./teste.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644 | IPC_CREAT));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
ptr = (struct minha_struct *) shmat(shmid, (void *)0, 0);<br />
if ((char *)ptr == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
ptr->flag =0;<br />
ptr->numero = 0;<br />
while (ptr->flag==0) { <br />
printf("%d\n", ptr->numero);<br />
sleep(1);<br />
} <br />
<br />
if (shmdt(ptr) == -1) {<br />
perror("shmdt");<br />
exit(1);<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Em outro terminal executar:<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
#define SHM_SIZE 1024 <br />
<br />
int main(int argc, char *argv[])<br />
{<br />
key_t key;<br />
int shmid;<br />
char *segmento;<br />
int modo,filho;<br />
<br />
struct minha_struct {<br />
char flag;<br />
int numero;<br />
} *ptr;<br />
<br />
<br />
key = ftok("./teste.txt", 'A'); /*O arquivo deve existir de verdade*/ <br />
if (key == -1) <br />
{<br />
perror("ftok");<br />
exit(1);<br />
}<br />
<br />
<br />
shmid = shmget(key, SHM_SIZE, (0644));<br />
if (shmid == -1) {<br />
perror("shmget");<br />
exit(1);<br />
}<br />
<br />
<br />
ptr = (struct minha_struct *) shmat(shmid, (void *)0, 0);<br />
if ((char *)ptr == (char *)(-1)) {<br />
perror("shmat");<br />
exit(1);<br />
} <br />
<br />
<br />
<br />
while (ptr->numero++<10)<br />
sleep(1);<br />
<br />
ptr->flag = 1;<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Exercício Desafio: Implementar o problema do buffer circular usando memória compartilhada.<br />
<br />
{{collapse bottom}}<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Exercício (Algoritmo de Peterson)}}<br />
<br />
== Exercício (Algoritmo de Peterson) ==<br />
<br />
<br />
'''Exercício 1''': Sincronize o código a seguir, de maneira que o processo pai imprima apenas os números impares e o processo filho os números pares. Para isso utilize o algoritmo de '''Peterson''' visto em aula. '''Utilize memória compartilhada''' para comunicação entre os processos.<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
main()<br />
{ <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int i; <br />
<br />
for(i = 0;i < 10;i=i+2){ <br />
printf("Processo pai %d \n", i); <br />
<br />
} <br />
<br />
<br />
}<br />
<br />
else { /*Child code */<br />
int i; <br />
for(i = 1;i < 10;i=i+2){ <br />
printf("Processo filho %d \n", i); <br />
<br />
}<br />
<br />
<br />
}<br />
<br />
exit(0);<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
'''Exercício 2''': Considerando o exercício anterior faça a mesma sincronização, no entanto desta vez utilize a modelagem em software do TSL. <br />
* Em sua experiência, depois de testar diversas vezes as execuções de suas soluções baseadas no algoritmo de '''Peterson''' e '''Tsl''', qual sua opinião sobre as abordagens?<br />
Explique seu raciocínio. <br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Exercício (Semáforos)}}<br />
== Exercício (Semáforos) ==<br />
<br />
<br />
'''Exercício 1''': Sincronize o código a seguir, de maneira que o processo pai imprima apenas os números impares e o processo filho os números pares. Para isso utilize '''Semáforos''' de acordo com a implementação em '''semaforo.h'''. '''Utilize memória compartilhada''' para comunicação entre os processos.<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <string.h><br />
#include <sys/types.h><br />
#include <sys/ipc.h><br />
#include <sys/shm.h><br />
<br />
main()<br />
{ <br />
<br />
<br />
if (fork() != 0) { /* I am the parent */<br />
int i; <br />
<br />
for(i = 0;i < 10;i=i+2){ <br />
printf("Processo pai %d \n", i); <br />
sleep(1);<br />
<br />
} <br />
<br />
<br />
}<br />
<br />
else { /*Child code */<br />
int i; <br />
for(i = 1;i < 10;i=i+2){ <br />
printf("Processo filho %d \n", i); <br />
<br />
}<br />
<br />
<br />
}<br />
<br />
exit(0);<br />
<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
SEMAFORO.H<br />
<br />
<br />
<syntaxhighlight lang=c><br />
<br />
#include <sys/sem.h><br />
<br />
<br />
int criar_semaforo(int val, int chave) <br />
{<br />
int semid ;<br />
<br />
union semun {<br />
int val;<br />
struct semid_ds *buf ;<br />
ushort array[1];<br />
} arg_ctl ;<br />
<br />
key_t ft = ftok("/tmp", chave);<br />
<br />
semid = semget(ft,1,IPC_CREAT|IPC_EXCL|0666);<br />
if (semid == -1) {<br />
semid = semget(ft,1,0666); <br />
if (semid == -1) {<br />
perror("Erro semget()");<br />
exit(1) ;<br />
}<br />
}<br />
<br />
arg_ctl.val = val; //valor de início<br />
if (semctl(semid,0,SETVAL,arg_ctl) == -1) {<br />
perror("Erro inicializacao semaforo");<br />
exit(1);<br />
}<br />
return(semid) ;<br />
}<br />
<br />
void P(int semid){<br />
<br />
struct sembuf *sops = malloc(10*sizeof(int));<br />
sops->sem_num = 0;<br />
sops->sem_op = -1;<br />
sops->sem_flg = 0;<br />
semop(semid, sops, 1); <br />
free(sops);<br />
<br />
}<br />
<br />
<br />
void V(int semid){<br />
<br />
struct sembuf *sops = malloc(10*sizeof(int));<br />
sops->sem_num = 0;<br />
sops->sem_op = 1;<br />
sops->sem_flg = 0; <br />
semop(semid, sops, 1); <br />
free(sops);<br />
<br />
} <br />
<br />
<br />
<br />
void sem_delete(int semid) <br />
{<br />
<br />
if (semctl(semid,0,IPC_RMID,0) == -1)<br />
perror("Erro na destruicao do semaforo");<br />
}<br />
<br />
<br />
<br />
<br />
</syntaxhighlight><br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Programação concorrente}}<br />
<br />
== Programação concorrente ==<br />
<br />
;POSIX Threads<br />
A 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):<br />
*''pthread_create'': cria uma thread;<br />
*''pthread_kill'': força a terminação de uma thread;<br />
*''pthread_join'': sincroniza o final de uma thread (qual a diferença/semelhança com o ''wait'' que usamos para processos?);<br />
*''pthread_exit'': finaliza uma thread.<br />
Para utilizar estas funções é necessário linkar o programa à libpthread (''-lpthread''). <br />
<br />
<br />
;POSIX pthread mutex<br />
<br />
A biblioteca pthread implementa um tipo ''pthread_mutex_t'', que garante a exclusão mútua entre threads. Estes mutex são manipulados através das funções (acesse as man-pages das chamadas para maiores detalhes):<br />
*''pthread_mutex_lock'': acessa um mutex.<br />
*''pthread_mutex_trylock'': tenta acessar um mutex (retorna valor indicando sucesso ou falha no lock).<br />
*''pthread_mutex_unlock'': libera um mutex.<br />
<br />
<br />
<br />
<br />
;POSIX Semaphores<br />
<br />
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):<br />
*''sem_init'': inicializa um semáforo;<br />
*''sem_destroy'': destroy um semáforo;<br />
*''sem_wait'': implementa a operação ''p'';<br />
*''sem_post'': implementa a operação ''v''.<br />
Para utilizar estas funções é necessário linkar o programa à librt ou à libpthread (''-lrt'' ou ''-lpthread'').<br />
<br />
;Exercício 1<br />
<br />
O programa abaixo cria 5 threads, e cada uma destas threads atualiza uma variável global (memória compartilhada).<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include <pthread.h><br />
#include <signal.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
pthread_mutex_t mut;<br />
<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
}<br />
</syntaxhighlight><br />
<br />
# Compile este programa. <br />
# Execute este programa várias vezes. Ele funciona? Será que ele gera as saídas esperadas?<br />
# Identifique as '''seções críticas''' do programa.<br />
# Corrija o programa utilizando '''mutex'''. <br />
# Analise a função ''AtualizaSaldo()'' com a sua solução. Lembre-se que o uso do mutex implica em apenas uma thread acessar a seção crítica por vez, enquanto outras threads ficam bloqueadas, esperando. Disso vem que, quanto menor o trecho de código entre um ''lock'' e um ''unlock'', menos tempo uma thread necessita ficar esperando.<br />
# Modifique o programa para usar um semáforo binário ao invés de um mutex em sua solução.<br />
<br />
<!--<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <cstring><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
<br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
pthread_mutex_lock(&mut);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
pthread_mutex_unlock(&mut);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
pthread_mutex_init(&mut, NULL);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
}<br />
</syntaxhighlight><br />
<br />
<syntaxhighlight lang=c><br />
#include <iostream><br />
#include <pthread.h><br />
#include <signal.h><br />
#include <cstring><br />
#include <semaphore.h><br />
<br />
#define NUM_THREADS 5<br />
<br />
using namespace std;<br />
<br />
sem_t sem;<br />
pthread_mutex_t mut;<br />
int saldo = 1000;<br />
<br />
int AtualizaSaldo(int n)<br />
{<br />
int value;<br />
sem_wait(&sem);<br />
int meu_saldo = saldo;<br />
int novo_saldo = meu_saldo + n*100;<br />
cout << "Novo saldo = " << novo_saldo << endl;<br />
saldo = novo_saldo;<br />
sem_getvalue(&sem, &value);<br />
printf("valor sem = %d\n", value);<br />
sem_post(&sem);<br />
}<br />
<br />
int main()<br />
{<br />
pthread_t threads[NUM_THREADS];<br />
int i,ret;<br />
<br />
sem_init(&sem,0,1);<br />
<br />
// Cria cinco threads que executarão a mesma função<br />
for(i=0; i<5; ++i){<br />
ret = pthread_create(&threads[i], NULL, (void*(*)(void*))AtualizaSaldo,(void*)((long)i+1));<br />
if(ret != 0){<br />
fprintf(stderr, "Erro thread %d. Código %d: %s\n", (i+1), ret, strerror(ret));<br />
exit(EXIT_FAILURE);<br />
}<br />
}<br />
// Aguarda o fim das threads<br />
for(i=0; i<5; ++i)<br />
pthread_join(threads[i], NULL);<br />
<br />
cout << "Saldo final é " << saldo << "." << endl;<br />
sem_destroy(&sem);<br />
}<br />
</syntaxhighlight><br />
--><br />
<br />
<br />
;Exercício 2<br />
Refaça o exercício 3 usando processos criados com fork e exec. O semáforo deve ser criado em uma região de memória compartilhada.<br />
<br />
;Exercício 3<br />
Implemente com pthreads e semáforos/mutex a solução do produtor/comsumidor.<br />
<br />
;Exercício 4<br />
<br />
O programa abaixo manipula uma matriz de tamanho MxN (veja os defines para o tamanho da matriz). A função ''SumValues'' soma todos os valores em uma linha da matriz. A linha a ser somada é identificada pela variável ''i''. Modifique o programa principal (''main'') nos locais indicados para:<br />
# Criar N threads, uma para somar os valores de cada linha.<br />
# Receber o resultado do somatório de cada linha e gerar o somatório total da matriz.<br />
# Analise o programa: há problemas de sincronização que precisam ser resolvidos? Se sim, resolva-os.<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include "thread.h"<br />
<br />
/* number of matrix columns and rows */<br />
#define M 5<br />
#define N 10<br />
<br />
using namespace std;<br />
<br />
int matrix[N][M];<br />
Thread *threads[N];<br />
<br />
<br />
/* thread function; it sums the values of the matrix in the row */<br />
int SumValues(int i)<br />
{<br />
int n = i; /* number of row */<br />
int total = 0; /* the total of the values in the row */<br />
int j;<br />
for (j = 0; j < M; j++) /* sum values in the "n" row */<br />
total += matrix[n][j];<br />
cout << "The total in row" << n << " is " << total << "." << endl;<br />
/* terminate a thread and return a total in the row */<br />
exit(total);<br />
}<br />
<br />
int main(int argc, char *argv[])<br />
{<br />
int i, j;<br />
int total = 0; /* the total of the values in the matrix */<br />
<br />
/* initialize the matrix */<br />
for (i = 0; i < N; i++)<br />
for (j = 0; j < M; j++)<br />
matrix[i][j] = i * M + j;<br />
<br />
/* create threads */<br />
/* COLOQUE SEU CÓDIGO PARA CRIAR AS THREADS AQUI! */<br />
<br />
/* wait for terminate a threads */<br />
/* COLOQUE SEU CÓDIGO PARA PEGAR O SOMATÓRIO DE LINHAS E TOTALIZAR A SOMA DA MATRIZ AQUI! */<br />
<br />
cout << "The total values in the matrix is " << total << endl;<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Lista de exercícios "Revisão para Prova" }}<br />
<br />
== Lista de exercícios/Revisão para Prova ==<br />
<br />
A lista de exercícios referente a primeira prova (Parte introdutória + Processos) segue neste LINK [http://docente.ifsc.edu.br/andre.damato/sop2018/lista_rev1.pdf | Lista de exercícios]. <br />
<br />
{{collapse bottom}}<br />
{{collapse top| bg=lightyellow | expandir=true | Primeiro trabalho}}<br />
== JOGO DA VIDA DE CONWAY e JANTAR DOS FILÓSOFOS==<br />
<br />
;Referências<br />
<br />
* [https://www.open-mpi.org/doc/current/ MPI]<br />
<br />
* [https://quark.phy.bnl.gov/~creutz/qcdoc/mpi/mpi.h Tipos de dados MPI]<br />
<br />
* [https://pt.wikipedia.org/wiki/Jogo_da_vida Jogo da Vida]<br />
<br />
<br />
<br />
<br />
A partir da implementação sequencial do Game of Life apresentada a seguir, estude o código e transforme esta implementação em uma implementação paralela utilizando o protocolo de passagem de mensagens MPI.<br />
Perceba que a impĺementação mencionada utiliza como parâmetros de entrada um aquivo contendo o estado inicial do jogo, e o número de gerações que o usuário deseja rodar. A evolução do estado inicial <br />
é impressa na tela passo a passo. Sendo assim, a partir disso:<br />
<br />
*'''1: Elabore uma implementação com 2 processos para o jogo da vida utilizando o protocolo MPI, de maneira que um processo execute uma geração i qualquer e o outro execute a geração seguinte i+1''' <br />
<br />
*'''2: (0,7) Os processos deverão se comunicar utilizando as funções do protocolo MPI.''' <br />
<br />
*'''3: (0,3) Relatório simplificado explicando a sua solução. Utilize diagramas para representar a comunicação entre os processos, explicando como a matriz do jogo é transferida entre os processos. ''' <br />
<br />
*'''4: Entregue o Relatório e o código fonte do trabalho em um pacote compactado via e-mail (PRAZO 19/10). <br />
<br />
<br />
<br />
* ''' Compilar o código com MPI '''<br />
<code><br />
mpicc -o nomeApp arquivo.c<br />
</syntaxhighlight><br />
<br />
* ''' Rodar rodar programa utilizando MPI '''<br />
<code><br />
mpirun -np numeroDeProcessos ./nomeApp entrada.txt gerações<br />
</syntaxhighlight><br />
<br />
* (int) -np: Quantidade de processos que você deseja executar <br />
<br />
* entrada.txt: Arquivo de entrada com estado inicial do jogo <br />
<br />
* (int) gerações: número de gerações que você deseja rodar<br />
<br />
* [http://docente.ifsc.edu.br/andre.damato/sop2018/entrada.txt Arquivo de entrada para Testes]<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
<br />
<br />
<br />
/*<br />
<br />
Conway's Game of Life<br />
<br />
Compilar código com MPI<br />
mpicc -o nomeApp arquivo.c<br />
<br />
<br />
Rodar rodar programa utilizando MPI<br />
<br />
mpirun -np numeroDeProcessos ./nomeApp entrada.txt gerações<br />
<br />
(int) -np: Quantidade de processos que você deseja executar <br />
entrada.txt: Arquivo de entrada com estado inicial do jogo <br />
(int) gerações: número de gerações que você deseja rodar<br />
<br />
<br />
*/<br />
<br />
#include <stdio.h><br />
#include <string.h><br />
#include <stdlib.h><br />
#include "mpi.h"<br />
<br />
<br />
//Numero de linhas e colunas<br />
#define nLinhas 32<br />
#define nColunas 82 <br />
<br />
char *matriz[nLinhas];<br />
char *entrada[nLinhas];<br />
<br />
<br />
void iniciar() {<br />
<br />
int i;<br />
<br />
//Alocar espaço em memória para as matrizes<br />
for (i = 0; i < nLinhas; i++ ) <br />
matriz[i] = (char *) malloc((nColunas) * sizeof( char )); <br />
<br />
<br />
}<br />
<br />
int adjacente(char **matriz, int i, int j){<br />
<br />
int x,y, initX, initY, limitX, limitY;<br />
int vizinhos = 0;<br />
<br />
if(i == 0)<br />
initX = 0;<br />
else <br />
initX = -1;<br />
<br />
if(i == (nLinhas-1)) <br />
limitX = 1;<br />
else<br />
limitX = 2;<br />
<br />
<br />
if(y == 0)<br />
initY = 0;<br />
else <br />
initY = -1;<br />
<br />
if(y == (nColunas-3)) <br />
limitY = 1;<br />
else<br />
limitY = 2;<br />
<br />
for(x = initX ; x < limitX; x++){<br />
for(y = initY; y < limitY; y++){<br />
if(matriz[i+x][j+y] == '#') <br />
vizinhos++; <br />
} <br />
}<br />
<br />
<br />
if(matriz[i][j] == '#') <br />
return (vizinhos-1);<br />
else <br />
return vizinhos;<br />
<br />
}<br />
<br />
<br />
void calculoGeracao(char **matriz, int ger) {<br />
<br />
int i, j, a;<br />
char novaGeracao[nLinhas][nColunas];<br />
<br />
/* Aplicando as regras do jogo da vida */<br />
for (i=0; i < nLinhas; i++){ <br />
for (j=0; j < nColunas; j++) {<br />
<br />
a = adjacente(matriz, i, j);<br />
<br />
if (a == 2) novaGeracao[i][j] = matriz[i][j];<br />
if (a == 3) novaGeracao[i][j] = '#';<br />
if (a < 2) novaGeracao[i][j] = ' ';<br />
if (a > 3) novaGeracao[i][j] = ' ';<br />
<br />
if (j == 0)<br />
novaGeracao[i][j] = '"';<br />
} <br />
<br />
novaGeracao[i][79] = '"';<br />
novaGeracao[i][80] = '\n';<br />
<br />
<br />
}<br />
<br />
/* Passando o resultado da nova geração para a matriz de entrada */<br />
for (i=0; i < nLinhas; i++){ <br />
for (j=0; j < nColunas; j++) <br />
matriz[i][j] = novaGeracao[i][j];<br />
}<br />
}<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
main(int argc, char *argv[2]){<br />
<br />
/* Para uso com MPI<br />
<br />
<br />
//Variáveis para uso com MPI<br />
int numeroDeProcessos = 0;<br />
int rank = 0;<br />
MPI_Status status; <br />
<br />
//Iniciar MPI---<br />
MPI_Init( &argc, &argv );<br />
<br />
//Atribui a variável numeroDeProcessos o número de processos passado como parâmetro em -np <br />
MPI_Comm_size( MPI_COMM_WORLD, &numeroDeProcessos );<br />
<br />
//Pega o valor do rank (processo)<br />
MPI_Comm_rank( MPI_COMM_WORLD, &rank );<br />
*/<br />
<br />
<br />
FILE *matrizEntrada;<br />
matrizEntrada = fopen(argv[1], "r");<br />
iniciar();<br />
<br />
<br />
if (matrizEntrada == NULL)<br />
printf ("Não posso abrir o arquivo \"%s\"\n", argv[1]);<br />
<br />
<br />
char str[nColunas];<br />
int linha = 0;<br />
<br />
<br />
<br />
//Lendo o estado inicial do jogo a partir do arquivo<br />
while((fgets(str, nColunas, matrizEntrada) != NULL)&&(linha < nLinhas)){<br />
strcat(matriz[linha], str);<br />
linha++;<br />
}<br />
<br />
int i,gens; <br />
<br />
<br />
for(gens = 0; gens < atoi(argv[2]); gens++){ //Gens é o número de gerações especificado no segundo parâmetro <br />
<br />
calculoGeracao(matriz, gens);<br />
printf("%c[2J",27); // Esta linha serve para limpar a tela antes de imprimir o resultado de uma geração <br />
<br />
//Lendo o estado do jogo e imprime na tela <br />
for(i = 0; i < nLinhas; i++)<br />
printf("%s", matriz[i]); <br />
<br />
sleep(1);<br />
<br />
}<br />
<br />
<br />
for(i = 0; i < nLinhas; i++) <br />
free(matriz[i]); <br />
<br />
<br />
<br />
/* Finaliza o MPI */ <br />
//MPI_Finalize();<br />
<br />
exit(0);<br />
} <br />
<br />
<br />
</syntaxhighlight><br />
<br />
<br />
;Jantar dos Filósofos<br />
O problema clássico Jantar dos Filósofos consiste em que n fluxos (n filósofos) disputam n recursos (n talheres). No problema, para conseguir "jantar" (ou executar), cada filósofo precisa pegar dois talheres adjascentes a ele. Cada recurso é compartilhado por dois filósofos.<br />
*[http://www.doc.ic.ac.uk/~jnm/concurrency/classes/Diners/Diners.html Veja esta simulação]<br />
*[http://en.wikipedia.org/wiki/Dining_philosophers_problem Veja esta descrição do problema]<br />
<br />
<br />
* ''' (0,7) programa abaixo implementa um Jantar dos Filósofos utilizando semáforos para sincronização. Contudo, as chamadas para as operações ''v'' e ''p'' foram removidas, conforme comentários no código. Re-insira as operações no código e analise a solução. Esta modificação é suficiente para garantir que não haverá deadlock? Se sim, mostre o porque. Se não, proponha uma solução completa. '''<br />
<br />
<br />
*''' (0,3) Relatório simplificado explicando a sua solução. ''' <br />
<br />
*''' Entregue o Relatório e o código fonte do trabalho em um pacote compactado via e-mail (PRAZO 19/10). <br />
<br />
<br />
<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <iostream><br />
#include "thread.h"<br />
#include "semaphore.h"<br />
<br />
using namespace std;<br />
<br />
const int DELAY = 10000000;<br />
const int ITERATIONS = 5;<br />
<br />
Semaphore chopstick[5];<br />
<br />
int philosopher(int n)<br />
{<br />
cout << "Philosopher " << n << " was born!\n";<br />
<br />
int first = (n < 4)? n : 0; // left for phil 0 .. 3, right for phil 4<br />
int second = (n < 4)? n + 1 : 4; // right for phil 0 .. 3, left for phil 4<br />
<br />
// Foram removidos do laço abaixo:<br />
// - uma chamada para chopstick[first].p()<br />
// - uma chamada para chopstick[second].p()<br />
// - uma chamada para chopstick[first].v()<br />
// - uma chamada para chopstick[second].v()<br />
for(int i = 0; i < ITERATIONS; i++) {<br />
cout << "Philosopher " << n << " thinking ...\n";<br />
for(int i = 0; i < DELAY * 10; i++);<br />
<br />
cout << "Philosopher " << n << " eating ...\n";<br />
for(int i = 0; i < DELAY; i++);<br />
}<br />
<br />
return n;<br />
}<br />
<br />
int main()<br />
{<br />
cout << "The Dining-Philosophers Problem\n";<br />
<br />
Thread * phil[5];<br />
for(int i = 0; i < 5; i++)<br />
phil[i] = new Thread(&philosopher, i);<br />
<br />
int status;<br />
for(int i = 0; i < 5; i++) {<br />
phil[i]->join(&status);<br />
if(status == i)<br />
cout << "Philosopher " << i << " went to heaven!\n";<br />
else<br />
cout << "Philosopher " << i << " went to hell!\n";<br />
}<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top| bg=lightyellow | expandir=true | Softwares básicos, caso Hello Word! (Trabalho 2) Entrega dia 09/11}}<br />
<br />
== Softwares básicos, caso Hello Word! ==<br />
<br />
O objetivo do experimento de hoje é pesquisar e entender os processos de atribuição de endereços de programas realizados em tempo de compilação pelos softwares básicos como: compilador, linker, e assembler. Sendo assim, neste experimento vamos utilizar os seguintes softwares para criação e análise de código:<br />
<br />
*'''GCC''': compilador para gerar código objeto a partir de um código de programa escrito na linguagem c;<br />
*'''GNU Linker (LD)''': Para vincular os códigos (módulos) objetos do programa;<br />
*[https://linux.die.net/man/1/ld| Linker ] <br />
*'''GNU Assembler''': Para gerar o código executável a partir do código objeto;<br />
*[https://linux.die.net/man/1/as | assembler]<br />
* '''OBJDUMP''': Para mostrar informações do código;<br />
*[https://linux.die.net/man/1/objdump | Objdump ]<br />
<br />
<br />
A seguir segue descrito o programa a ser utilizado no exercício 1:<br />
<br />
<syntaxhighlight lang=cpp><br />
#include <stdio.h><br />
int main()<br />
{<br />
printf("Hello, World!");<br />
return 0;<br />
}<br />
<br />
</syntaxhighlight><br />
Trata-se do programa hello word, este programa apenas exibe uma mensagem na tela. No entanto, vamos analisar como são as etapas confecção do executável a partir deste código ''simples''. <br />
<br />
Exercício 1: <br />
* Compile o programa hello word, e o transforme em código objeto utilizando o programa GCC. Para esta tarefa execute o seguinte comando:<br />
<code><br />
gcc -o hello hello.c <br />
</syntaxhighlight><br />
* Agora abra o código objeto utilizando o programa OBJDUMP.<br />
<code><br />
objdump -D hello<br />
</syntaxhighlight><br />
* Identifique quais são as seções de código obtidas a partir do '''hello.c'''.<br />
* Pesquise e entenda o significado das seções de código: .bss, .txt, .data, .init.<br />
* Faça uma análise e identifique o endereço de memória que o programa ''hello world'' vai ser carregado. <br />
* Este código objeto é relocável? Justifique sua resposta.<br />
* Agora gere o código assembly do hello world.<br />
<code><br />
gcc -S hello.c<br />
</syntaxhighlight> <br />
*Agora gere o código executável utilizando o programa '''AS''' e o programa '''LD'''.<br />
<code><br />
as -o hello.o hello.s<br />
</syntaxhighlight><br />
* Como a etapa de linkagem para a construção do código executável está sendo executada sem o auxílio do '''GCC''', necessitamos vincular manualmente as bibliotecas necessárias. Para criar apropriadamente o executável vamos precisar das bibliotecas '''ld-linux-x86-64.so.2''', '''crt1.o''', '''crti.o''', '''crtn.o'''.<br />
* Para descobrir suas respectivas localizações use o comando '''LOCATE'''. Por exemplo:<br />
<code><br />
<br />
locate crti.o <br />
<br />
</syntaxhighlight><br />
<br />
ou <br />
<br />
<code><br />
<br />
find /usr/ -name crti*<br />
<br />
</syntaxhighlight><br />
<br />
* Agora que já sabemos a localização das bibliotecas necessárias vamos vincular essas a nossa aplicação.<br />
<code><br />
ld --dynamic-linker /caminho/ld-linux-x86-64.so.2 /caminho/crt1.o /caminho/crti.o /caminho/crtn.o hello.o -lc -o hello.exe<br />
</syntaxhighlight><br />
<br />
* Agora abra o código objeto utilizando o programa OBJDUMP.<br />
* Faça uma análise e identifique o endereço de memória em que o programa ''hello world'' inicializa suas estruturas na memória.<br />
* Dica!<br />
<code><br />
objdump -D -s -j .init hello.exe<br />
</syntaxhighlight><br />
* Houve diferença entre os endereços do programa executável em relação ao código objeto? Explique.<br />
* Explique as principais diferenças entre o arquivo objeto .o e o executável final. (dica utilize o objdump para fazer essa análise)<br />
{{collapse bottom}}<br />
<ol><br />
<li> Estudar e executar o código em http://cs.lmu.edu/~ray/notes/gasexamples/ <br />
Detalhes das chamadas na arquitetura x86_64 ver em https://lwn.net/Articles/604287/ <br />
<li>Estudar e executar o código usando a função (em conformidade com a API POSIX) write() para o ''hello world'':<br />
<code><br />
#include <unistd.h> <br />
<br />
main()<br />
{<br />
write(1,"Alo Mundo\n",10);<br />
}<br />
</syntaxhighlight><br />
</li><br />
<li> Use o comando strace para verificar todas as chamadas de sistema dos programas acima.<br />
</li><br />
<li><br />
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:<br />
<code><br />
main()<br />
{<br />
meu_hello_world();<br />
}<br />
</syntaxhighlight><br />
</li><br />
Gere o assembly do código em C e discuta a diferença entre uma chamada de função e uma chamada de sistema.<br />
<li><br />
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:<br />
<code><br />
#include <string.h><br />
main()<br />
{<br />
char *p="Tudo bem com vocês?";<br />
meu_hello_world(p, strlen(p));<br />
}<br />
</syntaxhighlight><br />
Solução:<br />
{{collapse top|Solução}}<br />
<code><br />
modificado de http://cs.lmu.edu/~ray/notes/gasexamples/<br />
.global meu_hello_world<br />
<br />
.text<br />
meu_hello_world:<br />
<br />
push %rdi # salva primeiro parâmetro<br />
push %rsi # salva segundo parâmetro<br />
mov $1, %rax # system call 1 é write<br />
mov $1, %rdi # file handle 1 é stdout<br />
mov $message, %rsi # endereço da string<br />
mov $13, %rdx # número de bytes da string<br />
syscall # chamada ao sistema<br />
<br />
pop %rdx # o que havia sido passado em rsi (número de bytes) é colocado em rdx<br />
pop %rsi # o que havia sido colocado em rdi (endereço da string) é colocado em rsi<br />
mov $1, %rax # system call 1 is write<br />
mov $1, %rdi # file handle 1 é stdout<br />
syscall # nova chamada ao sistema<br />
<br />
ret<br />
<br />
message:<br />
.ascii "Hello, World\n"<br />
</syntaxhighlight><br />
</li><br />
</ol><br />
{{collapse bottom}}</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=Arquivo:Smith_casamento_misto.pdf&diff=162027Arquivo:Smith casamento misto.pdf2019-10-04T00:43:41Z<p>127.0.0.1: </p>
<hr />
<div></div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=MTG-EngTel_(p%C3%A1gina)&diff=162026MTG-EngTel (página)2019-10-04T00:43:14Z<p>127.0.0.1: /* 08/10 - Carta de Smith - Casamento de Impedâncias */</p>
<hr />
<div>{{DivulgueEngtelecom}}<br />
<br />
= [[MTG-EngTel|Carga horária, Ementas, Bibliografia, Professores]]=<br />
<br />
= [[Cronograma de atividades (MTG-EngTel)]]=<br />
<br />
= [[MTG-EngTel (Plano de Ensino) | Plano de Ensino]]=<br />
<br />
<br />
'''Professores da Unidade Curricular'''<br />
<br />
{{Professor|2019-2|[[Jorge Henrique B. Casagrande]] }}<br />
<br />
{{Professor|'''2017-2'''| [[MTG29007 2017-2|'''Meios de Transmissão Guiados - Wiki''']] - [[https://moodle.sj.ifsc.edu.br/course/view.php?id=80 '''Meios de Transmissão Guiados - Moodle''']]([https://wiki.sj.ifsc.edu.br/index.php/Usu%C3%A1rio:Ederson.luiz Ederson Luiz de Souza Santos])}}<br />
{{Professor|'''2017-2'''| [[MTG29007 2017-2|'''Meios de Transmissão Guiados - Wiki''']] - [[https://moodle.sj.ifsc.edu.br/course/view.php?id=80 '''Meios de Transmissão Guiados - Moodle''']]([https://wiki.sj.ifsc.edu.br/index.php/Usu%C3%A1rio:karin.eickhoff Karin Eickhoff Cavalhieri])}}<br />
<br />
{{Professor|2015-2|[[Saul S. Caetano]] ([[MTG-EngTel-2015-2 Meios de Transmissão Guiados | Diário de aulas)]]}}<br />
{{Professor|2015-1|[[Saul S. Caetano]] ([[MTG-EngTel-2015-1 Meios de Transmissão Guiados | Diário de aulas)]]}}<br />
<br />
<br />
=Dados Importantes=<br />
''Professor'': [[Jorge Henrique B. Casagrande]]<br />
<br>''Email'': casagrande@ifsc.edu.br<br />
<br>'''Atendimento paralelo: 2as e 5as das 17:35h às 18:30h''' (Sala de Professores de TELE II ou Laboratório de Meios de Transmissão)<br />
<br> ''Link alternativo para Material de Apoio da disciplina'': http://www.sj.ifsc.edu.br/~casagrande/MTG<br />
<br />
=Resultados das Avaliações=<br />
<br />
;Critérios<br />
:Os alunos serão avaliados da seguinte forma:<br />
::- 3 Avaliações parciais A1, A2 e A3. Cada avaliação parcial contará com uma '''PROVA ESCRITA''' de 2HA de conteúdos preferencialmente associados as teorias e práticas da disciplina os quais representam 60% da nota; Os outros 40% de cada avaliação parcial é relativa a média das notas atribuídas a aptidão e qualidade das atividades práticas e teóricas correspondentes, atividades extras e avaliação individual.<br><br />
::- Avaliação Individual (AI1, AI2 e AI3) é uma nota atribuída pelo professor que representa o mérito de assiduidade, participação em sala, cumprimento de tarefas adicionais como relatórios e listas de exercícios.<br><br />
::- Todas as notas parciais serão valoradas de 0 à 10 em passos de 1 ponto e convertidas em conceitos conforme abaixo:<br />
::Se '''NOTA FINAL (NF)''' OU '''PROVA ESCRITA'''da avaliação parcial '''< 6''' é OBRIGATÓRIO realizar a recuperação dos conteúdos da respectiva avaliação parcial <br><br />
::Se '''NOTA FINAL''' OU '''PROVA ESCRITA'''da avaliação parcial '''>= 6''' a recuperação de conteúdos é opcional<br><br />
<br />
::- '''Para a aprovação na disciplina''' é necessário atingir no mínimo nota '''6''' na média final ponderada em carga horária de todas as avaliações parciais e 75% de participação em sala de aula;<br><br />
::- As datas de recuperação das avaliações parciais serão decididas em comum acordo com a turma. <br><br />
<br />
<br />
{| border="1" cellpadding="5" cellspacing="0" <br />
!Aluno<br />
!AE1<br />
!AE2<br />
!AI1<br />
!Prova1 <br />
!A1<br />
!REC A1<br />
!NF A1<br />
!AE4<br />
|-<br />
|Alisson ||90 ||70 ||90 ||35 ||54 || || ||<br />
|-<br />
|Guilherme ||90 ||70 ||90||48 ||62 || || ||<br />
|-<br />
|Rafael ||90 ||80 ||90|| 54|| 67|| || ||<br />
|-<br />
|Victor ||90 ||70 ||90 ||37 || 56|| || ||<br />
|-<br />
|Yan ||90 ||80 ||90 ||80 ||83 || || ||<br />
|- <br />
|}<br />
<br />
'''LEGENDA E DETALHES '''<br />
<br />
AE1 = Parâmetros distribuídos de cabos comerciais - 29/08 <br><br />
AE2 = Simulação MATLAB Magnitude versus tamanho da LT - 12/09 <br><br />
<br />
=Recados Importantes=<br />
<br />
<br> Toda vez que você encontrar a marcação <math>\blacklozenge</math> ao lado de alguma atividade, significa que essa atividade estará sendo computada na avaliação como AIn de An. O prazo estabelecido para entrega estará destacado ao lado da atividade. Portanto, não perca o prazo limite para entrega. '''Atividades entregues fora do prazo terão seu valor máximo de nota debitado de 10 pontos ao dia;'''<br />
<br />
<br> '''Uso da Wiki:''' Todo o repositório de material de apoio e referências de nossas aulas passam a usar a Wiki de tele;<br />
<br />
<br> '''Whatsapp:''' Para interação fora da sala de aula, acessem nosso grupo no Whatsapp;<br />
<br />
<br> '''SIGAA: ''' Eventualmente alguns materiais, mídias instrucionais, avaliações ou atividades poderão usar o ambiente da turma virtual do SIGAA. O professor fará o devido destaque para isso;<br />
<br />
<br> '''ATENÇÃO:''' Uma avaliação poderá ser recuperada somente se existir justificativa reconhecida pela coordenação. Desse modo, deve-se protocolar a justificativa no prazo de 48 horas, contando da data e horário da avaliação, e aguardar o parecer da coordenação. O não cumprimento desse procedimento implica a impossibilidade de fazer a recuperação.<br />
<br />
=Material de Apoio=<br />
<br />
;Tabela de leitura básica e de atividades correlatas das Bibliografias recomendadas.<br />
<br />
{| border="1" cellpadding="5" cellspacing="0" <br />
!Referência<br />
!Tópicos<br />
!Observações<br />
|-<br />
| || || <br />
|-<br />
| || || <br />
|-<br />
| || || <br />
|-<br />
|}<br />
<br />
;Atividades extra sala de aula<br />
:* [[media:MTG29007_lista1_2019_2.pdf | LISTA1]] de exercícios para a avaliação A1<br />
:* [[media:MTG29007_lista2_2019_2.pdf | LISTA2]] de exercícios para a avaliação A2<br />
:* [[media:MTG29007_lista3_2019_2.pdf | LISTA3]] de exercícios para a avaliação A3<br />
<br />
;Slides utilizados durante algumas aulas<br />
<br />
:* [[media:MTG29007_parte1_parametros.pdf | Parte1 - Parâmetros Distribuídos - Primários]] Slides sobre os Paramêtros Primários de LTs da Parte 1;<br />
:* [[media:MTG29007_parte1_fasores.pdf | Parte1 - Fasore e Parâmetros Distribuídos - Secundários]] Slides sobre Fasores e os Paramêtros Secundários de LTs da Parte 1;<br />
:* [[media:MTG29007_parte2.pdf | Parte2]] Slides da Parte 2 para acompanhamento das aulas<br />
:* [[media:MTG29007_parte3.pdf | Parte3]] Slides da Parte 3 para acompanhamento das aulas<br />
<br />
<br />
;Manuais e outros<br />
<br />
* [https://www.youtube.com/watch?v=mNkWP61GiVs vídeo sobre a meios guiados]<br />
* [http://tele.sj.ifsc.edu.br/~casagrande/MTG/apoio/cartasmith.pdf Carta de Smith] <br />
<br />
<br />
== Bibliografia Básica ==<br />
<br />
* DUTTA WDM TECHNOLOGIES - OPTICAL NETWORKS; ed. [S.l]:ELSEVIER, 2004;<br />
* RAMASWAMI, R.; SIVARAJAN, K. Optical Networks: A Practical Perspective; 3ª ed. [S.l]:Morgan Kaufmann, 2009;<br />
* WENTWORTH, Stuart M. Eletromagnetismo aplicado : abordagem antecipada das linhas de transmissão; ed. [S.l]: Bookman, 2009.<br />
<br />
== Bibliografia Complementar ==<br />
<br />
* KRAMER, Glen Ethernet passive optical networks; ed. New York:McGraw-Hill,, 2005;<br />
* AMAZONAS, José R.A Projeto de sistemas de comunicações ópticas; 1ª ed. [S.l]:Manole, 2005;<br />
* COELHO, Paulo Eustáquio Projetos de redes locais com cabeamento estruturado; ed. Belo Horizonte: Instituto Online, 2003;<br />
* MAGNUSSON, Philip C. Transmission lines and wave propagation; 4ª ed. [S.l]:Boca Raton, FL : CRC Press, 2001;<br />
* HECHT, Jeff. Understanding Fiber Optics; 5ª ed. [S.l]:Prentice Hall, 2005.<br />
<br />
<br />
Para pesquisar o acervo das bibliotecas do IFSC:<br />
<br />
* [http://biblioteca.ifsc.edu.br/sophia/ Acesso ao acervo da Biblioteca do IFSC]<br />
<br />
== Softwares e Links úteis ==<br />
<br />
<!--* [[Netkit]]: possibilita criar experimentos com redes compostas por máquinas virtuais Linux<br />
* [http://tele.sj.ifsc.edu.br/~casagrande/IER/ipkit.html IPKIT]: um simulador de encaminhamento IP em java (roda direto no navegador)--><br />
* [https://www.sejda.com/pdf-editor editor de PDF]:<br />
<br />
=Diário de aulas MTG29007 - 2019-2 - Prof. Jorge H. B. Casagrande=<br />
<br />
<br />
{{Collapse top |30/07 - Os Meios de transmissão e suas limitações}}<br />
<br />
==30/07 - Os Meios de transmissão e suas limitações ==<br />
<br />
* Apresentação da disciplina e plano de ensino;<br />
* Relembrando os principais meios de transmissão.<br />
<br />
== Tipos de meios utilizados em telecomunicações ==<br />
<br />
:'''Par trançado:''' Utilizado na rede de distribuição telefônica, principalmente do armário de distribuição até o assinante. Também é utilizado no cabeamento estruturado. Em geral esta acondicionado em cabos com vários pares, os quais são identificados por um código de cores.<br />
<br />
[http://www.conducab.ind.br/anexos/Anexo054-Cabos%20Telefonicos%20CCE%20APL.pdf detalhes de fabricante]<br />
<br />
:: [[Arquivo:cabo_telefonico.jpg |300px]] [http://www.furukawa.com.br/br/produtos/cabo-telefonico-metalico/rede-subterranea-ou-rede-espinada-em-mensageiro/cabo-telefonico-metalico-ctp-apl-g-540.html fonte]<br />
<br />
<br />
<br />
::'''Cabo coaxial:''' Empregado nas redes de distribuição de CATV e CFTV, na interligação entre equipamentos de telecomunicações e nas ligações entre transmissores e antenas. É formado por um condutor central, dielétrico, malha externa e capa protetora.<br />
:: [[Arquivo: cabo_coaxial.jpg |300px]] [http://en.wikipedia.org/wiki/Coaxial_cable fonte]<br />
<br />
<br />
::'''Fibra óptica:''' Está no coração de todas as redes de telecomunicações (Voz, Imagem e Dados).É utilizada em redes de transmissão e distribuição telefônicas, em redes de CATV e no cabeamento estruturado. É composta por um núcleo e uma casca, dois vidros com índices de refração diferentes. A tendência é que substitua o par trançado e o cabo coaxial. No cabeamento estruturado sua maior restrição de uso é o custo dos equipamentos de ponta (placas de rede e portas ópticas de equipamentos).<br />
::[[Arquivo: Optical_Fiber.jpg |300px]] [[http://en.wikipedia.org/wiki/Optical_fiber fonte]]<br />
<br />
:::* [http://www.cablemap.info/ Mapa dos cabos ópticos ao redor do planeta]<br />
<br />
<br />
<br />
::'''Ar (wireless):''' empregado nas comunicações sem fio.<br />
::[[Arquivo: radiotransmissao.jpg|300px]] [http://en.wikipedia.org/wiki/Twisted_pair fonte]<br />
<br />
; ...e a novidade:<br />
<br />
::''' Guia de onda:''' Utilizado na faixa de microondas, em frequências próximas ou superiores a 2 GHz. Nessa faixa de frequência apresenta menor atenuação do que os cabos coaxiais equivalentes. Utilizado para interligar os estágios amplificadores de potência em sistemas de radiodifusão e para ligar esses amplificadores aos seus respectivos sistemas de antenas.<br />
:: [[Arquivo:Guia_de_onda.jpg |300px]] [http://www.epirsa.com/htm/productos.asp?id=79 fonte]<br />
<br />
<br />
<br />
: Independente do meio os cabos que os encapsulam podem diferir em função do ambiente onde serão instalados. Existem cabos para ambientes internos, para instalação aérea, subterrânea ou diretamente enterrada.<br />
<br />
<br />
::'''Código de cores'''<br />
<br />
:::Para identificação dos pares trançados dentro dos cabos multipares existe um código de cores padronizado como por exemplo, do fabricante Furukawa [[Arquivo:ET923.pdf]].<br />
<br />
:::Além do código de cores os cabos de pares trançados são fabricados através do agrupamento de grupos de 25 ou supergrupos de 50 ou 100 pares .<br />
<br />
:::Os cabos de fibra óptica também utilizam um código de cores.<br />
<br />
:: [[Arquivo: FiberCableCodes2.jpg|500px]] [http://www.accu-tech.com/accu-insider/bid/98212/Corning-Accu-tech-Introduction-to-Fiber-Color-Codes]<br />
<br />
== Parâmetros concentrados x Parâmetros distribuídos ==<br />
<br />
No estudo de análise de circuitos é comum tratar os condutores que interligam fontes, resistores, indutores e capacitores como ideais. Estes condurores não apresentam resistência ou outras propriedades elétricas, são condutores perfeitos. <br />
<br />
Este tipo de abordagem é possível devido a boa qualidade dos condutores utilizados nos circuitos elétricos. A resistência desses condutores é muito baixa podendo ser desprezada na maioria dos casos.<br />
<br />
Além da boa qualidade dos condutores, é possível desprezar seus efeitos elétricos quando estamos trabalhando em baixas frequências e/ou com comprimentos de onda que se propaga no meio muito maiores do que o comprimento dos condutores.<br />
<br />
Os condutores que interligam uma fonte a uma impedância não são tratados como ideais quando tem comprimentos da mesma ordem de grandeza ou maiores do que o comprimento de onda gerado pela fonte. Nesses casos os efeitos resistivos, capacitivos e indutivos dos condutores influenciam no comportamento das tensões e das correntes do circuito elétrico. <br />
<br />
<br />
::'''Parâmetros Concentrados:''' Quando tratamos os condutores que interligam componentes como ideais, trabalhamos com a abordagem de '''parâmetros concentrados''', isto é, consideramos que os efeitos resistivos, capacitivos e indutivos resultam apenas dos componentes que inserimos no circuito.<br />
<br />
<br />
::'''Parâmetros Distribuídos:''' Quando o comprimento de onda que se propaga num circuito apresenta a mesma ordem de grandeza ou é muito menor do que o tamanho dos condutores que interligam os componentes, temos que considerar os efeitos das propriedades elétricas desses condutores. Nesse caso, utilizamos uma abordagem de '''parâmetros distribuídos'''.<br />
<br />
<br />
::''' Tensão, corrente e onda eletromagnética:''' Um condutor percorrido por corrente elétrica gera ao seu redor um campo magnético. Se a corrente variar no tempo, o campo magnético também sofrerá variações, produzindo uma perturbação magnética que se propaga na forma de uma onda eletromagnética. De formar semelhante um par de condutores submetidos a uma tensão elétrica geram no espaço um campo elétrico. Se a tensão variar o campo elétrico irá gera uma perturbação eletromagnética. Essa breve descrição da relação entre tensão, corrente e onda eletromagnética, já fornece elementos para admitirmos que a propagação da energia elétrica por circuitos pode ser analisada considerando suas tensões e correntes ou a onda eletromagnética que o percorre.<br />
<br />
<br />
::'''Parâmetros de uma onda sinusoidal:''' Onda é a propagação de uma perturbação através do espaço ou de um meio sem que acha a propagação da matéria. Apenas a energia da perturbação é propagada. São parâmetros de uma onda periódica sinusoidal:<br />
<br />
<br />
::<span style="color: red">'''1. Frequência (f)'''</span>: quantidade de vezes que a onda se repete em um segundo (Hz)<br />
::<span style="color: red">'''2. Período (T)'''</span>: intervalo de tempo entre o fim e o início de um ciclo da onda. É o inverso da frequência (s)<br />
::<span style="color: red">'''3. Amplitude máxima'''</span>: valor máximo que a perturbação atinge durante um ciclo. Sua unidade depende da natureza da onda. (tensão - V, corrente - A, campo elétrico - N/C, campo Magnético - T ...)<br />
::<span style="color: red">'''4. Velocidade de propagação (Vp)'''</span>: a velocidade da onda eletromagnética é a velocidade da luz. No vácuo é aproximadamente <math>3x10^8</math> m/s<br />
::<span style="color: red">'''5. Comprimento de onda (<math>\lambda</math>)'''</span>: comprimento de um ciclo completo da onda (m)<br />
<br />
::'''Relação entre Vp,<math>\lambda</math> e f:<span style="color: red"> <math>Vp= \lambda . f</math></span>'''<br />
<br />
{|class="wikitable"<br />
|style= "width:400px;"|[[Arquivo:Parametros_onda_lambda.png ]]<br />
|style= "width:400px;"| [[Arquivo:Parametros_onda_periodo.png ]]<br />
|}<br />
<br />
<br />
== Relação entre <math>\lambda</math> e o tamanho dos "condutores" que interligam os componentes ==<br />
<br />
As duas comparações que seguem procuram mostrar a diferença do fenômeno físico entre para o circuito abaixo, percorrido por uma onda com <span style="color: red">'''&lambda;'''</span> muito maior do que o seu tamanho físico e um circuito percorrido por uma onda com <span style="color: red">'''&lambda;'''</span> igual ou inferior ao seu tamanho físico.<br />
<br />
[[Arquivo:Circuito_1.gif |700px]] <br />
<br />
: <<strike>-----------------------------------------------------------------</strike>0,30 m <strike>--------------------------------------------------------------</strike>><br />
<br />
<br />
<br />
* <u> Circuito com <span style="color: red">'''&lambda;'''</span> muito maior do que o seu tamanho físico.</u><br />
<br />
Neste circuito a fonte gera uma onda com f=60 Hz, para simplificação dos cálculos vamos considerar que a velocidade da onda eletromagnética no condutor é igual a 3x10<sup>8</sup>, portanto: <br />
<br />
:::<math>\lambda={Vp \over f}= {3.10^8 \over 60} = 5.10^6 m</math><br />
<br />
Como o circuito tem apenas 0,30 m a variação da tensão entre o ponto onde esta a fonte e o ponto onde esta o resistor é menor que 3x10<sup>-6</sup>. Comparando esse valor com a tensão da fonte percebe-se que o mesmo é desprezível. Quanto a fase, temos que:<br />
<br />
:::: <math>\beta = {360 \over 5.10^6}= 7,2.10^{-5 } { .^o}/m </math>.<br />
<br />
<br />
Para 0,30 m <math>\theta = 0,30 \beta = 2,2.10^{-5} {.^o}</math>, novamente desprezível.<br />
<br />
Considerando a diferença da tensão e da fase entre a fonte e o resistor, podemos considerar que as mesmas são iguais e o condutor como ideal.<br />
<br />
<br />
[[Arquivo:Seno60.png|700px]]<br />
<br />
<br />
<br />
* <u> Circuito com <span style="color: red">'''&lambda;'''</span> muito menor do que o seu tamanho físico.</u><br />
<br />
Para o segundo circuito abaixo, a fonte gera uma onda com <math>f= 3 GHz</math>, portanto: <math>\lambda={Vp \over f}= {3.10^8 \over 3.10^9} = 0,10 m</math><br />
<br />
<br />
[[Arquivo:Circuito_2.gif|700px]]<br />
<br />
: <<strike>------------------------------------------------------------</strike>0,30 m <strike>---------------------------------------------------------------</strike>><br />
<br />
<br />
Como o circuito tem 0,30 m entre a fonte e o resistor cabem 3 comprimentos de onda completos. Se acompanharmos o valor da tensão ao longo do condutor vemos que o mesmo altera várias vezes entre o valor máximo e o mínimo. Não podemos desconsiderar essa variação, temos que analisar o que ocorre em cada parte do condutor também.<br />
<br />
Se o nosso circuito tivesse 0,35m o valor da tensão no resistor seria de 10V enquanto na fonte o valor seria de 0 V !!!!<br />
<br />
Em relação a fase temos que <math>\beta = {360 \over 0,1}= 36^o/m </math>. Para 0,30 m <math>\theta = 0,30 \beta = 1080^o</math>.Essa defasagem não pode ser desconsiderada.<br />
<br />
<br />
Nesta situação trabalhamos com a abordagem de parâmetros distribuídos.<br />
<br />
<br />
<br />
[[Arquivo:Seno_3giga.png|700px]]<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |22/08 - Parâmetros Distribuídos - Parâmetros Primários da Linha de transmissão}}<br />
<br />
==22/08 - Parâmetros Distribuídos - Parâmetros Primários da Linha de transmissão ==<br />
<br />
:* [[media:MTG29007_parte1_parametros.pdf | Parte1 - Parâmetros Distribuídos]] Slides sobre os Paramêtros Primários de LTs da Parte 1<br />
<br />
Parâmetros Distribuídos considerando Sinais de frequências elevadas<br />
<br />
* R' - Resistência por comprimento de Linha;<br />
* G' - Condutância por comprimento de Linha;<br />
* C' - Capacitância por comprimento de Linha;<br />
* L' - Indutância por comprimento de Linha;<br />
<br />
<br />
* Par Trançado e cabo Coaxial.<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |27/08 - Fasores e Parâmetros Distribuídos - Parâmetros Secundários da Linha de Transmissão}}<br />
<br />
==27/08 - Fasores e Parâmetros Distribuídos - Parâmetros Secundários da Linha de Transmissão ==<br />
<br />
:* [[media:MTG29007_parte1_fasores.pdf | Parte1 - Fasores e Parâmetros Distribuídos - Secundários]] Slides sobre Fasores e os Parâmetros Secundários de LTs da Parte 1<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 29/08 - <math>\blacklozenge</math> Parâmetros Distribuídos - Impedância Característica das Linhas de Transmissão}}<br />
<br />
== 29/08 - <math>\blacklozenge</math> Parâmetros Distribuídos - Impedância Característica das Linhas de Transmissão ==<br />
<br />
* Equações Telegráficas das Linhas de Transmissão;<br />
* Parâmetros secundários das Linhas de Transmissão;<br />
* Impedância característica;<br />
* Exercício.<br />
<br />
<math>\blacklozenge</math> '''Atividade Extra: Entrega INDIVIDUAL até 03/09/2019, manuscrito ou impresso.'''<br />
<br />
Pesquise e selecione na internet fabricante de boa procedência de um dos tipos de cabo: par trançado (UTP, STP, ou para redes telefônicas) ou coaxial (linha RG). Procure encontrar os detalhes construtivos informados pela folha de dados do fabricante como medidas e características elétricas dos condutores e isolantes de tal modo que você consiga determinar com precisão, os valores dos parâmetros distribuídos primários do cabo (R', C', L' e G') para uma operação com ondas viajantes de 1GHz. De posse desses valores determine também os valores esperados dos parâmetros secundários do mesmo meio ('''<math> \alpha; \beta; \gamma </math>'''). Detalhe as informações, ilustrações e cálculos de todos os parâmetros calculados para futuro uso em ensaios de laboratório.<br />
<br />
Links sugestão de alguns cabos:<br />
[https://www.timesmicrowave.com/calculator/?productId=121 Times Microwave]<br />
[https://www.furukawalatam.com/pt-br/catalogo-de-produtos-categoria/FCS/produto-fcs/cabo-lan Furukawa]<br />
[https://www.nexans.com.br/eservice/Brazil-pt_BR/navigate_219588/Cabos_telefonicos.html Nexans]<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 03/09 - Linhas de Transmissão sem Perdas}}<br />
<br />
== 03/09 - Linhas de Transmissão sem Perdas ==<br />
<br />
* Constante de Propagação desconsiderando perdas;<br />
* Impedância Característica;<br />
* Parâmetros de cabos coaxiais sem perdas;<br />
* Exercícios;<br />
* Transmissão de Potência em LTs sem perdas.<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 05/09 - Transmissão de Potência em LTs com Perdas - LTs Terminadas com Carga}}<br />
<br />
== 05/09 - Transmissão de Potência em LTs com Perdas - LTs Terminadas com Carga ==<br />
<br />
* Transmissão de Potência em LTs com Perdas;<br />
* Exercício;<br />
* LTs Terminadas com Carga;<br />
* Coeficiente de Reflexão na carga;<br />
* Coeficiente de Reflexão em qquer pto da LT.<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 10/09 - Razão de Onda de Tensão Estacionária - VSWR ou ROTE}}<br />
<br />
== 10/09 - Razão de Onda de Tensão Estacionária - VSWR ou ROTE ==<br />
<br />
* Relação do Coeficiente de Reflexão com VSWR;<br />
* Exercícios;<br />
* Impedância de Entrada para LTs com perdas e sem perdas;<br />
* Cargas Complexas;<br />
* Circuitos Completos;<br />
* Exercícios.<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 12/09 - <math>\blacklozenge</math> Circuito Completo da LT - Transitórios - Resposta ao Degrau}}<br />
<br />
== 12/09 - <math>\blacklozenge</math> Circuito Completo da LT - Transitórios - Resposta ao Degrau ==<br />
<br />
* Circuito Completo da LT - Resumo e revisão;<br />
* Comparativo dos modelos de LT SEM perdas simples e com parâmetros Concentrados;<br />
* Transitórios - Resposta da LT ao Degrau;<br />
* Diagrama de Saltos ou Diagrama de Reflexão;<br />
* Exercício.<br />
* Entrega da lista de exercícios do livro texto.<br />
<br />
<math>\blacklozenge</math> '''Atividade Extra: Entrega INDIVIDUAL até 19/09/2019, manuscrito ou impresso.'''<br />
<br />
;Tarefa 1:<br />
<br />
Foi distribuída uma cópia da páginas 74 à 77 do livro texto (Wentworth) que contém o desenvolvimento de um código em MATLAB objetivando mostrar um comparativo entre as respostas da modelagem de um circuito completo de LT SEM perdas simples (considerando as ondas viajantes incidentes e refletidas vistas até aqui) e com parâmetros concentrados. Os circuitos são formados considerando Zo=50 ohms e RL=RS=200 ohms. Os gráficos comparativos mostram a relação entre a Magnitude do sinal na carga (VL) em relação ao tamanho da LT em termos de quantidade de comprimentos de onda. As diferenças entre os gráficos são muito relevantes. <br><br />
<br />
A tarefa agora é levantar os mesmos gráficos, porém considerando os parâmetros distribuídos de uma LT real com os mesmos valores de RS e RL. Fica assim designado os seguintes tipos de cabos por aluno:<br />
* Victor, Yan e Rafael: '''Usar os mesmos cabos comerciais da atividade extra solicitada em 29/08''';<br />
* Guilherme: Cabo comercial RG58 da DATALINK;<br />
* Alisson: Cabo UTP (análise de um par dos 4) Cat 5e da FURUKAWA.<br />
<br />
;Tarefa 2:<br />
<br />
Refaça o Exercício 1 da aula anterior considerando o mesmo circuito porém acrescentando nele a chave em paralelo com a fonte Vs como detalhado na figura 2.38 na página 107 do livro texto. Considere T=2ns para este exercício o qual determina a largura de pulso entre as ondas Vo e -Vo que irão propagar na linha. Levante o DIAGRAMA DE SALTOS, o gráfico de VL em relação ao tempo e o valor de VL depois de um tempo suficientemente grande quando não houver mais reflexões na LT.<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 17/09 - Respostas às Terminações de Sinais Digitais - TDR }}<br />
<br />
== 17/09 - Respostas às Terminações de Sinais Digitais - TDR ==<br />
<br />
* Terminações com diodos Schottky;<br />
* Cargas Reativas em transitórios;<br />
* Reflectômetro no Domínio do Tempo (TDR)<br />
* Dispersão em sinais digitais;<br />
* [[media:wentworth_cap2_parcial.pdf | slides com figuras de apoio]]<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 19/09 - Laboratório - Medições de SWR em cabos reais - Exercícios de Revisão}}<br />
<br />
== 19/09 - Laboratório - Medições de SWR em cabos reais - Exercícios de Revisão ==<br />
<br />
* Laboratório - Medições de SWR em cabos reais;<br />
* Exercícios de Revisão<br />
<br />
== Experimentos: Velocidade e comprimento da linha de transmissão e Descasamento de impedância e Onda Estacionária ==<br />
<br />
<br />
; Objetivos do experimento:<br />
<br />
- Realizar medições da tensão e do tempo de propagação em linhas descasadas.<br />
- Obter a velocidade da onda na linha conhecendo seu comprimento e o tempo de propagação do pulso.<br />
- Conhecer o método de identificação do local de ocorrência de curto ou linha aberta através da análise da reflexão no domínio do tempo.<br />
- Verificar o comportamento do pulso refletido para as situações de Zo < ZL, Zo=ZL e Zo>ZL.<br />
- Estimar a impedância de uma linha de transmissão.<br />
- Estimar o comprimento da onda numa linha de transmissão.<br />
<br />
; Material necessário:<br />
<br />
a) Cabo coaxial RG58, Zo = 50 Ohms<br />
b) Terminador de 50 Ohms.<br />
c) Par trançado.<br />
d) Balun 75-100 Ohms<br />
e) Potênciometro de 450 Ohms<br />
f) Multímetro.<br />
g) Osciloscópio.<br />
h) Conector coaxial do tipo T.<br />
i) Gerador de sinal.<br />
j) Analisador de espectro.<br />
k) Trena.<br />
<br />
; Procedimentos.<br />
<br />
=== Primeira parte ===<br />
<br />
1. Colocar o conector T na entrada do canal 1 do osciloscópio.<br />
2. Conectar o gerador de função numa das extremidades do conector T.<br />
3. Conectar o cabo coaxial na outra extremidade do conector T.<br />
4. Ajustar no gerador de sinal um pulso com largura de 20ns, período de 1ms e valor de pico de 2V.<br />
5. Com a extremidade da linha em aberto verificar o pulso refletido, anotar sua amplitude e a diferença de tempo entre o início do pulso enviado pelo gerador e o início do pulso refletido pela linha. Salvar a tela do osciloscópio.<br />
6. Com a extremidade da linha em curto verificar o pulso refletido, anotar sua amplitude e a diferença de tempo entre o início do pulso enviado pelo gerador e o início do pulso refletido pela linha. Salvar a tela do osciloscópio.<br />
7. Com a linha casada verificar o que ocorre com o o pulso refletido. Salvar a tela do osciloscópio.<br />
8. Medir o comprimento do cabo.<br />
<br />
<br />
<br />
=== Segunda parte ===<br />
<br />
1. Colocar o conector T na entrada do canal 1 do osciloscópio.<br />
2. Conectar o gerador de função numa das extremidades do conector T.<br />
3. Conectar o par trançado ao Balun e este a outra extremidada de conector T.<br />
4. Ajustar no gerador de sinal um pulso com largura de 20ns, período de 1ms e valor de pico de 2V.<br />
5. Ajustar o potênciomentro para Z= 0 W e conecta-lo a extremidade livre do par trançado.<br />
6. Anotar as amplitudes dos pulsos e a diferença de tempo entre o início do pulso enviado pelo gerador e o início do pulso refletido pela linha. Salvar a tela do osciloscópio.<br />
7. Repetir os passos 5 e 6 para os valores de resistência de 50, 100, 150 e 450 W<br />
8. Com a extremidade da linha em curto verificar o pulso refletido, anotar sua amplitude e a diferença de tempo entre o início do pulso enviado pelo gerador e o início do pulso refletido pela linha. Salvar a tela do osciloscópio.<br />
9. Com o potênciomentro conectado a linha variar a sua resistência e encontrar o valor mais próximo da impedância da linha. Desconecte o potênciometro da linha e meça o valor da resistência.<br />
10. Meça o comprimento do cabo.<br />
<br />
=== Terceira parte. ===<br />
<br />
1. Conectar o cabo coaxial com a terminação em aberto e cortes do isolante no gerador de sinal de alta frequência.<br />
2. Conectar uma ponteira de osciloscópio no analisador de espectro.<br />
3. Ajustar o sinal do gerador para uma onda senoidal de 400 mV de nível e 1GHz de frequência.<br />
4. Com a terminação do cabo em aberto medir em cada ponto de acesso do cabo o valor do nível de tensão. Anote os valores adequadamente.<br />
5. Medir com a trena a distância entre cada ponto no qual foi coletado a medida e a extremidade final do cabo.<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 23/09 - Laboratório - Medições de atenuação e defasagem de onda}}<br />
<br />
== 23/09 - Laboratório - Medições de atenuação e defasagem de onda ==<br />
<br />
<br />
== Experimentos: Roteiro distribuído em sala ==<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 26/09 - Avaliação A1}}<br />
<br />
== 26/09 - Avaliação A1 ==<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 01/10 - Carta de Smith}}<br />
<br />
== 01/10 - Carta de Smith ==<br />
<br />
* Introdução e interpretação da [[media:SmithChart.pdf |Carta de Smith]].<br />
* [[media:Smith.pdf | Slides de apoio]] (professora Evanaska)<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 03/10 - Correção Avaliação A1 }}<br />
<br />
== 03/10 - Correção Avaliação A1 ==<br />
<br />
* Correção avaliação A1<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 08/10 - Carta de Smith - Casamento de Impedâncias}}<br />
<br />
== 08/10 - Carta de Smith - Casamento de Impedâncias ==<br />
<br />
* Casamento de Impedâncias segundo carta de Smith.<br />
* [[media:Smith_casamento_misto.pdf | Slides de apoio sobre Casamento misto de Impedâncias em LTs]] (professora Evanaska)<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top | 10/10 - Recuperação Avaliação A1 }}<br />
<br />
== 10/10 - Recuperação Avaliação A1 ==<br />
<br />
* Recuperação Avaliação A1<br />
<br />
{{Collapse bottom}}<br />
<br />
{{ENGTELECO}}</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=FIC_MATLAB_2019-2/Aula-12&diff=162021FIC MATLAB 2019-2/Aula-122019-10-03T23:01:36Z<p>127.0.0.1: Criou página com '<syntaxhighlight lang=matlab class="mw-collapsible"> x = [1 2 3 4 5]; x2 = x.^2; disp(['o valor de x é ' num2str(x(1)) ' e o valor de x ao quadrado é ' num2str(x2(1))]) disp(['o valor de x é...'</p>
<hr />
<div><syntaxhighlight lang=matlab class="mw-collapsible"><br />
x = [1 2 3 4 5];<br />
x2 = x.^2;<br />
<br />
disp(['o valor de x é ' num2str(x(1)) ' e o valor de x ao quadrado é ' num2str(x2(1))])<br />
disp(['o valor de x é ' num2str(x(2)) ' e o valor de x ao quadrado é ' num2str(x2(2))])<br />
disp(['o valor de x é ' num2str(x(3)) ' e o valor de x ao quadrado é ' num2str(x2(3))])<br />
disp(['o valor de x é ' num2str(x(4)) ' e o valor de x ao quadrado é ' num2str(x2(4))])<br />
disp(['o valor de x é ' num2str(x(5)) ' e o valor de x ao quadrado é ' num2str(x2(5))])<br />
%%<br />
for i = 1:length(x)<br />
disp(['o valor de x é ' num2str(x(i)) ', o valor de x ao quadrado é ' num2str(x2(i))])<br />
end<br />
<br />
%%<br />
clear i<br />
for i = 1:4<br />
for j = 7:9<br />
disp(['primeiro valor ' num2str(i) ' segundo valor ' num2str(j)]);<br />
end<br />
end<br />
<br />
%%<br />
clear i<br />
soma = 0;<br />
vetor = zeros(1,10);<br />
<br />
for i = 1:length(vetor)<br />
soma = soma + i;<br />
vetor(i) = soma;<br />
disp(soma)<br />
end<br />
disp(vetor)<br />
<br />
<br />
%% WHILE<br />
<br />
a = 1;<br />
while a == 1<br />
<br />
a<br />
<br />
end<br />
<br />
%% QUESTAO 1<br />
saida = 1;<br />
<br />
while saida ==1<br />
<br />
operador = input('escolha sua operação (/ * + -) \n', 's');<br />
num1 = input('primeiro numero: \n');<br />
num2 = input('segundo numero: \n');<br />
<br />
if operador == '*'<br />
result = num1 * num2;<br />
disp(['O resultado é: ' num2str(result)]);<br />
elseif operador == '/'<br />
result = num1 / num2;<br />
disp(['O resultado é: ' num2str(result)]);<br />
elseif operador == '-'<br />
result = num1 - num2;<br />
disp(['O resultado é: ' num2str(result)]);<br />
elseif operador == '+'<br />
result = num1 + num2;<br />
disp(['O resultado é: ' num2str(result)]);<br />
end<br />
<br />
saida = input('Se quiser sair, digite s \n','s');<br />
if saida == 's'<br />
break<br />
else<br />
saida = 1;<br />
end<br />
<br />
end<br />
<br />
<br />
%%<br />
<br />
for b = 1 : 4;<br />
b<br />
if b > 2<br />
continue<br />
else<br />
disp('oi')<br />
end<br />
b<br />
end<br />
<br />
</syntaxhighlight></div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=Graphviz_ppC&diff=162014Graphviz ppC2019-10-03T20:39:37Z<p>127.0.0.1: Criou página com '<graphviz> digraph G { labelloc=c fontsize=30 label ="Engenharia de Telecomunicações" labelloc = t //rankdir = "LR" //packMode = "clust" //clusterM...'</p>
<hr />
<div><graphviz><br />
digraph G {<br />
<br />
labelloc=c fontsize=30<br />
label ="Engenharia de Telecomunicações"<br />
labelloc = t<br />
//rankdir = "LR"<br />
//packMode = "clust"<br />
//clusterMode = "local"<br />
fixedsize = true<br />
//splines = ortho<br />
//splines = octilinear<br />
node [width = 2, height = 1,labelloc=c fontsize=17, style=filled, shape=box, style="rounded,filled"]<br />
<br />
edge [arrowsize=0.5]<br />
<br />
<br />
<br />
// Eixo marrom - hardware<br />
STE [color="#9F8170", label ="Sistemas \nEmbarcados"]<br />
ELD1 [color="#9F8170", label = "Eletronica \nDigital 1"]<br />
ELD2 [color="#9F8170", label = "Eletronica \nDigital 2"]<br />
MIC [color="#9F8170", label = "Microprocessadores"]<br />
DLP [color="#9F8170", label = "Dispositivos \nLógicos \nProgramáveis"]<br />
<br />
ELD1 -> ELD2<br />
{ELD2, PRG2} -> MIC<br />
{MIC, SOP} -> DLP<br />
{SOP,POO,MIC} -> STE<br />
POO -> MIC [arrowsize=0.7, arrowhead=empty, style=dashed, label="co-requisito"]<br />
<br />
<br />
// Eixo verde - software<br />
POO [color="#339966"]<br />
STD [color="#339966"]<br />
SOP [color="#339966"]<br />
BCD [color="#339966"]<br />
PRG1 [color="#339966"]<br />
PRG2 [color="#339966"]<br />
LOG [color="#339966"]<br />
<br />
// Eixo verde<br />
LOG -> PRG1<br />
PRG1 -> PRG2<br />
PRG2 -> POO<br />
POO -> BCD<br />
{POO, RED1, SOP} -> STD<br />
{PRG2, MIC} -> SOP<br />
<br />
//------------------------------------------------<br />
// Cadeia de pré-requisitos<br />
//------------------------------------------------<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
subgraph cluster_Sw {<br />
label = "Eixo Sw";<br />
style=filled;<br />
color=lightgrey;<br />
labelloc=c fontsize=30<br />
node [style=filled,color=white];<br />
POO STD SOP BCD PRG1 PRG2 LOG <br />
}<br />
<br />
subgraph cluster_Hw {<br />
label = "Eixo Hw";<br />
style=filled;<br />
color=lightgrey;<br />
labelloc=c fontsize=30<br />
node [style=filled,color=white];<br />
// Eixo marrom - hardware<br />
STE ELD1 ELD2 DLP MIC<br />
}<br />
<br />
<br />
}<br />
</graphviz><br />
<br />
<graphviz><br />
digraph G {<br />
<br />
label ="Engenharia de Telecomunicações"<br />
labelloc = t<br />
<br />
node [labelloc=c fontsize=10, style=filled, shape=box, style="rounded,filled"]<br />
<br />
edge [arrowsize=.5]<br />
<br />
// eixo laranja<br />
PCA [color="#FFA343"]<br />
CAL1 [color="#FFA343"]<br />
CAL2 [color="#FFA343"]<br />
CAL3 [color="#FFA343"]<br />
CAL4 [color="#FFA343"]<br />
CALN [color="#FFA343"]<br />
<br />
FSC1 [color="#FFA343"]<br />
FSC2 [color="#FFA343"]<br />
FSC3 [color="#FFA343"]<br />
ALG [color="#FFA343"]<br />
GAL [color="#FFA343"]<br />
<br />
DES [color="#FFA343"]<br />
QMC1 [color="#FFA343"]<br />
QMC2 [color="#FFA343"]<br />
MEC [color="#FFA343"]<br />
MPQ [color="#FFA343"]<br />
EST [color="#FFA343"]<br />
FEN [color="#FFA343"]<br />
PTG [color="#FFA343"]<br />
ADM [color="#FFA343"]<br />
ECO [color="#FFA343"]<br />
SUS [color="#FFA343"]<br />
<br />
// Eixo amarelo<br />
ELI [color="#FFD700"]<br />
CIE1 [color="#FFD700"]<br />
CIE2 [color="#FFD700"]<br />
ELA1 [color="#FFD700"]<br />
ELA2 [color="#FFD700"]<br />
<br />
<br />
// Eixo cinza<br />
PJI1 [color="#808080"]<br />
PJI2 [color="#808080"]<br />
PJI3 [color="#808080"]<br />
TCC1 [color="#808080"]<br />
TCC2 [color="#808080"]<br />
ETO [color="#808080"]<br />
<br />
// Eixo azul<br />
SIS1 [color="#007FFF"]<br />
SIS2 [color="#007FFF"]<br />
PSD [color="#007FFF"]<br />
COM1 [color="#007FFF"]<br />
COM2 [color="#007FFF"]<br />
PRE [color="#007FFF"]<br />
<br />
<br />
<br />
// Eixo marrom - hardware<br />
STE [color="#9F8170"]<br />
CIL [color="#9F8170"]<br />
DLP1 [color="#9F8170"]<br />
DLP2 [color="#9F8170"]<br />
MIC [color="#9F8170"]<br />
<br />
// Eixo roxo<br />
RTX [color="#9678B6"]<br />
ANT [color="#9678B6"]<br />
CSF [color="#9678B6"]<br />
MTG [color="#9678B6"]<br />
STC [color="#9678B6"]<br />
CRF [color="#9678B6"]<br />
<br />
<br />
<br />
// Eixo verde - software<br />
POO [color="#339966"]<br />
STD [color="#339966"]<br />
SOP [color="#339966"]<br />
BCD [color="#339966"]<br />
PRG1 [color="#339966"]<br />
PRG2 [color="#339966"]<br />
LOG [color="#339966"]<br />
<br />
// Eixo verde claro<br />
RED1 [color="#77DD77"]<br />
RED2 [color="#77DD77"]<br />
PTC [color="#77DD77"]<br />
ADS [color="#77DD77"]<br />
<br />
<br />
<br />
//------------------------------------------------<br />
// Cadeia de pré-requisitos<br />
//------------------------------------------------<br />
<br />
// eixo laranja<br />
CAL3 -> CAL4<br />
CAL1 -> FSC1<br />
FSC1 -> FSC2<br />
FSC1 -> FSC3<br />
ALG -> CALN<br />
GAL -> CAL3<br />
<br />
// eixo amarelo<br />
CIE2 -> CIE1<br />
ELA2 -> ELA1<br />
ELI -> CIE1<br />
<br />
// eixo cinza<br />
PJI1 -> PJI2<br />
PJI2 -> PJI3<br />
TCC2 -> TCC1<br />
<br />
<br />
// Eixo verde<br />
LOG -> PRG1<br />
PRG1 -> PRG2<br />
PRG2 -> POO<br />
POO -> BCD<br />
{POO, RED1, SOP} -> STD<br />
<br />
<br />
// Eixo verde claro<br />
RED1 -> RED2<br />
PTC -> ADS<br />
<br />
// eixo azul<br />
EST -> PRE<br />
SIS2 -> SIS1<br />
{DLP2, SIS2} -> PSD<br />
{SIS2, PRE} -> COM1<br />
COM1 -> COM2<br />
<br />
<br />
<br />
subgraph cluster_fase1 {<br />
label = "fase 1";<br />
style=filled;<br />
color=lightgrey;<br />
node [style=filled,color=white];<br />
<br />
LOG<br />
<br />
PCA<br />
<br />
<br />
}<br />
<br />
subgraph cluster_fase2 {<br />
label = "fase 2";<br />
style=filled;<br />
color=lightgrey;<br />
node [style=filled,color=white];<br />
<br />
PRG1<br />
<br />
CAL1<br />
<br />
}<br />
<br />
subgraph cluster_fase3 {<br />
label = "fase 3";<br />
style=filled;<br />
color=lightgrey;<br />
node [style=filled,color=white];<br />
<br />
CAL2<br />
<br />
PRG2<br />
}<br />
<br />
subgraph cluster_fase4 {<br />
label = "fase 4";<br />
style=filled;<br />
color=lightgrey;<br />
node [style=filled,color=white];<br />
<br />
CAL3<br />
<br />
POO<br />
<br />
}<br />
<br />
subgraph cluster_fase5 {<br />
label = "fase 5";<br />
style=filled;<br />
color=lightgrey;<br />
node [style=filled,color=white];<br />
<br />
CAL4<br />
CALN<br />
<br />
<br />
}<br />
<br />
subgraph cluster_fase6 {<br />
label = "fase 6";<br />
style=filled;<br />
color=lightgrey;<br />
node [style=filled,color=white];<br />
<br />
STD<br />
<br />
}<br />
<br />
subgraph cluster_fase7 {<br />
label = "fase 7";<br />
style=filled;<br />
color=lightgrey;<br />
node [style=filled,color=white];<br />
<br />
COM1<br />
<br />
}<br />
<br />
subgraph cluster_fase8 {<br />
label = "fase 8";<br />
style=filled;<br />
color=lightgrey;<br />
node [style=filled,color=white];<br />
<br />
COM2<br />
<br />
}<br />
<br />
subgraph cluster_fase9 {<br />
label = "fase 9";<br />
style=filled;<br />
color=lightgrey;<br />
node [style=filled,color=white];<br />
<br />
TCC1<br />
<br />
}<br />
<br />
<br />
subgraph cluster_fase10 {<br />
label = "fase 10";<br />
style=filled;<br />
color=lightgrey;<br />
node [style=filled,color=white];<br />
<br />
TCC2<br />
<br />
}<br />
<br />
<br />
<br />
}<br />
</graphviz></div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)&diff=162012Curso Técnico Integrado de Telecomunicações - Redes de Computadores (RCO)2019-10-03T20:01:14Z<p>127.0.0.1: /* Introdução */</p>
<hr />
<div>__NOTOC__<br />
<br />
{{DivulgueEngtelecom}}<br />
==Informações Gerais==<br />
*[[RCO-IntTel|Carga horária, Ementas, Bibliografia]]<br />
*[[RCO-IntTel (Plano de Ensino) | Plano de Ensino]]<br />
*[[Cronograma de atividades (RCO-IntTel) | Cronograma de atividades]]<br />
<br />
==Edições==<br />
*[[RCO60803 2019-1|RCO60803 2019-1 - Trabalho dirigido - Prof. Odilson Tadeu Valle]]<br />
*[[RCO60803 2018-2|RCO60803 2018-2 - Prof. Odilson Tadeu Valle / Prof. Eraldo Silveira e Silva]]<br />
*[[RCO60803 2018-1|RCO60803 2018-1 - Prof. Odilson Tadeu Valle / Prof. Eraldo Silveira e Silva]]<br />
*[[RCO60803 2017-2|RCO60803 2017-2 - Prof. Odilson Tadeu Valle / Prof. Eraldo Silveira e Silva]]<br />
*[[RCO60803 2017-1|RCO60803 2017-1 - Prof. Juliano de Souza / Prof. Eraldo Silveira e Silva]]<br />
*[[RCO60803 2016-2|RCO60803 2016-2 - Prof. Juliano de Souza / Prof. Luciano Barreto]]<br />
*[[RCO60803 2016-1|RCO60803 2016-1 - Prof. Fernando Rodrigues Santos / Prof. Juliano de Souza]]<br />
*[[RCO60803-2015-2|RCO60803 2015-2 - Prof. Simara Sonaglio]]<br />
*[[RCO60803-2015-1|RCO60803 2015-1 - Prof. Arliones Hoeller / Prof. Túlio Ribeiro]]<br />
*[[RCO60803-2014-2|RCO60803 2014-2 - Prof. Arliones Hoeller / Prof. Tomás Grimm / Prof. José Clair]]<br />
<br />
= Material de apoio =<br />
<br />
==''Applets'' do Kurose==<br />
Vários [http://wps.pearsoned.com/ecs_kurose_compnetw_6/216/55463/14198700.cw/ aplicativos] com representação dinâmica de características das redes de computadores.<br />
==Transparências utilizadas durante as aulas==<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/slides-kurose-cap1.pdf Capítulo 1 - Introdução]<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/slides-kurose-cap2.pdf Capítulo 2 - Camada de Aplicação]<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/PPTs%20-%20Cap%C3%ADtulo%202%20-%20FTP%20-%20Email%20-%20P2P.pdf Capítulo 2 - Camada de Aplicação - FTP + EMAIL + P2P]<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/slides-kurose-cap3.pdf Capítulo 3 - Camada de Transporte]<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/PPTs%20-%20Cap%C3%ADtulo%204%20A%20camada%20de%20REDE.pdf Capítulo 4 - Camada de Rede]<br />
<br />
==Slides de Outras Universidades==<br />
<br />
*[https://www.google.com.br/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0ahUKEwiO0aDJu_LTAhWJlZAKHX8JA2wQFggjMAA&url=http%3A%2F%2Fwww.eecs.yorku.ca%2Fcourse_archive%2F2015-16%2FW%2F3214%2FCSE3214_14_TCP_2_2016_posted_part2.pdf&usg=AFQjCNEJh3yITWuyOPZ17bbObT54JqrLCw&sig2=jJwHLo13iooIUaI5F2m-kA TCP Error Control- EECS - LASSONDE]<br />
*[https://www.google.com.br/url?sa=t&rct=j&q=&esrc=s&source=web&cd=2&cad=rja&uact=8&ved=0ahUKEwiO0aDJu_LTAhWJlZAKHX8JA2wQFggpMAE&url=http%3A%2F%2Fwww.eecs.yorku.ca%2Fcourse_archive%2F2015-16%2FW%2F3214%2FCSE3214_14_TCP_2_2016_posted_part1.pdf&usg=AFQjCNHNz8hZ4GHyiDZkcMgomCQBR4KTaA&sig2=nS8450rR2x6C_EM9tT0yWw TCP- Flow and Error Control - LASSONDE]<br />
*[https://www.google.com.br/url?sa=t&rct=j&q=&esrc=s&source=web&cd=3&ved=0ahUKEwjUvtPAmJjUAhXHHZAKHfSBAEgQFghCMAI&url=http%3A%2F%2Fwww.eecs.yorku.ca%2Fcourse_archive%2F2015-16%2FW%2F3214%2FCSE3214_14_TCP_3_2016_posted.pdf&usg=AFQjCNHFkmBZT2Pn_G6e-AuDvJHL6FuZzg&sig2=UxXTDU_OKoMp2jC3K1O-jg Congestion Control - LASSONDE]<br />
*[https://www.cpe.ku.ac.th/~cpj/204325/ Slides/Aula Faculty of Engineering, Kasetsart University]<br />
<br />
== Curiosidades ==<br />
<br />
* [http://www.pop-sc.rnp.br/publico/monitoramento.php Monitoramento do tráfego RNP - PoP-SC]<br />
* [http://memoria.rnp.br/ceo/trafego/panorama.php Monitoramento do tráfego RNP - Nacional]<br />
* [http://www.redclara.net/index.php/pt/red/redclara/topologia-actual-de-la-red Rede Clara Internacional]<br />
* [https://eventos.rnp.br/sites/default/files/activity/activity-presentation/apresentacao_wrnp_2017_eduardo_grizenid_v_1.2.pdf Futura infraestrutura de rede da RNP]<br />
* [https://www.youtube.com/watch?v=IlAJJI-qG2k Animated map shows the undersea cables that power the internet]<br />
* [http://submarine-cable-map-2018.telegeography.com/ Submarine Cable Map 2018]<br />
* [https://www.youtube.com/watch?v=A5dD2x2iQx8 ''History of the Internet'' - legendado]<br />
* [https://www.youtube.com/watch?v=O_xG0ay5Vqs ''Warriors of the Net'' - legendado]<br />
* [https://www.youtube.com/watch?v=1G3SUTmioQE ''Browser Wars'' - legendado]<br />
* [https://www.youtube.com/watch?v=0nz-lcuv3TM ''Browser Wars'' - dublado]<br />
* [https://db-ip.com/200.135.37.65 Localização geográfica de IPs]<br />
* [http://ipv6.br/ '''IPv6 no Brasil''']<br />
* [http://ipv6.br/lab/ Laboratório de IPv6 - Livro didático contendo vários roteiros para entendimento do IPv6]<br />
* [https://www.google.com/intl/pt-BR/ipv6/statistics.html#tab=per-country-ipv6-adoption&tab=per-country-ipv6-adoption Estatísticas Google sobre IPv6]<br />
<br />
=Laboratórios=<br />
<br />
<br />
{{Collapse top |Laboratório 1 - Ferramentas de Rede e Conceitos Básicos}}<br />
<br />
===Objetivos===<br />
<br />
*Familiarização com a infraestrutura dos laboratórios de redes<br />
*Familiarização com ferramentas de rede: ifconfig, ping, traceroute;<br />
*Desenvolver a noção de endereçamentos de rede IP e de endereço de hardware (MAC)<br />
*Desenvolver a noção de rotas em redes IP<br />
*Testar a conectividade IP com ping<br />
<br />
===Conceitos introdutórios para uso do laboratório===<br />
<br />
<br />
====Estrutura do Laboratório====<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/Ferramentas%20de%20rede%20e%20conceitos%20basicos.pdf Conceitos Básicos]<br />
<br />
[http://tele.sj.ifsc.edu.br/~eraldo/AULAS/2018-2/RCO-INTEGRADO/MACxIP.pdf Endereçamento MAC x Endereçamento IP]<br />
<br />
A rede do laboratório em uso segue o modelo apresentado no diagrama da Figura 1 (endereçamento pode ser diferente).<br />
<br />
[[Arquivo:Diagrama_rede_IFSC_lab_redes_I.jpeg |thumb | 400px| Figura 1 - Diagrama da rede do laboratório]]<br />
<br />
Os Laboratórios de Redes de Computadores estão equipados com N+1 (N = número de computadores para alunos) computadores conectados em rede e com acesso a Internet. A rede local do laboratório tem endereço IP 192.168.1.0/24. A máscara de rede '''/24''' indica que o último ''byte'' do endereço é utilizado para identificar cada máquina, por exemplo 192.168.1.1, 192.168.1.2, etc.<br />
<br />
===Roteiro de atividades===<br />
====Parte 1: Observando interfaces do sistema com ifconfig====<br />
O aplicativo '''ifconfig''' pode ser utilizado para visualizar a configuração ou configurar uma interface de host em redes TCP/IP. Se nenhum argumento for passado na chamada do '''ifconfig''', o comando mostra a configuração atual de cada interface de rede.<br />
<br />
NOTA: o ifconfig está sendo substituído pelo comando ip. A última versão do Uuntu já não traz mais o ifconfig por default.<br />
<br />
Consultar as páginas ''man ifconfig'' do Linux para maiores detalhes sobre o funcionamento deste aplicativo, o qual permite ativar/desativar a interface, configurar o endereço IP, definir o tamanho da MTU, redefinir o endereço de hardware se a interface suporta, redefinir a interrupção utilizada pelo dispositivo, entre outros.<br />
<br />
<br />
#Analisando os dados obtidos do seguinte exemplo <syntaxhighlight lang=bash>ifconfig <br />
eth0 Link encap:Ethernet Endereço de HW 64:51:06:1a:f3:da <br />
inet end.: 172.18.18.14 Bcast:172.18.63.255 Masc:255.255.192.0<br />
endereço inet6: fe80::6651:6ff:fe1a:f3da/64 Escopo:Link<br />
UP BROADCAST RUNNING MULTICAST MTU:1500 Métrica:1<br />
pacotes RX:415237 erros:0 descartados:0 excesso:0 quadro:0<br />
Pacotes TX:118109 erros:0 descartados:0 excesso:0 portadora:0<br />
colisões:0 txqueuelen:1000 <br />
RX bytes:364658695 (364.6 MB) TX bytes:18315199 (18.3 MB)<br />
IRQ:18 <br />
<br />
lo Link encap:Loopback Local <br />
inet end.: 127.0.0.1 Masc:255.0.0.0<br />
endereço inet6: ::1/128 Escopo:Máquina<br />
UP LOOPBACK RUNNING MTU:65536 Métrica:1<br />
pacotes RX:6688 erros:0 descartados:0 excesso:0 quadro:0<br />
Pacotes TX:6688 erros:0 descartados:0 excesso:0 portadora:0<br />
colisões:0 txqueuelen:0 <br />
RX bytes:1057934 (1.0 MB) TX bytes:1057934 (1.0 MB) </syntaxhighlight><br />
##O sistema em questão possui duas interfaces de rede: '''eth0''' e '''lo'''<br />
##'''Link encap:Ethernet''': Configuração da interface '''Eth'''ernet 0 (primeira)<br />
##'''Endereço de HW 64:51:06:1a:f3:da''': É o endereço da placa de rede, camada 2<br />
##'''inet end.: 172.18.18.14 Bcast:172.18.63.255 Masc:255.255.192.0''': Endereço IPv4 associado a interface, seu respectivo endereço de ''broadcast'' e mascara de rede<br />
##endereço inet6: fe80::6651:6ff:fe1a:f3da/64 Escopo:Link: Endereço IPv6 de escopo local gerado por autoconfiguração<br />
##'''UP BROADCAST RUNNING MULTICAST''': Significa que a interface está ativa (UP), responde a requisições de broadcast (pode ser desabilitado no kernel) e também pode ser associada a tráfegos ''multicast''<br />
##'''MTU: 1500''': ''Maximum Transfer Unit'' – Tamanho máximo do pacote suportado pelo enlace que é do tipo Ethernet<br />
##Os demais parâmetros são estatísticas da respectiva interface, como por exemplo, pacotes transmitidos, recebidos etc<br />
##A interface '''lo''': Qualquer tráfego que um computador envie em uma rede ''loopback'' é endereçada ao mesmo computador. O endereço IP mais usado para tal finalidade é 127.0.0.1 no IPv4 e ::1 no IPv6. O nome de domínio padrão para tal endereço é ''localhost''. Em sistemas Unix, a interface loopback é geralmente chamada de lo ou lo0.<br />
#Agora utilize o comando '''ifconfig''' para verificar o estado de suas interfaces e responda:<br />
##Quantas e quais interfaces de rede sua máquina possui? Liste.<br />
##Quais são os endereços da camada 2 atribuído as mesmas? De onde o sistema obteve esses endereços?<br />
##Quais são os endereços IPv4? De onde o sistema obteve esses endereços?<br />
##Suas interfaces tem IPv6 configurado? Qual o endereço e escopo dos mesmos? Como foram obtidos? Qual o alcance (é roteável) do mesmo?<br />
##Use o link *[http://jodies.de/ipcalc Verificando a estrutura do endereço IP] para explorar a estrutura do seu endereço IPv4.<br />
<br />
====Parte 2: Testando a conectividade com o ping====<br />
<br />
Aplicativo '''ping''' permite a um usuário verificar se um ''host'' remoto está ativo. É bastante utilizado para detectar problemas de comunicação na rede.<br />
O '''ping''' está baseado no envio de mensagens de solicitação de eco (''echo request'') e de resposta de eco (''echo reply''). Estas mensagens fazem parte do rol de mensagens do protocolo ICMP, que é um protocolo de reportagem de erros, a ser estudado mais tarde, componente do protocolo IP.<br />
<br />
O '''ping''' é um dos principais comandos a disposição do administrador de rede no sentido de verificar a conectividade em rede. Por exemplo, se houver resposta de um ping a partir de um servidor remoto, significa que a máquina local está rodando corretamente o TCP/IP, o enlace local está funcionando corretamente, o roteamento entre a origem e o destino está operando, e por fim, a máquina remota também está rodando corretamente o TCP/IP.<br />
<br />
Consultar as páginas ''man'' do ping para verificar as possibilidades de uso deste aplicativo.<br />
<br />
#Exemplo 1: <syntaxhighlight lang=bash><br />
ping 191.36.0.94<br />
PING 191.36.0.94 (191.36.0.94) 56(84) bytes of data.<br />
64 bytes from 191.36.0.94: icmp_seq=1 ttl=60 time=2.46 ms<br />
64 bytes from 191.36.0.94: icmp_seq=2 ttl=60 time=0.513 ms<br />
64 bytes from 191.36.0.94: icmp_seq=3 ttl=60 time=0.573 ms<br />
64 bytes from 191.36.0.94: icmp_seq=4 ttl=60 time=0.558 ms<br />
^C<br />
--- 191.36.0.94 ping statistics ---<br />
4 packets transmitted, 4 received, 0% packet loss, time 3001ms<br />
rtt min/avg/max/mdev = 0.513/1.026/2.463/0.830 ms </syntaxhighlight><br />
<br />
##No exemplo foram enviados quatro pacotes ICMP, cada um com um número de seqüência (''icmp_seq''), os quais foram recebidos com sucesso com o tempo de viagem assinalado (''time'')<br />
##Cada pacote tem ainda um tempo de vida (''ttl'' – ''time to live''), o qual é decrementado em cada roteador, sendo o pacote descartado quando chegar a zero; isto evita pacotes perdidos na rede<br />
##Quando o ping é interrompido ('''CRTL-C'''), uma estatística é apresentada indicando o percentual de pacotes transmitidos, recebidos e perdidos<br />
##O tempo de viagem (''rtt'' – ''round trip time'') mínimo (''min''), médio (''avg'') e máximo (''max'') é calculado, assim como o desvio padrão (''mdev'')<br />
#Como exercício envie '''ping''' para diferentes ''hosts'' e compare os tempos de resposta:<br />
##no endereço local de loopback;<br />
##máquina de um colega do laboratório;<br />
##servidor e roteador da rede da escola;<br />
##servidores externos: <syntaxhighlight lang=bash><br />
www.ifsc.edu.br<br />
www.uol.com.br<br />
www.nasa.com </syntaxhighlight> e explique as possíveis diferenças entre os tempos de resposta dos ping realizados.<br />
#Consulte as páginas ''man'' e teste o '''ping''' com os parâmetros abaixo e descreva suas funcionalidades:<br />
##-c count<br />
##-i intervalo<br />
##-s packetsize<br />
##-t ttl (para um site distante inicie com 1 e vá incrementando, observe as mensagens)<br />
#Observe que também é possível realizar ping em endereços no formato IPv6, por exemplo: <syntaxhighlight lang=bash> ping6 www.sj.ifsc.edu.br </syntaxhighlight><br />
#Tente o ping6 para outros sites.<br />
<br />
====Parte 3: Verificando rotas com o traceroute====<br />
O '''traceroute''' é capaz de traçar uma rota aproximada entre dois ''hosts''. Este comando usa mensagens ICMP. Para determinar o nome e o endereço dos roteadores entre a fonte e o destino, o traceroute na fonte envia uma série de datagramas IP ordinários ao destino. O primeiro datagrama tem o TTL (''time to live'' – tempo de vida) igual a 1, o segundo 2, o terceiro 3, e assim por diante, e inicia temporizadores para cada datagrama. Quando o enésimo datagrama chega ao enésimo roteador, este verifica que o tempo de sobrevida do datagrama acaba de terminar. Pelas regras do IP, o datagrama é então descartado e uma mensagem ICMP de advertência tempo de vida excedido é enviada a fonte com o nome do roteador e seu endereço IP. Quando a resposta chega de volta a fonte, a mesma calcula o tempo de viagem em função dos temporizadores.<br />
<br />
O '''traceroute''' envia datagramas IP encapsulados em segmentos UDP a um host destino. Todavia escolhe um número de porta destino com um valor desconhecido (maior que 30000), tornando improvável que o host destino esteja usando esta porta. Quando o datagrama chega ao destino uma mensagem ICMP porta inalcançável é gerada e enviada a origem. O programa traceroute precisa saber diferenciar as mensagens ICMP recebidas – tempo excedido e porta inalcançável – para saber quando a rota foi concluída.<br />
<br />
#Exemplo: <syntaxhighlight lang=bash><br />
sudo traceroute -I 200.135.37.65<br />
traceroute to 200.135.37.65 (200.135.37.65), 30 hops max, 60 byte packets<br />
1 192.168.1.1 (192.168.1.1) 0.225 ms 0.216 ms 0.368 ms<br />
2 172.18.0.254 (172.18.0.254) 1.236 ms 1.235 ms 1.343 ms<br />
3 hendrix.sj.ifsc.edu.br (200.135.37.65) 1.331 ms 1.313 ms 1.414 ms </syntaxhighlight><br />
O exemplo mostra a rota dos pacotes entre um computador do Lab. Redes (192.168.1.1) e o servidor ''hendrix'' (200.135.37.65). Observe que para cada roteador são realizados três amostras de tempo de ida e volta. Veja pelo mapa da rede do Campus São José que entre estes dois computadores, sistemas finais, existem dois roteadores intermediários, máquina do professor e Switch camada 3 (VLANs).<br />
#Traçar a rota dos pacotes entre seu computador e diferentes hosts:<br />
##máquina de um colega do laboratório<br />
##servidor e roteador da rede da escola<br />
##servidores externos.<br />
#Explique as possíveis diferenças entre os tempos de resposta de cada uma das amostras do '''traceroute'''<br />
#Explique as linhas com o caracter *.<br />
#Fazendo uso das ferramentas desse laboratório, refaça o diagrama da rede do campus apontando claramente os novos endereços IPs associados aos roteadores.<br />
#Observe que também é possível realizar traceroute em endereços no formato IPv6, por exemplo: <syntaxhighlight lang=bash> sudo traceroute -I6 ipv6.br </syntaxhighlight><br />
#Tente o traceroute no IPv6 para outros sites.<br />
<br />
====Referências adcionais====<br />
<br />
* [http://linux-ip.net/html Guia de Administração da Camada IP no Linux<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 2 - Wireshark e encapsulamento}}<br />
<br />
===Objetivos===<br />
<br />
*Familiarização com o ''sniffer'' de rede WireShark<br />
*Observar o comportamento do ''ping'' e se familiarizar com o processo de encapsulamento;<br />
<br />
====WireShark====<br />
2005 KUROSE, J.F & ROSS, K. W. Todos os direitos reservados <br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/Wireshark%20e%20encapsulamento.pdf Wireshark e encapsulamento]<br />
*Introdução<br />
O entendimento de protocolos de redes pode ser bastante aprofundado através da “observação de protocolos funcionando” e “da manipulação de protocolos” - observando a sequência de mensagens trocadas entre duas entidades, entrando nos detalhes da operação do protocolo, e fazendo com que os protocolos realizem certas ações e então observando estas ações e as consequências. <br />
<br />
A ferramenta básica para observar as mensagens trocadas entre as entidades em execução é chamada de ''sniffer''. Como o nome sugere, um ''sniffer'' captura mensagens sendo enviadas/recebidas pelo seu computador; ele também tipicamente armazena e/ou apresenta os conteúdos dos vários campos dos protocolos nestas mensagens capturadas. Um ''sniffer'' isoladamente é um elemento passivo. Ele observa as mensagens sendo enviadas e recebidas pelas aplicações e protocolos executando no seu computador, mas jamais envia pacotes. Similarmente, os pacotes recebidos nunca são explicitamente endereçados ao ''sniffer''. Ao invés disso, um ''sniffer'' recebe uma cópia de pacotes que são enviados/recebidos para/de aplicações e protocolos executando no seu computador. <br />
<br />
A Figura 2 mostra a estrutura de um ''sniffer''. À direita da Figura 2 estão os protocolos (neste caso, protocolos da Internet) e aplicações (tais como navegador web ou cliente FTP) que normalmente executam no seu computador. O ''sniffer'', exibido dentro do retângulo tracejado na Figura 2 é uma adição aos softwares usuais no seu computador, e consiste de duas partes: a biblioteca de captura de pacotes e o analisador de pacotes. A biblioteca de captura de pacotes recebe uma cópia de cada quadro da camada de enlace que é enviado do ou recebido pelo seu computador. Lembre que mensagens trocadas por protocolos das camadas mais altas tais como HTTP, FTP, TCP, UDP, DNS ou IP, são todos eventualmente encapsulados em quadros que são transmitidos para o meio físico como um cabo Ethernet. Na Figura 2, assume-se que o meio físico é uma Ethernet, e desta forma, os protocolos das camadas superiores são eventualmente encapsulados em um quadro Ethernet. Capturar todos os quadros fornece todas as mensagens enviadas/recebidas de/por todos os protocolos e aplicações executando em seu computador.<br />
<br />
[[Arquivo:Sniffer_estrutura.png |thumb | 500px| Figura 2 - Estrutura de um ''sniffer'']]<br />
<br />
O analisador de pacotes exibe os conteúdos de todos os campos dentro de uma mensagem de protocolo. Para que isso seja feito, o analisador de pacotes deve “entender” a estrutura de todas as mensagens trocadas pelos protocolos. Por exemplo, suponha que estamos interessados em mostrar os vários campos nas mensagens trocadas pelo protocolo HTTP na Figura 5. O analisador de pacotes entende o formato dos quadros Ethernet, e desta forma pode identificar o datagrama IP dentro de um quadro. Ele também entende o formato do datagrama IP, para que ele possa extrair o segmento TCP dentro do datagrama IP. Ele entende a estrutura do segmento TCP, para que possa extrair a mensagem HTTP contida no segmento. Finalmente, ele entende o protocolo HTTP e então, por exemplo, sabe que os primeiros bytes de uma mensagem HTTP contém a cadeia “GET”, “POST” ou “HEAD”. Nós utilizaremos o ''sniffer'' Wireshark (http://www.wireshark.org) para estes laboratórios, o que nos permite exibir os conteúdos das mensagens sendo enviadas/recebidas de/por protocolos em diferentes camadas da pilha de protocolos. Tecnicamente falando, Wireshark é um analisador de pacotes que pode ser executado em computadores com Windows, Linux/UNIX e MAC.<br />
<br />
É um analisador de pacotes ideal para nossos laboratórios, pois é estável, tem uma grande base de usuários e é bem documentado incluindo um guia de usuário (http://www.wireshark.org/docs/wsug_html/), páginas de manual (http://www.wireshark.org/docs/man-pages/), e uma seção de FAQ detalhada (http://www.wireshark.org/faq.html), funcionalidade rica que inclui a capacidade de analisar mais que 500 protocolos, e uma interface com o usuário bem projetada. Ele funciona em computadores ligados a uma Ethernet para conectar-se à Internet, bem como protocolos ponto a ponto, tal como PPP.<br />
<br />
*Analisando os campos da interface do Wireshark <br />
Quando você executar o programa Wireshark, a interface com o usuário exibida na Figura 3 aparecerá. Inicialmente, nenhum dado será apresentado nas janelas. A interface do Wireshark tem seis componentes principais: <br />
#Os menus de comandos são localizados no topo da janela. Por enquanto, interessam apenas os menus ''File'' e ''Capture''. O menu ''File'' permite salvar dados de capturas de pacotes ou abrir um arquivo contendo dados de capturas de pacotes previamente realizadas, e sair da aplicação. O menu ''Capture'' permite iniciar uma captura de pacotes; <br />
#A barra de ferramentas contém os comandos de menu que são mais frequentemente utilizados. Há atalhos para abrir ou salvar dados de captura de pacotes e para iniciar ou parar uma captura de pacotes; <br />
#Abaixo da barra de ferramentas, está o campo de filtragem de pacotes exibidos. Nele podem ser digitados nome de protocolo ou outra informação apresentada na janela de listagem de pacotes. Apenas os pacotes que correspondem ao filtro são exibidos; <br />
#A janela de listagem de pacotes apresenta um resumo de uma linha para cada pacote capturado, incluindo o número do pacote (atribuído pelo Wireshark; este não é o número do pacote contido no cabeçalho de qualquer protocolo), o tempo que o pacote foi capturado, os endereços fonte e destino do pacote, o tipo de protocolo, e informação específica do protocolo contida no pacote. A lista de pacotes pode ser ordenada conforme qualquer uma destas categorias clicando no nome de uma coluna correspondente. O campo tipo do protocolo lista o protocolo de mais alto nível que enviou ou recebeu este pacote, i.e., o protocolo que é a fonte ou o último sorvedouro para este pacote; <br />
#A janela de detalhes de cabeçalho de pacotes fornece detalhes sobre o pacote selecionado na janela de listagem de pacotes. Para selecionar um pacote, basta clicar sobre ele com o botão esquerdo do mouse na janela de listagem de pacotes. Os detalhes apresentados incluem informações sobre o quadro Ethernet e o datagrama IP que contém o pacote. A quantidade de detalhes exibida pode ser expandida ou contraída. Se o pacote foi carregado sobre TCP ou UDP, detalhes correspondentes também são apresentados, os quais também podem ser contraídos ou expandidos. Finalmente, detalhes sobre o protocolo de mais alto nível que enviou ou recebeu este pacote também são apresentados; <br />
#A janela de conteúdo de pacotes mostra o conteúdo inteiro do quadro capturado, nos formatos ASCII e hexadecimal.<br />
<br />
[[Arquivo:Wireshark_interface_usuario.png | 700px| Figura 3 - Interface com o usuário do Wireshark]]<br />
<br />
====Roteiro de atividades====<br />
<br />
=====Etapa 1===== <br />
#Inicie o navegador web; <br />
#Inicie o Wireshark. Inicialmente as janelas estarão vazias, pois não há captura de pacotes em progresso; <br />
#Para iniciar uma captura de pacotes, selecione o menu Capture e depois Interfaces. Provavelmente sua interface de rede será a '''eth0'''. <br />
#Isso faz com que a janela de interfaces de rede disponíveis seja apresentada (Figura 4); [[Arquivo:Wireshark_interfaces_rede.png |thumb | 400px| Figura 4 - Interfaces de rede no Wireshark]]<br />
#O botão ''Start'' da interface '''eth0''' deve ser selecionado. Na Figura 4, no Wireshark foi selecionada a interface wlan; <br />
#Como nada está acontecendo na rede, a janela apresenta o conteúdo vazio;<br />
#Execute um comando ping (endereço na saída da nossa rede - ver aula anterior):<syntaxhighlight lang=bash><br />
ping 200.237.201.153</syntaxhighlight><br />
#Ao voltar para a janela do Wireshark, houve a captura de todos os pacotes envolvidos no process;<br />
#Antes de continuar, vamos parar a captura de pacotes e trabalhar com o que temos. Basta clicar em ''Capture'' e depois em ''Stop''; <br />
#Para testar as capacidades de filtragem, vamos inserir a cadeia “icmp” (sem as aspas e em minúsculo) no especificação do filtro de exibição e depois selecionar ''Apply'' (ou Aplicar). Observe que somente os pacotes envolvidos no ping estão sendo mostrados. Os resultados obtidos devem ser similar a tela mostrada na Figura 5. <br />
#Selecione a primeira mensagem ECHO REQUEST: as informações dos cabeçalhos do quadro Ethernet, do datagrama IP, do pacote ICMP aparecem na janela de cabeçalhos de pacotes. É possível ver os detalhes, expandido ou comprimindo os itens com um clique na seta ao lado deles.<br />
#Selecione uma mensagem ECHO REPLY. Analise o pacote: endereço fonte, endereço destino etc;<br />
#Saia do Wireshark.<br />
<br />
[[Arquivo:TelaWiresharkPing.png | 700px| Figura 5 - Tela Wireshark - Ping]]<br />
<br />
=====Etapa 2=====<br />
<br />
#Com Wireshark ativo (Abra-o novamente) faça um pingue para um site conhecido (você pode usar o nome: www.ifsc.edu.br por exemplo):<br />
#Teste outros filtros, por exemplo, mostre somente pacotes originados e/ou destinados a um determinado ''host'' ('''ip.addr == 192.168...''', ip.src, ip.dst).<br />
#Qual é o endereço IP do sítio navegado? Qual é o endereço IP da interface de rede do seu computador? Qual o endereço MAC de sua máquina?<br />
<br />
<br />
=====Etapa 3 - Desafios=====<br />
<br />
#Solicite um endereço IP de um colega e faça um experimento para descobrir o endereço MAC do computador dele.<br />
#Tente elaborar um experimento para descobrir o endereço MAC do servidor de www.ifsc.edu.br. É possível? Explique para o professor...<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 3 - Conceituando protocolos}}<br />
<br />
===Objetivos===<br />
<br />
*Desenvolver o conceito de protocolo<br />
*Conceber um protocolo/serviço de calculadora pela rede<br />
<br />
===Introdução===<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/Conceituando%20protocolos.pdf Conceituando protocolos]<br />
<br />
O entendimento de protocolos de redes pode ser bastante aprofundado através da “observação de protocolos funcionando” e “da manipulação de protocolos” - observando a sequência de mensagens trocadas entre duas entidades, entrando nos detalhes da operação do protocolo, e fazendo com que os protocolos realizem certas ações e então observando estas ações e as consequências.<br />
<br />
Um protocolo de camada de aplicação define:<br />
#Os tipos de mensagens trocadas.<br />
#A sintaxe dos vários tipos de mensagens, tais como os campos da mensagem e como os campos são delineados.<br />
#A semântica dos campos, isto é, o significado da informação nos campos.<br />
#Regras para determinar quando e como um processo envia mensagens e responde a mensagens.<br />
<br />
Neste experimento será proposto a construção de um protocolo de aplicação para prestar serviços na área de operações matemáticas. Na implementação deste serviço todos grupos serão clientes, solicitando respostas a desafios matemáticos, e servidores, enviando respostas as solicitações, de serviço. Deve ser observado que para não se tornar complexo será usado o transporte de informação através do ICMP (usando o ping). O ping possui uma facilidade para transportar bytes de dados (flag -p). A observação destes dados será feita usando o wireshark (captura de pacotes). Pode-se dizer que o programa ping juntamente com o wireshark e a própria interpretação de pacotes pelo grupo constituem a camada de aplicação.<br />
A camada de transporte foi de certa forma subsituída pelo ICMP que na prática é posicionado na camada de rede (por ser um protocolo auxiliar no funcionamento da camada IP).<br />
<br />
[[Arquivo:AppRCO.png | 500px | Estrutura Applicação'']]<br />
<br />
===Procedimento do Laboratório===<br />
<br />
*Definição do protocolo a ser criado<br />
#Vamos criar uma calculadora em rede através de um protocolo bem simples, utilizando como ferramenta de comunicação o ping.<br />
##O protocolo tem por objetivo dar suporte a uma calculadora em rede.<br />
##Um aluno cria uma mensagem e envia, sem aviso prévio, a um colega. Este será o cliente da arquitetura cliente-servidor.<br />
##O colega, ao receber a mensagem, deverá interpretá-la, elaborar uma resposta à pergunta e retorná-la ao colega. Este será o servidor da arquitetura cliente-servidor.<br />
##A estrutura básica de um pacote que flui do cliente para o servidor e vice-versa é apresentada na figura abaixo. Essa estrutura deverá ser absolutamente respeitada, caso contrário, o servidor poderá não conseguir interpretá-la e descartará a mensagem. <br />
[[Arquivo:RCOestrutura-pacote.png | 400px | Estrutura do Pacote'']]<br />
<br />
<br />
Para auxiliar na interpretação das mensagens utilize:<br />
#[http://iris.sel.eesc.usp.br/sel433a/ASCII.pdf Tabela ASCII]<br />
#[http://www.rapidtables.com/convert/number/hex-to-ascii.htm Ferramenta para conversão ASCII <==> Hexadecimal]<br />
#[http://xor.pw/ XOR CALCULATOR]<br />
<br />
*Roteiro de Atividades:<br />
#Inicie o Wireshark.<br />
#Inicie a captura de pacotes em sua interface de rede e adicione o filtro '''icmp'''.<br />
#Cada estudante vai construir uma mensagem, respeitando o formato estabelecido, de solicitação (lado cliente). Para construir a mensagem utilize o código ASCII. Essa mensagem deverá explicitar:<br />
##O tipo (requisição ou resposta, ver figura).<br />
##Como endereço de destino (DEST) e fonte (FONTE) utilize o último campo do endereço IP de sua máquina e do colega para qual a mensagem se destina. Por exemplo, a máquina do professor possui o IP 192.168.1.1 e, portanto, seu endereço seria 01.<br />
##Um desafio matemático, por exemplo: 2+2.<br />
#Envie essa mensagem através do comando '''ping''' com a ''flag'' ''pattern''. Um exemplo de mensagem é: <syntaxhighlight lang=bash> ping -p FFFF02001001322B322B03FFFF 192.168.1.10 </syntaxhighlight><br />
##Verifique com Wireshark se a mensagem é para o seu grupo e decifre a mensagem.<br />
#Ao receber uma ou mais mensagens de colegas no wireshark, interprete-a verificando quem é o emitente e realizando a operação aritmética solicitada.<br />
##Monte uma resposta e utilize o comando '''ping''' para responder ao emitente.<br />
##Certifique-se que o colega conseguiu interpretar a mensagem<br />
#Desafio:<br />
#*Em equipes, 2 alunos, proponha um novo padrão de mensagens de um protocolo que dê suporte a um Quiz, perguntas e repostas, sobre o tema geografia. Perguntas do tipo: qual é a capital da Austrália?<br />
#*Implemente o protocolo e teste seus conhecimentos e de seus colegas sobre o tema.<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 4 - Desvendando o HTTP com Wireshark - BÁSICO}}<br />
<br />
===Sobre este Laboratório===<br />
<br />
*Baseado na pequena introdução ao Wireshark apresentada no '''Laboratório 2''' e no '''Laboratório Conceituando Protocolos''' , agora estamos prontos para utilizar o Wireshark para investigar protocolos de aplicação reais em operação. Neste laboratório o protocolo HTTP é explorado nas suas características básicas<br />
<br />
===Fonte base===<br />
<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/Desvendando%20o%20HTTP%20basico.pdf SLIDES DE APOIO: Desvendando o HTTP - Básico - Baseado na Pearson/Kurose]<br />
*[http://www.ebah.com.br/content/ABAAABZ6QAD/wireshark-http Wireshark - HTTP]<br />
*[https://pt.wikipedia.org/wiki/Hypertext_Transfer_Protocol HTTP na Wikipedia]<br />
<br />
===Objetivos===<br />
<br />
*Explorar vários aspectos do protocolo HTTP:<br />
*a interação básica GET/resposta do HTTP,<br />
*formatos de mensagens HTTP;<br />
*diferenças http 1.0 e 1.1 / persistência<br />
<br />
===PARTE 1 - Interação Básica GET/Resposta do HTTP===<br />
<br />
Vamos iniciar a nossa exploração do HTTP baixando um arquivo em HTML simples - bastante pequeno, que não contém objetos incluídos. Faça o seguinte:<br />
#inicie o navegador;<br />
#limpe o cache do mesmo (teclas de atalho para o Firefox: '''Ctrl + Shift + Del''');<br />
#inicie o Wireshark, como descrito no '''Laboratório 1''';<br />
#inicie a captura de pacotes;<br />
#digite o seguinte URL no navegador http://tele.sj.ifsc.edu.br/~odilson/RED29004/RED29004.html;<br />
#pare a captura de pacotes;<br />
#digite “http” (somente as letras, sem as aspas) na caixa de texto de especificação do filtro de exibição, de tal forma que apenas as mensagens HTTP capturadas serão exibidas na janela de listagem de pacotes. (Só estamos interessados em HTTP desta vez, e não desejamos ver todos os pacotes capturados).<br />
#No ''browser'', clique o botão da direita e visualize o código fonte da página adquirida em html.<br />
[[Arquivo:HTTP_Wireshark.png |thumb | 300px| Fig.1 Requisição e Resposta HTTP]]<br />
<br />
O exemplo da figura 1 mostra na janela de listagem de pacotes duas mensagens HTTP capturadas:<br />
#A mensagem GET (do seu navegador para o servidor web www.sj.ifsc.edu.br) e a mensagem de resposta do servidor para o seu navegador.<br />
#A janela de conteúdos de pacotes mostra detalhes da mensagem selecionada (neste caso a mensagem HTTP GET /~odilson/RED29004//RED29004.html, que está em destaque na janela de listagem de pacotes).<br />
#A mensagem HTTP transportada em um segmento TCP, que é carregado em um datagrama IP, que é levado em um quadro Ethernet com 5728 bits no fio. Isso é observado de baixo para cima na janela de detalhes do cabeçalho do pacote selecionado. O Wireshark exibe informações sobre o quadro, IP, TCP e HTTP. Você deve expandir as informações, por exemplo, do HTTP clicando na seta ao lado esquerdo de “Hypertext Transfer Protocol”. Observando as informações das mensagens HTTP GET e de resposta. Você consegue inclusive enxergar a mensagem mostrada no navegador: '''RED29004! Página de teste.'''<br />
<br />
Responda às seguintes perguntas e imprima as mensagens GET e a resposta e indique em que parte da mensagem você encontrou a informação que responde às questões.<br />
#O seu navegador executa HTTP 1.0 ou 1.1?<br />
#Qual a versão de HTTP do servidor?<br />
#Quais idiomas (se algum) o seu navegador indica ao servidor que pode aceitar?<br />
#Qual o endereço IP do seu computador?<br />
#E do servidor tele.sj.ifsc.edu.br?<br />
#Qual o número da porta utilizada no seu computador? Note que esta pergunta se refere a porta do protocolo de transporte TCP, portanto, verifique o header TCP;<br />
#E do servidor tele.sj.ifsc.edu.br?<br />
#Qual o código de status retornado do servidor para o seu navegador?<br />
#Quando o arquivo em HTML que você baixou foi modificado no servidor pela última vez?<br />
#Quantos bytes de conteúdo são baixados pelo seu navegador?<br />
#Encontre a mensagem '''RED29004! Página de teste'''. Onde (em qual campo) encontra-se?<br />
#Qual a diferença entre os endereços (IP) de origem e destino entre a mensagem GET e a de resposta do HTTP?<br />
<br />
===PARTE 2 - Interação Básica GET/Resposta do HTTP usando TELNET e REQUISIÇÃO MANUAL===<br />
<br />
Para esta etapa temos que recordar que o browser é responsável por:<br />
*se conectar ao servidor usando uma porta TCP 80 (default) e <br />
*gerar uma mensagem GET para apanhar um recurso no servidor;<br />
*receber e mostrar a página<br />
Mas será que podemos "emular" o comportamento do browser usando uma outra ferramenta? Por exemplo, o telnet permite abrir uma conexão na porta 80. O que for teclado após a conexão será enviado para o servidor pela conexão estabelecida.<br />
<br />
Aproveitando o comportamento acima, vamos montar na MÃO o pacote de aplicação (que o browser gera) e receber a página do servidor como resposta. Claro que agora não teremos a facilidade do browser em mostrar a página para nós. O que veremos é um código HTML, que é um formato de documentos WEB.<br />
<br />
# Vamos repetir o acesso aos links acima, porém sem usar o navegador. A ideia é que nós façamos o papel de navegador. Isso deve ser feito com os seguintes passos:<br />
#* Coloque o Wireshark para capturar pacotes <br />
#* Abra um terminal de texto no Linux (menu ''Aplicativos->Acessórios->Terminal'').<br />
#* Execute este comando: <syntaxhighlight lang=bash><br />
telnet tele.sj.ifsc.edu.br 80<br />
</syntaxhighlight><br />
#* Após aparecer esta linha: <syntaxhighlight lang=text><br />
Trying 200.135.37.75...<br />
Connected to integrado.sj.ifsc.edu.br.<br />
Escape character is '^]'.<br />
</syntaxhighlight>digite o seguinte:<syntaxhighlight lang=text><br />
GET /~odilson/RED29004//RED29004.html HTTP/1.0<br />
</syntaxhighlight> e em seguida tecle ENTER duas vezes.<br />
#* Identifique a página html que foi enviada como resposta.<br />
#* No WireShark, compare o resultado das execuções desses comandos com o resultado anteriormente visto no navegador. Qual a diferença em ambos os casos?<br />
#* Identifique os componentes do sistema de comunicação de dados nesse acesso direto (quem é cliente, quem é servidor)<br />
#* Refaça um pedido em que o recurso é inexistente no servidor (ex: página html com nome inexistente, GET /~odilson/RED29004//Nada.html HTTP/1.0). Observe a resposta. Qual o código (número) de resposta recebido? <syntaxhighlight lang=bash> telnet tele.sj.ifsc.edu.br 80<br />
GET /~odilson/RED29004//Nada.html HTTP/1.0 </syntaxhighlight><br />
#* Refaça um pedido para o recurso ''default'' e veja o código de resposta:<syntaxhighlight lang=bash> telnet tele.sj.ifsc.edu.br 80<br />
GET / HTTP/1.0</syntaxhighlight><br />
#* Refaça o pedido usando o HTTP/1.1 e tente inferir a diferença da versão 1.0. Note que o GET nesta versão deve ser realizado com o campo Host:<syntaxhighlight lang=bash><br />
telnet tele.sj.ifsc.edu.br 80<br />
GET /~odilson/RED29004//RED29004.html HTTP/1.1<br />
Host: tele.sj.ifsc.edu.br</syntaxhighlight><br />
#'''Nesse teste você deve ter observado que a conexão se manteve aberta'''. Experimente refazer o pedido para um outro recurso na mesma conexão:<syntaxhighlight lang=bash><br />
GET /~odilson/RED29004//RED29004_arq2.html HTTP/1.1<br />
Host: tele.sj.ifsc.edu.br<br />
</syntaxhighlight><br />
Esta característica é a "persistência" do http versão 1.1, que permite reutilizar a mesma conexão para adquirir múltiplos recursos.<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 5 - Desvendando o HTTP com Wireshark - AVANÇADO}}<br />
<br />
===Objetivos===<br />
<br />
*Explorar GET Condicional/Resposta no protocolo HTTP:<br />
*Analisar documentos HTML com Objetos Incluídos<br />
*Comparar as mensagens nos protocolos HTTP X HTTP.<br />
<br />
===Fonte base===<br />
<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/Desvendando%20o%20HTTP%20avancado.pdf SLIDES DE APOIO: Desvendando o HTTP - Avançado - Baseado na Pearson/Kurose]<br />
*[http://www.ebah.com.br/content/ABAAABZ6QAD/wireshark-http Wireshark - HTTP]<br />
*[https://pt.wikipedia.org/wiki/Hypertext_Transfer_Protocol HTTP na Wikipedia]<br />
<br />
===PARTE 1 - A Interação HTTP GET Condicional/Resposta===<br />
<br />
A maioria dos navegadores web tem um cache (seção 2.2.6 do livro) e, desta forma, realizam GET condicional quando baixam um objeto HTTP. Execute os seguintes passos:<br />
#inicie o navegador web;<br />
#limpe o cache do seu navegador('''Ctrl + Shift + Del''');<br />
#inicie o Wireshark;<br />
#digite o URL no navegador http://tele.sj.ifsc.edu.br/~odilson/RED29004//RED29004.html seu navegador deve exibir um arquivo em HTML muito simples com duas linhas;<br />
#pressione o botão “refresh” ('''F5''') no navegador (ou digite o URL novamente);<br />
#pare a captura de pacotes, e digite “http” na caixa de texto de especificação de filtro, para que apenas as mensagens HTTP sejam apresentadas na janela de listagem de pacotes. Se você realizou o procedimento corretamente, você visualizará um total de 6 mensagens no Wireshark: três GETs e três respostas. Obs: Para finas de análise, despreze a solicitação e resposta relativa ao ''fiveicon'', que é relativa ao ''download'' do ícone do IFSC.<br />
<br />
Responda às seguintes questões:<br />
#Inspecione o conteúdo da primeira mensagem HTTP GET do seu navegador para o servidor tele.sj.ifsc.edu.br. Você vê uma linha “If-Modified-Since”?<br />
#Inspecione o conteúdo da primeira resposta do servidor. O servidor retornou explicitamente o conteúdo do arquivo? Como você pode dizer isso?<br />
#Agora inspecione o conteúdo da segunda mensagem HTTP GET do seu navegador para o servidor. Você vê uma linha “If-Modified-Since”? Caso a resposta seja afirmativa, qual informação segue o cabeçalho “If-Modified-Since”?<br />
#Qual é o código de status e a frase retornada do servidor na resposta à segunda mensagem HTTP GET? É diferente do código de retorno da primeira mensagem?<br />
#O servidor retornou explicitamente o conteúdo do arquivo? Explique.<br />
#Qual o tamanho da primeira e segunda mensagem de retorno do servidor?<br />
<br />
===PARTE 2 -Documentos HTML com Objetos Incluídos===<br />
<br />
Agora que vimos como o Wireshark mostra o tráfego capturado para arquivos em HTML grandes, nós podemos observar o que acontece quando o seu browser baixa um arquivo com objetos incluídos, no nosso exemplo, imagens que estão armazenadas em outros servidores. Faça o seguinte:<br />
#inicie o navegador web;<br />
#limpe o cache do seu navegador;<br />
#inicie o Wireshark;<br />
#digite o URL no navegador http://tele.sj.ifsc.edu.br/~odilson/RED29004/RED29004_arq3.html seu navegador deve exibir um arquivo pequeno em HTML com duas imagens incluídas. Estas duas imagens estão referenciadas no arquivo em HTML. Isto é, as imagens não estão no arquivo em HTML, ao invés disso, há um URL para cada imagem no arquivo em HTML. Como discutido no livro, seu navegador terá que baixar estas imagens dos locais correspondentes. As imagens estão em docente.ifsc.edu.br;<br />
#Verifique o código fonte da página, clicando com o botão direito sobre ela. Observe os links dentro do código html.<br />
#digite o URL no navegador http://tele.sj.ifsc.edu.br/~odilson/RED29004/RED29004_arq4.html seu navegador deve exibir um arquivo pequeno em HTML com cinco imagens incluídas. Estas cinco imagens,diferentemente do caso anterior, estão depositadas no próprio sítio do professor;<br />
#Verifique o código fonte da página, clicando com o botão direito sobre ela. Observe os links dentro do código html.<br />
#pare a captura de pacotes, e digite “http” na caixa de texto de especificação de filtro, para que apenas as mensagens HTTP seja exibidas.<br />
<br />
Responda às seguintes questões:<br />
#Quantas mensagens HTTP GET foram enviadas pelo seu navegador em cada acesso?<br />
#Para quais endereços na Internet estas mensagens foram enviadas em cada acesso?<br />
#Você consegue dizer se o seu navegador baixou imagens com ou sem paralelismo? Explique e diferencie o comportamento em cada um dos casos.<br />
<br />
===PARTE 3 -Segurança com HTTPS===<br />
Para finalizar, vamos capturar sequências de mensagens HTTPS, somente a título de comparação. Execute os seguintes procedimentos:<br />
#inicie o navegador web;<br />
#limpe o cache do seu navegador;<br />
#inicie o Wireshark;<br />
#digite o seguinte URL no navegador https://www.ssllabs.com/ssltest/;<br />
#pare a captura de pacotes e digite "ssl" na caixa de texto de especificação de filtro, para que apenas as mensagens criptografadas sejam exibidas.<br />
<br />
Responda:<br />
#Compare a sequência de troca de mensagens (GET e resposta) entre o HTTP (das seções anteriores) com o ssl, existe alguma similaridade?<br />
#Que tipos de campos são mais presentes nesse tipo de mensagens?<br />
#Você consegue identificar o conteúdo de alguma nas mensagens ssl, como no caso das mensagens http?<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 6 - Servidor Apache e Construção de Página HTML}}<br />
<br />
===Objetivos===<br />
*Introdução a ferramenta de simulação de redes Netkit.<br />
*Configurando o servidor Apache para disponibilizar páginas HTML.<br />
*Construindo e disponibilizando páginas HTML.<br />
*Noções de ''shell script'' para automatizar tarefas.<br />
<br />
===Fonte base===<br />
<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/ServidorApache.pdf SLIDES DE APOIO: Introdução à Programação “para Web”]. Baseado no resumo destes material Introdução à Programação para Web de Carlos Bazilio: [http://www.ic.uff.br/~bazilio/cursos/java/slides/Introducao.pptm]<br />
*[https://www.apache.org/ Apache]<br />
<br />
===Máquinas Virtuais UML / Netkit2===<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/SlidesApoioMaquinaVirtual.pdf Conceitos de máquinas virtuais]<br />
<br />
Para esta aula de laboratório estaremos usando o [https://wiki.sj.ifsc.edu.br/index.php/Netkit2 netkit2] do Prof. Sobral, uma extensão do [http://wiki.netkit.org/index.php/Main_Page netkit] da '''Universidade Roma Tre'''.<br />
Trata-se de uma ferramenta que que permite criar máquinas virtuais leves sobre o linux. Estas máquinas podem ser ligadas em rede. Neste laboratório conectaremos uma máquina virtual na REDE do Laboratório através de uma bridge.<br />
<br />
===O Servidor Apache===<br />
<br />
Neste laboratório vamos criar uma página html e hospedá-la em um máquina virtual com o [http://www.apache.org/ Web Server Apache]. Para maiores informações consulte [http://softwarelivre.org/php/servidor-web-apache Visão Geral do Apache ].<br />
<br />
===PARTE 1 - Colocando o servidor Apache no ar no Netkit===<br />
<br />
#Inicialmente vamos colocar um Máquina Virtual (VM) Netkit conectada com uma bridge para que possamos acessá-la de qualquer lugar do laboratório. Utilize o editor de texto Gedit e salve as definições do laboratório abaixo em um arquivo '''/home/aluno/lab.conf''':<syntaxhighlight lang=bash><br />
pc1[type]=generic<br />
pc1[eth0]=uplink:bridge=eth0:ip=dhcp<br />
</syntaxhighlight><br />
#Rode o '''netKit''' em seu computador. Em um terminal digite: <syntaxhighlight lang=bash> mkdir .netkit<br />
netkit2 & </syntaxhighlight><br />
#Caso surja uma mensagem recomendando atualizar o Netkit, faça-o através do menu: '''<General> <Update>'''. Aguarde a finalização do processo.<br />
#No menu '''<File> <Load and Run>''', procure o arquivo '''/home/aluno/lab.conf''' e clique em OK. Abrirá um terminal da máquina virtual (VM) que estará rodando servidor Apache que vamos utilizar, onde é possível fazer a configuração do mesmo.<br />
#<span style="color: red;">Dica: não tente alterar o tamanho da janela do Netkit. Se isso for feito não consegue-se mais voltar ao tamnho original.<br />
#Ao clicar no menu '''<File> <Graph>''', pode-se ter uma visão da rede a ser simulada e conferir se é equivalente ao diagrama proposto.<br />
#Identifique o IP da VM usando o comando '''ifconfig'''. Esse será, doravante, seu '''''endereço_IP'''''.<br />
#*<span style="color: blue;">Dica: para copiar textos para o Netkit, copie normalmente o texto, por exemplo, da Wiki, com o < Ctrl > + < C > e cole clicando sobre a rodinha (''scroll'') do mouse.<br />
#Teste a conectividade entre a máquina virtual e a máquina hospedeira com o comando ping. Na VM execute: <syntaxhighlight lang=bash><br />
ping 192.168.1.1 </syntaxhighlight><br />
#Coloque o servidor apache em execução. Este servidor escutará na porta 80 por requisições de páginas (objetos HTTP). Execute no terminal da VM: <syntaxhighlight lang=bash> /etc/init.d/apache2 start </syntaxhighlight><br />
#Inicie o Wireshark em sua máquina.<br />
#Abra o Firefox na sua máquina (hospedeira) e coloque como endereço: <syntaxhighlight lang=bash> http://endereco_IP </syntaxhighlight><br />
#Pronto. Você está acessando a página ''default'' do Apache da VM.<br />
#Você pode verificar o arquivo de definição da página ''default'' na VM com o comando: <syntaxhighlight lang=bash> cat /var/www/index.html </syntaxhighlight><br />
#Com sua experiência com o Wireshark filtre as mensagens trocadas entre o servidor da VM e seu navegador. <br />
##Localize os comandos GET e a resposta do servidor. <br />
##Observe quais são os IPs de destino e fonte da requisição e resposta.<br />
##Observe as portas de destino e fonte da requisição e resposta.<br />
##Qual versão do HTTP está sendo usada?<br />
#Escolha um servidor web de um colega, acesse a página HTML desse colega e repita as capturas de pacotes.<br />
<br />
===PARTE 2 - Colocando no ar a sua página HTML===<br />
<br />
Nesta parte do experimento vamos editar um código HTML e disponibilizá-la em um diretório especial por você criado. Observe que vamos editar a página no hospedeiro e salvá-la em um diretório compartilhado entre a máquina hospedeira e a MV.<br />
<br />
#Usando o Gedit, salve o código html abaixo como no arquivo '''/home/aluno/lab/shared/index.html''' da sua máquina hospedeira.<syntaxhighlight lang=bash><br />
<!DOCTYPE html><br />
<html><br />
<body><br />
<br />
<h1>Alo Mundo</h1><br />
<br />
<p>Estamos sendo visitados por extraterrestres...</p><br />
<br />
</body><br />
</syntaxhighlight><br />
#Crie a adapte para o seu caso um [https://pt.wikipedia.org/wiki/Shell_script Shell Script] com o conteúdo exemplo abaixo. Com o Gedit crie um arquivo e salve como '''/home/aluno/lab/shared/config_apache.sh''' <syntaxhighlight lang=bash><br />
#!/bin/bash<br />
mkdir /var/www/ET<br />
chmod 755 /var/www/ET<br />
cp /hostlab/shared/index.html /var/www/ET<br />
chmod 555 /var/www/ET/index.html<br />
service apache2 restart </syntaxhighlight><br />
#Em sua máquina hospedeira transforme o script em executável. Num terminal digite: <syntaxhighlight lang=bash> chmod +x /home/aluno/lab/shared/config_apache.sh </syntaxhighlight><br />
#O shell script será executado na máquina virtual do apache, portanto, abra o terminal da mesma no Netkit e digite: <syntaxhighlight lang=bash><br />
/hostlab/shared/config_apache.sh <br />
</syntaxhighlight><br />
#Agora você deve ser capaz de acessar a página recém criada através do seu navegador no hospedeiro usando o endereço: <syntaxhighlight lang=bash> http://endereco_IP/ET </syntaxhighlight><br />
#Personalize a página HTML acrescentando novas frases de sua preferência. Para isso repita os passos: 1, 3 e 4.<br />
#Avise o professor para que ele mostre no telão sua página através do Epoptes.<br />
#Acesse as páginas HTML personalizadas dos demais colegas.<br />
#Se desejar, crie outras páginas, para isto basta executar os passos 1 a 5, só que criando diretórios com nomes distintos dos demais já existentes. Cada novo diretório poderá conter uma nova página.<br />
#Também se desejar incremente suas novas páginas com figuras (objetos). Lembre-se de copiar esse objetos para o diretório pertinente na VM.<br />
#*Com o navegador acesse as novas páginas criadas.<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 7 - Serviço de Nomes (DNS)}}<br />
<br />
===Objetivos===<br />
O Domain Name System (DNS) traduz nomes de hosts em endereços Internet Protocol (IP), preenchendo uma lacuna crítica na infraestrutura da Internet. Neste laboratório, observaremos mais de perto:<br />
#O lado cliente do DNS.<br />
#Uma pequena análise do protocolo e<br />
#Consultas AAAA<br />
<br />
Lembre-se de que o papel do cliente no DNS é relativamente simples - um cliente envia uma consulta ao seu DNS, e obtém uma resposta. Muito pode acontecer “por baixo dos panos”, de forma invisível aos clientes DNS, enquanto os servidores DNS, organizados hierarquicamente, comunicam-se entre si para, ou recursivamente ou iterativamente, resolver uma consulta DNS de um cliente. Do ponto de vista do cliente DNS, contudo, o protocolo é bastante simples - uma consulta é feita ao seu servidor DNS e uma resposta é recebida deste servidor.<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/Servico%20de%20Nomes%20DNS.pdf Serviço de Nomes - DNS]<br />
<br />
===PARTE 1: Consulta simples ao DNS gerada a partir de um comando ping===<br />
<br />
O comando ping pode ser usado tanto com um endereço IP como com um nome de host. Em última instância, ele sempre enviará pacotes para um endereço IP. No caso de ser usado o endereço de host, ele tentará resolver (mapear) este nome em um endereço IP usando um servidor DNS (local). Ele gera uma pergunta para o servidor (ou para os servidores, caso exista mais de um configurado). Esta experiência mostra como verificar os servidores instalados e, através de uma captura de pacote mostra a estrutura dos cabeçalhos DNS.<br />
<br />
#Inicialmente consulte e anote quem são os servidores DNS instados na sua máquina. É para estes servidores que serão conduzidas as perguntas DNS. Use a ferramenta nm-tool ou acesso ao arquivo de configuração do sistema:<syntaxhighlight lang=bash><br />
cat /etc/resolv.conf</syntaxhighlight><br />
#Prepare o wireshark para capturar pacotes.<br />
#Execute o ping para um endereço de host conhecido <syntaxhighlight lang=bash><br />
ping www.ifsc.edu.br</syntaxhighlight><br />
#Pare a captura de pacotes no Wireshark e coloque um filtro de display para mostrar apenas mensagens DNS e de ICMP<syntaxhighlight lang=bash><br />
dns || icmp </syntaxhighlight><br />
#Observe os pacotes capturados. Em particular foque no pacote de pergunta que deve ser similar ao mostrado abaixo e deve estar direcionado a um dos servidores DNS. Nos ''flags'' do header do pacote DNS é possível observar que é um QUERY (pergunta) a ser resolvido de forma recursiva. A pergunta propriamente dita está no campo QUERIES, onde é colocado o nome a ser resolvido e o tipo do registro solicitado (tipo A) que indica resolução de nome. <br />
#:<br />
#:[[Arquivo:DNS-Tela1-Wireshark.jpg | 900px| Estrutura de uma pergunta simples DNS]]<br />
#:<br />
#:<br />
#Foque agora um pacote de resposta do servidor para o cliente. Deve ter uma estrutura similar ao mostrado abaixo. Nos flags do header do pacote DNS é possível observar que é uma resposta. A resposta propriamente dita está no campo ANSWERS (ele também repete a pergunta no campo QUERIES). Note que podem haver vários registros (RR) retornados, cada um com um tipo. No exemplo abaixo também é retornada uma lista de servidores autorizados (RR tipo NS). Também é retornado o endereço IP destes servidores através de RRs adicionais do tipo A (inclusive endereços IPv6).<br />
#:<br />
#:<br />
#:[[Arquivo:DNS-Tela2-Wireshark.jpg | 900px| Estrutura de uma resposta simples DNS]]<br />
#Perguntas a serem respondidas, baseado nos pacotes "''Standard query''" e "''Standard query response''":<br />
##Quem são os servidores DNS da sua máquina?<br />
##O ping gerou pergunta para cada um deles?<br />
##Qual o tipo da RR associada a pergunta (''Queries''). O que significa?<br />
##Qual endereço IP retornado para o www.ifsc.edu.br?<br />
##Qual endereço IP usado no ping (ver pacote REQUEST ICMP)?<br />
##Qual protocolo de transporte, camada 4, que foi usado para transportar as mensagens de aplicação DNS?<br />
##Quais os servidores autorizados (''Authoritative nameservers'') foram repassados em resposta a sua consulta?<br />
#Logo após o primeiro ping existe mais uma consulta DNS. Esta pergunta é realizada através de uma mensagem do tipo PTR. O ping está tentando verificar qual é o nome da máquina que realmente está respondendo. É o DNS reverso, nesse tipo de colsulta se fornece um IP e o servidor devolve o nome da máquina.<br />
#Perguntas a serem respondidas:<br />
##Qual o IP que se pretende resolver?<br />
##Qual o nome retornado?<br />
##O nome retornado é www.ifsc.edu.br? Sim ou não? Explique.<br />
<br />
===PARTE 2 - Consultas DNS por meio de ferramentas especializadas===<br />
# Usando o programa [http://manpages.ubuntu.com/manpages/precise/man5/hosts.5.html host], [http://manpages.ubuntu.com/manpages/trusty/en/man1/nslookup.1.html Nslookup] ou [http://manpages.ubuntu.com/manpages/precise/man1/dig.1.html dig], que são executados no terminal, descubra e anote no relatório os endereços IP associados aos seguintes nomes de hosts (máquinas):<br />
#* mail.ifsc.edu.br<br />
#* www.google.com<br />
#* www.gmail.com<br />
# Agora descubra e anote no relatório quem é o servidor DNS responsável por cada um dos domínios dos nomes acima. Para isso consulte o valor do registro NS associado a esses domínios. Por exemplo, com o programa ''host'' ou ''dig'' isso pode ser feito assim: <syntaxhighlight lang=bash><br />
host -t ns ifsc.edu.br<br />
dig -t ns ifsc.edu.br<br />
</syntaxhighlight><br />
# O serviço DNS fornece outras informações além do endereço IP associado a cada nome de domínio e/ou máquina. Por exemplo, como ele pode-se descobrir que ''host'' recebe emails em um determinado domínio. Isso é utilizado pelos MTA (''Mail Transfer Agent'') mundo afora para entregarem emails para seus destinatários (lembre que isso se faz com o protocolo SMTP). Para descobrir essa informação, deve-se consultar o registro MX (''Mail eXchange'') de um domínio. Novamente as ferramentas a ser utilizada nesse caso podem ser ''host'' ou ''dig''. Por exemplo: <syntaxhighlight lang=bash><br />
host -t mx ifsc.edu.br<br />
dig -t mx ifsc.edu.br<br />
</syntaxhighlight>Descubra e anote no relatório quem é o servidor de emails nos seguintes domínios:<br />
#* gmail.com<br />
#* hotmail.com<br />
#* ifsc.edu.br<br />
# Outra informação útil guardada por servidores DNS é a tradução de endereço IP para nome de domínio. Isso é chamado de tradução reversa (ou DNS reverso). Usando os programas de diagnóstico já vistos, isso pode ser feito assim: <syntaxhighlight lang=bash><br />
dig -x 200.135.37.65<br />
</syntaxhighlight> ... o ''dig'' tem um resultado um pouco mais carregado que os outros utilitários (''host'' e ''nslookup''), porém neste caso é mais prático. Veja o resultado da consulta logo após a linha '';; ANSWER SECTION:''. Experimente fazer a resolução reversa para cada um dos IP obtidos nas consultas realizadas no primeiro exercício desta atividade. Pode-se também usar a variante do ''dig'' para respostas curtas: <syntaxhighlight lang=bash><br />
dig -x 200.135.37.65 +short<br />
</syntaxhighlight><br />
#Faça uma consulta iterativa com dig e responda:<syntaxhighlight lang=bash><br />
dig +trace mail.ru. </syntaxhighlight><br />
##Qual foi o RLD (''Root Level Domain'') consultado?<br />
##Qual o TLD (''Top Level Domain'') consultado?<br />
##Qual o SLD (''Second Level Domain'') consultado?<br />
##Como você sabe que foram esses os LDs consultados?<br />
#Consultando um servidor explícito(@)<syntaxhighlight lang=bash><br />
dig @j.root-servers.net. +trace www.sj.ifsc.edu.br. </syntaxhighlight><br />
#AVANÇADO. Execute somente se tiver curiosidade. Como explicado durante a aula e visto no exercício anterior, DNS é um banco de dados distribuído. Isso quer dizer que suas informações estão espalhadas em milhares (ou milhões?) de servidores DNS mundo afora. Cada servidor DNS mantém os dados dos domínios por que é responsável. Será que é possível rastrear todos os servidores DNS que devem ser consultados até chegar ao servidor do domínio procurado? Posto de outro modo, vamos fazer todo o processo de requisição interativa, do exercício anterior, manualmente, ou seja, descobrir quem é o ''Root Level Domain'', o ''Top Level Domain'' e o ''Second Level Domain''. Anote no relatório.<br />
## Descubra quem são os servidores raiz (topo de hierarquia DNS): <syntaxhighlight lang=bash><br />
host -t ns .<br />
dig -t ns .<br />
</syntaxhighlight><br />
## Escolha um dos servidores TLD listados, e use-o para fazer as consultas. Por exemplo: <syntaxhighlight lang=bash><br />
host -v -t a www.sj.ifsc.edu.br. j.root-servers.net.<br />
</syntaxhighlight>... e observe a seção '';; AUTHORITY SECTION:''. Ele contém a listagem de servidores DNS que podem atender sua consulta.<br />
## Continue fazendo as consultas aos servidores DNS listados, até conseguir traduzir o nome requisitado. Por exemplo: <syntaxhighlight lang=bash><br />
host -v -t a www.sj.ifsc.edu.br. b.dns.br </syntaxhighlight><br />
## Quantos servidores DNS foram necessários consultar no total?<br />
<br />
===Algumas consultas AAAA===<br />
Vamos expandir um pouco nossos horizontes e fazer algumas consultas envolvendo IPv6.<br />
#No terminal de sua máquina faça uma consulta e responda: qual o endereço IPv6 dos hosts? Por exemplo: <syntaxhighlight lang=bash><br />
dig AAAA google.com<br />
host -t AAAA google.com </syntaxhighlight><br />
##webmail.ufsc.br<br />
##www.sj.ifsc.edu.br<br />
##www.nyt.com<br />
##ipv6.br<br />
##www.microsoft.com<br />
#Agora vamos fazer a consulta reversa. Qual é o nome de host dos seguintes endereços? Por exemplo: <syntaxhighlight lang=bash><br />
dig -x 2001:12ff::10<br />
dig -x 2001:12ff::10 +short<br />
host 2001:12ff::10 </syntaxhighlight><br />
##2801:84:0:2::10<br />
##2001:12d0:0:126::183:244<br />
##2001:12ff::10<br />
##2804:1454:1004:100::2<br />
<br />
===Analisando o protocolo via Wireshark===<br />
Agora que já está ficando claro como funcionam as consultas DNS, deve-se investigar como se dá a comunicação entre seu computador e seu servidor DNS.<br />
#abra o navegador web e limpe o cache do mesmo;<br />
#abra o Wireshark e escolha a interface e inicie a captura de pacotes;<br />
#inicie a captura de pacotes no Wireshark;<br />
#no terminal digite '''dig +trace canon.jp''' (isso vai provocar a consulta DNS);<br />
#pare a captura de pacotes;<br />
#No Wireshark digite “dns” no filtro (sem as aspas);<br />
Com base nisso identifique o seguinte:<br />
#quantas mensagens são trocadas entre cliente e servidor DNS para cada consulta?<br />
#que protocolo de transporte é usado?<br />
#que portas de origem e destino são utilizadas?<br />
#qual o formato das mensagens DNS? Elas são textuais como as mensagens HTTP?<br />
#qual o tipo de registro DNS acessado em cada consulta?<br />
#que informações estão contidas nas respostas DNS? Há algo além do que foi pedido?<br />
#qual o tamanho das mensagens DNS?<br />
#qual endereço IP a mensagem de consulta DNS é enviada? Foi o mesmo ip obtido na seção anterior: seu servidor DNS?<br />
#examine a mensagem de consulta DNS. Qual o campo “type” desta mensagem?<br />
#a mensagem de consulta contém algum campo “answer”?<br />
#examine a mensagem de resposta DNS. Quantos campos com “answer” existem?<br />
#quais são os benefícios de usar o UDP ao invés do TCP como protocolo de transporte para o DNS?<br />
<br />
===Exemplos de arquivos de um ''Second Level Domain'' fictício===<br />
*Exemplo de arquivos de configuração de um servidor [https://www.isc.org/downloads/bind/ BIND]<br />
/etc/bind/db.redes <syntaxhighlight lang=bash><br />
$TTL 86400<br />
@ IN SOA ns.redes.edu.br. root (<br />
2016090900 ; Serial<br />
604800 ; Refresh<br />
86400 ; Retry<br />
2419200 ; Expire<br />
86400 ) ; Negative Cache TTL<br />
;<br />
@ IN NS ns.redes.edu.br.<br />
@ IN MX 10 mail.redes.edu.br.<br />
$ORIGIN redes.edu.br.<br />
ns A 192.168.1.101<br />
www A 192.168.1.102<br />
www A 192.168.1.103<br />
www A 192.168.1.104<br />
www A 192.168.1.105<br />
www A 192.168.1.106<br />
www A 192.168.1.107<br />
ftp A 192.168.1.108<br />
mail A 192.168.1.109 </syntaxhighlight><br />
<br />
/etc/bind/db.2.168.192 (Zona reversa) <syntaxhighlight lang=bash><br />
$TTL 86400<br />
@ IN SOA ns.redes.edu.br. root (<br />
2016090900 ; Serial<br />
604800 ; Refresh<br />
86400 ; Retry<br />
2419200 ; Expire<br />
86400 ) ; Negative Cache TTL<br />
;<br />
IN NS ns.redes.edu.br.<br />
101 IN PTR ns.redes.edu.br.<br />
102 IN PTR www.redes.edu.br.<br />
108 IN PTR ftp.redes.edu.br.<br />
109 IN PTR mail.redes.edu.br. </syntaxhighlight><br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 8 - Desvendando o UDP - Básico}}<br />
<br />
===Objetivos===<br />
<br />
*Familiarizar-se com o UDP<br />
*Entender a estrutura do pacote UDP<br />
*Entender o conceito de portas<br />
*Entender o conceito de multiplexação<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/UDP%20Basico.pdf Introdução a camada de transporte e UDP básico]<br />
<br />
===Parte 1 - Fluxo único UDP===<br />
<br />
#Combinar equipes com dois computadores para execução do experimento.<br />
#*Uma equipe escutará na porta 5000 e a outra equipe transmitirá uma mensagem nessa porta. Os processos de transmissão e recepção podem ocorrer simultaneamente, em terminais distintos.<br />
#*Cada equipe deve identificar os IPs ('''IP_DEST''') das máquinas de seus pares.<br />
#Cada equipe deve abrir uma Janela de terminal.<br />
#Cada equipe deve preparar o '''Wireshark''', interfaces '''any''', para escuta das portas no protocolo UDP usando um filtro:<syntaxhighlight lang=bash><br />
udp.port==5000</syntaxhighlight><br />
#A equipe da escuta na porta 5000 executa no terminal: <syntaxhighlight lang=bash><br />
netcat -u -l -p 5000 </syntaxhighlight><br />
#A equipe que irá transmitir para a porta 5000 executa no terminal: <syntaxhighlight lang=bash><br />
netcat -u IP_DEST 5000 </syntaxhighlight><br />
#*Em seguida escreve no terminal uma mensagem de até 20 caracteres, ao teclar <Enter> a mensagem será enviada.<br />
#*O wireshark deve ter capturado os pacotes UDP <br />
#Identifique e anote os seguintes dados na captura do wireshark:<br />
#*IP FONTE e DESTINO<br />
#*PORTAS FONTE E DESTINO para ambas comunicações<br />
#*Campo de protocolo no pacote IP<br />
#*Campo de tamanho (anote o tamanho) e ''checksum'' no pacote (datagrama) UDP<br />
#*O campo de dados no pacote UDP<br />
#Troquem os papéis das equipes: quem houvia agora transmite mensagens.<br />
#Cada equipe pode transmitir sequencialmente várias mensagens, devendo identificar múltiplos datagramas UDP.<br />
#PERGUNTAS baseadas na captura:<br />
##Qual o tamanho de cada campo do cabeçalho do pacote UDP?<br />
##Qual o tamanho máximo do número de porta?<br />
##Qual o tamanho máximo da área de dados (payload) do pacote?<br />
##Qual o número identificador de protocolo UDP no pacote IP? <br />
##Em algum momento foi identificado algum procedimento para estabelecimento de conexão? <br />
##Em algum campo do UDP existe numeração de mensagens?<br />
<br />
===Parte 2 - Experimento com UDP - MUX e DEMUX===<br />
<br />
#Conceber um adendo ao experimento anterior para demonstrar a multiplexação e demultiplexação de informação.<br />
#*Lembre-se que a demultiplexação permitirá que diferentes fluxos sejam encaminhados para diferentes processos. Nesse sentido, por exemplo, em uma mesma máquina pode-se abrir dois os mais terminais onde, em cada um deles, pode-se gerar ou aguardar fluxos distintos (diferenciados pelas portas).<br />
#Capture os pacotes com o Wireshark e caracterize quais pacotes pertencem a cada fluxo (porta).<br />
#Mostre o experimento ao professor, que projetará o mesmo no telão.<br />
<br />
'''DESAFIO''' (para casa?): capture e anote byte a byte o conteúdo de um pequeno pacote UDP (e dados IP) e calcule o CHECKSUM do mesmo (pesquise no google como fazer).<br />
{{Collapse bottom}}<br />
{{Collapse top |Laboratório 9 - Desvendando o TCP - Básico}}<br />
<br />
===Objetivos===<br />
<br />
*Verificar o comportamento básico do Protocolo TCP:<br />
**Fase de Estabelecimento de Conexão<br />
**Troca de Dados<br />
**Finalização da Conexão<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/TCP%20Basico.pdf Camada de transporte: TCP básico]<br />
<br />
==Configuração do Laboratório==<br />
O netkit2 deve ser atualizado manualmente com este procedimento:<br />
# Abrir um terminal<br />
# Baixar o programa do ''Netkit2'' com o comando: <syntaxhighlight lang=bash><br />
wget http://tele.sj.ifsc.edu.br/~msobral/netkit2/bin/netkit2<br />
</syntaxhighlight><br />
# Copiá-lo para o diretório do Netkit2 com o comando: <syntaxhighlight lang=bash><br />
cp netkit2 ${NETKIT2_HOME}/bin/<br />
</syntaxhighlight><br />
<br />
O roteiro será executado sobre 3 máquinas virtuais, através do uso do [[Netkit2 | Netkit2]]. Copie o texto abaixo no '''Gedit''' e salve com o nome '''/home/aluno/TCP.conf'''. <br />
<syntaxhighlight lang=text><br />
PC1[type]=generic<br />
PC2[type]=generic<br />
PC3[type]=generic<br />
<br />
<br />
PC1[eth0]=lan0:ip=10.0.0.1/24<br />
PC2[eth0]=lan0:ip=10.0.0.2/24<br />
PC3[eth0]=lan0:ip=10.0.0.3/24<br />
</syntaxhighlight><br />
<br />
===Verificando o estabelecimento, troca de dados e finalização da conexão===<br />
<br />
#Executar a configuração do laboratório no Netkit. Abra o NetKit2 e abra o arquivo de configuração: <syntaxhighlight lang=bash><br />
File > Load and Run </syntaxhighlight><br />
#*Perceba que abrirá uma janela com três abas inferiores, representando três máquina virtuais criadas pelo Netkit, denominadas: PC1, PC2 e PC3. Cada uma dessas abas é o terminal de configuração da respectiva máquina virtual.<br />
#Executar no PC2 um servidor TCP aguardando na porta 5555 na forma: <syntaxhighlight lang=bash> netcat -l 5555 </syntaxhighlight><br />
#*Obs.: para copiar texto para as máquinas do NetKit, pode-se copiar normalmente o texto e em seguida, no terminal do NetKit apropriado, clique na "rodinha" do mouse.<br />
#*Em uma comunicação TCP um processo é servidor (aguarda pedido de conexão) e um processo é o cliente, que gera um pedido de conexão<br />
#Executar no PC3 o tcpdump com foco na porta tcp 5555 e para salvar pacotes em arquivo: <syntaxhighlight lang=bash> tcpdump -i eth0 tcp port 5555 -s 1024 -U -w /hostlab/shared/pc3.cap </syntaxhighlight><br />
#Executar no PC1 um cliente TCP que solicita uma conexão ao servidor: <syntaxhighlight lang=bash> netcat 10.0.0.2 5555 </syntaxhighlight><br />
#Enviar uma pequena mensagem de 5 caracteres, e no final teclar ENTER e depois CTRL+D.<br />
#*O CTRL-D encerra a conexão no netcat<br />
#Vá até o terminal do PC3 e encerre a captura de pacotes do '''tcpdump''' digitando CTRL+C.<br />
#Abrir o arquivo de captura gravado no PC3 com o Wireshark. Temos duas possibilidades para fazer isso, escolha uma das duas:<br />
##Abrir o Wireshark e ir no menu File > Open > Pasta Pessoal > lab > shared > pc3.pcap<br />
##Abrir o "navegador de arquivos" e encontrar procurar o arquivo na pasta aluno/lab/shared/pc3.pcap (/home/aluno/lab/shared/pc3.pcap).<br />
#Todos pacotes TCP, desde o estabelecimento até a desconexão devem estar capturados. Um exemplo dessa captura encontra-se na Figura 1.<br />
[[Arquivo:WiresharkTCP.png |thumb | 600px| Fig.1 -- Protocolo TCP]]<br />
#O processo de conexão do TCP envolve a troca de 3 pacotes e é sempre iniciado pelo cliente. O cliente envia um pacote SYN, o servidor responde com um SYN-ACK e o cliente finalmente responde com ACK. Observe estes pacotes no wireshark.<br />
#*Pratique seu inglês e leia um pouco sobre este processo de estabelecimento de conexão em [https://en.wikipedia.org/wiki/Transmission_Control_Protocol#Connection_establishment Connection Establishment] <br />
#Baseado na captura de pacotes realizada responda:<br />
##Quais foram as portas de origem e destino usadas?<br />
##Quais os tamanhos das janelas informadas, tanto pelo cliente quanto pelo servidor?<br />
##Quais os números de sequência informado pelo Wireshark e o número que consta no campo Data em bytes. Qual é relação entre esses números?<br />
##Em qual mensagem (número) aparece a texto que você digitou?<br />
##Qual o número identificador de protocolo TCP no pacote IP?<br />
#*Um dos objetivos do processo de conexão é sincronizar o número de sequência. Cada lado fica sabendo do número de sequência do outro. O número de sequência não começa com zero.<br />
#*O Wireshark converte a numeração para mostrar a partir do 0 mas o número inicial de sequência é criado randomicamente por cada lado. (ver [https://wiki.wireshark.org/TCP_Relative_Sequence_Numbers])<br />
#Volte ao wireshark e analise o processo de termino da conexão (iniciado pelo cliente neste caso, no momento do CTRL+D).<br />
#*Note que qualquer uma das partes pode realizar esta finalização.<br />
#*Pode ser observado que o cliente envia um pacote TCP com flag FIN.<br />
#*O servidor responde com um FIN-ACK.<br />
#*Finalmente o cliente faz um ACK. <br />
#*Veja se confere com a figura [http://www.tcpipguide.com/free/t_TCPConnectionTermination-2.htm Término de conexão TCP] ou com os [http://docente.ifsc.edu.br/odilson/RCO60803/TCP%20Basico.pdf slides] apresentados no início da aula.<br />
#Gere com o wireshark um diagrama da comunicação, ou diagrama de troca de mensagens, fazendo: Statistics > Flow Graph > OK<br />
#Analise esse diagrama, observando qual pacote contém os dados, ou seja, o texto que você digitou.<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 10 - Desvendando o TCP - Número de Sequência, Controle de Erros e Funcionamento Full-Duplex}}<br />
<br />
===Objetivos===<br />
<br />
*Verificar:<br />
**Controle de Erros: Significado de Número de Sequência, ACK<br />
**Controle de Fluxo: Significado do campo Windows Size; Funcionamento do controle de fluxo;<br />
**Comportamento Full-Duplex<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/TCP%20controle%20de%20erros.pdf TCP - Controle de Erros]<br />
<br />
==Configuração do Laboratório==<br />
O roteiro será executado sobre máquinas virtuais, através do uso do [[Netkit2 | Netkit2]]. Copie o texto abaixo, abra o editor Gedit, cole o texto e salve o arquivo em /home/aluno/TCP.conf.<br />
<syntaxhighlight lang=bash><br />
PC1[type]=generic<br />
PC2[type]=generic<br />
PC3[type]=generic<br />
<br />
<br />
PC1[eth0]=lan0:ip=10.0.0.1/24<br />
PC2[eth0]=lan0:ip=10.0.0.2/24<br />
PC3[eth0]=lan0:ip=10.0.0.3/24<br />
</syntaxhighlight><br />
<br />
===PARTE 1 - Transmissão sem erros: Verificação de Número de Sequência, Reconhecimentos e Controle de Fluxo===<br />
#Executar a configuração do laboratório no Netkit. Abra o NetKit2 e abra o arquivo de configuração: <syntaxhighlight lang=bash><br />
File > Load and Run </syntaxhighlight><br />
#*Perceba que abrirá uma janela com três abas inferiores, representando três máquina virtuais criadas pelo Netkit, denominadas: PC1, PC2 e PC3. Cada uma dessas abas é o terminal de configuração da respectiva máquina virtual.<br />
#Utilize o editor de texto '''gedit''' da máquina real, inclua o texto abaixo, e salve como '''/home/aluno/lab/shared/arq.tx''' <syntaxhighlight lang=bash><br />
ABCDEFGHIJKLMNOPQRSTUVXZW1234 </syntaxhighlight><br />
#Execute o tcpdump no PC3 <syntaxhighlight lang=bash><br />
tcpdump -i eth0 tcp port 5555 -s 1024 -U -w /hostlab/shared/pc3.pcap </syntaxhighlight><br />
#Execute os comandos abaixo no PC2 (copie e cole).<br />
##O primeiro comando limita sua capacidade de recepção em cerca de 20 bytes (tamanho do ''buffer''). Isto permitirá ver a quebra do arquivo de 30 bytes em alguns segmentos TCP.<br />
##O segundo comando abre a porta 5555, através do netcat, e espera a chegada dos dados.<syntaxhighlight lang=bash><br />
sysctl -w net.ipv4.tcp_rmem='20 20 20'<br />
netcat -l 5555 > arq.rx </syntaxhighlight><br />
#Envie o arquivo arq.tx a partir do PC1 com o comando:<syntaxhighlight lang=bash><br />
netcat 10.0.0.2 5555 < /hostlab/shared/arq.tx </syntaxhighlight><br />
#No PC3 faça CTRL+C, para parar a captura de pacotes.<br />
#Abra o arquivo de captura gravado no PC3 (/home/aluno/lab/shared/pc3.pcap) com o Wireshark:<br />
##Abrir o Wireshark e ir no menu File > Open > Pasta Pessoal > lab > shared > pc3.pcap<br />
#Você terá algo parecido com o apresentado na Figura 1.[[Arquivo:WiresharkTCPPerdaDePacotes.png |thumb | 600px| Fig.1 -- Protocolo TCP]]<br />
#Analise como os dados foram transmitidos e reconhecidos.<br />
====Perguntas====<br />
#Qual o número de sequência (normalizado pelo Wireshark) de cada segmento de dados transmitido (de PC1 para PC2) e qual o significado do número de reconhecimento em cada um deles? <br />
#Como foi reconhecido cada segmento enviado? <br />
#*Relate esta análise por segmento usando os timestamps (coluna Time) como referência.<br />
<br />
====Arquivo CAP deste experimento====<br />
<br />
*[https://www.dropbox.com/s/cv82wa1r3jatvgp/tcp_parte1-pc3-sequencia-controle-fluxo.cap Sequencia.cap]<br />
<br />
===PARTE 2 - Transmissão com erros: retransmissões===<br />
<br />
#Repetir todo a parte 1 mas substituir o item 4 por: <syntaxhighlight lang=bash><br />
sysctl -w net.ipv4.tcp_rmem='20 20 20'<br />
tc qdisc add dev eth0 root netem loss 50% <br />
netcat -l 5555 > arq.rx </syntaxhighlight><br />
Perguntas:<br />
#Qual o número de sequência (normalizado pelo Wireshark) de cada segmento de dados transmitido (de PC1 para PC2) e qual o significado do número de reconhecimento em cada um deles?<br />
#Como foi reconhecido cada segmento enviado?<br />
#Houve perda de pacotes? Como você identificou isso?<br />
#Os pacotes perdidos foram retransmitidos? Justifique.<br />
<br />
====arquivo cap deste experimento====<br />
<br />
*[https://www.dropbox.com/s/fb9izlu3ykin4yt/pc3-retransmissoes.cap retransmissoes.cap]<br />
<br />
===PARTE 3 - Testando a capacidade do TCP de enviar dados de forma duplex===<br />
<br />
*Agora vamos deixar de lado o netkit para fazer um pequeno teste de transmissão de arquivos entre dois colegas.<br />
*No experimento, o arquivo de um aluno será transmitido para outro e vice-versa.<br />
<br />
#Em um terminal da máquina real, crie um diretório de trabalho e entre no mesmo <syntaxhighlight lang=bash><br />
mkdir teste<br />
cd teste </syntaxhighlight><br />
#Com o '''gedit''' construa um arquivo de cerca de 2000 bytes. Coloque neste arquivo o seu poema ou letra de canção preferida. Salve o arquivo com nome '''/home/aluno/teste/arq.tx'''.<br />
#Escolha um colega para transferir o arquivo.<br />
##Negocie quem será o servidor e quem será o cliente.<br />
##No processo, o arquivo criado por um aluno será enviado ao colega e vice-versa (tx, rx).<br />
#O servidor deve fazer <syntaxhighlight lang=bash><br />
netcat -l 5555 < arq.tx > arq.rx </syntaxhighlight><br />
#*Ao término da transmissão, o arq.rx conterá os dados recebidos.<br />
#O cliente deve fazer, <span style="color: red;">lembre-se de adequar o IP_SERVIDOR<syntaxhighlight lang=bash><br />
netcat IP_SERVIDOR 5555 < arq.tx > arq.rx </syntaxhighlight><br />
#*<span style="color: black;">Ao término da transmissão, o arq.rx conterá os dados recebidos.<br />
#Abra o arquivo recebido do colega (arq.rx) com o '''gedit''' e confira o conteúdo.<br />
Perguntas:<br />
#Onde pode ser observado a comunicação ''full-duplex''?<br />
#Qual é a relação entre os comandos do cliente e servidor com a comunicação ''full-duplex''?<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 11 - Controle de congestionamento e equidade do TCP}}<br />
<br />
===Objetivos===<br />
*Tem como objetivo gerar um gráfico para facilitar a visualização do '''controle de congestionamento''' e a consequente '''equidade''' do protocolo TCP.<br />
*Utilizar o software [https://iperf.fr/ Iperf] (iperf –h para help) para gerar tráfego entre duas máquinas, '''cliente''' e '''servidor'''.<br />
*Utilizar o software [[netkit2]].<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/TCP%20controle%20de%20congestionbamento%20e%20equidade.pdf TCP - Controle de Congestionamento e Equidade]<br />
*[https://media.pearsoncmg.com/aw/ecs_kurose_compnetwork_7/cw/content/interactiveanimations/tcp-congestion/index.html Animação do controle de congestinamento]<br />
<br />
===Roteiro===<br />
*O roteiro será executado sobre máquinas virtuais, através do uso do [[Netkit2 | Netkit2]].<br />
*Para realização dos ensaios será montada a rede virtual apresentada na Figura 1. <br />
<br />
[[Arquivo:TCP_Rede_Controle_de_Fluxo.png |thumb | 200px| Figura 1 - Rede ara testes]]<br />
#Copie o texto abaixo e crie um arquivo com o '''Gedit''', salve-o como /home/aluno/TCP.conf.<syntaxhighlight lang=bash><br />
# Definição das máquinas<br />
R1[type]=router<br />
PC1[type]=generic<br />
PC2[type]=generic<br />
PC3[type]=generic<br />
<br />
# Definição dos roteadores padrão<br />
PC1[default_gateway]=10.0.0.254<br />
PC2[default_gateway]=10.0.1.254<br />
PC3[default_gateway]=10.0.1.254<br />
<br />
# Definição das interfaces do roteador <br />
R1[eth0]=lan0:ip=10.0.0.254/24:rate=10000<br />
R1[eth1]=lan1:ip=10.0.1.254/24:rate=10000<br />
<br />
# Definição das interfaces dos PCs<br />
PC1[eth0]=lan0:ip=10.0.0.1/24:rate=10000<br />
PC2[eth0]=lan1:ip=10.0.1.2/24:rate=10000<br />
PC3[eth0]=lan1:ip=10.0.1.3/24:rate=10000 </syntaxhighlight><br />
#Execute o NetKit2.<br />
#Carregue o arquivo de configuração: <syntaxhighlight lang=bash><br />
File > Load and Run </syntaxhighlight><br />
#*Perceba que abrirá uma janela com quatro abas inferiores, representando um roteador e três máquina virtuais criadas pelo Netkit, denominadas: R1, PC1, PC2 e PC3. Cada uma dessas abas é o terminal de configuração do respectivo equipamento.<br />
#*Ao clicar no menu '''File - Graph''', pode-se ter uma visão da rede a ser simulada e conferir se é equivalente ao diagrama proposto.<br />
#Execute no PC3 o tcpdump para salvar a troca de dados entre o PC1 e o PC2 num arquivo: <syntaxhighlight lang=bash><br />
tcpdump -i eth0 -w /hostlab/shared/pc3.cap </syntaxhighlight><br />
#*Para copiar comando para os terminais das máquinas virtuais: copie o texto desejado, no Netkit selecione o terminal da máquina desejada e clique sobre a "rodinha" do mouse que o texto será colado.<br />
#No PC1 (servidor) execute: <syntaxhighlight lang=bash><br />
iperf -s -p 2000 & iperf -s -p 2001 & iperf -s -p 2002 & </syntaxhighlight><br />
#No PC2 (cliente) execute (copie a três linhas e cole no terminal adequado e em seguida tecle <Enter>): <syntaxhighlight lang=bash><br />
iperf -c 10.0.0.1 -f m -i 1 -t 90 -p 2000 -l 1300 & \<br />
(sleep 20; iperf -c 10.0.0.1 -f m -i 1 -t 70 -p 2001 -l 1300) & \<br />
(sleep 30; iperf -c 10.0.0.1 -f m -i 1 -t 60 -p 2002 -l 1300) & </syntaxhighlight><br />
#Fique monitorando o PC2 até a tela parar de ser atualizada, aproximadamente 90 s.<br />
#Pare os processos nos três PCs utilizando CTRL-C.<br />
#Abra o Wireshark.<br />
#Abra o arquivo <syntaxhighlight lang=bash><br />
File > Open > /home/aluno/lab/shared/pc3.cap </syntaxhighlight><br />
#No wireshark acesse '''Statistics''' >> '''IO Graph''' e, na tela que abrir, ajuste TODOS os parâmetros para obter um gráfico similar ao apresentado na Figura 2.<br />
#*Perceba que todos os botões '''Graph 1...4''' devem ser clicados, e os filtros aplicados (tcp.port==2000; tcp.port==2001; tcp.port==2002) isso fará com que o Wireshark mostre as respectivas curvas. [[Arquivo:TCP_Wireshark.png |thumb | 400px| Figura 2 - Captura de 3 fluxos de dados]]<br />
#Responda:<br />
##Explique detalhadamente o significado de cada parâmetro dos comandos dos itens 5 e 6 acima, tanto do cliente quanto do servidor.<br />
##Explique os filtros aplicados no gráfico do Wireshark.<br />
##*Quais são os 4 gráficos apresentados?<br />
##*Há uma relação de valor entre as curvas?<br />
##*Qual é esta relação?<br />
##Por que a curva vermelha se sobrepõe a curva preta nos primeiros 20 segundos? Considere o início do tempo onde há início de tráfego!<br />
##Qual é a relação entre a curva preta e as curvas vermelha e verde no intervalo entre 20 e 30 segundos?<br />
##Explique a relação entre as 4 curvas e o comando do cliente (item 5) no intervalo entre 20 e 40 segundos.<br />
##Qual é o mecanismo do TCP que explica a grande oscilação das curvas, principalmente percebida no intervalo entre 20 e 30 segundos?<br />
<br />
=====Incluindo UDP=====<br />
Agora vamos dificultar a vida do TCP incluindo um tráfego UDP. O gráfico gerado deverá apresentar a competição pelo meio de transmissão entre os diversos fluxos de dados.<br />
#Deslique o NetKit2, para limpar todos os processos e ''buffers'': <syntaxhighlight lang=bash><br />
File > Quit </syntaxhighlight><br />
#Copie o texto abaixo e crie um arquivo, salve-o como /home/aluno/TCPxUDP.conf: <syntaxhighlight lang=bash><br />
# Definição das máquinas<br />
R1[type]=router<br />
PC1[type]=generic<br />
PC2[type]=generic<br />
PC3[type]=generic<br />
PC4[type]=generic<br />
<br />
# Definição dos roteadores padrão<br />
PC1[default_gateway]=10.0.0.254<br />
PC2[default_gateway]=10.0.1.254<br />
PC3[default_gateway]=10.0.1.254<br />
PC4[default_gateway]=10.0.1.254<br />
<br />
# Definição das interfaces do roteador <br />
R1[eth0]=lan0:ip=10.0.0.254/24:rate=10000<br />
R1[eth1]=lan1:ip=10.0.1.254/24:rate=10000<br />
<br />
# Definição das interfaces dos PCs<br />
PC1[eth0]=lan0:ip=10.0.0.1/24:rate=10000<br />
PC2[eth0]=lan1:ip=10.0.1.2/24:rate=10000<br />
PC3[eth0]=lan1:ip=10.0.1.3/24:rate=10000<br />
PC4[eth0]=lan1:ip=10.0.1.4/24:rate=10000 </syntaxhighlight><br />
#Execute o NetKit2 e carregue o arquivo de configuração.<br />
#No PC4 execute: <syntaxhighlight lang=bash><br />
tcpdump -i eth0 -w /hostlab/shared/pc4.cap </syntaxhighlight><br />
#No PC1 execute: <syntaxhighlight lang=bash><br />
iperf -s -u -p 2000 & iperf -s -p 2001 & </syntaxhighlight><br />
#A próxima etapa deve ser executada "simultaneamente" nos PC2 e PC3.<br />
##Para isso copie o texto abaixo e cole no terminal do PC2, ainda NÃO tecle <Enter>: <syntaxhighlight lang=bash><br />
iperf -u -c 10.0.0.1 -f m -i 1 -t 60 -p 2000 -l 1300 -b 10000000 </syntaxhighlight><br />
##Copie o texto abaixo e cole no terminal do PC3, ainda NÃO tecle <Enter>: <syntaxhighlight lang=bash><br />
iperf -c 10.0.0.1 -f m -i 1 -t 90 -p 2001 -l 1300 </syntaxhighlight><br />
##Tecle <Enter> no PC3 e PC2, NESSA ORDEM, "simultaneamente".<br />
#Fique monitorando o PC3 a tela parar de ser atualizada, aproximadamente 90 s.<br />
#Pare os processos nos quatro PCs utilizando CTRL-C.<br />
#Rode o Wireshark e abra o arquivo /home/aluno/lab/shared/pc4.cap.<br />
#Baseado na Figura 3, no '''Graph 2''' altere o filtro para '''udp.port==2000''' e no '''Graph 3''' altere o filtro para '''tcp.port==2001'''. Salve o gráfico gerado.<br />
[[Arquivo:TCPxUDP_Wireshark.png |thumb | 400px| Figura 3 - Captura de 2 fluxos de dados TCP e UDP]]<br />
#Responda as mesmas questões do item anterior, '''todas'''.<br />
#Explique o comportamento dos vários fluxos de dados com e sem o UDP.<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 12 - TCP x UDP}}<br />
<br />
===Objetivos===<br />
*O objetivo desses experimentos é evidenciar as diferenças entre os protocolos TCP e UDP.<br />
*Ambos protocolos de transporte podem ser usados por aplicações que precisem se comunicar. Porém cada um deles têm certas propriedades, então a escolha precisa ser realizada baseada no tipo de comunicação a ser feita pela aplicação.<br />
<br />
==== Experimento 1 ====<br />
<span style="color: red;">Antes de qualquer experimento deve-se desabilitar algumas funcionalidades do kernel do LINUX, para que os experimentos reflitam a teoria. Caso sua interface de rede não seja a '''eth0''' adapte o comando, caso reiniciar a máquina repita-o:</span><br />
<syntaxhighlight lang=bash>sudo ethtool --offload eth0 gso off tso off sg off gro off </syntaxhighlight><br />
<br />
O que aconteceria se um arquivo fosse transferido de um computador a outro com ambos protocolos?<br />
<br />
# Abra um terminal e execute o seguinte comando para fazer o download de um arquivo a ser usado no experimento: <syntaxhighlight lang=bash><br />
wget http://tele.sj.ifsc.edu.br/~odilson/RED29004/jogo.exe<br />
</syntaxhighlight><br />
# Observe o tamanho do arquivo transferido ... ele deve ter exatamente 332831416 bytes (cerca de 318 MB). Você pode fazer isso com o comando '''ls -l jogo.exe''', ou executando o gerenciador de arquivos e visualizando as propriedades desse arquivo.<br />
# Escolha um colega para fazer o experimento em que o arquivo será transferido de um computador para o outro. NÃO pode ser na própria máquina. Um será o '''receptor''' e outro o '''transmissor'''.<br />
=====A primeira transferência será feita usando o protocolo TCP da seguinte forma=====<br />
#Execute o WireShark e deixe-o capturando pacotes '''somente''' durante a transferência do arquivo. Como o o comportamento padrão do wireshark é redefinir o número de sequência para sempre iniciar em um e isso pode atrapalhar nossos experimentos, vamos '''desabilitar/desativar''' essa funcionalidade: <syntaxhighlight lang=bash><br />
Edit >> Preferences >> Protocols >> TCP >> Relative sequence numbers </syntaxhighlight><br />
#No computador '''receptor''' execute o '''netcat''' ('''nc''') (utilize '''man nc''' para saber os detalhes das ''flags'' utilizadas) que abrirá uma conexão TCP na porta, por exemplo, 5555 e salvará os dados transferidos em '''arquivo''': <syntaxhighlight lang=bash><br />
nc -vvnl 5555 > arquivoTCP<br />
</syntaxhighlight><br />
#No computador '''transmissor''' execute, após o processo do '''receptor''' estar executando ('''adeque o ip_do_receptor para o devido número IP'''): <syntaxhighlight lang=bash><br />
time nc -vvn ip_do_receptor 5555 < jogo.exe<br />
</syntaxhighlight><br />
#Quando completar a transferência, pare o Wireshark.<br />
#Verifique o tamanho do arquivo recebido. Ele é igual ao arquivo original? E quanto tempo levou para transmiti-lo? No terminal digite: <syntaxhighlight lang=bash><br />
ls -l </syntaxhighlight><br />
#Analisando a captura de pacotes do WireShark responda:<br />
## Quais as portas origem e destino escolhidas pelo cliente e servidor?<br />
## Qual é o número de sequência do primeiro e do último pacote?<br />
## Qual é o número de sequência do primeiro e do último ACK?<br />
## Qual o Tamanho Máximo de Segmento (MSS) escolhidos pelo cliente e servidor na conexão.<br />
## É possível calcular o tamanho do arquivo pela análise dos pacotes? Qual é a maneira mais fácil? Apresente os cálculos ou descreva a maneira de obtenção do valor.<br />
## Qual é o tamanho do último segmento de dados recebido?<br />
## Todos os segmentos trocados entre as máquinas contém dados ou alguns são somente de controle? Qual o percentual aproximado de segmentos de controle?<br />
<br />
=====A segunda transferência será feita usando o protocolo UDP=====<br />
#Execute o WireShark e deixe-o capturando pacotes '''somente''' durante a transferência do arquivo.<br />
#Combine com um colega e estabeleça quem suem será o transmissor e quem será o receptor. No computador '''receptor''' baixe o programa '''receptor''', acrescente a ele permissão de execução e o execute, conforme a sequência de comandos abaixo: <syntaxhighlight lang=bash><br />
wget http://tele.sj.ifsc.edu.br/~odilson/RED29004/receptor<br />
chmod +x receptor<br />
./receptor 5555 > arquivoUDP<br />
</syntaxhighlight><br />
#No computador '''transmissor''' baixe o programa '''transmissor''', acrescente a ele permissão de execução e o execute, conforme a sequência de comandos abaixo: <syntaxhighlight lang=bash><br />
wget http://tele.sj.ifsc.edu.br/~odilson/RED29004/transmissor<br />
chmod +x transmissor </syntaxhighlight><br />
#Inicie a transferência do arquivo ('''adeque o ip_do_receptor para o número IP do colega'''): <syntaxhighlight lang=bash><br />
./transmissor ip_do_receptor 5555 < jogo.exe<br />
</syntaxhighlight><br />
#Quando completar a transferência (vai aparecer a mensagem no '''transmissor''' "Levou XXXXX segundos para transmitir XXXXX bytes).<br />
#No '''receptor''' digite <CTRL + C><br />
#Verifique o tamanho do arquivo recebido.<br />
##Ele é igual ao arquivo original?<br />
##Quanto tempo levou para transmiti-lo?<br />
#Analisando a captura de pacotes do WireShark responda:<br />
## Qual é o número de sequência do primeiro e do último pacote? Existe?<br />
## É possível calcular o tamanho do arquivo pela análise dos pacotes? É mais fácil ou difícil que no caso da transferência via TCP?<br />
## Há segmentos de controle ou somente segmentos de dados?<br />
## Qual é o tamanho do último segmento de dados recebido?<br />
# Compare as transferências feitas com os protocolos TCP e UDP.<br />
## O que eles têm em comum?<br />
## Que diferenças lhe pareceram mais pronunciadas?<br />
## Como isso deve afetar as aplicações que usam esses protocolos?<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 13 - Interligação de duas redes locais via um roteador}}<br />
<br />
===Objetivos===<br />
<br />
*Introdução ao mundo IP<br />
*Verificação das configurações de interfaces<br />
*Verificação de tabelas de roteamento nos hospedeiros e no roteador<br />
*Verificação de roteamento no roteador<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IP%20Basico.pdf Introdução a Camada de Rede]<br />
*[http://tele.sj.ifsc.edu.br/~eraldo/AULAS/2018-2/RCO-INTEGRADO/MACxIP.pdf Endereçamento MAC x Endereçamento IP]<br />
<br />
===Procedimento===<br />
<br />
#Construir uma rede no Netkit com dois PCs e um roteador. Use um arquivo lab.conf da forma: <syntaxhighlight lang=text><br />
r1[type]=router<br />
<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
r1[eth0]=lan0:ip=192.168.200.254/24<br />
r1[eth1]=lan1:ip=192.168.100.254/24<br />
<br />
pc1[eth0]=lan0:ip=192.168.200.1/24<br />
pc1[default_gateway]=192.168.200.254<br />
<br />
pc2[eth0]=lan0:ip=192.168.200.2/24<br />
pc2[default_gateway]=192.168.200.254<br />
<br />
pc3[eth0]=lan1<br />
<br />
pc4[eth0]=lan1:ip=192.168.100.2/24<br />
pc4[default_gateway]=192.168.100.254<br />
</syntaxhighlight><br />
#Chamar o netkit2 (Aplicativos >> Educativo >> Netkit2)<br />
#Forçar a atualização do Netkit2: <syntaxhighlight lang=text> General >> Update </syntaxhighlight><br />
#Carregar o arquivo '''lab.conf''' a partir do Netkit2:<syntaxhighlight lang=bash><br />
File >> Load Only<br />
</syntaxhighlight><br />
#Visualizar a rede a ser implementada:<syntaxhighlight lang=bash><br />
File >> Graph<br />
</syntaxhighlight><br />
#Executar a rede: <syntaxhighlight lang=bash><br />
Network >> Start<br />
</syntaxhighlight><br />
#Copie o diagrama da rede para o papel e, para todas interfaces de rede apresentadas no diagrama, anote, baseados nos comandos dos itens seguintes:<br />
##Endereço IP<br />
##Endereço MAC<br />
##Roteador padrão<br />
#Observar os endereços de hardware (ou MAC) e IP de cada dispositivo na rede. No terminal de cada '''pc''' execute: <syntaxhighlight lang=bash><br />
ifconfig </syntaxhighlight><br />
#Observar e interpretar a tabela de roteamento nos hospedeiros '''pc1''' e '''pc4'''. Identificar os ''default gateways'' em cada '''pc'''.<syntaxhighlight lang=bash><br />
route -n<br />
</syntaxhighlight><br />
#Observar e interpretar a tabela de roteamento no roteador ('''r1''')<syntaxhighlight lang=bash><br />
exit<br />
route -n<br />
</syntaxhighlight><br />
#Observar e "provar" que pacotes indo de '''pc1''' para '''pc4''' são encaminhados ao roteador e, em seguida, entregues ao destino, ou seja, entrega indireta.<br />
#*Use o '''ping''', '''tcpdump''' e seu diagrama de rede como apoio.<br />
#*Lembre-se que você pode verificar o fluxo de dados individualmente em cada interface de rede e, portanto, se certificar que se há ou não pacotes atravessando o roteador:<br />
#**Num primeiro momento em '''r1''':<syntaxhighlight lang=bash><br />
tcpdump -i eth0 -n -e</syntaxhighlight><br />
#**Em seguida, ainda em '''r1''': <syntaxhighlight lang=bash><br />
tcpdump -i eth1 -n -e</syntaxhighlight><br />
#**Ver: [http://www.tcpdump.org/tcpdump_man.html manpage do tcpdump]<br />
#Observar e "provar" que pacotes indo de '''pc1''' para '''pc2''' na '''lan0''' são enviados diretamente para '''pc2''', ou seja, entrega direta.<br />
#*Use o '''ping''' e '''tcpdump''' como apoio, adequando os comandos apresentados no item anterior.<br />
<br />
===Configuração básica de interface de rede===<br />
#Configure a interface de rede no '''pc3'''.<br />
#*O mesmo deverá ser capaz de "pingar" para qualquer outro PC ou ser "pingado".<br />
#*Dica: observe a configuração de rede do '''pc4''' e tente adaptá-la para o '''pc3'''.<br />
#*Dica de ferramentas de configuração: use os comandos '''ifconfig''' e '''route'''. Use o '''man''' ou procure na web como utilizar esses comandos.<br />
#Execute o comando ping do '''pc3''' para o '''pc4'''. Obteve sucesso?<br />
#Execute o comando ping do '''pc3''' para o '''pc1'''. Obteve sucesso?<br />
#Execute o comando ping do '''pc2''' para o '''pc3'''. Obteve sucesso?<br />
<br />
====Referências adicionais====<br />
<br />
* [http://linux-ip.net/html Guia de Administração da Camada IP no Linux<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 14 - Roteamento Estático em Redes }}<br />
<br />
===Objetivo===<br />
<br />
*Proporcionar ao aluno uma visão prática de roteamento IP.<br />
*Princípios de configuração de rotas.<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IP%20Roteamento.pdf Introdução ao Roteamento]<br />
<br />
====PARTE 1 - Rede com 3 roteadores====<br />
<br />
:Laboratório a ser montado no netkit.<br />
<br />
[[Image:LabRoteamento-RCO1-2017-2.png |thumb | 800px| Figura 1 - Rede para roteamento]]<br />
<br />
#Construir a rede apresentada na Figura 1, usando como apoio a configuração do netkit descrita na sequência. As sub-redes (SN) a serem utilizadas na parte 1 e 2 são:<br />
## SN1 : 200.10.1.0/24<br />
## SN2 : 200.10.2.0/24 <br />
## SN3 : 200.10.3.0/24<br />
## SN4 : 200.10.4.0/24<br />
## SN5 : 200.10.5.0/24 <br />
## SN6 : 200.10.6.0/24 <br />
## SN7 : 200.10.7.0/24 <br />
## SN8 : 200.10.8.0/24<br />
#Abaixo o arquivo de configuração para o NetKit. Copie e salve como '''/home/aluno/roteamento.conf'''.<syntaxhighlight lang=text><br />
<br />
H1[type]=generic<br />
H2[type]=generic<br />
<br />
R1[type]=generic<br />
R2[type]=generic<br />
R3[type]=generic<br />
<br />
<br />
H1[eth0]=SN1:ip=200.10.1.1/24<br />
H2[eth0]=SN8:ip=200.10.8.1/24<br />
<br />
R1[eth0]=SN1:ip=200.10.1.254/24<br />
R1[eth1]=SN4:ip=200.10.4.1/24<br />
R1[eth2]=SN2:ip=200.10.2.1/24<br />
<br />
<br />
R2[eth0]=SN8:ip=200.10.8.254/24<br />
R2[eth1]=SN4:ip=200.10.4.2/24<br />
R2[eth2]=SN7:ip=200.10.7.1/24<br />
<br />
R3[eth0]=SN2:ip=200.10.2.2/24<br />
R3[eth1]=SN7:ip=200.10.7.2/24 </syntaxhighlight><br />
#Inicie o Netkit e carregue o arquivo de configuração e execute-o.<br />
#Execute comandos de ping entre os hosts e roteadores.<br />
##O ping entre as interfaces/equipamentos pertencentes a mesma sub-rede funcionam, por quê?<br />
##O ping entre interfaces/equipamentos de sub-redes distintas não funcionam, por quê?<br />
#Usando como apoio os comandos de inserção de rota insira as rotas default em H1 e H2:<br />
##H1: <syntaxhighlight lang=bash> route add default gw 200.10.1.254 </syntaxhighlight><br />
##H2: <syntaxhighlight lang=bash> route add default gw 200.10.8.254 </syntaxhighlight><br />
#Habilitar o roteamento e instalar rotas em cada roteador para que pacotes vindos de H1 para H2 passem por R1, R3 e R2. O retorno deve ser via R2 e R1.<br />
##R1: <syntaxhighlight lang=bash><br />
echo 1 > /proc/sys/net/ipv4/ip_forward<br />
echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth0/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth1/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth2/rp_filter<br />
route add -net 200.10.8.0/24 gw 200.10.2.2 </syntaxhighlight><br />
##R2: <syntaxhighlight lang=bash><br />
echo 1 > /proc/sys/net/ipv4/ip_forward<br />
echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth0/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth1/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth2/rp_filter<br />
route add -net 200.10.1.0/24 gw 200.10.4.1 </syntaxhighlight><br />
##R3: <syntaxhighlight lang=bash><br />
echo 1 > /proc/sys/net/ipv4/ip_forward<br />
echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth0/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth1/rp_filter<br />
route add -net 200.10.8.0/24 gw 200.10.7.1<br />
route add -net 200.10.1.0/24 gw 200.10.2.1 <br />
</syntaxhighlight><br />
#Teste a conectividade IP com o comando ping.<br />
##O ping entre as interfaces/equipamentos pertencentes a mesma sub-rede funcionam, por quê?<br />
##O ping entre interfaces/equipamentos de sub-redes distintas não funcionam, por quê?<br />
#Confirme os caminhos estabelecidos monitorando as interfaces com o tcpdump e/ou traceroute.<br />
<br />
====PARTE 2 - Desafio: Rede com 4 roteadores====<br />
<br />
#Crie um arquivo de configuração que descreva a rede abaixo no '''netkit'''.<br />
##Observe que essa rede tem somente um roteador a mais que a rede apresentada anteriormente.<br />
##As rotas devem ser configuradas de forma que pacotes que trafegam de H1 para H2 passem por R1, R3, R4 e R2.<br />
##O retorno (H2 ==> H1) deve ser por R2, R4 e R1.<br />
##Cada sub-rede SN está em uma rede ethernet separada.<br />
##Chame o professor e mostre que os roteamentos estão sendo realizados corretamente, com o apoio do tcpdump e tracerotue.<br />
<br />
* SN1 : 200.10.1.0/24<br />
* SN2 : 200.10.2.0/24 <br />
* SN3 : 200.10.3.0/24 <br />
* SN4 : 200.10.4.0/24 <br />
* SN5 : 200.10.5.0/24 <br />
* SN6 : 200.10.6.0/24 <br />
* SN7 : 200.10.7.0/24 <br />
* SN8 : 200.10.8.0/24<br />
<br />
[[Image:ExercicioConfEstaticaZebra.png]]<br />
<br />
====PARTE 3 - Criando loop para verificar o campo TTL====<br />
<br />
#Crie um conjunto de rotas que façam que um pacote vindo de H1 para H2 entre em um loop entre R1, R3, R2, R1.<br />
#Envie um pacote único com o ping de H1 para H2.<br />
#Rastreie com o tcpdump o pacote em loop e verifique o momento em que o pacote sai de circulação.<br />
<br />
==Links de Referência==<br />
<br />
* [http://en.wikipedia.org/wiki/Longest_prefix_match Prefixo Mais Longo]<br />
<br />
* [http://jodies.de/ipcalc?host=192.168.20.19&mask1=28&mask2= Calculador IP]<br />
<br />
* [http://linux-ip.net/html Guia de Administração da Camada IP no Linux]<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 15 - Sub-redes}}<br />
<br />
===Objetivos===<br />
*Compreender endereçamento IPv4.<br />
*Compreender o processo de alocação de faixas de IPs.<br />
*Compreender e manipular os números IPs.<br />
*Compreender e manipular as máscaras de rede.<br />
===Fonte Base===<br />
*[https://www.todoespacoonline.com/w/2015/06/calculo-de-sub-redes-ipv4/ Cálculo de Sub-rede IPv4]<br />
<br />
===Exercícios===<br />
#Considere um endereço IP 200.135.233.8/21. Determine:<br />
##O endereço da rede ao qual pertence;<br />
##O endereço de broadcast da rede;<br />
##A faixa de endereçamento que podem ser usados por hospedeiros desta rede.<br />
#Suponha que um administrador de rede tenha recebido o bloco de endereços 200.40.8.0/21 e que deseja dividir este bloco em 8 blocos de endereços iguais, de menor tamanho, para ser alocado a 8 sub-redes administradas por ele.<br />
##Determine o tamanho total do bloco de endereços.<br />
##Determine o tamanho de cada sub-bloco.<br />
##Determine o endereço/máscara de rede de cada sub-rede.<br />
#Quantas estações (''hosts'') uma rede 223.1.10.0/24 suporta? <br />
#Um provedor de acesso com bloco de IPs 200.23.16.0/20 deseja montar 8 sub-redes. Mostre como isso é possível e como ficaria os endereços de cada uma dessas sub-redes.<br />
#Um provedor de acesso a Internet possui o seguinte bloco de endereços IP: 12.17.192.0/18. Os endereços IP de 12.17.192.0 até 12.17.207.255 já estão alocados para clientes deste provedor. Este provedor precisa atender a quatro novos clientes, um deles necessita de rede com pelo menos 1000 endereços de IP válidos e os outros três necessitam de rede com pelo menos 30 IP válidos. Faça uma proposta para alocação de endereços IP para estes clientes. Os endereços reservados para estes novos clientes devem ser alocados a partir da numeração mais baixa disponível. Procure também responder as questões abaixo:<br />
##Qual o total de endereços que dispõe o provedor em questão?<br />
##Quantos endereços IP já estão utilizados?<br />
##Quantos endereços IP este provedor possui livres para alocar aos novos clientes?<br />
##Qual o endereço identificador de cada sub-rede dos novos clientes?<br />
##Qual o a máscara de rede de cada sub-rede dos novos clientes?<br />
##Qual o endereço de broadcast de cada sub-rede dos novos clientes?<br />
##Quantos endereços IP ainda sobrarão ao provedor após atender a estes clientes?<br />
#Um administrador precisa montar uma rede experimental conforme mostrada na Figura 1. Na sub-rede 1 ele precisará instalar cerca 25 ''hosts'', e nas sub-redes 2 e 3 ele precisará instalar cerca de 12 ''hosts''. O administrador dispõe do bloco de endereços IP 192.168.10.0/24 para ser utilizado no endereçamento da rede experimental. Faça uma proposta para alocação de endereços IP para cada sub-rede (rede 1, 2 e 3), incluindo também as sub-redes relativas aos enlaces ponto-a-ponto (rede AB, AC e BC). Responda ainda:<br />
##Qual o endereço identificador de rede de cada sub-rede (1, 2, 3, AB, AC e BC)?<br />
##Qual o a máscara de rede de cada sub-rede (1, 2, 3, AB, AC e BC)?<br />
##Quais os endereços IP que serão atribuídos a cada interface de rede nos enlaces ponto-a-ponto dos roteadores (enlaces relativos as redes AB, AC e BC)? [[Arquivo:CdrEx.png |thumb | 400px| Figura 1 - Rede experimental]]<br />
<br />
*Para conferir seu cálculos utilize, por exemplo, as seguintes ferramentas:<br />
**Terminal Linux: '''ipcalc'''<br />
**Site web: [http://jodies.de/ipcalc ipcalc]<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 16 - Sub-redes e Roteamento Estático em Redes }}<br />
<br />
===Objetivos===<br />
*Compreender endereçamento IPv4.<br />
*Compreender o processo de alocação de faixas de IPs.<br />
*Compreender e manipular os números IPs.<br />
*Compreender e manipular as máscaras de rede.<br />
*Proporcionar ao aluno uma visão prática de roteamento IP.<br />
<br />
===Fonte Básica===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IP_DHCP_NAT.pdf DHCP e NAT]<br />
*[http://www.davidc.net/sites/default/subnets/subnets.html Cálculo de sub-redes]<br />
<br />
===Roteiro===<br />
<br />
#Um administrador precisa montar uma rede experimental conforme mostrada na Figura 1. Na sub-rede 1 ele precisará instalar cerca 50 ''hosts'', e nas sub-redes 2 e 3 ele precisará instalar cerca de 20 ''hosts''. O administrador dispõe do bloco de endereços IP 192.168.10.0/24 para ser utilizado no endereçamento da rede experimental. Faça uma proposta para alocação de endereços IP para cada sub-rede (rede 1, 2 e 3), incluindo também as sub-redes relativas aos enlaces ponto-a-ponto (rede AB, AC e BC). Responda ainda:<br />
##Qual o endereço identificador de rede de cada sub-rede (1, 2, 3, AB, AC e BC)?<br />
##Qual o a máscara de rede de cada sub-rede (1, 2, 3, AB, AC e BC)?<br />
##Quais os endereços IP que serão atribuídos a cada interface de rede nos enlaces ponto-a-ponto dos roteadores (enlaces relativos as redes AB, AC e BC)? [[Arquivo:CdrEx.png |thumb | 400px| Figura 1 - Rede experimental]]<br />
#Baseado no arquivo exemplo abaixo, crie um arquivo de configuração para o NetKit que implemente sua proposta. O arquivo deve contemplar todas as configurações necessárias para o perfeito funcionamento da rede, ou seja, ao carregar o arquivo todos os hosts deverão ser capazes de "pingar" uma ao outro. <br />
##Faça testes de conectividade entre os hosts.<br />
##Demostre para o professor o perfeito funcionamento de sua rede.<br />
*O arquivo de configuração do Netkit abaixo, é a definição para o perfeito funcionamento da simulação da rede apresentada na Figura 2. [[Arquivo:DynamicRoutingTriangle.png |thumb | 400px| Figura 2 - Rede exemplo]]<br />
<syntaxhighlight lang=bash><br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=link0:ip=192.168.0.1/24<br />
pc2[eth0]=link1:ip=192.168.1.1/24<br />
pc3[eth0]=link2:ip=192.168.2.1/24<br />
<br />
# Default gateways definitions<br />
pc1[default_gateway]=192.168.0.254<br />
pc2[default_gateway]=192.168.1.254<br />
pc3[default_gateway]=192.168.2.254<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
r3[type]=gateway<br />
<br />
# Routers' interfaces to local networks<br />
r1[eth0]=link0:ip=192.168.0.254/24<br />
r2[eth0]=link1:ip=192.168.1.254/24<br />
r3[eth0]=link2:ip=192.168.2.254/24<br />
<br />
# Network "backbone" links<br />
r1[eth1]=backbone0:ip=10.0.0.1/30<br />
r1[eth2]=backbone1:ip=10.0.1.1/30<br />
<br />
r2[eth1]=backbone0:ip=10.0.0.2/30<br />
r2[eth2]=backbone2:ip=10.0.2.1/30<br />
<br />
r3[eth1]=backbone1:ip=10.0.1.2/30<br />
r3[eth2]=backbone2:ip=10.0.2.2/30 <br />
<br />
# Routes definition<br />
r1[route]=192.168.2.0/24:gateway=10.0.1.2<br />
r1[route]=192.168.1.0/24:gateway=10.0.0.2<br />
r1[route]=10.0.2.0/30:gateway=10.0.0.2<br />
r2[route]=192.168.0.0/24:gateway=10.0.0.1<br />
r2[route]=192.168.2.0/24:gateway=10.0.2.2<br />
r2[route]=10.0.1.0/30:gateway=10.0.2.2<br />
r3[route]=192.168.0.0/24:gateway=10.0.1.1<br />
r3[route]=192.168.1.0/24:gateway=10.0.2.1<br />
r3[route]=10.0.0.0/30:gateway=10.0.2.1</syntaxhighlight><br />
<br />
===Referencia===<br />
<br />
*[http://www.davidc.net/sites/default/subnets/subnets.html Link Calculador Online de Subnets]<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 17 - Tecnologia de Enlace Ethernet }}<br />
<br />
===Objetivos===<br />
<br />
*Compreender que Ethernet não é Internet e que não é necessário o mundo IP para haver comunicação.<br />
*Diferenciar Hub de Switch<br />
*Compreender o papel do protocolo ARP<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/Camada%20de%20enlace.pdf Camada de Enlace]<br />
<br />
===Animação Pearson/Kurose===<br />
<br />
*[https://media.pearsoncmg.com/aw/ecs_kurose_compnetwork_7/cw/content/interactiveanimations/csma-cd/index.html Animação CSMA/CD]<br />
<br />
===PARTE 1===<br />
<br />
Neste experimento vamos conectar quatro computadores através de um Hub Ethernet. Este dispositivo faz com que todos os computadores se conectem tal como um cabo. Quando um PC envia uma mensagem para outro PC, TODOS os computadores podem ver esta mensagem. Para haver comunicação basta que um computador envie um frame ETHERNET direcionado para o endereço de hardware do computador destino. NÃO é necessário que as interfaces dos computadores estejam configuradas com endereços IP.<br />
<br />
[[Arquivo:RCO-Animacao_HUB.gif | thumb | 400px| Figura 2 - Funcionamento de um Hub]]<br />
<br />
#Contruir um arquivo '''\home\aluno\hub.conf''' com a seguinte configuração <syntaxhighlight lang=bash><br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
pc1[eth0]=lan0<br />
pc2[eth0]=lan0<br />
pc3[eth0]=lan0<br />
pc4[eth0]=lan0<br />
</syntaxhighlight><br />
#Carregar e executar a configuração no Netkit.<br />
#Baixar o arquivo sendraw.py: [http://tele.sj.ifsc.edu.br/~eraldo/AULAS/2018/RCO-INTEGRADO/sendraw.py sendraw.py] para o diretório /home/aluno<br />
#Copiar o arquivo para a Máquina Virtual, no terminal da máquina real digite:<syntaxhighlight lang=bash><br />
cp /home/aluno/sendraw.py /home/aluno/lab/shared </syntaxhighlight><br />
#Identificar o endereço de Hardware (MAC) do PC2. Use o '''ifconfig'''. Note que NÃO existe endereço IPv4 configurado.<br />
#Executar o tcpdump no PC2:<syntaxhighlight lang=bash><br />
tcpdump -i eth0 -e -X -vvv -s 50</syntaxhighlight><br />
#Executar o tcpdump no PC3:<syntaxhighlight lang=bash><br />
tcpdump -i eth0 -e -X -vvv -s 50</syntaxhighlight><br />
#Executar o tcpdump no PC4:<syntaxhighlight lang=bash><br />
tcpdump -i eth0 -e -X -vvv -s 50</syntaxhighlight><br />
#No PC1 enviar uma mensagem para o PC2 usando o endereço de hardware identificado anteriormente, <span style="color: red;">lembre-se se substituir o ENDERECO_MAC pelo MAC adequado:<syntaxhighlight lang=bash><br />
python /hostlab/shared/sendraw.py -d ENDERECO_MAC -i Alo-Mundo</syntaxhighlight> <span style="color: black;"><blockquote style="background: lime; border: 1px solid black; padding: 1em;"> Observe que a mensagem chega a todos os PCs embora foi enviada somente para o PC2. </blockquote><br />
#O que explica o comportamento de broadcast para esse caso?<br />
#Pode existir colisão em um sistema com HUBs simples como este do experimento?<br />
<br />
===PARTE 2 - Explorando o SWITCH e o endereço de Broadcast Ethernet===<br />
<br />
[[Arquivo:RCO-Animacao_SWITCH.gif | thumb | 370px| Figura 2 - Funcionamento de um Switch]]<br />
<br />
#Construir um arquivo '''/home/aluno/switch.conf''' com a seguinte configuração: <syntaxhighlight lang=bash><br />
switchA[type]=switch<br />
<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
switchA[eth0]=port0<br />
switchA[eth1]=port1<br />
switchA[eth2]=port2<br />
switchA[eth3]=port3<br />
<br />
pc1[eth0]=port0<br />
pc2[eth0]=port1<br />
pc3[eth0]=port2<br />
pc4[eth0]=port3<br />
</syntaxhighlight><br />
#Carregar e executar a configuração no Netkit.<br />
#Baixar o arquivo sendraw.py do site: [http://tele.sj.ifsc.edu.br/~eraldo/AULAS/2018/RCO-INTEGRADO/sendraw.py sendraw.py] para o /home/aluno.<br />
#Copiar o arquivo para a Máquina Virtual. No terminal da máquina real digite:<syntaxhighlight lang=bash><br />
cp /home/aluno/sendraw.py /home/aluno/lab/shared/ </syntaxhighlight><br />
#Identificar o endereço de Hardware (MAC) do PC2. Use o ifconfig. Note que NÃO existe endereço IPv4 configurado<br />
#Executar o tcpdump no PC2, PC3 e PC4 com o comando:<syntaxhighlight lang=bash><br />
tcpdump -i eth0 -e -X -vvv -s 50</syntaxhighlight><br />
#No PC1 enviar uma mensagem para o PC2 usando o endereço de hardware identificado anteriormente, <span style="color: red;">Lembre-se se substituir o ENDERECO_MAC pelo MAC adequado:<syntaxhighlight lang=bash><br />
python /hostlab/shared/sendraw.py -d ENDERECO_MAC -i Alo-Mundo </syntaxhighlight> <span style="color: black;"><blockquote style="background: lime; border: 1px solid black; padding: 1em;"> Agora somente o PC2 deve receber pois o ''switch'' entrega o quadro somente para a porta de saída associada ao respectivo MAC destino. </blockquote><blockquote style="background: red; border: 1px solid black; padding: 1em;"> CASO todos tenham recebido, é devido ao fato que por algum motivo o switch ainda não aprendeu quem está conectado nas portas. Neste caso envie pacotes do PC2 para o PC1 e depois retome o experimento do item 4. </blockquote><br />
#No PC1 enviar uma mensagem em broadcast (endereço FF:FF:FF:FF:FF:FF)<syntaxhighlight lang=bash><br />
python /hostlab/shared/sendraw.py -d FF:FF:FF:FF:FF:FF -i Mensagem_Broadcast </syntaxhighlight><br />
<blockquote style="background: lime; border: 1px solid black; padding: 1em;"><br />
Note que neste caso todos os computadores recebem a mensagem em ''broadcast'', mesmo sendo um '''switch'''.<br />
</blockquote><br />
<br />
===PARTE 3 - Explorando o ARP===<br />
<br />
O protocolo ARP serve como apoio para descoberta do endereço MAC dado que se sabe o endereço IP de uma máquina. Quando um PC deseja enviar um pacote IP para uma máquina na rede local, ele necessita descobrir o endereço MAC desta máquina. O protocolo ARP usa o broadcast ETHERNET para perguntar para todas as máquinas na rede QUEM tem o endereço IP em questão. A máquina que possui o endereço responderá informando o seu MAC.<br />
<br />
#Configure endereços IP em todas as máquinas do laboratório anterior. Use exemplo a rede 10.10.10.0/24<br />
#Rode o wireshark no '''PC2''' com os procedimentos:<br />
##Clique sobre a aba do '''PC2'''.<br />
##Menu: Wireshark >> any<br />
#Faça um ping do PC1 no PC2 e observe a sequência de pacotes trocados. Faça um diagrama no tempo mostrando a troca de pacotes até a realização do ECHO REQUEST do ping. Os resultados do Wireshark devem ser similares a: [[Arquivo:RCO-TelaARP.jpg | 700px| Troca de pacotes ARP e PING]]<br />
#Confira o cache do arp no PC1 fazendo:<syntaxhighlight lang=bash><br />
arp -a</syntaxhighlight><br />
#Confira o cache do arp no PC2 fazendo:<syntaxhighlight lang=bash><br />
arp -a</syntaxhighlight><br />
#Faça um ping do PC1 no PC3.<br />
#Confira novamente o cache do arp no PC1 fazendo:<syntaxhighlight lang=bash><br />
arp -a</syntaxhighlight><br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 18 - IPv6: Endereços e ''Neighbor Discovery''}}<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IPv6.pdf IPv6]<br />
<br />
Fontes Extras<br />
*Este roteiro foi baseado no material disponível no Livro - [http://www.paulogurgel.com.br/ Laboratório de IPv6].<br />
*[http://docente.ifsc.edu.br/odilson/RED29004/enderec-v6.pdf Guia didático de endereçamento IPv6] obtido de http://ipv6.br/.<br />
<br />
===Objetivos do laboratório:===<br />
*Um primeiro contato com o protocolo [https://pt.wikipedia.org/wiki/IPv6 IPv6].<br />
*Compreender o funcionando do ''Neighbor Discovery'', o equivalente ao ARP (''Address Resolution Protocol'') do IPv4, que em resumo é uma tabela contendo a relação ente IPs e MACs.<br />
*Aprender configurações básicas de interfaces IPv6 no Linux.<br />
<br />
===Introdução teórica===<br />
Obs.: texto copiado literalmente de: [http://ipv6.br/lab/ Laboratório de IPv6].<br />
<br />
A '''descoberta de vizinhança''' por meio do protocolo ''Neighbor Discovery'' no<br />
IPv6 é um procedimento realizado pelos nós de uma rede para descobrir endereços físicos dos dispositivos vizinhos presentes no mesmo enlace. A função deste protocolo se assemelha à função do ARP e do RARP no IPv4.<br />
*O procedimento é iniciado quando um dispositivo tenta enviar um pacote cujo endereço físico de destino é desconhecido. O nó solicitante envia uma mensagem ''Neighbor Solicitation'' (NS) para todos os nós do enlace pertencentes ao grupo ''multicast solicited-node'' (ff02::1:ffXX:XXXX), de modo que XX:XXXX são os últimos 24 bits do endereço IPv6 em que está interessado.<br />
*É possível notar que, por uma coincidência dos últimos 24 bits, é bastante provável que apenas o nó de destino faça realmente parte deste grupo. Isto é um ''truque'' interessante do IPv6 para diminuir o tráfego deste tipo de pacote na rede.<br />
*Na mensagem NS, o endereço IPv6 a ser resolvido é informado no campo ''Target''. O campo ''Source link-layer address'' informa ao nó de destino o endereço MAC do nó de origem, poupando-o de ter que fazer o mesmo procedimento no sentido inverso.<br />
*O nó de destino, dono do IPv6 requisitado, ao receber este pacote, envia uma mensagem ''Neighbor Advertisement'' (NA) como resposta diretamente ao nó requisitante. O seu endereço físico será informado no campo ''Target link-layer address''.<br />
*A informação de mapeamento entre endereços IP e endereços físicos é armazenada em uma tabela chamada ''neighbor cache''. Nela também fica registrado o ''status'' de cada destino, informando se o mesmo é alcançável ou não.<br />
<br />
===Roteiro de atividades: ETAPA 1===<br />
<br />
A figura abaixo apresenta o diagrama esquemático da rede a ser montada/analisada. Observe que todos os IPv6 ''Global Unicast'' já estão definidos na mesma, são esses IPs que utilizaremos em nosso experimento.<br />
<br />
[[Arquivo:Diagrama_rede_IPv6.jpg]]<br />
<br />
#Crie em seu computador um arquivo com nome '''/home/aluno/IPv6.conf''', com o seguinte conteúdo: <syntaxhighlight lang=bash><br />
#Ligacao das maquinas nos dominios de colisao<br />
#Duas pequenas redes interligadas pelo backbone<br />
<br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=link0:ipv6=2001:bcc:faca:1::101/64<br />
pc2[eth0]=link1:ipv6=2001:bcc:cafe:1::102/64<br />
pc3[eth0]=HUB1:ipv6=2001:bcc:1f0:1::103/64<br />
pc4[eth0]=HUB1<br />
<br />
#Default Gateways definitions<br />
pc1[route]=default6:gateway=2001:bcc:faca:1::1<br />
pc2[route]=default6:gateway=2001:bcc:cafe:1::1<br />
pc3[route]=default6:gateway=2001:bcc:1f0:1::1<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
#Routers interfaces definitions<br />
r1[eth0]=backbone0:ipv6=2001:db8:dead:1::1/64<br />
r1[eth1]=link0:ipv6=2001:bcc:faca:1::1/64<br />
r1[eth2]=link1:ipv6=2001:bcc:cafe:1::1/64<br />
<br />
r2[eth0]=backbone0:ipv6=2001:db8:dead:1::2/64<br />
r2[eth1]=HUB1:ipv6=2001:bcc:1f0:1::1/64<br />
<br />
#Routers definitions<br />
r1[route]=2001:bcc:1f0:1::0/64:gateway=2001:db8:dead:1::2<br />
r2[route]=2001:bcc:faca:1::0/64:gateway=2001:db8:dead:1::1<br />
r2[route]=2001:bcc:cafe:1::0/64:gateway=2001:db8:dead:1::1<br />
</syntaxhighlight><br />
#Tenha certeza que o Netkit2 estja atualizado: General >> Update.<br />
#Rode o NetKit em seu computador. Em um terminal digite: <syntaxhighlight lang=bash><br />
netkit2 & </syntaxhighlight><br />
#No menu '''File''' - '''Load and Run''', procure o arquivo '''/home/aluno/IPv6.conf''' e clique em OK. Abrirá uma janela com 6 abas, onde cada uma delas é um terminal de configuração do respectivo equipamento: '''pc1-4''' ou '''r1-2'''.<br />
#Observe que o '''pc4''' não está com sua interface configurada.<br />
#Ao clicar no menu '''File''' - '''Graph''', pode-se ter uma visão da rede a ser simulada e conferir se é equivalente ao diagrama proposto.<br />
#Faça um '''ping6''' entre o '''pc1''' ao '''pc3''': <syntaxhighlight lang=bash><br />
ping6 -c4 2001:bcc:1f0:1::103 </syntaxhighlight><br />
#Faça um '''ping6''' entre o '''pc1''' e '''pc2'''.<br />
#No '''pc4''' use o seguinte comando para adicionar o endereço IPv6 à interface de rede: <syntaxhighlight lang=bash><br />
ip addr add 2001:bcc:1f0:1::104/64 dev eth0 </syntaxhighlight><br />
#No '''pc4''', acrescente o ''default gateway'' com o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add default via 2001:bcc:1f0:1::1 dev eth0 </syntaxhighlight><br />
#No '''pc1''' use o seguinte comando para verificar como ficou a configuração dos endereços da interface de rede. O resultado é similar ao apresentado pelo comando '''ifconfig''': <syntaxhighlight lang=bash><br />
ip addr show dev eth0 </syntaxhighlight><br />
#Todo o roteamento está pronto, mas caso desejássemos poderíamos acrescentar rotas com comando similares aos já utilizados. Por exemplo, no '''r1''', para adicionar uma rota estática para a rede dos '''pc3''' e '''pc4''' utilizaríamos o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add 2001:bcc:1f0:1::/64 via 2001:db8:dead:1::2 dev eth0 </syntaxhighlight><br />
#Confira as rotas estabelecidas em todos os ''hosts'' com o comando abaixo. <br />
##São coerentes com os dados apresentados no diagrama acima?<syntaxhighlight lang=bash><br />
ip -6 route show </syntaxhighlight><br />
#No '''pc1''' use os seguintes comandos para ver a rota para alguns vizinhos: <syntaxhighlight lang=bash><br />
traceroute6 2001:bcc:1f0:1::103<br />
traceroute6 2001:bcc:1f0:1::104 </syntaxhighlight><br />
#*Anote as rotas.<br />
#Deixe um '''ping6''' entre o '''pc1''' ao '''pc3''' rodando: <syntaxhighlight lang=bash><br />
ping6 2001:bcc:1f0:1::103 </syntaxhighlight><br />
#Rode o wireshark no '''r1''' com os procedimentos:<br />
##Clique sobre a aba do '''r1'''.<br />
##Menu: Wireshark >> any<br />
#Analisando a captura do Wireshark, você verá os pacotes relativos ao ping6 e também pacotes parecidos com: <syntaxhighlight lang=bash> fe80::4cd6:19ff:fedc:2b52 2001:db8:dead:1::1 ICMPv6 86 Neighbor Solicitation for 2001:db8:dead:1::1 from 4e:d6:19:dc:2b:52<br />
2001:db8:dead:1::1 fe80::4cd6:19ff:fedc:2b52 ICMPv6 78 Neighbor Advertisement 2001:db8:dead:1::1 (rtr, sol) </syntaxhighlight><br />
#Explique o processo de descoberta de vizinhança (''Neighbor Discovery'' / ''Neighbor Solicitation'' - '''NS''' e ''Neighbor Advertisement'' - '''NA'''), citando o endereço '''link local''' utilizado.<br />
#*Alguns exemplos de campos visualizáveis para uma mensagem do tipo ''Neighbor Advertisement'':<br />
##Destination (camada Ethernet)<br />
##*O endereço MAC do nó requisitante que foi obtido por meio da mensagem NS enviada anteriormente.<br />
##Source (camada Ethernet)<br />
##*A origem é o endereço MAC da interface do dispositivo que enviou a resposta.<br />
##Type (camada Ethernet)<br />
##*Indica que a mensagem utiliza IPv6.<br />
##Next header (camada IPv6)<br />
##*Indica qual é o próximo cabeçalho. Neste caso, o valor 58 (0x3a) refere-se a uma mensagem ICMPv6.<br />
##Source (camada IPv6)<br />
##*A origem é o endereço IP da interface diretamente ligada ao enlace em que a requisição foi recebida.<br />
##Destination (camada IPv6)<br />
##*Diferentemente da mensagem NS, a mensagem NA possui como destino o endereço IPv6 global do nó requisitante.<br />
##Type (camada ICMPv6)<br />
##*Indica que a mensagem é do tipo 136 (Neighbor Advertisement).<br />
##Flags (camada ICMPv6)<br />
##*Uma mensagem NA possui três flags:<br />
###Indica se quem está enviando é um roteador. Neste caso, o valor marcado é 0, pois não é um roteador.<br />
###Indica se a mensagem é uma resposta a um NS. Neste caso, o valor marcado é 1, pois é uma resposta.<br />
###Indica se a informação carregada na mensagem é uma atualização de endereço de algum nó da rede. Neste caso, o valor marcado é 1, pois está informando o endereço pela primeira vez.<br />
##Target Address (camada ICMPv6)<br />
##*Indica o endereço IP associado às informações das flags. Neste caso, é o próprio endereço da interface do dispositivo em questão.<br />
##ICMPv6 option (camada ICMPv6)<br />
##*Indica as opções do pacote ICMPv6:<br />
###Target link-layer address<br />
##Type<br />
##*Indica o tipo de opção. Neste caso, Target link-layer address.<br />
##Link-layer address<br />
##*Indica o endereço MAC da interface do dispositivo em questão.<br />
#Em todos os ''hosts'' rode o comando <syntaxhighlight lang=bash> ip -6 neighbor show </syntaxhighlight><br />
##Qual é a funcionalidade desse comando?<br />
##Qual é o significado do conteúdo dessa tabela?<br />
##A tabela mostrada em cada um dos casos é compatível com o diagrama da rede montado?<br />
##Por que, por exemplo, na tabela do '''pc3''' não há uma referência explícita ao '''pc1'''?<br />
<br />
===Roteiro de atividades: ETAPA 2 - DESAFIO===<br />
<br />
Acrescentar um terceiro roteador ligado a R1 e R2 (backbone0). Acrescentar uma rede ethernet ligada a este roteador. Configure a rede com endereços IPv6 colocando pelo menos um PC adicional. Acrescente os roteamentos necessários para que este PC seja pingável a partir de PC1.<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 19 - Configurando uma Rede Doméstica}}<br />
<br />
===Objetivos===<br />
*Entender os componentes e princípio de funcionamento de uma rede residencial.<br />
*Configurar um roteador sem fio.<br />
*Testa a rede configurada através do acesso da mesma via Telefone Celular.<br />
<br />
===Fonte Base===<br />
<br />
*[https://esr.rnp.br/publicacoes/sistemas/proinfo?download=d2ddea18f00665ce8623e36bd4e3c7c5 Livro da Escola Superior de Redes (ESR): Formação de suporte técnico PROINFO]<br />
<br />
===Analisando o roteador===<br />
#Roteador ??????. Descrição Geral do aparelho: <br />
##Fonte de alimentação. Cuidar com tensão cc e polaridade.<br />
##Porta WAN (''Wide Area Network'')<br />
##Portas LAN (''Local Area Network'')<br />
##Antena ou antenas <br />
##Botão reset. Normalmente configura LAN em 192.168.0.0/24 ou 192.168.1.0/24<br />
##Parte frontal, LEDs: Power, Status, WAN, WLAN, 1...4.<br />
#Descrição dos modos de uso básicos.<br />
#Ligar o aparelho na tomada.<br />
##LED Power acendeu?<br />
<br />
====Montando uma rede básica====<br />
#Conectar o computador numa das portas LAN do roteador sem fio.<br />
#Conectar a porta WAN num dos pontos de rede do laboratório.<br />
#Pressionar o botão Reset.<br />
#Teste a rede de seu computador, caso não esteja funcionando desconecte e reconecte o cabo de rede entre seu computador e uma porta LAN do roteador sem fio.<br />
#Com o navegador acesse 192.168.0.1. '''Usuário: admin''', '''senha: em branco'''. Caso não consiga acesso, pressione novamente o botão reset.<br />
#Redefina a senha do administrador do roteador para RCO60803.<br />
#Aba Home:<br />
##Clique no menu esquerdo WAN. Discutir a funcionalidade.<br />
##Clique no menu esquerdo LAN. Discutir a funcionalidade.<br />
##Clique no menu esquerdo DHCP. Discutir a funcionalidade.<br />
##Clique no menu esquerdo Wireless. Discutir a funcionalidade.<br />
##Clique no menu esquerdo Wizard. Discutir a funcionalidade.<br />
#Aba Status:<br />
##Device Info. Discutir a funcionalidade.<br />
##Wireless. Discutir a funcionalidade.<br />
#Reconfigure o roteador sem fio para alugar os endereços 192.168.X.20-60, onde X é igual ao último dígito do número IP de sua máquina. Por exemplo, para a máquina 192.168.1.7, X=7.<br />
#Para verificar o funcionamento, num terminal da máquina (real) execute o comando abaixo. Caso tudo esteja funcionando corretamente, sua máquina configurará uma nova interface de rede com o número IP fornecido por seu roteador ou um roteador de um colega. <syntaxhighlight lang=bash> sudo dhclient eth0:0 </syntaxhighlight><br />
#Reconfigure o WiFi de seu roteador:<br />
##Troque o SSID (''Service Set IDentifier'') de seu roteador, colocando seu primeiro nome como nome de rede.<br />
##Configure a segurança para WPA2 (''Wireless Security Setup'').<br />
##Ajuste a senha para RCO60803 (respeite as maiúsculas).<br />
##Salve e reinicie o roteador para as alterações terem validade.<br />
#Teste a configuração, acessando a sua rede sem fio através de seu telefone celular.<br />
<br />
{{Collapse bottom}}<br />
<br />
==Projeto Final==<br />
{{Collapse top |Descrição do Projeto}}<br />
<br />
===Objetivos===<br />
<br />
*Aplicar os conhecimentos adquiridos durante o curso de redes através da confecção de uma rede múltiplos domínios simulando a Internet.<br />
**Dado uma topologia de rede definida a um grupo, calcular as sub-redes de acordo com os requisitos colocados;<br />
**Implementar a proposta de sub-redes no arquivo de configuração do netkit de tal modo a rede ficar plenamente operacional;<br />
**Estabelecer um roteamento global entre todos os domínios das equipes;<br />
**Estabelecer um serviço WEB sobre a rede construída;<br />
**Construir páginas WEB de acordo com os requisitos;<br />
**Estabelecer um serviço de configuração automática de hospedeiros (DHCP);<br />
<!--**Estabelecer um serviço de conexão sem fio sobre cada domínio.--><br />
**Trabalhar o conceito de ''shell script'' para automatizar tarefas.<br />
<br />
A arquitetura da rede é mostrada na Figura abaixo. <br />
<br />
[[Image:RCO3-TrabalhoFinal-2017-2.png|500px]]<br />
<br />
===Especificações do Projeto===<br />
<br />
#Fazer um desenho da '''topologia''' do domínio com todos IPs alocados e apresentar os cálculos das subredes conforme restrições abaixo. <br />
##Construir as tabelas de roteamento para que a rede fique plenamente operacional. Apresentar as '''tabelas de roteamento na página WEB do projeto''';<br />
##Apresentar o desenho da '''topologia na página WEB do projeto'''. Utilize o modelo ao lado. Observe que o modelo está propositalmente incompleto; [[Image:Modelo_de_diagrama_do_projeto.png|300px]]<br />
##Enlaces ponto-a-ponto devem obrigatoriamente ter máscara /30;<br />
##Enlaces multiponto devem obrigatoriamente comportar no mínimo 50 hospedeiros;<br />
##Todas as rotas devem ser colocadas no arquivo '''projeto.conf''' do netkit. Apresentar esse arquivo na '''página WEB do projeto''';<br />
#Na sub-rede onde existe um cliente (notebook) acrescentar um servidor '''[[Netkit2#Usando_DHCP | DHCP]]''' (máquina adicional) com os seguintes requisitos:<br />
##Com uma faixa de aluguel de pelo menos 5 números IP;<br />
##Explicar a configuração do '''DHCP na página WEB do projeto''';<br />
#Estabelecer o serviço '''Apache''' no servidor previsto no domínio com os seguintes requisitos:<br />
##uma página WEB com a descrição integral do projeto;<br />
##uma segunda página WEB com conteúdo de sua preferência com os seguintes requisitos:<br />
###a página deve ser em inglês ou espanhol;<br />
###texto com no mínimo 500 palavras; <br />
###no mínimo uma figura deve aparecer;<br />
###no mínimo um link para uma página WEB de uma outra equipe.<br />
##Todas as páginas devem devem ser mantidas em um diretório de nome ''/home/aluno/lab/shared/WEB''.<br />
##Elaborar um ''shell script'' para automação do serviço WEB. Sítio para treinamento de [http://www.compileonline.com/execute_bash_online.php shell script]. <br />
#O '''roteamento global''' deve permitir conectividade entre todas as equipes. Para evitar possíveis erros advindos de filtros do Netkit2, execute os seguintes comandos em todos os seus roteadores (copie e cole): <syntaxhighlight lang=bash><br />
echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth0/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth1/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth2/rp_filter <br />
echo 0 > /proc/sys/net/ipv4/conf/eth3/rp_filter </syntaxhighlight><br />
<br />
* Exemplo de arquivo '''projeto.conf'''.<br />
**No roteiro do '''Laboratório 16''' também é apresentado um arquivo de configuração de uma rede plenamente funcional para o Netkit, utilize-o como exemplo para entendimento das configurações requisitadas.<br />
**O arquivo deverá ser adaptado para a topologia de cada equipe.<br />
<syntaxhighlight lang=bash><br />
H1[type]=generic<br />
H2[type]=generic<br />
<br />
R1[type]=gateway<br />
R2[type]=gateway<br />
R3[type]=gateway<br />
<br />
H1[eth0]=SR2:ip=10.9.2.2/24<br />
H1[default_gateway]=10.9.2.1<br />
<br />
H2[eth0]=SR4:ip=10.9.4.2/24<br />
H2[default_gateway]=10.9.4.1<br />
<br />
R1[eth0]=uplink:bridge=eth0:ip=192.168.1.190/24<br />
R1[eth1]=SR1:ip=10.9.1.1/24<br />
R1[eth2]=SR5:ip=10.9.5.1/24<br />
R1[route]=10.9.2.0/24:gateway=10.9.1.2<br />
R1[route]=10.9.4.0/24:gateway=10.9.5.2<br />
<br />
R2[eth0]=SR1:ip=10.9.1.2/24<br />
R2[eth1]=SR2:ip=10.9.2.1/24<br />
R2[eth2]=SR3:ip=10.9.3.1/24<br />
R2[default_gateway]=10.9.1.1<br />
<br />
R3[eth0]=SR3:ip=10.9.3.2/24<br />
R3[eth1]=SR4:ip=10.9.4.1/24<br />
R3[eth2]=SR5:ip=10.9.5.2/24<br />
R3[default_gateway]=10.9.5.1<br />
</syntaxhighlight><br />
<br />
*Como trabalhar com o shell script<br />
<br />
#O shell script será executado na máquina virtual do apache, e portanto deverá ser copiado para o /home/aluno/shared/lab/config_apache.sh<br />
##Na máquina virtual do apache deve-se tornar o arquivo do script executável e em seguida executá-lo:<syntaxhighlight lang=bash><br />
chmod +x /hostlab/shared/config_apache.sh<br />
/hostlab/shared/config_apache.sh <br />
</syntaxhighlight><br />
<br />
* Exemplo de arquivo ''shell script''. Este arquivo deve ser adaptado para a topologia de cada equipe. <br />
<br />
#Editar o arquivo com gedit com nome ''config_apache.sh''. Qualquer comando executado no terminal pode ser colocado com exata sintaxe no ''shell script'', e vários comandos podem ser colocados em várias linhas.<br />
#Construir o arquivo da forma:<br />
<syntaxhighlight lang=bash><br />
#!/bin/bash<br />
#comentario: copiar um arquivo<br />
cp /home/aluno/teste.txt /var/www<br />
<br />
#renomeando o arquivo copiado teste.txt para index.html<br />
mv /var/www/teste.txt /var/www/index.html<br />
<br />
#iniciando um serviço<br />
/etc/init.d/ssh start<br />
</syntaxhighlight><br />
<br />
*Dar permissão de execução do script no Apache<br />
<br />
Copiar o script para o /home/aluno/lab/shared e apartir do Apache fazer:<br />
Dar direito de execução do script:<br />
<br />
chmod 777 /hostlab/shared/config_apache.sh<br />
<br />
*Executar o script no apache<br />
/hostlab/shared/config_apache.sh<br />
<br />
<br />
* Teste do acesso ao Servidor Apache a partir da linha de comando:<br />
<br />
Note que como todas as máquinas virtuais do netkit são em modo de comando (não tem interface gráfica) então o uso de browsers para teste<br />
do acesso a páginas html fica limitado. Entretanto, para teste rápido é possível usar o comando lynx:<br />
<br />
lynx IP_SERVIDOR_APACHE<br />
<br />
Note que o servidor deve ter conectividade IP (faça ping antes para testar);<br />
<br />
* Acesso pleno as páginas html a partir da Virtualbox<br />
<br />
Um problema que nos deparamos ao usar o netkit para acesso de páginas hospedadas em suas Máquinas Virtuais é o fato de não termos a interface gráfica. Uma interface gráfica é necessária para um browser do tipo Firefox. Uma alternativa é o uso de browser em modo texo do tipo "lynx". Para testes rápidos pode ser interessante mas para visualizarmos em plenitude a página não é a melhor solução.<br />
<br />
Para contornar este problema vamos usar uma máquina VirtualBox que estará conectada na rede do laboratório. Faremos o default gateway desta máquina apontar para o roteador de borda do domínio da equipe garantindo que a mesma conduza todo o tráfego indireto para este roteador. Para garantir que exista rota reversa vamos colocar em cada roteador do domínio uma rota default gateway para o roteador de borda. Vamos elaborar passo a passo estes procedimentos:<br />
<br />
#Iniciar na máquina real uma VirtualBox com Ubuntu e Interface Gráfica;<br />
#Abrir um terminal e verificar a rota para o default gateway usando:<syntaxhighlight lang=bash>route -n </syntaxhighlight><br />
#Adicionar uma rota para a sua rede: <syntaxhighlight lang=bash> sudo route add -net 10.X.0.0/16 gw 192.168.1.XX </syntaxhighlight> onde 192.168.1.XX é o endereço externo do roteador de borda do domínio onde está o servidor APACHE.<br />
#Para garantir a rota reversa vamos colocar rotas ''default'' também nos roteadores dos domínios (roteadores no netkit). Para tanto coloque no projeto.conf esta informação de rota para cada roteador que não está na borda: <syntaxhighlight lang=bash> Rx[route]=default:gateway=Y.Y.Y.Y <br />
ou<br />
Rx[default_gateway]=Y.Y.Y.Y<br />
</syntaxhighlight>onde Y.Y.Y.Y é uma interface do roteador de borda ligado a Rx ou, caso não esteja diretamente ligado a este, deve ser um endereço de roteador vizinho que tenha rota para o roteador de borda.<br />
{{Collapse bottom}}<br />
<br />
==Listas de Exercícios==<br />
{{Collapse top |Lista de exercícios 1 - Introdução}}<br />
<br />
#Qual é a diferença entre um hospedeiro e um sistema final? Cite os tipos de sistemas finais. Um servidor web é um sistema final?<br />
#O que caracteriza um protocolo? Dê um exemplo de um protocolo.<br />
#Por que os padrões são importantes para os protocolos?<br />
#O que é um programa cliente? O que é um programa servidor? Um programa servidor requisita e recebe serviços de um programa cliente? <br />
#Quais são os dois tipos de serviços de transporte que a Internet provê às suas aplicações? Cite algumas características de cada um desses serviços. (pg.38)<br />
#Explique o que é e quais são as vantagens de uma rede de comutação de circuitos em relação a uma rede de comutação de pacotes? <br />
#O que é uma rede de acesso?<br />
#FTTH, HFC e ADSL são usados para acesso residencial. Para cada uma dessas tecnologias de acesso, cite uma faixa de taxas de transmissão e comente se a largura de banda é compartilhada ou dedicada.<br />
#Cite tecnologias de acesso residencial disponíveis na grande Florianópolis. Para cada tipo de acesso, apresente a taxa de ''downstream'', a taxa de ''upstream'' e o preço mensal anunciados.<br />
#Qual é a taxa de transmissão de LANs Ethernet?<br />
#Porque dividimos a arquitetura da Internet (e de redes de comutação de pacotes em geral) em camadas? Por que dizemos que uma camada inferior presta um serviço a camada superior?<br />
#Quais são as cinco camadas da pilha de protocolo da Internet? Quais as principais responsabilidades de cada uma dessas camadas? <br />
#O que significa o processo de encapsulamento e desencapsulamento de pacotes no contexto da rede organizada em camadas?<br />
#O que é uma mensagem de camada de aplicação? Um segmento da camada de transporte? Um datagrama da camada de rede? Um quadro de camada de enlace? Qual a relação entre eles?<br />
#Que camadas da pilha de protocolo da Internet um roteador implementa? Que camadas um comutador de enlace implementa? Que camadas um sistema final implementa?<br />
#Imagine que você queira enviar, com urgência, 40 terabytes de dados de São José a Manaus. Você tem disponível um enlace dedicado de 100 Mbps para a transferência de dados. Você escolheria transferir os dados pelo enlace ou mandar mídias por Sedex 10? Explique.<br />
#Para pensar I: um celular tipo smartphone acessa normalmente quantas redes? Quais tecnologias sao usadas? Elas são de comutação de pacotes ou de circuitos?<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Lista de exercícios 2 - Camada de Aplicação}}<br />
#Relacione cinco aplicações da Internet não proprietárias e os protocolos da camada de aplicação que elas usam. <br />
#Qual é a diferença entre arquitetura de rede e arquitetura de aplicação? <br />
#De que modo um mensageiro instantâneo é um híbrido das arquiteturas cliente-servidor e P2P? <br />
#Para uma sessão de comunicação entre um par de processos, qual processo é o cliente e qual é o servidor? <br />
#Que informação é usada por um processo que está rodando em um hospedeiro para identificar um processo que está rodando em outro hospedeiro? <br />
#Porque o HTTP, FTP, SMTP, POP3 e IMAP rodam sobre TCP e não sobre UDP? <br />
#Por que se diz que o FTP envia informações de controle “fora da banda”? <br />
#Suponha que Aline envie uma mensagem a Eduardo por meio de uma conta de e-mail da web (como o gmail), e que Eduardo acesse seu e-mail por seu servidor utilizando POP3. Descreva como a mensagem vai do hospedeiro Aline até o hospedeiro de Eduardo. Não se esqueça de relacionar a série de protocolos de camada de aplicação usados para movimentar as mensagens entre os hospedeiros.<br />
#Em uma aplicação de compartilhamento de arquivos P2P, você concorda com a afirmação: ”não existe nenhuma noção de lados cliente e servidor de uma sessão de comunicação”? Por que sim ou por que não? <br />
#Relacione alguns agentes de usuário de aplicação de rede que você utiliza no dia-a-dia. <br />
#Considere um site de comércio eletrônico que quer manter um registro de compras para cada um de seus clientes. Descreva como isso pode ser feito com cookies. <br />
#Descreva uma aplicação que requeira “não perda de dados” e seja também altamente sensível ao atraso.<br />
#Quais informações básicas estão em um cabeçalho do pacote IP?<br />
#Um pacote IP pode ser colocado diretamente na rede física? Ele chegará a seu destino?<br />
#Os pacotes ECHO request e ECHO reply são de que protocolo? Eles trafegam dentro de qual pacote?<br />
#Para pensar II: Quando você usa o uma aplicação tipo whatsapp para conversação você está usando rede de comutação de circuitos ou de pacote?<br />
<br />
ADICIONAIS PARTE 2- HTTP<br />
<br />
#Cite pelo menos dois clientes http.<br />
#O que é o servidor Apache?<br />
#O protocolo http deve se executar em todos os roteadores do caminho entre cliente e servidor? Explique.<br />
#Se um hospedeiro colocar um pacote de aplicação HTTP diretamente na rede física ele chegará a seu destino?<br />
#Considere que um cliente acessa uma página HTML de servidor WEB e nesta página existem dois links para dois objetos JPG que residem no mesmo servidor. Quantos comandos GETS no total deveriam ser realizados pelo cliente? Todos eles serão realizados sobre a mesma conexão TCP?<br />
#Em uma página HTML pode existir um link para um objeto que esteja armazenado em outro site? O que o browser deve fazer neste caso? <br />
#No pacote http de resposta de um servidor normalmente existem duas partes. Quais são elas?<br />
#Imagine que uma página html está sendo mostrada para o usuário cliente. Se o usuário pedir para que a página seja atualizada, o browser vai requisitar o objeto novamente? O servidor vai retornar o objeto mesmo que ele não tenha sido alterado?<br />
#O que é um cookie? Considere um site de comércio eletrônico que quer manter um registro de compras para cada um de seus clientes. Descreva como isso pode ser feito com cookies.<br />
#Qual é a diferença entre HTTP persistente com ''pipelining'' e HTTP persistente sem ''pipelining''. Qual dos dois é utilizado pelo HTTP/1.1? <br />
#Descreva como o cache Web pode reduzir o atraso na recepção de um objeto desejado. O cachê Web reduzirá o atraso para todos os objetos requisitados por um usuário ou somente para alguns objetos? Por quê? <br />
#Um servidor Web, quando recebe uma requisição necessita saber para qual porta deve responder na máquina requisitante? Se positivo, esta porta seria sempre a mesma?<br />
#Por que um servidor Web espera na porta TCP número 80 em geral?<br />
#O que é um proxy Web server?<br />
#Um browser pode fazer cache local? Qual a diferença entre cache local e cache em um servidor proxy?<br />
<br />
ADICIONAIS PARTE 3- DNS<br />
#Porque o DNS não é centralizado? <br />
#O que são consultas recursivas e interativas em uma consulta DNS? <br />
#Quais os três tipos de servidores DNS?<br />
#Em um hospedeiro normalmente existe pelo menos um servidor DNS configurado. Que servidor deve estar configurado? Onde ele se localiza normalmente?<br />
#Quando um servidor local não consegue resolver um endereço IP olhando em seu cache, para quem ele deve encaminhar a consulta?<br />
#Um servidor sempre sabe resolver um nome solicitado? Explique.<br />
#É possível que um servidor DNS local seja um servidor com autoridade?<br />
#O que é um nome canônico e um apelido no contexto de DNS?<br />
#O que é e qual o formato de uma RR?<br />
#Explique os seguintes tipos de RR: A, NS, CNAME, MX e PTR.<br />
#Em um comando ping www.ifsc.edu.br quantas transações no mínimo serão realizadas até o último ECHO REPLY?<br />
#Por que um ping normalmente realiza uma consulta PTR?<br />
#Faça um esquema mostrando uma consulta de um cliente a um servidor local mostrando uma consulta interativa entre o servidor raiz e recursiva com um servidor de autoridade. <br />
#Cite o nome de servidor DNS bastante utilizado.<br />
#Quantos servidores raízes temos no mundo? Qual comando permite que possamos "ver" estes servidores em um hospedeiro?<br />
#Foi realizado um comando '''dig www.ifsc.edu.br''' tendo sido retornado: <br />
#:<br />
#: www.ifsc.edu.br. 240 IN A 200.135.190.95<br />
#:<br />
#Em seguida foi realizado um '''dig ifsc.edu.br MX''' com resposta:<br />
#:<br />
#: ;; ANSWER SECTION:<br />
#: ifsc.edu.br. 1327 IN MX 15 zimbra.ifsc.edu.br.<br />
#: <br />
#: ;; AUTHORITY SECTION:<br />
#: ifsc.edu.br. 2082 IN NS ns1.ifsc.edu.br.<br />
#: ifsc.edu.br. 2082 IN NS adns1.pop-sc.rnp.br.<br />
#: ifsc.edu.br. 2082 IN NS ns2.ifsc.edu.br.<br />
#: ifsc.edu.br. 2082 IN NS adns2.pop-sc.rnp.br.<br />
#: <br />
#: ;; ADDITIONAL SECTION:<br />
#: zimbra.ifsc.edu.br. 78 IN A 200.135.190.2<br />
#:<br />
#O que se pode concluir sobre a resolução do nome baseando-se nestas respostas?<br />
<br />
<!--RESPOSTAS <br />
<br />
#Qual é a diferença entre um hospedeiro e um sistema final? Cite os tipos de sistemas finais. Um servidor web é um sistema final?<br />
R.Segundo Kurose[1] os sistemas hospedeiros são sistemas finais, ou seja são considerados sinônimos. São os computadores do nosso dia a dia e que se encontram na periferia da rede executando aplicações que usufruem dos serviços da rede. Estas aplicações executam protocolos específicos para seu funcionamento (protocolos de aplicação).<br />
#O que caracteriza um protocolo? Dê um exemplo de um protocolo.<br />
R.Um conjunto de regras e formatos que viabilizam a comunicação entre duas ou mais entidades comunicantes. No caso de uma rede define as regras para troca de mensagens entre processos da rede (ações a serem realizadas no envio e no recebimento de mensagens), bem como o formato das mensagens trocadas. Em uma rede, as entidades comunicantes se encontram em uma mesma camada.<br />
#Por que os padrões são importantes para os protocolos?<br />
R.Para que exista compatibilidade na comunicação entre processos e equipamentos de rede, além de facilitar a implementação dos mesmos.<br />
#O que é um programa cliente? O que é um programa servidor? Um programa servidor requisita e recebe serviços de um programa cliente?<br />
R.Um programa cliente é uma parte de uma aplicação distribuída que requisita serviços de um outro programa chamado servidor. Tanto cliente como servidor se executam em sistemas finais. O servidor normalmente fica aguardando por uma requisição de algum recurso solicitado por um cliente. Ex: servidor Web e cliente Mozilla ou Chrome. <br />
#Quais são os dois tipos de serviços de transporte que a Internet provê às suas aplicações? Cite algumas características de cada um desses serviços.<br />
Os dois tipos básicos são serviços com conexão e sem conexão. Um serviço com conexão faz com que (em geral) duas entidades de aplicação que pretendem se comunicar, troquem mensagens de controle no sentido de manter informações mútuas de forma a permitir a execução de serviços adicionais do tipo: transferência confiável de dados, controle de fluxo de dados para não sobrecarregar o receptor e controle de congestionamento para evitar o congestionamento de pacotes na rede. Fluxos de pacotes podem ser direcionados a uma determinada conexão. Importante notar que os componentes intermediários da rede desconhecem as conexões. Na Internet, o protocolo que garante o serviço com conexão é o TCP.<br />
Já no serviço sem conexão as entidades comunicantes enviam pacotes (datagramas) sem nenhuma apresentação prévia (troca de mensagens de controle). Cada pacote é enviado de forma independente não tendo garantia de entrega. Na internet o protocolo associado a este comportamento é o UDP. Vale lembrar que por não ter nenhum procedimento associado, a troca de mensagens com UDP tem maior desempenho do que o TCP.<br />
#Quais são as vantagens de uma rede de comutação de circuitos em relação a uma rede de comutação de pacotes? <br />
Em uma rede de comutação de circuitos (ex: rede telefônica clássica) é estabelecido um canal dedicado para a a comunicação entre entidades comunicantes. Normalmente a alocação do canal dedicado é precedido de um processo de sinalização (discar o número, verificar se o destino está disponível, conectar). Uma canal dedicado não pode ser compartilhado por outras comunicações, mesmo quando fica ocioso (ex: duas pessoas na linha telefônica sem conversar). Já em uma rede de pacotes a informação é organizada em pacotes que podem compartilhar canais. Pacotes são comutados para seus destino por equipamentos do tipo roteadores. O roteamento é baseado em informações do cabeçalho do pacote. <br />
#Cite 5 tecnologias de acesso. Classifique cada uma delas nas categorias acesso residencial, acesso corporativo ou acesso móvel. <br />
#FTTH, HFC e ADSL são usados para acesso residencial. Para cada uma dessas tecnologias de acesso, cite uma faixa de taxas de transmissão e comente se a largura de banda é compartilhada ou dedicada.<br />
#Cite tecnologias de acesso residencial disponíveis na grande Florianópolis. Para cada tipo de acesso, apresente a taxa de ''downstream'', a taxa de ''upstream'' e o preço mensal anunciados.<br />
#Qual é a taxa de transmissão de LANs Ethernet?<br />
#Qual é a vantagem de uma rede de comutação de circuitos em relação a uma de comutação de pacotes?<br />
#Porque dividimos a arquitetura da Internet (e de redes de comutação de pacotes em geral) em camadas? Por que dizemos que uma camada inferior presta um serviço a camada superior?<br />
#Quais são as cinco camadas da pilha de protocolo da Internet? Quais as principais responsabilidades de cada uma dessas camadas? <br />
#O que significa o processo de encapsulamento e desencapsulamento de pacotes no contexto da rede organizada em camadas?<br />
#O que é uma mensagem de camada de aplicação? Um segmento da camada de transporte? Um datagrama da camada de rede? Um quadro de camada de enlace? Qual a relação entre eles?<br />
#Que camadas da pilha de protocolo da Internet um roteador implementa? Que camadas um comutador de enlace implementa? Que camadas um sistema final implementa?<br />
#A noção de portas é criada pela camada de transporte na arquitetura TCP/IP. Qual a funcionalidade que as portas permitem implementar?<br />
#Descreva todo o processo de ''download'' de um arquivo utilizando a ferramenta Bittorrent. Considere que o usuário acabou de instalar a mesma.<br />
#Imagine que você queira enviar, com urgência, 40 terabytes de dados de São José a Manaus. Você tem disponível um enlace dedicado de 100 Mbps para a transferência de dados. Você escolheria transferir os dados pelo enlace ou mandar mídias por Sedex 10? Explique.<br />
#Para pensar I: um celular tipo smartphone acessa normalmente quantas redes? Quais tecnologias sao usadas? Elas são de comutação de pacotes ou de circuitos?<br />
--><br />
{{Collapse bottom}}<br />
{{Collapse top |Lista de exercícios 3 - Camada de Transporte}}<br />
#Considere uma conexão TCP entre o hospedeiro A e o hospedeiro B. Suponha que os segmentos TCP que trafegam do hospedeiro A para o hospedeiro B tenham número de porta fonte x e número de porta destino y. Quais são os números de porta fonte e do destino para os segmentos que trafegam do hospedeiro B para o hospedeiro A? <br />
#Descreva porque um desenvolvedor de aplicação pode escolher rodar uma aplicação sobre UDP em vez de sobre TCP. <br />
#O que são os serviços de multiplexação e demultiplexação implementados pela camada de transporte? <br />
#Porque se diz que o UDP é um protocolo não orientado para conexão? <br />
#Qual o papel das informações de porta origem e destino contidas nos segmentos TCP e UDP? <br />
#Porque é dito que o TCP fornece transferência confiável de dados sobre um canal não confiável?<br />
#Cite 3 diferenças entre os serviços oferecidos pelo TCP e UDP.<br />
#Para que serve um ''checksum'' em um segmento TCP ou UDP? Como ele é formado?<br />
#Cite um motivo para um protocolo de transmissão confiável adicionar um número de seqüência em cada pacote transmitido. Justifique o uso dessa informação explicando o problema que ocorreria caso ela não fosse usada.<br />
#Para que serve um ''timeout'' em um protocolo de transmissão confiável?<br />
#O que é uma reconhecimento cumulativo? [[Arquivo:WiresharkUDP.png |thumb | 600px| Figura 1 -- Captura 1 - Wireshark]]<br />
#Baseado na Figura 1, responda as seguintes perguntas:<br />
##Quais os IP fonte e destino?<br />
##Qual o protocolo da camada de transporte utilizado?<br />
##Quais as portas fonte e destino.<br />
##Qual o conteúdo do campo de tamanho (anote o tamanho) e ''checksum'' no pacote (datagrama)?<br />
##Quantos bits possui o ''checksum''? Como você calculou?<br />
##Qual o significado do campo '''Data: 74657374650a'''? Qual é a mensagem contida? Como você chegou a essa conclusão? [[Arquivo:WiresharkTCP.png |thumb | 600px| Figura 2 -- Captura 2 - Wireshark]]<br />
#Baseado na Figura 2, responda as seguintes perguntas:<br />
##Quais os IP fonte e destino?<br />
##Qual o protocolo da camada de transporte utilizado?<br />
##Quais as portas fonte e destino.<br />
##Qual o conteúdo do campo de tamanho (anote o tamanho) no pacote (datagrama)? O tamanho apresentado significa bits ou bytes?<br />
##Qual o significado do campo '''Data: 74657374650a'''? Qual é a mensagem contida? Como você chegou a essa conclusão? [[Arquivo:WiresharkTCPPerdaDePacotes.png |thumb | 600px| Figura 3 -- Captura 3 - Wireshark]]<br />
#Baseado na Figura 3, responda as seguintes perguntas:<br />
##Quais os IP fonte e destino?<br />
##Qual o protocolo da camada de transporte utilizado?<br />
##Quais as portas fonte e destino.<br />
##Qual o número de sequência (normalizado pelo Wireshark) de cada segmento de dados transmitido, e qual o significado do número de reconhecimento em cada um deles?<br />
##Como foi reconhecido cada segmento enviado?<br />
##Qual o significado do conjunto de mensagens de número (No.) 1 à 3? Explique essas 3 mensagens.<br />
##Qual o significado do conjunto de mensagens de número (No.) 17 à 19? Explique essas 3 mensagens.<br />
##Qual o significado do conjunto de mensagens de número (No.) 6, 11 e 16? Explique essas 3 mensagens.<br />
##Qual é o tamanho "médio" de janela de cado um dos ''hosts''?<br />
##Qual a utilizade das mensagens com fundo preto?<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Lista de exercícios 4 - Camada de Rede}}<br />
#Quais são as principais características de uma rede de datagramas?<br />
#Roteadores possuem endereços IP? Quantos endereços IP um roteador possui?<br />
#Para que serve o protocolo ICMP? <br />
#Para que serve o campo “Time to Live” (sobrevida) em um datagrama IP? <br />
#Quantos hosts podem ser endereçados com um bloco IP 200.23.16.0/20? Como podemos montar 8 sub-redes a partir deste bloco de endereços IP?<br />
#Um provedor de serviços ISP possui cerca de 2000 clientes cadastrados atualmente. Porém um levantamento realizado recentemente pelo administrador da rede constatou que nunca mais do que 450 clientes estão on-line ao mesmo tempo. Qual o bloco de endereços IP na forma CIDR (a.b.c.d/x) deve ser contratado pelo ISP, considerando o estudo realizado pelo administrador da rede?<br />
#Um administrador precisa montar uma rede experimental conforme mostrada na figura. Na sub-rede 1 ele precisará instalar cerca 25 hosts, e nas sub-redes 2 e 3 ele precisará instalar cerca de 12 hosts. O administrador dispõe do bloco de endereços IP 192.168.10.0/24 para ser utilizado no endereçamento da rede experimental. Faça uma proposta para alocação de endereços IP para cada sub-rede (rede 1, 2 e 3), incluindo também as sub-redes relativas aos enlaces ponto-a-ponto (rede AB, AC e BC). Responda ainda:<br />
##Qual o endereço identificador de rede de cada sub-rede (1, 2 e 3)?<br />
##Qual o a máscara de rede de cada sub-rede (1, 2 e 3)?<br />
##Quais os endereços IP que serão atribuídos a cada interface de rede nos enlaces ponto-a-ponto dos roteadores (enlaces relativos as redes AB, AC e BC)[[Arquivo:CdrEx.png]]<br />
#Suponha que um administrador de rede tenha recebido o bloco de endereços 200.40.8.0/21 e que deseja dividir este bloco em 8 blocos de endereços iguais, de menor tamanho, para ser alocado a 8 sub-redes administradas por ele.<br />
##Determine o tamanho total do bloco de endereços.<br />
##Determine o tamanho de cada sub-bloco.<br />
##Determine o endereço/máscara de rede de cada sub-rede.<br />
#Um provedor de acesso a Internet possui o seguinte bloco de endereços IP: 12.17.192.0/18. Os endereços IP de 12.17.192.1 até 12.17.207.255 já estão alocados para clientes deste provedor. Este provedor precisa atender a quatro novos clientes, um deles necessita de rede com pelo menos 1000 endereços de IP válidos e os outros três necessitam de rede com pelo menos 30 IP válidos. Faça uma proposta para alocação de endereços IP para estes clientes. Os endereços reservados para estes novos clientes devem ser alocados a partir da numeração mais baixa disponível. Procure também responder as questões abaixo:<br />
##Qual o total de endereços que dispõe o provedor em questão?<br />
##Quantos endereços IP já estão utilizados?<br />
##Quantos endereços IP este provedor possui livres para alocar aos novos clientes?<br />
##Qual o endereço identificador de cada sub-rede dos novos clientes?<br />
##Qual o a máscara de rede de cada sub-rede dos novos clientes?<br />
##Qual o endereço de broadcast de cada sub-rede dos novos clientes?<br />
##Quantos endereços IP ainda sobrarão ao provedor após atender a estes clientes?<br />
#Quantas estações uma rede 223.1.10.0/24 suporta? <br />
#Uma rede com bloco de IPs 200.23.16.0/20 deseja montar 8 subredes. Mostre como isso é possível e como ficaria os endereços de cada uma dessas subredes.<br />
#Um datagrama enviado para uma estação da mesma rede precisa passar por um roteador?<br />
#Suponha que entre o hospedeiro de origem A e o hospedeiro de destino B os datagramas estejam limitados a 1500 bytes (incluindo cabeçalho). Admitindo um cabeçalho IP de 20 bytes, quantos datagramas seriam necessários para enviar um arquivo MP3 de 5 milhões de bytes? Explique como você obteve a resposta.<br />
#Descreva e detalhe o processo de obtenção de um endereço IP através do protocolo DHCP. [[Image:ExercicioConfEstaticaZebra.png]]<br />
#Considere a rede apresetanda na Figura, onde todas as sub-redes apresentam máscara de rede /24 (255.255.255.0), e tendo os dados do Host1 e Roteador 4 apresentados no quadro abaixo, responda: <syntaxhighlight lang=bash><br />
root@H1:~# ifconfig <br />
eth0 Link encap:Ethernet HWaddr 7a:a6:f4:ca:51:0e <br />
inet addr:200.10.1.1 Bcast:200.10.1.255 Mask:255.255.255.0<br />
<br />
root@H1:~# route -n<br />
Kernel IP routing table<br />
Destination Gateway Genmask Flags Metric Ref Use Iface<br />
0.0.0.0 200.10.1.254 0.0.0.0 UG 0 0 0 eth0<br />
200.10.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0<br />
<br />
root@R4:~# route -n<br />
Kernel IP routing table<br />
Destination Gateway Genmask Flags Metric Ref Use Iface<br />
200.10.1.0 200.10.3.1 255.255.255.0 UG 0 0 0 eth0<br />
200.10.3.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0<br />
200.10.5.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1<br />
200.10.6.0 0.0.0.0 255.255.255.0 U 0 0 0 eth2<br />
200.10.8.0 200.10.6.1 255.255.255.0 UG 0 0 0 eth2 </syntaxhighlight><br />
##Observando a tabela do hospedeiro (H1) é possível dizer quem é seu roteador default?<br />
##Se o hospedeiro (H1) tiver um pacote para entregar para o IP 200.10.1.20 ele utilizará entrega direta ou utilizará seu roteador padrão? Explique o significado da entrega direta e indireta (via roteador).<br />
##Se o hospedeiro (H1) tiver um pacote para entregar para o IP 200.10.8.1 ele utilizará entrega direta ou utilizará seu roteador padrão?<br />
##Se o roteador (R4) receber um pacote cujo IP de destino é 200.10.1.10 para qual roteador ele entregará tal pacote e por qual interface? Será uma entrega direta ou indireta?<br />
##Se o roteador (R4) receber um pacote cujo IP de destino é 200.10.6.1 para qual roteador ele entregará tal pacote e por qual interface? Será uma entrega direta ou indireta?<br />
##Se o roteador (R4) receber um pacote cujo IP de destino é 200.10.1.10, cuja carga segmento TCP com destino a porta 80, para qual roteador ele entregará tal pacote e por qual interface? Será uma entrega direta ou indireta?<br />
##Se o roteador (R4) receber um pacote cujo IP de destino é 122.10.4.7 para qual roteador ele entregará tal pacote e por qual interface? Explique.<br />
##Qual comando que você executaria no roteador (R4) para acrescentar uma rota para a rede SN2? Explique seu comando.<br />
##Considerando a pergunta anterior, a rota acrescentada garantiria que se você fizer um ping para um host da rede SN2 você obteria sucesso? Explique todas as possibilidades.<br />
##Explique o significado dos campos das colunas 1, 2, 3 e 8 da última linha da tabela do roteador (R4).<br />
{{Collapse bottom}}</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=ISL-FicLinux_(p%C3%A1gina)&diff=162011ISL-FicLinux (página)2019-10-03T19:58:55Z<p>127.0.0.1: /* Objetivos */</p>
<hr />
<div>__NOTOC__<br />
= Introdução ao Sistema Operacional Linux / Redes com Linux =<br />
<br />
*'''Encontros:''' Terças e Quintas das 19:00 às 22:00.<br />
*'''Local:''' Laboratório de Redes de Computadores (Redes 1).<br />
<br />
*[[ISL-FicLinux_(Plano_de_Ensino)| Plano de Ensino]]<br />
<br />
==Curso FIC Linux 2019==<br />
<br />
{{collapse top | Semestre 2019-2 - Prof. Eraldo Silveira e Silva}}<br />
<br />
==Cronograma Tentativa==<br />
<br />
Horários: 19h às 22h.<br />
<br />
{| class="wikitable"|<br />
| AULA || DATA || Professor || Conteúdo<br />
|-<br />
| 1 || 27/09/2019 || ERALDO || Programa da Disciplina.Forma de Avaliação. O computador: hardware e software. SO Linux: histórico e distribuições. Ligando/Logando/Desligando a Máquina. Conceitos básico de Sistema de Arquivos e Processos.<br />
|-<br />
| 2 || 29/09/2019 || ERALDO || Gerenciamento de Arquivos I: Operações sobre arquivos e diretórios usando o terminale o Nautilus.<br />
|-<br />
| 3 || 3/09/2019 || ERALDO || Gerenciamento de Arquivos II: continuação Operações sobre arquivos e diretórios. Links Simbólicos, Criação de Arquivo com vi e outros editores.<br />
|-<br />
| 4 || 5/09/2019 || ERALDO || Interfaces Gráficas: X11, Gnome. KDE e outras. Instalação de Programas via Gerenciador de Pacotes.<br />
|-<br />
| 5 || 10/09/2019 || ERALDO || Administração de contas de usuários I<br />
|-<br />
| 6 || 12/09/2019 || ERALDO || Administração de contas de usuários II<br />
|-<br />
| 7 || 17/09/2019 || ERALDO || Permissionamento de Arquivos<br />
|-<br />
| 8 || 19/09/2019 || ERALDO || Gerenciamento de Processos<br />
|-<br />
| 9 || 24/09/2019 || ERALDO || Introdução ao Shell Script<br />
|-<br />
| 10 || 26/09/2019 || ERALDO || Introdução ao Shell Script<br />
|-<br />
| 11 || 1/10/2019 || ERALDO || Introdução a Redes. Conceito de Protocolos. Ferramentas de Rede no Linux.<br />
|-<br />
| 12 || 3/10/2019 || ERALDO || Conceito de Protocolos. Protocolos de Aplicação: exemplo http. Protocolo DNS<br />
|-<br />
| 13 || 8/10/2019 || ERALDO || Camada de Transporte: protocolo UDP. Protocolo TCP. Diferenças dos protocolos de Transporte TCP/UDP. <br />
|-<br />
| 14 || 10/10/2019 || ERALDO || Camada IP e aspectos da configuração da mesma sob o Linux<br />
|-<br />
| 15 || 15/10/2019 || ERALDO || Camada de Enlace/Física. Hubs X Switches. O Papel do Protocolo ARP. Outros serviços/protocolos: Serviço DHCP e NAT<br />
|-<br />
| 16 || 17/10/2019 || ERALDO|| Segmentação Redes IP. Cálculo de subredes. <br />
|-<br />
| 17 || 22/10/2019 || ERALDO || Introdução ao IPV6. Introdução ao Access Point TPLINK N750: configuração da LAN e WAN<br />
|-<br />
| 18 || 24/10/2019 || ERALDO || Serviço SSH no Linux. Acesso a rede WIFI. Conceitos básicos de redes sem fio.<br />
|-<br />
| 19 || 29/10/2009 || ERALDO || Tópicos Adicionais sobre redes no Linux: Configuração Manual X NetworkManager. Relatório Avaliativo 1.<br />
|-<br />
| 20 || 31/10/2019 || ERALDO || Relatório Avaliativo 2<br />
|}<br />
<br />
=Curso FIC Linux 2019-2=<br />
<br />
==Professor==<br />
<br />
:*Prof. [[Eraldo Silveira e Silva]]<br />
:*email: eraldo@ifsc.edu.br<br />
:*sala: Sala de I de Professores da Área de Telecomunicações (primeira sala lado da Biblioteca - direção esquerda)<br />
<br />
=27/08/2019=<br />
<br />
==Objetivos==<br />
<br />
===Parte 1===<br />
<br />
*Apresentar o IFSC: estrutura, câmpus e serviços<br />
*Apresentar o curso: perfil do egresso, competências gerais, áreas de atuação do egresso e conteúdos previstos<br />
*Apresentar o Cronograma Tentativa (ver SIGA A)<br />
*Apresentar metodologia e forma de avaliação<br />
<br />
===Parte 2===<br />
<br />
*Conceitos de Hardware, Software e Firmware<br />
*Arquiteturas de processadores<br />
*Classificação de softwares<br />
*Conceitos de Sistemas Operacionais e exemplos<br />
<br />
===Parte 3===<br />
<br />
*Histórico do Linux<br />
*Linux e GNU/Linux<br />
*Instalando o Linux<br />
*Arquitetura do Linux<br />
*Distribuições<br />
*Distribuições usadas no IFSC/SJ<br />
*Ligando e Desligando o Sistema<br />
*Primeiros contatos.<br />
<br />
==Professores do FIC Linux Edição 2019-2==<br />
<br />
*Prof. [[Eraldo Silveira e Silva]] (Introdução ao Linux e Redes com Linux)<br />
<br />
==Apresentação do IFSC==<br />
<br />
*[http://www.ifsc.edu.br/estrutura-organizacional-inicio Página do IFSC]<br />
*[https://www.sj.ifsc.edu.br/index.php Página do Câmpus]<br />
<br />
==Apresentação do Curso==<br />
<br />
*[[ISL-FicLinux_(Plano_de_Ensino) | Introdução ao Linux]]<br />
*[https://wiki.sj.ifsc.edu.br/index.php/PRL-FicLinux_(Plano_de_Ensino) Projeto de Rede Residencial com o Linux]<br />
*[[Curso_de_Formação_Continuada_de_Configuração_de_Redes_de_Computadores_Linux | PPC do Curso e Outras Regulamentações]]<br />
<br />
==Cronograma Tentativa==<br />
<br />
Horários: 19h às 22h.<br />
<br />
VER SIGA A [https://sig.ifsc.edu.br/sigaa/verTelaLogin.do]<br />
<br />
==Metodologia, Avaliação e Critérios de Aprovação==<br />
<br />
*Aulas expositivas e aulas práticas no laboratório. Nas aulas práticas serão desenvolvidos exercícios e trabalhos individuais.<br />
*Avaliações individuais: Listas de exercícios com aproveitamento e entregues no prazo. <br />
*Critérios para aprovação: Serão considerados aprovados os alunos que obtiverem conceito final 6 ou superior em cada componente curricular. ATENÇÃO: Possuir no mínimo 75% de presença<br />
<br />
==Bibliografia==<br />
<br />
#Odilson Tadeu Valle<br />
##Administração de redes com Linux: fundamentos e práticas<br />
##Editora IFSC, 2010<br />
#Gleydson Mazioli da Silva<br />
##Guia Foca Linux<br />
##http://www.guiafoca.org/<br />
#Luiz Carlos Lobato Lobo de Medeiros e Wendel Soares<br />
##Formação de suporte técnico PROINFO<br />
##https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo<br />
#Ari Frazão Jr e Marcelo Braga<br />
##Administração de Sistemas Linux<br />
##https://pt.scribd.com/doc/128912228/Administracao-de-Sistemas-Linux<br />
<br />
==Conceitos de Hardware, Software e Firmware==<br />
<br />
*Em informática, o hardware consiste nos equipamentos<br />
**Ex: Computador, teclado, mouse, monitor<br />
*Software é um aplicativo, desenvolvido em uma linguagem de programação<br />
**Ex: Windows, Linux, Mozilla Firefox, Google Chrome<br />
*Firmware é um conjunto de instruções básicas e específicas para um hardware<br />
**Ex: BIOS nos computadores, sistemas de controle das máquinas de lavar, etc.<br />
<br />
==Estrutura de um Computador e Arquitetura de Processadores==<br />
<br />
*Material de Referência: https://www.dropbox.com/s/fn3l9os4l7gh9o5/AULA%201.odp?dl=0<br />
<br />
===Outros Links Interessantes===<br />
<br />
*Bits, [https://pt.wikipedia.org/wiki/Byte Bytes] e tamanho de memória;<br />
*Representação de Caracteres: [https://pt.wikipedia.org/wiki/ASCII Tabela ASCII];<br />
*O [https://pt.wikipedia.org/wiki/Microprocessador microprocessador], barramentos e memórias semicondutoras: RAM,ROM, E2PROM, FLASH;<br />
*Memórias cache e memórias secundárias;<br />
*[https://pt.wikipedia.org/wiki/Mem%C3%B3ria_virtual Memória Virtual] e Swapping;<br />
*Registradores de 32bits ou 64bits<br />
*Arquitetura [https://pt.wikipedia.org/wiki/X86 x86] / [https://pt.wikipedia.org/wiki/AMD64 x86-64] – presente nos computadores pessoais<br />
*Arquitetura ARM – presente em sistemas embarcados e dispositivos móveis<br />
*Múltiplos núcleos (core)<br />
*Máquinas Virtuas: VirtualBox, UML (User Mode Linux).<br />
<br />
==O papel do Sistema Operacional==<br />
<br />
*O [https://pt.wikipedia.org/wiki/Sistema_operativo SO] é um programa (software) que controla a máquina e a torna utilizável para o usuário;<br />
*Abstrações do Sistema: arquivos e processos;<br />
*Pode ser multitarefa e multiusuário;<br />
*[https://en.wikipedia.org/wiki/Device_driver Driver] de dispositivo<br />
*[https://pt.wikipedia.org/wiki/Multi_boot Múltiplos OS instalados] em um computador. É possível??<br />
<br />
==Sistema de Arquivos==<br />
<br />
*Forma como estão estruturados/organizados os arquivos/dados em uma determinada mídia [https://pt.wikipedia.org/wiki/Sistema_de_ficheiros];<br />
*Um sistema operacional deve saber como acessar e operar sobre este sistema;<br />
*Tipos de sistemas: ext4, NTFS, VFAT32<br />
<br />
==Exemplos de SO==<br />
<br />
*Unix<br />
*Microsoft DOS<br />
*IBM<br />
*Microsoft Windows<br />
*netBSD, freeBSD, openBSD<br />
*Linux<br />
*macOS<br />
*Android<br />
*iOS<br />
<br />
==Histórico do Linux==<br />
<br />
*O início de tudo: UNIX;<br />
*Surgiu em 1991 quando Linus Torvalds, um estudante finlandês, resolveu desenvolver um sistema operacional compatível com a POSIX, por em que pudesse ser executado em arquitetura x86;<br />
*Linux está sob uma licença de software livre e diversas pessoas e empresas contribuem para o desenvolvimento do mesmo.<br />
*E o que é [https://pt.wikipedia.org/wiki/POSIX POSIX]? Define padrões para a interface de programação de aplicações (API) de um OS de forma a manter compatibilidade com o UNIX;<br />
<br />
==Arquitetura do Linux==<br />
<br />
===Material de Referência===<br />
<br />
*[https://www.dropbox.com/s/zvpo7zw19ns7rmk/AULA%202.odp?dl=0 Slides Introdução ao SO Linux]<br />
*Ver pg.16 a 19 de [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo]<br />
<br />
==Distribuições==<br />
<br />
Uma distribuição Linux consiste de um kernel Linux e uma coleção de software utilitários e aplicativos de usuário (baseado slides Prof. Emerson)<br />
**Redhat<br />
**Slackware<br />
**Debian<br />
**Ubuntu<br />
**OpenSuse<br />
**Fedora<br />
**CentOS<br />
**Kali<br />
<br />
<br />
Algumas distribuições podem ser executadas diretamente no CD/pendrive<br />
sem a necessidade de fazer sua instalação no disco rígido do computador<br />
<br />
==Distribuições aqui no IFSC SJ==<br />
<br />
*Ubuntu<br />
*Ubuntu Mate (fork do Ubuntu)<br />
*Debian<br />
<br />
==Instalando o Linux==<br />
<br />
*Fazer Download do arquivo ISO em [http://mirror.pop-sc.rnp.br/mirror/ubuntu-releases/18.04/] versão Ubuntu 18.04.3 LTS;<br />
*Instalar a VirtualBox (já está instalada no nosso Lab). Baixar de [https://www.virtualbox.org/wiki/Downloads] e selecionar para a máquina hospedeira alvo;<br />
*Seguir o procedimento colocado pelo professor.<br />
<br />
*[Ver https://www.dropbox.com/s/4xfdhqq8lruvq8m/LinuxSobreVM.odp?dl=0 Slides de Instalação]<br />
<br />
==Ligando e Desligando o Sistema Linux==<br />
<br />
*Cuidado ao desligar um OS como o Linux!!! Dados podem ser perdidos.<br />
*Ver [https://pt.wikibooks.org/wiki/Guia_do_Linux/Iniciante%2BIntermedi%C3%A1rio/Introdu%C3%A7%C3%A3o/Ligando_o_computador]<br />
<br />
==O Desktop do Ubuntu - Primeiras Considerações==<br />
<br />
*O Desktop no Ubuntu ver[https://help.ubuntu.com/stable/ubuntu-help/shell-overview.html]<br />
<br />
=AULA 2 - Dia 29/08/2019=<br />
<br />
==Objetivos==<br />
<br />
===PARTE 1===<br />
<br />
*Revisão da aula passada;<br />
*repassar itens não mencionados na aula passada;<br />
**Paginação e Memória [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo pg.19]<br />
**Estrutura do Linux [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo pg.18]<br />
<br />
===PARTE 2===<br />
<br />
*Operações com arquivos e diretórios usando o terminal;<br />
*formato de um comando básico;<br />
*quase tudo no Linux é arquivo: tipos de arquivos, diretórios, arquivos ordinários;<br />
*conceito de sistema de arquivos;<br />
*conceito de referência absoluta e relativa;<br />
*conceito de diretório de entrada, diretório de trabalho;<br />
*mudando de diretório com cd;<br />
*listando diretórios e arquivos com ls;<br />
*vendo o significado de um comando com man;<br />
*criando diretórios com mkdir;<br />
*removendo diretórios e arquivos com rmdir e rm;<br />
*referência com . .. - ~<br />
*criando arquivos ordinários com touch;<br />
*arquivos e diretórios escondidos;<br />
*copiando arquivos;<br />
*movendo e renomeando arquivos;<br />
*vendo a história de comandos com history;<br />
<br />
===Slides===<br />
<br />
*[https://www.dropbox.com/s/wtc479wmrtle9m4/SistemaDeArquivos.odp?dl=0 Slides Sistema de Arquivos]<br />
<br />
==Conceito de sistemas de arquivos, arquivos e diretórios==<br />
<br />
* [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Sistemas de Arquivos pg.18]<br />
* [Estrutura básica de diretórios do Sistema Linux]<br />
<br />
==Comandos no Linux==<br />
<br />
* [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Comandos e Interpretador de Comandos no Linux pg.18]<br />
<br />
==Tipos de Arquivos==<br />
<br />
* [https://pt.scribd.com/doc/128912228/Administracao-de-Sistemas-Linux Tipos de Arquivos 12,13 e 14 ]<br />
<br />
==Os comandos de operação sobre arquivos e diretórios==<br />
<br />
*[https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Interpretador de comandos - Comandos Básicos - pg.20 e 21]<br />
*[https://www.dropbox.com/s/mv6qpa8bqimiwzg/Aula1_Linux%282%29.pdf Ver lista de exercícios da Aula 2]<br />
<!-- *[https://www.dropbox.com/s/g3xr3wimffde2zm/Aula2_Linux_OperacoesComArquivos_2.pdf Ver lista de exercícios da Aula 3] --><br />
<br />
=AULA 3 - Dia 03/09/2019=<br />
<br />
<br />
===Mirros do Ubuntu Download e Outros===<br />
<br />
<br />
*[http://mirror.pop-sc.rnp.br/mirror/ubuntu-releases/18.04.3/ Ununtu 18.04.3 Mirror Brazil]<br />
<br />
*[https://linuxmint.com/edition.php?id=267 Linux Mint]<br />
<br />
*[https://software.opensuse.org/distributions/leap Opensuse]<br />
<br />
*[https://elementary.io/ Elementary Os]<br />
<br />
*[https://lubuntu.net/ Lubuntu]<br />
<br />
*[https://www.debian.org/CD/live/ Debian]<br />
<br />
*[https://kubuntu.org/getkubuntu/ Kubuntu]<br />
<br />
*[https://peppermintos.com/ Peppermint]<br />
<br />
*[https://www.linuxliteos.com/ Linux Lite]<br />
<br />
*[https://www.lxle.net/download/ LXLE para PCs Antigos...]<br />
<br />
*[https://www.bodhilinux.com/ Bodhi Linux]<br />
<br />
===Como verificar se o arquivo está correto?===<br />
<br />
*[https://help.ubuntu.com/community/HowToMD5SUM HowToMD5SUM] <br />
<br />
===Instalar e Preparar 3 transparências no Oppenoffice===<br />
<br />
*Nome da Equipe e da Distribuição - colar a desktop no slide<br />
*O que tem de interessante nesta distro<br />
*Requisitos da Distribuição<br />
<br />
*Gerar pdf e Enviar para o Siga a<br />
<br />
=AULA 4 - Dia 03/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Ainda operações com arquivos;<br />
*Uso de Coringas<br />
*Editor de texto sobre Ubuntu<br />
*Redirecionamento de Entradas e Saídas<br />
*Aspectos da Interface Gnome no Ubuntu 18.04<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/zti7nn0xq25x8ne/Aula2_Linux_OperacoesComArquivos_2.pdf Ainda Operações com Arquivos]<br />
*[https://www.dropbox.com/s/af3jolkvrb24g8c/Aula3_Linux_LinksSimb_licos_gedit_cat.pdf Edição de Texto]<br />
*[https://www.dropbox.com/s/vihh5r9186d40uj/Aula3_Linux_Parte4_RedirecionamentoEntradasSaidas.pdf Redirecionamento de Entradas e Saídas]<br />
<br />
=AULA 5 - Dia 10/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Gerenciamento de Processos - Parte 1<br />
*Permissionamento de Arquivos - Parte 1<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/4i1n2wqsds18eol/Aula5_Linux_GerenciamentoDeProcessos_Parte1.pdf?dl=0 Gerenciamento de Processos - Parte 1]<br />
*[https://www.dropbox.com/s/3z61r8r0b9wpftr/Aula4_Linux_PermissionamentoDeAcesso_Parte1.pdf Permissionamento de Arquivos - Parte 1]<br />
<br />
=AULA 6 - Dia 12/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Aval1<br />
<br />
==Comand wget==<br />
<br />
Para fazer o downloiad do Linux Ubuntu via linha de comando:<br />
<br />
wget http://mirror.pop-sc.rnp.br/mirror/ubuntu-releases/18.04.3/ubuntu-18.04.3-desktop-amd64.iso<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/fdl5kzq0ba2nv3v/Aula4_Linux_PermissionamentoDeAcesso_Parte2.pdf Permissionamento Parte 2 ]<br />
<br />
=AULA 7 - Dia 12/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Instalação do Ubuntu em partições separadas<br />
*Permissionamento de Grupos e Outros<br />
*Criação de Contas de Usuários<br />
*Camandos adicionais para gerenciamento de processos<br />
<br />
==Instalação==<br />
<br />
Considere a estrutura de sistemas de arquivos abaixo. Montar um sistema de arquivos da forma abaixo considerando que sb1 seria um segundo hd máquina virtual.<br />
<br />
[[arquivo:SOP2019-1-ExemploMontagemSistema.png]]<br />
<br />
Logar no sistema e usando o terminal verificar as configurações estabelecidas.<br />
<br />
df -h<br />
cd /home<br />
ls spock<br />
<br />
Usar o comando gparted para criar uma partição adicional no segundo disco.<br />
<br />
sudo apt-get install gparted<br />
sudo gparted<br />
<br />
Redimensionar a partição original para poder criar uma adicional.<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/fdl5kzq0ba2nv3v/Aula4_Linux_PermissionamentoDeAcesso_Parte2.pdf Permissionamento Parte 2 ]<br />
<br />
*[https://www.dropbox.com/s/ozjd3qz0yblcj43/Aula6_Comandos_Adicionais_de_Gerenciamento_de_Processos.pdf Gerenciamento de Processos Parte 2]<br />
<br />
=AULA 8 - Dia 12/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Permissionamento de Grupos e Outros<br />
*Criação de Contas de Usuários<br />
*Reparticionamento de Disco após instalação. Montagem de sistemas com mount.<br />
<br />
==Desafio Final==<br />
<br />
Na máquina instalada na aula anterior fazer as seguintes operações:<br />
<br />
*Reparticionar o disco 2 (/dev/sdb) em 2 partições de 5G (usar o comando gparted) (redimensionar a partição do spock)<br />
*Criar uma conta para o usuário uhura<br />
*Criar dois subdiretórios no diretório home de uhura. Estes diretórios serão pontos de montagem dos dois sistemas de arquivos criados no segundo disco.<br />
*Montar os sistemas de arquivos usando o comando mounthttps://wiki.sj.ifsc.edu.br/index.php/ISL-FicLinux_(Plano_de_Ensino)<br />
*Mudar o dono destes diretórios (usuário e grupo) )para o novo dono (uhura)<br />
*Verificar o sistema montado (comando df)<br />
*Testar o acesso entrando como <br />
<br />
==Continuando o o permissionamento de Grupos e Outros==<br />
<br />
Ver material de referência<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/fdl5kzq0ba2nv3v/Aula4_Linux_PermissionamentoDeAcesso_Parte2.pdf Permissionamento Parte 2 ]<br />
*[https://www.dropbox.com/s/ozjd3qz0yblcj43/Aula6_Comandos_Adicionais_de_Gerenciamento_de_Processos.pdf Gerenciamento de Processos Parte 2]<br />
<br />
=AULA 9 - Dia 24/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*ainda criação de usuários<br />
*ainda gerenciamento de processos: crontab<br />
*compactação e backups em linha de comando<br />
<br />
<br />
==Material de Referência==<br />
<br />
<br />
*[Ainda Gerenciamento de Usuários https://www.dropbox.com/s/8vsg0yeforcsuq9/Aula7_GerenciamentoDeUsuarios_Parte1.pdf?dl=0]<br />
*[https://www.dropbox.com/s/ozjd3qz0yblcj43/Aula6_Comandos_Adicionais_de_Gerenciamento_de_Processos.pdf Gerenciamento de Processos Parte 2]<br />
*[https://www.dropbox.com/s/61n9is9c8o7bgbz/Aula3_Linux_Parte3_vi.pdf?dl=0 Introdução ao VI]<br />
<br />
=AULA 10 - Dia 26/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Finalização da aula anterior: arquivo sudoers<br />
*Introdução ao shell script<br />
*Um pouco sobre instalação de pacotes<br />
*exercicício avaliativo 2<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/54tnv5rjwguzppd/Aula8_ShellScript_Parte1.pdf?dl=0 Introdução ao Shell script]<br />
*[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula9-pacotes.pdf Instalação de Pacotes (Prof.Luciano Barreto)]<br />
<br />
=AULA 11 - Dia 1/10/2019=<br />
<br />
Introdução a Redes de Computadores<br />
**Conceito Básicos em Redes e Protocolos<br />
**Ferramentas de Redes<br />
**Exemplo de Protocolo de Aplicação: http<br />
**O processo de encapsulamento<br />
<br />
==Plano de Ensino==<br />
<br />
*[https://wiki.sj.ifsc.edu.br/index.php/PRL-FicLinux_(Plano_de_Ensino) Plano de Ensino]<br />
<br />
<br />
==Laboratório 1 - Ferramentas de Rede e Conceitos Básicos==<br />
<br />
*Familiarização com a infraestrutura dos laboratórios de redes<br />
*Familiarização com ferramentas de rede: ifconfig, ping, traceroute;<br />
*Desenvolver a noção de endereçamentos de rede IP e de endereço de hardware (MAC)<br />
*Desenvolver a noção de rotas em redes IP<br />
*Testar a conectividade IP com ping<br />
<br />
*Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)]<br />
<br />
==Laboratório 2 - Wireshark e encapsulamento==<br />
<br />
*Familiarização com o sniffer de rede WireShark<br />
*Observar o comportamento do ping e se familiarizar com o processo de encapsulamento;<br />
<br />
**Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)]<br />
<br />
==Conceituando Protocolos e Aplicações de Rede==<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/Conceituando%20protocolos.pdf Conceituando protocolos]<br />
<br />
<br />
=AULA 12 - Dia 03/10/2019=<br />
<br />
==Objetivos==<br />
<br />
*Conceituando protocolos<br />
*Protocolos de aplicação: exemplo http<br />
*O serviço DNS<br />
<br />
==Laboratório 3 - Conceituando protocolo==<br />
<br />
Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)#Laborat.C3.B3rios]<br />
<br />
==Laboratório 4 - Desvendando o HTTP com Wireshark - BÁSICO==<br />
<br />
Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)#Laborat.C3.B3rios]<br />
<br />
==Laboratório 7 - O DNS ==<br />
<br />
Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)#Laborat.C3.B3rios]<br />
<br />
{{collapse bottom}}<br />
<br />
<br />
<br />
{{collapse top | Semestre 2019-1 - Prof. Tiago Semprebom e Eraldo Silveira e Silva}}<br />
<br />
=Professor=<br />
<br />
:*Prof. [[Tiago Semprebom]]<br />
:*email: tisemp@ifsc.edu.br<br />
:*sala: Sala de II de Professores da Área de Telecomunicações (primeira sala lado da Biblioteca - direção esquerda)<br />
<br />
=12/03/2019=<br />
<br />
==Objetivos==<br />
<br />
===Parte 1===<br />
*Apresentar os professores e o coordenador;<br />
*Apresentar o IFSC: estrutura, câmpus e serviços<br />
*Apresentar o curso: perfil do egresso, competências gerais, áreas de atuação do egresso e conteúdos previstos<br />
*Apresentar o Cronograma Tentativa<br />
*Apresentar metodologia e forma de avaliação<br />
<br />
===Parte 2===<br />
<br />
*Conceitos de Hardware, Software e Firmware<br />
*Arquiteturas de processadores<br />
*Classificação de softwares<br />
*Conceitos de Sistemas Operacionais e exemplos<br />
<br />
===Parte 3===<br />
<br />
*Histórico do Linux<br />
*Linux e GNU/Linux<br />
*Arquitetura do Linux<br />
*Distribuições<br />
*Distribuições usadas no IFSC/SJ<br />
*Ligando e Desligando o Sistema<br />
*Primeiros contatos.<br />
<br />
==Professores do FIC Linux Edição 2019-1==<br />
*Prof. [[Tiago Semprebom]] (Introdução ao Linux)<br />
*Prof. [[Eraldo Silveira e Silva]] (Redes com Linux)<br />
<br />
==Apresentação do IFSC==<br />
<br />
*[http://www.ifsc.edu.br/estrutura-organizacional-inicio Página do IFSC]<br />
*[https://www.sj.ifsc.edu.br/index.php Página do Câmpus]<br />
<br />
==Apresentação do Curso==<br />
<br />
*[[ISL-FicLinux_(Plano_de_Ensino) | Introdução ao Linux]]<br />
*[[PRL-FicLinux (página) | Projeto de Rede Residencial com o Linux]]<br />
*[[Curso_de_Formação_Continuada_de_Configuração_de_Redes_de_Computadores_Linux | PPC do Curso e Outras Regulamentações]]<br />
<br />
==Cronograma Tentativa==<br />
<br />
Horários: 19h às 22h.<br />
<br />
{| class="wikitable"|<br />
| AULA || DATA || Professor || Conteúdo<br />
|-<br />
| 1 || 12/03/2019 || TIAGO || Programa da Disciplina.Forma de Avaliação. O computador: hardware e software. SO Linux: histórico e distribuições. Ligando/Logando/Desligando a Máquina. Conceitos básico de Sistema de Arquivos e Processos.<br />
|-<br />
| 2 || 14/03/2019 || TIAGO || Gerenciamento de Arquivos I: Operações sobre arquivos e diretórios usando o terminale o Nautilus.<br />
|-<br />
| 3 || 21/03/2019 || TIAGO || Gerenciamento de Arquivos II: continuação Operações sobre arquivos e diretórios. Links Simbólicos, Criação de Arquivo com vi e outros editores.<br />
|-<br />
| 4 || 26/03/2019 || TIAGO || Interfaces Gráficas: X11, Gnome. KDE e outras. Instalação de Programas via Gerenciador de Pacotes.<br />
|-<br />
| 5 || 28/03/2019 || TIAGO || Administração de contas de usuários I<br />
|-<br />
| 6 || 02/04/2019 || TIAGO || Administração de contas de usuários II<br />
|-<br />
| 7 || 04/04/2019 || TIAGO || Permissionamento de Arquivos<br />
|-<br />
| 8 || 09/04/2019 || TIAGO || Gerenciamento de Processos<br />
|-<br />
| 9 || 11/04/2019 || TIAGO || Introdução ao Shell Script<br />
|-<br />
| 10 || 16/04/2019 || TIAGO || Avaliação 1 - Introdução ao Sistema Operacional Linux<br />
|-<br />
| 11 || 09/10/2019 || ERALDO || Introdução a Redes. Conceito de Protocolos. Ferramentas de Rede.<br />
|-<br />
| 12 || 11/10/2019 || ERALDO || Protocolos de Aplicação: exemplo http <br />
|-<br />
| 13 || 16/10/2019 || ERALDO || O DNS como protocolo de Aplicação; Camada de Transporte: protocolo UDP <br />
|-<br />
| 14 || 18/10/2019 || ERALDO || Protocolo TCP. Diferenças dos protocolos de Transporte TCP/UDP. Camada IP e aspectos da configuração da mesma sob o Linux<br />
|-<br />
| 15 || 23/10/2017 || ERALDO || Camada de Enlace/Física. Hubs X Switches. O Papel do Protocolo ARP. Outros serviços/protocolos: Serviço DHCP e NAT<br />
|-<br />
| 16 || 25/10/2017 || ERALDO (TIAGO) || Segmentação Redes IP. Cálculo de subredes. <br />
|-<br />
| 17 || 30/10/2017 || ERALDO || Introdução ao IPV6. Introdução ao Access Point TPLINK N750: configuração da LAN e WAN<br />
|-<br />
| 18 || 01/11/2017 || ERALDO || Serviço SSH no Linux. Acesso a rede WIFI. Conceitos básicos de redes sem fio.<br />
|-<br />
| 19 || 06/11/2007 || ERALDO || Tópicos Adicionais sobre redes no Linux: Configuração Manual X NetworkManager. Relatório Avaliativo 1.<br />
|-<br />
| 20 || 08/11/2017 || ERALDO || Relatório Avaliativo 2<br />
|}<br />
<br />
==Metodologia, Avaliação e Critérios de Aprovação==<br />
<br />
*Aaulas expositivas e aulas práticas no laboratório. Nas aulas práticas serão desenvolvidos exercícios e trabalhos individuais.<br />
*Avaliações individuais: Listas de exercícios com aproveitamento e entregues no prazo. <br />
*Critérios para aprovação: Serão considerados aprovados os alunos que obtiverem conceito final 6 ou superior em cada componente curricular. ATENÇÂO: Possuir no mínimo 75% de presença<br />
<br />
==Bibliografia==<br />
<br />
#Odilson Tadeu Valle<br />
##Administração de redes com Linux: fundamentos e práticas<br />
##Editora IFSC, 2010<br />
#Gleydson Mazioli da Silva<br />
##Guia Foca Linux<br />
##http://www.guiafoca.org/<br />
#Luiz Carlos Lobato Lobo de Medeiros e Wendel Soares<br />
##Formação de suporte técnico PROINFO<br />
##https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo<br />
#Ari Frazão Jr e Marcelo Braga<br />
##Administração de Sistemas Linux<br />
##https://pt.scribd.com/doc/128912228/Administracao-de-Sistemas-Linux<br />
<br />
==Conceitos de Hardware, Software e Firmware==<br />
<br />
*Em informática, o hardware consiste nos equipamentos<br />
**Ex: Computador, teclado, mouse, monitor<br />
*Software é um aplicativo, desenvolvido em uma linguagem de programação<br />
**Ex: Windows, Linux, Mozilla Firefox, Google Chrome<br />
*Firmware é um conjunto de instruções básicas e específicas para um hardware<br />
**Ex: BIOS nos computadores, sistemas de controle das máquinas de lavar, etc.<br />
<br />
==Estrutura de um Computador e Arquitetura de Processadores==<br />
<br />
*Bits, [https://pt.wikipedia.org/wiki/Byte Bytes] e tamanho de memória;<br />
*Representação de Caracteres: [https://pt.wikipedia.org/wiki/ASCII Tabela ASCII];<br />
*O [https://pt.wikipedia.org/wiki/Microprocessador microprocessador], barramentos e memórias semicondutoras: RAM,ROM, E2PROM, FLASH;<br />
*Memórias cache e memórias secundárias;<br />
*[https://pt.wikipedia.org/wiki/Mem%C3%B3ria_virtual Memória Virtual] e Swapping;<br />
*Registradores de 32bits ou 64bits<br />
*Arquitetura [https://pt.wikipedia.org/wiki/X86 x86] / [https://pt.wikipedia.org/wiki/AMD64 x86-64] – presente nos computadores pessoais<br />
*Arquitetura ARM – presente em sistemas embarcados e dispositivos móveis<br />
*Múltiplos núcleos (core)<br />
*Máquinas Virtuas: VirtualBox, UML (User Mode Linux).<br />
<br />
==O papel do Sistema Operacional==<br />
<br />
*O [https://pt.wikipedia.org/wiki/Sistema_operativo SO] é um programa (software) que controla a máquina e a torna utilizável para o usuário;<br />
*Abstrações do Sistema: arquivos e processos;<br />
*Pode ser multitarefa e multiusuário;<br />
*[https://en.wikipedia.org/wiki/Device_driver Driver] de dispositivo<br />
*[https://pt.wikipedia.org/wiki/Multi_boot Múltiplos OS instalados] em um computador. É possível??<br />
<br />
==Sistema de Arquivos==<br />
<br />
*Forma como estão estruturados/organizados os arquivos/dados em uma determinada mídia [https://pt.wikipedia.org/wiki/Sistema_de_ficheiros];<br />
*Um sistema operacional deve saber como acessar e operar sobre este sistema;<br />
*Tipos de sistemas: ext4, NTFS, VFAT32<br />
<br />
==Exemplos de SO==<br />
<br />
*Unix<br />
*Microsoft DOS<br />
*IBM<br />
*Microsoft Windows<br />
*netBSD, freeBSD, openBSD<br />
*Linux<br />
*macOS<br />
*Android<br />
*iOS<br />
<br />
==Histórico do Linux==<br />
<br />
*O início de tudo: UNIX;<br />
*Surgiu em 1991 quando Linus Torvalds, um estudante finlandês, resolveu desenvolver um sistema operacional compatível com a POSIX, por em que pudesse ser executado em arquitetura x86;<br />
*Linux está sob uma licença de software livre e diversas pessoas e empresas contribuem para o desenvolvimento do mesmo.<br />
*E o que é [https://pt.wikipedia.org/wiki/POSIX POSIX]? Define padrões para a interface de programação de aplicações (API) de um OS de forma a manter compatibilidade com o UNIX;<br />
<br />
==Arquitetura do Linux==<br />
<br />
*Ver pg.16 a 19 de [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo]<br />
<br />
==Distribuições==<br />
<br />
Uma distribuição Linux consiste de um kernel Linux e uma coleção de software utilitários e aplicativos de usuário (baseado slides Prof. Emerson)<br />
**Redhat<br />
**Slackware<br />
**Debian<br />
**Ubuntu<br />
**OpenSuse<br />
**Fedora<br />
**CentOS<br />
**Kali<br />
<br />
<br />
Algumas distribuições podem ser executadas diretamente no CD/pendrive<br />
sem a necessidade de fazer sua instalação no disco rígido do computador<br />
<br />
==Distribuições aqui no IFSC SJ==<br />
<br />
*Ubuntu<br />
*Ubuntu Mate (fork do Ubuntu)<br />
*Debian<br />
<br />
==Ligando e Desligando o Sistema Linux==<br />
<br />
*Cuidado ao desligar um OS como o Linux!!! Dados podem ser perdidos.<br />
*Ver [https://pt.wikibooks.org/wiki/Guia_do_Linux/Iniciante%2BIntermedi%C3%A1rio/Introdu%C3%A7%C3%A3o/Ligando_o_computador]<br />
<br />
==O Desktop do Ubuntu - Primeiras Considerações==<br />
<br />
*O Desktop no Ubuntu ver[https://help.ubuntu.com/stable/ubuntu-help/shell-overview.html]<br />
<br />
=AULA 2 - Dia 14/03/2019=<br />
<br />
==Objetivos==<br />
<br />
===PARTE 1===<br />
<br />
*Revisão da aula passada;<br />
*repassar itens não mencionados na aula passada;<br />
**Paginação e Memória [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo pg.19]<br />
**Estrutura do Linux [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo pg.18]<br />
<br />
===PARTE 2===<br />
<br />
*Operações com arquivos e diretórios usando o terminal;<br />
*formato de um comando básico;<br />
*quase tudo no Linux é arquivo: tipos de arquivos, diretórios, arquivos ordinários;<br />
*conceito de sistema de arquivos;<br />
*conceito de referência absoluta e relativa;<br />
*conceito de diretório de entrada, diretório de trabalho;<br />
*mudando de diretório com cd;<br />
*listando diretórios e arquivos com ls;<br />
*vendo o significado de um comando com man;<br />
*criando diretórios com mkdir;<br />
*removendo diretórios e arquivos com rmdir e rm;<br />
*referência com . .. - ~<br />
*criando arquivos ordinários com touch;<br />
*arquivos e diretórios escondidos;<br />
*copiando arquivos;<br />
*movendo e renomeando arquivos;<br />
*vendo a história de comandos com history;<br />
<br />
==Conceito de sistemas de arquivos, arquivos e diretórios==<br />
<br />
* [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Sistemas de Arquivos pg.18]<br />
* [Estrutura básica de diretórios do Sistema Linux]<br />
<br />
==Comandos no Linux==<br />
<br />
* [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Comandos e Interpretador de Comandos no Linux pg.18]<br />
<br />
==Tipos de Arquivos==<br />
<br />
* [https://pt.scribd.com/doc/128912228/Administracao-de-Sistemas-Linux Tipos de Arquivos 12,13 e 14 ]<br />
<br />
==Os comandos de operação sobre arquivos e diretórios==<br />
<br />
*[https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Interpretador de comandos - Comandos Básicos - pg.20 e 21]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_2_FICLinux.pdf Ver lista de exercícios da Aula 2]<br />
<!-- *[https://www.dropbox.com/s/g3xr3wimffde2zm/Aula2_Linux_OperacoesComArquivos_2.pdf Ver lista de exercícios da Aula 3] --><br />
<br />
=AULA 3 - Dia 21/03/2019 (aula com Prof. Eraldo)=<br />
<br />
==Objetivos==<br />
<br />
===PARTE 1===<br />
<br />
*Rever comandos básicos de operações sobre arquivos;<br />
*Usar coringas<br />
*usar opções do comando ls<br />
<br />
===PARTE 2===<br />
<br />
*uso do editor gedit para criar arquivos texto;<br />
*usar comandos cat, more e less para visualizar conteúdos de arquivos.<br />
<br />
===PARTE 3===<br />
<br />
*Criar Links simbólicos<br />
<br />
===Parte 4===<br />
<br />
*Redirecionamento de entradas e saídas;<br />
*Pipes<br />
<br />
==Exercícios para esta aula==<br />
'''Créditos e agradecimentos ao Prof. Eraldo pelo desenvolvimento das listas utilizadas''':<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_3_FICLinux.pdf Mais operações Sobre Arquivos e Diretórios]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_4_FICLinux.pdf Editor Gedit, Link Simbólico]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_5_FICLinux.pdf Editor vi]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_6_FICLinux.pdf Entradas e Saídas]<br />
<br />
=AULA 4 - Dia 26/03/2019=<br />
<br />
==Objetivos==<br />
<br />
===PARTE 1===<br />
<br />
*Revisão geral<br />
<br />
<br />
===PARTE 2===<br />
<br />
*Redirecionamento de entradas e saídas: continuação;<br />
*Pipes<br />
<br />
===PARTE 3===<br />
<br />
*Permissão no acesso a arquivos;<br />
*Owner, grupo e outros<br />
<br />
==Exercícios para esta aula==<br />
<br />
=Referências=<br />
<br />
[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_7_FICLinux.pdf Permissão de Acesso a Arquivos: parte 1]<br />
<br />
[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_8_FICLinux.pdf Permissão de Acesso a Arquivos: parte 2]<br />
<br />
=AULA 5 - Dia 28/03/2019=<br />
<br />
==Objetivos==<br />
<br />
*Revisão e preparação para teste;<br />
*introdução ao gerenciamento de processos;<br />
**conceito de processo<br />
**escalonamento de processos<br />
**PID e PPID<br />
**fork/exec<br />
**espaço de endereçamento de um processo;<br />
**estados de um processo: Running, Stopped, Sleeping, Zombie<br />
<br />
https://www.tecmint.com/linux-process-management/<br />
<br />
==Referências==<br />
<br />
[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_9_FICLinux.pdf Gerenciamento De Processos Parte 1]<br />
[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_10_FICLinux.pdf Gerenciamento De Processos Parte 2]<br />
<br />
[https://www.dropbox.com/s/gm1sv856ailny2e/Aula5_TreinamentoTeste.pdf Treinamento Teste 1]<br />
<br />
=AULA 6 - Dia 02/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*Comandos adicionais de gerenciamento de processos;<br />
*Mudança de prioridade com nice e renice;<br />
*Agendamento de processos com crontab<br />
*Aplicações do crontab: conectividade de rede e backup<br />
*Ferramentas de compactação;<br />
*Execução de comandos inseridos em outros comandos;<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/z1d0itcz9ommhrm/Aula6_Aval1.pdf Avaliação 1]<br />
<br />
=AULA 7 - Dia 04/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*Comandos adicionais de manipulação de arquivos:<br />
**comando grep;<br />
**comando find;<br />
*Gerenciamento de usuários:<br />
**adição e remoção de usuários e grupos<br />
**arquivo sudoers<br />
<br />
<br />
==Exercícios==<br />
<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_11_FICLinux.pdf Comandos Adicionais] <br />
<!--*[https://www.dropbox.com/s/h0v122is4aj9ogr/Aula7_GerenciamentoDeUsuarios_Parte1.pdf Aula 7 - Parte 2]--><br />
<br />
=AULA 8 - Dia 09/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*Introdução ao Shell script<br />
*variáveis<br />
*Comando if<br />
<br />
==Referências==<br />
<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_14_FICLinux.pdf Outros comando gerenciamento de processos]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_12_FICLinux.pdf Shell Parte 1]<br />
<br />
{{collapse top | script DESAFIO (a)}}<br />
<syntaxhighlight lang=c><br />
#!/bin/bash<br />
<br />
FILE="$1"<br />
<br />
if [ ! $# -eq 1 ]; then<br />
echo opa! Algo errado...<br />
echo uso: script parametro<br />
exit<br />
fi<br />
<br />
<br />
if [ -h $FILE ]; then<br />
echo $FILE é um link simbólico<br />
else<br />
echo $FILE não é um link simbólico<br />
fi<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
{{collapse top | script DESAFIO (b)}}<br />
<syntaxhighlight lang=c><br />
<br />
#!/bin/bash<br />
<br />
FILE="$1"<br />
<br />
if [ ! $# -eq 1 ]; then<br />
echo opa! Algo errado...<br />
echo uso: script parametro<br />
exit<br />
fi<br />
<br />
<br />
if [[ -w $FILE && -O $FILE ]]; then<br />
echo Possui permissao de escrita de $FILE<br />
else<br />
echo Colocando permissão de escrita para $FILE<br />
chmod u+w $FILE<br />
echo permissoes adicionadas com sucesso para $FILE ver abaixo<br />
ls -l $FILE<br />
<br />
fi<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
{{collapse top | script DESAFIO (c)}}<br />
<syntaxhighlight lang=c><br />
#!/bin/bash<br />
<br />
FILE1="$1"<br />
FILE2="$2"<br />
<br />
if [ ! $# -eq 2 ]; then<br />
echo opa! Algo errado...<br />
echo uso: script parametro<br />
exit<br />
fi<br />
<br />
if [[ -f $FILE1 && -r $FILE1 ]]; then<br />
echo $1 É regular e possui permissao de leitura<br />
mv $FILE1 $FILE2<br />
echo Mudei o nome de $FILE1 para $FILE2<br />
else<br />
echo $FILE1 não tem permissao...<br />
fi<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
=AULA 9 - Dia 11/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*ainda shell script<br />
*comando for<br />
*comando while<br />
<br />
==Referências==<br />
<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_13_FICLinux.pdf Shell Parte 2]<br />
<br />
=AULA 10 - Dia 16/04/2019=<br />
<br />
*Avaliação da disciplina<br />
<br />
=Tópicos extras=<br />
<br />
==Objetivos==<br />
<br />
*mais alguns tópicos sobre criação de usuários;<br />
*servidores de janelas: X11, <br />
*gerenciadores de janelas e desktops: Gnome, KDE<br />
*instalação de pacotes;<br />
*o Linux e o Software Livre<br />
*avaliação<br />
<br />
==Servidores de Janelas==<br />
<br />
[https://pt.wikipedia.org/wiki/X_Window_System X Windows System]<br />
<br />
[https://en.wikipedia.org/wiki/X_Window_System_protocols_and_architecture Arquitetura do X]<br />
<br />
==Desktops e Geneciadores de Janelas==<br />
<br />
[https://pt.wikipedia.org/wiki/Interface_gr%C3%A1fica_do_utilizador Interfaces Gráficas]<br />
<br />
==Instalando pacotes==<br />
<br />
[https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Ver pg.43 do Formacao-de-Suporte-Tecnico-Proinfo]<br />
<br />
[http://www.hardware.com.br/tutoriais/tutorial-completo-apt-get/ uso do apt-get]<br />
<br />
Exercício: instalar e executar um servidor ssh:<br />
<br />
sudo apt-get update<br />
sudo apt-get install openssh-server<br />
sudo service start ssh<br />
<br />
Acessar o ssh de outra máquina<br />
ssh usuario@numero_ip<br />
<br />
Exportar o display e executar o comando remoto:<br />
export DISPLAY=IP_cliente_ssh:0.0<br />
firefox &<br />
<br />
Conferir se o firefox realmente está se executando (use o ps)<br />
<br />
Remover o pacote ssh server:<br />
<br />
sudo apt-get remove openssh-server<br />
<br />
==Linux = Software Livre==<br />
<br />
[https://pt.wikipedia.org/wiki/Software_livre]<br />
<br />
<br />
<br />
[https://www.novell.com/coolsolutions/feature/1532.html]<br />
<br />
==Onde baixar o Ubuntu==<br />
<br />
[https://www.ubuntu.com/download/desktop Baixar Ubuntu daqui]<br />
<br />
==Sobre o Boot==<br />
<br />
[http://www.rodsbooks.com/linux-uefi/ by Roderick W. Smith]<br />
<br />
[https://www.happyassassin.net/2014/01/25/uefi-boot-how-does-that-actually-work-then/ AdamW on Linux and more]<br />
<br />
==Sobre o Desktop Environment e o Desktop Shell==<br />
<br />
[https://ittutorials.net/linux/ubuntu/desktop-guide/ /desktop-guide]<br />
<br />
==Instalar Ubuntu no Virtual Box==<br />
<br />
[http://www.edivaldobrito.com.br/virtualbox-no-linux/ Instalar VirtualBox no Linux]<br />
<br />
[http://www.bosontreinamentos.com.br/virtualizacao/como-instalar-o-virtualbox-no-windows-para-criacao-de-maquinas-virtuais/ Instalar VirtualBox no Windows]<br />
<br />
[http://www.techtudo.com.br/dicas-e-tutoriais/noticia/2016/04/como-instalar-o-ubuntu-com-o-virtualbox.html Instalar Linux no VirtualBox]<br />
<br />
=AULA 11 - Dia 23/04/2019=<br />
<br />
*Introdução a Redes de Computadores<br />
**Conceito Básicos em Redes e Protocolos<br />
**Ferramentas de Redes<br />
**Exemplo de Protocolo de Aplicação: http<br />
**O processo de encapsulamento<br />
<br />
==Plano de Ensino==<br />
<br />
*[https://wiki.sj.ifsc.edu.br/index.php/PRL-FicLinux_(Plano_de_Ensino) Plano de Ensino]<br />
<br />
<br />
==Laboratório 1 - Ferramentas de Rede e Conceitos Básicos==<br />
<br />
*Familiarização com a infraestrutura dos laboratórios de redes<br />
*Familiarização com ferramentas de rede: ifconfig, ping, traceroute;<br />
*Desenvolver a noção de endereçamentos de rede IP e de endereço de hardware (MAC)<br />
*Desenvolver a noção de rotas em redes IP<br />
*Testar a conectividade IP com ping<br />
<br />
*Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)]<br />
<br />
==Laboratório 2 - Wireshark e encapsulamento==<br />
<br />
*Familiarização com o sniffer de rede WireShark<br />
*Observar o comportamento do ping e se familiarizar com o processo de encapsulamento;<br />
<br />
**Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)]<br />
<br />
==Conceituando Protocolos e Aplicações de Rede==<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/Conceituando%20protocolos.pdf Conceituando protocolos]<br />
<br />
=AULA 12 - Dia 25/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*Protocolos de aplicação: exemplo http<br />
<br />
==Laboratório 4 - Desvendando o HTTP com Wireshark - BÁSICO==<br />
<br />
Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)#Parte_1:_Observando_interfaces_do_sistema_com_ifconfig]<br />
<br />
=AULA 13 - Dia 30/04/2019=<br />
<br />
*Revisão do Conceito de Protocolo ([-] Laboratório 3 - Conceituando protocolos )<br />
*O DNS como protocolo de Aplicação;<br />
*Camada de Transporte: protocolo UDP<br />
<br />
==Revisão dos Conceitos de Protocolo==<br />
<br />
Laboratório 3 - Conceituando protocolos [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)#Parte_1:_Observando_interfaces_do_sistema_com_ifconfig]<br />
<br />
==O DNS como protocolo de Aplicação==<br />
<br />
Laboratório 7 - Serviço de Nomes (DNS) [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)#Parte_1:_Observando_interfaces_do_sistema_com_ifconfig]<br />
<br />
==O Protocolo UDP==<br />
<br />
Laboratório 8 - Desvendando o UDP - Básico <br />
<br />
=AULA 14 - Dia 02/05/2019=<br />
<br />
==Objetivos==<br />
<br />
*Explorar o papel e diferenças dos protocolos de Transporte TCP/UDP<br />
*Explorar a Camada IP e aspectos da configuração da mesma sob o Linux<br />
<br />
<br />
===TCP e UDP===<br />
<br />
*docente.ifsc.edu.br/odilson/RCO60803/TCP%20controle%20de%20erros.pdf<br />
*docente.ifsc.edu.br/odilson/RCO60803/UDP%20Basico.pdf<br />
<br />
==Camada IP no Linux: Configuração das Interfaces usando ifconfig e ip addr==<br />
<br />
Usando a ferramenta Netkit2, que permite construir redes virtuais com o Linux vamos construir DUAS redes locais interligadas por um roteador. Em cada rede colocaremos dois PCs. As interfaces estarão completamente desconfiguradas:<br />
<br />
<ol><br />
<li><br />
Construir um arquivo texto de nome rede.conf usando o editor de texto gedit.<br />
<code>gedit rede.conf &</syntaxhighlight> <br />
</li><br />
<li><br />
Criar a seguinte topologia:<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=generic<br />
<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
#Definição da Topologia da Rede<br />
<br />
pc1[eth0]=lan0<br />
pc2[eth0]=lan0<br />
<br />
pc3[eth0]=lan1<br />
pc4[eth0]=lan1<br />
<br />
r1[eth0]=lan0<br />
r1[eth1]=lan1<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Executar netkit fazendo (atualize se necessário - pergunte para o professor como fazer):<br />
Aplicativos >> Educativo >> Netkit2 <br />
</li><br />
<li><br />
Carregar o arquivo lab.conf a partir do Netkit2:<br />
<code>File >> Load Only</syntaxhighlight><br />
</li><br />
<li><br />
Visualizar a rede a ser implementada:<br />
<code>File >> Graph</syntaxhighlight><br />
</li><br />
<li> <br />
Executar a configuração:<br />
<code>Network >> Start</syntaxhighlight><br />
</li><br />
<li><br />
Verificar o estado de todas interfaces (se UP ou DOWN) com:<br />
<code>ifconfig -a</syntaxhighlight><br />
<code>ip addr</syntaxhighlight> <br />
Note que nas últimas versões do Linux o comando ip vem sendo recomendado (embora o ifconfig ainda esteja disponível).<br />
</li><br />
<li><br />
Vamos configurar as interfaces. Para tanto vamos assumir que teremos duas sub-redes:<br />
<code>lan0 - endereço da rede 10.10.10.0/24</syntaxhighlight><br />
<code>lan1 - endereço da rede 20.20.20.0/24</syntaxhighlight><br />
A interface eth0 de PC1 receberá o endereço 10.10.10.1/24 e a interface eth0 de PC2 recebera 10.10.10.2/24. A interface do roteador NA lan0 também deve receber um endereço: 10.10.10.254/24:<br />
<br />
No PC1:<br />
<code>ifconfig eth0 10.10.10.1/24</syntaxhighlight><br />
No PC2:<br />
<code>ifconfig eth0 10.10.10.2/24</syntaxhighlight><br />
No R1:<br />
<code>ifconfig eth0 10.10.10.254/24</syntaxhighlight><br />
</li> <br />
<li><br />
Seguindo a mesma lógica configure as máquinas e o roteador na lan1<br />
</li><br />
<li> Um ponto importante a ser lembrado é que quando uma interface é configurada com um número IP, a tabela de roteamento do sistema é alimentada com o número correspondente da rede associada ao número. Isto pode ser observado em TODAS as máquinas, inclusive no roteador:<br />
<code> route -n </syntaxhighlight><br />
ou <br />
<code> ip route </syntaxhighlight><br />
</li><br />
</ol><br />
<br />
==Camada IP no Linux: verificando e configurando rotas - configuração da rota default ==<br />
<br />
<ol><br />
<li> Um ponto importante a ser lembrado é que quando uma interface é configurada com um número IP, a tabela de roteamento do sistema é alimentada com o número correspondente da rede associada ao número. Isto pode ser observado em TODAS as máquinas, inclusive no roteador:<br />
<code> route -n </syntaxhighlight><br />
ou <br />
<code> ip route </syntaxhighlight><br />
Esta informação é importante pois define a entrega DIRETA de pacotes na rede, ou seja, se PC1 quiser enviar um pacote para PC2, esta linha na tabela de roteamento garante que o pacote IP seja despachado diretamente para o PC2 através de um frame ETHERNET endereçado para o MAC do PC1.<br />
</li><br />
<li> Confira os endereços MAC e IP das interfaces dos PC1 e PC2 e anote. Faça um ping no PC1 em direção a PC2.<br />
<code>root@pc1:~# ping 10.10.10.2</syntaxhighlight><br />
</li><br />
<li> Use um capturador de pacotes em modo texto para observar o tráfego na eth0 do PC2. Observe os endereços MAC do Frame Ethernet e os endereços IP do pacote IP.<br />
<code>root@pc2:~# tcpdump -i eth0 -e</syntaxhighlight><br />
ENTÃO? O que se pode concluir? É uma entrega direta ou indireta? <br />
</li><br />
<li> Uma curiosidade. Tente observar o tráfego na interface eth0 do Roteador R1. É possível observar algo? O que se pode concluir? Pare agora o ping e os tcpdumps executados.<br />
</li><br />
<li> Qualquer máquina IP acaba tomando uma decisão de roteamento. O PC1, ao observar que PC2 está na sua própria rede 10.10.10.0/24, entrega diretamente o pacote. E se PC1 tentar entregar para PC3? Faça um ping e observe o que acontece:<br />
<code>root@pc1:~#ping 20.20.20.1</syntaxhighlight><br />
Não deve ter funcionado :-(<br />
Um primeiro problema é que simplesmente a camada IP observa que o endereço não é entrega DIRETA mas não tem informação (linha) na tabela de roteamento dizendo para quem deve ser entregue o pacote. <br />
</li><br />
<li> Vamos acrescentar uma linha na tabela de PC1 dizendo como fazer esta entrega INDIRETA. Usaremos o conceito de gateway default. Ou seja, se não tiver para quem entregar explicitamente, o pacote será entregue para o gateway default:<br />
<code>root@pc1:~# route add default gateway 10.10.10.254</syntaxhighlight><br />
confira o estabelocimento da rota:<br />
<code>root@pc1:~# route -n</syntaxhighlight><br />
tente o ping novamente escutando com o tcpdump na interface eth0 de R1. Ainda não funcionou mas o R1 já recebe os pacotes. Confira o MAC de destino do pacote. Deve ser o MAC do roteador. <br />
</li> <br />
<li><br />
POR QUE NÃO FUNCIONOU: será que R1 não sabe como entregar o pacote para PC3? Confira se o pacote sai de R1 na rede lan1:<br />
<code>root@r1:~# tcpdump -i eth2 -e</syntaxhighlight><br />
</li> <br />
<li><br />
Temos um problema ainda que o nosso roteador Linux NÃO está habilitado a ser roteador. Isto pode ser feito com:<br />
<code>echo 1 > /proc/sys/net/ipv4/ip_forward</syntaxhighlight><br />
</li> <br />
<li> Tente novamente o ping de PC1 para PC3. Ainda não funcionará mas escute a interface eth1 de R1 e a interface eth0 de PC3 e verá que os pacotes do ICMP REQUEST estão chegando. Confira inclusive os MACs envolvidos...<br />
</li><br />
<li><br />
O que estaria faltando ainda para que PC3 responda aos ECHO REQUEST? O problema é de entrega indireta. O PC3 não sabe como entregar pacotes "externos". Acrescente um gateway default.<br />
</li><br />
<li><br />
Exercício adicional com 2 roteadores. Ver manual:<br />
* [http://linux-ip.net/html Guia de Administração da Camada IP no Linux<br />
</li><br />
</ol><br />
<br />
==Exercício: acrescentando uma lan2 com com 2 PCs no roteador==<br />
<br />
Acrescente uma rede 30.30.30.0/24 (lan2) no roteador R1. Acrescente 2 PCs e configure o sistema.<br />
Teste a conectividade entre todos os PCs.<br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
pc5[type]=generic<br />
pc6[type]=generic<br />
<br />
pc7[type]=generic<br />
pc8[type]=generic<br />
<br />
<br />
#Definição da Topologia da Rede<br />
<br />
pc1[eth0]=lan0:ip=10.10.10.1/24<br />
pc1[default_gateway]=10.10.10.254<br />
<br />
pc2[eth0]=lan0:ip=10.10.10.2/24<br />
pc2[default_gateway]=10.10.10.254<br />
<br />
pc3[eth0]=lan1:ip=20.20.20.1/24<br />
pc3[default_gateway]=20.20.20.254<br />
<br />
pc4[eth0]=lan1:ip=20.20.20.2/24<br />
pc4[default_gateway]=20.20.20.254<br />
<br />
pc5[eth0]=lan2:ip=30.30.30.1/24<br />
pc5[default_gateway]=30.30.30.254<br />
<br />
pc6[eth0]=lan2:ip=30.30.30.2/24<br />
pc6[default_gateway]=30.30.30.254<br />
<br />
pc7[eth0]=lan4:ip=40.40.40.1/24<br />
pc7[default_gateway]=40.40.40.254<br />
<br />
pc8[eth0]=lan3:ip=50.50.50.1/24<br />
pc8[default_gateway]=40.40.40.254<br />
<br />
<br />
r1[eth0]=lan0:ip=10.10.10.254/24<br />
r1[eth1]=lan1:ip=20.20.20.254/24<br />
r1[eth2]=lan2:ip=30.30.30.254/24<br />
r1[eth3]=lan3:ip=50.50.50.253/24<br />
r2[eth1]=lan3:ip=50.50.50.254/24<br />
r2[eth0]=lan4:ip=40.40.40.254/24<br />
<br />
r2[route]=10.10.10.0/24:gateway=50.50.50.253<br />
<br />
</syntaxhighlight><br />
<br />
=AULA 15 - Dia 7/05/2019=<br />
<br />
*Hubs X Switches. O Papel do Protocolo ARP<br />
<br />
<br />
*Serviço DHCP e NAT<br />
[-] Laboratório 16 - Sub-redes e Roteamento Estático em Redes <br />
<br />
==Hubs, Switches. Protocolo ARP==<br />
<br />
[Laboratório 17 - Tecnologia de Enlace Ethernet]<br />
<br />
==Serviço DHCP==<br />
<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IP_DHCP_NAT.pdf DHCP e NAT]<br />
<br />
Construir uma rede simular a aula anterior mas deixar PC1 e PC2 desconfigurados. Criar uma máquina para atuar como servidor DHCP. <br />
<br />
<ol><br />
<li><br />
Editar o arquivo de configuração do dhcp server:<br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=gateway #já habilitado para forward<br />
<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
pcdhcp[type]=generic<br />
<br />
<br />
#Definição da Topologia da Rede<br />
<br />
pc1[eth0]=lan0 #desconfigurada...<br />
<br />
pc2[eth0]=lan0:ip=10.10.10.2/24<br />
pc2[default_gateway]=10.10.10.254<br />
<br />
pcdhcp[eth0]=lan0:ip=10.10.10.3/24<br />
pcdhcp[default_gateway]=10.10.10.254 <br />
<br />
pc3[eth0]=lan1:ip=20.20.20.1/24<br />
pc3[default_gateway]=20.20.20.254<br />
<br />
pc4[eth0]=lan1:ip=20.20.20.2/24<br />
pc4[default_gateway]=20.20.20.254<br />
<br />
<br />
r1[eth0]=lan0:ip=10.10.10.254/24<br />
r1[eth1]=lan1:ip=20.20.20.254/24<br />
<br />
</syntaxhighlight><br />
</li><br />
<li> No server estabelecer a configuração desejada:<br />
<br />
nano /etc/dhcp/dhcpd.conf<br />
<br />
com:<br />
<br />
<code><br />
<br />
subnet 10.10.10.0 netmask 255.255.255.0 {<br />
range 10.10.10.10 10.10.10.50;<br />
option routers 10.10.10.254;<br />
option broadcast-address 10.10.10.255;<br />
default-lease-time 600;<br />
max-lease-time 7200;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
</li><br />
<li><br />
Rodar o servidor DHCP na máquina pc_dhcp:<br />
<code><br />
/usr/sbin/dhcpd -q -4 -pf /run/dhcp-server/dhcpd.pid -cf /etc/dhcp/dhcpd.conf eth0<br />
</syntaxhighlight><br />
</li><br />
<li><br />
No cliente (PC1) fazer:<br />
<code><br />
dhclient -v eth0<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Usando o ifconfig e route confira se o PC1 está completamente configurado. Faça teste com o ping<br />
</li><br />
<li> Rode o tcpdump na eth0 de r1 para "verificar" os pacotes DHCP:<br />
<code><br />
tcpdump -i eth0<br />
</syntaxhighlight><br />
</li><br />
<li> Repetir a operação no PC2. Baixe a interface antes:<br />
<code><br />
ifconfig eth0 down<br />
dhclient -v eth0<br />
</syntaxhighlight><br />
</li><br />
</ol><br />
<br />
==O NAT==<br />
<br />
Vamos tentar elaborar um laboratório usando o NAT MASQUERADE<br />
https://www.karlrupp.net/en/computer/nat_tutorial<br />
<br />
Construir uma rede com 3 LANs e 2 roteadores como na aula passada. Executar o APACHE em uma máquina da lan3 (exemplo PC4). Não colocar rotas para lan0 em r2. Desta forma PC1 não deve pingar em PC4. <br />
<br />
<code><br />
LAN0 <-R1-> LAN1 <-R2 -> LAN3<br />
</syntaxhighlight><br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
pc1[type]=generic<br />
apache[type]=generic<br />
<br />
<br />
pc1[eth0]=lan0:ip=10.10.10.1/24<br />
pc1[default_gateway]=10.10.10.254<br />
<br />
<br />
r1[eth0]=lan0:ip=10.10.10.254/24<br />
r1[eth1]=lan1:ip=20.20.20.254/24<br />
r1[route]=30.30.30.0/24:gateway=20.20.20.253<br />
<br />
r2[eth0]=lan1:ip=20.20.20.253/24<br />
r2[eth1]=lan2:ip=30.30.30.254/24<br />
<br />
apache[eth0]=lan2:ip=30.30.30.1/24<br />
apache[default_gateway]=30.30.30.254<br />
</syntaxhighlight><br />
<br />
<ol><br />
<li> Rodar o apache em PC4:<br />
<code> /etc/init.d/apache2 start </syntaxhighlight><br />
</li><br />
<li> Testar se o Apache é acessível a partir de PC3<br />
<code>lynx END_PC3 </syntaxhighlight><br />
<li><br />
Em R1 fazer:<br />
<code>iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE</syntaxhighlight><br />
</li><br />
<li> Monitorar os pacotes que chegam e saem da eth0 de PC4.<br />
</li><br />
<li> Fazer em PC1:<br />
lynx END_PC4 #endereço de PC4.<br />
O que se pode concluir?<br />
</li><br />
<br />
</ol><br />
<br />
=AULA 16 - Dia 09/05/2019=<br />
*Endereçamento IPv4.<br />
*Exercícios segmentação Redes. <br />
<br />
===Objetivos===<br />
*Compreender endereçamento IPv4.<br />
*Compreender o processo de alocação de faixas de IPs.<br />
*Compreender e manipular os números IPs.<br />
*Compreender e manipular as máscaras de rede.<br />
*Proporcionar ao aluno uma visão prática de roteamento IP.<br />
<br />
===Fonte Básica===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IP_DHCP_NAT.pdf DHCP e NAT]<br />
*[http://www.davidc.net/sites/default/subnets/subnets.html Cálculo de sub-redes]<br />
<br />
===Roteiro===<br />
<br />
#Baseado no arquivo exemplo abaixo, crie um arquivo de configuração para o NetKit que implemente sua proposta. O arquivo deve contemplar todas as configurações necessárias para o perfeito funcionamento da rede, ou seja, ao carregar o arquivo todos os hosts deverão ser capazes de "pingar" uma ao outro. <br />
##Faça testes de conectividade entre os hosts.<br />
##Demonstre para o professor o perfeito funcionamento de sua rede.<br />
*O arquivo de configuração do Netkit abaixo, é a definição para o funcionamento da simulação da rede apresentada na Figura 2. Falta adicionar as rotas.<br />
<br />
[[Arquivo:DynamicRoutingTriangle.png |thumb | 400px| Figura 2 - Rede exemplo]]<br />
<br />
<code><br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=link0:ip=192.168.0.1/24<br />
pc2[eth0]=link1:ip=192.168.1.1/24<br />
pc3[eth0]=link2:ip=192.168.2.1/24<br />
<br />
# Default gateways definitions<br />
pc1[default_gateway]=192.168.0.254<br />
pc2[default_gateway]=192.168.1.254<br />
pc3[default_gateway]=192.168.2.254<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
r3[type]=gateway<br />
<br />
# Routers' interfaces to local networks<br />
r1[eth0]=link0:ip=192.168.0.254/24<br />
r2[eth0]=link1:ip=192.168.1.254/24<br />
r3[eth0]=link2:ip=192.168.2.254/24<br />
<br />
# Network "backbone" links<br />
r1[eth1]=backbone0:ip=10.0.0.1/30<br />
r1[eth2]=backbone1:ip=10.0.1.1/30<br />
<br />
r2[eth1]=backbone0:ip=10.0.0.2/30<br />
r2[eth2]=backbone2:ip=10.0.2.1/30<br />
<br />
r3[eth1]=backbone1:ip=10.0.1.2/30<br />
r3[eth2]=backbone2:ip=10.0.2.2/30 <br />
<br />
# Routes definition<br />
r1[route]=192.168.2.0/24:gateway=10.0.1.2<br />
r1[route]=192.168.1.0/24:gateway=10.0.0.2<br />
r1[route]=10.0.2.0/30:gateway=10.0.0.2<br />
<br />
r2[route]=192.168.0.0/24:gateway=10.0.0.1 <br />
r2[route]=192.168.2.0/24:gateway=10.0.2.2<br />
r2[route]=10.0.1.0/30:gateway=10.0.2.2<br />
<br />
r3[route]=192.168.0.0/24:gateway=10.0.1.1<br />
r3[route]=192.168.1.0/24:gateway=10.0.2.1<br />
r3[route]=10.0.0.0/30:gateway=10.0.2.1<br />
</syntaxhighlight><br />
<br />
===Exercícios Extras (resolvidos)===<br />
*[[Arquivo:exercicios_CIDR.pdf]]<br />
<br />
===Referencia===<br />
*[http://www.davidc.net/sites/default/subnets/subnets.html Link Calculador Online de Subnets]<br />
<br />
=AULA 17 - Dia 14/05/2019=<br />
<br />
*Finalização do Laboratório do NAT<br />
*Laboratório de Introdução ao IPV6<br />
*Introdução ao Access Point TPLINK N750: configuração da LAN e WAN<br />
<br />
==LAboratório de Introdução ao IPv6==<br />
<br />
===Material de REferência===<br />
<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IPv6.pdf IPv6]<br />
<br />
===Roteiro de atividades sobre o IPv6===<br />
<br />
A figura abaixo apresenta o diagrama esquemático da rede a ser montada/analisada. Observe que todos os IPv6 ''Global Unicast'' já estão definidos na mesma, são esses IPs que utilizaremos em nosso experimento.<br />
<br />
[[Arquivo:Diagrama_rede_IPv6.jpg]]<br />
<br />
#Crie em seu computador um arquivo com nome '''/home/aluno/IPv6.conf''', com o seguinte conteúdo: <syntaxhighlight lang=bash><br />
#Ligacao das maquinas nos dominios de colisao<br />
#Duas pequenas redes interligadas pelo backbone<br />
<br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=link0:ipv6=2001:bcc:faca:1::101/64<br />
pc2[eth0]=link1:ipv6=2001:bcc:cafe:1::102/64<br />
pc3[eth0]=HUB1:ipv6=2001:bcc:1f0:1::103/64<br />
pc4[eth0]=HUB1<br />
<br />
#Default Gateways definitions<br />
pc1[route]=default6:gateway=2001:bcc:faca:1::1<br />
pc2[route]=default6:gateway=2001:bcc:cafe:1::1<br />
pc3[route]=default6:gateway=2001:bcc:1f0:1::1<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
#Routers interfaces definitions<br />
r1[eth0]=backbone0:ipv6=2001:db8:dead:1::1/64<br />
r1[eth1]=link0:ipv6=2001:bcc:faca:1::1/64<br />
r1[eth2]=link1:ipv6=2001:bcc:cafe:1::1/64<br />
<br />
r2[eth0]=backbone0:ipv6=2001:db8:dead:1::2/64<br />
r2[eth1]=HUB1:ipv6=2001:bcc:1f0:1::1/64<br />
<br />
#Routers definitions<br />
r1[route]=2001:bcc:1f0:1::0/64:gateway=2001:db8:dead:1::2<br />
r2[route]=2001:bcc:faca:1::0/64:gateway=2001:db8:dead:1::1<br />
r2[route]=2001:bcc:cafe:1::0/64:gateway=2001:db8:dead:1::1<br />
</syntaxhighlight><br />
#Tenha certeza que o Netkit2 estja atualizado: General >> Update.<br />
#Rode o NetKit em seu computador. Em um terminal digite: <syntaxhighlight lang=bash><br />
netkit2 & </syntaxhighlight><br />
#No menu '''File''' - '''Load and Run''', procure o arquivo '''/home/aluno/IPv6.conf''' e clique em OK. Abrirá uma janela com 6 abas, onde cada uma delas é um terminal de configuração do respectivo equipamento: '''pc1-4''' ou '''r1-2'''.<br />
#Observe que o '''pc4''' não está com sua interface configurada.<br />
#Ao clicar no menu '''File''' - '''Graph''', pode-se ter uma visão da rede a ser simulada e conferir se é equivalente ao diagrama proposto.<br />
#Faça um '''ping6''' entre o '''pc1''' ao '''pc3''': <syntaxhighlight lang=bash><br />
ping6 -c4 2001:bcc:1f0:1::103 </syntaxhighlight><br />
#Faça um '''ping6''' entre o '''pc1''' e '''pc2'''.<br />
#No '''pc4''' use o seguinte comando para adicionar o endereço IPv6 à interface de rede: <syntaxhighlight lang=bash><br />
ip addr add 2001:bcc:1f0:1::104/64 dev eth0 </syntaxhighlight><br />
#No '''pc4''', acrescente o ''default gateway'' com o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add default via 2001:bcc:1f0:1::1 dev eth0 </syntaxhighlight><br />
#No '''pc1''' use o seguinte comando para verificar como ficou a configuração dos endereços da interface de rede. O resultado é similar ao apresentado pelo comando '''ifconfig''': <syntaxhighlight lang=bash><br />
ip addr show dev eth0 </syntaxhighlight><br />
#Todo o roteamento está pronto, mas caso desejássemos poderíamos acrescentar rotas com comando similares aos já utilizados. Por exemplo, no '''r1''', para adicionar uma rota estática para a rede dos '''pc3''' e '''pc4''' utilizaríamos o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add 2001:bcc:1f0:1::/64 via 2001:db8:dead:1::2 dev eth0 </syntaxhighlight><br />
#Confira as rotas estabelecidas em todos os ''hosts'' com o comando abaixo. <br />
##São coerentes com os dados apresentados no diagrama acima?<syntaxhighlight lang=bash><br />
ip -6 route show </syntaxhighlight><br />
#No '''pc1''' use os seguintes comandos para ver a rota para alguns vizinhos: <syntaxhighlight lang=bash><br />
traceroute6 2001:bcc:1f0:1::103<br />
traceroute6 2001:bcc:1f0:1::104 </syntaxhighlight><br />
#*Anote as rotas.<br />
#Deixe um '''ping6''' entre o '''pc1''' ao '''pc3''' rodando: <syntaxhighlight lang=bash><br />
ping6 2001:bcc:1f0:1::103 </syntaxhighlight><br />
<br />
==Introdução ao Roteador-AP da TP-Link==<br />
<br />
Ver manual https://www.tp-link.com/us/support/download/tl-wdr4300/<br />
<br />
===Configuração Básica===<br />
<br />
Seguir as instruções do professor para a seguinte configuração:<br />
<br />
#Retirar o plugue cabo ethernet que liga o PC do Lab a rede do IFSC. Conectar o PC a uma das portas LAN do AP;<br />
#Conectar a WAN do AP ao Lab. do IFSC;<br />
#Em um terminal do PC aplique o comando:<br />
sudo dhclient eth0<br />
#No browser do PC acesse o AP colocando o endereço:<br />
http://tplinklogin.net<br />
#Entrar com user admin e senha admin<br />
#Configurar a WAN para DHCP (IP dinâmico)<br />
#Configurar a LAN para DHCP na faixa 192.168.0.10 a 192.168.0.100<br />
#Usar uma máquina virtual para testar a aquisição do IP:<br />
pc1[type]=generic<br />
pc1[eth0]=uplink:bridge=eth0<br />
<br />
DESAFIO 1: Elabore um experimento para mostrar que a LAN do AP funciona como um switch.<br />
Sugestão: Use uma máquina adicional colocada em uma porta do AP.<br />
<br />
DESAFIO 2: Elabore um experimento para mostrar como o NAT funciona no AP. Se inspire no experimento realizado sobre o NAT.<br />
<br />
=AULA 18 - Dia 16/05/2019=<br />
<br />
==Objetivos==<br />
<br />
<br />
PARTE 0 - Exercício de Revisão<br />
<br />
PARTE 1 - Serviços de rede sobre o Linux<br />
<br />
*serviço SSH no Linux<br />
<br />
PARTE 2 - Acesso a rede WIFI<br />
<br />
*conceitos básicos de redes sem fio: pg.103 de [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo]<br />
*configuração da WIFI no Access Point e Acesso via Linux<br />
<br />
===PARTE 0===<br />
<br />
Considere a rede abaixo definida pelo arquivo do netkit. Configure as redes com os seguintes prefixos:<br />
<br />
*lan0: 50.50.50.0/24<br />
*lan1: 60.60.60.0/24<br />
*lan2: 70.70.70.0/24<br />
<br />
O pc2dhcp deve ser configurado como servidor DHCP e deverá liberar IPs na faixa de 50.50.50.100/24 a 50.50.50.200/24. Todos os PCs receberão IP estáticos com exceção do PC1 que deverá receber dinamicamente o endereço. Toda a configuração deve ser realizada manualmente.<br />
<br />
Teste a conectividade entre todos os PCs. Usando o tcpdump demonstre que quando PC2 faz um ping em PC4 a entrega será indireta. Demonstre usando o MAC address das máquinas como apoio. Chame o professor para demonstrar.<br />
<br />
ALGUNS COMANDOS NOTÁVEIS:<br />
<br />
ifconfig<br />
ifconfig eth0 10.10.10.1/24<br />
route -n<br />
route add default gw 200.10.1.254<br />
route del -net 200.10.1.0/24 gw 200.10.2.1<br />
route add -net 200.10.1.0/24 gw 200.10.2.1<br />
<br />
tcpdump -i eth1 -n -e<br />
<br />
<code><br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2dhcp[type]=generic<br />
<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=lan0<br />
pc2dhcp[eth0]=lan0<br />
<br />
pc3[eth0]=lan1<br />
<br />
pc4[eth0]=lan2<br />
<br />
r1[eth0]=lan0<br />
r1[eth1]=lan1<br />
<br />
r2[eth0]=lan1<br />
r2[eth1]=lan2<br />
</syntaxhighlight><br />
<br />
Solução:<br />
R1:<br />
ifconfig eth0 50.50.50.254/24<br />
ifconfig eth1 60.60.60.254/24<br />
route add -net 70.70.70.0/254 gw 60.60.60.253<br />
R2:<br />
ifconfig eth1 70.70.70.254/24<br />
ifconfig eth0 60.60.60.253/24<br />
route add -net 50.50.50.0/24 gw 60.60.60.254<br />
PC2DHCP:<br />
ifconfig eth0 50.50.50.2/24<br />
route add default gateway 50.50.50.254<br />
configurar server: nano /etc/dhcp/dhcpd.conf<br />
# A slightly different configuration for an internal subnet.<br />
subnet 50.50.50.0 netmask 255.255.255.0 {<br />
range 50.50.50.100 50.50.50.200;<br />
# option domain-name-servers ns1.internal.example.org;<br />
# option domain-name "internal.example.org";<br />
option routers 50.50.50.254;<br />
option broadcast-address 50.50.50.255;<br />
default-lease-time 600;<br />
max-lease-time 7200;<br />
}<br />
<br />
/usr/sbin/dhcpd -q -4 -pf /run/dhcp-server/dhcpd.pid -cf /etc/dhcp/dhcpd.conf eth0<br />
PC3:<br />
ifconfig eth0 60.60.60.1/24<br />
route add default gw 60.60.60.254 #note que poderia ser para o outro roteador (R2)<br />
PC4:<br />
ifconfig eth0 70.70.70.1/24<br />
route add default gw 70.70.70.254<br />
PC1:<br />
dhclient eth0 -v<br />
<br />
==Serviço SSH==<br />
<br />
O Serviço SSH se utiliza do modelo cliente-servidor. Deve-se executar um servidora ssh na máquina que permitirá o acesso remoto.<br />
Um cliente a partir de uma outra máquina poderá logar remotamente usando um cliente ssh ou poderá fazer outras operações, tipo cópia remota<br />
de arquivos.<br />
<br />
===ETAPA 1 - Rodando o servidor SSH===<br />
*Baseado no Material do Prof.Odilson Valle<br />
<br />
No Ubuntu server:<br />
<ol><br />
<li><br />
<code>sudo su</syntaxhighlight><br />
<code>apt-get update</syntaxhighlight><br />
<code>apt-get install ssh</syntaxhighlight> O SSH já estará funcionando normalmente.<br />
Para configurações extras deve-se editar o arquivo /etc/ssh/sshd_config e acrescentar, por exemplo:<br />
*X11Forwarding yes (no) ### habilita/desabilita acesso com ambiente gráfico remoto<br />
*AllowUsers Fred Wilma ### Libera o acesso somente para os usuários Fred e Wilma<br />
*DenyUsers Dino Pebbles ### Bloqueia o acesso aos usuários Dino e Pebbles e libera para os demais usuários<br />
*AllowGroups admin ### Libera o acesso somente para o grupo admin.<br />
</li><br />
<li><br />
Após modificar o arquivo de configuração deve-se reiniciar o serviço: <code>service ssh restart</syntaxhighlight><br />
</li><br />
<li><br />
Criar um usuário na máquina servidora:<br />
<code>adduser alien</syntaxhighlight><br />
</li><br />
<li><br />
Logar como alien:<br />
<code>su alien</syntaxhighlight><br />
</li><br />
</ol><br />
<br />
===ETAPA 2 - Logando remotamente===<br />
<br />
<ol><br />
<li><br />
Para acessar o servidor basta digitar em um terminal: <br />
<code>ssh alien@ip_do_servidor. </syntaxhighlight> Será solicitado a senha.<br />
</li><br />
<li><br />
Confira que está "dentro" da máquina remota:<code>hostname</syntaxhighlight><br />
</li><br />
<li><br />
Confira os arquivos do diretório corrente:<code>ls -l</syntaxhighlight><br />
</li><br />
</ol><br />
<br />
<br />
===ETAPA 3 - Cópia Remota de aquivos===<br />
<br />
#Na máquina hospedeira/cliente, EM OUTRO TERMINAL, criar um arquivo qualquer usando um editor de texto:<code>gedit teste.txt &</syntaxhighlight><br />
#Envie o arquivo para a máquina servidora: <code>scp teste.txt alien@IP_MAQUINA_SERVIDORA:./</syntaxhighlight><br />
#No terminal onde está logado remotamente confira se o arquivo está copiado: <code>ls -l</syntaxhighlight><br />
#Mude o nome do arquivo: <code>mv teste.txt alfat.txt</syntaxhighlight><br />
#No terminal da máquina cliente traga novamente o arquivo: <code>scp alien@IP_MAQUINA_SERVIDORA:./alfa.txt .</syntaxhighlight><br />
#Confira se o arquivo foi copiado corretamente: <code>ls -l</syntaxhighlight><br />
<br />
==PARTE 2 - Configuração do Access Point na rede de 2.4Ghz==<br />
<br />
#Entrar na configuração do AP conforme aula anterior.<br />
#Conectara a WAN do AP na rede do laboratório e o PC em uma porta da LAN do AP.<br />
#Configurar a WAN para IP dinâmico.<br />
#Configurar a rede WIreless 2.4 Ghz:<br />
##Nome SSID: nome FIC-NomeAluno<br />
##Configurar canal AUTO e channel width para AUTO<br />
##Habilite o broadcast da rede.<br />
#Configurar segurança (Wireless Security) para WPA versão Automática, Criptografia AES e password ABCDEF<br />
#Configurar o DHCP na LAN para distribuir endereços entre 192.168.0.100 e 192.168.0.200<br />
#Salve as configurações<br />
#Reboote o roteador<br />
<br />
==Acessando a rede de dispostivo Celular==<br />
<br />
#Teste o acesso a rede a partir de um celular. No Androi ligue e desligue o wifi. Deve aparecer a lista de dispositivos.<br />
<br />
==Habilitando Filtros por MAC==<br />
<br />
*Na configuração da WLAN entre em Wireless MAC Filtering<br />
*Em Filtering Rules coloque Deny (negar)<br />
*Adicione um terminal que deseja bloquear o acesso. Utilize o MAC do seu celular (veja em configurações do telefone ou anote na opção Wireless Statistics)<br />
*Habilite o Filtro e tente se conectar<br />
<br />
OBS: Este filtro é interessante para ter maior segurança na rede, garantindo que somente dispositivos gabilitados possam acessá-la.<br />
<br />
==Coloque no ar a rede 5Ghz==<br />
<br />
Repita o procedimento da rede de 2.4Ghz e coloque-a no ar.<br />
<br />
Teste a conectividade com o celular.<br />
<br />
<br />
<br />
=AULA 19 - Dia 21/05/2019=<br />
<br />
==Objetivos==<br />
<br />
*Tópicos Adicionais sobre redes no Linux: Configuração Manual X NetworkManager<br />
**Opções de Acesso a Internet: ADSL, Cabo<br />
**Sistema de Arquivos em Rede: Samba Server<br />
*Relatório de Avaliação 1<br />
*Opções de Extensão da Rede Wireless<br />
<br />
==Tópicos Adicionais sobre redes no Linux==<br />
<br />
===Configuração da Rede no Linux - o NetworkManager===<br />
<br />
Ao longo do curso estudamos vários comandos para ver e modificar parâmetros de rede. Entretanto, em uma instalação padrão de um sistema Linux Ubuntu vamos verificar que existe um serviço de suporte a estas configurações que permite configurar interfaces graficamente e reconectar/escolher uma rede. Trata-se do NetworkManager. Ver alguns detalhes aqui [https://www.hardware.com.br/dicas/entendendo-networkmanager.html] e aqui[https://wiki.debian.org/pt_BR/NetworkManager]. Este serviço tenta fornecer a melhor conectividade possível usando as interfaces disponíveis. O serviço é composto por:<br />
<br />
*um processo do sistema (roda como serviço) monitorando constantemente as interfaces;<br />
*uma applet para interação com o usuário (canto direito da interface);<br />
<br />
O NetworkManager vai ignorar as configurações das interfaces realizadas em /etc/network/interfaces<br />
<br />
Teste o uso do NetworkManager. Clique no topo do desktop a direita e inspecione as interfaces disponíveis.<br />
<br />
Em algumas situações pode ser desejável desabilitar o NetworkManager. Na linha de comando pode ser executado:<br />
<br />
sudo service network-manager stop<br />
<br />
===Configurando interfaces de forma manual ===<br />
<br />
TEXTO baseado nas anotações do Prog.Marcelo Sobral:<br />
<br />
O arquivo ''/etc/network/interfaces'' contém declarações para configurar as interfaces de rede. Um exemplo de configuração básica contida nesse arquivo pode ser vista a seguir:<br />
<br />
<syntaxhighlight lang=text><br />
auto lo eth0<br />
iface lo inet loopback<br />
iface eth0 inet dhcp<br />
</syntaxhighlight><br />
<br />
Esse exemplo pode ser interpretado assim:<br />
* ''Linha 1'': declara que as interfaces ''lo'' e ''eth0'' devem ser ativadas automaticamente no boot. Se uma interface não aparecer em uma declaração como esta, então ela não será ativada. OBS: interface ativadas desta forma NÃO são controladas pelo ''NetworkManager''.<br />
* ''Linha 2'': configura a interface ''lo'' como sendo do tiupo ''loopback''. Essa é uma interface especial criada puramente em software (uma interface de rede virtual), usada para comunicação entre processos de um mesmo computador.<br />
* ''Linha 3'': configura a interface ''eth0'' de forma dinâmica usando [[GER-2010-1#DHCP|DHCP]]. A configuração de rede é solicitada usando a própria rede. Ness ecaso, deve existir algum equipamento ou computador nessa rede que seja um servidor DHCP, capaz de responder com uma mensagem contendo a configuração de rede a ser utilizada.<br />
<br />
<br />
O exemplo anterior é bastante simplificado, uma vez que a configuração de rede de fato é obtida dinamicamente com DHCP. Isso pode ser suficiente para computadores usados somente para acesso a Internet, mas não para computadores que sejam servidores. Nesse caso, é melhor definir uma configuração de rede estática, como mostrado a seguir:<br />
<br />
<syntaxhighlight lang=text><br />
auto lo eth0<br />
iface lo inet loopback<br />
iface eth0 inet static<br />
address 172.18.80.251<br />
netmask 255.255.128.0<br />
gateway 172.18.0.254<br />
dns-nameservers 191.36.8.2 191.36.8.3<br />
</syntaxhighlight><br />
<br />
<br />
A diferença em relação ao caso anterior está na declaração da interface ''eth0''. Ao invés de configurá-la com ''DHCP'', declararam-se todas as informações de rede. Assim, essa interface sempre será ativada com essas informações configuradas. No exemplo apresentado, as configurações de rede são:<br />
* ''address 172.18.80.251'': endereço IP da interface<br />
* ''netmask 255.255.128.0'': máscara de rede<br />
* ''gateway 172.18.0.254'': endereço do gateway (ou roteador ''default'')<br />
* ''dns-nameservers 191.36.8.2 191.36.8.3'': servidores DNS a serem utilizados (podem-se especificar um ou mais endereços IP)<br />
<br />
O [http://manpages.ubuntu.com/manpages/trusty/en/man5/interfaces.5.html manual do arquivo /etc/network/interfaces] apresenta muitos outros detalhes sobre possíveis configurações de rede.<br />
<br />
Antes da alteração de configuração de uma interface é interessante desativá-la:<br />
ifdown eth0<br />
Alterar o arquivo /etc/network/interfaces<br />
<br />
E na sequência ativá-la novamente:<br />
ifup eth0<br />
ou<br />
sudo /etc/init.d/networking restart<br />
<br />
O comando ifup vai consultar o arquivo e alterar as configurações. Indiretamente, o script networking também usa o ifup para ativar as configurações (e todas demais que forem realizadas).<br />
<br />
==Relatório Avaliativo 1==<br />
<br />
Criar um arquivo no OpenOffice nomeando-o SeuNomeSemEspaco-FICLinux-2019-A1<br />
<br />
Copiar e responder as questões abaixo:<br />
<br />
1.Faça um ifconfig na interface eth0. Cole um recorte da tela no espaço abaixo e faça um texto indicando qual o endereço de hardware associado a esta interface, qual o endereço IPv4 e qual a máscara de subrede.<br />
<br />
<br />
2.Faça um experimento usando o ping e o wireshark mostrando como o DNS atua para resolver o nome que está sendo "pingando". Informe em texto abaixo qual o IP do servidor DNS local e qual o IP do site que está sendo "pingado".<br />
<br />
<br />
3,Execute o laboratório do Netkit da forma e cole abaixo a figura da rede fornecida pelo netkit:<br />
<code><br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
<br />
# Hosts' interfaces to local routers<br />
<br />
r1[eth0]=lan0<br />
r1[eth1]=lan1<br />
<br />
pc1[eth0]=lan0<br />
pc2[eth0]=lan0<br />
pc3[eth0]=lan1<br />
</syntaxhighlight><br />
<br />
<br />
4.Configure todas as interfaces dos PC usando para lan0 o prefixo 50.50.50.0/24 e para lan1 use no lugar de 50 o dia de seu nascimento.<br />
Cole uma tela mostrando PC1 pingando PC3. <br />
<br />
5.Informe abaixo o MAC da eth0 do roteador.<br />
<br />
6.Usando o tcpdump na eth0 do roteador mostre que a entrega é indireta.<br />
<br />
==Estendendo a rede através da LAN usando segundo AP e WAN==<br />
<br />
Conecte um segundo AP (WAN do segundo AP a LAN do primeiro AP). Teste a conectividade colocando uma máquina Linux na LAN do segundo AP.<br />
Esta configuração deve funcionar mas impõe um overhead adicional devido ao NAT realizado duas vezes... <br />
<br />
DESAFIO: mostrar que o NAT está sendo duplicado.<br />
<br />
[[Arquivo:WLAN-2PAs-viaWAN.png]]<br />
<br />
==Estendendo a rede através da LAN usando segundo AP e LAN==<br />
<br />
Discuta com o colega ao lado e pense como poderia conectar o segundo AP via LAN. Uma configuração adicional será necessária.<br />
<br />
==Estendendo a rede através do Wireless (WDS)==<br />
<br />
Estude no manual como poderia estender a rede Sem Fio usando conexão via WDS.<br />
<br />
=AULA 20 - Dia 18/04/2019=<br />
<br />
*Tópicos Adicionais sobre redes no Linux:<br />
**Opções de Acesso a Internet: ADSL, Cabo<br />
**Sistema de Arquivos em Rede: Samba Server (http://www.guiafoca.org/cgs/guia/avancado/ch-s-samba.html)<br />
*Relatório Avaliativo 2<br />
<br />
==Relatório Avaliativo==<br />
<br />
===PARTE 1=== <br />
<br />
Usando a configuração abaixo do netkit2 e uma máquina Virtualbox devidamente configurada implementar a configuração abaixo:<br />
<br />
ATENÇÂO: Vamos substituir a VirtualBox por uma máquina Netkit executada em OUTRO PC com a configuração:<br />
<br />
INSTRUÇÔES para virtual box:<br />
*colocar rede como bridge<br />
*desabilitar o network manager<br />
sudo service network-manager stop<br />
*baixar a interface<br />
sudo ifconfig enp0s3 down<br />
*reconfigurar a interface (usar o endereço do seu grupo)<br />
sudo ifconfig enp0s3 50.50.50.11/24<br />
*colocar a rota direta (que se perdeu) (usar o endereço do seu grupo)<br />
sudo route add -net 50.50.50.0/24 dev enp0s3<br />
*colocar gateway default (usar o endereço do seu grupo)<br />
sudo route add default gateway 50.50.50.1<br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
<br />
pc1[type]=generic<br />
pc1[eth0]=uplink:bridge=eth0:ip=dhcp<br />
<br />
</syntaxhighlight><br />
<br />
<br />
[[Arquivo:Aval2-Parte1-FICLinux2019-2.png]]<br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
pc1[type]=generic<br />
<br />
pc1[eth0]=lan1<br />
<br />
r1[eth0]=uplink:bridge=eth0:ip=VER COM PROFESSOR<br />
r1[eth1]=lan2<br />
<br />
r2[eth0]=lan1<br />
r2[eth1]=lan2<br />
</syntaxhighlight><br />
<br />
Construir um doc conforme aula anterior com as seguintes informações:<br />
<br />
#Coloque a tela de um píng funcionando de R1 para PC1<br />
#Cole a tela da tabela de roteamento de R2<br />
#Cole a tela de um ping de uma máquina VirtualBox (netkit) no R1 (uplink)<br />
#Cole a tela de um ping funcionando uma máquina VirtualBox (netkit) no PC1<br />
<br />
Note que o gateway default da máquina virtual deverá ser reconfigurado para PC1.<br />
<br />
ADENDO: Coloque em R1 rotas para as redes dos PC1 dos demais grupos.<br />
<br />
===PARTE 2===<br />
<br />
Acrescente na sua rede um AP configurado como indicado abaixo:<br />
<br />
OBS: Para este exercício configuramos estaticamente todos os endereços para o lado do backbone (Laboratório). Usamos 50.50.50.0/24<br />
<br />
[[Arquivo:Aval2-Parte2-FICLinux2019-2.png]]<br />
<br />
<br />
=ATIVIDADE DE RECUPERAÇÃO 1=<br />
<br />
Refazer o relatório Avaliativo 1 proposto anteriormente. Enviar doc para o SIGA A<br />
<br />
=ATIVIDADE DE RECUPERAÇÃO 2=<br />
<br />
Registre em um DOC e faça um post no SIGA A colando a imagem das telas das saídas de cada comando!<br />
<br />
===Roteiro de atividades sobre o IPv6===<br />
<br />
A figura abaixo apresenta o diagrama esquemático da rede a ser montada/analisada. Observe que todos os IPv6 ''Global Unicast'' já estão definidos na mesma, são esses IPs que utilizaremos em nosso experimento.<br />
<br />
[[Arquivo:Diagrama_rede_IPv6.jpg]]<br />
<br />
#Crie em seu computador um arquivo com nome '''/home/aluno/IPv6.conf''', com o seguinte conteúdo: <syntaxhighlight lang=bash><br />
#Ligacao das maquinas nos dominios de colisao<br />
#Duas pequenas redes interligadas pelo backbone<br />
<br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=link0:ipv6=2001:bcc:faca:1::101/64<br />
pc2[eth0]=link1:ipv6=2001:bcc:cafe:1::102/64<br />
pc3[eth0]=HUB1:ipv6=2001:bcc:1f0:1::103/64<br />
pc4[eth0]=HUB1<br />
<br />
#Default Gateways definitions<br />
pc1[route]=default6:gateway=2001:bcc:faca:1::1<br />
pc2[route]=default6:gateway=2001:bcc:cafe:1::1<br />
pc3[route]=default6:gateway=2001:bcc:1f0:1::1<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
#Routers interfaces definitions<br />
r1[eth0]=backbone0:ipv6=2001:db8:dead:1::1/64<br />
r1[eth1]=link0:ipv6=2001:bcc:faca:1::1/64<br />
r1[eth2]=link1:ipv6=2001:bcc:cafe:1::1/64<br />
<br />
r2[eth0]=backbone0:ipv6=2001:db8:dead:1::2/64<br />
r2[eth1]=HUB1:ipv6=2001:bcc:1f0:1::1/64<br />
<br />
#Routers definitions<br />
r1[route]=2001:bcc:1f0:1::0/64:gateway=2001:db8:dead:1::2<br />
r2[route]=2001:bcc:faca:1::0/64:gateway=2001:db8:dead:1::1<br />
r2[route]=2001:bcc:cafe:1::0/64:gateway=2001:db8:dead:1::1<br />
</syntaxhighlight><br />
#Tenha certeza que o Netkit2 estja atualizado: General >> Update.<br />
#Rode o NetKit em seu computador. Em um terminal digite: <syntaxhighlight lang=bash><br />
netkit2 & </syntaxhighlight><br />
#No menu '''File''' - '''Load and Run''', procure o arquivo '''/home/aluno/IPv6.conf''' e clique em OK. Abrirá uma janela com 6 abas, onde cada uma delas é um terminal de configuração do respectivo equipamento: '''pc1-4''' ou '''r1-2'''.<br />
#Observe que o '''pc4''' não está com sua interface configurada.<br />
#Ao clicar no menu '''File''' - '''Graph''', pode-se ter uma visão da rede a ser simulada e conferir se é equivalente ao diagrama proposto.<br />
#Faça um '''ping6''' entre o '''pc1''' ao '''pc3''': <syntaxhighlight lang=bash><br />
ping6 -c4 2001:bcc:1f0:1::103 </syntaxhighlight><br />
#Faça um '''ping6''' entre o '''pc1''' e '''pc2'''.<br />
#No '''pc4''' use o seguinte comando para adicionar o endereço IPv6 à interface de rede: <syntaxhighlight lang=bash><br />
ip addr add 2001:bcc:1f0:1::104/64 dev eth0 </syntaxhighlight><br />
#No '''pc4''', acrescente o ''default gateway'' com o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add default via 2001:bcc:1f0:1::1 dev eth0 </syntaxhighlight><br />
#No '''pc1''' use o seguinte comando para verificar como ficou a configuração dos endereços da interface de rede. O resultado é similar ao apresentado pelo comando '''ifconfig''': <syntaxhighlight lang=bash><br />
ip addr show dev eth0 </syntaxhighlight><br />
#Todo o roteamento está pronto, mas caso desejássemos poderíamos acrescentar rotas com comando similares aos já utilizados. Por exemplo, no '''r1''', para adicionar uma rota estática para a rede dos '''pc3''' e '''pc4''' utilizaríamos o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add 2001:bcc:1f0:1::/64 via 2001:db8:dead:1::2 dev eth0 </syntaxhighlight><br />
#Confira as rotas estabelecidas em todos os ''hosts'' com o comando abaixo. <br />
##São coerentes com os dados apresentados no diagrama acima?<syntaxhighlight lang=bash><br />
ip -6 route show </syntaxhighlight><br />
#No '''pc1''' use os seguintes comandos para ver a rota para alguns vizinhos: <syntaxhighlight lang=bash><br />
traceroute6 2001:bcc:1f0:1::103<br />
traceroute6 2001:bcc:1f0:1::104 </syntaxhighlight><br />
#*Anote as rotas.<br />
#Deixe um '''ping6''' entre o '''pc1''' ao '''pc3''' rodando: <syntaxhighlight lang=bash><br />
ping6 2001:bcc:1f0:1::103 </syntaxhighlight><br />
<br />
=ATIVIDADE DE RECUPERAÇÃO 3=<br />
<br />
Registre em um DOC e faça um post no SIGA A colando a imagem das telas das saídas de cada comando! Coloque também a resposta as perguntas.<br />
<br />
===Objetivos===<br />
<br />
*Familiarizar-se com o UDP<br />
*Entender a estrutura do pacote UDP<br />
*Entender o conceito de portas<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/UDP%20Basico.pdf Introdução a camada de transporte e UDP básico]<br />
<br />
===Parte 1 - Fluxo único UDP===<br />
<br />
#Combinar equipes com dois computadores para execução do experimento.<br />
#*Uma equipe escutará na porta 5000 e a outra equipe transmitirá uma mensagem nessa porta. Os processos de transmissão e recepção podem ocorrer simultaneamente, em terminais distintos.<br />
#*Cada equipe deve identificar os IPs ('''IP_DEST''') das máquinas de seus pares.<br />
#Cada equipe deve abrir uma Janela de terminal.<br />
#Cada equipe deve preparar o '''Wireshark''', interfaces '''any''', para escuta das portas no protocolo UDP usando um filtro:<syntaxhighlight lang=bash><br />
udp.port==5000</syntaxhighlight><br />
#A equipe da escuta na porta 5000 executa no terminal: <syntaxhighlight lang=bash><br />
netcat -u -l -p 5000 </syntaxhighlight><br />
#A equipe que irá transmitir para a porta 5000 executa no terminal: <syntaxhighlight lang=bash><br />
netcat -u IP_DEST 5000 </syntaxhighlight><br />
#*Em seguida escreve no terminal uma mensagem de até 20 caracteres, ao teclar <Enter> a mensagem será enviada.<br />
#*O wireshark deve ter capturado os pacotes UDP <br />
#Identifique e anote os seguintes dados na captura do wireshark:<br />
#*IP FONTE e DESTINO<br />
#*PORTAS FONTE E DESTINO para ambas comunicações<br />
#*Campo de protocolo no pacote IP<br />
#*Campo de tamanho (anote o tamanho) e ''checksum'' no pacote (datagrama) UDP<br />
#*O campo de dados no pacote UDP<br />
#Troquem os papéis das equipes: quem houvia agora transmite mensagens.<br />
#Cada equipe pode transmitir sequencialmente várias mensagens, devendo identificar múltiplos datagramas UDP.<br />
#PERGUNTAS baseadas na captura:<br />
##Qual o tamanho de cada campo do cabeçalho do pacote UDP?<br />
##Qual o tamanho máximo do número de porta?<br />
##Qual o tamanho máximo da área de dados (payload) do pacote?<br />
##Qual o número identificador de protocolo UDP no pacote IP? <br />
##Em algum momento foi identificado algum procedimento para estabelecimento de conexão? <br />
##Em algum campo do UDP existe numeração de mensagens?<br />
<br />
=AULA 20 - Dia 18/04/2019=<br />
<br />
{{collapse bottom}}<br />
<br />
==Curso FIC Linux 2018==<br />
<br />
{{collapse top|Semestre 2018-2 - Prof. André D'Amato}}<br />
<br />
== Introdução ao Sistema Operacional Linux ==<br />
<br />
'''10/09/18: Aula01'''<br />
<br />
Apresentação da Disciplina, Introdução a Informática e Memória e Armazenamento<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula01.pdf Aula 01]<br />
<br />
{{collapse bottom}}<br />
<br />
==Curso FIC Linux 2016==<br />
<br />
{{collapse top|Semestre 2016-2 - Prof. Luciano Barreto}}<br />
<br />
== Introdução ao Sistema Operacional Linux ==<br />
<br />
'''04/10/16: Aula01'''<br />
<br />
Apresentação da Disciplina, Introdução a Informática e Memória e Armazenamento<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula01.pdf Aula 01]<br />
<br />
'''06/10/16: Aula 02'''<br />
<br />
Introdução ao Linux, Sistema de Arquivos e Conhecendo o Terminal<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula02.pdf Aula 02]<br />
<br />
''' 11/10/2016: Aula 03'''<br />
<br />
Continuação Comandos no Terminal<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula03.pdf Aula 03]<br />
<br />
''' 13/10/2016: Aula 04''' <br />
<br />
Continuação Comandos no Terminal<br />
<br />
''' 18/10/2016: Aula 05''' <br />
<br />
Lista de Exercícios<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/ficlinux-aula05-exercicios.pdf Aula 05 - Lista de Exercícios]<br />
<br />
''' 20/10/2016: Aula 06'''<br />
<br />
Introdução ao Gerenciamento de Processos<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula06-processos.pdf Aula 06 - Gerenciamento de Processos]<br />
<br />
''' 25/10/2016: Aula 07''' <br />
<br />
Gerenciamento de Usuários<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula07-usuariosgrupos.pdf Aula 07 - Gerenciamento de Usuários]<br />
<br />
Permissionamento<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula07-permissionamento.pdf Aula 07 - Permissionamento]<br />
<br />
''' 27/10/2016: Aula 08'''<br />
<br />
Continuação Permissionamento<br />
<br />
Instalação Linux<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula8-instalacao.pdf Aula 08 - Instalação Linux] <br />
<br />
''' 01/11/2016: Aula 09'''<br />
<br />
Continuação Instalação Linux<br />
<br />
Instalação de Pacotes via Apt<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula9-pacotes.pdf Aula 09 - Instalação Pacotes] <br />
<br />
''' 03/11/2016: Aula 10'''<br />
Continuação Lista Exercícios (47 - 60)<br />
<br />
=AULA 11 - Dia 18/04/2019=<br />
<br />
=AULA 12 - Dia 18/04/2019=<br />
<br />
=AULA 13 - Dia 18/04/2019=<br />
<br />
=AULA 14 - Dia 18/04/2019=<br />
<br />
=AULA 15 - Dia 18/04/2019=<br />
<br />
=AULA 16 - Dia 18/04/2019=<br />
<br />
=AULA 17 - Dia 18/04/2019=<br />
<br />
=AULA 18 - Dia 18/04/2019=<br />
<br />
=AULA 19 - Dia 18/04/2019=<br />
<br />
=AULA 20 - Dia 18/04/2019=<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top|Semestre 2016-1 - Prof. Luciano Barreto}}<br />
<br />
= Diário de Aulas 2016 - 1 =<br />
<br />
==29/03/16: Apresentação do curso==<br />
Apresentação do curso, Visão geral de funções, responsabilidades e estruturas de um SO.<br />
<br />
==31/03/16: Introdução a Sistema de Arquivos e Terminal==<br />
Estrutura do Sistema de Arquivos Linux, Introdução a comandos no Terminal.<br />
<br />
==04/04/16: Continuação Terminal==<br />
Continuação de comandos no terminal, redirecionamento de saída e caracteres coringa.<br />
<br />
==07/04/16: Introdução a Processos e Usuários==<br />
Conhecendo Processos e Gerenciamento de usuários<br />
<br />
==12/04/16: Lista de Exercícios de Comandos no Terminal==<br />
<br />
[http://bellard.org/jslinux/ Emulador de Terminal no navegador (demora um pouquinho pra abrir)]<br />
<br />
==14/04/16: Usuários, Grupos e Permissões==<br />
Administração de usuários, grupos e adicionando permissões a arquivos.<br />
<br />
==19/04/16: Instalação do Linux==<br />
Instalação do Sistema Linux em modo texto, gráfico e dualboot.<br />
<br />
==26/04/16: Introdução ao Shell Script==<br />
Introdução ao Shell Script<br />
<br />
==28/04/16: Continuação ao Shell Script==<br />
Introdução ao Shell Script<br />
<br />
==03/05/16: Lista de Exercícios==<br />
Lista de Exercícios até a aula de 28/04/16<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top|Semestre 2015-2}}<br />
<br />
*'''Professores:''' [[Ana Paula Rosa Negri]] e [[Francisco de Assis Souza dos Santos]]<br />
<br />
{| style="background-color:#ABCDEF; font-family:verdana,Arial, Helvetica, sans-serif; font-size:100%; margin:0; border: 1px solid #C7D0F8; padding:7px 7px 0px 7px; text-align:center;" width="100%"<br />
| | Bem-vindo ao<br /><br />
<span style="font-size:200%">'''Curso de Formação Continuada de Configuração de Redes de Computadores Linux''' <br />do Instituto Federal de Santa Catarina - Campus São José</span><br />
|}<br />
<br />
Introdução ao Sistema Operacional Linux<br />
<br />
*'''Professores:''' [[Ana Paula Rosa Negri]] e [[Francisco de Assis Souza dos Santos]]<br />
*'''Encontros:''' Terças e quintas das 19:00 às 22:00 no Laboratório de Apoio ao Ensino.<br />
<br />
*[[ISL-FicLinux_(Plano_de_Ensino)| Plano de Ensino]]<br />
*[[Cronograma de atividades (ISL-FicLinux) | Cronograma]]<br />
<br />
= Diário de Aulas 2015 =<br />
== 13/10 ==<br />
'''Parte 1:'''<br />
Slides da aula:<br />
[[Arquivo:introducao.pdf]]<br />
<br>Exercício sobre taxa de transferência:<br />
[[Arquivo:Exercicio_taxa_Transferencia.pdf]]<br />
<br><br />
<br />
'''Parte 2:'''<br />
Slides da Aula:<br />
[[Arquivo:LinuxModoTexto.pdf]]<br />
<br>Exercícios sobre comandos básicos do Linux:<br />
[[Arquivo:ExercícioLinuxTexto.pdf]]<br />
<br />
== 15/10 ==<br />
'''Parte 3:'''<br />
Slides da Aula:<br />
[[Arquivo:Parte3.pdf]]<br />
== 20/10 ==<br />
'''Parte 4:'''<br />
Slides caracteres coringas: [[Arquivo:Coringas.pdf]]<br />
<br />
Exercícios caracteres coringas: [[Arquivo:Exercício CB03 Pokemon.pdf]]<br />
<br />
'''Parte 5:'''<br />
Sildes Redirecionamento: [[Arquivo: Redirecionamento.pdf]]<br />
<br />
Exercícios redirecionamento e pipe: [[Arquivo: ex_pipe.pdf]]<br />
<br />
== 22/10 ==<br />
'''Parte 6:'''<br />
Slides Processos: [[Arquivo:FICLinux_Processos.pdf]]<br />
<br />
== 27/10 ==<br />
'''Parte 7:''''<br />
Slides Usuários e Grupos: [[Arquivo:UserGroup.pdf]]<br />
<br>Exercícios: [[Arquivo:usuarios.pdf]]<br />
<br>Exercícios (.odt): [[Arquivo:usuarios.odt]]<br />
<br />
== 29/10 ==<br />
'''Parte 8:'''<br />
Slides Introducao a Redes: [[Arquivo:FICLinux_Introducao_Redes.pdf]]<br />
<br />
== 03/11 ==<br />
<br />
'''Parte 9:'''<br />
Slides permissionamento: [[Arquivo:permissionamento.odp]]<br><br />
Exercícios permissionamento: [[Arquivo: Exercício Perm02.odt]]<br><br />
Outro exercício permissionamento: [[Arquivo: Exercício Perm04 GatosRatosCães.odt]]<br />
<br />
== 05/11 ==<br />
<br />
'''Parte 10:'''<br />
Slides Redes - Broadcast: [[Arquivo:FICLinux_Introducao_Redes_Broadcast_01.pdf]]<br><br />
<br />
== 10/11 ==<br />
<br />
'''Parte 11:'''<br />
Slides Script: [[Arquivo:Scripts do Linux.odp]]<br />
<br>Exercícios Scripts: [[Arquivo:Exercício Scripts01 pdfmerger.odt]]<br />
<br />
== 12/11 ==<br />
<br />
'''Parte 12:'''<br />
Introdução para comandos em Bash: [[Arquivo:Introdução ao Shell_2015_1.pdf]]<br />
<br />
{{collapse bottom}}</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)&diff=162010Curso Técnico Integrado de Telecomunicações - Redes de Computadores (RCO)2019-10-03T19:58:11Z<p>127.0.0.1: /* Laboratórios */</p>
<hr />
<div>__NOTOC__<br />
<br />
{{DivulgueEngtelecom}}<br />
==Informações Gerais==<br />
*[[RCO-IntTel|Carga horária, Ementas, Bibliografia]]<br />
*[[RCO-IntTel (Plano de Ensino) | Plano de Ensino]]<br />
*[[Cronograma de atividades (RCO-IntTel) | Cronograma de atividades]]<br />
<br />
==Edições==<br />
*[[RCO60803 2019-1|RCO60803 2019-1 - Trabalho dirigido - Prof. Odilson Tadeu Valle]]<br />
*[[RCO60803 2018-2|RCO60803 2018-2 - Prof. Odilson Tadeu Valle / Prof. Eraldo Silveira e Silva]]<br />
*[[RCO60803 2018-1|RCO60803 2018-1 - Prof. Odilson Tadeu Valle / Prof. Eraldo Silveira e Silva]]<br />
*[[RCO60803 2017-2|RCO60803 2017-2 - Prof. Odilson Tadeu Valle / Prof. Eraldo Silveira e Silva]]<br />
*[[RCO60803 2017-1|RCO60803 2017-1 - Prof. Juliano de Souza / Prof. Eraldo Silveira e Silva]]<br />
*[[RCO60803 2016-2|RCO60803 2016-2 - Prof. Juliano de Souza / Prof. Luciano Barreto]]<br />
*[[RCO60803 2016-1|RCO60803 2016-1 - Prof. Fernando Rodrigues Santos / Prof. Juliano de Souza]]<br />
*[[RCO60803-2015-2|RCO60803 2015-2 - Prof. Simara Sonaglio]]<br />
*[[RCO60803-2015-1|RCO60803 2015-1 - Prof. Arliones Hoeller / Prof. Túlio Ribeiro]]<br />
*[[RCO60803-2014-2|RCO60803 2014-2 - Prof. Arliones Hoeller / Prof. Tomás Grimm / Prof. José Clair]]<br />
<br />
= Material de apoio =<br />
<br />
==''Applets'' do Kurose==<br />
Vários [http://wps.pearsoned.com/ecs_kurose_compnetw_6/216/55463/14198700.cw/ aplicativos] com representação dinâmica de características das redes de computadores.<br />
==Transparências utilizadas durante as aulas==<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/slides-kurose-cap1.pdf Capítulo 1 - Introdução]<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/slides-kurose-cap2.pdf Capítulo 2 - Camada de Aplicação]<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/PPTs%20-%20Cap%C3%ADtulo%202%20-%20FTP%20-%20Email%20-%20P2P.pdf Capítulo 2 - Camada de Aplicação - FTP + EMAIL + P2P]<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/slides-kurose-cap3.pdf Capítulo 3 - Camada de Transporte]<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/PPTs%20-%20Cap%C3%ADtulo%204%20A%20camada%20de%20REDE.pdf Capítulo 4 - Camada de Rede]<br />
<br />
==Slides de Outras Universidades==<br />
<br />
*[https://www.google.com.br/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0ahUKEwiO0aDJu_LTAhWJlZAKHX8JA2wQFggjMAA&url=http%3A%2F%2Fwww.eecs.yorku.ca%2Fcourse_archive%2F2015-16%2FW%2F3214%2FCSE3214_14_TCP_2_2016_posted_part2.pdf&usg=AFQjCNEJh3yITWuyOPZ17bbObT54JqrLCw&sig2=jJwHLo13iooIUaI5F2m-kA TCP Error Control- EECS - LASSONDE]<br />
*[https://www.google.com.br/url?sa=t&rct=j&q=&esrc=s&source=web&cd=2&cad=rja&uact=8&ved=0ahUKEwiO0aDJu_LTAhWJlZAKHX8JA2wQFggpMAE&url=http%3A%2F%2Fwww.eecs.yorku.ca%2Fcourse_archive%2F2015-16%2FW%2F3214%2FCSE3214_14_TCP_2_2016_posted_part1.pdf&usg=AFQjCNHNz8hZ4GHyiDZkcMgomCQBR4KTaA&sig2=nS8450rR2x6C_EM9tT0yWw TCP- Flow and Error Control - LASSONDE]<br />
*[https://www.google.com.br/url?sa=t&rct=j&q=&esrc=s&source=web&cd=3&ved=0ahUKEwjUvtPAmJjUAhXHHZAKHfSBAEgQFghCMAI&url=http%3A%2F%2Fwww.eecs.yorku.ca%2Fcourse_archive%2F2015-16%2FW%2F3214%2FCSE3214_14_TCP_3_2016_posted.pdf&usg=AFQjCNHFkmBZT2Pn_G6e-AuDvJHL6FuZzg&sig2=UxXTDU_OKoMp2jC3K1O-jg Congestion Control - LASSONDE]<br />
*[https://www.cpe.ku.ac.th/~cpj/204325/ Slides/Aula Faculty of Engineering, Kasetsart University]<br />
<br />
== Curiosidades ==<br />
<br />
* [http://www.pop-sc.rnp.br/publico/monitoramento.php Monitoramento do tráfego RNP - PoP-SC]<br />
* [http://memoria.rnp.br/ceo/trafego/panorama.php Monitoramento do tráfego RNP - Nacional]<br />
* [http://www.redclara.net/index.php/pt/red/redclara/topologia-actual-de-la-red Rede Clara Internacional]<br />
* [https://eventos.rnp.br/sites/default/files/activity/activity-presentation/apresentacao_wrnp_2017_eduardo_grizenid_v_1.2.pdf Futura infraestrutura de rede da RNP]<br />
* [https://www.youtube.com/watch?v=IlAJJI-qG2k Animated map shows the undersea cables that power the internet]<br />
* [http://submarine-cable-map-2018.telegeography.com/ Submarine Cable Map 2018]<br />
* [https://www.youtube.com/watch?v=A5dD2x2iQx8 ''History of the Internet'' - legendado]<br />
* [https://www.youtube.com/watch?v=O_xG0ay5Vqs ''Warriors of the Net'' - legendado]<br />
* [https://www.youtube.com/watch?v=1G3SUTmioQE ''Browser Wars'' - legendado]<br />
* [https://www.youtube.com/watch?v=0nz-lcuv3TM ''Browser Wars'' - dublado]<br />
* [https://db-ip.com/200.135.37.65 Localização geográfica de IPs]<br />
* [http://ipv6.br/ '''IPv6 no Brasil''']<br />
* [http://ipv6.br/lab/ Laboratório de IPv6 - Livro didático contendo vários roteiros para entendimento do IPv6]<br />
* [https://www.google.com/intl/pt-BR/ipv6/statistics.html#tab=per-country-ipv6-adoption&tab=per-country-ipv6-adoption Estatísticas Google sobre IPv6]<br />
<br />
=Laboratórios=<br />
<br />
<br />
{{Collapse top |Laboratório 1 - Ferramentas de Rede e Conceitos Básicos}}<br />
<br />
===Objetivos===<br />
<br />
*Familiarização com a infraestrutura dos laboratórios de redes<br />
*Familiarização com ferramentas de rede: ifconfig, ping, traceroute;<br />
*Desenvolver a noção de endereçamentos de rede IP e de endereço de hardware (MAC)<br />
*Desenvolver a noção de rotas em redes IP<br />
*Testar a conectividade IP com ping<br />
<br />
===Conceitos introdutórios para uso do laboratório===<br />
<br />
<br />
====Estrutura do Laboratório====<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/Ferramentas%20de%20rede%20e%20conceitos%20basicos.pdf Conceitos Básicos]<br />
<br />
[http://tele.sj.ifsc.edu.br/~eraldo/AULAS/2018-2/RCO-INTEGRADO/MACxIP.pdf Endereçamento MAC x Endereçamento IP]<br />
<br />
A rede do laboratório em uso segue o modelo apresentado no diagrama da Figura 1 (endereçamento pode ser diferente).<br />
<br />
[[Arquivo:Diagrama_rede_IFSC_lab_redes_I.jpeg |thumb | 400px| Figura 1 - Diagrama da rede do laboratório]]<br />
<br />
Os Laboratórios de Redes de Computadores estão equipados com N+1 (N = número de computadores para alunos) computadores conectados em rede e com acesso a Internet. A rede local do laboratório tem endereço IP 192.168.1.0/24. A máscara de rede '''/24''' indica que o último ''byte'' do endereço é utilizado para identificar cada máquina, por exemplo 192.168.1.1, 192.168.1.2, etc.<br />
<br />
===Roteiro de atividades===<br />
====Parte 1: Observando interfaces do sistema com ifconfig====<br />
O aplicativo '''ifconfig''' pode ser utilizado para visualizar a configuração ou configurar uma interface de host em redes TCP/IP. Se nenhum argumento for passado na chamada do '''ifconfig''', o comando mostra a configuração atual de cada interface de rede.<br />
<br />
NOTA: o ifconfig está sendo substituído pelo comando ip. A última versão do Uuntu já não traz mais o ifconfig por default.<br />
<br />
Consultar as páginas ''man ifconfig'' do Linux para maiores detalhes sobre o funcionamento deste aplicativo, o qual permite ativar/desativar a interface, configurar o endereço IP, definir o tamanho da MTU, redefinir o endereço de hardware se a interface suporta, redefinir a interrupção utilizada pelo dispositivo, entre outros.<br />
<br />
<br />
#Analisando os dados obtidos do seguinte exemplo <syntaxhighlight lang=bash>ifconfig <br />
eth0 Link encap:Ethernet Endereço de HW 64:51:06:1a:f3:da <br />
inet end.: 172.18.18.14 Bcast:172.18.63.255 Masc:255.255.192.0<br />
endereço inet6: fe80::6651:6ff:fe1a:f3da/64 Escopo:Link<br />
UP BROADCAST RUNNING MULTICAST MTU:1500 Métrica:1<br />
pacotes RX:415237 erros:0 descartados:0 excesso:0 quadro:0<br />
Pacotes TX:118109 erros:0 descartados:0 excesso:0 portadora:0<br />
colisões:0 txqueuelen:1000 <br />
RX bytes:364658695 (364.6 MB) TX bytes:18315199 (18.3 MB)<br />
IRQ:18 <br />
<br />
lo Link encap:Loopback Local <br />
inet end.: 127.0.0.1 Masc:255.0.0.0<br />
endereço inet6: ::1/128 Escopo:Máquina<br />
UP LOOPBACK RUNNING MTU:65536 Métrica:1<br />
pacotes RX:6688 erros:0 descartados:0 excesso:0 quadro:0<br />
Pacotes TX:6688 erros:0 descartados:0 excesso:0 portadora:0<br />
colisões:0 txqueuelen:0 <br />
RX bytes:1057934 (1.0 MB) TX bytes:1057934 (1.0 MB) </syntaxhighlight><br />
##O sistema em questão possui duas interfaces de rede: '''eth0''' e '''lo'''<br />
##'''Link encap:Ethernet''': Configuração da interface '''Eth'''ernet 0 (primeira)<br />
##'''Endereço de HW 64:51:06:1a:f3:da''': É o endereço da placa de rede, camada 2<br />
##'''inet end.: 172.18.18.14 Bcast:172.18.63.255 Masc:255.255.192.0''': Endereço IPv4 associado a interface, seu respectivo endereço de ''broadcast'' e mascara de rede<br />
##endereço inet6: fe80::6651:6ff:fe1a:f3da/64 Escopo:Link: Endereço IPv6 de escopo local gerado por autoconfiguração<br />
##'''UP BROADCAST RUNNING MULTICAST''': Significa que a interface está ativa (UP), responde a requisições de broadcast (pode ser desabilitado no kernel) e também pode ser associada a tráfegos ''multicast''<br />
##'''MTU: 1500''': ''Maximum Transfer Unit'' – Tamanho máximo do pacote suportado pelo enlace que é do tipo Ethernet<br />
##Os demais parâmetros são estatísticas da respectiva interface, como por exemplo, pacotes transmitidos, recebidos etc<br />
##A interface '''lo''': Qualquer tráfego que um computador envie em uma rede ''loopback'' é endereçada ao mesmo computador. O endereço IP mais usado para tal finalidade é 127.0.0.1 no IPv4 e ::1 no IPv6. O nome de domínio padrão para tal endereço é ''localhost''. Em sistemas Unix, a interface loopback é geralmente chamada de lo ou lo0.<br />
#Agora utilize o comando '''ifconfig''' para verificar o estado de suas interfaces e responda:<br />
##Quantas e quais interfaces de rede sua máquina possui? Liste.<br />
##Quais são os endereços da camada 2 atribuído as mesmas? De onde o sistema obteve esses endereços?<br />
##Quais são os endereços IPv4? De onde o sistema obteve esses endereços?<br />
##Suas interfaces tem IPv6 configurado? Qual o endereço e escopo dos mesmos? Como foram obtidos? Qual o alcance (é roteável) do mesmo?<br />
##Use o link *[http://jodies.de/ipcalc Verificando a estrutura do endereço IP] para explorar a estrutura do seu endereço IPv4.<br />
<br />
====Parte 2: Testando a conectividade com o ping====<br />
<br />
Aplicativo '''ping''' permite a um usuário verificar se um ''host'' remoto está ativo. É bastante utilizado para detectar problemas de comunicação na rede.<br />
O '''ping''' está baseado no envio de mensagens de solicitação de eco (''echo request'') e de resposta de eco (''echo reply''). Estas mensagens fazem parte do rol de mensagens do protocolo ICMP, que é um protocolo de reportagem de erros, a ser estudado mais tarde, componente do protocolo IP.<br />
<br />
O '''ping''' é um dos principais comandos a disposição do administrador de rede no sentido de verificar a conectividade em rede. Por exemplo, se houver resposta de um ping a partir de um servidor remoto, significa que a máquina local está rodando corretamente o TCP/IP, o enlace local está funcionando corretamente, o roteamento entre a origem e o destino está operando, e por fim, a máquina remota também está rodando corretamente o TCP/IP.<br />
<br />
Consultar as páginas ''man'' do ping para verificar as possibilidades de uso deste aplicativo.<br />
<br />
#Exemplo 1: <syntaxhighlight lang=bash><br />
ping 191.36.0.94<br />
PING 191.36.0.94 (191.36.0.94) 56(84) bytes of data.<br />
64 bytes from 191.36.0.94: icmp_seq=1 ttl=60 time=2.46 ms<br />
64 bytes from 191.36.0.94: icmp_seq=2 ttl=60 time=0.513 ms<br />
64 bytes from 191.36.0.94: icmp_seq=3 ttl=60 time=0.573 ms<br />
64 bytes from 191.36.0.94: icmp_seq=4 ttl=60 time=0.558 ms<br />
^C<br />
--- 191.36.0.94 ping statistics ---<br />
4 packets transmitted, 4 received, 0% packet loss, time 3001ms<br />
rtt min/avg/max/mdev = 0.513/1.026/2.463/0.830 ms </syntaxhighlight><br />
<br />
##No exemplo foram enviados quatro pacotes ICMP, cada um com um número de seqüência (''icmp_seq''), os quais foram recebidos com sucesso com o tempo de viagem assinalado (''time'')<br />
##Cada pacote tem ainda um tempo de vida (''ttl'' – ''time to live''), o qual é decrementado em cada roteador, sendo o pacote descartado quando chegar a zero; isto evita pacotes perdidos na rede<br />
##Quando o ping é interrompido ('''CRTL-C'''), uma estatística é apresentada indicando o percentual de pacotes transmitidos, recebidos e perdidos<br />
##O tempo de viagem (''rtt'' – ''round trip time'') mínimo (''min''), médio (''avg'') e máximo (''max'') é calculado, assim como o desvio padrão (''mdev'')<br />
#Como exercício envie '''ping''' para diferentes ''hosts'' e compare os tempos de resposta:<br />
##no endereço local de loopback;<br />
##máquina de um colega do laboratório;<br />
##servidor e roteador da rede da escola;<br />
##servidores externos: <syntaxhighlight lang=bash><br />
www.ifsc.edu.br<br />
www.uol.com.br<br />
www.nasa.com </syntaxhighlight> e explique as possíveis diferenças entre os tempos de resposta dos ping realizados.<br />
#Consulte as páginas ''man'' e teste o '''ping''' com os parâmetros abaixo e descreva suas funcionalidades:<br />
##-c count<br />
##-i intervalo<br />
##-s packetsize<br />
##-t ttl (para um site distante inicie com 1 e vá incrementando, observe as mensagens)<br />
#Observe que também é possível realizar ping em endereços no formato IPv6, por exemplo: <syntaxhighlight lang=bash> ping6 www.sj.ifsc.edu.br </syntaxhighlight><br />
#Tente o ping6 para outros sites.<br />
<br />
====Parte 3: Verificando rotas com o traceroute====<br />
O '''traceroute''' é capaz de traçar uma rota aproximada entre dois ''hosts''. Este comando usa mensagens ICMP. Para determinar o nome e o endereço dos roteadores entre a fonte e o destino, o traceroute na fonte envia uma série de datagramas IP ordinários ao destino. O primeiro datagrama tem o TTL (''time to live'' – tempo de vida) igual a 1, o segundo 2, o terceiro 3, e assim por diante, e inicia temporizadores para cada datagrama. Quando o enésimo datagrama chega ao enésimo roteador, este verifica que o tempo de sobrevida do datagrama acaba de terminar. Pelas regras do IP, o datagrama é então descartado e uma mensagem ICMP de advertência tempo de vida excedido é enviada a fonte com o nome do roteador e seu endereço IP. Quando a resposta chega de volta a fonte, a mesma calcula o tempo de viagem em função dos temporizadores.<br />
<br />
O '''traceroute''' envia datagramas IP encapsulados em segmentos UDP a um host destino. Todavia escolhe um número de porta destino com um valor desconhecido (maior que 30000), tornando improvável que o host destino esteja usando esta porta. Quando o datagrama chega ao destino uma mensagem ICMP porta inalcançável é gerada e enviada a origem. O programa traceroute precisa saber diferenciar as mensagens ICMP recebidas – tempo excedido e porta inalcançável – para saber quando a rota foi concluída.<br />
<br />
#Exemplo: <syntaxhighlight lang=bash><br />
sudo traceroute -I 200.135.37.65<br />
traceroute to 200.135.37.65 (200.135.37.65), 30 hops max, 60 byte packets<br />
1 192.168.1.1 (192.168.1.1) 0.225 ms 0.216 ms 0.368 ms<br />
2 172.18.0.254 (172.18.0.254) 1.236 ms 1.235 ms 1.343 ms<br />
3 hendrix.sj.ifsc.edu.br (200.135.37.65) 1.331 ms 1.313 ms 1.414 ms </syntaxhighlight><br />
O exemplo mostra a rota dos pacotes entre um computador do Lab. Redes (192.168.1.1) e o servidor ''hendrix'' (200.135.37.65). Observe que para cada roteador são realizados três amostras de tempo de ida e volta. Veja pelo mapa da rede do Campus São José que entre estes dois computadores, sistemas finais, existem dois roteadores intermediários, máquina do professor e Switch camada 3 (VLANs).<br />
#Traçar a rota dos pacotes entre seu computador e diferentes hosts:<br />
##máquina de um colega do laboratório<br />
##servidor e roteador da rede da escola<br />
##servidores externos.<br />
#Explique as possíveis diferenças entre os tempos de resposta de cada uma das amostras do '''traceroute'''<br />
#Explique as linhas com o caracter *.<br />
#Fazendo uso das ferramentas desse laboratório, refaça o diagrama da rede do campus apontando claramente os novos endereços IPs associados aos roteadores.<br />
#Observe que também é possível realizar traceroute em endereços no formato IPv6, por exemplo: <syntaxhighlight lang=bash> sudo traceroute -I6 ipv6.br </syntaxhighlight><br />
#Tente o traceroute no IPv6 para outros sites.<br />
<br />
====Referências adcionais====<br />
<br />
* [http://linux-ip.net/html Guia de Administração da Camada IP no Linux<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 2 - Wireshark e encapsulamento}}<br />
<br />
===Objetivos===<br />
<br />
*Familiarização com o ''sniffer'' de rede WireShark<br />
*Observar o comportamento do ''ping'' e se familiarizar com o processo de encapsulamento;<br />
<br />
====WireShark====<br />
2005 KUROSE, J.F & ROSS, K. W. Todos os direitos reservados <br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/Wireshark%20e%20encapsulamento.pdf Wireshark e encapsulamento]<br />
*Introdução<br />
O entendimento de protocolos de redes pode ser bastante aprofundado através da “observação de protocolos funcionando” e “da manipulação de protocolos” - observando a sequência de mensagens trocadas entre duas entidades, entrando nos detalhes da operação do protocolo, e fazendo com que os protocolos realizem certas ações e então observando estas ações e as consequências. <br />
<br />
A ferramenta básica para observar as mensagens trocadas entre as entidades em execução é chamada de ''sniffer''. Como o nome sugere, um ''sniffer'' captura mensagens sendo enviadas/recebidas pelo seu computador; ele também tipicamente armazena e/ou apresenta os conteúdos dos vários campos dos protocolos nestas mensagens capturadas. Um ''sniffer'' isoladamente é um elemento passivo. Ele observa as mensagens sendo enviadas e recebidas pelas aplicações e protocolos executando no seu computador, mas jamais envia pacotes. Similarmente, os pacotes recebidos nunca são explicitamente endereçados ao ''sniffer''. Ao invés disso, um ''sniffer'' recebe uma cópia de pacotes que são enviados/recebidos para/de aplicações e protocolos executando no seu computador. <br />
<br />
A Figura 2 mostra a estrutura de um ''sniffer''. À direita da Figura 2 estão os protocolos (neste caso, protocolos da Internet) e aplicações (tais como navegador web ou cliente FTP) que normalmente executam no seu computador. O ''sniffer'', exibido dentro do retângulo tracejado na Figura 2 é uma adição aos softwares usuais no seu computador, e consiste de duas partes: a biblioteca de captura de pacotes e o analisador de pacotes. A biblioteca de captura de pacotes recebe uma cópia de cada quadro da camada de enlace que é enviado do ou recebido pelo seu computador. Lembre que mensagens trocadas por protocolos das camadas mais altas tais como HTTP, FTP, TCP, UDP, DNS ou IP, são todos eventualmente encapsulados em quadros que são transmitidos para o meio físico como um cabo Ethernet. Na Figura 2, assume-se que o meio físico é uma Ethernet, e desta forma, os protocolos das camadas superiores são eventualmente encapsulados em um quadro Ethernet. Capturar todos os quadros fornece todas as mensagens enviadas/recebidas de/por todos os protocolos e aplicações executando em seu computador.<br />
<br />
[[Arquivo:Sniffer_estrutura.png |thumb | 500px| Figura 2 - Estrutura de um ''sniffer'']]<br />
<br />
O analisador de pacotes exibe os conteúdos de todos os campos dentro de uma mensagem de protocolo. Para que isso seja feito, o analisador de pacotes deve “entender” a estrutura de todas as mensagens trocadas pelos protocolos. Por exemplo, suponha que estamos interessados em mostrar os vários campos nas mensagens trocadas pelo protocolo HTTP na Figura 5. O analisador de pacotes entende o formato dos quadros Ethernet, e desta forma pode identificar o datagrama IP dentro de um quadro. Ele também entende o formato do datagrama IP, para que ele possa extrair o segmento TCP dentro do datagrama IP. Ele entende a estrutura do segmento TCP, para que possa extrair a mensagem HTTP contida no segmento. Finalmente, ele entende o protocolo HTTP e então, por exemplo, sabe que os primeiros bytes de uma mensagem HTTP contém a cadeia “GET”, “POST” ou “HEAD”. Nós utilizaremos o ''sniffer'' Wireshark (http://www.wireshark.org) para estes laboratórios, o que nos permite exibir os conteúdos das mensagens sendo enviadas/recebidas de/por protocolos em diferentes camadas da pilha de protocolos. Tecnicamente falando, Wireshark é um analisador de pacotes que pode ser executado em computadores com Windows, Linux/UNIX e MAC.<br />
<br />
É um analisador de pacotes ideal para nossos laboratórios, pois é estável, tem uma grande base de usuários e é bem documentado incluindo um guia de usuário (http://www.wireshark.org/docs/wsug_html/), páginas de manual (http://www.wireshark.org/docs/man-pages/), e uma seção de FAQ detalhada (http://www.wireshark.org/faq.html), funcionalidade rica que inclui a capacidade de analisar mais que 500 protocolos, e uma interface com o usuário bem projetada. Ele funciona em computadores ligados a uma Ethernet para conectar-se à Internet, bem como protocolos ponto a ponto, tal como PPP.<br />
<br />
*Analisando os campos da interface do Wireshark <br />
Quando você executar o programa Wireshark, a interface com o usuário exibida na Figura 3 aparecerá. Inicialmente, nenhum dado será apresentado nas janelas. A interface do Wireshark tem seis componentes principais: <br />
#Os menus de comandos são localizados no topo da janela. Por enquanto, interessam apenas os menus ''File'' e ''Capture''. O menu ''File'' permite salvar dados de capturas de pacotes ou abrir um arquivo contendo dados de capturas de pacotes previamente realizadas, e sair da aplicação. O menu ''Capture'' permite iniciar uma captura de pacotes; <br />
#A barra de ferramentas contém os comandos de menu que são mais frequentemente utilizados. Há atalhos para abrir ou salvar dados de captura de pacotes e para iniciar ou parar uma captura de pacotes; <br />
#Abaixo da barra de ferramentas, está o campo de filtragem de pacotes exibidos. Nele podem ser digitados nome de protocolo ou outra informação apresentada na janela de listagem de pacotes. Apenas os pacotes que correspondem ao filtro são exibidos; <br />
#A janela de listagem de pacotes apresenta um resumo de uma linha para cada pacote capturado, incluindo o número do pacote (atribuído pelo Wireshark; este não é o número do pacote contido no cabeçalho de qualquer protocolo), o tempo que o pacote foi capturado, os endereços fonte e destino do pacote, o tipo de protocolo, e informação específica do protocolo contida no pacote. A lista de pacotes pode ser ordenada conforme qualquer uma destas categorias clicando no nome de uma coluna correspondente. O campo tipo do protocolo lista o protocolo de mais alto nível que enviou ou recebeu este pacote, i.e., o protocolo que é a fonte ou o último sorvedouro para este pacote; <br />
#A janela de detalhes de cabeçalho de pacotes fornece detalhes sobre o pacote selecionado na janela de listagem de pacotes. Para selecionar um pacote, basta clicar sobre ele com o botão esquerdo do mouse na janela de listagem de pacotes. Os detalhes apresentados incluem informações sobre o quadro Ethernet e o datagrama IP que contém o pacote. A quantidade de detalhes exibida pode ser expandida ou contraída. Se o pacote foi carregado sobre TCP ou UDP, detalhes correspondentes também são apresentados, os quais também podem ser contraídos ou expandidos. Finalmente, detalhes sobre o protocolo de mais alto nível que enviou ou recebeu este pacote também são apresentados; <br />
#A janela de conteúdo de pacotes mostra o conteúdo inteiro do quadro capturado, nos formatos ASCII e hexadecimal.<br />
<br />
[[Arquivo:Wireshark_interface_usuario.png | 700px| Figura 3 - Interface com o usuário do Wireshark]]<br />
<br />
====Roteiro de atividades====<br />
<br />
=====Etapa 1===== <br />
#Inicie o navegador web; <br />
#Inicie o Wireshark. Inicialmente as janelas estarão vazias, pois não há captura de pacotes em progresso; <br />
#Para iniciar uma captura de pacotes, selecione o menu Capture e depois Interfaces. Provavelmente sua interface de rede será a '''eth0'''. <br />
#Isso faz com que a janela de interfaces de rede disponíveis seja apresentada (Figura 4); [[Arquivo:Wireshark_interfaces_rede.png |thumb | 400px| Figura 4 - Interfaces de rede no Wireshark]]<br />
#O botão ''Start'' da interface '''eth0''' deve ser selecionado. Na Figura 4, no Wireshark foi selecionada a interface wlan; <br />
#Como nada está acontecendo na rede, a janela apresenta o conteúdo vazio;<br />
#Execute um comando ping (endereço na saída da nossa rede - ver aula anterior):<syntaxhighlight lang=bash><br />
ping 200.237.201.153</syntaxhighlight><br />
#Ao voltar para a janela do Wireshark, houve a captura de todos os pacotes envolvidos no process;<br />
#Antes de continuar, vamos parar a captura de pacotes e trabalhar com o que temos. Basta clicar em ''Capture'' e depois em ''Stop''; <br />
#Para testar as capacidades de filtragem, vamos inserir a cadeia “icmp” (sem as aspas e em minúsculo) no especificação do filtro de exibição e depois selecionar ''Apply'' (ou Aplicar). Observe que somente os pacotes envolvidos no ping estão sendo mostrados. Os resultados obtidos devem ser similar a tela mostrada na Figura 5. <br />
#Selecione a primeira mensagem ECHO REQUEST: as informações dos cabeçalhos do quadro Ethernet, do datagrama IP, do pacote ICMP aparecem na janela de cabeçalhos de pacotes. É possível ver os detalhes, expandido ou comprimindo os itens com um clique na seta ao lado deles.<br />
#Selecione uma mensagem ECHO REPLY. Analise o pacote: endereço fonte, endereço destino etc;<br />
#Saia do Wireshark.<br />
<br />
[[Arquivo:TelaWiresharkPing.png | 700px| Figura 5 - Tela Wireshark - Ping]]<br />
<br />
=====Etapa 2=====<br />
<br />
#Com Wireshark ativo (Abra-o novamente) faça um pingue para um site conhecido (você pode usar o nome: www.ifsc.edu.br por exemplo):<br />
#Teste outros filtros, por exemplo, mostre somente pacotes originados e/ou destinados a um determinado ''host'' ('''ip.addr == 192.168...''', ip.src, ip.dst).<br />
#Qual é o endereço IP do sítio navegado? Qual é o endereço IP da interface de rede do seu computador? Qual o endereço MAC de sua máquina?<br />
<br />
<br />
=====Etapa 3 - Desafios=====<br />
<br />
#Solicite um endereço IP de um colega e faça um experimento para descobrir o endereço MAC do computador dele.<br />
#Tente elaborar um experimento para descobrir o endereço MAC do servidor de www.ifsc.edu.br. É possível? Explique para o professor...<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 3 - Conceituando protocolos}}<br />
<br />
===Objetivos===<br />
<br />
*Desenvolver o conceito de protocolo<br />
*Conceber um protocolo/serviço de calculadora pela rede<br />
<br />
===Introdução===<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/Conceituando%20protocolos.pdf Conceituando protocolos]<br />
<br />
O entendimento de protocolos de redes pode ser bastante aprofundado através da “observação de protocolos funcionando” e “da manipulação de protocolos” - observando a sequência de mensagens trocadas entre duas entidades, entrando nos detalhes da operação do protocolo, e fazendo com que os protocolos realizem certas ações e então observando estas ações e as consequências.<br />
<br />
Um protocolo de camada de aplicação define:<br />
#Os tipos de mensagens trocadas.<br />
#A sintaxe dos vários tipos de mensagens, tais como os campos da mensagem e como os campos são delineados.<br />
#A semântica dos campos, isto é, o significado da informação nos campos.<br />
#Regras para determinar quando e como um processo envia mensagens e responde a mensagens.<br />
<br />
Neste experimento será proposto a construção de um protocolo de aplicação para prestar serviços na área de operações matemáticas. Na implementação deste serviço todos grupos serão clientes, solicitando respostas a desafios matemáticos, e servidores, enviando respostas as solicitações, de serviço. Deve ser observado que para não se tornar complexo será usado o transporte de informação através do ICMP (usando o ping). O ping possui uma facilidade para transportar bytes de dados (flag -p). A observação destes dados será feita usando o wireshark (captura de pacotes). Pode-se dizer que o programa ping juntamente com o wireshark e a própria interpretação de pacotes pelo grupo constituem a camada de aplicação.<br />
A camada de transporte foi de certa forma subsituída pelo ICMP que na prática é posicionado na camada de rede (por ser um protocolo auxiliar no funcionamento da camada IP).<br />
<br />
[[Arquivo:AppRCO.png | 500px | Estrutura Applicação'']]<br />
<br />
<br />
*Definição do protocolo a ser criado<br />
#Vamos criar uma calculadora em rede através de um protocolo bem simples, utilizando como ferramenta de comunicação o ping.<br />
##O protocolo tem por objetivo dar suporte a uma calculadora em rede.<br />
##Um aluno cria uma mensagem e envia, sem aviso prévio, a um colega. Este será o cliente da arquitetura cliente-servidor.<br />
##O colega, ao receber a mensagem, deverá interpretá-la, elaborar uma resposta à pergunta e retorná-la ao colega. Este será o servidor da arquitetura cliente-servidor.<br />
##A estrutura básica de um pacote que flui do cliente para o servidor e vice-versa é apresentada na figura abaixo. Essa estrutura deverá ser absolutamente respeitada, caso contrário, o servidor poderá não conseguir interpretá-la e descartará a mensagem. <br />
[[Arquivo:RCOestrutura-pacote.png | 400px | Estrutura do Pacote'']]<br />
<br />
<br />
Para auxiliar na interpretação das mensagens utilize:<br />
#[http://iris.sel.eesc.usp.br/sel433a/ASCII.pdf Tabela ASCII]<br />
#[http://www.rapidtables.com/convert/number/hex-to-ascii.htm Ferramenta para conversão ASCII <==> Hexadecimal]<br />
#[http://xor.pw/ XOR CALCULATOR]<br />
<br />
*Roteiro de Atividades:<br />
#Inicie o Wireshark.<br />
#Inicie a captura de pacotes em sua interface de rede e adicione o filtro '''icmp'''.<br />
#Cada estudante vai construir uma mensagem, respeitando o formato estabelecido, de solicitação (lado cliente). Para construir a mensagem utilize o código ASCII. Essa mensagem deverá explicitar:<br />
##O tipo (requisição ou resposta, ver figura).<br />
##Como endereço de destino (DEST) e fonte (FONTE) utilize o último campo do endereço IP de sua máquina e do colega para qual a mensagem se destina. Por exemplo, a máquina do professor possui o IP 192.168.1.1 e, portanto, seu endereço seria 01.<br />
##Um desafio matemático, por exemplo: 2+2.<br />
#Envie essa mensagem através do comando '''ping''' com a ''flag'' ''pattern''. Um exemplo de mensagem é: <syntaxhighlight lang=bash> ping -p FFFF02001001322B322B03FFFF 192.168.1.10 </syntaxhighlight><br />
##Verifique com Wireshark se a mensagem é para o seu grupo e decifre a mensagem.<br />
#Ao receber uma ou mais mensagens de colegas no wireshark, interprete-a verificando quem é o emitente e realizando a operação aritmética solicitada.<br />
##Monte uma resposta e utilize o comando '''ping''' para responder ao emitente.<br />
##Certifique-se que o colega conseguiu interpretar a mensagem<br />
#Desafio:<br />
#*Em equipes, 2 alunos, proponha um novo padrão de mensagens de um protocolo que dê suporte a um Quiz, perguntas e repostas, sobre o tema geografia. Perguntas do tipo: qual é a capital da Austrália?<br />
#*Implemente o protocolo e teste seus conhecimentos e de seus colegas sobre o tema.<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 4 - Desvendando o HTTP com Wireshark - BÁSICO}}<br />
<br />
===Sobre este Laboratório===<br />
<br />
*Baseado na pequena introdução ao Wireshark apresentada no '''Laboratório 2''' e no '''Laboratório Conceituando Protocolos''' , agora estamos prontos para utilizar o Wireshark para investigar protocolos de aplicação reais em operação. Neste laboratório o protocolo HTTP é explorado nas suas características básicas<br />
<br />
===Fonte base===<br />
<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/Desvendando%20o%20HTTP%20basico.pdf SLIDES DE APOIO: Desvendando o HTTP - Básico - Baseado na Pearson/Kurose]<br />
*[http://www.ebah.com.br/content/ABAAABZ6QAD/wireshark-http Wireshark - HTTP]<br />
*[https://pt.wikipedia.org/wiki/Hypertext_Transfer_Protocol HTTP na Wikipedia]<br />
<br />
===Objetivos===<br />
<br />
*Explorar vários aspectos do protocolo HTTP:<br />
*a interação básica GET/resposta do HTTP,<br />
*formatos de mensagens HTTP;<br />
*diferenças http 1.0 e 1.1 / persistência<br />
<br />
===PARTE 1 - Interação Básica GET/Resposta do HTTP===<br />
<br />
Vamos iniciar a nossa exploração do HTTP baixando um arquivo em HTML simples - bastante pequeno, que não contém objetos incluídos. Faça o seguinte:<br />
#inicie o navegador;<br />
#limpe o cache do mesmo (teclas de atalho para o Firefox: '''Ctrl + Shift + Del''');<br />
#inicie o Wireshark, como descrito no '''Laboratório 1''';<br />
#inicie a captura de pacotes;<br />
#digite o seguinte URL no navegador http://tele.sj.ifsc.edu.br/~odilson/RED29004/RED29004.html;<br />
#pare a captura de pacotes;<br />
#digite “http” (somente as letras, sem as aspas) na caixa de texto de especificação do filtro de exibição, de tal forma que apenas as mensagens HTTP capturadas serão exibidas na janela de listagem de pacotes. (Só estamos interessados em HTTP desta vez, e não desejamos ver todos os pacotes capturados).<br />
#No ''browser'', clique o botão da direita e visualize o código fonte da página adquirida em html.<br />
[[Arquivo:HTTP_Wireshark.png |thumb | 300px| Fig.1 Requisição e Resposta HTTP]]<br />
<br />
O exemplo da figura 1 mostra na janela de listagem de pacotes duas mensagens HTTP capturadas:<br />
#A mensagem GET (do seu navegador para o servidor web www.sj.ifsc.edu.br) e a mensagem de resposta do servidor para o seu navegador.<br />
#A janela de conteúdos de pacotes mostra detalhes da mensagem selecionada (neste caso a mensagem HTTP GET /~odilson/RED29004//RED29004.html, que está em destaque na janela de listagem de pacotes).<br />
#A mensagem HTTP transportada em um segmento TCP, que é carregado em um datagrama IP, que é levado em um quadro Ethernet com 5728 bits no fio. Isso é observado de baixo para cima na janela de detalhes do cabeçalho do pacote selecionado. O Wireshark exibe informações sobre o quadro, IP, TCP e HTTP. Você deve expandir as informações, por exemplo, do HTTP clicando na seta ao lado esquerdo de “Hypertext Transfer Protocol”. Observando as informações das mensagens HTTP GET e de resposta. Você consegue inclusive enxergar a mensagem mostrada no navegador: '''RED29004! Página de teste.'''<br />
<br />
Responda às seguintes perguntas e imprima as mensagens GET e a resposta e indique em que parte da mensagem você encontrou a informação que responde às questões.<br />
#O seu navegador executa HTTP 1.0 ou 1.1?<br />
#Qual a versão de HTTP do servidor?<br />
#Quais idiomas (se algum) o seu navegador indica ao servidor que pode aceitar?<br />
#Qual o endereço IP do seu computador?<br />
#E do servidor tele.sj.ifsc.edu.br?<br />
#Qual o número da porta utilizada no seu computador? Note que esta pergunta se refere a porta do protocolo de transporte TCP, portanto, verifique o header TCP;<br />
#E do servidor tele.sj.ifsc.edu.br?<br />
#Qual o código de status retornado do servidor para o seu navegador?<br />
#Quando o arquivo em HTML que você baixou foi modificado no servidor pela última vez?<br />
#Quantos bytes de conteúdo são baixados pelo seu navegador?<br />
#Encontre a mensagem '''RED29004! Página de teste'''. Onde (em qual campo) encontra-se?<br />
#Qual a diferença entre os endereços (IP) de origem e destino entre a mensagem GET e a de resposta do HTTP?<br />
<br />
===PARTE 2 - Interação Básica GET/Resposta do HTTP usando TELNET e REQUISIÇÃO MANUAL===<br />
<br />
Para esta etapa temos que recordar que o browser é responsável por:<br />
*se conectar ao servidor usando uma porta TCP 80 (default) e <br />
*gerar uma mensagem GET para apanhar um recurso no servidor;<br />
*receber e mostrar a página<br />
Mas será que podemos "emular" o comportamento do browser usando uma outra ferramenta? Por exemplo, o telnet permite abrir uma conexão na porta 80. O que for teclado após a conexão será enviado para o servidor pela conexão estabelecida.<br />
<br />
Aproveitando o comportamento acima, vamos montar na MÃO o pacote de aplicação (que o browser gera) e receber a página do servidor como resposta. Claro que agora não teremos a facilidade do browser em mostrar a página para nós. O que veremos é um código HTML, que é um formato de documentos WEB.<br />
<br />
# Vamos repetir o acesso aos links acima, porém sem usar o navegador. A ideia é que nós façamos o papel de navegador. Isso deve ser feito com os seguintes passos:<br />
#* Coloque o Wireshark para capturar pacotes <br />
#* Abra um terminal de texto no Linux (menu ''Aplicativos->Acessórios->Terminal'').<br />
#* Execute este comando: <syntaxhighlight lang=bash><br />
telnet tele.sj.ifsc.edu.br 80<br />
</syntaxhighlight><br />
#* Após aparecer esta linha: <syntaxhighlight lang=text><br />
Trying 200.135.37.75...<br />
Connected to integrado.sj.ifsc.edu.br.<br />
Escape character is '^]'.<br />
</syntaxhighlight>digite o seguinte:<syntaxhighlight lang=text><br />
GET /~odilson/RED29004//RED29004.html HTTP/1.0<br />
</syntaxhighlight> e em seguida tecle ENTER duas vezes.<br />
#* Identifique a página html que foi enviada como resposta.<br />
#* No WireShark, compare o resultado das execuções desses comandos com o resultado anteriormente visto no navegador. Qual a diferença em ambos os casos?<br />
#* Identifique os componentes do sistema de comunicação de dados nesse acesso direto (quem é cliente, quem é servidor)<br />
#* Refaça um pedido em que o recurso é inexistente no servidor (ex: página html com nome inexistente, GET /~odilson/RED29004//Nada.html HTTP/1.0). Observe a resposta. Qual o código (número) de resposta recebido? <syntaxhighlight lang=bash> telnet tele.sj.ifsc.edu.br 80<br />
GET /~odilson/RED29004//Nada.html HTTP/1.0 </syntaxhighlight><br />
#* Refaça um pedido para o recurso ''default'' e veja o código de resposta:<syntaxhighlight lang=bash> telnet tele.sj.ifsc.edu.br 80<br />
GET / HTTP/1.0</syntaxhighlight><br />
#* Refaça o pedido usando o HTTP/1.1 e tente inferir a diferença da versão 1.0. Note que o GET nesta versão deve ser realizado com o campo Host:<syntaxhighlight lang=bash><br />
telnet tele.sj.ifsc.edu.br 80<br />
GET /~odilson/RED29004//RED29004.html HTTP/1.1<br />
Host: tele.sj.ifsc.edu.br</syntaxhighlight><br />
#'''Nesse teste você deve ter observado que a conexão se manteve aberta'''. Experimente refazer o pedido para um outro recurso na mesma conexão:<syntaxhighlight lang=bash><br />
GET /~odilson/RED29004//RED29004_arq2.html HTTP/1.1<br />
Host: tele.sj.ifsc.edu.br<br />
</syntaxhighlight><br />
Esta característica é a "persistência" do http versão 1.1, que permite reutilizar a mesma conexão para adquirir múltiplos recursos.<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 5 - Desvendando o HTTP com Wireshark - AVANÇADO}}<br />
<br />
===Objetivos===<br />
<br />
*Explorar GET Condicional/Resposta no protocolo HTTP:<br />
*Analisar documentos HTML com Objetos Incluídos<br />
*Comparar as mensagens nos protocolos HTTP X HTTP.<br />
<br />
===Fonte base===<br />
<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/Desvendando%20o%20HTTP%20avancado.pdf SLIDES DE APOIO: Desvendando o HTTP - Avançado - Baseado na Pearson/Kurose]<br />
*[http://www.ebah.com.br/content/ABAAABZ6QAD/wireshark-http Wireshark - HTTP]<br />
*[https://pt.wikipedia.org/wiki/Hypertext_Transfer_Protocol HTTP na Wikipedia]<br />
<br />
===PARTE 1 - A Interação HTTP GET Condicional/Resposta===<br />
<br />
A maioria dos navegadores web tem um cache (seção 2.2.6 do livro) e, desta forma, realizam GET condicional quando baixam um objeto HTTP. Execute os seguintes passos:<br />
#inicie o navegador web;<br />
#limpe o cache do seu navegador('''Ctrl + Shift + Del''');<br />
#inicie o Wireshark;<br />
#digite o URL no navegador http://tele.sj.ifsc.edu.br/~odilson/RED29004//RED29004.html seu navegador deve exibir um arquivo em HTML muito simples com duas linhas;<br />
#pressione o botão “refresh” ('''F5''') no navegador (ou digite o URL novamente);<br />
#pare a captura de pacotes, e digite “http” na caixa de texto de especificação de filtro, para que apenas as mensagens HTTP sejam apresentadas na janela de listagem de pacotes. Se você realizou o procedimento corretamente, você visualizará um total de 6 mensagens no Wireshark: três GETs e três respostas. Obs: Para finas de análise, despreze a solicitação e resposta relativa ao ''fiveicon'', que é relativa ao ''download'' do ícone do IFSC.<br />
<br />
Responda às seguintes questões:<br />
#Inspecione o conteúdo da primeira mensagem HTTP GET do seu navegador para o servidor tele.sj.ifsc.edu.br. Você vê uma linha “If-Modified-Since”?<br />
#Inspecione o conteúdo da primeira resposta do servidor. O servidor retornou explicitamente o conteúdo do arquivo? Como você pode dizer isso?<br />
#Agora inspecione o conteúdo da segunda mensagem HTTP GET do seu navegador para o servidor. Você vê uma linha “If-Modified-Since”? Caso a resposta seja afirmativa, qual informação segue o cabeçalho “If-Modified-Since”?<br />
#Qual é o código de status e a frase retornada do servidor na resposta à segunda mensagem HTTP GET? É diferente do código de retorno da primeira mensagem?<br />
#O servidor retornou explicitamente o conteúdo do arquivo? Explique.<br />
#Qual o tamanho da primeira e segunda mensagem de retorno do servidor?<br />
<br />
===PARTE 2 -Documentos HTML com Objetos Incluídos===<br />
<br />
Agora que vimos como o Wireshark mostra o tráfego capturado para arquivos em HTML grandes, nós podemos observar o que acontece quando o seu browser baixa um arquivo com objetos incluídos, no nosso exemplo, imagens que estão armazenadas em outros servidores. Faça o seguinte:<br />
#inicie o navegador web;<br />
#limpe o cache do seu navegador;<br />
#inicie o Wireshark;<br />
#digite o URL no navegador http://tele.sj.ifsc.edu.br/~odilson/RED29004/RED29004_arq3.html seu navegador deve exibir um arquivo pequeno em HTML com duas imagens incluídas. Estas duas imagens estão referenciadas no arquivo em HTML. Isto é, as imagens não estão no arquivo em HTML, ao invés disso, há um URL para cada imagem no arquivo em HTML. Como discutido no livro, seu navegador terá que baixar estas imagens dos locais correspondentes. As imagens estão em docente.ifsc.edu.br;<br />
#Verifique o código fonte da página, clicando com o botão direito sobre ela. Observe os links dentro do código html.<br />
#digite o URL no navegador http://tele.sj.ifsc.edu.br/~odilson/RED29004/RED29004_arq4.html seu navegador deve exibir um arquivo pequeno em HTML com cinco imagens incluídas. Estas cinco imagens,diferentemente do caso anterior, estão depositadas no próprio sítio do professor;<br />
#Verifique o código fonte da página, clicando com o botão direito sobre ela. Observe os links dentro do código html.<br />
#pare a captura de pacotes, e digite “http” na caixa de texto de especificação de filtro, para que apenas as mensagens HTTP seja exibidas.<br />
<br />
Responda às seguintes questões:<br />
#Quantas mensagens HTTP GET foram enviadas pelo seu navegador em cada acesso?<br />
#Para quais endereços na Internet estas mensagens foram enviadas em cada acesso?<br />
#Você consegue dizer se o seu navegador baixou imagens com ou sem paralelismo? Explique e diferencie o comportamento em cada um dos casos.<br />
<br />
===PARTE 3 -Segurança com HTTPS===<br />
Para finalizar, vamos capturar sequências de mensagens HTTPS, somente a título de comparação. Execute os seguintes procedimentos:<br />
#inicie o navegador web;<br />
#limpe o cache do seu navegador;<br />
#inicie o Wireshark;<br />
#digite o seguinte URL no navegador https://www.ssllabs.com/ssltest/;<br />
#pare a captura de pacotes e digite "ssl" na caixa de texto de especificação de filtro, para que apenas as mensagens criptografadas sejam exibidas.<br />
<br />
Responda:<br />
#Compare a sequência de troca de mensagens (GET e resposta) entre o HTTP (das seções anteriores) com o ssl, existe alguma similaridade?<br />
#Que tipos de campos são mais presentes nesse tipo de mensagens?<br />
#Você consegue identificar o conteúdo de alguma nas mensagens ssl, como no caso das mensagens http?<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 6 - Servidor Apache e Construção de Página HTML}}<br />
<br />
===Objetivos===<br />
*Introdução a ferramenta de simulação de redes Netkit.<br />
*Configurando o servidor Apache para disponibilizar páginas HTML.<br />
*Construindo e disponibilizando páginas HTML.<br />
*Noções de ''shell script'' para automatizar tarefas.<br />
<br />
===Fonte base===<br />
<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/ServidorApache.pdf SLIDES DE APOIO: Introdução à Programação “para Web”]. Baseado no resumo destes material Introdução à Programação para Web de Carlos Bazilio: [http://www.ic.uff.br/~bazilio/cursos/java/slides/Introducao.pptm]<br />
*[https://www.apache.org/ Apache]<br />
<br />
===Máquinas Virtuais UML / Netkit2===<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/SlidesApoioMaquinaVirtual.pdf Conceitos de máquinas virtuais]<br />
<br />
Para esta aula de laboratório estaremos usando o [https://wiki.sj.ifsc.edu.br/index.php/Netkit2 netkit2] do Prof. Sobral, uma extensão do [http://wiki.netkit.org/index.php/Main_Page netkit] da '''Universidade Roma Tre'''.<br />
Trata-se de uma ferramenta que que permite criar máquinas virtuais leves sobre o linux. Estas máquinas podem ser ligadas em rede. Neste laboratório conectaremos uma máquina virtual na REDE do Laboratório através de uma bridge.<br />
<br />
===O Servidor Apache===<br />
<br />
Neste laboratório vamos criar uma página html e hospedá-la em um máquina virtual com o [http://www.apache.org/ Web Server Apache]. Para maiores informações consulte [http://softwarelivre.org/php/servidor-web-apache Visão Geral do Apache ].<br />
<br />
===PARTE 1 - Colocando o servidor Apache no ar no Netkit===<br />
<br />
#Inicialmente vamos colocar um Máquina Virtual (VM) Netkit conectada com uma bridge para que possamos acessá-la de qualquer lugar do laboratório. Utilize o editor de texto Gedit e salve as definições do laboratório abaixo em um arquivo '''/home/aluno/lab.conf''':<syntaxhighlight lang=bash><br />
pc1[type]=generic<br />
pc1[eth0]=uplink:bridge=eth0:ip=dhcp<br />
</syntaxhighlight><br />
#Rode o '''netKit''' em seu computador. Em um terminal digite: <syntaxhighlight lang=bash> mkdir .netkit<br />
netkit2 & </syntaxhighlight><br />
#Caso surja uma mensagem recomendando atualizar o Netkit, faça-o através do menu: '''<General> <Update>'''. Aguarde a finalização do processo.<br />
#No menu '''<File> <Load and Run>''', procure o arquivo '''/home/aluno/lab.conf''' e clique em OK. Abrirá um terminal da máquina virtual (VM) que estará rodando servidor Apache que vamos utilizar, onde é possível fazer a configuração do mesmo.<br />
#<span style="color: red;">Dica: não tente alterar o tamanho da janela do Netkit. Se isso for feito não consegue-se mais voltar ao tamnho original.<br />
#Ao clicar no menu '''<File> <Graph>''', pode-se ter uma visão da rede a ser simulada e conferir se é equivalente ao diagrama proposto.<br />
#Identifique o IP da VM usando o comando '''ifconfig'''. Esse será, doravante, seu '''''endereço_IP'''''.<br />
#*<span style="color: blue;">Dica: para copiar textos para o Netkit, copie normalmente o texto, por exemplo, da Wiki, com o < Ctrl > + < C > e cole clicando sobre a rodinha (''scroll'') do mouse.<br />
#Teste a conectividade entre a máquina virtual e a máquina hospedeira com o comando ping. Na VM execute: <syntaxhighlight lang=bash><br />
ping 192.168.1.1 </syntaxhighlight><br />
#Coloque o servidor apache em execução. Este servidor escutará na porta 80 por requisições de páginas (objetos HTTP). Execute no terminal da VM: <syntaxhighlight lang=bash> /etc/init.d/apache2 start </syntaxhighlight><br />
#Inicie o Wireshark em sua máquina.<br />
#Abra o Firefox na sua máquina (hospedeira) e coloque como endereço: <syntaxhighlight lang=bash> http://endereco_IP </syntaxhighlight><br />
#Pronto. Você está acessando a página ''default'' do Apache da VM.<br />
#Você pode verificar o arquivo de definição da página ''default'' na VM com o comando: <syntaxhighlight lang=bash> cat /var/www/index.html </syntaxhighlight><br />
#Com sua experiência com o Wireshark filtre as mensagens trocadas entre o servidor da VM e seu navegador. <br />
##Localize os comandos GET e a resposta do servidor. <br />
##Observe quais são os IPs de destino e fonte da requisição e resposta.<br />
##Observe as portas de destino e fonte da requisição e resposta.<br />
##Qual versão do HTTP está sendo usada?<br />
#Escolha um servidor web de um colega, acesse a página HTML desse colega e repita as capturas de pacotes.<br />
<br />
===PARTE 2 - Colocando no ar a sua página HTML===<br />
<br />
Nesta parte do experimento vamos editar um código HTML e disponibilizá-la em um diretório especial por você criado. Observe que vamos editar a página no hospedeiro e salvá-la em um diretório compartilhado entre a máquina hospedeira e a MV.<br />
<br />
#Usando o Gedit, salve o código html abaixo como no arquivo '''/home/aluno/lab/shared/index.html''' da sua máquina hospedeira.<syntaxhighlight lang=bash><br />
<!DOCTYPE html><br />
<html><br />
<body><br />
<br />
<h1>Alo Mundo</h1><br />
<br />
<p>Estamos sendo visitados por extraterrestres...</p><br />
<br />
</body><br />
</syntaxhighlight><br />
#Crie a adapte para o seu caso um [https://pt.wikipedia.org/wiki/Shell_script Shell Script] com o conteúdo exemplo abaixo. Com o Gedit crie um arquivo e salve como '''/home/aluno/lab/shared/config_apache.sh''' <syntaxhighlight lang=bash><br />
#!/bin/bash<br />
mkdir /var/www/ET<br />
chmod 755 /var/www/ET<br />
cp /hostlab/shared/index.html /var/www/ET<br />
chmod 555 /var/www/ET/index.html<br />
service apache2 restart </syntaxhighlight><br />
#Em sua máquina hospedeira transforme o script em executável. Num terminal digite: <syntaxhighlight lang=bash> chmod +x /home/aluno/lab/shared/config_apache.sh </syntaxhighlight><br />
#O shell script será executado na máquina virtual do apache, portanto, abra o terminal da mesma no Netkit e digite: <syntaxhighlight lang=bash><br />
/hostlab/shared/config_apache.sh <br />
</syntaxhighlight><br />
#Agora você deve ser capaz de acessar a página recém criada através do seu navegador no hospedeiro usando o endereço: <syntaxhighlight lang=bash> http://endereco_IP/ET </syntaxhighlight><br />
#Personalize a página HTML acrescentando novas frases de sua preferência. Para isso repita os passos: 1, 3 e 4.<br />
#Avise o professor para que ele mostre no telão sua página através do Epoptes.<br />
#Acesse as páginas HTML personalizadas dos demais colegas.<br />
#Se desejar, crie outras páginas, para isto basta executar os passos 1 a 5, só que criando diretórios com nomes distintos dos demais já existentes. Cada novo diretório poderá conter uma nova página.<br />
#Também se desejar incremente suas novas páginas com figuras (objetos). Lembre-se de copiar esse objetos para o diretório pertinente na VM.<br />
#*Com o navegador acesse as novas páginas criadas.<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 7 - Serviço de Nomes (DNS)}}<br />
<br />
===Objetivos===<br />
O Domain Name System (DNS) traduz nomes de hosts em endereços Internet Protocol (IP), preenchendo uma lacuna crítica na infraestrutura da Internet. Neste laboratório, observaremos mais de perto:<br />
#O lado cliente do DNS.<br />
#Uma pequena análise do protocolo e<br />
#Consultas AAAA<br />
<br />
Lembre-se de que o papel do cliente no DNS é relativamente simples - um cliente envia uma consulta ao seu DNS, e obtém uma resposta. Muito pode acontecer “por baixo dos panos”, de forma invisível aos clientes DNS, enquanto os servidores DNS, organizados hierarquicamente, comunicam-se entre si para, ou recursivamente ou iterativamente, resolver uma consulta DNS de um cliente. Do ponto de vista do cliente DNS, contudo, o protocolo é bastante simples - uma consulta é feita ao seu servidor DNS e uma resposta é recebida deste servidor.<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/Servico%20de%20Nomes%20DNS.pdf Serviço de Nomes - DNS]<br />
<br />
===PARTE 1: Consulta simples ao DNS gerada a partir de um comando ping===<br />
<br />
O comando ping pode ser usado tanto com um endereço IP como com um nome de host. Em última instância, ele sempre enviará pacotes para um endereço IP. No caso de ser usado o endereço de host, ele tentará resolver (mapear) este nome em um endereço IP usando um servidor DNS (local). Ele gera uma pergunta para o servidor (ou para os servidores, caso exista mais de um configurado). Esta experiência mostra como verificar os servidores instalados e, através de uma captura de pacote mostra a estrutura dos cabeçalhos DNS.<br />
<br />
#Inicialmente consulte e anote quem são os servidores DNS instados na sua máquina. É para estes servidores que serão conduzidas as perguntas DNS. Use a ferramenta nm-tool ou acesso ao arquivo de configuração do sistema:<syntaxhighlight lang=bash><br />
cat /etc/resolv.conf</syntaxhighlight><br />
#Prepare o wireshark para capturar pacotes.<br />
#Execute o ping para um endereço de host conhecido <syntaxhighlight lang=bash><br />
ping www.ifsc.edu.br</syntaxhighlight><br />
#Pare a captura de pacotes no Wireshark e coloque um filtro de display para mostrar apenas mensagens DNS e de ICMP<syntaxhighlight lang=bash><br />
dns || icmp </syntaxhighlight><br />
#Observe os pacotes capturados. Em particular foque no pacote de pergunta que deve ser similar ao mostrado abaixo e deve estar direcionado a um dos servidores DNS. Nos ''flags'' do header do pacote DNS é possível observar que é um QUERY (pergunta) a ser resolvido de forma recursiva. A pergunta propriamente dita está no campo QUERIES, onde é colocado o nome a ser resolvido e o tipo do registro solicitado (tipo A) que indica resolução de nome. <br />
#:<br />
#:[[Arquivo:DNS-Tela1-Wireshark.jpg | 900px| Estrutura de uma pergunta simples DNS]]<br />
#:<br />
#:<br />
#Foque agora um pacote de resposta do servidor para o cliente. Deve ter uma estrutura similar ao mostrado abaixo. Nos flags do header do pacote DNS é possível observar que é uma resposta. A resposta propriamente dita está no campo ANSWERS (ele também repete a pergunta no campo QUERIES). Note que podem haver vários registros (RR) retornados, cada um com um tipo. No exemplo abaixo também é retornada uma lista de servidores autorizados (RR tipo NS). Também é retornado o endereço IP destes servidores através de RRs adicionais do tipo A (inclusive endereços IPv6).<br />
#:<br />
#:<br />
#:[[Arquivo:DNS-Tela2-Wireshark.jpg | 900px| Estrutura de uma resposta simples DNS]]<br />
#Perguntas a serem respondidas, baseado nos pacotes "''Standard query''" e "''Standard query response''":<br />
##Quem são os servidores DNS da sua máquina?<br />
##O ping gerou pergunta para cada um deles?<br />
##Qual o tipo da RR associada a pergunta (''Queries''). O que significa?<br />
##Qual endereço IP retornado para o www.ifsc.edu.br?<br />
##Qual endereço IP usado no ping (ver pacote REQUEST ICMP)?<br />
##Qual protocolo de transporte, camada 4, que foi usado para transportar as mensagens de aplicação DNS?<br />
##Quais os servidores autorizados (''Authoritative nameservers'') foram repassados em resposta a sua consulta?<br />
#Logo após o primeiro ping existe mais uma consulta DNS. Esta pergunta é realizada através de uma mensagem do tipo PTR. O ping está tentando verificar qual é o nome da máquina que realmente está respondendo. É o DNS reverso, nesse tipo de colsulta se fornece um IP e o servidor devolve o nome da máquina.<br />
#Perguntas a serem respondidas:<br />
##Qual o IP que se pretende resolver?<br />
##Qual o nome retornado?<br />
##O nome retornado é www.ifsc.edu.br? Sim ou não? Explique.<br />
<br />
===PARTE 2 - Consultas DNS por meio de ferramentas especializadas===<br />
# Usando o programa [http://manpages.ubuntu.com/manpages/precise/man5/hosts.5.html host], [http://manpages.ubuntu.com/manpages/trusty/en/man1/nslookup.1.html Nslookup] ou [http://manpages.ubuntu.com/manpages/precise/man1/dig.1.html dig], que são executados no terminal, descubra e anote no relatório os endereços IP associados aos seguintes nomes de hosts (máquinas):<br />
#* mail.ifsc.edu.br<br />
#* www.google.com<br />
#* www.gmail.com<br />
# Agora descubra e anote no relatório quem é o servidor DNS responsável por cada um dos domínios dos nomes acima. Para isso consulte o valor do registro NS associado a esses domínios. Por exemplo, com o programa ''host'' ou ''dig'' isso pode ser feito assim: <syntaxhighlight lang=bash><br />
host -t ns ifsc.edu.br<br />
dig -t ns ifsc.edu.br<br />
</syntaxhighlight><br />
# O serviço DNS fornece outras informações além do endereço IP associado a cada nome de domínio e/ou máquina. Por exemplo, como ele pode-se descobrir que ''host'' recebe emails em um determinado domínio. Isso é utilizado pelos MTA (''Mail Transfer Agent'') mundo afora para entregarem emails para seus destinatários (lembre que isso se faz com o protocolo SMTP). Para descobrir essa informação, deve-se consultar o registro MX (''Mail eXchange'') de um domínio. Novamente as ferramentas a ser utilizada nesse caso podem ser ''host'' ou ''dig''. Por exemplo: <syntaxhighlight lang=bash><br />
host -t mx ifsc.edu.br<br />
dig -t mx ifsc.edu.br<br />
</syntaxhighlight>Descubra e anote no relatório quem é o servidor de emails nos seguintes domínios:<br />
#* gmail.com<br />
#* hotmail.com<br />
#* ifsc.edu.br<br />
# Outra informação útil guardada por servidores DNS é a tradução de endereço IP para nome de domínio. Isso é chamado de tradução reversa (ou DNS reverso). Usando os programas de diagnóstico já vistos, isso pode ser feito assim: <syntaxhighlight lang=bash><br />
dig -x 200.135.37.65<br />
</syntaxhighlight> ... o ''dig'' tem um resultado um pouco mais carregado que os outros utilitários (''host'' e ''nslookup''), porém neste caso é mais prático. Veja o resultado da consulta logo após a linha '';; ANSWER SECTION:''. Experimente fazer a resolução reversa para cada um dos IP obtidos nas consultas realizadas no primeiro exercício desta atividade. Pode-se também usar a variante do ''dig'' para respostas curtas: <syntaxhighlight lang=bash><br />
dig -x 200.135.37.65 +short<br />
</syntaxhighlight><br />
#Faça uma consulta iterativa com dig e responda:<syntaxhighlight lang=bash><br />
dig +trace mail.ru. </syntaxhighlight><br />
##Qual foi o RLD (''Root Level Domain'') consultado?<br />
##Qual o TLD (''Top Level Domain'') consultado?<br />
##Qual o SLD (''Second Level Domain'') consultado?<br />
##Como você sabe que foram esses os LDs consultados?<br />
#Consultando um servidor explícito(@)<syntaxhighlight lang=bash><br />
dig @j.root-servers.net. +trace www.sj.ifsc.edu.br. </syntaxhighlight><br />
#AVANÇADO. Execute somente se tiver curiosidade. Como explicado durante a aula e visto no exercício anterior, DNS é um banco de dados distribuído. Isso quer dizer que suas informações estão espalhadas em milhares (ou milhões?) de servidores DNS mundo afora. Cada servidor DNS mantém os dados dos domínios por que é responsável. Será que é possível rastrear todos os servidores DNS que devem ser consultados até chegar ao servidor do domínio procurado? Posto de outro modo, vamos fazer todo o processo de requisição interativa, do exercício anterior, manualmente, ou seja, descobrir quem é o ''Root Level Domain'', o ''Top Level Domain'' e o ''Second Level Domain''. Anote no relatório.<br />
## Descubra quem são os servidores raiz (topo de hierarquia DNS): <syntaxhighlight lang=bash><br />
host -t ns .<br />
dig -t ns .<br />
</syntaxhighlight><br />
## Escolha um dos servidores TLD listados, e use-o para fazer as consultas. Por exemplo: <syntaxhighlight lang=bash><br />
host -v -t a www.sj.ifsc.edu.br. j.root-servers.net.<br />
</syntaxhighlight>... e observe a seção '';; AUTHORITY SECTION:''. Ele contém a listagem de servidores DNS que podem atender sua consulta.<br />
## Continue fazendo as consultas aos servidores DNS listados, até conseguir traduzir o nome requisitado. Por exemplo: <syntaxhighlight lang=bash><br />
host -v -t a www.sj.ifsc.edu.br. b.dns.br </syntaxhighlight><br />
## Quantos servidores DNS foram necessários consultar no total?<br />
<br />
===Algumas consultas AAAA===<br />
Vamos expandir um pouco nossos horizontes e fazer algumas consultas envolvendo IPv6.<br />
#No terminal de sua máquina faça uma consulta e responda: qual o endereço IPv6 dos hosts? Por exemplo: <syntaxhighlight lang=bash><br />
dig AAAA google.com<br />
host -t AAAA google.com </syntaxhighlight><br />
##webmail.ufsc.br<br />
##www.sj.ifsc.edu.br<br />
##www.nyt.com<br />
##ipv6.br<br />
##www.microsoft.com<br />
#Agora vamos fazer a consulta reversa. Qual é o nome de host dos seguintes endereços? Por exemplo: <syntaxhighlight lang=bash><br />
dig -x 2001:12ff::10<br />
dig -x 2001:12ff::10 +short<br />
host 2001:12ff::10 </syntaxhighlight><br />
##2801:84:0:2::10<br />
##2001:12d0:0:126::183:244<br />
##2001:12ff::10<br />
##2804:1454:1004:100::2<br />
<br />
===Analisando o protocolo via Wireshark===<br />
Agora que já está ficando claro como funcionam as consultas DNS, deve-se investigar como se dá a comunicação entre seu computador e seu servidor DNS.<br />
#abra o navegador web e limpe o cache do mesmo;<br />
#abra o Wireshark e escolha a interface e inicie a captura de pacotes;<br />
#inicie a captura de pacotes no Wireshark;<br />
#no terminal digite '''dig +trace canon.jp''' (isso vai provocar a consulta DNS);<br />
#pare a captura de pacotes;<br />
#No Wireshark digite “dns” no filtro (sem as aspas);<br />
Com base nisso identifique o seguinte:<br />
#quantas mensagens são trocadas entre cliente e servidor DNS para cada consulta?<br />
#que protocolo de transporte é usado?<br />
#que portas de origem e destino são utilizadas?<br />
#qual o formato das mensagens DNS? Elas são textuais como as mensagens HTTP?<br />
#qual o tipo de registro DNS acessado em cada consulta?<br />
#que informações estão contidas nas respostas DNS? Há algo além do que foi pedido?<br />
#qual o tamanho das mensagens DNS?<br />
#qual endereço IP a mensagem de consulta DNS é enviada? Foi o mesmo ip obtido na seção anterior: seu servidor DNS?<br />
#examine a mensagem de consulta DNS. Qual o campo “type” desta mensagem?<br />
#a mensagem de consulta contém algum campo “answer”?<br />
#examine a mensagem de resposta DNS. Quantos campos com “answer” existem?<br />
#quais são os benefícios de usar o UDP ao invés do TCP como protocolo de transporte para o DNS?<br />
<br />
===Exemplos de arquivos de um ''Second Level Domain'' fictício===<br />
*Exemplo de arquivos de configuração de um servidor [https://www.isc.org/downloads/bind/ BIND]<br />
/etc/bind/db.redes <syntaxhighlight lang=bash><br />
$TTL 86400<br />
@ IN SOA ns.redes.edu.br. root (<br />
2016090900 ; Serial<br />
604800 ; Refresh<br />
86400 ; Retry<br />
2419200 ; Expire<br />
86400 ) ; Negative Cache TTL<br />
;<br />
@ IN NS ns.redes.edu.br.<br />
@ IN MX 10 mail.redes.edu.br.<br />
$ORIGIN redes.edu.br.<br />
ns A 192.168.1.101<br />
www A 192.168.1.102<br />
www A 192.168.1.103<br />
www A 192.168.1.104<br />
www A 192.168.1.105<br />
www A 192.168.1.106<br />
www A 192.168.1.107<br />
ftp A 192.168.1.108<br />
mail A 192.168.1.109 </syntaxhighlight><br />
<br />
/etc/bind/db.2.168.192 (Zona reversa) <syntaxhighlight lang=bash><br />
$TTL 86400<br />
@ IN SOA ns.redes.edu.br. root (<br />
2016090900 ; Serial<br />
604800 ; Refresh<br />
86400 ; Retry<br />
2419200 ; Expire<br />
86400 ) ; Negative Cache TTL<br />
;<br />
IN NS ns.redes.edu.br.<br />
101 IN PTR ns.redes.edu.br.<br />
102 IN PTR www.redes.edu.br.<br />
108 IN PTR ftp.redes.edu.br.<br />
109 IN PTR mail.redes.edu.br. </syntaxhighlight><br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 8 - Desvendando o UDP - Básico}}<br />
<br />
===Objetivos===<br />
<br />
*Familiarizar-se com o UDP<br />
*Entender a estrutura do pacote UDP<br />
*Entender o conceito de portas<br />
*Entender o conceito de multiplexação<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/UDP%20Basico.pdf Introdução a camada de transporte e UDP básico]<br />
<br />
===Parte 1 - Fluxo único UDP===<br />
<br />
#Combinar equipes com dois computadores para execução do experimento.<br />
#*Uma equipe escutará na porta 5000 e a outra equipe transmitirá uma mensagem nessa porta. Os processos de transmissão e recepção podem ocorrer simultaneamente, em terminais distintos.<br />
#*Cada equipe deve identificar os IPs ('''IP_DEST''') das máquinas de seus pares.<br />
#Cada equipe deve abrir uma Janela de terminal.<br />
#Cada equipe deve preparar o '''Wireshark''', interfaces '''any''', para escuta das portas no protocolo UDP usando um filtro:<syntaxhighlight lang=bash><br />
udp.port==5000</syntaxhighlight><br />
#A equipe da escuta na porta 5000 executa no terminal: <syntaxhighlight lang=bash><br />
netcat -u -l -p 5000 </syntaxhighlight><br />
#A equipe que irá transmitir para a porta 5000 executa no terminal: <syntaxhighlight lang=bash><br />
netcat -u IP_DEST 5000 </syntaxhighlight><br />
#*Em seguida escreve no terminal uma mensagem de até 20 caracteres, ao teclar <Enter> a mensagem será enviada.<br />
#*O wireshark deve ter capturado os pacotes UDP <br />
#Identifique e anote os seguintes dados na captura do wireshark:<br />
#*IP FONTE e DESTINO<br />
#*PORTAS FONTE E DESTINO para ambas comunicações<br />
#*Campo de protocolo no pacote IP<br />
#*Campo de tamanho (anote o tamanho) e ''checksum'' no pacote (datagrama) UDP<br />
#*O campo de dados no pacote UDP<br />
#Troquem os papéis das equipes: quem houvia agora transmite mensagens.<br />
#Cada equipe pode transmitir sequencialmente várias mensagens, devendo identificar múltiplos datagramas UDP.<br />
#PERGUNTAS baseadas na captura:<br />
##Qual o tamanho de cada campo do cabeçalho do pacote UDP?<br />
##Qual o tamanho máximo do número de porta?<br />
##Qual o tamanho máximo da área de dados (payload) do pacote?<br />
##Qual o número identificador de protocolo UDP no pacote IP? <br />
##Em algum momento foi identificado algum procedimento para estabelecimento de conexão? <br />
##Em algum campo do UDP existe numeração de mensagens?<br />
<br />
===Parte 2 - Experimento com UDP - MUX e DEMUX===<br />
<br />
#Conceber um adendo ao experimento anterior para demonstrar a multiplexação e demultiplexação de informação.<br />
#*Lembre-se que a demultiplexação permitirá que diferentes fluxos sejam encaminhados para diferentes processos. Nesse sentido, por exemplo, em uma mesma máquina pode-se abrir dois os mais terminais onde, em cada um deles, pode-se gerar ou aguardar fluxos distintos (diferenciados pelas portas).<br />
#Capture os pacotes com o Wireshark e caracterize quais pacotes pertencem a cada fluxo (porta).<br />
#Mostre o experimento ao professor, que projetará o mesmo no telão.<br />
<br />
'''DESAFIO''' (para casa?): capture e anote byte a byte o conteúdo de um pequeno pacote UDP (e dados IP) e calcule o CHECKSUM do mesmo (pesquise no google como fazer).<br />
{{Collapse bottom}}<br />
{{Collapse top |Laboratório 9 - Desvendando o TCP - Básico}}<br />
<br />
===Objetivos===<br />
<br />
*Verificar o comportamento básico do Protocolo TCP:<br />
**Fase de Estabelecimento de Conexão<br />
**Troca de Dados<br />
**Finalização da Conexão<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/TCP%20Basico.pdf Camada de transporte: TCP básico]<br />
<br />
==Configuração do Laboratório==<br />
O netkit2 deve ser atualizado manualmente com este procedimento:<br />
# Abrir um terminal<br />
# Baixar o programa do ''Netkit2'' com o comando: <syntaxhighlight lang=bash><br />
wget http://tele.sj.ifsc.edu.br/~msobral/netkit2/bin/netkit2<br />
</syntaxhighlight><br />
# Copiá-lo para o diretório do Netkit2 com o comando: <syntaxhighlight lang=bash><br />
cp netkit2 ${NETKIT2_HOME}/bin/<br />
</syntaxhighlight><br />
<br />
O roteiro será executado sobre 3 máquinas virtuais, através do uso do [[Netkit2 | Netkit2]]. Copie o texto abaixo no '''Gedit''' e salve com o nome '''/home/aluno/TCP.conf'''. <br />
<syntaxhighlight lang=text><br />
PC1[type]=generic<br />
PC2[type]=generic<br />
PC3[type]=generic<br />
<br />
<br />
PC1[eth0]=lan0:ip=10.0.0.1/24<br />
PC2[eth0]=lan0:ip=10.0.0.2/24<br />
PC3[eth0]=lan0:ip=10.0.0.3/24<br />
</syntaxhighlight><br />
<br />
===Verificando o estabelecimento, troca de dados e finalização da conexão===<br />
<br />
#Executar a configuração do laboratório no Netkit. Abra o NetKit2 e abra o arquivo de configuração: <syntaxhighlight lang=bash><br />
File > Load and Run </syntaxhighlight><br />
#*Perceba que abrirá uma janela com três abas inferiores, representando três máquina virtuais criadas pelo Netkit, denominadas: PC1, PC2 e PC3. Cada uma dessas abas é o terminal de configuração da respectiva máquina virtual.<br />
#Executar no PC2 um servidor TCP aguardando na porta 5555 na forma: <syntaxhighlight lang=bash> netcat -l 5555 </syntaxhighlight><br />
#*Obs.: para copiar texto para as máquinas do NetKit, pode-se copiar normalmente o texto e em seguida, no terminal do NetKit apropriado, clique na "rodinha" do mouse.<br />
#*Em uma comunicação TCP um processo é servidor (aguarda pedido de conexão) e um processo é o cliente, que gera um pedido de conexão<br />
#Executar no PC3 o tcpdump com foco na porta tcp 5555 e para salvar pacotes em arquivo: <syntaxhighlight lang=bash> tcpdump -i eth0 tcp port 5555 -s 1024 -U -w /hostlab/shared/pc3.cap </syntaxhighlight><br />
#Executar no PC1 um cliente TCP que solicita uma conexão ao servidor: <syntaxhighlight lang=bash> netcat 10.0.0.2 5555 </syntaxhighlight><br />
#Enviar uma pequena mensagem de 5 caracteres, e no final teclar ENTER e depois CTRL+D.<br />
#*O CTRL-D encerra a conexão no netcat<br />
#Vá até o terminal do PC3 e encerre a captura de pacotes do '''tcpdump''' digitando CTRL+C.<br />
#Abrir o arquivo de captura gravado no PC3 com o Wireshark. Temos duas possibilidades para fazer isso, escolha uma das duas:<br />
##Abrir o Wireshark e ir no menu File > Open > Pasta Pessoal > lab > shared > pc3.pcap<br />
##Abrir o "navegador de arquivos" e encontrar procurar o arquivo na pasta aluno/lab/shared/pc3.pcap (/home/aluno/lab/shared/pc3.pcap).<br />
#Todos pacotes TCP, desde o estabelecimento até a desconexão devem estar capturados. Um exemplo dessa captura encontra-se na Figura 1.<br />
[[Arquivo:WiresharkTCP.png |thumb | 600px| Fig.1 -- Protocolo TCP]]<br />
#O processo de conexão do TCP envolve a troca de 3 pacotes e é sempre iniciado pelo cliente. O cliente envia um pacote SYN, o servidor responde com um SYN-ACK e o cliente finalmente responde com ACK. Observe estes pacotes no wireshark.<br />
#*Pratique seu inglês e leia um pouco sobre este processo de estabelecimento de conexão em [https://en.wikipedia.org/wiki/Transmission_Control_Protocol#Connection_establishment Connection Establishment] <br />
#Baseado na captura de pacotes realizada responda:<br />
##Quais foram as portas de origem e destino usadas?<br />
##Quais os tamanhos das janelas informadas, tanto pelo cliente quanto pelo servidor?<br />
##Quais os números de sequência informado pelo Wireshark e o número que consta no campo Data em bytes. Qual é relação entre esses números?<br />
##Em qual mensagem (número) aparece a texto que você digitou?<br />
##Qual o número identificador de protocolo TCP no pacote IP?<br />
#*Um dos objetivos do processo de conexão é sincronizar o número de sequência. Cada lado fica sabendo do número de sequência do outro. O número de sequência não começa com zero.<br />
#*O Wireshark converte a numeração para mostrar a partir do 0 mas o número inicial de sequência é criado randomicamente por cada lado. (ver [https://wiki.wireshark.org/TCP_Relative_Sequence_Numbers])<br />
#Volte ao wireshark e analise o processo de termino da conexão (iniciado pelo cliente neste caso, no momento do CTRL+D).<br />
#*Note que qualquer uma das partes pode realizar esta finalização.<br />
#*Pode ser observado que o cliente envia um pacote TCP com flag FIN.<br />
#*O servidor responde com um FIN-ACK.<br />
#*Finalmente o cliente faz um ACK. <br />
#*Veja se confere com a figura [http://www.tcpipguide.com/free/t_TCPConnectionTermination-2.htm Término de conexão TCP] ou com os [http://docente.ifsc.edu.br/odilson/RCO60803/TCP%20Basico.pdf slides] apresentados no início da aula.<br />
#Gere com o wireshark um diagrama da comunicação, ou diagrama de troca de mensagens, fazendo: Statistics > Flow Graph > OK<br />
#Analise esse diagrama, observando qual pacote contém os dados, ou seja, o texto que você digitou.<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 10 - Desvendando o TCP - Número de Sequência, Controle de Erros e Funcionamento Full-Duplex}}<br />
<br />
===Objetivos===<br />
<br />
*Verificar:<br />
**Controle de Erros: Significado de Número de Sequência, ACK<br />
**Controle de Fluxo: Significado do campo Windows Size; Funcionamento do controle de fluxo;<br />
**Comportamento Full-Duplex<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/TCP%20controle%20de%20erros.pdf TCP - Controle de Erros]<br />
<br />
==Configuração do Laboratório==<br />
O roteiro será executado sobre máquinas virtuais, através do uso do [[Netkit2 | Netkit2]]. Copie o texto abaixo, abra o editor Gedit, cole o texto e salve o arquivo em /home/aluno/TCP.conf.<br />
<syntaxhighlight lang=bash><br />
PC1[type]=generic<br />
PC2[type]=generic<br />
PC3[type]=generic<br />
<br />
<br />
PC1[eth0]=lan0:ip=10.0.0.1/24<br />
PC2[eth0]=lan0:ip=10.0.0.2/24<br />
PC3[eth0]=lan0:ip=10.0.0.3/24<br />
</syntaxhighlight><br />
<br />
===PARTE 1 - Transmissão sem erros: Verificação de Número de Sequência, Reconhecimentos e Controle de Fluxo===<br />
#Executar a configuração do laboratório no Netkit. Abra o NetKit2 e abra o arquivo de configuração: <syntaxhighlight lang=bash><br />
File > Load and Run </syntaxhighlight><br />
#*Perceba que abrirá uma janela com três abas inferiores, representando três máquina virtuais criadas pelo Netkit, denominadas: PC1, PC2 e PC3. Cada uma dessas abas é o terminal de configuração da respectiva máquina virtual.<br />
#Utilize o editor de texto '''gedit''' da máquina real, inclua o texto abaixo, e salve como '''/home/aluno/lab/shared/arq.tx''' <syntaxhighlight lang=bash><br />
ABCDEFGHIJKLMNOPQRSTUVXZW1234 </syntaxhighlight><br />
#Execute o tcpdump no PC3 <syntaxhighlight lang=bash><br />
tcpdump -i eth0 tcp port 5555 -s 1024 -U -w /hostlab/shared/pc3.pcap </syntaxhighlight><br />
#Execute os comandos abaixo no PC2 (copie e cole).<br />
##O primeiro comando limita sua capacidade de recepção em cerca de 20 bytes (tamanho do ''buffer''). Isto permitirá ver a quebra do arquivo de 30 bytes em alguns segmentos TCP.<br />
##O segundo comando abre a porta 5555, através do netcat, e espera a chegada dos dados.<syntaxhighlight lang=bash><br />
sysctl -w net.ipv4.tcp_rmem='20 20 20'<br />
netcat -l 5555 > arq.rx </syntaxhighlight><br />
#Envie o arquivo arq.tx a partir do PC1 com o comando:<syntaxhighlight lang=bash><br />
netcat 10.0.0.2 5555 < /hostlab/shared/arq.tx </syntaxhighlight><br />
#No PC3 faça CTRL+C, para parar a captura de pacotes.<br />
#Abra o arquivo de captura gravado no PC3 (/home/aluno/lab/shared/pc3.pcap) com o Wireshark:<br />
##Abrir o Wireshark e ir no menu File > Open > Pasta Pessoal > lab > shared > pc3.pcap<br />
#Você terá algo parecido com o apresentado na Figura 1.[[Arquivo:WiresharkTCPPerdaDePacotes.png |thumb | 600px| Fig.1 -- Protocolo TCP]]<br />
#Analise como os dados foram transmitidos e reconhecidos.<br />
====Perguntas====<br />
#Qual o número de sequência (normalizado pelo Wireshark) de cada segmento de dados transmitido (de PC1 para PC2) e qual o significado do número de reconhecimento em cada um deles? <br />
#Como foi reconhecido cada segmento enviado? <br />
#*Relate esta análise por segmento usando os timestamps (coluna Time) como referência.<br />
<br />
====Arquivo CAP deste experimento====<br />
<br />
*[https://www.dropbox.com/s/cv82wa1r3jatvgp/tcp_parte1-pc3-sequencia-controle-fluxo.cap Sequencia.cap]<br />
<br />
===PARTE 2 - Transmissão com erros: retransmissões===<br />
<br />
#Repetir todo a parte 1 mas substituir o item 4 por: <syntaxhighlight lang=bash><br />
sysctl -w net.ipv4.tcp_rmem='20 20 20'<br />
tc qdisc add dev eth0 root netem loss 50% <br />
netcat -l 5555 > arq.rx </syntaxhighlight><br />
Perguntas:<br />
#Qual o número de sequência (normalizado pelo Wireshark) de cada segmento de dados transmitido (de PC1 para PC2) e qual o significado do número de reconhecimento em cada um deles?<br />
#Como foi reconhecido cada segmento enviado?<br />
#Houve perda de pacotes? Como você identificou isso?<br />
#Os pacotes perdidos foram retransmitidos? Justifique.<br />
<br />
====arquivo cap deste experimento====<br />
<br />
*[https://www.dropbox.com/s/fb9izlu3ykin4yt/pc3-retransmissoes.cap retransmissoes.cap]<br />
<br />
===PARTE 3 - Testando a capacidade do TCP de enviar dados de forma duplex===<br />
<br />
*Agora vamos deixar de lado o netkit para fazer um pequeno teste de transmissão de arquivos entre dois colegas.<br />
*No experimento, o arquivo de um aluno será transmitido para outro e vice-versa.<br />
<br />
#Em um terminal da máquina real, crie um diretório de trabalho e entre no mesmo <syntaxhighlight lang=bash><br />
mkdir teste<br />
cd teste </syntaxhighlight><br />
#Com o '''gedit''' construa um arquivo de cerca de 2000 bytes. Coloque neste arquivo o seu poema ou letra de canção preferida. Salve o arquivo com nome '''/home/aluno/teste/arq.tx'''.<br />
#Escolha um colega para transferir o arquivo.<br />
##Negocie quem será o servidor e quem será o cliente.<br />
##No processo, o arquivo criado por um aluno será enviado ao colega e vice-versa (tx, rx).<br />
#O servidor deve fazer <syntaxhighlight lang=bash><br />
netcat -l 5555 < arq.tx > arq.rx </syntaxhighlight><br />
#*Ao término da transmissão, o arq.rx conterá os dados recebidos.<br />
#O cliente deve fazer, <span style="color: red;">lembre-se de adequar o IP_SERVIDOR<syntaxhighlight lang=bash><br />
netcat IP_SERVIDOR 5555 < arq.tx > arq.rx </syntaxhighlight><br />
#*<span style="color: black;">Ao término da transmissão, o arq.rx conterá os dados recebidos.<br />
#Abra o arquivo recebido do colega (arq.rx) com o '''gedit''' e confira o conteúdo.<br />
Perguntas:<br />
#Onde pode ser observado a comunicação ''full-duplex''?<br />
#Qual é a relação entre os comandos do cliente e servidor com a comunicação ''full-duplex''?<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 11 - Controle de congestionamento e equidade do TCP}}<br />
<br />
===Objetivos===<br />
*Tem como objetivo gerar um gráfico para facilitar a visualização do '''controle de congestionamento''' e a consequente '''equidade''' do protocolo TCP.<br />
*Utilizar o software [https://iperf.fr/ Iperf] (iperf –h para help) para gerar tráfego entre duas máquinas, '''cliente''' e '''servidor'''.<br />
*Utilizar o software [[netkit2]].<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/TCP%20controle%20de%20congestionbamento%20e%20equidade.pdf TCP - Controle de Congestionamento e Equidade]<br />
*[https://media.pearsoncmg.com/aw/ecs_kurose_compnetwork_7/cw/content/interactiveanimations/tcp-congestion/index.html Animação do controle de congestinamento]<br />
<br />
===Roteiro===<br />
*O roteiro será executado sobre máquinas virtuais, através do uso do [[Netkit2 | Netkit2]].<br />
*Para realização dos ensaios será montada a rede virtual apresentada na Figura 1. <br />
<br />
[[Arquivo:TCP_Rede_Controle_de_Fluxo.png |thumb | 200px| Figura 1 - Rede ara testes]]<br />
#Copie o texto abaixo e crie um arquivo com o '''Gedit''', salve-o como /home/aluno/TCP.conf.<syntaxhighlight lang=bash><br />
# Definição das máquinas<br />
R1[type]=router<br />
PC1[type]=generic<br />
PC2[type]=generic<br />
PC3[type]=generic<br />
<br />
# Definição dos roteadores padrão<br />
PC1[default_gateway]=10.0.0.254<br />
PC2[default_gateway]=10.0.1.254<br />
PC3[default_gateway]=10.0.1.254<br />
<br />
# Definição das interfaces do roteador <br />
R1[eth0]=lan0:ip=10.0.0.254/24:rate=10000<br />
R1[eth1]=lan1:ip=10.0.1.254/24:rate=10000<br />
<br />
# Definição das interfaces dos PCs<br />
PC1[eth0]=lan0:ip=10.0.0.1/24:rate=10000<br />
PC2[eth0]=lan1:ip=10.0.1.2/24:rate=10000<br />
PC3[eth0]=lan1:ip=10.0.1.3/24:rate=10000 </syntaxhighlight><br />
#Execute o NetKit2.<br />
#Carregue o arquivo de configuração: <syntaxhighlight lang=bash><br />
File > Load and Run </syntaxhighlight><br />
#*Perceba que abrirá uma janela com quatro abas inferiores, representando um roteador e três máquina virtuais criadas pelo Netkit, denominadas: R1, PC1, PC2 e PC3. Cada uma dessas abas é o terminal de configuração do respectivo equipamento.<br />
#*Ao clicar no menu '''File - Graph''', pode-se ter uma visão da rede a ser simulada e conferir se é equivalente ao diagrama proposto.<br />
#Execute no PC3 o tcpdump para salvar a troca de dados entre o PC1 e o PC2 num arquivo: <syntaxhighlight lang=bash><br />
tcpdump -i eth0 -w /hostlab/shared/pc3.cap </syntaxhighlight><br />
#*Para copiar comando para os terminais das máquinas virtuais: copie o texto desejado, no Netkit selecione o terminal da máquina desejada e clique sobre a "rodinha" do mouse que o texto será colado.<br />
#No PC1 (servidor) execute: <syntaxhighlight lang=bash><br />
iperf -s -p 2000 & iperf -s -p 2001 & iperf -s -p 2002 & </syntaxhighlight><br />
#No PC2 (cliente) execute (copie a três linhas e cole no terminal adequado e em seguida tecle <Enter>): <syntaxhighlight lang=bash><br />
iperf -c 10.0.0.1 -f m -i 1 -t 90 -p 2000 -l 1300 & \<br />
(sleep 20; iperf -c 10.0.0.1 -f m -i 1 -t 70 -p 2001 -l 1300) & \<br />
(sleep 30; iperf -c 10.0.0.1 -f m -i 1 -t 60 -p 2002 -l 1300) & </syntaxhighlight><br />
#Fique monitorando o PC2 até a tela parar de ser atualizada, aproximadamente 90 s.<br />
#Pare os processos nos três PCs utilizando CTRL-C.<br />
#Abra o Wireshark.<br />
#Abra o arquivo <syntaxhighlight lang=bash><br />
File > Open > /home/aluno/lab/shared/pc3.cap </syntaxhighlight><br />
#No wireshark acesse '''Statistics''' >> '''IO Graph''' e, na tela que abrir, ajuste TODOS os parâmetros para obter um gráfico similar ao apresentado na Figura 2.<br />
#*Perceba que todos os botões '''Graph 1...4''' devem ser clicados, e os filtros aplicados (tcp.port==2000; tcp.port==2001; tcp.port==2002) isso fará com que o Wireshark mostre as respectivas curvas. [[Arquivo:TCP_Wireshark.png |thumb | 400px| Figura 2 - Captura de 3 fluxos de dados]]<br />
#Responda:<br />
##Explique detalhadamente o significado de cada parâmetro dos comandos dos itens 5 e 6 acima, tanto do cliente quanto do servidor.<br />
##Explique os filtros aplicados no gráfico do Wireshark.<br />
##*Quais são os 4 gráficos apresentados?<br />
##*Há uma relação de valor entre as curvas?<br />
##*Qual é esta relação?<br />
##Por que a curva vermelha se sobrepõe a curva preta nos primeiros 20 segundos? Considere o início do tempo onde há início de tráfego!<br />
##Qual é a relação entre a curva preta e as curvas vermelha e verde no intervalo entre 20 e 30 segundos?<br />
##Explique a relação entre as 4 curvas e o comando do cliente (item 5) no intervalo entre 20 e 40 segundos.<br />
##Qual é o mecanismo do TCP que explica a grande oscilação das curvas, principalmente percebida no intervalo entre 20 e 30 segundos?<br />
<br />
=====Incluindo UDP=====<br />
Agora vamos dificultar a vida do TCP incluindo um tráfego UDP. O gráfico gerado deverá apresentar a competição pelo meio de transmissão entre os diversos fluxos de dados.<br />
#Deslique o NetKit2, para limpar todos os processos e ''buffers'': <syntaxhighlight lang=bash><br />
File > Quit </syntaxhighlight><br />
#Copie o texto abaixo e crie um arquivo, salve-o como /home/aluno/TCPxUDP.conf: <syntaxhighlight lang=bash><br />
# Definição das máquinas<br />
R1[type]=router<br />
PC1[type]=generic<br />
PC2[type]=generic<br />
PC3[type]=generic<br />
PC4[type]=generic<br />
<br />
# Definição dos roteadores padrão<br />
PC1[default_gateway]=10.0.0.254<br />
PC2[default_gateway]=10.0.1.254<br />
PC3[default_gateway]=10.0.1.254<br />
PC4[default_gateway]=10.0.1.254<br />
<br />
# Definição das interfaces do roteador <br />
R1[eth0]=lan0:ip=10.0.0.254/24:rate=10000<br />
R1[eth1]=lan1:ip=10.0.1.254/24:rate=10000<br />
<br />
# Definição das interfaces dos PCs<br />
PC1[eth0]=lan0:ip=10.0.0.1/24:rate=10000<br />
PC2[eth0]=lan1:ip=10.0.1.2/24:rate=10000<br />
PC3[eth0]=lan1:ip=10.0.1.3/24:rate=10000<br />
PC4[eth0]=lan1:ip=10.0.1.4/24:rate=10000 </syntaxhighlight><br />
#Execute o NetKit2 e carregue o arquivo de configuração.<br />
#No PC4 execute: <syntaxhighlight lang=bash><br />
tcpdump -i eth0 -w /hostlab/shared/pc4.cap </syntaxhighlight><br />
#No PC1 execute: <syntaxhighlight lang=bash><br />
iperf -s -u -p 2000 & iperf -s -p 2001 & </syntaxhighlight><br />
#A próxima etapa deve ser executada "simultaneamente" nos PC2 e PC3.<br />
##Para isso copie o texto abaixo e cole no terminal do PC2, ainda NÃO tecle <Enter>: <syntaxhighlight lang=bash><br />
iperf -u -c 10.0.0.1 -f m -i 1 -t 60 -p 2000 -l 1300 -b 10000000 </syntaxhighlight><br />
##Copie o texto abaixo e cole no terminal do PC3, ainda NÃO tecle <Enter>: <syntaxhighlight lang=bash><br />
iperf -c 10.0.0.1 -f m -i 1 -t 90 -p 2001 -l 1300 </syntaxhighlight><br />
##Tecle <Enter> no PC3 e PC2, NESSA ORDEM, "simultaneamente".<br />
#Fique monitorando o PC3 a tela parar de ser atualizada, aproximadamente 90 s.<br />
#Pare os processos nos quatro PCs utilizando CTRL-C.<br />
#Rode o Wireshark e abra o arquivo /home/aluno/lab/shared/pc4.cap.<br />
#Baseado na Figura 3, no '''Graph 2''' altere o filtro para '''udp.port==2000''' e no '''Graph 3''' altere o filtro para '''tcp.port==2001'''. Salve o gráfico gerado.<br />
[[Arquivo:TCPxUDP_Wireshark.png |thumb | 400px| Figura 3 - Captura de 2 fluxos de dados TCP e UDP]]<br />
#Responda as mesmas questões do item anterior, '''todas'''.<br />
#Explique o comportamento dos vários fluxos de dados com e sem o UDP.<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 12 - TCP x UDP}}<br />
<br />
===Objetivos===<br />
*O objetivo desses experimentos é evidenciar as diferenças entre os protocolos TCP e UDP.<br />
*Ambos protocolos de transporte podem ser usados por aplicações que precisem se comunicar. Porém cada um deles têm certas propriedades, então a escolha precisa ser realizada baseada no tipo de comunicação a ser feita pela aplicação.<br />
<br />
==== Experimento 1 ====<br />
<span style="color: red;">Antes de qualquer experimento deve-se desabilitar algumas funcionalidades do kernel do LINUX, para que os experimentos reflitam a teoria. Caso sua interface de rede não seja a '''eth0''' adapte o comando, caso reiniciar a máquina repita-o:</span><br />
<syntaxhighlight lang=bash>sudo ethtool --offload eth0 gso off tso off sg off gro off </syntaxhighlight><br />
<br />
O que aconteceria se um arquivo fosse transferido de um computador a outro com ambos protocolos?<br />
<br />
# Abra um terminal e execute o seguinte comando para fazer o download de um arquivo a ser usado no experimento: <syntaxhighlight lang=bash><br />
wget http://tele.sj.ifsc.edu.br/~odilson/RED29004/jogo.exe<br />
</syntaxhighlight><br />
# Observe o tamanho do arquivo transferido ... ele deve ter exatamente 332831416 bytes (cerca de 318 MB). Você pode fazer isso com o comando '''ls -l jogo.exe''', ou executando o gerenciador de arquivos e visualizando as propriedades desse arquivo.<br />
# Escolha um colega para fazer o experimento em que o arquivo será transferido de um computador para o outro. NÃO pode ser na própria máquina. Um será o '''receptor''' e outro o '''transmissor'''.<br />
=====A primeira transferência será feita usando o protocolo TCP da seguinte forma=====<br />
#Execute o WireShark e deixe-o capturando pacotes '''somente''' durante a transferência do arquivo. Como o o comportamento padrão do wireshark é redefinir o número de sequência para sempre iniciar em um e isso pode atrapalhar nossos experimentos, vamos '''desabilitar/desativar''' essa funcionalidade: <syntaxhighlight lang=bash><br />
Edit >> Preferences >> Protocols >> TCP >> Relative sequence numbers </syntaxhighlight><br />
#No computador '''receptor''' execute o '''netcat''' ('''nc''') (utilize '''man nc''' para saber os detalhes das ''flags'' utilizadas) que abrirá uma conexão TCP na porta, por exemplo, 5555 e salvará os dados transferidos em '''arquivo''': <syntaxhighlight lang=bash><br />
nc -vvnl 5555 > arquivoTCP<br />
</syntaxhighlight><br />
#No computador '''transmissor''' execute, após o processo do '''receptor''' estar executando ('''adeque o ip_do_receptor para o devido número IP'''): <syntaxhighlight lang=bash><br />
time nc -vvn ip_do_receptor 5555 < jogo.exe<br />
</syntaxhighlight><br />
#Quando completar a transferência, pare o Wireshark.<br />
#Verifique o tamanho do arquivo recebido. Ele é igual ao arquivo original? E quanto tempo levou para transmiti-lo? No terminal digite: <syntaxhighlight lang=bash><br />
ls -l </syntaxhighlight><br />
#Analisando a captura de pacotes do WireShark responda:<br />
## Quais as portas origem e destino escolhidas pelo cliente e servidor?<br />
## Qual é o número de sequência do primeiro e do último pacote?<br />
## Qual é o número de sequência do primeiro e do último ACK?<br />
## Qual o Tamanho Máximo de Segmento (MSS) escolhidos pelo cliente e servidor na conexão.<br />
## É possível calcular o tamanho do arquivo pela análise dos pacotes? Qual é a maneira mais fácil? Apresente os cálculos ou descreva a maneira de obtenção do valor.<br />
## Qual é o tamanho do último segmento de dados recebido?<br />
## Todos os segmentos trocados entre as máquinas contém dados ou alguns são somente de controle? Qual o percentual aproximado de segmentos de controle?<br />
<br />
=====A segunda transferência será feita usando o protocolo UDP=====<br />
#Execute o WireShark e deixe-o capturando pacotes '''somente''' durante a transferência do arquivo.<br />
#Combine com um colega e estabeleça quem suem será o transmissor e quem será o receptor. No computador '''receptor''' baixe o programa '''receptor''', acrescente a ele permissão de execução e o execute, conforme a sequência de comandos abaixo: <syntaxhighlight lang=bash><br />
wget http://tele.sj.ifsc.edu.br/~odilson/RED29004/receptor<br />
chmod +x receptor<br />
./receptor 5555 > arquivoUDP<br />
</syntaxhighlight><br />
#No computador '''transmissor''' baixe o programa '''transmissor''', acrescente a ele permissão de execução e o execute, conforme a sequência de comandos abaixo: <syntaxhighlight lang=bash><br />
wget http://tele.sj.ifsc.edu.br/~odilson/RED29004/transmissor<br />
chmod +x transmissor </syntaxhighlight><br />
#Inicie a transferência do arquivo ('''adeque o ip_do_receptor para o número IP do colega'''): <syntaxhighlight lang=bash><br />
./transmissor ip_do_receptor 5555 < jogo.exe<br />
</syntaxhighlight><br />
#Quando completar a transferência (vai aparecer a mensagem no '''transmissor''' "Levou XXXXX segundos para transmitir XXXXX bytes).<br />
#No '''receptor''' digite <CTRL + C><br />
#Verifique o tamanho do arquivo recebido.<br />
##Ele é igual ao arquivo original?<br />
##Quanto tempo levou para transmiti-lo?<br />
#Analisando a captura de pacotes do WireShark responda:<br />
## Qual é o número de sequência do primeiro e do último pacote? Existe?<br />
## É possível calcular o tamanho do arquivo pela análise dos pacotes? É mais fácil ou difícil que no caso da transferência via TCP?<br />
## Há segmentos de controle ou somente segmentos de dados?<br />
## Qual é o tamanho do último segmento de dados recebido?<br />
# Compare as transferências feitas com os protocolos TCP e UDP.<br />
## O que eles têm em comum?<br />
## Que diferenças lhe pareceram mais pronunciadas?<br />
## Como isso deve afetar as aplicações que usam esses protocolos?<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 13 - Interligação de duas redes locais via um roteador}}<br />
<br />
===Objetivos===<br />
<br />
*Introdução ao mundo IP<br />
*Verificação das configurações de interfaces<br />
*Verificação de tabelas de roteamento nos hospedeiros e no roteador<br />
*Verificação de roteamento no roteador<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IP%20Basico.pdf Introdução a Camada de Rede]<br />
*[http://tele.sj.ifsc.edu.br/~eraldo/AULAS/2018-2/RCO-INTEGRADO/MACxIP.pdf Endereçamento MAC x Endereçamento IP]<br />
<br />
===Procedimento===<br />
<br />
#Construir uma rede no Netkit com dois PCs e um roteador. Use um arquivo lab.conf da forma: <syntaxhighlight lang=text><br />
r1[type]=router<br />
<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
r1[eth0]=lan0:ip=192.168.200.254/24<br />
r1[eth1]=lan1:ip=192.168.100.254/24<br />
<br />
pc1[eth0]=lan0:ip=192.168.200.1/24<br />
pc1[default_gateway]=192.168.200.254<br />
<br />
pc2[eth0]=lan0:ip=192.168.200.2/24<br />
pc2[default_gateway]=192.168.200.254<br />
<br />
pc3[eth0]=lan1<br />
<br />
pc4[eth0]=lan1:ip=192.168.100.2/24<br />
pc4[default_gateway]=192.168.100.254<br />
</syntaxhighlight><br />
#Chamar o netkit2 (Aplicativos >> Educativo >> Netkit2)<br />
#Forçar a atualização do Netkit2: <syntaxhighlight lang=text> General >> Update </syntaxhighlight><br />
#Carregar o arquivo '''lab.conf''' a partir do Netkit2:<syntaxhighlight lang=bash><br />
File >> Load Only<br />
</syntaxhighlight><br />
#Visualizar a rede a ser implementada:<syntaxhighlight lang=bash><br />
File >> Graph<br />
</syntaxhighlight><br />
#Executar a rede: <syntaxhighlight lang=bash><br />
Network >> Start<br />
</syntaxhighlight><br />
#Copie o diagrama da rede para o papel e, para todas interfaces de rede apresentadas no diagrama, anote, baseados nos comandos dos itens seguintes:<br />
##Endereço IP<br />
##Endereço MAC<br />
##Roteador padrão<br />
#Observar os endereços de hardware (ou MAC) e IP de cada dispositivo na rede. No terminal de cada '''pc''' execute: <syntaxhighlight lang=bash><br />
ifconfig </syntaxhighlight><br />
#Observar e interpretar a tabela de roteamento nos hospedeiros '''pc1''' e '''pc4'''. Identificar os ''default gateways'' em cada '''pc'''.<syntaxhighlight lang=bash><br />
route -n<br />
</syntaxhighlight><br />
#Observar e interpretar a tabela de roteamento no roteador ('''r1''')<syntaxhighlight lang=bash><br />
exit<br />
route -n<br />
</syntaxhighlight><br />
#Observar e "provar" que pacotes indo de '''pc1''' para '''pc4''' são encaminhados ao roteador e, em seguida, entregues ao destino, ou seja, entrega indireta.<br />
#*Use o '''ping''', '''tcpdump''' e seu diagrama de rede como apoio.<br />
#*Lembre-se que você pode verificar o fluxo de dados individualmente em cada interface de rede e, portanto, se certificar que se há ou não pacotes atravessando o roteador:<br />
#**Num primeiro momento em '''r1''':<syntaxhighlight lang=bash><br />
tcpdump -i eth0 -n -e</syntaxhighlight><br />
#**Em seguida, ainda em '''r1''': <syntaxhighlight lang=bash><br />
tcpdump -i eth1 -n -e</syntaxhighlight><br />
#**Ver: [http://www.tcpdump.org/tcpdump_man.html manpage do tcpdump]<br />
#Observar e "provar" que pacotes indo de '''pc1''' para '''pc2''' na '''lan0''' são enviados diretamente para '''pc2''', ou seja, entrega direta.<br />
#*Use o '''ping''' e '''tcpdump''' como apoio, adequando os comandos apresentados no item anterior.<br />
<br />
===Configuração básica de interface de rede===<br />
#Configure a interface de rede no '''pc3'''.<br />
#*O mesmo deverá ser capaz de "pingar" para qualquer outro PC ou ser "pingado".<br />
#*Dica: observe a configuração de rede do '''pc4''' e tente adaptá-la para o '''pc3'''.<br />
#*Dica de ferramentas de configuração: use os comandos '''ifconfig''' e '''route'''. Use o '''man''' ou procure na web como utilizar esses comandos.<br />
#Execute o comando ping do '''pc3''' para o '''pc4'''. Obteve sucesso?<br />
#Execute o comando ping do '''pc3''' para o '''pc1'''. Obteve sucesso?<br />
#Execute o comando ping do '''pc2''' para o '''pc3'''. Obteve sucesso?<br />
<br />
====Referências adicionais====<br />
<br />
* [http://linux-ip.net/html Guia de Administração da Camada IP no Linux<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 14 - Roteamento Estático em Redes }}<br />
<br />
===Objetivo===<br />
<br />
*Proporcionar ao aluno uma visão prática de roteamento IP.<br />
*Princípios de configuração de rotas.<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IP%20Roteamento.pdf Introdução ao Roteamento]<br />
<br />
====PARTE 1 - Rede com 3 roteadores====<br />
<br />
:Laboratório a ser montado no netkit.<br />
<br />
[[Image:LabRoteamento-RCO1-2017-2.png |thumb | 800px| Figura 1 - Rede para roteamento]]<br />
<br />
#Construir a rede apresentada na Figura 1, usando como apoio a configuração do netkit descrita na sequência. As sub-redes (SN) a serem utilizadas na parte 1 e 2 são:<br />
## SN1 : 200.10.1.0/24<br />
## SN2 : 200.10.2.0/24 <br />
## SN3 : 200.10.3.0/24<br />
## SN4 : 200.10.4.0/24<br />
## SN5 : 200.10.5.0/24 <br />
## SN6 : 200.10.6.0/24 <br />
## SN7 : 200.10.7.0/24 <br />
## SN8 : 200.10.8.0/24<br />
#Abaixo o arquivo de configuração para o NetKit. Copie e salve como '''/home/aluno/roteamento.conf'''.<syntaxhighlight lang=text><br />
<br />
H1[type]=generic<br />
H2[type]=generic<br />
<br />
R1[type]=generic<br />
R2[type]=generic<br />
R3[type]=generic<br />
<br />
<br />
H1[eth0]=SN1:ip=200.10.1.1/24<br />
H2[eth0]=SN8:ip=200.10.8.1/24<br />
<br />
R1[eth0]=SN1:ip=200.10.1.254/24<br />
R1[eth1]=SN4:ip=200.10.4.1/24<br />
R1[eth2]=SN2:ip=200.10.2.1/24<br />
<br />
<br />
R2[eth0]=SN8:ip=200.10.8.254/24<br />
R2[eth1]=SN4:ip=200.10.4.2/24<br />
R2[eth2]=SN7:ip=200.10.7.1/24<br />
<br />
R3[eth0]=SN2:ip=200.10.2.2/24<br />
R3[eth1]=SN7:ip=200.10.7.2/24 </syntaxhighlight><br />
#Inicie o Netkit e carregue o arquivo de configuração e execute-o.<br />
#Execute comandos de ping entre os hosts e roteadores.<br />
##O ping entre as interfaces/equipamentos pertencentes a mesma sub-rede funcionam, por quê?<br />
##O ping entre interfaces/equipamentos de sub-redes distintas não funcionam, por quê?<br />
#Usando como apoio os comandos de inserção de rota insira as rotas default em H1 e H2:<br />
##H1: <syntaxhighlight lang=bash> route add default gw 200.10.1.254 </syntaxhighlight><br />
##H2: <syntaxhighlight lang=bash> route add default gw 200.10.8.254 </syntaxhighlight><br />
#Habilitar o roteamento e instalar rotas em cada roteador para que pacotes vindos de H1 para H2 passem por R1, R3 e R2. O retorno deve ser via R2 e R1.<br />
##R1: <syntaxhighlight lang=bash><br />
echo 1 > /proc/sys/net/ipv4/ip_forward<br />
echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth0/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth1/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth2/rp_filter<br />
route add -net 200.10.8.0/24 gw 200.10.2.2 </syntaxhighlight><br />
##R2: <syntaxhighlight lang=bash><br />
echo 1 > /proc/sys/net/ipv4/ip_forward<br />
echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth0/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth1/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth2/rp_filter<br />
route add -net 200.10.1.0/24 gw 200.10.4.1 </syntaxhighlight><br />
##R3: <syntaxhighlight lang=bash><br />
echo 1 > /proc/sys/net/ipv4/ip_forward<br />
echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth0/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth1/rp_filter<br />
route add -net 200.10.8.0/24 gw 200.10.7.1<br />
route add -net 200.10.1.0/24 gw 200.10.2.1 <br />
</syntaxhighlight><br />
#Teste a conectividade IP com o comando ping.<br />
##O ping entre as interfaces/equipamentos pertencentes a mesma sub-rede funcionam, por quê?<br />
##O ping entre interfaces/equipamentos de sub-redes distintas não funcionam, por quê?<br />
#Confirme os caminhos estabelecidos monitorando as interfaces com o tcpdump e/ou traceroute.<br />
<br />
====PARTE 2 - Desafio: Rede com 4 roteadores====<br />
<br />
#Crie um arquivo de configuração que descreva a rede abaixo no '''netkit'''.<br />
##Observe que essa rede tem somente um roteador a mais que a rede apresentada anteriormente.<br />
##As rotas devem ser configuradas de forma que pacotes que trafegam de H1 para H2 passem por R1, R3, R4 e R2.<br />
##O retorno (H2 ==> H1) deve ser por R2, R4 e R1.<br />
##Cada sub-rede SN está em uma rede ethernet separada.<br />
##Chame o professor e mostre que os roteamentos estão sendo realizados corretamente, com o apoio do tcpdump e tracerotue.<br />
<br />
* SN1 : 200.10.1.0/24<br />
* SN2 : 200.10.2.0/24 <br />
* SN3 : 200.10.3.0/24 <br />
* SN4 : 200.10.4.0/24 <br />
* SN5 : 200.10.5.0/24 <br />
* SN6 : 200.10.6.0/24 <br />
* SN7 : 200.10.7.0/24 <br />
* SN8 : 200.10.8.0/24<br />
<br />
[[Image:ExercicioConfEstaticaZebra.png]]<br />
<br />
====PARTE 3 - Criando loop para verificar o campo TTL====<br />
<br />
#Crie um conjunto de rotas que façam que um pacote vindo de H1 para H2 entre em um loop entre R1, R3, R2, R1.<br />
#Envie um pacote único com o ping de H1 para H2.<br />
#Rastreie com o tcpdump o pacote em loop e verifique o momento em que o pacote sai de circulação.<br />
<br />
==Links de Referência==<br />
<br />
* [http://en.wikipedia.org/wiki/Longest_prefix_match Prefixo Mais Longo]<br />
<br />
* [http://jodies.de/ipcalc?host=192.168.20.19&mask1=28&mask2= Calculador IP]<br />
<br />
* [http://linux-ip.net/html Guia de Administração da Camada IP no Linux]<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 15 - Sub-redes}}<br />
<br />
===Objetivos===<br />
*Compreender endereçamento IPv4.<br />
*Compreender o processo de alocação de faixas de IPs.<br />
*Compreender e manipular os números IPs.<br />
*Compreender e manipular as máscaras de rede.<br />
===Fonte Base===<br />
*[https://www.todoespacoonline.com/w/2015/06/calculo-de-sub-redes-ipv4/ Cálculo de Sub-rede IPv4]<br />
<br />
===Exercícios===<br />
#Considere um endereço IP 200.135.233.8/21. Determine:<br />
##O endereço da rede ao qual pertence;<br />
##O endereço de broadcast da rede;<br />
##A faixa de endereçamento que podem ser usados por hospedeiros desta rede.<br />
#Suponha que um administrador de rede tenha recebido o bloco de endereços 200.40.8.0/21 e que deseja dividir este bloco em 8 blocos de endereços iguais, de menor tamanho, para ser alocado a 8 sub-redes administradas por ele.<br />
##Determine o tamanho total do bloco de endereços.<br />
##Determine o tamanho de cada sub-bloco.<br />
##Determine o endereço/máscara de rede de cada sub-rede.<br />
#Quantas estações (''hosts'') uma rede 223.1.10.0/24 suporta? <br />
#Um provedor de acesso com bloco de IPs 200.23.16.0/20 deseja montar 8 sub-redes. Mostre como isso é possível e como ficaria os endereços de cada uma dessas sub-redes.<br />
#Um provedor de acesso a Internet possui o seguinte bloco de endereços IP: 12.17.192.0/18. Os endereços IP de 12.17.192.0 até 12.17.207.255 já estão alocados para clientes deste provedor. Este provedor precisa atender a quatro novos clientes, um deles necessita de rede com pelo menos 1000 endereços de IP válidos e os outros três necessitam de rede com pelo menos 30 IP válidos. Faça uma proposta para alocação de endereços IP para estes clientes. Os endereços reservados para estes novos clientes devem ser alocados a partir da numeração mais baixa disponível. Procure também responder as questões abaixo:<br />
##Qual o total de endereços que dispõe o provedor em questão?<br />
##Quantos endereços IP já estão utilizados?<br />
##Quantos endereços IP este provedor possui livres para alocar aos novos clientes?<br />
##Qual o endereço identificador de cada sub-rede dos novos clientes?<br />
##Qual o a máscara de rede de cada sub-rede dos novos clientes?<br />
##Qual o endereço de broadcast de cada sub-rede dos novos clientes?<br />
##Quantos endereços IP ainda sobrarão ao provedor após atender a estes clientes?<br />
#Um administrador precisa montar uma rede experimental conforme mostrada na Figura 1. Na sub-rede 1 ele precisará instalar cerca 25 ''hosts'', e nas sub-redes 2 e 3 ele precisará instalar cerca de 12 ''hosts''. O administrador dispõe do bloco de endereços IP 192.168.10.0/24 para ser utilizado no endereçamento da rede experimental. Faça uma proposta para alocação de endereços IP para cada sub-rede (rede 1, 2 e 3), incluindo também as sub-redes relativas aos enlaces ponto-a-ponto (rede AB, AC e BC). Responda ainda:<br />
##Qual o endereço identificador de rede de cada sub-rede (1, 2, 3, AB, AC e BC)?<br />
##Qual o a máscara de rede de cada sub-rede (1, 2, 3, AB, AC e BC)?<br />
##Quais os endereços IP que serão atribuídos a cada interface de rede nos enlaces ponto-a-ponto dos roteadores (enlaces relativos as redes AB, AC e BC)? [[Arquivo:CdrEx.png |thumb | 400px| Figura 1 - Rede experimental]]<br />
<br />
*Para conferir seu cálculos utilize, por exemplo, as seguintes ferramentas:<br />
**Terminal Linux: '''ipcalc'''<br />
**Site web: [http://jodies.de/ipcalc ipcalc]<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 16 - Sub-redes e Roteamento Estático em Redes }}<br />
<br />
===Objetivos===<br />
*Compreender endereçamento IPv4.<br />
*Compreender o processo de alocação de faixas de IPs.<br />
*Compreender e manipular os números IPs.<br />
*Compreender e manipular as máscaras de rede.<br />
*Proporcionar ao aluno uma visão prática de roteamento IP.<br />
<br />
===Fonte Básica===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IP_DHCP_NAT.pdf DHCP e NAT]<br />
*[http://www.davidc.net/sites/default/subnets/subnets.html Cálculo de sub-redes]<br />
<br />
===Roteiro===<br />
<br />
#Um administrador precisa montar uma rede experimental conforme mostrada na Figura 1. Na sub-rede 1 ele precisará instalar cerca 50 ''hosts'', e nas sub-redes 2 e 3 ele precisará instalar cerca de 20 ''hosts''. O administrador dispõe do bloco de endereços IP 192.168.10.0/24 para ser utilizado no endereçamento da rede experimental. Faça uma proposta para alocação de endereços IP para cada sub-rede (rede 1, 2 e 3), incluindo também as sub-redes relativas aos enlaces ponto-a-ponto (rede AB, AC e BC). Responda ainda:<br />
##Qual o endereço identificador de rede de cada sub-rede (1, 2, 3, AB, AC e BC)?<br />
##Qual o a máscara de rede de cada sub-rede (1, 2, 3, AB, AC e BC)?<br />
##Quais os endereços IP que serão atribuídos a cada interface de rede nos enlaces ponto-a-ponto dos roteadores (enlaces relativos as redes AB, AC e BC)? [[Arquivo:CdrEx.png |thumb | 400px| Figura 1 - Rede experimental]]<br />
#Baseado no arquivo exemplo abaixo, crie um arquivo de configuração para o NetKit que implemente sua proposta. O arquivo deve contemplar todas as configurações necessárias para o perfeito funcionamento da rede, ou seja, ao carregar o arquivo todos os hosts deverão ser capazes de "pingar" uma ao outro. <br />
##Faça testes de conectividade entre os hosts.<br />
##Demostre para o professor o perfeito funcionamento de sua rede.<br />
*O arquivo de configuração do Netkit abaixo, é a definição para o perfeito funcionamento da simulação da rede apresentada na Figura 2. [[Arquivo:DynamicRoutingTriangle.png |thumb | 400px| Figura 2 - Rede exemplo]]<br />
<syntaxhighlight lang=bash><br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=link0:ip=192.168.0.1/24<br />
pc2[eth0]=link1:ip=192.168.1.1/24<br />
pc3[eth0]=link2:ip=192.168.2.1/24<br />
<br />
# Default gateways definitions<br />
pc1[default_gateway]=192.168.0.254<br />
pc2[default_gateway]=192.168.1.254<br />
pc3[default_gateway]=192.168.2.254<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
r3[type]=gateway<br />
<br />
# Routers' interfaces to local networks<br />
r1[eth0]=link0:ip=192.168.0.254/24<br />
r2[eth0]=link1:ip=192.168.1.254/24<br />
r3[eth0]=link2:ip=192.168.2.254/24<br />
<br />
# Network "backbone" links<br />
r1[eth1]=backbone0:ip=10.0.0.1/30<br />
r1[eth2]=backbone1:ip=10.0.1.1/30<br />
<br />
r2[eth1]=backbone0:ip=10.0.0.2/30<br />
r2[eth2]=backbone2:ip=10.0.2.1/30<br />
<br />
r3[eth1]=backbone1:ip=10.0.1.2/30<br />
r3[eth2]=backbone2:ip=10.0.2.2/30 <br />
<br />
# Routes definition<br />
r1[route]=192.168.2.0/24:gateway=10.0.1.2<br />
r1[route]=192.168.1.0/24:gateway=10.0.0.2<br />
r1[route]=10.0.2.0/30:gateway=10.0.0.2<br />
r2[route]=192.168.0.0/24:gateway=10.0.0.1<br />
r2[route]=192.168.2.0/24:gateway=10.0.2.2<br />
r2[route]=10.0.1.0/30:gateway=10.0.2.2<br />
r3[route]=192.168.0.0/24:gateway=10.0.1.1<br />
r3[route]=192.168.1.0/24:gateway=10.0.2.1<br />
r3[route]=10.0.0.0/30:gateway=10.0.2.1</syntaxhighlight><br />
<br />
===Referencia===<br />
<br />
*[http://www.davidc.net/sites/default/subnets/subnets.html Link Calculador Online de Subnets]<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 17 - Tecnologia de Enlace Ethernet }}<br />
<br />
===Objetivos===<br />
<br />
*Compreender que Ethernet não é Internet e que não é necessário o mundo IP para haver comunicação.<br />
*Diferenciar Hub de Switch<br />
*Compreender o papel do protocolo ARP<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/Camada%20de%20enlace.pdf Camada de Enlace]<br />
<br />
===Animação Pearson/Kurose===<br />
<br />
*[https://media.pearsoncmg.com/aw/ecs_kurose_compnetwork_7/cw/content/interactiveanimations/csma-cd/index.html Animação CSMA/CD]<br />
<br />
===PARTE 1===<br />
<br />
Neste experimento vamos conectar quatro computadores através de um Hub Ethernet. Este dispositivo faz com que todos os computadores se conectem tal como um cabo. Quando um PC envia uma mensagem para outro PC, TODOS os computadores podem ver esta mensagem. Para haver comunicação basta que um computador envie um frame ETHERNET direcionado para o endereço de hardware do computador destino. NÃO é necessário que as interfaces dos computadores estejam configuradas com endereços IP.<br />
<br />
[[Arquivo:RCO-Animacao_HUB.gif | thumb | 400px| Figura 2 - Funcionamento de um Hub]]<br />
<br />
#Contruir um arquivo '''\home\aluno\hub.conf''' com a seguinte configuração <syntaxhighlight lang=bash><br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
pc1[eth0]=lan0<br />
pc2[eth0]=lan0<br />
pc3[eth0]=lan0<br />
pc4[eth0]=lan0<br />
</syntaxhighlight><br />
#Carregar e executar a configuração no Netkit.<br />
#Baixar o arquivo sendraw.py: [http://tele.sj.ifsc.edu.br/~eraldo/AULAS/2018/RCO-INTEGRADO/sendraw.py sendraw.py] para o diretório /home/aluno<br />
#Copiar o arquivo para a Máquina Virtual, no terminal da máquina real digite:<syntaxhighlight lang=bash><br />
cp /home/aluno/sendraw.py /home/aluno/lab/shared </syntaxhighlight><br />
#Identificar o endereço de Hardware (MAC) do PC2. Use o '''ifconfig'''. Note que NÃO existe endereço IPv4 configurado.<br />
#Executar o tcpdump no PC2:<syntaxhighlight lang=bash><br />
tcpdump -i eth0 -e -X -vvv -s 50</syntaxhighlight><br />
#Executar o tcpdump no PC3:<syntaxhighlight lang=bash><br />
tcpdump -i eth0 -e -X -vvv -s 50</syntaxhighlight><br />
#Executar o tcpdump no PC4:<syntaxhighlight lang=bash><br />
tcpdump -i eth0 -e -X -vvv -s 50</syntaxhighlight><br />
#No PC1 enviar uma mensagem para o PC2 usando o endereço de hardware identificado anteriormente, <span style="color: red;">lembre-se se substituir o ENDERECO_MAC pelo MAC adequado:<syntaxhighlight lang=bash><br />
python /hostlab/shared/sendraw.py -d ENDERECO_MAC -i Alo-Mundo</syntaxhighlight> <span style="color: black;"><blockquote style="background: lime; border: 1px solid black; padding: 1em;"> Observe que a mensagem chega a todos os PCs embora foi enviada somente para o PC2. </blockquote><br />
#O que explica o comportamento de broadcast para esse caso?<br />
#Pode existir colisão em um sistema com HUBs simples como este do experimento?<br />
<br />
===PARTE 2 - Explorando o SWITCH e o endereço de Broadcast Ethernet===<br />
<br />
[[Arquivo:RCO-Animacao_SWITCH.gif | thumb | 370px| Figura 2 - Funcionamento de um Switch]]<br />
<br />
#Construir um arquivo '''/home/aluno/switch.conf''' com a seguinte configuração: <syntaxhighlight lang=bash><br />
switchA[type]=switch<br />
<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
switchA[eth0]=port0<br />
switchA[eth1]=port1<br />
switchA[eth2]=port2<br />
switchA[eth3]=port3<br />
<br />
pc1[eth0]=port0<br />
pc2[eth0]=port1<br />
pc3[eth0]=port2<br />
pc4[eth0]=port3<br />
</syntaxhighlight><br />
#Carregar e executar a configuração no Netkit.<br />
#Baixar o arquivo sendraw.py do site: [http://tele.sj.ifsc.edu.br/~eraldo/AULAS/2018/RCO-INTEGRADO/sendraw.py sendraw.py] para o /home/aluno.<br />
#Copiar o arquivo para a Máquina Virtual. No terminal da máquina real digite:<syntaxhighlight lang=bash><br />
cp /home/aluno/sendraw.py /home/aluno/lab/shared/ </syntaxhighlight><br />
#Identificar o endereço de Hardware (MAC) do PC2. Use o ifconfig. Note que NÃO existe endereço IPv4 configurado<br />
#Executar o tcpdump no PC2, PC3 e PC4 com o comando:<syntaxhighlight lang=bash><br />
tcpdump -i eth0 -e -X -vvv -s 50</syntaxhighlight><br />
#No PC1 enviar uma mensagem para o PC2 usando o endereço de hardware identificado anteriormente, <span style="color: red;">Lembre-se se substituir o ENDERECO_MAC pelo MAC adequado:<syntaxhighlight lang=bash><br />
python /hostlab/shared/sendraw.py -d ENDERECO_MAC -i Alo-Mundo </syntaxhighlight> <span style="color: black;"><blockquote style="background: lime; border: 1px solid black; padding: 1em;"> Agora somente o PC2 deve receber pois o ''switch'' entrega o quadro somente para a porta de saída associada ao respectivo MAC destino. </blockquote><blockquote style="background: red; border: 1px solid black; padding: 1em;"> CASO todos tenham recebido, é devido ao fato que por algum motivo o switch ainda não aprendeu quem está conectado nas portas. Neste caso envie pacotes do PC2 para o PC1 e depois retome o experimento do item 4. </blockquote><br />
#No PC1 enviar uma mensagem em broadcast (endereço FF:FF:FF:FF:FF:FF)<syntaxhighlight lang=bash><br />
python /hostlab/shared/sendraw.py -d FF:FF:FF:FF:FF:FF -i Mensagem_Broadcast </syntaxhighlight><br />
<blockquote style="background: lime; border: 1px solid black; padding: 1em;"><br />
Note que neste caso todos os computadores recebem a mensagem em ''broadcast'', mesmo sendo um '''switch'''.<br />
</blockquote><br />
<br />
===PARTE 3 - Explorando o ARP===<br />
<br />
O protocolo ARP serve como apoio para descoberta do endereço MAC dado que se sabe o endereço IP de uma máquina. Quando um PC deseja enviar um pacote IP para uma máquina na rede local, ele necessita descobrir o endereço MAC desta máquina. O protocolo ARP usa o broadcast ETHERNET para perguntar para todas as máquinas na rede QUEM tem o endereço IP em questão. A máquina que possui o endereço responderá informando o seu MAC.<br />
<br />
#Configure endereços IP em todas as máquinas do laboratório anterior. Use exemplo a rede 10.10.10.0/24<br />
#Rode o wireshark no '''PC2''' com os procedimentos:<br />
##Clique sobre a aba do '''PC2'''.<br />
##Menu: Wireshark >> any<br />
#Faça um ping do PC1 no PC2 e observe a sequência de pacotes trocados. Faça um diagrama no tempo mostrando a troca de pacotes até a realização do ECHO REQUEST do ping. Os resultados do Wireshark devem ser similares a: [[Arquivo:RCO-TelaARP.jpg | 700px| Troca de pacotes ARP e PING]]<br />
#Confira o cache do arp no PC1 fazendo:<syntaxhighlight lang=bash><br />
arp -a</syntaxhighlight><br />
#Confira o cache do arp no PC2 fazendo:<syntaxhighlight lang=bash><br />
arp -a</syntaxhighlight><br />
#Faça um ping do PC1 no PC3.<br />
#Confira novamente o cache do arp no PC1 fazendo:<syntaxhighlight lang=bash><br />
arp -a</syntaxhighlight><br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 18 - IPv6: Endereços e ''Neighbor Discovery''}}<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IPv6.pdf IPv6]<br />
<br />
Fontes Extras<br />
*Este roteiro foi baseado no material disponível no Livro - [http://www.paulogurgel.com.br/ Laboratório de IPv6].<br />
*[http://docente.ifsc.edu.br/odilson/RED29004/enderec-v6.pdf Guia didático de endereçamento IPv6] obtido de http://ipv6.br/.<br />
<br />
===Objetivos do laboratório:===<br />
*Um primeiro contato com o protocolo [https://pt.wikipedia.org/wiki/IPv6 IPv6].<br />
*Compreender o funcionando do ''Neighbor Discovery'', o equivalente ao ARP (''Address Resolution Protocol'') do IPv4, que em resumo é uma tabela contendo a relação ente IPs e MACs.<br />
*Aprender configurações básicas de interfaces IPv6 no Linux.<br />
<br />
===Introdução teórica===<br />
Obs.: texto copiado literalmente de: [http://ipv6.br/lab/ Laboratório de IPv6].<br />
<br />
A '''descoberta de vizinhança''' por meio do protocolo ''Neighbor Discovery'' no<br />
IPv6 é um procedimento realizado pelos nós de uma rede para descobrir endereços físicos dos dispositivos vizinhos presentes no mesmo enlace. A função deste protocolo se assemelha à função do ARP e do RARP no IPv4.<br />
*O procedimento é iniciado quando um dispositivo tenta enviar um pacote cujo endereço físico de destino é desconhecido. O nó solicitante envia uma mensagem ''Neighbor Solicitation'' (NS) para todos os nós do enlace pertencentes ao grupo ''multicast solicited-node'' (ff02::1:ffXX:XXXX), de modo que XX:XXXX são os últimos 24 bits do endereço IPv6 em que está interessado.<br />
*É possível notar que, por uma coincidência dos últimos 24 bits, é bastante provável que apenas o nó de destino faça realmente parte deste grupo. Isto é um ''truque'' interessante do IPv6 para diminuir o tráfego deste tipo de pacote na rede.<br />
*Na mensagem NS, o endereço IPv6 a ser resolvido é informado no campo ''Target''. O campo ''Source link-layer address'' informa ao nó de destino o endereço MAC do nó de origem, poupando-o de ter que fazer o mesmo procedimento no sentido inverso.<br />
*O nó de destino, dono do IPv6 requisitado, ao receber este pacote, envia uma mensagem ''Neighbor Advertisement'' (NA) como resposta diretamente ao nó requisitante. O seu endereço físico será informado no campo ''Target link-layer address''.<br />
*A informação de mapeamento entre endereços IP e endereços físicos é armazenada em uma tabela chamada ''neighbor cache''. Nela também fica registrado o ''status'' de cada destino, informando se o mesmo é alcançável ou não.<br />
<br />
===Roteiro de atividades: ETAPA 1===<br />
<br />
A figura abaixo apresenta o diagrama esquemático da rede a ser montada/analisada. Observe que todos os IPv6 ''Global Unicast'' já estão definidos na mesma, são esses IPs que utilizaremos em nosso experimento.<br />
<br />
[[Arquivo:Diagrama_rede_IPv6.jpg]]<br />
<br />
#Crie em seu computador um arquivo com nome '''/home/aluno/IPv6.conf''', com o seguinte conteúdo: <syntaxhighlight lang=bash><br />
#Ligacao das maquinas nos dominios de colisao<br />
#Duas pequenas redes interligadas pelo backbone<br />
<br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=link0:ipv6=2001:bcc:faca:1::101/64<br />
pc2[eth0]=link1:ipv6=2001:bcc:cafe:1::102/64<br />
pc3[eth0]=HUB1:ipv6=2001:bcc:1f0:1::103/64<br />
pc4[eth0]=HUB1<br />
<br />
#Default Gateways definitions<br />
pc1[route]=default6:gateway=2001:bcc:faca:1::1<br />
pc2[route]=default6:gateway=2001:bcc:cafe:1::1<br />
pc3[route]=default6:gateway=2001:bcc:1f0:1::1<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
#Routers interfaces definitions<br />
r1[eth0]=backbone0:ipv6=2001:db8:dead:1::1/64<br />
r1[eth1]=link0:ipv6=2001:bcc:faca:1::1/64<br />
r1[eth2]=link1:ipv6=2001:bcc:cafe:1::1/64<br />
<br />
r2[eth0]=backbone0:ipv6=2001:db8:dead:1::2/64<br />
r2[eth1]=HUB1:ipv6=2001:bcc:1f0:1::1/64<br />
<br />
#Routers definitions<br />
r1[route]=2001:bcc:1f0:1::0/64:gateway=2001:db8:dead:1::2<br />
r2[route]=2001:bcc:faca:1::0/64:gateway=2001:db8:dead:1::1<br />
r2[route]=2001:bcc:cafe:1::0/64:gateway=2001:db8:dead:1::1<br />
</syntaxhighlight><br />
#Tenha certeza que o Netkit2 estja atualizado: General >> Update.<br />
#Rode o NetKit em seu computador. Em um terminal digite: <syntaxhighlight lang=bash><br />
netkit2 & </syntaxhighlight><br />
#No menu '''File''' - '''Load and Run''', procure o arquivo '''/home/aluno/IPv6.conf''' e clique em OK. Abrirá uma janela com 6 abas, onde cada uma delas é um terminal de configuração do respectivo equipamento: '''pc1-4''' ou '''r1-2'''.<br />
#Observe que o '''pc4''' não está com sua interface configurada.<br />
#Ao clicar no menu '''File''' - '''Graph''', pode-se ter uma visão da rede a ser simulada e conferir se é equivalente ao diagrama proposto.<br />
#Faça um '''ping6''' entre o '''pc1''' ao '''pc3''': <syntaxhighlight lang=bash><br />
ping6 -c4 2001:bcc:1f0:1::103 </syntaxhighlight><br />
#Faça um '''ping6''' entre o '''pc1''' e '''pc2'''.<br />
#No '''pc4''' use o seguinte comando para adicionar o endereço IPv6 à interface de rede: <syntaxhighlight lang=bash><br />
ip addr add 2001:bcc:1f0:1::104/64 dev eth0 </syntaxhighlight><br />
#No '''pc4''', acrescente o ''default gateway'' com o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add default via 2001:bcc:1f0:1::1 dev eth0 </syntaxhighlight><br />
#No '''pc1''' use o seguinte comando para verificar como ficou a configuração dos endereços da interface de rede. O resultado é similar ao apresentado pelo comando '''ifconfig''': <syntaxhighlight lang=bash><br />
ip addr show dev eth0 </syntaxhighlight><br />
#Todo o roteamento está pronto, mas caso desejássemos poderíamos acrescentar rotas com comando similares aos já utilizados. Por exemplo, no '''r1''', para adicionar uma rota estática para a rede dos '''pc3''' e '''pc4''' utilizaríamos o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add 2001:bcc:1f0:1::/64 via 2001:db8:dead:1::2 dev eth0 </syntaxhighlight><br />
#Confira as rotas estabelecidas em todos os ''hosts'' com o comando abaixo. <br />
##São coerentes com os dados apresentados no diagrama acima?<syntaxhighlight lang=bash><br />
ip -6 route show </syntaxhighlight><br />
#No '''pc1''' use os seguintes comandos para ver a rota para alguns vizinhos: <syntaxhighlight lang=bash><br />
traceroute6 2001:bcc:1f0:1::103<br />
traceroute6 2001:bcc:1f0:1::104 </syntaxhighlight><br />
#*Anote as rotas.<br />
#Deixe um '''ping6''' entre o '''pc1''' ao '''pc3''' rodando: <syntaxhighlight lang=bash><br />
ping6 2001:bcc:1f0:1::103 </syntaxhighlight><br />
#Rode o wireshark no '''r1''' com os procedimentos:<br />
##Clique sobre a aba do '''r1'''.<br />
##Menu: Wireshark >> any<br />
#Analisando a captura do Wireshark, você verá os pacotes relativos ao ping6 e também pacotes parecidos com: <syntaxhighlight lang=bash> fe80::4cd6:19ff:fedc:2b52 2001:db8:dead:1::1 ICMPv6 86 Neighbor Solicitation for 2001:db8:dead:1::1 from 4e:d6:19:dc:2b:52<br />
2001:db8:dead:1::1 fe80::4cd6:19ff:fedc:2b52 ICMPv6 78 Neighbor Advertisement 2001:db8:dead:1::1 (rtr, sol) </syntaxhighlight><br />
#Explique o processo de descoberta de vizinhança (''Neighbor Discovery'' / ''Neighbor Solicitation'' - '''NS''' e ''Neighbor Advertisement'' - '''NA'''), citando o endereço '''link local''' utilizado.<br />
#*Alguns exemplos de campos visualizáveis para uma mensagem do tipo ''Neighbor Advertisement'':<br />
##Destination (camada Ethernet)<br />
##*O endereço MAC do nó requisitante que foi obtido por meio da mensagem NS enviada anteriormente.<br />
##Source (camada Ethernet)<br />
##*A origem é o endereço MAC da interface do dispositivo que enviou a resposta.<br />
##Type (camada Ethernet)<br />
##*Indica que a mensagem utiliza IPv6.<br />
##Next header (camada IPv6)<br />
##*Indica qual é o próximo cabeçalho. Neste caso, o valor 58 (0x3a) refere-se a uma mensagem ICMPv6.<br />
##Source (camada IPv6)<br />
##*A origem é o endereço IP da interface diretamente ligada ao enlace em que a requisição foi recebida.<br />
##Destination (camada IPv6)<br />
##*Diferentemente da mensagem NS, a mensagem NA possui como destino o endereço IPv6 global do nó requisitante.<br />
##Type (camada ICMPv6)<br />
##*Indica que a mensagem é do tipo 136 (Neighbor Advertisement).<br />
##Flags (camada ICMPv6)<br />
##*Uma mensagem NA possui três flags:<br />
###Indica se quem está enviando é um roteador. Neste caso, o valor marcado é 0, pois não é um roteador.<br />
###Indica se a mensagem é uma resposta a um NS. Neste caso, o valor marcado é 1, pois é uma resposta.<br />
###Indica se a informação carregada na mensagem é uma atualização de endereço de algum nó da rede. Neste caso, o valor marcado é 1, pois está informando o endereço pela primeira vez.<br />
##Target Address (camada ICMPv6)<br />
##*Indica o endereço IP associado às informações das flags. Neste caso, é o próprio endereço da interface do dispositivo em questão.<br />
##ICMPv6 option (camada ICMPv6)<br />
##*Indica as opções do pacote ICMPv6:<br />
###Target link-layer address<br />
##Type<br />
##*Indica o tipo de opção. Neste caso, Target link-layer address.<br />
##Link-layer address<br />
##*Indica o endereço MAC da interface do dispositivo em questão.<br />
#Em todos os ''hosts'' rode o comando <syntaxhighlight lang=bash> ip -6 neighbor show </syntaxhighlight><br />
##Qual é a funcionalidade desse comando?<br />
##Qual é o significado do conteúdo dessa tabela?<br />
##A tabela mostrada em cada um dos casos é compatível com o diagrama da rede montado?<br />
##Por que, por exemplo, na tabela do '''pc3''' não há uma referência explícita ao '''pc1'''?<br />
<br />
===Roteiro de atividades: ETAPA 2 - DESAFIO===<br />
<br />
Acrescentar um terceiro roteador ligado a R1 e R2 (backbone0). Acrescentar uma rede ethernet ligada a este roteador. Configure a rede com endereços IPv6 colocando pelo menos um PC adicional. Acrescente os roteamentos necessários para que este PC seja pingável a partir de PC1.<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 19 - Configurando uma Rede Doméstica}}<br />
<br />
===Objetivos===<br />
*Entender os componentes e princípio de funcionamento de uma rede residencial.<br />
*Configurar um roteador sem fio.<br />
*Testa a rede configurada através do acesso da mesma via Telefone Celular.<br />
<br />
===Fonte Base===<br />
<br />
*[https://esr.rnp.br/publicacoes/sistemas/proinfo?download=d2ddea18f00665ce8623e36bd4e3c7c5 Livro da Escola Superior de Redes (ESR): Formação de suporte técnico PROINFO]<br />
<br />
===Analisando o roteador===<br />
#Roteador ??????. Descrição Geral do aparelho: <br />
##Fonte de alimentação. Cuidar com tensão cc e polaridade.<br />
##Porta WAN (''Wide Area Network'')<br />
##Portas LAN (''Local Area Network'')<br />
##Antena ou antenas <br />
##Botão reset. Normalmente configura LAN em 192.168.0.0/24 ou 192.168.1.0/24<br />
##Parte frontal, LEDs: Power, Status, WAN, WLAN, 1...4.<br />
#Descrição dos modos de uso básicos.<br />
#Ligar o aparelho na tomada.<br />
##LED Power acendeu?<br />
<br />
====Montando uma rede básica====<br />
#Conectar o computador numa das portas LAN do roteador sem fio.<br />
#Conectar a porta WAN num dos pontos de rede do laboratório.<br />
#Pressionar o botão Reset.<br />
#Teste a rede de seu computador, caso não esteja funcionando desconecte e reconecte o cabo de rede entre seu computador e uma porta LAN do roteador sem fio.<br />
#Com o navegador acesse 192.168.0.1. '''Usuário: admin''', '''senha: em branco'''. Caso não consiga acesso, pressione novamente o botão reset.<br />
#Redefina a senha do administrador do roteador para RCO60803.<br />
#Aba Home:<br />
##Clique no menu esquerdo WAN. Discutir a funcionalidade.<br />
##Clique no menu esquerdo LAN. Discutir a funcionalidade.<br />
##Clique no menu esquerdo DHCP. Discutir a funcionalidade.<br />
##Clique no menu esquerdo Wireless. Discutir a funcionalidade.<br />
##Clique no menu esquerdo Wizard. Discutir a funcionalidade.<br />
#Aba Status:<br />
##Device Info. Discutir a funcionalidade.<br />
##Wireless. Discutir a funcionalidade.<br />
#Reconfigure o roteador sem fio para alugar os endereços 192.168.X.20-60, onde X é igual ao último dígito do número IP de sua máquina. Por exemplo, para a máquina 192.168.1.7, X=7.<br />
#Para verificar o funcionamento, num terminal da máquina (real) execute o comando abaixo. Caso tudo esteja funcionando corretamente, sua máquina configurará uma nova interface de rede com o número IP fornecido por seu roteador ou um roteador de um colega. <syntaxhighlight lang=bash> sudo dhclient eth0:0 </syntaxhighlight><br />
#Reconfigure o WiFi de seu roteador:<br />
##Troque o SSID (''Service Set IDentifier'') de seu roteador, colocando seu primeiro nome como nome de rede.<br />
##Configure a segurança para WPA2 (''Wireless Security Setup'').<br />
##Ajuste a senha para RCO60803 (respeite as maiúsculas).<br />
##Salve e reinicie o roteador para as alterações terem validade.<br />
#Teste a configuração, acessando a sua rede sem fio através de seu telefone celular.<br />
<br />
{{Collapse bottom}}<br />
<br />
==Projeto Final==<br />
{{Collapse top |Descrição do Projeto}}<br />
<br />
===Objetivos===<br />
<br />
*Aplicar os conhecimentos adquiridos durante o curso de redes através da confecção de uma rede múltiplos domínios simulando a Internet.<br />
**Dado uma topologia de rede definida a um grupo, calcular as sub-redes de acordo com os requisitos colocados;<br />
**Implementar a proposta de sub-redes no arquivo de configuração do netkit de tal modo a rede ficar plenamente operacional;<br />
**Estabelecer um roteamento global entre todos os domínios das equipes;<br />
**Estabelecer um serviço WEB sobre a rede construída;<br />
**Construir páginas WEB de acordo com os requisitos;<br />
**Estabelecer um serviço de configuração automática de hospedeiros (DHCP);<br />
<!--**Estabelecer um serviço de conexão sem fio sobre cada domínio.--><br />
**Trabalhar o conceito de ''shell script'' para automatizar tarefas.<br />
<br />
A arquitetura da rede é mostrada na Figura abaixo. <br />
<br />
[[Image:RCO3-TrabalhoFinal-2017-2.png|500px]]<br />
<br />
===Especificações do Projeto===<br />
<br />
#Fazer um desenho da '''topologia''' do domínio com todos IPs alocados e apresentar os cálculos das subredes conforme restrições abaixo. <br />
##Construir as tabelas de roteamento para que a rede fique plenamente operacional. Apresentar as '''tabelas de roteamento na página WEB do projeto''';<br />
##Apresentar o desenho da '''topologia na página WEB do projeto'''. Utilize o modelo ao lado. Observe que o modelo está propositalmente incompleto; [[Image:Modelo_de_diagrama_do_projeto.png|300px]]<br />
##Enlaces ponto-a-ponto devem obrigatoriamente ter máscara /30;<br />
##Enlaces multiponto devem obrigatoriamente comportar no mínimo 50 hospedeiros;<br />
##Todas as rotas devem ser colocadas no arquivo '''projeto.conf''' do netkit. Apresentar esse arquivo na '''página WEB do projeto''';<br />
#Na sub-rede onde existe um cliente (notebook) acrescentar um servidor '''[[Netkit2#Usando_DHCP | DHCP]]''' (máquina adicional) com os seguintes requisitos:<br />
##Com uma faixa de aluguel de pelo menos 5 números IP;<br />
##Explicar a configuração do '''DHCP na página WEB do projeto''';<br />
#Estabelecer o serviço '''Apache''' no servidor previsto no domínio com os seguintes requisitos:<br />
##uma página WEB com a descrição integral do projeto;<br />
##uma segunda página WEB com conteúdo de sua preferência com os seguintes requisitos:<br />
###a página deve ser em inglês ou espanhol;<br />
###texto com no mínimo 500 palavras; <br />
###no mínimo uma figura deve aparecer;<br />
###no mínimo um link para uma página WEB de uma outra equipe.<br />
##Todas as páginas devem devem ser mantidas em um diretório de nome ''/home/aluno/lab/shared/WEB''.<br />
##Elaborar um ''shell script'' para automação do serviço WEB. Sítio para treinamento de [http://www.compileonline.com/execute_bash_online.php shell script]. <br />
#O '''roteamento global''' deve permitir conectividade entre todas as equipes. Para evitar possíveis erros advindos de filtros do Netkit2, execute os seguintes comandos em todos os seus roteadores (copie e cole): <syntaxhighlight lang=bash><br />
echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth0/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth1/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth2/rp_filter <br />
echo 0 > /proc/sys/net/ipv4/conf/eth3/rp_filter </syntaxhighlight><br />
<br />
* Exemplo de arquivo '''projeto.conf'''.<br />
**No roteiro do '''Laboratório 16''' também é apresentado um arquivo de configuração de uma rede plenamente funcional para o Netkit, utilize-o como exemplo para entendimento das configurações requisitadas.<br />
**O arquivo deverá ser adaptado para a topologia de cada equipe.<br />
<syntaxhighlight lang=bash><br />
H1[type]=generic<br />
H2[type]=generic<br />
<br />
R1[type]=gateway<br />
R2[type]=gateway<br />
R3[type]=gateway<br />
<br />
H1[eth0]=SR2:ip=10.9.2.2/24<br />
H1[default_gateway]=10.9.2.1<br />
<br />
H2[eth0]=SR4:ip=10.9.4.2/24<br />
H2[default_gateway]=10.9.4.1<br />
<br />
R1[eth0]=uplink:bridge=eth0:ip=192.168.1.190/24<br />
R1[eth1]=SR1:ip=10.9.1.1/24<br />
R1[eth2]=SR5:ip=10.9.5.1/24<br />
R1[route]=10.9.2.0/24:gateway=10.9.1.2<br />
R1[route]=10.9.4.0/24:gateway=10.9.5.2<br />
<br />
R2[eth0]=SR1:ip=10.9.1.2/24<br />
R2[eth1]=SR2:ip=10.9.2.1/24<br />
R2[eth2]=SR3:ip=10.9.3.1/24<br />
R2[default_gateway]=10.9.1.1<br />
<br />
R3[eth0]=SR3:ip=10.9.3.2/24<br />
R3[eth1]=SR4:ip=10.9.4.1/24<br />
R3[eth2]=SR5:ip=10.9.5.2/24<br />
R3[default_gateway]=10.9.5.1<br />
</syntaxhighlight><br />
<br />
*Como trabalhar com o shell script<br />
<br />
#O shell script será executado na máquina virtual do apache, e portanto deverá ser copiado para o /home/aluno/shared/lab/config_apache.sh<br />
##Na máquina virtual do apache deve-se tornar o arquivo do script executável e em seguida executá-lo:<syntaxhighlight lang=bash><br />
chmod +x /hostlab/shared/config_apache.sh<br />
/hostlab/shared/config_apache.sh <br />
</syntaxhighlight><br />
<br />
* Exemplo de arquivo ''shell script''. Este arquivo deve ser adaptado para a topologia de cada equipe. <br />
<br />
#Editar o arquivo com gedit com nome ''config_apache.sh''. Qualquer comando executado no terminal pode ser colocado com exata sintaxe no ''shell script'', e vários comandos podem ser colocados em várias linhas.<br />
#Construir o arquivo da forma:<br />
<syntaxhighlight lang=bash><br />
#!/bin/bash<br />
#comentario: copiar um arquivo<br />
cp /home/aluno/teste.txt /var/www<br />
<br />
#renomeando o arquivo copiado teste.txt para index.html<br />
mv /var/www/teste.txt /var/www/index.html<br />
<br />
#iniciando um serviço<br />
/etc/init.d/ssh start<br />
</syntaxhighlight><br />
<br />
*Dar permissão de execução do script no Apache<br />
<br />
Copiar o script para o /home/aluno/lab/shared e apartir do Apache fazer:<br />
Dar direito de execução do script:<br />
<br />
chmod 777 /hostlab/shared/config_apache.sh<br />
<br />
*Executar o script no apache<br />
/hostlab/shared/config_apache.sh<br />
<br />
<br />
* Teste do acesso ao Servidor Apache a partir da linha de comando:<br />
<br />
Note que como todas as máquinas virtuais do netkit são em modo de comando (não tem interface gráfica) então o uso de browsers para teste<br />
do acesso a páginas html fica limitado. Entretanto, para teste rápido é possível usar o comando lynx:<br />
<br />
lynx IP_SERVIDOR_APACHE<br />
<br />
Note que o servidor deve ter conectividade IP (faça ping antes para testar);<br />
<br />
* Acesso pleno as páginas html a partir da Virtualbox<br />
<br />
Um problema que nos deparamos ao usar o netkit para acesso de páginas hospedadas em suas Máquinas Virtuais é o fato de não termos a interface gráfica. Uma interface gráfica é necessária para um browser do tipo Firefox. Uma alternativa é o uso de browser em modo texo do tipo "lynx". Para testes rápidos pode ser interessante mas para visualizarmos em plenitude a página não é a melhor solução.<br />
<br />
Para contornar este problema vamos usar uma máquina VirtualBox que estará conectada na rede do laboratório. Faremos o default gateway desta máquina apontar para o roteador de borda do domínio da equipe garantindo que a mesma conduza todo o tráfego indireto para este roteador. Para garantir que exista rota reversa vamos colocar em cada roteador do domínio uma rota default gateway para o roteador de borda. Vamos elaborar passo a passo estes procedimentos:<br />
<br />
#Iniciar na máquina real uma VirtualBox com Ubuntu e Interface Gráfica;<br />
#Abrir um terminal e verificar a rota para o default gateway usando:<syntaxhighlight lang=bash>route -n </syntaxhighlight><br />
#Adicionar uma rota para a sua rede: <syntaxhighlight lang=bash> sudo route add -net 10.X.0.0/16 gw 192.168.1.XX </syntaxhighlight> onde 192.168.1.XX é o endereço externo do roteador de borda do domínio onde está o servidor APACHE.<br />
#Para garantir a rota reversa vamos colocar rotas ''default'' também nos roteadores dos domínios (roteadores no netkit). Para tanto coloque no projeto.conf esta informação de rota para cada roteador que não está na borda: <syntaxhighlight lang=bash> Rx[route]=default:gateway=Y.Y.Y.Y <br />
ou<br />
Rx[default_gateway]=Y.Y.Y.Y<br />
</syntaxhighlight>onde Y.Y.Y.Y é uma interface do roteador de borda ligado a Rx ou, caso não esteja diretamente ligado a este, deve ser um endereço de roteador vizinho que tenha rota para o roteador de borda.<br />
{{Collapse bottom}}<br />
<br />
==Listas de Exercícios==<br />
{{Collapse top |Lista de exercícios 1 - Introdução}}<br />
<br />
#Qual é a diferença entre um hospedeiro e um sistema final? Cite os tipos de sistemas finais. Um servidor web é um sistema final?<br />
#O que caracteriza um protocolo? Dê um exemplo de um protocolo.<br />
#Por que os padrões são importantes para os protocolos?<br />
#O que é um programa cliente? O que é um programa servidor? Um programa servidor requisita e recebe serviços de um programa cliente? <br />
#Quais são os dois tipos de serviços de transporte que a Internet provê às suas aplicações? Cite algumas características de cada um desses serviços. (pg.38)<br />
#Explique o que é e quais são as vantagens de uma rede de comutação de circuitos em relação a uma rede de comutação de pacotes? <br />
#O que é uma rede de acesso?<br />
#FTTH, HFC e ADSL são usados para acesso residencial. Para cada uma dessas tecnologias de acesso, cite uma faixa de taxas de transmissão e comente se a largura de banda é compartilhada ou dedicada.<br />
#Cite tecnologias de acesso residencial disponíveis na grande Florianópolis. Para cada tipo de acesso, apresente a taxa de ''downstream'', a taxa de ''upstream'' e o preço mensal anunciados.<br />
#Qual é a taxa de transmissão de LANs Ethernet?<br />
#Porque dividimos a arquitetura da Internet (e de redes de comutação de pacotes em geral) em camadas? Por que dizemos que uma camada inferior presta um serviço a camada superior?<br />
#Quais são as cinco camadas da pilha de protocolo da Internet? Quais as principais responsabilidades de cada uma dessas camadas? <br />
#O que significa o processo de encapsulamento e desencapsulamento de pacotes no contexto da rede organizada em camadas?<br />
#O que é uma mensagem de camada de aplicação? Um segmento da camada de transporte? Um datagrama da camada de rede? Um quadro de camada de enlace? Qual a relação entre eles?<br />
#Que camadas da pilha de protocolo da Internet um roteador implementa? Que camadas um comutador de enlace implementa? Que camadas um sistema final implementa?<br />
#Imagine que você queira enviar, com urgência, 40 terabytes de dados de São José a Manaus. Você tem disponível um enlace dedicado de 100 Mbps para a transferência de dados. Você escolheria transferir os dados pelo enlace ou mandar mídias por Sedex 10? Explique.<br />
#Para pensar I: um celular tipo smartphone acessa normalmente quantas redes? Quais tecnologias sao usadas? Elas são de comutação de pacotes ou de circuitos?<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Lista de exercícios 2 - Camada de Aplicação}}<br />
#Relacione cinco aplicações da Internet não proprietárias e os protocolos da camada de aplicação que elas usam. <br />
#Qual é a diferença entre arquitetura de rede e arquitetura de aplicação? <br />
#De que modo um mensageiro instantâneo é um híbrido das arquiteturas cliente-servidor e P2P? <br />
#Para uma sessão de comunicação entre um par de processos, qual processo é o cliente e qual é o servidor? <br />
#Que informação é usada por um processo que está rodando em um hospedeiro para identificar um processo que está rodando em outro hospedeiro? <br />
#Porque o HTTP, FTP, SMTP, POP3 e IMAP rodam sobre TCP e não sobre UDP? <br />
#Por que se diz que o FTP envia informações de controle “fora da banda”? <br />
#Suponha que Aline envie uma mensagem a Eduardo por meio de uma conta de e-mail da web (como o gmail), e que Eduardo acesse seu e-mail por seu servidor utilizando POP3. Descreva como a mensagem vai do hospedeiro Aline até o hospedeiro de Eduardo. Não se esqueça de relacionar a série de protocolos de camada de aplicação usados para movimentar as mensagens entre os hospedeiros.<br />
#Em uma aplicação de compartilhamento de arquivos P2P, você concorda com a afirmação: ”não existe nenhuma noção de lados cliente e servidor de uma sessão de comunicação”? Por que sim ou por que não? <br />
#Relacione alguns agentes de usuário de aplicação de rede que você utiliza no dia-a-dia. <br />
#Considere um site de comércio eletrônico que quer manter um registro de compras para cada um de seus clientes. Descreva como isso pode ser feito com cookies. <br />
#Descreva uma aplicação que requeira “não perda de dados” e seja também altamente sensível ao atraso.<br />
#Quais informações básicas estão em um cabeçalho do pacote IP?<br />
#Um pacote IP pode ser colocado diretamente na rede física? Ele chegará a seu destino?<br />
#Os pacotes ECHO request e ECHO reply são de que protocolo? Eles trafegam dentro de qual pacote?<br />
#Para pensar II: Quando você usa o uma aplicação tipo whatsapp para conversação você está usando rede de comutação de circuitos ou de pacote?<br />
<br />
ADICIONAIS PARTE 2- HTTP<br />
<br />
#Cite pelo menos dois clientes http.<br />
#O que é o servidor Apache?<br />
#O protocolo http deve se executar em todos os roteadores do caminho entre cliente e servidor? Explique.<br />
#Se um hospedeiro colocar um pacote de aplicação HTTP diretamente na rede física ele chegará a seu destino?<br />
#Considere que um cliente acessa uma página HTML de servidor WEB e nesta página existem dois links para dois objetos JPG que residem no mesmo servidor. Quantos comandos GETS no total deveriam ser realizados pelo cliente? Todos eles serão realizados sobre a mesma conexão TCP?<br />
#Em uma página HTML pode existir um link para um objeto que esteja armazenado em outro site? O que o browser deve fazer neste caso? <br />
#No pacote http de resposta de um servidor normalmente existem duas partes. Quais são elas?<br />
#Imagine que uma página html está sendo mostrada para o usuário cliente. Se o usuário pedir para que a página seja atualizada, o browser vai requisitar o objeto novamente? O servidor vai retornar o objeto mesmo que ele não tenha sido alterado?<br />
#O que é um cookie? Considere um site de comércio eletrônico que quer manter um registro de compras para cada um de seus clientes. Descreva como isso pode ser feito com cookies.<br />
#Qual é a diferença entre HTTP persistente com ''pipelining'' e HTTP persistente sem ''pipelining''. Qual dos dois é utilizado pelo HTTP/1.1? <br />
#Descreva como o cache Web pode reduzir o atraso na recepção de um objeto desejado. O cachê Web reduzirá o atraso para todos os objetos requisitados por um usuário ou somente para alguns objetos? Por quê? <br />
#Um servidor Web, quando recebe uma requisição necessita saber para qual porta deve responder na máquina requisitante? Se positivo, esta porta seria sempre a mesma?<br />
#Por que um servidor Web espera na porta TCP número 80 em geral?<br />
#O que é um proxy Web server?<br />
#Um browser pode fazer cache local? Qual a diferença entre cache local e cache em um servidor proxy?<br />
<br />
ADICIONAIS PARTE 3- DNS<br />
#Porque o DNS não é centralizado? <br />
#O que são consultas recursivas e interativas em uma consulta DNS? <br />
#Quais os três tipos de servidores DNS?<br />
#Em um hospedeiro normalmente existe pelo menos um servidor DNS configurado. Que servidor deve estar configurado? Onde ele se localiza normalmente?<br />
#Quando um servidor local não consegue resolver um endereço IP olhando em seu cache, para quem ele deve encaminhar a consulta?<br />
#Um servidor sempre sabe resolver um nome solicitado? Explique.<br />
#É possível que um servidor DNS local seja um servidor com autoridade?<br />
#O que é um nome canônico e um apelido no contexto de DNS?<br />
#O que é e qual o formato de uma RR?<br />
#Explique os seguintes tipos de RR: A, NS, CNAME, MX e PTR.<br />
#Em um comando ping www.ifsc.edu.br quantas transações no mínimo serão realizadas até o último ECHO REPLY?<br />
#Por que um ping normalmente realiza uma consulta PTR?<br />
#Faça um esquema mostrando uma consulta de um cliente a um servidor local mostrando uma consulta interativa entre o servidor raiz e recursiva com um servidor de autoridade. <br />
#Cite o nome de servidor DNS bastante utilizado.<br />
#Quantos servidores raízes temos no mundo? Qual comando permite que possamos "ver" estes servidores em um hospedeiro?<br />
#Foi realizado um comando '''dig www.ifsc.edu.br''' tendo sido retornado: <br />
#:<br />
#: www.ifsc.edu.br. 240 IN A 200.135.190.95<br />
#:<br />
#Em seguida foi realizado um '''dig ifsc.edu.br MX''' com resposta:<br />
#:<br />
#: ;; ANSWER SECTION:<br />
#: ifsc.edu.br. 1327 IN MX 15 zimbra.ifsc.edu.br.<br />
#: <br />
#: ;; AUTHORITY SECTION:<br />
#: ifsc.edu.br. 2082 IN NS ns1.ifsc.edu.br.<br />
#: ifsc.edu.br. 2082 IN NS adns1.pop-sc.rnp.br.<br />
#: ifsc.edu.br. 2082 IN NS ns2.ifsc.edu.br.<br />
#: ifsc.edu.br. 2082 IN NS adns2.pop-sc.rnp.br.<br />
#: <br />
#: ;; ADDITIONAL SECTION:<br />
#: zimbra.ifsc.edu.br. 78 IN A 200.135.190.2<br />
#:<br />
#O que se pode concluir sobre a resolução do nome baseando-se nestas respostas?<br />
<br />
<!--RESPOSTAS <br />
<br />
#Qual é a diferença entre um hospedeiro e um sistema final? Cite os tipos de sistemas finais. Um servidor web é um sistema final?<br />
R.Segundo Kurose[1] os sistemas hospedeiros são sistemas finais, ou seja são considerados sinônimos. São os computadores do nosso dia a dia e que se encontram na periferia da rede executando aplicações que usufruem dos serviços da rede. Estas aplicações executam protocolos específicos para seu funcionamento (protocolos de aplicação).<br />
#O que caracteriza um protocolo? Dê um exemplo de um protocolo.<br />
R.Um conjunto de regras e formatos que viabilizam a comunicação entre duas ou mais entidades comunicantes. No caso de uma rede define as regras para troca de mensagens entre processos da rede (ações a serem realizadas no envio e no recebimento de mensagens), bem como o formato das mensagens trocadas. Em uma rede, as entidades comunicantes se encontram em uma mesma camada.<br />
#Por que os padrões são importantes para os protocolos?<br />
R.Para que exista compatibilidade na comunicação entre processos e equipamentos de rede, além de facilitar a implementação dos mesmos.<br />
#O que é um programa cliente? O que é um programa servidor? Um programa servidor requisita e recebe serviços de um programa cliente?<br />
R.Um programa cliente é uma parte de uma aplicação distribuída que requisita serviços de um outro programa chamado servidor. Tanto cliente como servidor se executam em sistemas finais. O servidor normalmente fica aguardando por uma requisição de algum recurso solicitado por um cliente. Ex: servidor Web e cliente Mozilla ou Chrome. <br />
#Quais são os dois tipos de serviços de transporte que a Internet provê às suas aplicações? Cite algumas características de cada um desses serviços.<br />
Os dois tipos básicos são serviços com conexão e sem conexão. Um serviço com conexão faz com que (em geral) duas entidades de aplicação que pretendem se comunicar, troquem mensagens de controle no sentido de manter informações mútuas de forma a permitir a execução de serviços adicionais do tipo: transferência confiável de dados, controle de fluxo de dados para não sobrecarregar o receptor e controle de congestionamento para evitar o congestionamento de pacotes na rede. Fluxos de pacotes podem ser direcionados a uma determinada conexão. Importante notar que os componentes intermediários da rede desconhecem as conexões. Na Internet, o protocolo que garante o serviço com conexão é o TCP.<br />
Já no serviço sem conexão as entidades comunicantes enviam pacotes (datagramas) sem nenhuma apresentação prévia (troca de mensagens de controle). Cada pacote é enviado de forma independente não tendo garantia de entrega. Na internet o protocolo associado a este comportamento é o UDP. Vale lembrar que por não ter nenhum procedimento associado, a troca de mensagens com UDP tem maior desempenho do que o TCP.<br />
#Quais são as vantagens de uma rede de comutação de circuitos em relação a uma rede de comutação de pacotes? <br />
Em uma rede de comutação de circuitos (ex: rede telefônica clássica) é estabelecido um canal dedicado para a a comunicação entre entidades comunicantes. Normalmente a alocação do canal dedicado é precedido de um processo de sinalização (discar o número, verificar se o destino está disponível, conectar). Uma canal dedicado não pode ser compartilhado por outras comunicações, mesmo quando fica ocioso (ex: duas pessoas na linha telefônica sem conversar). Já em uma rede de pacotes a informação é organizada em pacotes que podem compartilhar canais. Pacotes são comutados para seus destino por equipamentos do tipo roteadores. O roteamento é baseado em informações do cabeçalho do pacote. <br />
#Cite 5 tecnologias de acesso. Classifique cada uma delas nas categorias acesso residencial, acesso corporativo ou acesso móvel. <br />
#FTTH, HFC e ADSL são usados para acesso residencial. Para cada uma dessas tecnologias de acesso, cite uma faixa de taxas de transmissão e comente se a largura de banda é compartilhada ou dedicada.<br />
#Cite tecnologias de acesso residencial disponíveis na grande Florianópolis. Para cada tipo de acesso, apresente a taxa de ''downstream'', a taxa de ''upstream'' e o preço mensal anunciados.<br />
#Qual é a taxa de transmissão de LANs Ethernet?<br />
#Qual é a vantagem de uma rede de comutação de circuitos em relação a uma de comutação de pacotes?<br />
#Porque dividimos a arquitetura da Internet (e de redes de comutação de pacotes em geral) em camadas? Por que dizemos que uma camada inferior presta um serviço a camada superior?<br />
#Quais são as cinco camadas da pilha de protocolo da Internet? Quais as principais responsabilidades de cada uma dessas camadas? <br />
#O que significa o processo de encapsulamento e desencapsulamento de pacotes no contexto da rede organizada em camadas?<br />
#O que é uma mensagem de camada de aplicação? Um segmento da camada de transporte? Um datagrama da camada de rede? Um quadro de camada de enlace? Qual a relação entre eles?<br />
#Que camadas da pilha de protocolo da Internet um roteador implementa? Que camadas um comutador de enlace implementa? Que camadas um sistema final implementa?<br />
#A noção de portas é criada pela camada de transporte na arquitetura TCP/IP. Qual a funcionalidade que as portas permitem implementar?<br />
#Descreva todo o processo de ''download'' de um arquivo utilizando a ferramenta Bittorrent. Considere que o usuário acabou de instalar a mesma.<br />
#Imagine que você queira enviar, com urgência, 40 terabytes de dados de São José a Manaus. Você tem disponível um enlace dedicado de 100 Mbps para a transferência de dados. Você escolheria transferir os dados pelo enlace ou mandar mídias por Sedex 10? Explique.<br />
#Para pensar I: um celular tipo smartphone acessa normalmente quantas redes? Quais tecnologias sao usadas? Elas são de comutação de pacotes ou de circuitos?<br />
--><br />
{{Collapse bottom}}<br />
{{Collapse top |Lista de exercícios 3 - Camada de Transporte}}<br />
#Considere uma conexão TCP entre o hospedeiro A e o hospedeiro B. Suponha que os segmentos TCP que trafegam do hospedeiro A para o hospedeiro B tenham número de porta fonte x e número de porta destino y. Quais são os números de porta fonte e do destino para os segmentos que trafegam do hospedeiro B para o hospedeiro A? <br />
#Descreva porque um desenvolvedor de aplicação pode escolher rodar uma aplicação sobre UDP em vez de sobre TCP. <br />
#O que são os serviços de multiplexação e demultiplexação implementados pela camada de transporte? <br />
#Porque se diz que o UDP é um protocolo não orientado para conexão? <br />
#Qual o papel das informações de porta origem e destino contidas nos segmentos TCP e UDP? <br />
#Porque é dito que o TCP fornece transferência confiável de dados sobre um canal não confiável?<br />
#Cite 3 diferenças entre os serviços oferecidos pelo TCP e UDP.<br />
#Para que serve um ''checksum'' em um segmento TCP ou UDP? Como ele é formado?<br />
#Cite um motivo para um protocolo de transmissão confiável adicionar um número de seqüência em cada pacote transmitido. Justifique o uso dessa informação explicando o problema que ocorreria caso ela não fosse usada.<br />
#Para que serve um ''timeout'' em um protocolo de transmissão confiável?<br />
#O que é uma reconhecimento cumulativo? [[Arquivo:WiresharkUDP.png |thumb | 600px| Figura 1 -- Captura 1 - Wireshark]]<br />
#Baseado na Figura 1, responda as seguintes perguntas:<br />
##Quais os IP fonte e destino?<br />
##Qual o protocolo da camada de transporte utilizado?<br />
##Quais as portas fonte e destino.<br />
##Qual o conteúdo do campo de tamanho (anote o tamanho) e ''checksum'' no pacote (datagrama)?<br />
##Quantos bits possui o ''checksum''? Como você calculou?<br />
##Qual o significado do campo '''Data: 74657374650a'''? Qual é a mensagem contida? Como você chegou a essa conclusão? [[Arquivo:WiresharkTCP.png |thumb | 600px| Figura 2 -- Captura 2 - Wireshark]]<br />
#Baseado na Figura 2, responda as seguintes perguntas:<br />
##Quais os IP fonte e destino?<br />
##Qual o protocolo da camada de transporte utilizado?<br />
##Quais as portas fonte e destino.<br />
##Qual o conteúdo do campo de tamanho (anote o tamanho) no pacote (datagrama)? O tamanho apresentado significa bits ou bytes?<br />
##Qual o significado do campo '''Data: 74657374650a'''? Qual é a mensagem contida? Como você chegou a essa conclusão? [[Arquivo:WiresharkTCPPerdaDePacotes.png |thumb | 600px| Figura 3 -- Captura 3 - Wireshark]]<br />
#Baseado na Figura 3, responda as seguintes perguntas:<br />
##Quais os IP fonte e destino?<br />
##Qual o protocolo da camada de transporte utilizado?<br />
##Quais as portas fonte e destino.<br />
##Qual o número de sequência (normalizado pelo Wireshark) de cada segmento de dados transmitido, e qual o significado do número de reconhecimento em cada um deles?<br />
##Como foi reconhecido cada segmento enviado?<br />
##Qual o significado do conjunto de mensagens de número (No.) 1 à 3? Explique essas 3 mensagens.<br />
##Qual o significado do conjunto de mensagens de número (No.) 17 à 19? Explique essas 3 mensagens.<br />
##Qual o significado do conjunto de mensagens de número (No.) 6, 11 e 16? Explique essas 3 mensagens.<br />
##Qual é o tamanho "médio" de janela de cado um dos ''hosts''?<br />
##Qual a utilizade das mensagens com fundo preto?<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Lista de exercícios 4 - Camada de Rede}}<br />
#Quais são as principais características de uma rede de datagramas?<br />
#Roteadores possuem endereços IP? Quantos endereços IP um roteador possui?<br />
#Para que serve o protocolo ICMP? <br />
#Para que serve o campo “Time to Live” (sobrevida) em um datagrama IP? <br />
#Quantos hosts podem ser endereçados com um bloco IP 200.23.16.0/20? Como podemos montar 8 sub-redes a partir deste bloco de endereços IP?<br />
#Um provedor de serviços ISP possui cerca de 2000 clientes cadastrados atualmente. Porém um levantamento realizado recentemente pelo administrador da rede constatou que nunca mais do que 450 clientes estão on-line ao mesmo tempo. Qual o bloco de endereços IP na forma CIDR (a.b.c.d/x) deve ser contratado pelo ISP, considerando o estudo realizado pelo administrador da rede?<br />
#Um administrador precisa montar uma rede experimental conforme mostrada na figura. Na sub-rede 1 ele precisará instalar cerca 25 hosts, e nas sub-redes 2 e 3 ele precisará instalar cerca de 12 hosts. O administrador dispõe do bloco de endereços IP 192.168.10.0/24 para ser utilizado no endereçamento da rede experimental. Faça uma proposta para alocação de endereços IP para cada sub-rede (rede 1, 2 e 3), incluindo também as sub-redes relativas aos enlaces ponto-a-ponto (rede AB, AC e BC). Responda ainda:<br />
##Qual o endereço identificador de rede de cada sub-rede (1, 2 e 3)?<br />
##Qual o a máscara de rede de cada sub-rede (1, 2 e 3)?<br />
##Quais os endereços IP que serão atribuídos a cada interface de rede nos enlaces ponto-a-ponto dos roteadores (enlaces relativos as redes AB, AC e BC)[[Arquivo:CdrEx.png]]<br />
#Suponha que um administrador de rede tenha recebido o bloco de endereços 200.40.8.0/21 e que deseja dividir este bloco em 8 blocos de endereços iguais, de menor tamanho, para ser alocado a 8 sub-redes administradas por ele.<br />
##Determine o tamanho total do bloco de endereços.<br />
##Determine o tamanho de cada sub-bloco.<br />
##Determine o endereço/máscara de rede de cada sub-rede.<br />
#Um provedor de acesso a Internet possui o seguinte bloco de endereços IP: 12.17.192.0/18. Os endereços IP de 12.17.192.1 até 12.17.207.255 já estão alocados para clientes deste provedor. Este provedor precisa atender a quatro novos clientes, um deles necessita de rede com pelo menos 1000 endereços de IP válidos e os outros três necessitam de rede com pelo menos 30 IP válidos. Faça uma proposta para alocação de endereços IP para estes clientes. Os endereços reservados para estes novos clientes devem ser alocados a partir da numeração mais baixa disponível. Procure também responder as questões abaixo:<br />
##Qual o total de endereços que dispõe o provedor em questão?<br />
##Quantos endereços IP já estão utilizados?<br />
##Quantos endereços IP este provedor possui livres para alocar aos novos clientes?<br />
##Qual o endereço identificador de cada sub-rede dos novos clientes?<br />
##Qual o a máscara de rede de cada sub-rede dos novos clientes?<br />
##Qual o endereço de broadcast de cada sub-rede dos novos clientes?<br />
##Quantos endereços IP ainda sobrarão ao provedor após atender a estes clientes?<br />
#Quantas estações uma rede 223.1.10.0/24 suporta? <br />
#Uma rede com bloco de IPs 200.23.16.0/20 deseja montar 8 subredes. Mostre como isso é possível e como ficaria os endereços de cada uma dessas subredes.<br />
#Um datagrama enviado para uma estação da mesma rede precisa passar por um roteador?<br />
#Suponha que entre o hospedeiro de origem A e o hospedeiro de destino B os datagramas estejam limitados a 1500 bytes (incluindo cabeçalho). Admitindo um cabeçalho IP de 20 bytes, quantos datagramas seriam necessários para enviar um arquivo MP3 de 5 milhões de bytes? Explique como você obteve a resposta.<br />
#Descreva e detalhe o processo de obtenção de um endereço IP através do protocolo DHCP. [[Image:ExercicioConfEstaticaZebra.png]]<br />
#Considere a rede apresetanda na Figura, onde todas as sub-redes apresentam máscara de rede /24 (255.255.255.0), e tendo os dados do Host1 e Roteador 4 apresentados no quadro abaixo, responda: <syntaxhighlight lang=bash><br />
root@H1:~# ifconfig <br />
eth0 Link encap:Ethernet HWaddr 7a:a6:f4:ca:51:0e <br />
inet addr:200.10.1.1 Bcast:200.10.1.255 Mask:255.255.255.0<br />
<br />
root@H1:~# route -n<br />
Kernel IP routing table<br />
Destination Gateway Genmask Flags Metric Ref Use Iface<br />
0.0.0.0 200.10.1.254 0.0.0.0 UG 0 0 0 eth0<br />
200.10.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0<br />
<br />
root@R4:~# route -n<br />
Kernel IP routing table<br />
Destination Gateway Genmask Flags Metric Ref Use Iface<br />
200.10.1.0 200.10.3.1 255.255.255.0 UG 0 0 0 eth0<br />
200.10.3.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0<br />
200.10.5.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1<br />
200.10.6.0 0.0.0.0 255.255.255.0 U 0 0 0 eth2<br />
200.10.8.0 200.10.6.1 255.255.255.0 UG 0 0 0 eth2 </syntaxhighlight><br />
##Observando a tabela do hospedeiro (H1) é possível dizer quem é seu roteador default?<br />
##Se o hospedeiro (H1) tiver um pacote para entregar para o IP 200.10.1.20 ele utilizará entrega direta ou utilizará seu roteador padrão? Explique o significado da entrega direta e indireta (via roteador).<br />
##Se o hospedeiro (H1) tiver um pacote para entregar para o IP 200.10.8.1 ele utilizará entrega direta ou utilizará seu roteador padrão?<br />
##Se o roteador (R4) receber um pacote cujo IP de destino é 200.10.1.10 para qual roteador ele entregará tal pacote e por qual interface? Será uma entrega direta ou indireta?<br />
##Se o roteador (R4) receber um pacote cujo IP de destino é 200.10.6.1 para qual roteador ele entregará tal pacote e por qual interface? Será uma entrega direta ou indireta?<br />
##Se o roteador (R4) receber um pacote cujo IP de destino é 200.10.1.10, cuja carga segmento TCP com destino a porta 80, para qual roteador ele entregará tal pacote e por qual interface? Será uma entrega direta ou indireta?<br />
##Se o roteador (R4) receber um pacote cujo IP de destino é 122.10.4.7 para qual roteador ele entregará tal pacote e por qual interface? Explique.<br />
##Qual comando que você executaria no roteador (R4) para acrescentar uma rota para a rede SN2? Explique seu comando.<br />
##Considerando a pergunta anterior, a rota acrescentada garantiria que se você fizer um ping para um host da rede SN2 você obteria sucesso? Explique todas as possibilidades.<br />
##Explique o significado dos campos das colunas 1, 2, 3 e 8 da última linha da tabela do roteador (R4).<br />
{{Collapse bottom}}</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=ISL-FicLinux_(p%C3%A1gina)&diff=162009ISL-FicLinux (página)2019-10-03T19:57:51Z<p>127.0.0.1: /* AULA 12 - Dia 03/10/2019 */</p>
<hr />
<div>__NOTOC__<br />
= Introdução ao Sistema Operacional Linux / Redes com Linux =<br />
<br />
*'''Encontros:''' Terças e Quintas das 19:00 às 22:00.<br />
*'''Local:''' Laboratório de Redes de Computadores (Redes 1).<br />
<br />
*[[ISL-FicLinux_(Plano_de_Ensino)| Plano de Ensino]]<br />
<br />
==Curso FIC Linux 2019==<br />
<br />
{{collapse top | Semestre 2019-2 - Prof. Eraldo Silveira e Silva}}<br />
<br />
==Cronograma Tentativa==<br />
<br />
Horários: 19h às 22h.<br />
<br />
{| class="wikitable"|<br />
| AULA || DATA || Professor || Conteúdo<br />
|-<br />
| 1 || 27/09/2019 || ERALDO || Programa da Disciplina.Forma de Avaliação. O computador: hardware e software. SO Linux: histórico e distribuições. Ligando/Logando/Desligando a Máquina. Conceitos básico de Sistema de Arquivos e Processos.<br />
|-<br />
| 2 || 29/09/2019 || ERALDO || Gerenciamento de Arquivos I: Operações sobre arquivos e diretórios usando o terminale o Nautilus.<br />
|-<br />
| 3 || 3/09/2019 || ERALDO || Gerenciamento de Arquivos II: continuação Operações sobre arquivos e diretórios. Links Simbólicos, Criação de Arquivo com vi e outros editores.<br />
|-<br />
| 4 || 5/09/2019 || ERALDO || Interfaces Gráficas: X11, Gnome. KDE e outras. Instalação de Programas via Gerenciador de Pacotes.<br />
|-<br />
| 5 || 10/09/2019 || ERALDO || Administração de contas de usuários I<br />
|-<br />
| 6 || 12/09/2019 || ERALDO || Administração de contas de usuários II<br />
|-<br />
| 7 || 17/09/2019 || ERALDO || Permissionamento de Arquivos<br />
|-<br />
| 8 || 19/09/2019 || ERALDO || Gerenciamento de Processos<br />
|-<br />
| 9 || 24/09/2019 || ERALDO || Introdução ao Shell Script<br />
|-<br />
| 10 || 26/09/2019 || ERALDO || Introdução ao Shell Script<br />
|-<br />
| 11 || 1/10/2019 || ERALDO || Introdução a Redes. Conceito de Protocolos. Ferramentas de Rede no Linux.<br />
|-<br />
| 12 || 3/10/2019 || ERALDO || Conceito de Protocolos. Protocolos de Aplicação: exemplo http. Protocolo DNS<br />
|-<br />
| 13 || 8/10/2019 || ERALDO || Camada de Transporte: protocolo UDP. Protocolo TCP. Diferenças dos protocolos de Transporte TCP/UDP. <br />
|-<br />
| 14 || 10/10/2019 || ERALDO || Camada IP e aspectos da configuração da mesma sob o Linux<br />
|-<br />
| 15 || 15/10/2019 || ERALDO || Camada de Enlace/Física. Hubs X Switches. O Papel do Protocolo ARP. Outros serviços/protocolos: Serviço DHCP e NAT<br />
|-<br />
| 16 || 17/10/2019 || ERALDO|| Segmentação Redes IP. Cálculo de subredes. <br />
|-<br />
| 17 || 22/10/2019 || ERALDO || Introdução ao IPV6. Introdução ao Access Point TPLINK N750: configuração da LAN e WAN<br />
|-<br />
| 18 || 24/10/2019 || ERALDO || Serviço SSH no Linux. Acesso a rede WIFI. Conceitos básicos de redes sem fio.<br />
|-<br />
| 19 || 29/10/2009 || ERALDO || Tópicos Adicionais sobre redes no Linux: Configuração Manual X NetworkManager. Relatório Avaliativo 1.<br />
|-<br />
| 20 || 31/10/2019 || ERALDO || Relatório Avaliativo 2<br />
|}<br />
<br />
=Curso FIC Linux 2019-2=<br />
<br />
==Professor==<br />
<br />
:*Prof. [[Eraldo Silveira e Silva]]<br />
:*email: eraldo@ifsc.edu.br<br />
:*sala: Sala de I de Professores da Área de Telecomunicações (primeira sala lado da Biblioteca - direção esquerda)<br />
<br />
=27/08/2019=<br />
<br />
==Objetivos==<br />
<br />
===Parte 1===<br />
<br />
*Apresentar o IFSC: estrutura, câmpus e serviços<br />
*Apresentar o curso: perfil do egresso, competências gerais, áreas de atuação do egresso e conteúdos previstos<br />
*Apresentar o Cronograma Tentativa (ver SIGA A)<br />
*Apresentar metodologia e forma de avaliação<br />
<br />
===Parte 2===<br />
<br />
*Conceitos de Hardware, Software e Firmware<br />
*Arquiteturas de processadores<br />
*Classificação de softwares<br />
*Conceitos de Sistemas Operacionais e exemplos<br />
<br />
===Parte 3===<br />
<br />
*Histórico do Linux<br />
*Linux e GNU/Linux<br />
*Instalando o Linux<br />
*Arquitetura do Linux<br />
*Distribuições<br />
*Distribuições usadas no IFSC/SJ<br />
*Ligando e Desligando o Sistema<br />
*Primeiros contatos.<br />
<br />
==Professores do FIC Linux Edição 2019-2==<br />
<br />
*Prof. [[Eraldo Silveira e Silva]] (Introdução ao Linux e Redes com Linux)<br />
<br />
==Apresentação do IFSC==<br />
<br />
*[http://www.ifsc.edu.br/estrutura-organizacional-inicio Página do IFSC]<br />
*[https://www.sj.ifsc.edu.br/index.php Página do Câmpus]<br />
<br />
==Apresentação do Curso==<br />
<br />
*[[ISL-FicLinux_(Plano_de_Ensino) | Introdução ao Linux]]<br />
*[https://wiki.sj.ifsc.edu.br/index.php/PRL-FicLinux_(Plano_de_Ensino) Projeto de Rede Residencial com o Linux]<br />
*[[Curso_de_Formação_Continuada_de_Configuração_de_Redes_de_Computadores_Linux | PPC do Curso e Outras Regulamentações]]<br />
<br />
==Cronograma Tentativa==<br />
<br />
Horários: 19h às 22h.<br />
<br />
VER SIGA A [https://sig.ifsc.edu.br/sigaa/verTelaLogin.do]<br />
<br />
==Metodologia, Avaliação e Critérios de Aprovação==<br />
<br />
*Aulas expositivas e aulas práticas no laboratório. Nas aulas práticas serão desenvolvidos exercícios e trabalhos individuais.<br />
*Avaliações individuais: Listas de exercícios com aproveitamento e entregues no prazo. <br />
*Critérios para aprovação: Serão considerados aprovados os alunos que obtiverem conceito final 6 ou superior em cada componente curricular. ATENÇÃO: Possuir no mínimo 75% de presença<br />
<br />
==Bibliografia==<br />
<br />
#Odilson Tadeu Valle<br />
##Administração de redes com Linux: fundamentos e práticas<br />
##Editora IFSC, 2010<br />
#Gleydson Mazioli da Silva<br />
##Guia Foca Linux<br />
##http://www.guiafoca.org/<br />
#Luiz Carlos Lobato Lobo de Medeiros e Wendel Soares<br />
##Formação de suporte técnico PROINFO<br />
##https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo<br />
#Ari Frazão Jr e Marcelo Braga<br />
##Administração de Sistemas Linux<br />
##https://pt.scribd.com/doc/128912228/Administracao-de-Sistemas-Linux<br />
<br />
==Conceitos de Hardware, Software e Firmware==<br />
<br />
*Em informática, o hardware consiste nos equipamentos<br />
**Ex: Computador, teclado, mouse, monitor<br />
*Software é um aplicativo, desenvolvido em uma linguagem de programação<br />
**Ex: Windows, Linux, Mozilla Firefox, Google Chrome<br />
*Firmware é um conjunto de instruções básicas e específicas para um hardware<br />
**Ex: BIOS nos computadores, sistemas de controle das máquinas de lavar, etc.<br />
<br />
==Estrutura de um Computador e Arquitetura de Processadores==<br />
<br />
*Material de Referência: https://www.dropbox.com/s/fn3l9os4l7gh9o5/AULA%201.odp?dl=0<br />
<br />
===Outros Links Interessantes===<br />
<br />
*Bits, [https://pt.wikipedia.org/wiki/Byte Bytes] e tamanho de memória;<br />
*Representação de Caracteres: [https://pt.wikipedia.org/wiki/ASCII Tabela ASCII];<br />
*O [https://pt.wikipedia.org/wiki/Microprocessador microprocessador], barramentos e memórias semicondutoras: RAM,ROM, E2PROM, FLASH;<br />
*Memórias cache e memórias secundárias;<br />
*[https://pt.wikipedia.org/wiki/Mem%C3%B3ria_virtual Memória Virtual] e Swapping;<br />
*Registradores de 32bits ou 64bits<br />
*Arquitetura [https://pt.wikipedia.org/wiki/X86 x86] / [https://pt.wikipedia.org/wiki/AMD64 x86-64] – presente nos computadores pessoais<br />
*Arquitetura ARM – presente em sistemas embarcados e dispositivos móveis<br />
*Múltiplos núcleos (core)<br />
*Máquinas Virtuas: VirtualBox, UML (User Mode Linux).<br />
<br />
==O papel do Sistema Operacional==<br />
<br />
*O [https://pt.wikipedia.org/wiki/Sistema_operativo SO] é um programa (software) que controla a máquina e a torna utilizável para o usuário;<br />
*Abstrações do Sistema: arquivos e processos;<br />
*Pode ser multitarefa e multiusuário;<br />
*[https://en.wikipedia.org/wiki/Device_driver Driver] de dispositivo<br />
*[https://pt.wikipedia.org/wiki/Multi_boot Múltiplos OS instalados] em um computador. É possível??<br />
<br />
==Sistema de Arquivos==<br />
<br />
*Forma como estão estruturados/organizados os arquivos/dados em uma determinada mídia [https://pt.wikipedia.org/wiki/Sistema_de_ficheiros];<br />
*Um sistema operacional deve saber como acessar e operar sobre este sistema;<br />
*Tipos de sistemas: ext4, NTFS, VFAT32<br />
<br />
==Exemplos de SO==<br />
<br />
*Unix<br />
*Microsoft DOS<br />
*IBM<br />
*Microsoft Windows<br />
*netBSD, freeBSD, openBSD<br />
*Linux<br />
*macOS<br />
*Android<br />
*iOS<br />
<br />
==Histórico do Linux==<br />
<br />
*O início de tudo: UNIX;<br />
*Surgiu em 1991 quando Linus Torvalds, um estudante finlandês, resolveu desenvolver um sistema operacional compatível com a POSIX, por em que pudesse ser executado em arquitetura x86;<br />
*Linux está sob uma licença de software livre e diversas pessoas e empresas contribuem para o desenvolvimento do mesmo.<br />
*E o que é [https://pt.wikipedia.org/wiki/POSIX POSIX]? Define padrões para a interface de programação de aplicações (API) de um OS de forma a manter compatibilidade com o UNIX;<br />
<br />
==Arquitetura do Linux==<br />
<br />
===Material de Referência===<br />
<br />
*[https://www.dropbox.com/s/zvpo7zw19ns7rmk/AULA%202.odp?dl=0 Slides Introdução ao SO Linux]<br />
*Ver pg.16 a 19 de [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo]<br />
<br />
==Distribuições==<br />
<br />
Uma distribuição Linux consiste de um kernel Linux e uma coleção de software utilitários e aplicativos de usuário (baseado slides Prof. Emerson)<br />
**Redhat<br />
**Slackware<br />
**Debian<br />
**Ubuntu<br />
**OpenSuse<br />
**Fedora<br />
**CentOS<br />
**Kali<br />
<br />
<br />
Algumas distribuições podem ser executadas diretamente no CD/pendrive<br />
sem a necessidade de fazer sua instalação no disco rígido do computador<br />
<br />
==Distribuições aqui no IFSC SJ==<br />
<br />
*Ubuntu<br />
*Ubuntu Mate (fork do Ubuntu)<br />
*Debian<br />
<br />
==Instalando o Linux==<br />
<br />
*Fazer Download do arquivo ISO em [http://mirror.pop-sc.rnp.br/mirror/ubuntu-releases/18.04/] versão Ubuntu 18.04.3 LTS;<br />
*Instalar a VirtualBox (já está instalada no nosso Lab). Baixar de [https://www.virtualbox.org/wiki/Downloads] e selecionar para a máquina hospedeira alvo;<br />
*Seguir o procedimento colocado pelo professor.<br />
<br />
*[Ver https://www.dropbox.com/s/4xfdhqq8lruvq8m/LinuxSobreVM.odp?dl=0 Slides de Instalação]<br />
<br />
==Ligando e Desligando o Sistema Linux==<br />
<br />
*Cuidado ao desligar um OS como o Linux!!! Dados podem ser perdidos.<br />
*Ver [https://pt.wikibooks.org/wiki/Guia_do_Linux/Iniciante%2BIntermedi%C3%A1rio/Introdu%C3%A7%C3%A3o/Ligando_o_computador]<br />
<br />
==O Desktop do Ubuntu - Primeiras Considerações==<br />
<br />
*O Desktop no Ubuntu ver[https://help.ubuntu.com/stable/ubuntu-help/shell-overview.html]<br />
<br />
=AULA 2 - Dia 29/08/2019=<br />
<br />
==Objetivos==<br />
<br />
===PARTE 1===<br />
<br />
*Revisão da aula passada;<br />
*repassar itens não mencionados na aula passada;<br />
**Paginação e Memória [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo pg.19]<br />
**Estrutura do Linux [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo pg.18]<br />
<br />
===PARTE 2===<br />
<br />
*Operações com arquivos e diretórios usando o terminal;<br />
*formato de um comando básico;<br />
*quase tudo no Linux é arquivo: tipos de arquivos, diretórios, arquivos ordinários;<br />
*conceito de sistema de arquivos;<br />
*conceito de referência absoluta e relativa;<br />
*conceito de diretório de entrada, diretório de trabalho;<br />
*mudando de diretório com cd;<br />
*listando diretórios e arquivos com ls;<br />
*vendo o significado de um comando com man;<br />
*criando diretórios com mkdir;<br />
*removendo diretórios e arquivos com rmdir e rm;<br />
*referência com . .. - ~<br />
*criando arquivos ordinários com touch;<br />
*arquivos e diretórios escondidos;<br />
*copiando arquivos;<br />
*movendo e renomeando arquivos;<br />
*vendo a história de comandos com history;<br />
<br />
===Slides===<br />
<br />
*[https://www.dropbox.com/s/wtc479wmrtle9m4/SistemaDeArquivos.odp?dl=0 Slides Sistema de Arquivos]<br />
<br />
==Conceito de sistemas de arquivos, arquivos e diretórios==<br />
<br />
* [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Sistemas de Arquivos pg.18]<br />
* [Estrutura básica de diretórios do Sistema Linux]<br />
<br />
==Comandos no Linux==<br />
<br />
* [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Comandos e Interpretador de Comandos no Linux pg.18]<br />
<br />
==Tipos de Arquivos==<br />
<br />
* [https://pt.scribd.com/doc/128912228/Administracao-de-Sistemas-Linux Tipos de Arquivos 12,13 e 14 ]<br />
<br />
==Os comandos de operação sobre arquivos e diretórios==<br />
<br />
*[https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Interpretador de comandos - Comandos Básicos - pg.20 e 21]<br />
*[https://www.dropbox.com/s/mv6qpa8bqimiwzg/Aula1_Linux%282%29.pdf Ver lista de exercícios da Aula 2]<br />
<!-- *[https://www.dropbox.com/s/g3xr3wimffde2zm/Aula2_Linux_OperacoesComArquivos_2.pdf Ver lista de exercícios da Aula 3] --><br />
<br />
=AULA 3 - Dia 03/09/2019=<br />
<br />
<br />
===Mirros do Ubuntu Download e Outros===<br />
<br />
<br />
*[http://mirror.pop-sc.rnp.br/mirror/ubuntu-releases/18.04.3/ Ununtu 18.04.3 Mirror Brazil]<br />
<br />
*[https://linuxmint.com/edition.php?id=267 Linux Mint]<br />
<br />
*[https://software.opensuse.org/distributions/leap Opensuse]<br />
<br />
*[https://elementary.io/ Elementary Os]<br />
<br />
*[https://lubuntu.net/ Lubuntu]<br />
<br />
*[https://www.debian.org/CD/live/ Debian]<br />
<br />
*[https://kubuntu.org/getkubuntu/ Kubuntu]<br />
<br />
*[https://peppermintos.com/ Peppermint]<br />
<br />
*[https://www.linuxliteos.com/ Linux Lite]<br />
<br />
*[https://www.lxle.net/download/ LXLE para PCs Antigos...]<br />
<br />
*[https://www.bodhilinux.com/ Bodhi Linux]<br />
<br />
===Como verificar se o arquivo está correto?===<br />
<br />
*[https://help.ubuntu.com/community/HowToMD5SUM HowToMD5SUM] <br />
<br />
===Instalar e Preparar 3 transparências no Oppenoffice===<br />
<br />
*Nome da Equipe e da Distribuição - colar a desktop no slide<br />
*O que tem de interessante nesta distro<br />
*Requisitos da Distribuição<br />
<br />
*Gerar pdf e Enviar para o Siga a<br />
<br />
=AULA 4 - Dia 03/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Ainda operações com arquivos;<br />
*Uso de Coringas<br />
*Editor de texto sobre Ubuntu<br />
*Redirecionamento de Entradas e Saídas<br />
*Aspectos da Interface Gnome no Ubuntu 18.04<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/zti7nn0xq25x8ne/Aula2_Linux_OperacoesComArquivos_2.pdf Ainda Operações com Arquivos]<br />
*[https://www.dropbox.com/s/af3jolkvrb24g8c/Aula3_Linux_LinksSimb_licos_gedit_cat.pdf Edição de Texto]<br />
*[https://www.dropbox.com/s/vihh5r9186d40uj/Aula3_Linux_Parte4_RedirecionamentoEntradasSaidas.pdf Redirecionamento de Entradas e Saídas]<br />
<br />
=AULA 5 - Dia 10/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Gerenciamento de Processos - Parte 1<br />
*Permissionamento de Arquivos - Parte 1<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/4i1n2wqsds18eol/Aula5_Linux_GerenciamentoDeProcessos_Parte1.pdf?dl=0 Gerenciamento de Processos - Parte 1]<br />
*[https://www.dropbox.com/s/3z61r8r0b9wpftr/Aula4_Linux_PermissionamentoDeAcesso_Parte1.pdf Permissionamento de Arquivos - Parte 1]<br />
<br />
=AULA 6 - Dia 12/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Aval1<br />
<br />
==Comand wget==<br />
<br />
Para fazer o downloiad do Linux Ubuntu via linha de comando:<br />
<br />
wget http://mirror.pop-sc.rnp.br/mirror/ubuntu-releases/18.04.3/ubuntu-18.04.3-desktop-amd64.iso<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/fdl5kzq0ba2nv3v/Aula4_Linux_PermissionamentoDeAcesso_Parte2.pdf Permissionamento Parte 2 ]<br />
<br />
=AULA 7 - Dia 12/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Instalação do Ubuntu em partições separadas<br />
*Permissionamento de Grupos e Outros<br />
*Criação de Contas de Usuários<br />
*Camandos adicionais para gerenciamento de processos<br />
<br />
==Instalação==<br />
<br />
Considere a estrutura de sistemas de arquivos abaixo. Montar um sistema de arquivos da forma abaixo considerando que sb1 seria um segundo hd máquina virtual.<br />
<br />
[[arquivo:SOP2019-1-ExemploMontagemSistema.png]]<br />
<br />
Logar no sistema e usando o terminal verificar as configurações estabelecidas.<br />
<br />
df -h<br />
cd /home<br />
ls spock<br />
<br />
Usar o comando gparted para criar uma partição adicional no segundo disco.<br />
<br />
sudo apt-get install gparted<br />
sudo gparted<br />
<br />
Redimensionar a partição original para poder criar uma adicional.<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/fdl5kzq0ba2nv3v/Aula4_Linux_PermissionamentoDeAcesso_Parte2.pdf Permissionamento Parte 2 ]<br />
<br />
*[https://www.dropbox.com/s/ozjd3qz0yblcj43/Aula6_Comandos_Adicionais_de_Gerenciamento_de_Processos.pdf Gerenciamento de Processos Parte 2]<br />
<br />
=AULA 8 - Dia 12/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Permissionamento de Grupos e Outros<br />
*Criação de Contas de Usuários<br />
*Reparticionamento de Disco após instalação. Montagem de sistemas com mount.<br />
<br />
==Desafio Final==<br />
<br />
Na máquina instalada na aula anterior fazer as seguintes operações:<br />
<br />
*Reparticionar o disco 2 (/dev/sdb) em 2 partições de 5G (usar o comando gparted) (redimensionar a partição do spock)<br />
*Criar uma conta para o usuário uhura<br />
*Criar dois subdiretórios no diretório home de uhura. Estes diretórios serão pontos de montagem dos dois sistemas de arquivos criados no segundo disco.<br />
*Montar os sistemas de arquivos usando o comando mounthttps://wiki.sj.ifsc.edu.br/index.php/ISL-FicLinux_(Plano_de_Ensino)<br />
*Mudar o dono destes diretórios (usuário e grupo) )para o novo dono (uhura)<br />
*Verificar o sistema montado (comando df)<br />
*Testar o acesso entrando como <br />
<br />
==Continuando o o permissionamento de Grupos e Outros==<br />
<br />
Ver material de referência<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/fdl5kzq0ba2nv3v/Aula4_Linux_PermissionamentoDeAcesso_Parte2.pdf Permissionamento Parte 2 ]<br />
*[https://www.dropbox.com/s/ozjd3qz0yblcj43/Aula6_Comandos_Adicionais_de_Gerenciamento_de_Processos.pdf Gerenciamento de Processos Parte 2]<br />
<br />
=AULA 9 - Dia 24/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*ainda criação de usuários<br />
*ainda gerenciamento de processos: crontab<br />
*compactação e backups em linha de comando<br />
<br />
<br />
==Material de Referência==<br />
<br />
<br />
*[Ainda Gerenciamento de Usuários https://www.dropbox.com/s/8vsg0yeforcsuq9/Aula7_GerenciamentoDeUsuarios_Parte1.pdf?dl=0]<br />
*[https://www.dropbox.com/s/ozjd3qz0yblcj43/Aula6_Comandos_Adicionais_de_Gerenciamento_de_Processos.pdf Gerenciamento de Processos Parte 2]<br />
*[https://www.dropbox.com/s/61n9is9c8o7bgbz/Aula3_Linux_Parte3_vi.pdf?dl=0 Introdução ao VI]<br />
<br />
=AULA 10 - Dia 26/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Finalização da aula anterior: arquivo sudoers<br />
*Introdução ao shell script<br />
*Um pouco sobre instalação de pacotes<br />
*exercicício avaliativo 2<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/54tnv5rjwguzppd/Aula8_ShellScript_Parte1.pdf?dl=0 Introdução ao Shell script]<br />
*[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula9-pacotes.pdf Instalação de Pacotes (Prof.Luciano Barreto)]<br />
<br />
=AULA 11 - Dia 1/10/2019=<br />
<br />
Introdução a Redes de Computadores<br />
**Conceito Básicos em Redes e Protocolos<br />
**Ferramentas de Redes<br />
**Exemplo de Protocolo de Aplicação: http<br />
**O processo de encapsulamento<br />
<br />
==Plano de Ensino==<br />
<br />
*[https://wiki.sj.ifsc.edu.br/index.php/PRL-FicLinux_(Plano_de_Ensino) Plano de Ensino]<br />
<br />
<br />
==Laboratório 1 - Ferramentas de Rede e Conceitos Básicos==<br />
<br />
*Familiarização com a infraestrutura dos laboratórios de redes<br />
*Familiarização com ferramentas de rede: ifconfig, ping, traceroute;<br />
*Desenvolver a noção de endereçamentos de rede IP e de endereço de hardware (MAC)<br />
*Desenvolver a noção de rotas em redes IP<br />
*Testar a conectividade IP com ping<br />
<br />
*Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)]<br />
<br />
==Laboratório 2 - Wireshark e encapsulamento==<br />
<br />
*Familiarização com o sniffer de rede WireShark<br />
*Observar o comportamento do ping e se familiarizar com o processo de encapsulamento;<br />
<br />
**Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)]<br />
<br />
==Conceituando Protocolos e Aplicações de Rede==<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/Conceituando%20protocolos.pdf Conceituando protocolos]<br />
<br />
<br />
=AULA 12 - Dia 03/10/2019=<br />
<br />
==Objetivos==<br />
<br />
*Conceituando protocolos<br />
*Protocolos de aplicação: exemplo http<br />
<br />
==Laboratório 3 - Conceituando protocolo==<br />
<br />
Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)#Laborat.C3.B3rios]<br />
<br />
==Laboratório 4 - Desvendando o HTTP com Wireshark - BÁSICO==<br />
<br />
Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)#Laborat.C3.B3rios]<br />
<br />
==Laboratório 7 - O DNS ==<br />
<br />
Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)#Laborat.C3.B3rios]<br />
<br />
{{collapse bottom}}<br />
<br />
<br />
<br />
{{collapse top | Semestre 2019-1 - Prof. Tiago Semprebom e Eraldo Silveira e Silva}}<br />
<br />
=Professor=<br />
<br />
:*Prof. [[Tiago Semprebom]]<br />
:*email: tisemp@ifsc.edu.br<br />
:*sala: Sala de II de Professores da Área de Telecomunicações (primeira sala lado da Biblioteca - direção esquerda)<br />
<br />
=12/03/2019=<br />
<br />
==Objetivos==<br />
<br />
===Parte 1===<br />
*Apresentar os professores e o coordenador;<br />
*Apresentar o IFSC: estrutura, câmpus e serviços<br />
*Apresentar o curso: perfil do egresso, competências gerais, áreas de atuação do egresso e conteúdos previstos<br />
*Apresentar o Cronograma Tentativa<br />
*Apresentar metodologia e forma de avaliação<br />
<br />
===Parte 2===<br />
<br />
*Conceitos de Hardware, Software e Firmware<br />
*Arquiteturas de processadores<br />
*Classificação de softwares<br />
*Conceitos de Sistemas Operacionais e exemplos<br />
<br />
===Parte 3===<br />
<br />
*Histórico do Linux<br />
*Linux e GNU/Linux<br />
*Arquitetura do Linux<br />
*Distribuições<br />
*Distribuições usadas no IFSC/SJ<br />
*Ligando e Desligando o Sistema<br />
*Primeiros contatos.<br />
<br />
==Professores do FIC Linux Edição 2019-1==<br />
*Prof. [[Tiago Semprebom]] (Introdução ao Linux)<br />
*Prof. [[Eraldo Silveira e Silva]] (Redes com Linux)<br />
<br />
==Apresentação do IFSC==<br />
<br />
*[http://www.ifsc.edu.br/estrutura-organizacional-inicio Página do IFSC]<br />
*[https://www.sj.ifsc.edu.br/index.php Página do Câmpus]<br />
<br />
==Apresentação do Curso==<br />
<br />
*[[ISL-FicLinux_(Plano_de_Ensino) | Introdução ao Linux]]<br />
*[[PRL-FicLinux (página) | Projeto de Rede Residencial com o Linux]]<br />
*[[Curso_de_Formação_Continuada_de_Configuração_de_Redes_de_Computadores_Linux | PPC do Curso e Outras Regulamentações]]<br />
<br />
==Cronograma Tentativa==<br />
<br />
Horários: 19h às 22h.<br />
<br />
{| class="wikitable"|<br />
| AULA || DATA || Professor || Conteúdo<br />
|-<br />
| 1 || 12/03/2019 || TIAGO || Programa da Disciplina.Forma de Avaliação. O computador: hardware e software. SO Linux: histórico e distribuições. Ligando/Logando/Desligando a Máquina. Conceitos básico de Sistema de Arquivos e Processos.<br />
|-<br />
| 2 || 14/03/2019 || TIAGO || Gerenciamento de Arquivos I: Operações sobre arquivos e diretórios usando o terminale o Nautilus.<br />
|-<br />
| 3 || 21/03/2019 || TIAGO || Gerenciamento de Arquivos II: continuação Operações sobre arquivos e diretórios. Links Simbólicos, Criação de Arquivo com vi e outros editores.<br />
|-<br />
| 4 || 26/03/2019 || TIAGO || Interfaces Gráficas: X11, Gnome. KDE e outras. Instalação de Programas via Gerenciador de Pacotes.<br />
|-<br />
| 5 || 28/03/2019 || TIAGO || Administração de contas de usuários I<br />
|-<br />
| 6 || 02/04/2019 || TIAGO || Administração de contas de usuários II<br />
|-<br />
| 7 || 04/04/2019 || TIAGO || Permissionamento de Arquivos<br />
|-<br />
| 8 || 09/04/2019 || TIAGO || Gerenciamento de Processos<br />
|-<br />
| 9 || 11/04/2019 || TIAGO || Introdução ao Shell Script<br />
|-<br />
| 10 || 16/04/2019 || TIAGO || Avaliação 1 - Introdução ao Sistema Operacional Linux<br />
|-<br />
| 11 || 09/10/2019 || ERALDO || Introdução a Redes. Conceito de Protocolos. Ferramentas de Rede.<br />
|-<br />
| 12 || 11/10/2019 || ERALDO || Protocolos de Aplicação: exemplo http <br />
|-<br />
| 13 || 16/10/2019 || ERALDO || O DNS como protocolo de Aplicação; Camada de Transporte: protocolo UDP <br />
|-<br />
| 14 || 18/10/2019 || ERALDO || Protocolo TCP. Diferenças dos protocolos de Transporte TCP/UDP. Camada IP e aspectos da configuração da mesma sob o Linux<br />
|-<br />
| 15 || 23/10/2017 || ERALDO || Camada de Enlace/Física. Hubs X Switches. O Papel do Protocolo ARP. Outros serviços/protocolos: Serviço DHCP e NAT<br />
|-<br />
| 16 || 25/10/2017 || ERALDO (TIAGO) || Segmentação Redes IP. Cálculo de subredes. <br />
|-<br />
| 17 || 30/10/2017 || ERALDO || Introdução ao IPV6. Introdução ao Access Point TPLINK N750: configuração da LAN e WAN<br />
|-<br />
| 18 || 01/11/2017 || ERALDO || Serviço SSH no Linux. Acesso a rede WIFI. Conceitos básicos de redes sem fio.<br />
|-<br />
| 19 || 06/11/2007 || ERALDO || Tópicos Adicionais sobre redes no Linux: Configuração Manual X NetworkManager. Relatório Avaliativo 1.<br />
|-<br />
| 20 || 08/11/2017 || ERALDO || Relatório Avaliativo 2<br />
|}<br />
<br />
==Metodologia, Avaliação e Critérios de Aprovação==<br />
<br />
*Aaulas expositivas e aulas práticas no laboratório. Nas aulas práticas serão desenvolvidos exercícios e trabalhos individuais.<br />
*Avaliações individuais: Listas de exercícios com aproveitamento e entregues no prazo. <br />
*Critérios para aprovação: Serão considerados aprovados os alunos que obtiverem conceito final 6 ou superior em cada componente curricular. ATENÇÂO: Possuir no mínimo 75% de presença<br />
<br />
==Bibliografia==<br />
<br />
#Odilson Tadeu Valle<br />
##Administração de redes com Linux: fundamentos e práticas<br />
##Editora IFSC, 2010<br />
#Gleydson Mazioli da Silva<br />
##Guia Foca Linux<br />
##http://www.guiafoca.org/<br />
#Luiz Carlos Lobato Lobo de Medeiros e Wendel Soares<br />
##Formação de suporte técnico PROINFO<br />
##https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo<br />
#Ari Frazão Jr e Marcelo Braga<br />
##Administração de Sistemas Linux<br />
##https://pt.scribd.com/doc/128912228/Administracao-de-Sistemas-Linux<br />
<br />
==Conceitos de Hardware, Software e Firmware==<br />
<br />
*Em informática, o hardware consiste nos equipamentos<br />
**Ex: Computador, teclado, mouse, monitor<br />
*Software é um aplicativo, desenvolvido em uma linguagem de programação<br />
**Ex: Windows, Linux, Mozilla Firefox, Google Chrome<br />
*Firmware é um conjunto de instruções básicas e específicas para um hardware<br />
**Ex: BIOS nos computadores, sistemas de controle das máquinas de lavar, etc.<br />
<br />
==Estrutura de um Computador e Arquitetura de Processadores==<br />
<br />
*Bits, [https://pt.wikipedia.org/wiki/Byte Bytes] e tamanho de memória;<br />
*Representação de Caracteres: [https://pt.wikipedia.org/wiki/ASCII Tabela ASCII];<br />
*O [https://pt.wikipedia.org/wiki/Microprocessador microprocessador], barramentos e memórias semicondutoras: RAM,ROM, E2PROM, FLASH;<br />
*Memórias cache e memórias secundárias;<br />
*[https://pt.wikipedia.org/wiki/Mem%C3%B3ria_virtual Memória Virtual] e Swapping;<br />
*Registradores de 32bits ou 64bits<br />
*Arquitetura [https://pt.wikipedia.org/wiki/X86 x86] / [https://pt.wikipedia.org/wiki/AMD64 x86-64] – presente nos computadores pessoais<br />
*Arquitetura ARM – presente em sistemas embarcados e dispositivos móveis<br />
*Múltiplos núcleos (core)<br />
*Máquinas Virtuas: VirtualBox, UML (User Mode Linux).<br />
<br />
==O papel do Sistema Operacional==<br />
<br />
*O [https://pt.wikipedia.org/wiki/Sistema_operativo SO] é um programa (software) que controla a máquina e a torna utilizável para o usuário;<br />
*Abstrações do Sistema: arquivos e processos;<br />
*Pode ser multitarefa e multiusuário;<br />
*[https://en.wikipedia.org/wiki/Device_driver Driver] de dispositivo<br />
*[https://pt.wikipedia.org/wiki/Multi_boot Múltiplos OS instalados] em um computador. É possível??<br />
<br />
==Sistema de Arquivos==<br />
<br />
*Forma como estão estruturados/organizados os arquivos/dados em uma determinada mídia [https://pt.wikipedia.org/wiki/Sistema_de_ficheiros];<br />
*Um sistema operacional deve saber como acessar e operar sobre este sistema;<br />
*Tipos de sistemas: ext4, NTFS, VFAT32<br />
<br />
==Exemplos de SO==<br />
<br />
*Unix<br />
*Microsoft DOS<br />
*IBM<br />
*Microsoft Windows<br />
*netBSD, freeBSD, openBSD<br />
*Linux<br />
*macOS<br />
*Android<br />
*iOS<br />
<br />
==Histórico do Linux==<br />
<br />
*O início de tudo: UNIX;<br />
*Surgiu em 1991 quando Linus Torvalds, um estudante finlandês, resolveu desenvolver um sistema operacional compatível com a POSIX, por em que pudesse ser executado em arquitetura x86;<br />
*Linux está sob uma licença de software livre e diversas pessoas e empresas contribuem para o desenvolvimento do mesmo.<br />
*E o que é [https://pt.wikipedia.org/wiki/POSIX POSIX]? Define padrões para a interface de programação de aplicações (API) de um OS de forma a manter compatibilidade com o UNIX;<br />
<br />
==Arquitetura do Linux==<br />
<br />
*Ver pg.16 a 19 de [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo]<br />
<br />
==Distribuições==<br />
<br />
Uma distribuição Linux consiste de um kernel Linux e uma coleção de software utilitários e aplicativos de usuário (baseado slides Prof. Emerson)<br />
**Redhat<br />
**Slackware<br />
**Debian<br />
**Ubuntu<br />
**OpenSuse<br />
**Fedora<br />
**CentOS<br />
**Kali<br />
<br />
<br />
Algumas distribuições podem ser executadas diretamente no CD/pendrive<br />
sem a necessidade de fazer sua instalação no disco rígido do computador<br />
<br />
==Distribuições aqui no IFSC SJ==<br />
<br />
*Ubuntu<br />
*Ubuntu Mate (fork do Ubuntu)<br />
*Debian<br />
<br />
==Ligando e Desligando o Sistema Linux==<br />
<br />
*Cuidado ao desligar um OS como o Linux!!! Dados podem ser perdidos.<br />
*Ver [https://pt.wikibooks.org/wiki/Guia_do_Linux/Iniciante%2BIntermedi%C3%A1rio/Introdu%C3%A7%C3%A3o/Ligando_o_computador]<br />
<br />
==O Desktop do Ubuntu - Primeiras Considerações==<br />
<br />
*O Desktop no Ubuntu ver[https://help.ubuntu.com/stable/ubuntu-help/shell-overview.html]<br />
<br />
=AULA 2 - Dia 14/03/2019=<br />
<br />
==Objetivos==<br />
<br />
===PARTE 1===<br />
<br />
*Revisão da aula passada;<br />
*repassar itens não mencionados na aula passada;<br />
**Paginação e Memória [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo pg.19]<br />
**Estrutura do Linux [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo pg.18]<br />
<br />
===PARTE 2===<br />
<br />
*Operações com arquivos e diretórios usando o terminal;<br />
*formato de um comando básico;<br />
*quase tudo no Linux é arquivo: tipos de arquivos, diretórios, arquivos ordinários;<br />
*conceito de sistema de arquivos;<br />
*conceito de referência absoluta e relativa;<br />
*conceito de diretório de entrada, diretório de trabalho;<br />
*mudando de diretório com cd;<br />
*listando diretórios e arquivos com ls;<br />
*vendo o significado de um comando com man;<br />
*criando diretórios com mkdir;<br />
*removendo diretórios e arquivos com rmdir e rm;<br />
*referência com . .. - ~<br />
*criando arquivos ordinários com touch;<br />
*arquivos e diretórios escondidos;<br />
*copiando arquivos;<br />
*movendo e renomeando arquivos;<br />
*vendo a história de comandos com history;<br />
<br />
==Conceito de sistemas de arquivos, arquivos e diretórios==<br />
<br />
* [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Sistemas de Arquivos pg.18]<br />
* [Estrutura básica de diretórios do Sistema Linux]<br />
<br />
==Comandos no Linux==<br />
<br />
* [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Comandos e Interpretador de Comandos no Linux pg.18]<br />
<br />
==Tipos de Arquivos==<br />
<br />
* [https://pt.scribd.com/doc/128912228/Administracao-de-Sistemas-Linux Tipos de Arquivos 12,13 e 14 ]<br />
<br />
==Os comandos de operação sobre arquivos e diretórios==<br />
<br />
*[https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Interpretador de comandos - Comandos Básicos - pg.20 e 21]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_2_FICLinux.pdf Ver lista de exercícios da Aula 2]<br />
<!-- *[https://www.dropbox.com/s/g3xr3wimffde2zm/Aula2_Linux_OperacoesComArquivos_2.pdf Ver lista de exercícios da Aula 3] --><br />
<br />
=AULA 3 - Dia 21/03/2019 (aula com Prof. Eraldo)=<br />
<br />
==Objetivos==<br />
<br />
===PARTE 1===<br />
<br />
*Rever comandos básicos de operações sobre arquivos;<br />
*Usar coringas<br />
*usar opções do comando ls<br />
<br />
===PARTE 2===<br />
<br />
*uso do editor gedit para criar arquivos texto;<br />
*usar comandos cat, more e less para visualizar conteúdos de arquivos.<br />
<br />
===PARTE 3===<br />
<br />
*Criar Links simbólicos<br />
<br />
===Parte 4===<br />
<br />
*Redirecionamento de entradas e saídas;<br />
*Pipes<br />
<br />
==Exercícios para esta aula==<br />
'''Créditos e agradecimentos ao Prof. Eraldo pelo desenvolvimento das listas utilizadas''':<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_3_FICLinux.pdf Mais operações Sobre Arquivos e Diretórios]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_4_FICLinux.pdf Editor Gedit, Link Simbólico]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_5_FICLinux.pdf Editor vi]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_6_FICLinux.pdf Entradas e Saídas]<br />
<br />
=AULA 4 - Dia 26/03/2019=<br />
<br />
==Objetivos==<br />
<br />
===PARTE 1===<br />
<br />
*Revisão geral<br />
<br />
<br />
===PARTE 2===<br />
<br />
*Redirecionamento de entradas e saídas: continuação;<br />
*Pipes<br />
<br />
===PARTE 3===<br />
<br />
*Permissão no acesso a arquivos;<br />
*Owner, grupo e outros<br />
<br />
==Exercícios para esta aula==<br />
<br />
=Referências=<br />
<br />
[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_7_FICLinux.pdf Permissão de Acesso a Arquivos: parte 1]<br />
<br />
[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_8_FICLinux.pdf Permissão de Acesso a Arquivos: parte 2]<br />
<br />
=AULA 5 - Dia 28/03/2019=<br />
<br />
==Objetivos==<br />
<br />
*Revisão e preparação para teste;<br />
*introdução ao gerenciamento de processos;<br />
**conceito de processo<br />
**escalonamento de processos<br />
**PID e PPID<br />
**fork/exec<br />
**espaço de endereçamento de um processo;<br />
**estados de um processo: Running, Stopped, Sleeping, Zombie<br />
<br />
https://www.tecmint.com/linux-process-management/<br />
<br />
==Referências==<br />
<br />
[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_9_FICLinux.pdf Gerenciamento De Processos Parte 1]<br />
[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_10_FICLinux.pdf Gerenciamento De Processos Parte 2]<br />
<br />
[https://www.dropbox.com/s/gm1sv856ailny2e/Aula5_TreinamentoTeste.pdf Treinamento Teste 1]<br />
<br />
=AULA 6 - Dia 02/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*Comandos adicionais de gerenciamento de processos;<br />
*Mudança de prioridade com nice e renice;<br />
*Agendamento de processos com crontab<br />
*Aplicações do crontab: conectividade de rede e backup<br />
*Ferramentas de compactação;<br />
*Execução de comandos inseridos em outros comandos;<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/z1d0itcz9ommhrm/Aula6_Aval1.pdf Avaliação 1]<br />
<br />
=AULA 7 - Dia 04/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*Comandos adicionais de manipulação de arquivos:<br />
**comando grep;<br />
**comando find;<br />
*Gerenciamento de usuários:<br />
**adição e remoção de usuários e grupos<br />
**arquivo sudoers<br />
<br />
<br />
==Exercícios==<br />
<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_11_FICLinux.pdf Comandos Adicionais] <br />
<!--*[https://www.dropbox.com/s/h0v122is4aj9ogr/Aula7_GerenciamentoDeUsuarios_Parte1.pdf Aula 7 - Parte 2]--><br />
<br />
=AULA 8 - Dia 09/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*Introdução ao Shell script<br />
*variáveis<br />
*Comando if<br />
<br />
==Referências==<br />
<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_14_FICLinux.pdf Outros comando gerenciamento de processos]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_12_FICLinux.pdf Shell Parte 1]<br />
<br />
{{collapse top | script DESAFIO (a)}}<br />
<syntaxhighlight lang=c><br />
#!/bin/bash<br />
<br />
FILE="$1"<br />
<br />
if [ ! $# -eq 1 ]; then<br />
echo opa! Algo errado...<br />
echo uso: script parametro<br />
exit<br />
fi<br />
<br />
<br />
if [ -h $FILE ]; then<br />
echo $FILE é um link simbólico<br />
else<br />
echo $FILE não é um link simbólico<br />
fi<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
{{collapse top | script DESAFIO (b)}}<br />
<syntaxhighlight lang=c><br />
<br />
#!/bin/bash<br />
<br />
FILE="$1"<br />
<br />
if [ ! $# -eq 1 ]; then<br />
echo opa! Algo errado...<br />
echo uso: script parametro<br />
exit<br />
fi<br />
<br />
<br />
if [[ -w $FILE && -O $FILE ]]; then<br />
echo Possui permissao de escrita de $FILE<br />
else<br />
echo Colocando permissão de escrita para $FILE<br />
chmod u+w $FILE<br />
echo permissoes adicionadas com sucesso para $FILE ver abaixo<br />
ls -l $FILE<br />
<br />
fi<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
{{collapse top | script DESAFIO (c)}}<br />
<syntaxhighlight lang=c><br />
#!/bin/bash<br />
<br />
FILE1="$1"<br />
FILE2="$2"<br />
<br />
if [ ! $# -eq 2 ]; then<br />
echo opa! Algo errado...<br />
echo uso: script parametro<br />
exit<br />
fi<br />
<br />
if [[ -f $FILE1 && -r $FILE1 ]]; then<br />
echo $1 É regular e possui permissao de leitura<br />
mv $FILE1 $FILE2<br />
echo Mudei o nome de $FILE1 para $FILE2<br />
else<br />
echo $FILE1 não tem permissao...<br />
fi<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
=AULA 9 - Dia 11/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*ainda shell script<br />
*comando for<br />
*comando while<br />
<br />
==Referências==<br />
<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_13_FICLinux.pdf Shell Parte 2]<br />
<br />
=AULA 10 - Dia 16/04/2019=<br />
<br />
*Avaliação da disciplina<br />
<br />
=Tópicos extras=<br />
<br />
==Objetivos==<br />
<br />
*mais alguns tópicos sobre criação de usuários;<br />
*servidores de janelas: X11, <br />
*gerenciadores de janelas e desktops: Gnome, KDE<br />
*instalação de pacotes;<br />
*o Linux e o Software Livre<br />
*avaliação<br />
<br />
==Servidores de Janelas==<br />
<br />
[https://pt.wikipedia.org/wiki/X_Window_System X Windows System]<br />
<br />
[https://en.wikipedia.org/wiki/X_Window_System_protocols_and_architecture Arquitetura do X]<br />
<br />
==Desktops e Geneciadores de Janelas==<br />
<br />
[https://pt.wikipedia.org/wiki/Interface_gr%C3%A1fica_do_utilizador Interfaces Gráficas]<br />
<br />
==Instalando pacotes==<br />
<br />
[https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Ver pg.43 do Formacao-de-Suporte-Tecnico-Proinfo]<br />
<br />
[http://www.hardware.com.br/tutoriais/tutorial-completo-apt-get/ uso do apt-get]<br />
<br />
Exercício: instalar e executar um servidor ssh:<br />
<br />
sudo apt-get update<br />
sudo apt-get install openssh-server<br />
sudo service start ssh<br />
<br />
Acessar o ssh de outra máquina<br />
ssh usuario@numero_ip<br />
<br />
Exportar o display e executar o comando remoto:<br />
export DISPLAY=IP_cliente_ssh:0.0<br />
firefox &<br />
<br />
Conferir se o firefox realmente está se executando (use o ps)<br />
<br />
Remover o pacote ssh server:<br />
<br />
sudo apt-get remove openssh-server<br />
<br />
==Linux = Software Livre==<br />
<br />
[https://pt.wikipedia.org/wiki/Software_livre]<br />
<br />
<br />
<br />
[https://www.novell.com/coolsolutions/feature/1532.html]<br />
<br />
==Onde baixar o Ubuntu==<br />
<br />
[https://www.ubuntu.com/download/desktop Baixar Ubuntu daqui]<br />
<br />
==Sobre o Boot==<br />
<br />
[http://www.rodsbooks.com/linux-uefi/ by Roderick W. Smith]<br />
<br />
[https://www.happyassassin.net/2014/01/25/uefi-boot-how-does-that-actually-work-then/ AdamW on Linux and more]<br />
<br />
==Sobre o Desktop Environment e o Desktop Shell==<br />
<br />
[https://ittutorials.net/linux/ubuntu/desktop-guide/ /desktop-guide]<br />
<br />
==Instalar Ubuntu no Virtual Box==<br />
<br />
[http://www.edivaldobrito.com.br/virtualbox-no-linux/ Instalar VirtualBox no Linux]<br />
<br />
[http://www.bosontreinamentos.com.br/virtualizacao/como-instalar-o-virtualbox-no-windows-para-criacao-de-maquinas-virtuais/ Instalar VirtualBox no Windows]<br />
<br />
[http://www.techtudo.com.br/dicas-e-tutoriais/noticia/2016/04/como-instalar-o-ubuntu-com-o-virtualbox.html Instalar Linux no VirtualBox]<br />
<br />
=AULA 11 - Dia 23/04/2019=<br />
<br />
*Introdução a Redes de Computadores<br />
**Conceito Básicos em Redes e Protocolos<br />
**Ferramentas de Redes<br />
**Exemplo de Protocolo de Aplicação: http<br />
**O processo de encapsulamento<br />
<br />
==Plano de Ensino==<br />
<br />
*[https://wiki.sj.ifsc.edu.br/index.php/PRL-FicLinux_(Plano_de_Ensino) Plano de Ensino]<br />
<br />
<br />
==Laboratório 1 - Ferramentas de Rede e Conceitos Básicos==<br />
<br />
*Familiarização com a infraestrutura dos laboratórios de redes<br />
*Familiarização com ferramentas de rede: ifconfig, ping, traceroute;<br />
*Desenvolver a noção de endereçamentos de rede IP e de endereço de hardware (MAC)<br />
*Desenvolver a noção de rotas em redes IP<br />
*Testar a conectividade IP com ping<br />
<br />
*Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)]<br />
<br />
==Laboratório 2 - Wireshark e encapsulamento==<br />
<br />
*Familiarização com o sniffer de rede WireShark<br />
*Observar o comportamento do ping e se familiarizar com o processo de encapsulamento;<br />
<br />
**Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)]<br />
<br />
==Conceituando Protocolos e Aplicações de Rede==<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/Conceituando%20protocolos.pdf Conceituando protocolos]<br />
<br />
=AULA 12 - Dia 25/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*Protocolos de aplicação: exemplo http<br />
<br />
==Laboratório 4 - Desvendando o HTTP com Wireshark - BÁSICO==<br />
<br />
Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)#Parte_1:_Observando_interfaces_do_sistema_com_ifconfig]<br />
<br />
=AULA 13 - Dia 30/04/2019=<br />
<br />
*Revisão do Conceito de Protocolo ([-] Laboratório 3 - Conceituando protocolos )<br />
*O DNS como protocolo de Aplicação;<br />
*Camada de Transporte: protocolo UDP<br />
<br />
==Revisão dos Conceitos de Protocolo==<br />
<br />
Laboratório 3 - Conceituando protocolos [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)#Parte_1:_Observando_interfaces_do_sistema_com_ifconfig]<br />
<br />
==O DNS como protocolo de Aplicação==<br />
<br />
Laboratório 7 - Serviço de Nomes (DNS) [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)#Parte_1:_Observando_interfaces_do_sistema_com_ifconfig]<br />
<br />
==O Protocolo UDP==<br />
<br />
Laboratório 8 - Desvendando o UDP - Básico <br />
<br />
=AULA 14 - Dia 02/05/2019=<br />
<br />
==Objetivos==<br />
<br />
*Explorar o papel e diferenças dos protocolos de Transporte TCP/UDP<br />
*Explorar a Camada IP e aspectos da configuração da mesma sob o Linux<br />
<br />
<br />
===TCP e UDP===<br />
<br />
*docente.ifsc.edu.br/odilson/RCO60803/TCP%20controle%20de%20erros.pdf<br />
*docente.ifsc.edu.br/odilson/RCO60803/UDP%20Basico.pdf<br />
<br />
==Camada IP no Linux: Configuração das Interfaces usando ifconfig e ip addr==<br />
<br />
Usando a ferramenta Netkit2, que permite construir redes virtuais com o Linux vamos construir DUAS redes locais interligadas por um roteador. Em cada rede colocaremos dois PCs. As interfaces estarão completamente desconfiguradas:<br />
<br />
<ol><br />
<li><br />
Construir um arquivo texto de nome rede.conf usando o editor de texto gedit.<br />
<code>gedit rede.conf &</syntaxhighlight> <br />
</li><br />
<li><br />
Criar a seguinte topologia:<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=generic<br />
<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
#Definição da Topologia da Rede<br />
<br />
pc1[eth0]=lan0<br />
pc2[eth0]=lan0<br />
<br />
pc3[eth0]=lan1<br />
pc4[eth0]=lan1<br />
<br />
r1[eth0]=lan0<br />
r1[eth1]=lan1<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Executar netkit fazendo (atualize se necessário - pergunte para o professor como fazer):<br />
Aplicativos >> Educativo >> Netkit2 <br />
</li><br />
<li><br />
Carregar o arquivo lab.conf a partir do Netkit2:<br />
<code>File >> Load Only</syntaxhighlight><br />
</li><br />
<li><br />
Visualizar a rede a ser implementada:<br />
<code>File >> Graph</syntaxhighlight><br />
</li><br />
<li> <br />
Executar a configuração:<br />
<code>Network >> Start</syntaxhighlight><br />
</li><br />
<li><br />
Verificar o estado de todas interfaces (se UP ou DOWN) com:<br />
<code>ifconfig -a</syntaxhighlight><br />
<code>ip addr</syntaxhighlight> <br />
Note que nas últimas versões do Linux o comando ip vem sendo recomendado (embora o ifconfig ainda esteja disponível).<br />
</li><br />
<li><br />
Vamos configurar as interfaces. Para tanto vamos assumir que teremos duas sub-redes:<br />
<code>lan0 - endereço da rede 10.10.10.0/24</syntaxhighlight><br />
<code>lan1 - endereço da rede 20.20.20.0/24</syntaxhighlight><br />
A interface eth0 de PC1 receberá o endereço 10.10.10.1/24 e a interface eth0 de PC2 recebera 10.10.10.2/24. A interface do roteador NA lan0 também deve receber um endereço: 10.10.10.254/24:<br />
<br />
No PC1:<br />
<code>ifconfig eth0 10.10.10.1/24</syntaxhighlight><br />
No PC2:<br />
<code>ifconfig eth0 10.10.10.2/24</syntaxhighlight><br />
No R1:<br />
<code>ifconfig eth0 10.10.10.254/24</syntaxhighlight><br />
</li> <br />
<li><br />
Seguindo a mesma lógica configure as máquinas e o roteador na lan1<br />
</li><br />
<li> Um ponto importante a ser lembrado é que quando uma interface é configurada com um número IP, a tabela de roteamento do sistema é alimentada com o número correspondente da rede associada ao número. Isto pode ser observado em TODAS as máquinas, inclusive no roteador:<br />
<code> route -n </syntaxhighlight><br />
ou <br />
<code> ip route </syntaxhighlight><br />
</li><br />
</ol><br />
<br />
==Camada IP no Linux: verificando e configurando rotas - configuração da rota default ==<br />
<br />
<ol><br />
<li> Um ponto importante a ser lembrado é que quando uma interface é configurada com um número IP, a tabela de roteamento do sistema é alimentada com o número correspondente da rede associada ao número. Isto pode ser observado em TODAS as máquinas, inclusive no roteador:<br />
<code> route -n </syntaxhighlight><br />
ou <br />
<code> ip route </syntaxhighlight><br />
Esta informação é importante pois define a entrega DIRETA de pacotes na rede, ou seja, se PC1 quiser enviar um pacote para PC2, esta linha na tabela de roteamento garante que o pacote IP seja despachado diretamente para o PC2 através de um frame ETHERNET endereçado para o MAC do PC1.<br />
</li><br />
<li> Confira os endereços MAC e IP das interfaces dos PC1 e PC2 e anote. Faça um ping no PC1 em direção a PC2.<br />
<code>root@pc1:~# ping 10.10.10.2</syntaxhighlight><br />
</li><br />
<li> Use um capturador de pacotes em modo texto para observar o tráfego na eth0 do PC2. Observe os endereços MAC do Frame Ethernet e os endereços IP do pacote IP.<br />
<code>root@pc2:~# tcpdump -i eth0 -e</syntaxhighlight><br />
ENTÃO? O que se pode concluir? É uma entrega direta ou indireta? <br />
</li><br />
<li> Uma curiosidade. Tente observar o tráfego na interface eth0 do Roteador R1. É possível observar algo? O que se pode concluir? Pare agora o ping e os tcpdumps executados.<br />
</li><br />
<li> Qualquer máquina IP acaba tomando uma decisão de roteamento. O PC1, ao observar que PC2 está na sua própria rede 10.10.10.0/24, entrega diretamente o pacote. E se PC1 tentar entregar para PC3? Faça um ping e observe o que acontece:<br />
<code>root@pc1:~#ping 20.20.20.1</syntaxhighlight><br />
Não deve ter funcionado :-(<br />
Um primeiro problema é que simplesmente a camada IP observa que o endereço não é entrega DIRETA mas não tem informação (linha) na tabela de roteamento dizendo para quem deve ser entregue o pacote. <br />
</li><br />
<li> Vamos acrescentar uma linha na tabela de PC1 dizendo como fazer esta entrega INDIRETA. Usaremos o conceito de gateway default. Ou seja, se não tiver para quem entregar explicitamente, o pacote será entregue para o gateway default:<br />
<code>root@pc1:~# route add default gateway 10.10.10.254</syntaxhighlight><br />
confira o estabelocimento da rota:<br />
<code>root@pc1:~# route -n</syntaxhighlight><br />
tente o ping novamente escutando com o tcpdump na interface eth0 de R1. Ainda não funcionou mas o R1 já recebe os pacotes. Confira o MAC de destino do pacote. Deve ser o MAC do roteador. <br />
</li> <br />
<li><br />
POR QUE NÃO FUNCIONOU: será que R1 não sabe como entregar o pacote para PC3? Confira se o pacote sai de R1 na rede lan1:<br />
<code>root@r1:~# tcpdump -i eth2 -e</syntaxhighlight><br />
</li> <br />
<li><br />
Temos um problema ainda que o nosso roteador Linux NÃO está habilitado a ser roteador. Isto pode ser feito com:<br />
<code>echo 1 > /proc/sys/net/ipv4/ip_forward</syntaxhighlight><br />
</li> <br />
<li> Tente novamente o ping de PC1 para PC3. Ainda não funcionará mas escute a interface eth1 de R1 e a interface eth0 de PC3 e verá que os pacotes do ICMP REQUEST estão chegando. Confira inclusive os MACs envolvidos...<br />
</li><br />
<li><br />
O que estaria faltando ainda para que PC3 responda aos ECHO REQUEST? O problema é de entrega indireta. O PC3 não sabe como entregar pacotes "externos". Acrescente um gateway default.<br />
</li><br />
<li><br />
Exercício adicional com 2 roteadores. Ver manual:<br />
* [http://linux-ip.net/html Guia de Administração da Camada IP no Linux<br />
</li><br />
</ol><br />
<br />
==Exercício: acrescentando uma lan2 com com 2 PCs no roteador==<br />
<br />
Acrescente uma rede 30.30.30.0/24 (lan2) no roteador R1. Acrescente 2 PCs e configure o sistema.<br />
Teste a conectividade entre todos os PCs.<br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
pc5[type]=generic<br />
pc6[type]=generic<br />
<br />
pc7[type]=generic<br />
pc8[type]=generic<br />
<br />
<br />
#Definição da Topologia da Rede<br />
<br />
pc1[eth0]=lan0:ip=10.10.10.1/24<br />
pc1[default_gateway]=10.10.10.254<br />
<br />
pc2[eth0]=lan0:ip=10.10.10.2/24<br />
pc2[default_gateway]=10.10.10.254<br />
<br />
pc3[eth0]=lan1:ip=20.20.20.1/24<br />
pc3[default_gateway]=20.20.20.254<br />
<br />
pc4[eth0]=lan1:ip=20.20.20.2/24<br />
pc4[default_gateway]=20.20.20.254<br />
<br />
pc5[eth0]=lan2:ip=30.30.30.1/24<br />
pc5[default_gateway]=30.30.30.254<br />
<br />
pc6[eth0]=lan2:ip=30.30.30.2/24<br />
pc6[default_gateway]=30.30.30.254<br />
<br />
pc7[eth0]=lan4:ip=40.40.40.1/24<br />
pc7[default_gateway]=40.40.40.254<br />
<br />
pc8[eth0]=lan3:ip=50.50.50.1/24<br />
pc8[default_gateway]=40.40.40.254<br />
<br />
<br />
r1[eth0]=lan0:ip=10.10.10.254/24<br />
r1[eth1]=lan1:ip=20.20.20.254/24<br />
r1[eth2]=lan2:ip=30.30.30.254/24<br />
r1[eth3]=lan3:ip=50.50.50.253/24<br />
r2[eth1]=lan3:ip=50.50.50.254/24<br />
r2[eth0]=lan4:ip=40.40.40.254/24<br />
<br />
r2[route]=10.10.10.0/24:gateway=50.50.50.253<br />
<br />
</syntaxhighlight><br />
<br />
=AULA 15 - Dia 7/05/2019=<br />
<br />
*Hubs X Switches. O Papel do Protocolo ARP<br />
<br />
<br />
*Serviço DHCP e NAT<br />
[-] Laboratório 16 - Sub-redes e Roteamento Estático em Redes <br />
<br />
==Hubs, Switches. Protocolo ARP==<br />
<br />
[Laboratório 17 - Tecnologia de Enlace Ethernet]<br />
<br />
==Serviço DHCP==<br />
<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IP_DHCP_NAT.pdf DHCP e NAT]<br />
<br />
Construir uma rede simular a aula anterior mas deixar PC1 e PC2 desconfigurados. Criar uma máquina para atuar como servidor DHCP. <br />
<br />
<ol><br />
<li><br />
Editar o arquivo de configuração do dhcp server:<br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=gateway #já habilitado para forward<br />
<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
pcdhcp[type]=generic<br />
<br />
<br />
#Definição da Topologia da Rede<br />
<br />
pc1[eth0]=lan0 #desconfigurada...<br />
<br />
pc2[eth0]=lan0:ip=10.10.10.2/24<br />
pc2[default_gateway]=10.10.10.254<br />
<br />
pcdhcp[eth0]=lan0:ip=10.10.10.3/24<br />
pcdhcp[default_gateway]=10.10.10.254 <br />
<br />
pc3[eth0]=lan1:ip=20.20.20.1/24<br />
pc3[default_gateway]=20.20.20.254<br />
<br />
pc4[eth0]=lan1:ip=20.20.20.2/24<br />
pc4[default_gateway]=20.20.20.254<br />
<br />
<br />
r1[eth0]=lan0:ip=10.10.10.254/24<br />
r1[eth1]=lan1:ip=20.20.20.254/24<br />
<br />
</syntaxhighlight><br />
</li><br />
<li> No server estabelecer a configuração desejada:<br />
<br />
nano /etc/dhcp/dhcpd.conf<br />
<br />
com:<br />
<br />
<code><br />
<br />
subnet 10.10.10.0 netmask 255.255.255.0 {<br />
range 10.10.10.10 10.10.10.50;<br />
option routers 10.10.10.254;<br />
option broadcast-address 10.10.10.255;<br />
default-lease-time 600;<br />
max-lease-time 7200;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
</li><br />
<li><br />
Rodar o servidor DHCP na máquina pc_dhcp:<br />
<code><br />
/usr/sbin/dhcpd -q -4 -pf /run/dhcp-server/dhcpd.pid -cf /etc/dhcp/dhcpd.conf eth0<br />
</syntaxhighlight><br />
</li><br />
<li><br />
No cliente (PC1) fazer:<br />
<code><br />
dhclient -v eth0<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Usando o ifconfig e route confira se o PC1 está completamente configurado. Faça teste com o ping<br />
</li><br />
<li> Rode o tcpdump na eth0 de r1 para "verificar" os pacotes DHCP:<br />
<code><br />
tcpdump -i eth0<br />
</syntaxhighlight><br />
</li><br />
<li> Repetir a operação no PC2. Baixe a interface antes:<br />
<code><br />
ifconfig eth0 down<br />
dhclient -v eth0<br />
</syntaxhighlight><br />
</li><br />
</ol><br />
<br />
==O NAT==<br />
<br />
Vamos tentar elaborar um laboratório usando o NAT MASQUERADE<br />
https://www.karlrupp.net/en/computer/nat_tutorial<br />
<br />
Construir uma rede com 3 LANs e 2 roteadores como na aula passada. Executar o APACHE em uma máquina da lan3 (exemplo PC4). Não colocar rotas para lan0 em r2. Desta forma PC1 não deve pingar em PC4. <br />
<br />
<code><br />
LAN0 <-R1-> LAN1 <-R2 -> LAN3<br />
</syntaxhighlight><br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
pc1[type]=generic<br />
apache[type]=generic<br />
<br />
<br />
pc1[eth0]=lan0:ip=10.10.10.1/24<br />
pc1[default_gateway]=10.10.10.254<br />
<br />
<br />
r1[eth0]=lan0:ip=10.10.10.254/24<br />
r1[eth1]=lan1:ip=20.20.20.254/24<br />
r1[route]=30.30.30.0/24:gateway=20.20.20.253<br />
<br />
r2[eth0]=lan1:ip=20.20.20.253/24<br />
r2[eth1]=lan2:ip=30.30.30.254/24<br />
<br />
apache[eth0]=lan2:ip=30.30.30.1/24<br />
apache[default_gateway]=30.30.30.254<br />
</syntaxhighlight><br />
<br />
<ol><br />
<li> Rodar o apache em PC4:<br />
<code> /etc/init.d/apache2 start </syntaxhighlight><br />
</li><br />
<li> Testar se o Apache é acessível a partir de PC3<br />
<code>lynx END_PC3 </syntaxhighlight><br />
<li><br />
Em R1 fazer:<br />
<code>iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE</syntaxhighlight><br />
</li><br />
<li> Monitorar os pacotes que chegam e saem da eth0 de PC4.<br />
</li><br />
<li> Fazer em PC1:<br />
lynx END_PC4 #endereço de PC4.<br />
O que se pode concluir?<br />
</li><br />
<br />
</ol><br />
<br />
=AULA 16 - Dia 09/05/2019=<br />
*Endereçamento IPv4.<br />
*Exercícios segmentação Redes. <br />
<br />
===Objetivos===<br />
*Compreender endereçamento IPv4.<br />
*Compreender o processo de alocação de faixas de IPs.<br />
*Compreender e manipular os números IPs.<br />
*Compreender e manipular as máscaras de rede.<br />
*Proporcionar ao aluno uma visão prática de roteamento IP.<br />
<br />
===Fonte Básica===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IP_DHCP_NAT.pdf DHCP e NAT]<br />
*[http://www.davidc.net/sites/default/subnets/subnets.html Cálculo de sub-redes]<br />
<br />
===Roteiro===<br />
<br />
#Baseado no arquivo exemplo abaixo, crie um arquivo de configuração para o NetKit que implemente sua proposta. O arquivo deve contemplar todas as configurações necessárias para o perfeito funcionamento da rede, ou seja, ao carregar o arquivo todos os hosts deverão ser capazes de "pingar" uma ao outro. <br />
##Faça testes de conectividade entre os hosts.<br />
##Demonstre para o professor o perfeito funcionamento de sua rede.<br />
*O arquivo de configuração do Netkit abaixo, é a definição para o funcionamento da simulação da rede apresentada na Figura 2. Falta adicionar as rotas.<br />
<br />
[[Arquivo:DynamicRoutingTriangle.png |thumb | 400px| Figura 2 - Rede exemplo]]<br />
<br />
<code><br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=link0:ip=192.168.0.1/24<br />
pc2[eth0]=link1:ip=192.168.1.1/24<br />
pc3[eth0]=link2:ip=192.168.2.1/24<br />
<br />
# Default gateways definitions<br />
pc1[default_gateway]=192.168.0.254<br />
pc2[default_gateway]=192.168.1.254<br />
pc3[default_gateway]=192.168.2.254<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
r3[type]=gateway<br />
<br />
# Routers' interfaces to local networks<br />
r1[eth0]=link0:ip=192.168.0.254/24<br />
r2[eth0]=link1:ip=192.168.1.254/24<br />
r3[eth0]=link2:ip=192.168.2.254/24<br />
<br />
# Network "backbone" links<br />
r1[eth1]=backbone0:ip=10.0.0.1/30<br />
r1[eth2]=backbone1:ip=10.0.1.1/30<br />
<br />
r2[eth1]=backbone0:ip=10.0.0.2/30<br />
r2[eth2]=backbone2:ip=10.0.2.1/30<br />
<br />
r3[eth1]=backbone1:ip=10.0.1.2/30<br />
r3[eth2]=backbone2:ip=10.0.2.2/30 <br />
<br />
# Routes definition<br />
r1[route]=192.168.2.0/24:gateway=10.0.1.2<br />
r1[route]=192.168.1.0/24:gateway=10.0.0.2<br />
r1[route]=10.0.2.0/30:gateway=10.0.0.2<br />
<br />
r2[route]=192.168.0.0/24:gateway=10.0.0.1 <br />
r2[route]=192.168.2.0/24:gateway=10.0.2.2<br />
r2[route]=10.0.1.0/30:gateway=10.0.2.2<br />
<br />
r3[route]=192.168.0.0/24:gateway=10.0.1.1<br />
r3[route]=192.168.1.0/24:gateway=10.0.2.1<br />
r3[route]=10.0.0.0/30:gateway=10.0.2.1<br />
</syntaxhighlight><br />
<br />
===Exercícios Extras (resolvidos)===<br />
*[[Arquivo:exercicios_CIDR.pdf]]<br />
<br />
===Referencia===<br />
*[http://www.davidc.net/sites/default/subnets/subnets.html Link Calculador Online de Subnets]<br />
<br />
=AULA 17 - Dia 14/05/2019=<br />
<br />
*Finalização do Laboratório do NAT<br />
*Laboratório de Introdução ao IPV6<br />
*Introdução ao Access Point TPLINK N750: configuração da LAN e WAN<br />
<br />
==LAboratório de Introdução ao IPv6==<br />
<br />
===Material de REferência===<br />
<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IPv6.pdf IPv6]<br />
<br />
===Roteiro de atividades sobre o IPv6===<br />
<br />
A figura abaixo apresenta o diagrama esquemático da rede a ser montada/analisada. Observe que todos os IPv6 ''Global Unicast'' já estão definidos na mesma, são esses IPs que utilizaremos em nosso experimento.<br />
<br />
[[Arquivo:Diagrama_rede_IPv6.jpg]]<br />
<br />
#Crie em seu computador um arquivo com nome '''/home/aluno/IPv6.conf''', com o seguinte conteúdo: <syntaxhighlight lang=bash><br />
#Ligacao das maquinas nos dominios de colisao<br />
#Duas pequenas redes interligadas pelo backbone<br />
<br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=link0:ipv6=2001:bcc:faca:1::101/64<br />
pc2[eth0]=link1:ipv6=2001:bcc:cafe:1::102/64<br />
pc3[eth0]=HUB1:ipv6=2001:bcc:1f0:1::103/64<br />
pc4[eth0]=HUB1<br />
<br />
#Default Gateways definitions<br />
pc1[route]=default6:gateway=2001:bcc:faca:1::1<br />
pc2[route]=default6:gateway=2001:bcc:cafe:1::1<br />
pc3[route]=default6:gateway=2001:bcc:1f0:1::1<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
#Routers interfaces definitions<br />
r1[eth0]=backbone0:ipv6=2001:db8:dead:1::1/64<br />
r1[eth1]=link0:ipv6=2001:bcc:faca:1::1/64<br />
r1[eth2]=link1:ipv6=2001:bcc:cafe:1::1/64<br />
<br />
r2[eth0]=backbone0:ipv6=2001:db8:dead:1::2/64<br />
r2[eth1]=HUB1:ipv6=2001:bcc:1f0:1::1/64<br />
<br />
#Routers definitions<br />
r1[route]=2001:bcc:1f0:1::0/64:gateway=2001:db8:dead:1::2<br />
r2[route]=2001:bcc:faca:1::0/64:gateway=2001:db8:dead:1::1<br />
r2[route]=2001:bcc:cafe:1::0/64:gateway=2001:db8:dead:1::1<br />
</syntaxhighlight><br />
#Tenha certeza que o Netkit2 estja atualizado: General >> Update.<br />
#Rode o NetKit em seu computador. Em um terminal digite: <syntaxhighlight lang=bash><br />
netkit2 & </syntaxhighlight><br />
#No menu '''File''' - '''Load and Run''', procure o arquivo '''/home/aluno/IPv6.conf''' e clique em OK. Abrirá uma janela com 6 abas, onde cada uma delas é um terminal de configuração do respectivo equipamento: '''pc1-4''' ou '''r1-2'''.<br />
#Observe que o '''pc4''' não está com sua interface configurada.<br />
#Ao clicar no menu '''File''' - '''Graph''', pode-se ter uma visão da rede a ser simulada e conferir se é equivalente ao diagrama proposto.<br />
#Faça um '''ping6''' entre o '''pc1''' ao '''pc3''': <syntaxhighlight lang=bash><br />
ping6 -c4 2001:bcc:1f0:1::103 </syntaxhighlight><br />
#Faça um '''ping6''' entre o '''pc1''' e '''pc2'''.<br />
#No '''pc4''' use o seguinte comando para adicionar o endereço IPv6 à interface de rede: <syntaxhighlight lang=bash><br />
ip addr add 2001:bcc:1f0:1::104/64 dev eth0 </syntaxhighlight><br />
#No '''pc4''', acrescente o ''default gateway'' com o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add default via 2001:bcc:1f0:1::1 dev eth0 </syntaxhighlight><br />
#No '''pc1''' use o seguinte comando para verificar como ficou a configuração dos endereços da interface de rede. O resultado é similar ao apresentado pelo comando '''ifconfig''': <syntaxhighlight lang=bash><br />
ip addr show dev eth0 </syntaxhighlight><br />
#Todo o roteamento está pronto, mas caso desejássemos poderíamos acrescentar rotas com comando similares aos já utilizados. Por exemplo, no '''r1''', para adicionar uma rota estática para a rede dos '''pc3''' e '''pc4''' utilizaríamos o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add 2001:bcc:1f0:1::/64 via 2001:db8:dead:1::2 dev eth0 </syntaxhighlight><br />
#Confira as rotas estabelecidas em todos os ''hosts'' com o comando abaixo. <br />
##São coerentes com os dados apresentados no diagrama acima?<syntaxhighlight lang=bash><br />
ip -6 route show </syntaxhighlight><br />
#No '''pc1''' use os seguintes comandos para ver a rota para alguns vizinhos: <syntaxhighlight lang=bash><br />
traceroute6 2001:bcc:1f0:1::103<br />
traceroute6 2001:bcc:1f0:1::104 </syntaxhighlight><br />
#*Anote as rotas.<br />
#Deixe um '''ping6''' entre o '''pc1''' ao '''pc3''' rodando: <syntaxhighlight lang=bash><br />
ping6 2001:bcc:1f0:1::103 </syntaxhighlight><br />
<br />
==Introdução ao Roteador-AP da TP-Link==<br />
<br />
Ver manual https://www.tp-link.com/us/support/download/tl-wdr4300/<br />
<br />
===Configuração Básica===<br />
<br />
Seguir as instruções do professor para a seguinte configuração:<br />
<br />
#Retirar o plugue cabo ethernet que liga o PC do Lab a rede do IFSC. Conectar o PC a uma das portas LAN do AP;<br />
#Conectar a WAN do AP ao Lab. do IFSC;<br />
#Em um terminal do PC aplique o comando:<br />
sudo dhclient eth0<br />
#No browser do PC acesse o AP colocando o endereço:<br />
http://tplinklogin.net<br />
#Entrar com user admin e senha admin<br />
#Configurar a WAN para DHCP (IP dinâmico)<br />
#Configurar a LAN para DHCP na faixa 192.168.0.10 a 192.168.0.100<br />
#Usar uma máquina virtual para testar a aquisição do IP:<br />
pc1[type]=generic<br />
pc1[eth0]=uplink:bridge=eth0<br />
<br />
DESAFIO 1: Elabore um experimento para mostrar que a LAN do AP funciona como um switch.<br />
Sugestão: Use uma máquina adicional colocada em uma porta do AP.<br />
<br />
DESAFIO 2: Elabore um experimento para mostrar como o NAT funciona no AP. Se inspire no experimento realizado sobre o NAT.<br />
<br />
=AULA 18 - Dia 16/05/2019=<br />
<br />
==Objetivos==<br />
<br />
<br />
PARTE 0 - Exercício de Revisão<br />
<br />
PARTE 1 - Serviços de rede sobre o Linux<br />
<br />
*serviço SSH no Linux<br />
<br />
PARTE 2 - Acesso a rede WIFI<br />
<br />
*conceitos básicos de redes sem fio: pg.103 de [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo]<br />
*configuração da WIFI no Access Point e Acesso via Linux<br />
<br />
===PARTE 0===<br />
<br />
Considere a rede abaixo definida pelo arquivo do netkit. Configure as redes com os seguintes prefixos:<br />
<br />
*lan0: 50.50.50.0/24<br />
*lan1: 60.60.60.0/24<br />
*lan2: 70.70.70.0/24<br />
<br />
O pc2dhcp deve ser configurado como servidor DHCP e deverá liberar IPs na faixa de 50.50.50.100/24 a 50.50.50.200/24. Todos os PCs receberão IP estáticos com exceção do PC1 que deverá receber dinamicamente o endereço. Toda a configuração deve ser realizada manualmente.<br />
<br />
Teste a conectividade entre todos os PCs. Usando o tcpdump demonstre que quando PC2 faz um ping em PC4 a entrega será indireta. Demonstre usando o MAC address das máquinas como apoio. Chame o professor para demonstrar.<br />
<br />
ALGUNS COMANDOS NOTÁVEIS:<br />
<br />
ifconfig<br />
ifconfig eth0 10.10.10.1/24<br />
route -n<br />
route add default gw 200.10.1.254<br />
route del -net 200.10.1.0/24 gw 200.10.2.1<br />
route add -net 200.10.1.0/24 gw 200.10.2.1<br />
<br />
tcpdump -i eth1 -n -e<br />
<br />
<code><br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2dhcp[type]=generic<br />
<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=lan0<br />
pc2dhcp[eth0]=lan0<br />
<br />
pc3[eth0]=lan1<br />
<br />
pc4[eth0]=lan2<br />
<br />
r1[eth0]=lan0<br />
r1[eth1]=lan1<br />
<br />
r2[eth0]=lan1<br />
r2[eth1]=lan2<br />
</syntaxhighlight><br />
<br />
Solução:<br />
R1:<br />
ifconfig eth0 50.50.50.254/24<br />
ifconfig eth1 60.60.60.254/24<br />
route add -net 70.70.70.0/254 gw 60.60.60.253<br />
R2:<br />
ifconfig eth1 70.70.70.254/24<br />
ifconfig eth0 60.60.60.253/24<br />
route add -net 50.50.50.0/24 gw 60.60.60.254<br />
PC2DHCP:<br />
ifconfig eth0 50.50.50.2/24<br />
route add default gateway 50.50.50.254<br />
configurar server: nano /etc/dhcp/dhcpd.conf<br />
# A slightly different configuration for an internal subnet.<br />
subnet 50.50.50.0 netmask 255.255.255.0 {<br />
range 50.50.50.100 50.50.50.200;<br />
# option domain-name-servers ns1.internal.example.org;<br />
# option domain-name "internal.example.org";<br />
option routers 50.50.50.254;<br />
option broadcast-address 50.50.50.255;<br />
default-lease-time 600;<br />
max-lease-time 7200;<br />
}<br />
<br />
/usr/sbin/dhcpd -q -4 -pf /run/dhcp-server/dhcpd.pid -cf /etc/dhcp/dhcpd.conf eth0<br />
PC3:<br />
ifconfig eth0 60.60.60.1/24<br />
route add default gw 60.60.60.254 #note que poderia ser para o outro roteador (R2)<br />
PC4:<br />
ifconfig eth0 70.70.70.1/24<br />
route add default gw 70.70.70.254<br />
PC1:<br />
dhclient eth0 -v<br />
<br />
==Serviço SSH==<br />
<br />
O Serviço SSH se utiliza do modelo cliente-servidor. Deve-se executar um servidora ssh na máquina que permitirá o acesso remoto.<br />
Um cliente a partir de uma outra máquina poderá logar remotamente usando um cliente ssh ou poderá fazer outras operações, tipo cópia remota<br />
de arquivos.<br />
<br />
===ETAPA 1 - Rodando o servidor SSH===<br />
*Baseado no Material do Prof.Odilson Valle<br />
<br />
No Ubuntu server:<br />
<ol><br />
<li><br />
<code>sudo su</syntaxhighlight><br />
<code>apt-get update</syntaxhighlight><br />
<code>apt-get install ssh</syntaxhighlight> O SSH já estará funcionando normalmente.<br />
Para configurações extras deve-se editar o arquivo /etc/ssh/sshd_config e acrescentar, por exemplo:<br />
*X11Forwarding yes (no) ### habilita/desabilita acesso com ambiente gráfico remoto<br />
*AllowUsers Fred Wilma ### Libera o acesso somente para os usuários Fred e Wilma<br />
*DenyUsers Dino Pebbles ### Bloqueia o acesso aos usuários Dino e Pebbles e libera para os demais usuários<br />
*AllowGroups admin ### Libera o acesso somente para o grupo admin.<br />
</li><br />
<li><br />
Após modificar o arquivo de configuração deve-se reiniciar o serviço: <code>service ssh restart</syntaxhighlight><br />
</li><br />
<li><br />
Criar um usuário na máquina servidora:<br />
<code>adduser alien</syntaxhighlight><br />
</li><br />
<li><br />
Logar como alien:<br />
<code>su alien</syntaxhighlight><br />
</li><br />
</ol><br />
<br />
===ETAPA 2 - Logando remotamente===<br />
<br />
<ol><br />
<li><br />
Para acessar o servidor basta digitar em um terminal: <br />
<code>ssh alien@ip_do_servidor. </syntaxhighlight> Será solicitado a senha.<br />
</li><br />
<li><br />
Confira que está "dentro" da máquina remota:<code>hostname</syntaxhighlight><br />
</li><br />
<li><br />
Confira os arquivos do diretório corrente:<code>ls -l</syntaxhighlight><br />
</li><br />
</ol><br />
<br />
<br />
===ETAPA 3 - Cópia Remota de aquivos===<br />
<br />
#Na máquina hospedeira/cliente, EM OUTRO TERMINAL, criar um arquivo qualquer usando um editor de texto:<code>gedit teste.txt &</syntaxhighlight><br />
#Envie o arquivo para a máquina servidora: <code>scp teste.txt alien@IP_MAQUINA_SERVIDORA:./</syntaxhighlight><br />
#No terminal onde está logado remotamente confira se o arquivo está copiado: <code>ls -l</syntaxhighlight><br />
#Mude o nome do arquivo: <code>mv teste.txt alfat.txt</syntaxhighlight><br />
#No terminal da máquina cliente traga novamente o arquivo: <code>scp alien@IP_MAQUINA_SERVIDORA:./alfa.txt .</syntaxhighlight><br />
#Confira se o arquivo foi copiado corretamente: <code>ls -l</syntaxhighlight><br />
<br />
==PARTE 2 - Configuração do Access Point na rede de 2.4Ghz==<br />
<br />
#Entrar na configuração do AP conforme aula anterior.<br />
#Conectara a WAN do AP na rede do laboratório e o PC em uma porta da LAN do AP.<br />
#Configurar a WAN para IP dinâmico.<br />
#Configurar a rede WIreless 2.4 Ghz:<br />
##Nome SSID: nome FIC-NomeAluno<br />
##Configurar canal AUTO e channel width para AUTO<br />
##Habilite o broadcast da rede.<br />
#Configurar segurança (Wireless Security) para WPA versão Automática, Criptografia AES e password ABCDEF<br />
#Configurar o DHCP na LAN para distribuir endereços entre 192.168.0.100 e 192.168.0.200<br />
#Salve as configurações<br />
#Reboote o roteador<br />
<br />
==Acessando a rede de dispostivo Celular==<br />
<br />
#Teste o acesso a rede a partir de um celular. No Androi ligue e desligue o wifi. Deve aparecer a lista de dispositivos.<br />
<br />
==Habilitando Filtros por MAC==<br />
<br />
*Na configuração da WLAN entre em Wireless MAC Filtering<br />
*Em Filtering Rules coloque Deny (negar)<br />
*Adicione um terminal que deseja bloquear o acesso. Utilize o MAC do seu celular (veja em configurações do telefone ou anote na opção Wireless Statistics)<br />
*Habilite o Filtro e tente se conectar<br />
<br />
OBS: Este filtro é interessante para ter maior segurança na rede, garantindo que somente dispositivos gabilitados possam acessá-la.<br />
<br />
==Coloque no ar a rede 5Ghz==<br />
<br />
Repita o procedimento da rede de 2.4Ghz e coloque-a no ar.<br />
<br />
Teste a conectividade com o celular.<br />
<br />
<br />
<br />
=AULA 19 - Dia 21/05/2019=<br />
<br />
==Objetivos==<br />
<br />
*Tópicos Adicionais sobre redes no Linux: Configuração Manual X NetworkManager<br />
**Opções de Acesso a Internet: ADSL, Cabo<br />
**Sistema de Arquivos em Rede: Samba Server<br />
*Relatório de Avaliação 1<br />
*Opções de Extensão da Rede Wireless<br />
<br />
==Tópicos Adicionais sobre redes no Linux==<br />
<br />
===Configuração da Rede no Linux - o NetworkManager===<br />
<br />
Ao longo do curso estudamos vários comandos para ver e modificar parâmetros de rede. Entretanto, em uma instalação padrão de um sistema Linux Ubuntu vamos verificar que existe um serviço de suporte a estas configurações que permite configurar interfaces graficamente e reconectar/escolher uma rede. Trata-se do NetworkManager. Ver alguns detalhes aqui [https://www.hardware.com.br/dicas/entendendo-networkmanager.html] e aqui[https://wiki.debian.org/pt_BR/NetworkManager]. Este serviço tenta fornecer a melhor conectividade possível usando as interfaces disponíveis. O serviço é composto por:<br />
<br />
*um processo do sistema (roda como serviço) monitorando constantemente as interfaces;<br />
*uma applet para interação com o usuário (canto direito da interface);<br />
<br />
O NetworkManager vai ignorar as configurações das interfaces realizadas em /etc/network/interfaces<br />
<br />
Teste o uso do NetworkManager. Clique no topo do desktop a direita e inspecione as interfaces disponíveis.<br />
<br />
Em algumas situações pode ser desejável desabilitar o NetworkManager. Na linha de comando pode ser executado:<br />
<br />
sudo service network-manager stop<br />
<br />
===Configurando interfaces de forma manual ===<br />
<br />
TEXTO baseado nas anotações do Prog.Marcelo Sobral:<br />
<br />
O arquivo ''/etc/network/interfaces'' contém declarações para configurar as interfaces de rede. Um exemplo de configuração básica contida nesse arquivo pode ser vista a seguir:<br />
<br />
<syntaxhighlight lang=text><br />
auto lo eth0<br />
iface lo inet loopback<br />
iface eth0 inet dhcp<br />
</syntaxhighlight><br />
<br />
Esse exemplo pode ser interpretado assim:<br />
* ''Linha 1'': declara que as interfaces ''lo'' e ''eth0'' devem ser ativadas automaticamente no boot. Se uma interface não aparecer em uma declaração como esta, então ela não será ativada. OBS: interface ativadas desta forma NÃO são controladas pelo ''NetworkManager''.<br />
* ''Linha 2'': configura a interface ''lo'' como sendo do tiupo ''loopback''. Essa é uma interface especial criada puramente em software (uma interface de rede virtual), usada para comunicação entre processos de um mesmo computador.<br />
* ''Linha 3'': configura a interface ''eth0'' de forma dinâmica usando [[GER-2010-1#DHCP|DHCP]]. A configuração de rede é solicitada usando a própria rede. Ness ecaso, deve existir algum equipamento ou computador nessa rede que seja um servidor DHCP, capaz de responder com uma mensagem contendo a configuração de rede a ser utilizada.<br />
<br />
<br />
O exemplo anterior é bastante simplificado, uma vez que a configuração de rede de fato é obtida dinamicamente com DHCP. Isso pode ser suficiente para computadores usados somente para acesso a Internet, mas não para computadores que sejam servidores. Nesse caso, é melhor definir uma configuração de rede estática, como mostrado a seguir:<br />
<br />
<syntaxhighlight lang=text><br />
auto lo eth0<br />
iface lo inet loopback<br />
iface eth0 inet static<br />
address 172.18.80.251<br />
netmask 255.255.128.0<br />
gateway 172.18.0.254<br />
dns-nameservers 191.36.8.2 191.36.8.3<br />
</syntaxhighlight><br />
<br />
<br />
A diferença em relação ao caso anterior está na declaração da interface ''eth0''. Ao invés de configurá-la com ''DHCP'', declararam-se todas as informações de rede. Assim, essa interface sempre será ativada com essas informações configuradas. No exemplo apresentado, as configurações de rede são:<br />
* ''address 172.18.80.251'': endereço IP da interface<br />
* ''netmask 255.255.128.0'': máscara de rede<br />
* ''gateway 172.18.0.254'': endereço do gateway (ou roteador ''default'')<br />
* ''dns-nameservers 191.36.8.2 191.36.8.3'': servidores DNS a serem utilizados (podem-se especificar um ou mais endereços IP)<br />
<br />
O [http://manpages.ubuntu.com/manpages/trusty/en/man5/interfaces.5.html manual do arquivo /etc/network/interfaces] apresenta muitos outros detalhes sobre possíveis configurações de rede.<br />
<br />
Antes da alteração de configuração de uma interface é interessante desativá-la:<br />
ifdown eth0<br />
Alterar o arquivo /etc/network/interfaces<br />
<br />
E na sequência ativá-la novamente:<br />
ifup eth0<br />
ou<br />
sudo /etc/init.d/networking restart<br />
<br />
O comando ifup vai consultar o arquivo e alterar as configurações. Indiretamente, o script networking também usa o ifup para ativar as configurações (e todas demais que forem realizadas).<br />
<br />
==Relatório Avaliativo 1==<br />
<br />
Criar um arquivo no OpenOffice nomeando-o SeuNomeSemEspaco-FICLinux-2019-A1<br />
<br />
Copiar e responder as questões abaixo:<br />
<br />
1.Faça um ifconfig na interface eth0. Cole um recorte da tela no espaço abaixo e faça um texto indicando qual o endereço de hardware associado a esta interface, qual o endereço IPv4 e qual a máscara de subrede.<br />
<br />
<br />
2.Faça um experimento usando o ping e o wireshark mostrando como o DNS atua para resolver o nome que está sendo "pingando". Informe em texto abaixo qual o IP do servidor DNS local e qual o IP do site que está sendo "pingado".<br />
<br />
<br />
3,Execute o laboratório do Netkit da forma e cole abaixo a figura da rede fornecida pelo netkit:<br />
<code><br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
<br />
# Hosts' interfaces to local routers<br />
<br />
r1[eth0]=lan0<br />
r1[eth1]=lan1<br />
<br />
pc1[eth0]=lan0<br />
pc2[eth0]=lan0<br />
pc3[eth0]=lan1<br />
</syntaxhighlight><br />
<br />
<br />
4.Configure todas as interfaces dos PC usando para lan0 o prefixo 50.50.50.0/24 e para lan1 use no lugar de 50 o dia de seu nascimento.<br />
Cole uma tela mostrando PC1 pingando PC3. <br />
<br />
5.Informe abaixo o MAC da eth0 do roteador.<br />
<br />
6.Usando o tcpdump na eth0 do roteador mostre que a entrega é indireta.<br />
<br />
==Estendendo a rede através da LAN usando segundo AP e WAN==<br />
<br />
Conecte um segundo AP (WAN do segundo AP a LAN do primeiro AP). Teste a conectividade colocando uma máquina Linux na LAN do segundo AP.<br />
Esta configuração deve funcionar mas impõe um overhead adicional devido ao NAT realizado duas vezes... <br />
<br />
DESAFIO: mostrar que o NAT está sendo duplicado.<br />
<br />
[[Arquivo:WLAN-2PAs-viaWAN.png]]<br />
<br />
==Estendendo a rede através da LAN usando segundo AP e LAN==<br />
<br />
Discuta com o colega ao lado e pense como poderia conectar o segundo AP via LAN. Uma configuração adicional será necessária.<br />
<br />
==Estendendo a rede através do Wireless (WDS)==<br />
<br />
Estude no manual como poderia estender a rede Sem Fio usando conexão via WDS.<br />
<br />
=AULA 20 - Dia 18/04/2019=<br />
<br />
*Tópicos Adicionais sobre redes no Linux:<br />
**Opções de Acesso a Internet: ADSL, Cabo<br />
**Sistema de Arquivos em Rede: Samba Server (http://www.guiafoca.org/cgs/guia/avancado/ch-s-samba.html)<br />
*Relatório Avaliativo 2<br />
<br />
==Relatório Avaliativo==<br />
<br />
===PARTE 1=== <br />
<br />
Usando a configuração abaixo do netkit2 e uma máquina Virtualbox devidamente configurada implementar a configuração abaixo:<br />
<br />
ATENÇÂO: Vamos substituir a VirtualBox por uma máquina Netkit executada em OUTRO PC com a configuração:<br />
<br />
INSTRUÇÔES para virtual box:<br />
*colocar rede como bridge<br />
*desabilitar o network manager<br />
sudo service network-manager stop<br />
*baixar a interface<br />
sudo ifconfig enp0s3 down<br />
*reconfigurar a interface (usar o endereço do seu grupo)<br />
sudo ifconfig enp0s3 50.50.50.11/24<br />
*colocar a rota direta (que se perdeu) (usar o endereço do seu grupo)<br />
sudo route add -net 50.50.50.0/24 dev enp0s3<br />
*colocar gateway default (usar o endereço do seu grupo)<br />
sudo route add default gateway 50.50.50.1<br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
<br />
pc1[type]=generic<br />
pc1[eth0]=uplink:bridge=eth0:ip=dhcp<br />
<br />
</syntaxhighlight><br />
<br />
<br />
[[Arquivo:Aval2-Parte1-FICLinux2019-2.png]]<br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
pc1[type]=generic<br />
<br />
pc1[eth0]=lan1<br />
<br />
r1[eth0]=uplink:bridge=eth0:ip=VER COM PROFESSOR<br />
r1[eth1]=lan2<br />
<br />
r2[eth0]=lan1<br />
r2[eth1]=lan2<br />
</syntaxhighlight><br />
<br />
Construir um doc conforme aula anterior com as seguintes informações:<br />
<br />
#Coloque a tela de um píng funcionando de R1 para PC1<br />
#Cole a tela da tabela de roteamento de R2<br />
#Cole a tela de um ping de uma máquina VirtualBox (netkit) no R1 (uplink)<br />
#Cole a tela de um ping funcionando uma máquina VirtualBox (netkit) no PC1<br />
<br />
Note que o gateway default da máquina virtual deverá ser reconfigurado para PC1.<br />
<br />
ADENDO: Coloque em R1 rotas para as redes dos PC1 dos demais grupos.<br />
<br />
===PARTE 2===<br />
<br />
Acrescente na sua rede um AP configurado como indicado abaixo:<br />
<br />
OBS: Para este exercício configuramos estaticamente todos os endereços para o lado do backbone (Laboratório). Usamos 50.50.50.0/24<br />
<br />
[[Arquivo:Aval2-Parte2-FICLinux2019-2.png]]<br />
<br />
<br />
=ATIVIDADE DE RECUPERAÇÃO 1=<br />
<br />
Refazer o relatório Avaliativo 1 proposto anteriormente. Enviar doc para o SIGA A<br />
<br />
=ATIVIDADE DE RECUPERAÇÃO 2=<br />
<br />
Registre em um DOC e faça um post no SIGA A colando a imagem das telas das saídas de cada comando!<br />
<br />
===Roteiro de atividades sobre o IPv6===<br />
<br />
A figura abaixo apresenta o diagrama esquemático da rede a ser montada/analisada. Observe que todos os IPv6 ''Global Unicast'' já estão definidos na mesma, são esses IPs que utilizaremos em nosso experimento.<br />
<br />
[[Arquivo:Diagrama_rede_IPv6.jpg]]<br />
<br />
#Crie em seu computador um arquivo com nome '''/home/aluno/IPv6.conf''', com o seguinte conteúdo: <syntaxhighlight lang=bash><br />
#Ligacao das maquinas nos dominios de colisao<br />
#Duas pequenas redes interligadas pelo backbone<br />
<br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=link0:ipv6=2001:bcc:faca:1::101/64<br />
pc2[eth0]=link1:ipv6=2001:bcc:cafe:1::102/64<br />
pc3[eth0]=HUB1:ipv6=2001:bcc:1f0:1::103/64<br />
pc4[eth0]=HUB1<br />
<br />
#Default Gateways definitions<br />
pc1[route]=default6:gateway=2001:bcc:faca:1::1<br />
pc2[route]=default6:gateway=2001:bcc:cafe:1::1<br />
pc3[route]=default6:gateway=2001:bcc:1f0:1::1<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
#Routers interfaces definitions<br />
r1[eth0]=backbone0:ipv6=2001:db8:dead:1::1/64<br />
r1[eth1]=link0:ipv6=2001:bcc:faca:1::1/64<br />
r1[eth2]=link1:ipv6=2001:bcc:cafe:1::1/64<br />
<br />
r2[eth0]=backbone0:ipv6=2001:db8:dead:1::2/64<br />
r2[eth1]=HUB1:ipv6=2001:bcc:1f0:1::1/64<br />
<br />
#Routers definitions<br />
r1[route]=2001:bcc:1f0:1::0/64:gateway=2001:db8:dead:1::2<br />
r2[route]=2001:bcc:faca:1::0/64:gateway=2001:db8:dead:1::1<br />
r2[route]=2001:bcc:cafe:1::0/64:gateway=2001:db8:dead:1::1<br />
</syntaxhighlight><br />
#Tenha certeza que o Netkit2 estja atualizado: General >> Update.<br />
#Rode o NetKit em seu computador. Em um terminal digite: <syntaxhighlight lang=bash><br />
netkit2 & </syntaxhighlight><br />
#No menu '''File''' - '''Load and Run''', procure o arquivo '''/home/aluno/IPv6.conf''' e clique em OK. Abrirá uma janela com 6 abas, onde cada uma delas é um terminal de configuração do respectivo equipamento: '''pc1-4''' ou '''r1-2'''.<br />
#Observe que o '''pc4''' não está com sua interface configurada.<br />
#Ao clicar no menu '''File''' - '''Graph''', pode-se ter uma visão da rede a ser simulada e conferir se é equivalente ao diagrama proposto.<br />
#Faça um '''ping6''' entre o '''pc1''' ao '''pc3''': <syntaxhighlight lang=bash><br />
ping6 -c4 2001:bcc:1f0:1::103 </syntaxhighlight><br />
#Faça um '''ping6''' entre o '''pc1''' e '''pc2'''.<br />
#No '''pc4''' use o seguinte comando para adicionar o endereço IPv6 à interface de rede: <syntaxhighlight lang=bash><br />
ip addr add 2001:bcc:1f0:1::104/64 dev eth0 </syntaxhighlight><br />
#No '''pc4''', acrescente o ''default gateway'' com o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add default via 2001:bcc:1f0:1::1 dev eth0 </syntaxhighlight><br />
#No '''pc1''' use o seguinte comando para verificar como ficou a configuração dos endereços da interface de rede. O resultado é similar ao apresentado pelo comando '''ifconfig''': <syntaxhighlight lang=bash><br />
ip addr show dev eth0 </syntaxhighlight><br />
#Todo o roteamento está pronto, mas caso desejássemos poderíamos acrescentar rotas com comando similares aos já utilizados. Por exemplo, no '''r1''', para adicionar uma rota estática para a rede dos '''pc3''' e '''pc4''' utilizaríamos o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add 2001:bcc:1f0:1::/64 via 2001:db8:dead:1::2 dev eth0 </syntaxhighlight><br />
#Confira as rotas estabelecidas em todos os ''hosts'' com o comando abaixo. <br />
##São coerentes com os dados apresentados no diagrama acima?<syntaxhighlight lang=bash><br />
ip -6 route show </syntaxhighlight><br />
#No '''pc1''' use os seguintes comandos para ver a rota para alguns vizinhos: <syntaxhighlight lang=bash><br />
traceroute6 2001:bcc:1f0:1::103<br />
traceroute6 2001:bcc:1f0:1::104 </syntaxhighlight><br />
#*Anote as rotas.<br />
#Deixe um '''ping6''' entre o '''pc1''' ao '''pc3''' rodando: <syntaxhighlight lang=bash><br />
ping6 2001:bcc:1f0:1::103 </syntaxhighlight><br />
<br />
=ATIVIDADE DE RECUPERAÇÃO 3=<br />
<br />
Registre em um DOC e faça um post no SIGA A colando a imagem das telas das saídas de cada comando! Coloque também a resposta as perguntas.<br />
<br />
===Objetivos===<br />
<br />
*Familiarizar-se com o UDP<br />
*Entender a estrutura do pacote UDP<br />
*Entender o conceito de portas<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/UDP%20Basico.pdf Introdução a camada de transporte e UDP básico]<br />
<br />
===Parte 1 - Fluxo único UDP===<br />
<br />
#Combinar equipes com dois computadores para execução do experimento.<br />
#*Uma equipe escutará na porta 5000 e a outra equipe transmitirá uma mensagem nessa porta. Os processos de transmissão e recepção podem ocorrer simultaneamente, em terminais distintos.<br />
#*Cada equipe deve identificar os IPs ('''IP_DEST''') das máquinas de seus pares.<br />
#Cada equipe deve abrir uma Janela de terminal.<br />
#Cada equipe deve preparar o '''Wireshark''', interfaces '''any''', para escuta das portas no protocolo UDP usando um filtro:<syntaxhighlight lang=bash><br />
udp.port==5000</syntaxhighlight><br />
#A equipe da escuta na porta 5000 executa no terminal: <syntaxhighlight lang=bash><br />
netcat -u -l -p 5000 </syntaxhighlight><br />
#A equipe que irá transmitir para a porta 5000 executa no terminal: <syntaxhighlight lang=bash><br />
netcat -u IP_DEST 5000 </syntaxhighlight><br />
#*Em seguida escreve no terminal uma mensagem de até 20 caracteres, ao teclar <Enter> a mensagem será enviada.<br />
#*O wireshark deve ter capturado os pacotes UDP <br />
#Identifique e anote os seguintes dados na captura do wireshark:<br />
#*IP FONTE e DESTINO<br />
#*PORTAS FONTE E DESTINO para ambas comunicações<br />
#*Campo de protocolo no pacote IP<br />
#*Campo de tamanho (anote o tamanho) e ''checksum'' no pacote (datagrama) UDP<br />
#*O campo de dados no pacote UDP<br />
#Troquem os papéis das equipes: quem houvia agora transmite mensagens.<br />
#Cada equipe pode transmitir sequencialmente várias mensagens, devendo identificar múltiplos datagramas UDP.<br />
#PERGUNTAS baseadas na captura:<br />
##Qual o tamanho de cada campo do cabeçalho do pacote UDP?<br />
##Qual o tamanho máximo do número de porta?<br />
##Qual o tamanho máximo da área de dados (payload) do pacote?<br />
##Qual o número identificador de protocolo UDP no pacote IP? <br />
##Em algum momento foi identificado algum procedimento para estabelecimento de conexão? <br />
##Em algum campo do UDP existe numeração de mensagens?<br />
<br />
=AULA 20 - Dia 18/04/2019=<br />
<br />
{{collapse bottom}}<br />
<br />
==Curso FIC Linux 2018==<br />
<br />
{{collapse top|Semestre 2018-2 - Prof. André D'Amato}}<br />
<br />
== Introdução ao Sistema Operacional Linux ==<br />
<br />
'''10/09/18: Aula01'''<br />
<br />
Apresentação da Disciplina, Introdução a Informática e Memória e Armazenamento<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula01.pdf Aula 01]<br />
<br />
{{collapse bottom}}<br />
<br />
==Curso FIC Linux 2016==<br />
<br />
{{collapse top|Semestre 2016-2 - Prof. Luciano Barreto}}<br />
<br />
== Introdução ao Sistema Operacional Linux ==<br />
<br />
'''04/10/16: Aula01'''<br />
<br />
Apresentação da Disciplina, Introdução a Informática e Memória e Armazenamento<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula01.pdf Aula 01]<br />
<br />
'''06/10/16: Aula 02'''<br />
<br />
Introdução ao Linux, Sistema de Arquivos e Conhecendo o Terminal<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula02.pdf Aula 02]<br />
<br />
''' 11/10/2016: Aula 03'''<br />
<br />
Continuação Comandos no Terminal<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula03.pdf Aula 03]<br />
<br />
''' 13/10/2016: Aula 04''' <br />
<br />
Continuação Comandos no Terminal<br />
<br />
''' 18/10/2016: Aula 05''' <br />
<br />
Lista de Exercícios<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/ficlinux-aula05-exercicios.pdf Aula 05 - Lista de Exercícios]<br />
<br />
''' 20/10/2016: Aula 06'''<br />
<br />
Introdução ao Gerenciamento de Processos<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula06-processos.pdf Aula 06 - Gerenciamento de Processos]<br />
<br />
''' 25/10/2016: Aula 07''' <br />
<br />
Gerenciamento de Usuários<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula07-usuariosgrupos.pdf Aula 07 - Gerenciamento de Usuários]<br />
<br />
Permissionamento<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula07-permissionamento.pdf Aula 07 - Permissionamento]<br />
<br />
''' 27/10/2016: Aula 08'''<br />
<br />
Continuação Permissionamento<br />
<br />
Instalação Linux<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula8-instalacao.pdf Aula 08 - Instalação Linux] <br />
<br />
''' 01/11/2016: Aula 09'''<br />
<br />
Continuação Instalação Linux<br />
<br />
Instalação de Pacotes via Apt<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula9-pacotes.pdf Aula 09 - Instalação Pacotes] <br />
<br />
''' 03/11/2016: Aula 10'''<br />
Continuação Lista Exercícios (47 - 60)<br />
<br />
=AULA 11 - Dia 18/04/2019=<br />
<br />
=AULA 12 - Dia 18/04/2019=<br />
<br />
=AULA 13 - Dia 18/04/2019=<br />
<br />
=AULA 14 - Dia 18/04/2019=<br />
<br />
=AULA 15 - Dia 18/04/2019=<br />
<br />
=AULA 16 - Dia 18/04/2019=<br />
<br />
=AULA 17 - Dia 18/04/2019=<br />
<br />
=AULA 18 - Dia 18/04/2019=<br />
<br />
=AULA 19 - Dia 18/04/2019=<br />
<br />
=AULA 20 - Dia 18/04/2019=<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top|Semestre 2016-1 - Prof. Luciano Barreto}}<br />
<br />
= Diário de Aulas 2016 - 1 =<br />
<br />
==29/03/16: Apresentação do curso==<br />
Apresentação do curso, Visão geral de funções, responsabilidades e estruturas de um SO.<br />
<br />
==31/03/16: Introdução a Sistema de Arquivos e Terminal==<br />
Estrutura do Sistema de Arquivos Linux, Introdução a comandos no Terminal.<br />
<br />
==04/04/16: Continuação Terminal==<br />
Continuação de comandos no terminal, redirecionamento de saída e caracteres coringa.<br />
<br />
==07/04/16: Introdução a Processos e Usuários==<br />
Conhecendo Processos e Gerenciamento de usuários<br />
<br />
==12/04/16: Lista de Exercícios de Comandos no Terminal==<br />
<br />
[http://bellard.org/jslinux/ Emulador de Terminal no navegador (demora um pouquinho pra abrir)]<br />
<br />
==14/04/16: Usuários, Grupos e Permissões==<br />
Administração de usuários, grupos e adicionando permissões a arquivos.<br />
<br />
==19/04/16: Instalação do Linux==<br />
Instalação do Sistema Linux em modo texto, gráfico e dualboot.<br />
<br />
==26/04/16: Introdução ao Shell Script==<br />
Introdução ao Shell Script<br />
<br />
==28/04/16: Continuação ao Shell Script==<br />
Introdução ao Shell Script<br />
<br />
==03/05/16: Lista de Exercícios==<br />
Lista de Exercícios até a aula de 28/04/16<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top|Semestre 2015-2}}<br />
<br />
*'''Professores:''' [[Ana Paula Rosa Negri]] e [[Francisco de Assis Souza dos Santos]]<br />
<br />
{| style="background-color:#ABCDEF; font-family:verdana,Arial, Helvetica, sans-serif; font-size:100%; margin:0; border: 1px solid #C7D0F8; padding:7px 7px 0px 7px; text-align:center;" width="100%"<br />
| | Bem-vindo ao<br /><br />
<span style="font-size:200%">'''Curso de Formação Continuada de Configuração de Redes de Computadores Linux''' <br />do Instituto Federal de Santa Catarina - Campus São José</span><br />
|}<br />
<br />
Introdução ao Sistema Operacional Linux<br />
<br />
*'''Professores:''' [[Ana Paula Rosa Negri]] e [[Francisco de Assis Souza dos Santos]]<br />
*'''Encontros:''' Terças e quintas das 19:00 às 22:00 no Laboratório de Apoio ao Ensino.<br />
<br />
*[[ISL-FicLinux_(Plano_de_Ensino)| Plano de Ensino]]<br />
*[[Cronograma de atividades (ISL-FicLinux) | Cronograma]]<br />
<br />
= Diário de Aulas 2015 =<br />
== 13/10 ==<br />
'''Parte 1:'''<br />
Slides da aula:<br />
[[Arquivo:introducao.pdf]]<br />
<br>Exercício sobre taxa de transferência:<br />
[[Arquivo:Exercicio_taxa_Transferencia.pdf]]<br />
<br><br />
<br />
'''Parte 2:'''<br />
Slides da Aula:<br />
[[Arquivo:LinuxModoTexto.pdf]]<br />
<br>Exercícios sobre comandos básicos do Linux:<br />
[[Arquivo:ExercícioLinuxTexto.pdf]]<br />
<br />
== 15/10 ==<br />
'''Parte 3:'''<br />
Slides da Aula:<br />
[[Arquivo:Parte3.pdf]]<br />
== 20/10 ==<br />
'''Parte 4:'''<br />
Slides caracteres coringas: [[Arquivo:Coringas.pdf]]<br />
<br />
Exercícios caracteres coringas: [[Arquivo:Exercício CB03 Pokemon.pdf]]<br />
<br />
'''Parte 5:'''<br />
Sildes Redirecionamento: [[Arquivo: Redirecionamento.pdf]]<br />
<br />
Exercícios redirecionamento e pipe: [[Arquivo: ex_pipe.pdf]]<br />
<br />
== 22/10 ==<br />
'''Parte 6:'''<br />
Slides Processos: [[Arquivo:FICLinux_Processos.pdf]]<br />
<br />
== 27/10 ==<br />
'''Parte 7:''''<br />
Slides Usuários e Grupos: [[Arquivo:UserGroup.pdf]]<br />
<br>Exercícios: [[Arquivo:usuarios.pdf]]<br />
<br>Exercícios (.odt): [[Arquivo:usuarios.odt]]<br />
<br />
== 29/10 ==<br />
'''Parte 8:'''<br />
Slides Introducao a Redes: [[Arquivo:FICLinux_Introducao_Redes.pdf]]<br />
<br />
== 03/11 ==<br />
<br />
'''Parte 9:'''<br />
Slides permissionamento: [[Arquivo:permissionamento.odp]]<br><br />
Exercícios permissionamento: [[Arquivo: Exercício Perm02.odt]]<br><br />
Outro exercício permissionamento: [[Arquivo: Exercício Perm04 GatosRatosCães.odt]]<br />
<br />
== 05/11 ==<br />
<br />
'''Parte 10:'''<br />
Slides Redes - Broadcast: [[Arquivo:FICLinux_Introducao_Redes_Broadcast_01.pdf]]<br><br />
<br />
== 10/11 ==<br />
<br />
'''Parte 11:'''<br />
Slides Script: [[Arquivo:Scripts do Linux.odp]]<br />
<br>Exercícios Scripts: [[Arquivo:Exercício Scripts01 pdfmerger.odt]]<br />
<br />
== 12/11 ==<br />
<br />
'''Parte 12:'''<br />
Introdução para comandos em Bash: [[Arquivo:Introdução ao Shell_2015_1.pdf]]<br />
<br />
{{collapse bottom}}</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)&diff=162008Curso Técnico Integrado de Telecomunicações - Redes de Computadores (RCO)2019-10-03T19:56:01Z<p>127.0.0.1: /* Laboratórios */</p>
<hr />
<div>__NOTOC__<br />
<br />
{{DivulgueEngtelecom}}<br />
==Informações Gerais==<br />
*[[RCO-IntTel|Carga horária, Ementas, Bibliografia]]<br />
*[[RCO-IntTel (Plano de Ensino) | Plano de Ensino]]<br />
*[[Cronograma de atividades (RCO-IntTel) | Cronograma de atividades]]<br />
<br />
==Edições==<br />
*[[RCO60803 2019-1|RCO60803 2019-1 - Trabalho dirigido - Prof. Odilson Tadeu Valle]]<br />
*[[RCO60803 2018-2|RCO60803 2018-2 - Prof. Odilson Tadeu Valle / Prof. Eraldo Silveira e Silva]]<br />
*[[RCO60803 2018-1|RCO60803 2018-1 - Prof. Odilson Tadeu Valle / Prof. Eraldo Silveira e Silva]]<br />
*[[RCO60803 2017-2|RCO60803 2017-2 - Prof. Odilson Tadeu Valle / Prof. Eraldo Silveira e Silva]]<br />
*[[RCO60803 2017-1|RCO60803 2017-1 - Prof. Juliano de Souza / Prof. Eraldo Silveira e Silva]]<br />
*[[RCO60803 2016-2|RCO60803 2016-2 - Prof. Juliano de Souza / Prof. Luciano Barreto]]<br />
*[[RCO60803 2016-1|RCO60803 2016-1 - Prof. Fernando Rodrigues Santos / Prof. Juliano de Souza]]<br />
*[[RCO60803-2015-2|RCO60803 2015-2 - Prof. Simara Sonaglio]]<br />
*[[RCO60803-2015-1|RCO60803 2015-1 - Prof. Arliones Hoeller / Prof. Túlio Ribeiro]]<br />
*[[RCO60803-2014-2|RCO60803 2014-2 - Prof. Arliones Hoeller / Prof. Tomás Grimm / Prof. José Clair]]<br />
<br />
= Material de apoio =<br />
<br />
==''Applets'' do Kurose==<br />
Vários [http://wps.pearsoned.com/ecs_kurose_compnetw_6/216/55463/14198700.cw/ aplicativos] com representação dinâmica de características das redes de computadores.<br />
==Transparências utilizadas durante as aulas==<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/slides-kurose-cap1.pdf Capítulo 1 - Introdução]<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/slides-kurose-cap2.pdf Capítulo 2 - Camada de Aplicação]<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/PPTs%20-%20Cap%C3%ADtulo%202%20-%20FTP%20-%20Email%20-%20P2P.pdf Capítulo 2 - Camada de Aplicação - FTP + EMAIL + P2P]<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/slides-kurose-cap3.pdf Capítulo 3 - Camada de Transporte]<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/PPTs%20-%20Cap%C3%ADtulo%204%20A%20camada%20de%20REDE.pdf Capítulo 4 - Camada de Rede]<br />
<br />
==Slides de Outras Universidades==<br />
<br />
*[https://www.google.com.br/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0ahUKEwiO0aDJu_LTAhWJlZAKHX8JA2wQFggjMAA&url=http%3A%2F%2Fwww.eecs.yorku.ca%2Fcourse_archive%2F2015-16%2FW%2F3214%2FCSE3214_14_TCP_2_2016_posted_part2.pdf&usg=AFQjCNEJh3yITWuyOPZ17bbObT54JqrLCw&sig2=jJwHLo13iooIUaI5F2m-kA TCP Error Control- EECS - LASSONDE]<br />
*[https://www.google.com.br/url?sa=t&rct=j&q=&esrc=s&source=web&cd=2&cad=rja&uact=8&ved=0ahUKEwiO0aDJu_LTAhWJlZAKHX8JA2wQFggpMAE&url=http%3A%2F%2Fwww.eecs.yorku.ca%2Fcourse_archive%2F2015-16%2FW%2F3214%2FCSE3214_14_TCP_2_2016_posted_part1.pdf&usg=AFQjCNHNz8hZ4GHyiDZkcMgomCQBR4KTaA&sig2=nS8450rR2x6C_EM9tT0yWw TCP- Flow and Error Control - LASSONDE]<br />
*[https://www.google.com.br/url?sa=t&rct=j&q=&esrc=s&source=web&cd=3&ved=0ahUKEwjUvtPAmJjUAhXHHZAKHfSBAEgQFghCMAI&url=http%3A%2F%2Fwww.eecs.yorku.ca%2Fcourse_archive%2F2015-16%2FW%2F3214%2FCSE3214_14_TCP_3_2016_posted.pdf&usg=AFQjCNHFkmBZT2Pn_G6e-AuDvJHL6FuZzg&sig2=UxXTDU_OKoMp2jC3K1O-jg Congestion Control - LASSONDE]<br />
*[https://www.cpe.ku.ac.th/~cpj/204325/ Slides/Aula Faculty of Engineering, Kasetsart University]<br />
<br />
== Curiosidades ==<br />
<br />
* [http://www.pop-sc.rnp.br/publico/monitoramento.php Monitoramento do tráfego RNP - PoP-SC]<br />
* [http://memoria.rnp.br/ceo/trafego/panorama.php Monitoramento do tráfego RNP - Nacional]<br />
* [http://www.redclara.net/index.php/pt/red/redclara/topologia-actual-de-la-red Rede Clara Internacional]<br />
* [https://eventos.rnp.br/sites/default/files/activity/activity-presentation/apresentacao_wrnp_2017_eduardo_grizenid_v_1.2.pdf Futura infraestrutura de rede da RNP]<br />
* [https://www.youtube.com/watch?v=IlAJJI-qG2k Animated map shows the undersea cables that power the internet]<br />
* [http://submarine-cable-map-2018.telegeography.com/ Submarine Cable Map 2018]<br />
* [https://www.youtube.com/watch?v=A5dD2x2iQx8 ''History of the Internet'' - legendado]<br />
* [https://www.youtube.com/watch?v=O_xG0ay5Vqs ''Warriors of the Net'' - legendado]<br />
* [https://www.youtube.com/watch?v=1G3SUTmioQE ''Browser Wars'' - legendado]<br />
* [https://www.youtube.com/watch?v=0nz-lcuv3TM ''Browser Wars'' - dublado]<br />
* [https://db-ip.com/200.135.37.65 Localização geográfica de IPs]<br />
* [http://ipv6.br/ '''IPv6 no Brasil''']<br />
* [http://ipv6.br/lab/ Laboratório de IPv6 - Livro didático contendo vários roteiros para entendimento do IPv6]<br />
* [https://www.google.com/intl/pt-BR/ipv6/statistics.html#tab=per-country-ipv6-adoption&tab=per-country-ipv6-adoption Estatísticas Google sobre IPv6]<br />
<br />
=Laboratórios=<br />
<br />
; teste<br />
<br />
{{Collapse top |Laboratório 1 - Ferramentas de Rede e Conceitos Básicos}}<br />
<br />
===Objetivos===<br />
<br />
*Familiarização com a infraestrutura dos laboratórios de redes<br />
*Familiarização com ferramentas de rede: ifconfig, ping, traceroute;<br />
*Desenvolver a noção de endereçamentos de rede IP e de endereço de hardware (MAC)<br />
*Desenvolver a noção de rotas em redes IP<br />
*Testar a conectividade IP com ping<br />
<br />
===Conceitos introdutórios para uso do laboratório===<br />
<br />
<br />
====Estrutura do Laboratório====<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/Ferramentas%20de%20rede%20e%20conceitos%20basicos.pdf Conceitos Básicos]<br />
<br />
[http://tele.sj.ifsc.edu.br/~eraldo/AULAS/2018-2/RCO-INTEGRADO/MACxIP.pdf Endereçamento MAC x Endereçamento IP]<br />
<br />
A rede do laboratório em uso segue o modelo apresentado no diagrama da Figura 1 (endereçamento pode ser diferente).<br />
<br />
[[Arquivo:Diagrama_rede_IFSC_lab_redes_I.jpeg |thumb | 400px| Figura 1 - Diagrama da rede do laboratório]]<br />
<br />
Os Laboratórios de Redes de Computadores estão equipados com N+1 (N = número de computadores para alunos) computadores conectados em rede e com acesso a Internet. A rede local do laboratório tem endereço IP 192.168.1.0/24. A máscara de rede '''/24''' indica que o último ''byte'' do endereço é utilizado para identificar cada máquina, por exemplo 192.168.1.1, 192.168.1.2, etc.<br />
<br />
===Roteiro de atividades===<br />
====Parte 1: Observando interfaces do sistema com ifconfig====<br />
O aplicativo '''ifconfig''' pode ser utilizado para visualizar a configuração ou configurar uma interface de host em redes TCP/IP. Se nenhum argumento for passado na chamada do '''ifconfig''', o comando mostra a configuração atual de cada interface de rede.<br />
<br />
NOTA: o ifconfig está sendo substituído pelo comando ip. A última versão do Uuntu já não traz mais o ifconfig por default.<br />
<br />
Consultar as páginas ''man ifconfig'' do Linux para maiores detalhes sobre o funcionamento deste aplicativo, o qual permite ativar/desativar a interface, configurar o endereço IP, definir o tamanho da MTU, redefinir o endereço de hardware se a interface suporta, redefinir a interrupção utilizada pelo dispositivo, entre outros.<br />
<br />
<br />
#Analisando os dados obtidos do seguinte exemplo <syntaxhighlight lang=bash>ifconfig <br />
eth0 Link encap:Ethernet Endereço de HW 64:51:06:1a:f3:da <br />
inet end.: 172.18.18.14 Bcast:172.18.63.255 Masc:255.255.192.0<br />
endereço inet6: fe80::6651:6ff:fe1a:f3da/64 Escopo:Link<br />
UP BROADCAST RUNNING MULTICAST MTU:1500 Métrica:1<br />
pacotes RX:415237 erros:0 descartados:0 excesso:0 quadro:0<br />
Pacotes TX:118109 erros:0 descartados:0 excesso:0 portadora:0<br />
colisões:0 txqueuelen:1000 <br />
RX bytes:364658695 (364.6 MB) TX bytes:18315199 (18.3 MB)<br />
IRQ:18 <br />
<br />
lo Link encap:Loopback Local <br />
inet end.: 127.0.0.1 Masc:255.0.0.0<br />
endereço inet6: ::1/128 Escopo:Máquina<br />
UP LOOPBACK RUNNING MTU:65536 Métrica:1<br />
pacotes RX:6688 erros:0 descartados:0 excesso:0 quadro:0<br />
Pacotes TX:6688 erros:0 descartados:0 excesso:0 portadora:0<br />
colisões:0 txqueuelen:0 <br />
RX bytes:1057934 (1.0 MB) TX bytes:1057934 (1.0 MB) </syntaxhighlight><br />
##O sistema em questão possui duas interfaces de rede: '''eth0''' e '''lo'''<br />
##'''Link encap:Ethernet''': Configuração da interface '''Eth'''ernet 0 (primeira)<br />
##'''Endereço de HW 64:51:06:1a:f3:da''': É o endereço da placa de rede, camada 2<br />
##'''inet end.: 172.18.18.14 Bcast:172.18.63.255 Masc:255.255.192.0''': Endereço IPv4 associado a interface, seu respectivo endereço de ''broadcast'' e mascara de rede<br />
##endereço inet6: fe80::6651:6ff:fe1a:f3da/64 Escopo:Link: Endereço IPv6 de escopo local gerado por autoconfiguração<br />
##'''UP BROADCAST RUNNING MULTICAST''': Significa que a interface está ativa (UP), responde a requisições de broadcast (pode ser desabilitado no kernel) e também pode ser associada a tráfegos ''multicast''<br />
##'''MTU: 1500''': ''Maximum Transfer Unit'' – Tamanho máximo do pacote suportado pelo enlace que é do tipo Ethernet<br />
##Os demais parâmetros são estatísticas da respectiva interface, como por exemplo, pacotes transmitidos, recebidos etc<br />
##A interface '''lo''': Qualquer tráfego que um computador envie em uma rede ''loopback'' é endereçada ao mesmo computador. O endereço IP mais usado para tal finalidade é 127.0.0.1 no IPv4 e ::1 no IPv6. O nome de domínio padrão para tal endereço é ''localhost''. Em sistemas Unix, a interface loopback é geralmente chamada de lo ou lo0.<br />
#Agora utilize o comando '''ifconfig''' para verificar o estado de suas interfaces e responda:<br />
##Quantas e quais interfaces de rede sua máquina possui? Liste.<br />
##Quais são os endereços da camada 2 atribuído as mesmas? De onde o sistema obteve esses endereços?<br />
##Quais são os endereços IPv4? De onde o sistema obteve esses endereços?<br />
##Suas interfaces tem IPv6 configurado? Qual o endereço e escopo dos mesmos? Como foram obtidos? Qual o alcance (é roteável) do mesmo?<br />
##Use o link *[http://jodies.de/ipcalc Verificando a estrutura do endereço IP] para explorar a estrutura do seu endereço IPv4.<br />
<br />
====Parte 2: Testando a conectividade com o ping====<br />
<br />
Aplicativo '''ping''' permite a um usuário verificar se um ''host'' remoto está ativo. É bastante utilizado para detectar problemas de comunicação na rede.<br />
O '''ping''' está baseado no envio de mensagens de solicitação de eco (''echo request'') e de resposta de eco (''echo reply''). Estas mensagens fazem parte do rol de mensagens do protocolo ICMP, que é um protocolo de reportagem de erros, a ser estudado mais tarde, componente do protocolo IP.<br />
<br />
O '''ping''' é um dos principais comandos a disposição do administrador de rede no sentido de verificar a conectividade em rede. Por exemplo, se houver resposta de um ping a partir de um servidor remoto, significa que a máquina local está rodando corretamente o TCP/IP, o enlace local está funcionando corretamente, o roteamento entre a origem e o destino está operando, e por fim, a máquina remota também está rodando corretamente o TCP/IP.<br />
<br />
Consultar as páginas ''man'' do ping para verificar as possibilidades de uso deste aplicativo.<br />
<br />
#Exemplo 1: <syntaxhighlight lang=bash><br />
ping 191.36.0.94<br />
PING 191.36.0.94 (191.36.0.94) 56(84) bytes of data.<br />
64 bytes from 191.36.0.94: icmp_seq=1 ttl=60 time=2.46 ms<br />
64 bytes from 191.36.0.94: icmp_seq=2 ttl=60 time=0.513 ms<br />
64 bytes from 191.36.0.94: icmp_seq=3 ttl=60 time=0.573 ms<br />
64 bytes from 191.36.0.94: icmp_seq=4 ttl=60 time=0.558 ms<br />
^C<br />
--- 191.36.0.94 ping statistics ---<br />
4 packets transmitted, 4 received, 0% packet loss, time 3001ms<br />
rtt min/avg/max/mdev = 0.513/1.026/2.463/0.830 ms </syntaxhighlight><br />
<br />
##No exemplo foram enviados quatro pacotes ICMP, cada um com um número de seqüência (''icmp_seq''), os quais foram recebidos com sucesso com o tempo de viagem assinalado (''time'')<br />
##Cada pacote tem ainda um tempo de vida (''ttl'' – ''time to live''), o qual é decrementado em cada roteador, sendo o pacote descartado quando chegar a zero; isto evita pacotes perdidos na rede<br />
##Quando o ping é interrompido ('''CRTL-C'''), uma estatística é apresentada indicando o percentual de pacotes transmitidos, recebidos e perdidos<br />
##O tempo de viagem (''rtt'' – ''round trip time'') mínimo (''min''), médio (''avg'') e máximo (''max'') é calculado, assim como o desvio padrão (''mdev'')<br />
#Como exercício envie '''ping''' para diferentes ''hosts'' e compare os tempos de resposta:<br />
##no endereço local de loopback;<br />
##máquina de um colega do laboratório;<br />
##servidor e roteador da rede da escola;<br />
##servidores externos: <syntaxhighlight lang=bash><br />
www.ifsc.edu.br<br />
www.uol.com.br<br />
www.nasa.com </syntaxhighlight> e explique as possíveis diferenças entre os tempos de resposta dos ping realizados.<br />
#Consulte as páginas ''man'' e teste o '''ping''' com os parâmetros abaixo e descreva suas funcionalidades:<br />
##-c count<br />
##-i intervalo<br />
##-s packetsize<br />
##-t ttl (para um site distante inicie com 1 e vá incrementando, observe as mensagens)<br />
#Observe que também é possível realizar ping em endereços no formato IPv6, por exemplo: <syntaxhighlight lang=bash> ping6 www.sj.ifsc.edu.br </syntaxhighlight><br />
#Tente o ping6 para outros sites.<br />
<br />
====Parte 3: Verificando rotas com o traceroute====<br />
O '''traceroute''' é capaz de traçar uma rota aproximada entre dois ''hosts''. Este comando usa mensagens ICMP. Para determinar o nome e o endereço dos roteadores entre a fonte e o destino, o traceroute na fonte envia uma série de datagramas IP ordinários ao destino. O primeiro datagrama tem o TTL (''time to live'' – tempo de vida) igual a 1, o segundo 2, o terceiro 3, e assim por diante, e inicia temporizadores para cada datagrama. Quando o enésimo datagrama chega ao enésimo roteador, este verifica que o tempo de sobrevida do datagrama acaba de terminar. Pelas regras do IP, o datagrama é então descartado e uma mensagem ICMP de advertência tempo de vida excedido é enviada a fonte com o nome do roteador e seu endereço IP. Quando a resposta chega de volta a fonte, a mesma calcula o tempo de viagem em função dos temporizadores.<br />
<br />
O '''traceroute''' envia datagramas IP encapsulados em segmentos UDP a um host destino. Todavia escolhe um número de porta destino com um valor desconhecido (maior que 30000), tornando improvável que o host destino esteja usando esta porta. Quando o datagrama chega ao destino uma mensagem ICMP porta inalcançável é gerada e enviada a origem. O programa traceroute precisa saber diferenciar as mensagens ICMP recebidas – tempo excedido e porta inalcançável – para saber quando a rota foi concluída.<br />
<br />
#Exemplo: <syntaxhighlight lang=bash><br />
sudo traceroute -I 200.135.37.65<br />
traceroute to 200.135.37.65 (200.135.37.65), 30 hops max, 60 byte packets<br />
1 192.168.1.1 (192.168.1.1) 0.225 ms 0.216 ms 0.368 ms<br />
2 172.18.0.254 (172.18.0.254) 1.236 ms 1.235 ms 1.343 ms<br />
3 hendrix.sj.ifsc.edu.br (200.135.37.65) 1.331 ms 1.313 ms 1.414 ms </syntaxhighlight><br />
O exemplo mostra a rota dos pacotes entre um computador do Lab. Redes (192.168.1.1) e o servidor ''hendrix'' (200.135.37.65). Observe que para cada roteador são realizados três amostras de tempo de ida e volta. Veja pelo mapa da rede do Campus São José que entre estes dois computadores, sistemas finais, existem dois roteadores intermediários, máquina do professor e Switch camada 3 (VLANs).<br />
#Traçar a rota dos pacotes entre seu computador e diferentes hosts:<br />
##máquina de um colega do laboratório<br />
##servidor e roteador da rede da escola<br />
##servidores externos.<br />
#Explique as possíveis diferenças entre os tempos de resposta de cada uma das amostras do '''traceroute'''<br />
#Explique as linhas com o caracter *.<br />
#Fazendo uso das ferramentas desse laboratório, refaça o diagrama da rede do campus apontando claramente os novos endereços IPs associados aos roteadores.<br />
#Observe que também é possível realizar traceroute em endereços no formato IPv6, por exemplo: <syntaxhighlight lang=bash> sudo traceroute -I6 ipv6.br </syntaxhighlight><br />
#Tente o traceroute no IPv6 para outros sites.<br />
<br />
====Referências adcionais====<br />
<br />
* [http://linux-ip.net/html Guia de Administração da Camada IP no Linux<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 2 - Wireshark e encapsulamento}}<br />
<br />
===Objetivos===<br />
<br />
*Familiarização com o ''sniffer'' de rede WireShark<br />
*Observar o comportamento do ''ping'' e se familiarizar com o processo de encapsulamento;<br />
<br />
====WireShark====<br />
2005 KUROSE, J.F & ROSS, K. W. Todos os direitos reservados <br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/Wireshark%20e%20encapsulamento.pdf Wireshark e encapsulamento]<br />
*Introdução<br />
O entendimento de protocolos de redes pode ser bastante aprofundado através da “observação de protocolos funcionando” e “da manipulação de protocolos” - observando a sequência de mensagens trocadas entre duas entidades, entrando nos detalhes da operação do protocolo, e fazendo com que os protocolos realizem certas ações e então observando estas ações e as consequências. <br />
<br />
A ferramenta básica para observar as mensagens trocadas entre as entidades em execução é chamada de ''sniffer''. Como o nome sugere, um ''sniffer'' captura mensagens sendo enviadas/recebidas pelo seu computador; ele também tipicamente armazena e/ou apresenta os conteúdos dos vários campos dos protocolos nestas mensagens capturadas. Um ''sniffer'' isoladamente é um elemento passivo. Ele observa as mensagens sendo enviadas e recebidas pelas aplicações e protocolos executando no seu computador, mas jamais envia pacotes. Similarmente, os pacotes recebidos nunca são explicitamente endereçados ao ''sniffer''. Ao invés disso, um ''sniffer'' recebe uma cópia de pacotes que são enviados/recebidos para/de aplicações e protocolos executando no seu computador. <br />
<br />
A Figura 2 mostra a estrutura de um ''sniffer''. À direita da Figura 2 estão os protocolos (neste caso, protocolos da Internet) e aplicações (tais como navegador web ou cliente FTP) que normalmente executam no seu computador. O ''sniffer'', exibido dentro do retângulo tracejado na Figura 2 é uma adição aos softwares usuais no seu computador, e consiste de duas partes: a biblioteca de captura de pacotes e o analisador de pacotes. A biblioteca de captura de pacotes recebe uma cópia de cada quadro da camada de enlace que é enviado do ou recebido pelo seu computador. Lembre que mensagens trocadas por protocolos das camadas mais altas tais como HTTP, FTP, TCP, UDP, DNS ou IP, são todos eventualmente encapsulados em quadros que são transmitidos para o meio físico como um cabo Ethernet. Na Figura 2, assume-se que o meio físico é uma Ethernet, e desta forma, os protocolos das camadas superiores são eventualmente encapsulados em um quadro Ethernet. Capturar todos os quadros fornece todas as mensagens enviadas/recebidas de/por todos os protocolos e aplicações executando em seu computador.<br />
<br />
[[Arquivo:Sniffer_estrutura.png |thumb | 500px| Figura 2 - Estrutura de um ''sniffer'']]<br />
<br />
O analisador de pacotes exibe os conteúdos de todos os campos dentro de uma mensagem de protocolo. Para que isso seja feito, o analisador de pacotes deve “entender” a estrutura de todas as mensagens trocadas pelos protocolos. Por exemplo, suponha que estamos interessados em mostrar os vários campos nas mensagens trocadas pelo protocolo HTTP na Figura 5. O analisador de pacotes entende o formato dos quadros Ethernet, e desta forma pode identificar o datagrama IP dentro de um quadro. Ele também entende o formato do datagrama IP, para que ele possa extrair o segmento TCP dentro do datagrama IP. Ele entende a estrutura do segmento TCP, para que possa extrair a mensagem HTTP contida no segmento. Finalmente, ele entende o protocolo HTTP e então, por exemplo, sabe que os primeiros bytes de uma mensagem HTTP contém a cadeia “GET”, “POST” ou “HEAD”. Nós utilizaremos o ''sniffer'' Wireshark (http://www.wireshark.org) para estes laboratórios, o que nos permite exibir os conteúdos das mensagens sendo enviadas/recebidas de/por protocolos em diferentes camadas da pilha de protocolos. Tecnicamente falando, Wireshark é um analisador de pacotes que pode ser executado em computadores com Windows, Linux/UNIX e MAC.<br />
<br />
É um analisador de pacotes ideal para nossos laboratórios, pois é estável, tem uma grande base de usuários e é bem documentado incluindo um guia de usuário (http://www.wireshark.org/docs/wsug_html/), páginas de manual (http://www.wireshark.org/docs/man-pages/), e uma seção de FAQ detalhada (http://www.wireshark.org/faq.html), funcionalidade rica que inclui a capacidade de analisar mais que 500 protocolos, e uma interface com o usuário bem projetada. Ele funciona em computadores ligados a uma Ethernet para conectar-se à Internet, bem como protocolos ponto a ponto, tal como PPP.<br />
<br />
*Analisando os campos da interface do Wireshark <br />
Quando você executar o programa Wireshark, a interface com o usuário exibida na Figura 3 aparecerá. Inicialmente, nenhum dado será apresentado nas janelas. A interface do Wireshark tem seis componentes principais: <br />
#Os menus de comandos são localizados no topo da janela. Por enquanto, interessam apenas os menus ''File'' e ''Capture''. O menu ''File'' permite salvar dados de capturas de pacotes ou abrir um arquivo contendo dados de capturas de pacotes previamente realizadas, e sair da aplicação. O menu ''Capture'' permite iniciar uma captura de pacotes; <br />
#A barra de ferramentas contém os comandos de menu que são mais frequentemente utilizados. Há atalhos para abrir ou salvar dados de captura de pacotes e para iniciar ou parar uma captura de pacotes; <br />
#Abaixo da barra de ferramentas, está o campo de filtragem de pacotes exibidos. Nele podem ser digitados nome de protocolo ou outra informação apresentada na janela de listagem de pacotes. Apenas os pacotes que correspondem ao filtro são exibidos; <br />
#A janela de listagem de pacotes apresenta um resumo de uma linha para cada pacote capturado, incluindo o número do pacote (atribuído pelo Wireshark; este não é o número do pacote contido no cabeçalho de qualquer protocolo), o tempo que o pacote foi capturado, os endereços fonte e destino do pacote, o tipo de protocolo, e informação específica do protocolo contida no pacote. A lista de pacotes pode ser ordenada conforme qualquer uma destas categorias clicando no nome de uma coluna correspondente. O campo tipo do protocolo lista o protocolo de mais alto nível que enviou ou recebeu este pacote, i.e., o protocolo que é a fonte ou o último sorvedouro para este pacote; <br />
#A janela de detalhes de cabeçalho de pacotes fornece detalhes sobre o pacote selecionado na janela de listagem de pacotes. Para selecionar um pacote, basta clicar sobre ele com o botão esquerdo do mouse na janela de listagem de pacotes. Os detalhes apresentados incluem informações sobre o quadro Ethernet e o datagrama IP que contém o pacote. A quantidade de detalhes exibida pode ser expandida ou contraída. Se o pacote foi carregado sobre TCP ou UDP, detalhes correspondentes também são apresentados, os quais também podem ser contraídos ou expandidos. Finalmente, detalhes sobre o protocolo de mais alto nível que enviou ou recebeu este pacote também são apresentados; <br />
#A janela de conteúdo de pacotes mostra o conteúdo inteiro do quadro capturado, nos formatos ASCII e hexadecimal.<br />
<br />
[[Arquivo:Wireshark_interface_usuario.png | 700px| Figura 3 - Interface com o usuário do Wireshark]]<br />
<br />
====Roteiro de atividades====<br />
<br />
=====Etapa 1===== <br />
#Inicie o navegador web; <br />
#Inicie o Wireshark. Inicialmente as janelas estarão vazias, pois não há captura de pacotes em progresso; <br />
#Para iniciar uma captura de pacotes, selecione o menu Capture e depois Interfaces. Provavelmente sua interface de rede será a '''eth0'''. <br />
#Isso faz com que a janela de interfaces de rede disponíveis seja apresentada (Figura 4); [[Arquivo:Wireshark_interfaces_rede.png |thumb | 400px| Figura 4 - Interfaces de rede no Wireshark]]<br />
#O botão ''Start'' da interface '''eth0''' deve ser selecionado. Na Figura 4, no Wireshark foi selecionada a interface wlan; <br />
#Como nada está acontecendo na rede, a janela apresenta o conteúdo vazio;<br />
#Execute um comando ping (endereço na saída da nossa rede - ver aula anterior):<syntaxhighlight lang=bash><br />
ping 200.237.201.153</syntaxhighlight><br />
#Ao voltar para a janela do Wireshark, houve a captura de todos os pacotes envolvidos no process;<br />
#Antes de continuar, vamos parar a captura de pacotes e trabalhar com o que temos. Basta clicar em ''Capture'' e depois em ''Stop''; <br />
#Para testar as capacidades de filtragem, vamos inserir a cadeia “icmp” (sem as aspas e em minúsculo) no especificação do filtro de exibição e depois selecionar ''Apply'' (ou Aplicar). Observe que somente os pacotes envolvidos no ping estão sendo mostrados. Os resultados obtidos devem ser similar a tela mostrada na Figura 5. <br />
#Selecione a primeira mensagem ECHO REQUEST: as informações dos cabeçalhos do quadro Ethernet, do datagrama IP, do pacote ICMP aparecem na janela de cabeçalhos de pacotes. É possível ver os detalhes, expandido ou comprimindo os itens com um clique na seta ao lado deles.<br />
#Selecione uma mensagem ECHO REPLY. Analise o pacote: endereço fonte, endereço destino etc;<br />
#Saia do Wireshark.<br />
<br />
[[Arquivo:TelaWiresharkPing.png | 700px| Figura 5 - Tela Wireshark - Ping]]<br />
<br />
=====Etapa 2=====<br />
<br />
#Com Wireshark ativo (Abra-o novamente) faça um pingue para um site conhecido (você pode usar o nome: www.ifsc.edu.br por exemplo):<br />
#Teste outros filtros, por exemplo, mostre somente pacotes originados e/ou destinados a um determinado ''host'' ('''ip.addr == 192.168...''', ip.src, ip.dst).<br />
#Qual é o endereço IP do sítio navegado? Qual é o endereço IP da interface de rede do seu computador? Qual o endereço MAC de sua máquina?<br />
<br />
<br />
=====Etapa 3 - Desafios=====<br />
<br />
#Solicite um endereço IP de um colega e faça um experimento para descobrir o endereço MAC do computador dele.<br />
#Tente elaborar um experimento para descobrir o endereço MAC do servidor de www.ifsc.edu.br. É possível? Explique para o professor...<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 3 - Conceituando protocolos}}<br />
<br />
===Objetivos===<br />
<br />
*Desenvolver o conceito de protocolo<br />
*Conceber um protocolo/serviço de calculadora pela rede<br />
<br />
===Introdução===<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/Conceituando%20protocolos.pdf Conceituando protocolos]<br />
<br />
O entendimento de protocolos de redes pode ser bastante aprofundado através da “observação de protocolos funcionando” e “da manipulação de protocolos” - observando a sequência de mensagens trocadas entre duas entidades, entrando nos detalhes da operação do protocolo, e fazendo com que os protocolos realizem certas ações e então observando estas ações e as consequências.<br />
<br />
Um protocolo de camada de aplicação define:<br />
#Os tipos de mensagens trocadas.<br />
#A sintaxe dos vários tipos de mensagens, tais como os campos da mensagem e como os campos são delineados.<br />
#A semântica dos campos, isto é, o significado da informação nos campos.<br />
#Regras para determinar quando e como um processo envia mensagens e responde a mensagens.<br />
<br />
Neste experimento será proposto a construção de um protocolo de aplicação para prestar serviços na área de operações matemáticas. Na implementação deste serviço todos grupos serão clientes, solicitando respostas a desafios matemáticos, e servidores, enviando respostas as solicitações, de serviço. Deve ser observado que para não se tornar complexo será usado o transporte de informação através do ICMP (usando o ping). O ping possui uma facilidade para transportar bytes de dados (flag -p). A observação destes dados será feita usando o wireshark (captura de pacotes). Pode-se dizer que o programa ping juntamente com o wireshark e a própria interpretação de pacotes pelo grupo constituem a camada de aplicação.<br />
A camada de transporte foi de certa forma subsituída pelo ICMP que na prática é posicionado na camada de rede (por ser um protocolo auxiliar no funcionamento da camada IP).<br />
<br />
[[Arquivo:AppRCO.png | 500px | Estrutura Applicação'']]<br />
<br />
<br />
*Definição do protocolo a ser criado<br />
#Vamos criar uma calculadora em rede através de um protocolo bem simples, utilizando como ferramenta de comunicação o ping.<br />
##O protocolo tem por objetivo dar suporte a uma calculadora em rede.<br />
##Um aluno cria uma mensagem e envia, sem aviso prévio, a um colega. Este será o cliente da arquitetura cliente-servidor.<br />
##O colega, ao receber a mensagem, deverá interpretá-la, elaborar uma resposta à pergunta e retorná-la ao colega. Este será o servidor da arquitetura cliente-servidor.<br />
##A estrutura básica de um pacote que flui do cliente para o servidor e vice-versa é apresentada na figura abaixo. Essa estrutura deverá ser absolutamente respeitada, caso contrário, o servidor poderá não conseguir interpretá-la e descartará a mensagem. <br />
[[Arquivo:RCOestrutura-pacote.png | 400px | Estrutura do Pacote'']]<br />
<br />
<br />
Para auxiliar na interpretação das mensagens utilize:<br />
#[http://iris.sel.eesc.usp.br/sel433a/ASCII.pdf Tabela ASCII]<br />
#[http://www.rapidtables.com/convert/number/hex-to-ascii.htm Ferramenta para conversão ASCII <==> Hexadecimal]<br />
#[http://xor.pw/ XOR CALCULATOR]<br />
<br />
*Roteiro de Atividades:<br />
#Inicie o Wireshark.<br />
#Inicie a captura de pacotes em sua interface de rede e adicione o filtro '''icmp'''.<br />
#Cada estudante vai construir uma mensagem, respeitando o formato estabelecido, de solicitação (lado cliente). Para construir a mensagem utilize o código ASCII. Essa mensagem deverá explicitar:<br />
##O tipo (requisição ou resposta, ver figura).<br />
##Como endereço de destino (DEST) e fonte (FONTE) utilize o último campo do endereço IP de sua máquina e do colega para qual a mensagem se destina. Por exemplo, a máquina do professor possui o IP 192.168.1.1 e, portanto, seu endereço seria 01.<br />
##Um desafio matemático, por exemplo: 2+2.<br />
#Envie essa mensagem através do comando '''ping''' com a ''flag'' ''pattern''. Um exemplo de mensagem é: <syntaxhighlight lang=bash> ping -p FFFF02001001322B322B03FFFF 192.168.1.10 </syntaxhighlight><br />
##Verifique com Wireshark se a mensagem é para o seu grupo e decifre a mensagem.<br />
#Ao receber uma ou mais mensagens de colegas no wireshark, interprete-a verificando quem é o emitente e realizando a operação aritmética solicitada.<br />
##Monte uma resposta e utilize o comando '''ping''' para responder ao emitente.<br />
##Certifique-se que o colega conseguiu interpretar a mensagem<br />
#Desafio:<br />
#*Em equipes, 2 alunos, proponha um novo padrão de mensagens de um protocolo que dê suporte a um Quiz, perguntas e repostas, sobre o tema geografia. Perguntas do tipo: qual é a capital da Austrália?<br />
#*Implemente o protocolo e teste seus conhecimentos e de seus colegas sobre o tema.<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 4 - Desvendando o HTTP com Wireshark - BÁSICO}}<br />
<br />
===Sobre este Laboratório===<br />
<br />
*Baseado na pequena introdução ao Wireshark apresentada no '''Laboratório 2''' e no '''Laboratório Conceituando Protocolos''' , agora estamos prontos para utilizar o Wireshark para investigar protocolos de aplicação reais em operação. Neste laboratório o protocolo HTTP é explorado nas suas características básicas<br />
<br />
===Fonte base===<br />
<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/Desvendando%20o%20HTTP%20basico.pdf SLIDES DE APOIO: Desvendando o HTTP - Básico - Baseado na Pearson/Kurose]<br />
*[http://www.ebah.com.br/content/ABAAABZ6QAD/wireshark-http Wireshark - HTTP]<br />
*[https://pt.wikipedia.org/wiki/Hypertext_Transfer_Protocol HTTP na Wikipedia]<br />
<br />
===Objetivos===<br />
<br />
*Explorar vários aspectos do protocolo HTTP:<br />
*a interação básica GET/resposta do HTTP,<br />
*formatos de mensagens HTTP;<br />
*diferenças http 1.0 e 1.1 / persistência<br />
<br />
===PARTE 1 - Interação Básica GET/Resposta do HTTP===<br />
<br />
Vamos iniciar a nossa exploração do HTTP baixando um arquivo em HTML simples - bastante pequeno, que não contém objetos incluídos. Faça o seguinte:<br />
#inicie o navegador;<br />
#limpe o cache do mesmo (teclas de atalho para o Firefox: '''Ctrl + Shift + Del''');<br />
#inicie o Wireshark, como descrito no '''Laboratório 1''';<br />
#inicie a captura de pacotes;<br />
#digite o seguinte URL no navegador http://tele.sj.ifsc.edu.br/~odilson/RED29004/RED29004.html;<br />
#pare a captura de pacotes;<br />
#digite “http” (somente as letras, sem as aspas) na caixa de texto de especificação do filtro de exibição, de tal forma que apenas as mensagens HTTP capturadas serão exibidas na janela de listagem de pacotes. (Só estamos interessados em HTTP desta vez, e não desejamos ver todos os pacotes capturados).<br />
#No ''browser'', clique o botão da direita e visualize o código fonte da página adquirida em html.<br />
[[Arquivo:HTTP_Wireshark.png |thumb | 300px| Fig.1 Requisição e Resposta HTTP]]<br />
<br />
O exemplo da figura 1 mostra na janela de listagem de pacotes duas mensagens HTTP capturadas:<br />
#A mensagem GET (do seu navegador para o servidor web www.sj.ifsc.edu.br) e a mensagem de resposta do servidor para o seu navegador.<br />
#A janela de conteúdos de pacotes mostra detalhes da mensagem selecionada (neste caso a mensagem HTTP GET /~odilson/RED29004//RED29004.html, que está em destaque na janela de listagem de pacotes).<br />
#A mensagem HTTP transportada em um segmento TCP, que é carregado em um datagrama IP, que é levado em um quadro Ethernet com 5728 bits no fio. Isso é observado de baixo para cima na janela de detalhes do cabeçalho do pacote selecionado. O Wireshark exibe informações sobre o quadro, IP, TCP e HTTP. Você deve expandir as informações, por exemplo, do HTTP clicando na seta ao lado esquerdo de “Hypertext Transfer Protocol”. Observando as informações das mensagens HTTP GET e de resposta. Você consegue inclusive enxergar a mensagem mostrada no navegador: '''RED29004! Página de teste.'''<br />
<br />
Responda às seguintes perguntas e imprima as mensagens GET e a resposta e indique em que parte da mensagem você encontrou a informação que responde às questões.<br />
#O seu navegador executa HTTP 1.0 ou 1.1?<br />
#Qual a versão de HTTP do servidor?<br />
#Quais idiomas (se algum) o seu navegador indica ao servidor que pode aceitar?<br />
#Qual o endereço IP do seu computador?<br />
#E do servidor tele.sj.ifsc.edu.br?<br />
#Qual o número da porta utilizada no seu computador? Note que esta pergunta se refere a porta do protocolo de transporte TCP, portanto, verifique o header TCP;<br />
#E do servidor tele.sj.ifsc.edu.br?<br />
#Qual o código de status retornado do servidor para o seu navegador?<br />
#Quando o arquivo em HTML que você baixou foi modificado no servidor pela última vez?<br />
#Quantos bytes de conteúdo são baixados pelo seu navegador?<br />
#Encontre a mensagem '''RED29004! Página de teste'''. Onde (em qual campo) encontra-se?<br />
#Qual a diferença entre os endereços (IP) de origem e destino entre a mensagem GET e a de resposta do HTTP?<br />
<br />
===PARTE 2 - Interação Básica GET/Resposta do HTTP usando TELNET e REQUISIÇÃO MANUAL===<br />
<br />
Para esta etapa temos que recordar que o browser é responsável por:<br />
*se conectar ao servidor usando uma porta TCP 80 (default) e <br />
*gerar uma mensagem GET para apanhar um recurso no servidor;<br />
*receber e mostrar a página<br />
Mas será que podemos "emular" o comportamento do browser usando uma outra ferramenta? Por exemplo, o telnet permite abrir uma conexão na porta 80. O que for teclado após a conexão será enviado para o servidor pela conexão estabelecida.<br />
<br />
Aproveitando o comportamento acima, vamos montar na MÃO o pacote de aplicação (que o browser gera) e receber a página do servidor como resposta. Claro que agora não teremos a facilidade do browser em mostrar a página para nós. O que veremos é um código HTML, que é um formato de documentos WEB.<br />
<br />
# Vamos repetir o acesso aos links acima, porém sem usar o navegador. A ideia é que nós façamos o papel de navegador. Isso deve ser feito com os seguintes passos:<br />
#* Coloque o Wireshark para capturar pacotes <br />
#* Abra um terminal de texto no Linux (menu ''Aplicativos->Acessórios->Terminal'').<br />
#* Execute este comando: <syntaxhighlight lang=bash><br />
telnet tele.sj.ifsc.edu.br 80<br />
</syntaxhighlight><br />
#* Após aparecer esta linha: <syntaxhighlight lang=text><br />
Trying 200.135.37.75...<br />
Connected to integrado.sj.ifsc.edu.br.<br />
Escape character is '^]'.<br />
</syntaxhighlight>digite o seguinte:<syntaxhighlight lang=text><br />
GET /~odilson/RED29004//RED29004.html HTTP/1.0<br />
</syntaxhighlight> e em seguida tecle ENTER duas vezes.<br />
#* Identifique a página html que foi enviada como resposta.<br />
#* No WireShark, compare o resultado das execuções desses comandos com o resultado anteriormente visto no navegador. Qual a diferença em ambos os casos?<br />
#* Identifique os componentes do sistema de comunicação de dados nesse acesso direto (quem é cliente, quem é servidor)<br />
#* Refaça um pedido em que o recurso é inexistente no servidor (ex: página html com nome inexistente, GET /~odilson/RED29004//Nada.html HTTP/1.0). Observe a resposta. Qual o código (número) de resposta recebido? <syntaxhighlight lang=bash> telnet tele.sj.ifsc.edu.br 80<br />
GET /~odilson/RED29004//Nada.html HTTP/1.0 </syntaxhighlight><br />
#* Refaça um pedido para o recurso ''default'' e veja o código de resposta:<syntaxhighlight lang=bash> telnet tele.sj.ifsc.edu.br 80<br />
GET / HTTP/1.0</syntaxhighlight><br />
#* Refaça o pedido usando o HTTP/1.1 e tente inferir a diferença da versão 1.0. Note que o GET nesta versão deve ser realizado com o campo Host:<syntaxhighlight lang=bash><br />
telnet tele.sj.ifsc.edu.br 80<br />
GET /~odilson/RED29004//RED29004.html HTTP/1.1<br />
Host: tele.sj.ifsc.edu.br</syntaxhighlight><br />
#'''Nesse teste você deve ter observado que a conexão se manteve aberta'''. Experimente refazer o pedido para um outro recurso na mesma conexão:<syntaxhighlight lang=bash><br />
GET /~odilson/RED29004//RED29004_arq2.html HTTP/1.1<br />
Host: tele.sj.ifsc.edu.br<br />
</syntaxhighlight><br />
Esta característica é a "persistência" do http versão 1.1, que permite reutilizar a mesma conexão para adquirir múltiplos recursos.<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 5 - Desvendando o HTTP com Wireshark - AVANÇADO}}<br />
<br />
===Objetivos===<br />
<br />
*Explorar GET Condicional/Resposta no protocolo HTTP:<br />
*Analisar documentos HTML com Objetos Incluídos<br />
*Comparar as mensagens nos protocolos HTTP X HTTP.<br />
<br />
===Fonte base===<br />
<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/Desvendando%20o%20HTTP%20avancado.pdf SLIDES DE APOIO: Desvendando o HTTP - Avançado - Baseado na Pearson/Kurose]<br />
*[http://www.ebah.com.br/content/ABAAABZ6QAD/wireshark-http Wireshark - HTTP]<br />
*[https://pt.wikipedia.org/wiki/Hypertext_Transfer_Protocol HTTP na Wikipedia]<br />
<br />
===PARTE 1 - A Interação HTTP GET Condicional/Resposta===<br />
<br />
A maioria dos navegadores web tem um cache (seção 2.2.6 do livro) e, desta forma, realizam GET condicional quando baixam um objeto HTTP. Execute os seguintes passos:<br />
#inicie o navegador web;<br />
#limpe o cache do seu navegador('''Ctrl + Shift + Del''');<br />
#inicie o Wireshark;<br />
#digite o URL no navegador http://tele.sj.ifsc.edu.br/~odilson/RED29004//RED29004.html seu navegador deve exibir um arquivo em HTML muito simples com duas linhas;<br />
#pressione o botão “refresh” ('''F5''') no navegador (ou digite o URL novamente);<br />
#pare a captura de pacotes, e digite “http” na caixa de texto de especificação de filtro, para que apenas as mensagens HTTP sejam apresentadas na janela de listagem de pacotes. Se você realizou o procedimento corretamente, você visualizará um total de 6 mensagens no Wireshark: três GETs e três respostas. Obs: Para finas de análise, despreze a solicitação e resposta relativa ao ''fiveicon'', que é relativa ao ''download'' do ícone do IFSC.<br />
<br />
Responda às seguintes questões:<br />
#Inspecione o conteúdo da primeira mensagem HTTP GET do seu navegador para o servidor tele.sj.ifsc.edu.br. Você vê uma linha “If-Modified-Since”?<br />
#Inspecione o conteúdo da primeira resposta do servidor. O servidor retornou explicitamente o conteúdo do arquivo? Como você pode dizer isso?<br />
#Agora inspecione o conteúdo da segunda mensagem HTTP GET do seu navegador para o servidor. Você vê uma linha “If-Modified-Since”? Caso a resposta seja afirmativa, qual informação segue o cabeçalho “If-Modified-Since”?<br />
#Qual é o código de status e a frase retornada do servidor na resposta à segunda mensagem HTTP GET? É diferente do código de retorno da primeira mensagem?<br />
#O servidor retornou explicitamente o conteúdo do arquivo? Explique.<br />
#Qual o tamanho da primeira e segunda mensagem de retorno do servidor?<br />
<br />
===PARTE 2 -Documentos HTML com Objetos Incluídos===<br />
<br />
Agora que vimos como o Wireshark mostra o tráfego capturado para arquivos em HTML grandes, nós podemos observar o que acontece quando o seu browser baixa um arquivo com objetos incluídos, no nosso exemplo, imagens que estão armazenadas em outros servidores. Faça o seguinte:<br />
#inicie o navegador web;<br />
#limpe o cache do seu navegador;<br />
#inicie o Wireshark;<br />
#digite o URL no navegador http://tele.sj.ifsc.edu.br/~odilson/RED29004/RED29004_arq3.html seu navegador deve exibir um arquivo pequeno em HTML com duas imagens incluídas. Estas duas imagens estão referenciadas no arquivo em HTML. Isto é, as imagens não estão no arquivo em HTML, ao invés disso, há um URL para cada imagem no arquivo em HTML. Como discutido no livro, seu navegador terá que baixar estas imagens dos locais correspondentes. As imagens estão em docente.ifsc.edu.br;<br />
#Verifique o código fonte da página, clicando com o botão direito sobre ela. Observe os links dentro do código html.<br />
#digite o URL no navegador http://tele.sj.ifsc.edu.br/~odilson/RED29004/RED29004_arq4.html seu navegador deve exibir um arquivo pequeno em HTML com cinco imagens incluídas. Estas cinco imagens,diferentemente do caso anterior, estão depositadas no próprio sítio do professor;<br />
#Verifique o código fonte da página, clicando com o botão direito sobre ela. Observe os links dentro do código html.<br />
#pare a captura de pacotes, e digite “http” na caixa de texto de especificação de filtro, para que apenas as mensagens HTTP seja exibidas.<br />
<br />
Responda às seguintes questões:<br />
#Quantas mensagens HTTP GET foram enviadas pelo seu navegador em cada acesso?<br />
#Para quais endereços na Internet estas mensagens foram enviadas em cada acesso?<br />
#Você consegue dizer se o seu navegador baixou imagens com ou sem paralelismo? Explique e diferencie o comportamento em cada um dos casos.<br />
<br />
===PARTE 3 -Segurança com HTTPS===<br />
Para finalizar, vamos capturar sequências de mensagens HTTPS, somente a título de comparação. Execute os seguintes procedimentos:<br />
#inicie o navegador web;<br />
#limpe o cache do seu navegador;<br />
#inicie o Wireshark;<br />
#digite o seguinte URL no navegador https://www.ssllabs.com/ssltest/;<br />
#pare a captura de pacotes e digite "ssl" na caixa de texto de especificação de filtro, para que apenas as mensagens criptografadas sejam exibidas.<br />
<br />
Responda:<br />
#Compare a sequência de troca de mensagens (GET e resposta) entre o HTTP (das seções anteriores) com o ssl, existe alguma similaridade?<br />
#Que tipos de campos são mais presentes nesse tipo de mensagens?<br />
#Você consegue identificar o conteúdo de alguma nas mensagens ssl, como no caso das mensagens http?<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 6 - Servidor Apache e Construção de Página HTML}}<br />
<br />
===Objetivos===<br />
*Introdução a ferramenta de simulação de redes Netkit.<br />
*Configurando o servidor Apache para disponibilizar páginas HTML.<br />
*Construindo e disponibilizando páginas HTML.<br />
*Noções de ''shell script'' para automatizar tarefas.<br />
<br />
===Fonte base===<br />
<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/ServidorApache.pdf SLIDES DE APOIO: Introdução à Programação “para Web”]. Baseado no resumo destes material Introdução à Programação para Web de Carlos Bazilio: [http://www.ic.uff.br/~bazilio/cursos/java/slides/Introducao.pptm]<br />
*[https://www.apache.org/ Apache]<br />
<br />
===Máquinas Virtuais UML / Netkit2===<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/SlidesApoioMaquinaVirtual.pdf Conceitos de máquinas virtuais]<br />
<br />
Para esta aula de laboratório estaremos usando o [https://wiki.sj.ifsc.edu.br/index.php/Netkit2 netkit2] do Prof. Sobral, uma extensão do [http://wiki.netkit.org/index.php/Main_Page netkit] da '''Universidade Roma Tre'''.<br />
Trata-se de uma ferramenta que que permite criar máquinas virtuais leves sobre o linux. Estas máquinas podem ser ligadas em rede. Neste laboratório conectaremos uma máquina virtual na REDE do Laboratório através de uma bridge.<br />
<br />
===O Servidor Apache===<br />
<br />
Neste laboratório vamos criar uma página html e hospedá-la em um máquina virtual com o [http://www.apache.org/ Web Server Apache]. Para maiores informações consulte [http://softwarelivre.org/php/servidor-web-apache Visão Geral do Apache ].<br />
<br />
===PARTE 1 - Colocando o servidor Apache no ar no Netkit===<br />
<br />
#Inicialmente vamos colocar um Máquina Virtual (VM) Netkit conectada com uma bridge para que possamos acessá-la de qualquer lugar do laboratório. Utilize o editor de texto Gedit e salve as definições do laboratório abaixo em um arquivo '''/home/aluno/lab.conf''':<syntaxhighlight lang=bash><br />
pc1[type]=generic<br />
pc1[eth0]=uplink:bridge=eth0:ip=dhcp<br />
</syntaxhighlight><br />
#Rode o '''netKit''' em seu computador. Em um terminal digite: <syntaxhighlight lang=bash> mkdir .netkit<br />
netkit2 & </syntaxhighlight><br />
#Caso surja uma mensagem recomendando atualizar o Netkit, faça-o através do menu: '''<General> <Update>'''. Aguarde a finalização do processo.<br />
#No menu '''<File> <Load and Run>''', procure o arquivo '''/home/aluno/lab.conf''' e clique em OK. Abrirá um terminal da máquina virtual (VM) que estará rodando servidor Apache que vamos utilizar, onde é possível fazer a configuração do mesmo.<br />
#<span style="color: red;">Dica: não tente alterar o tamanho da janela do Netkit. Se isso for feito não consegue-se mais voltar ao tamnho original.<br />
#Ao clicar no menu '''<File> <Graph>''', pode-se ter uma visão da rede a ser simulada e conferir se é equivalente ao diagrama proposto.<br />
#Identifique o IP da VM usando o comando '''ifconfig'''. Esse será, doravante, seu '''''endereço_IP'''''.<br />
#*<span style="color: blue;">Dica: para copiar textos para o Netkit, copie normalmente o texto, por exemplo, da Wiki, com o < Ctrl > + < C > e cole clicando sobre a rodinha (''scroll'') do mouse.<br />
#Teste a conectividade entre a máquina virtual e a máquina hospedeira com o comando ping. Na VM execute: <syntaxhighlight lang=bash><br />
ping 192.168.1.1 </syntaxhighlight><br />
#Coloque o servidor apache em execução. Este servidor escutará na porta 80 por requisições de páginas (objetos HTTP). Execute no terminal da VM: <syntaxhighlight lang=bash> /etc/init.d/apache2 start </syntaxhighlight><br />
#Inicie o Wireshark em sua máquina.<br />
#Abra o Firefox na sua máquina (hospedeira) e coloque como endereço: <syntaxhighlight lang=bash> http://endereco_IP </syntaxhighlight><br />
#Pronto. Você está acessando a página ''default'' do Apache da VM.<br />
#Você pode verificar o arquivo de definição da página ''default'' na VM com o comando: <syntaxhighlight lang=bash> cat /var/www/index.html </syntaxhighlight><br />
#Com sua experiência com o Wireshark filtre as mensagens trocadas entre o servidor da VM e seu navegador. <br />
##Localize os comandos GET e a resposta do servidor. <br />
##Observe quais são os IPs de destino e fonte da requisição e resposta.<br />
##Observe as portas de destino e fonte da requisição e resposta.<br />
##Qual versão do HTTP está sendo usada?<br />
#Escolha um servidor web de um colega, acesse a página HTML desse colega e repita as capturas de pacotes.<br />
<br />
===PARTE 2 - Colocando no ar a sua página HTML===<br />
<br />
Nesta parte do experimento vamos editar um código HTML e disponibilizá-la em um diretório especial por você criado. Observe que vamos editar a página no hospedeiro e salvá-la em um diretório compartilhado entre a máquina hospedeira e a MV.<br />
<br />
#Usando o Gedit, salve o código html abaixo como no arquivo '''/home/aluno/lab/shared/index.html''' da sua máquina hospedeira.<syntaxhighlight lang=bash><br />
<!DOCTYPE html><br />
<html><br />
<body><br />
<br />
<h1>Alo Mundo</h1><br />
<br />
<p>Estamos sendo visitados por extraterrestres...</p><br />
<br />
</body><br />
</syntaxhighlight><br />
#Crie a adapte para o seu caso um [https://pt.wikipedia.org/wiki/Shell_script Shell Script] com o conteúdo exemplo abaixo. Com o Gedit crie um arquivo e salve como '''/home/aluno/lab/shared/config_apache.sh''' <syntaxhighlight lang=bash><br />
#!/bin/bash<br />
mkdir /var/www/ET<br />
chmod 755 /var/www/ET<br />
cp /hostlab/shared/index.html /var/www/ET<br />
chmod 555 /var/www/ET/index.html<br />
service apache2 restart </syntaxhighlight><br />
#Em sua máquina hospedeira transforme o script em executável. Num terminal digite: <syntaxhighlight lang=bash> chmod +x /home/aluno/lab/shared/config_apache.sh </syntaxhighlight><br />
#O shell script será executado na máquina virtual do apache, portanto, abra o terminal da mesma no Netkit e digite: <syntaxhighlight lang=bash><br />
/hostlab/shared/config_apache.sh <br />
</syntaxhighlight><br />
#Agora você deve ser capaz de acessar a página recém criada através do seu navegador no hospedeiro usando o endereço: <syntaxhighlight lang=bash> http://endereco_IP/ET </syntaxhighlight><br />
#Personalize a página HTML acrescentando novas frases de sua preferência. Para isso repita os passos: 1, 3 e 4.<br />
#Avise o professor para que ele mostre no telão sua página através do Epoptes.<br />
#Acesse as páginas HTML personalizadas dos demais colegas.<br />
#Se desejar, crie outras páginas, para isto basta executar os passos 1 a 5, só que criando diretórios com nomes distintos dos demais já existentes. Cada novo diretório poderá conter uma nova página.<br />
#Também se desejar incremente suas novas páginas com figuras (objetos). Lembre-se de copiar esse objetos para o diretório pertinente na VM.<br />
#*Com o navegador acesse as novas páginas criadas.<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 7 - Serviço de Nomes (DNS)}}<br />
<br />
===Objetivos===<br />
O Domain Name System (DNS) traduz nomes de hosts em endereços Internet Protocol (IP), preenchendo uma lacuna crítica na infraestrutura da Internet. Neste laboratório, observaremos mais de perto:<br />
#O lado cliente do DNS.<br />
#Uma pequena análise do protocolo e<br />
#Consultas AAAA<br />
<br />
Lembre-se de que o papel do cliente no DNS é relativamente simples - um cliente envia uma consulta ao seu DNS, e obtém uma resposta. Muito pode acontecer “por baixo dos panos”, de forma invisível aos clientes DNS, enquanto os servidores DNS, organizados hierarquicamente, comunicam-se entre si para, ou recursivamente ou iterativamente, resolver uma consulta DNS de um cliente. Do ponto de vista do cliente DNS, contudo, o protocolo é bastante simples - uma consulta é feita ao seu servidor DNS e uma resposta é recebida deste servidor.<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/Servico%20de%20Nomes%20DNS.pdf Serviço de Nomes - DNS]<br />
<br />
===PARTE 1: Consulta simples ao DNS gerada a partir de um comando ping===<br />
<br />
O comando ping pode ser usado tanto com um endereço IP como com um nome de host. Em última instância, ele sempre enviará pacotes para um endereço IP. No caso de ser usado o endereço de host, ele tentará resolver (mapear) este nome em um endereço IP usando um servidor DNS (local). Ele gera uma pergunta para o servidor (ou para os servidores, caso exista mais de um configurado). Esta experiência mostra como verificar os servidores instalados e, através de uma captura de pacote mostra a estrutura dos cabeçalhos DNS.<br />
<br />
#Inicialmente consulte e anote quem são os servidores DNS instados na sua máquina. É para estes servidores que serão conduzidas as perguntas DNS. Use a ferramenta nm-tool ou acesso ao arquivo de configuração do sistema:<syntaxhighlight lang=bash><br />
cat /etc/resolv.conf</syntaxhighlight><br />
#Prepare o wireshark para capturar pacotes.<br />
#Execute o ping para um endereço de host conhecido <syntaxhighlight lang=bash><br />
ping www.ifsc.edu.br</syntaxhighlight><br />
#Pare a captura de pacotes no Wireshark e coloque um filtro de display para mostrar apenas mensagens DNS e de ICMP<syntaxhighlight lang=bash><br />
dns || icmp </syntaxhighlight><br />
#Observe os pacotes capturados. Em particular foque no pacote de pergunta que deve ser similar ao mostrado abaixo e deve estar direcionado a um dos servidores DNS. Nos ''flags'' do header do pacote DNS é possível observar que é um QUERY (pergunta) a ser resolvido de forma recursiva. A pergunta propriamente dita está no campo QUERIES, onde é colocado o nome a ser resolvido e o tipo do registro solicitado (tipo A) que indica resolução de nome. <br />
#:<br />
#:[[Arquivo:DNS-Tela1-Wireshark.jpg | 900px| Estrutura de uma pergunta simples DNS]]<br />
#:<br />
#:<br />
#Foque agora um pacote de resposta do servidor para o cliente. Deve ter uma estrutura similar ao mostrado abaixo. Nos flags do header do pacote DNS é possível observar que é uma resposta. A resposta propriamente dita está no campo ANSWERS (ele também repete a pergunta no campo QUERIES). Note que podem haver vários registros (RR) retornados, cada um com um tipo. No exemplo abaixo também é retornada uma lista de servidores autorizados (RR tipo NS). Também é retornado o endereço IP destes servidores através de RRs adicionais do tipo A (inclusive endereços IPv6).<br />
#:<br />
#:<br />
#:[[Arquivo:DNS-Tela2-Wireshark.jpg | 900px| Estrutura de uma resposta simples DNS]]<br />
#Perguntas a serem respondidas, baseado nos pacotes "''Standard query''" e "''Standard query response''":<br />
##Quem são os servidores DNS da sua máquina?<br />
##O ping gerou pergunta para cada um deles?<br />
##Qual o tipo da RR associada a pergunta (''Queries''). O que significa?<br />
##Qual endereço IP retornado para o www.ifsc.edu.br?<br />
##Qual endereço IP usado no ping (ver pacote REQUEST ICMP)?<br />
##Qual protocolo de transporte, camada 4, que foi usado para transportar as mensagens de aplicação DNS?<br />
##Quais os servidores autorizados (''Authoritative nameservers'') foram repassados em resposta a sua consulta?<br />
#Logo após o primeiro ping existe mais uma consulta DNS. Esta pergunta é realizada através de uma mensagem do tipo PTR. O ping está tentando verificar qual é o nome da máquina que realmente está respondendo. É o DNS reverso, nesse tipo de colsulta se fornece um IP e o servidor devolve o nome da máquina.<br />
#Perguntas a serem respondidas:<br />
##Qual o IP que se pretende resolver?<br />
##Qual o nome retornado?<br />
##O nome retornado é www.ifsc.edu.br? Sim ou não? Explique.<br />
<br />
===PARTE 2 - Consultas DNS por meio de ferramentas especializadas===<br />
# Usando o programa [http://manpages.ubuntu.com/manpages/precise/man5/hosts.5.html host], [http://manpages.ubuntu.com/manpages/trusty/en/man1/nslookup.1.html Nslookup] ou [http://manpages.ubuntu.com/manpages/precise/man1/dig.1.html dig], que são executados no terminal, descubra e anote no relatório os endereços IP associados aos seguintes nomes de hosts (máquinas):<br />
#* mail.ifsc.edu.br<br />
#* www.google.com<br />
#* www.gmail.com<br />
# Agora descubra e anote no relatório quem é o servidor DNS responsável por cada um dos domínios dos nomes acima. Para isso consulte o valor do registro NS associado a esses domínios. Por exemplo, com o programa ''host'' ou ''dig'' isso pode ser feito assim: <syntaxhighlight lang=bash><br />
host -t ns ifsc.edu.br<br />
dig -t ns ifsc.edu.br<br />
</syntaxhighlight><br />
# O serviço DNS fornece outras informações além do endereço IP associado a cada nome de domínio e/ou máquina. Por exemplo, como ele pode-se descobrir que ''host'' recebe emails em um determinado domínio. Isso é utilizado pelos MTA (''Mail Transfer Agent'') mundo afora para entregarem emails para seus destinatários (lembre que isso se faz com o protocolo SMTP). Para descobrir essa informação, deve-se consultar o registro MX (''Mail eXchange'') de um domínio. Novamente as ferramentas a ser utilizada nesse caso podem ser ''host'' ou ''dig''. Por exemplo: <syntaxhighlight lang=bash><br />
host -t mx ifsc.edu.br<br />
dig -t mx ifsc.edu.br<br />
</syntaxhighlight>Descubra e anote no relatório quem é o servidor de emails nos seguintes domínios:<br />
#* gmail.com<br />
#* hotmail.com<br />
#* ifsc.edu.br<br />
# Outra informação útil guardada por servidores DNS é a tradução de endereço IP para nome de domínio. Isso é chamado de tradução reversa (ou DNS reverso). Usando os programas de diagnóstico já vistos, isso pode ser feito assim: <syntaxhighlight lang=bash><br />
dig -x 200.135.37.65<br />
</syntaxhighlight> ... o ''dig'' tem um resultado um pouco mais carregado que os outros utilitários (''host'' e ''nslookup''), porém neste caso é mais prático. Veja o resultado da consulta logo após a linha '';; ANSWER SECTION:''. Experimente fazer a resolução reversa para cada um dos IP obtidos nas consultas realizadas no primeiro exercício desta atividade. Pode-se também usar a variante do ''dig'' para respostas curtas: <syntaxhighlight lang=bash><br />
dig -x 200.135.37.65 +short<br />
</syntaxhighlight><br />
#Faça uma consulta iterativa com dig e responda:<syntaxhighlight lang=bash><br />
dig +trace mail.ru. </syntaxhighlight><br />
##Qual foi o RLD (''Root Level Domain'') consultado?<br />
##Qual o TLD (''Top Level Domain'') consultado?<br />
##Qual o SLD (''Second Level Domain'') consultado?<br />
##Como você sabe que foram esses os LDs consultados?<br />
#Consultando um servidor explícito(@)<syntaxhighlight lang=bash><br />
dig @j.root-servers.net. +trace www.sj.ifsc.edu.br. </syntaxhighlight><br />
#AVANÇADO. Execute somente se tiver curiosidade. Como explicado durante a aula e visto no exercício anterior, DNS é um banco de dados distribuído. Isso quer dizer que suas informações estão espalhadas em milhares (ou milhões?) de servidores DNS mundo afora. Cada servidor DNS mantém os dados dos domínios por que é responsável. Será que é possível rastrear todos os servidores DNS que devem ser consultados até chegar ao servidor do domínio procurado? Posto de outro modo, vamos fazer todo o processo de requisição interativa, do exercício anterior, manualmente, ou seja, descobrir quem é o ''Root Level Domain'', o ''Top Level Domain'' e o ''Second Level Domain''. Anote no relatório.<br />
## Descubra quem são os servidores raiz (topo de hierarquia DNS): <syntaxhighlight lang=bash><br />
host -t ns .<br />
dig -t ns .<br />
</syntaxhighlight><br />
## Escolha um dos servidores TLD listados, e use-o para fazer as consultas. Por exemplo: <syntaxhighlight lang=bash><br />
host -v -t a www.sj.ifsc.edu.br. j.root-servers.net.<br />
</syntaxhighlight>... e observe a seção '';; AUTHORITY SECTION:''. Ele contém a listagem de servidores DNS que podem atender sua consulta.<br />
## Continue fazendo as consultas aos servidores DNS listados, até conseguir traduzir o nome requisitado. Por exemplo: <syntaxhighlight lang=bash><br />
host -v -t a www.sj.ifsc.edu.br. b.dns.br </syntaxhighlight><br />
## Quantos servidores DNS foram necessários consultar no total?<br />
<br />
===Algumas consultas AAAA===<br />
Vamos expandir um pouco nossos horizontes e fazer algumas consultas envolvendo IPv6.<br />
#No terminal de sua máquina faça uma consulta e responda: qual o endereço IPv6 dos hosts? Por exemplo: <syntaxhighlight lang=bash><br />
dig AAAA google.com<br />
host -t AAAA google.com </syntaxhighlight><br />
##webmail.ufsc.br<br />
##www.sj.ifsc.edu.br<br />
##www.nyt.com<br />
##ipv6.br<br />
##www.microsoft.com<br />
#Agora vamos fazer a consulta reversa. Qual é o nome de host dos seguintes endereços? Por exemplo: <syntaxhighlight lang=bash><br />
dig -x 2001:12ff::10<br />
dig -x 2001:12ff::10 +short<br />
host 2001:12ff::10 </syntaxhighlight><br />
##2801:84:0:2::10<br />
##2001:12d0:0:126::183:244<br />
##2001:12ff::10<br />
##2804:1454:1004:100::2<br />
<br />
===Analisando o protocolo via Wireshark===<br />
Agora que já está ficando claro como funcionam as consultas DNS, deve-se investigar como se dá a comunicação entre seu computador e seu servidor DNS.<br />
#abra o navegador web e limpe o cache do mesmo;<br />
#abra o Wireshark e escolha a interface e inicie a captura de pacotes;<br />
#inicie a captura de pacotes no Wireshark;<br />
#no terminal digite '''dig +trace canon.jp''' (isso vai provocar a consulta DNS);<br />
#pare a captura de pacotes;<br />
#No Wireshark digite “dns” no filtro (sem as aspas);<br />
Com base nisso identifique o seguinte:<br />
#quantas mensagens são trocadas entre cliente e servidor DNS para cada consulta?<br />
#que protocolo de transporte é usado?<br />
#que portas de origem e destino são utilizadas?<br />
#qual o formato das mensagens DNS? Elas são textuais como as mensagens HTTP?<br />
#qual o tipo de registro DNS acessado em cada consulta?<br />
#que informações estão contidas nas respostas DNS? Há algo além do que foi pedido?<br />
#qual o tamanho das mensagens DNS?<br />
#qual endereço IP a mensagem de consulta DNS é enviada? Foi o mesmo ip obtido na seção anterior: seu servidor DNS?<br />
#examine a mensagem de consulta DNS. Qual o campo “type” desta mensagem?<br />
#a mensagem de consulta contém algum campo “answer”?<br />
#examine a mensagem de resposta DNS. Quantos campos com “answer” existem?<br />
#quais são os benefícios de usar o UDP ao invés do TCP como protocolo de transporte para o DNS?<br />
<br />
===Exemplos de arquivos de um ''Second Level Domain'' fictício===<br />
*Exemplo de arquivos de configuração de um servidor [https://www.isc.org/downloads/bind/ BIND]<br />
/etc/bind/db.redes <syntaxhighlight lang=bash><br />
$TTL 86400<br />
@ IN SOA ns.redes.edu.br. root (<br />
2016090900 ; Serial<br />
604800 ; Refresh<br />
86400 ; Retry<br />
2419200 ; Expire<br />
86400 ) ; Negative Cache TTL<br />
;<br />
@ IN NS ns.redes.edu.br.<br />
@ IN MX 10 mail.redes.edu.br.<br />
$ORIGIN redes.edu.br.<br />
ns A 192.168.1.101<br />
www A 192.168.1.102<br />
www A 192.168.1.103<br />
www A 192.168.1.104<br />
www A 192.168.1.105<br />
www A 192.168.1.106<br />
www A 192.168.1.107<br />
ftp A 192.168.1.108<br />
mail A 192.168.1.109 </syntaxhighlight><br />
<br />
/etc/bind/db.2.168.192 (Zona reversa) <syntaxhighlight lang=bash><br />
$TTL 86400<br />
@ IN SOA ns.redes.edu.br. root (<br />
2016090900 ; Serial<br />
604800 ; Refresh<br />
86400 ; Retry<br />
2419200 ; Expire<br />
86400 ) ; Negative Cache TTL<br />
;<br />
IN NS ns.redes.edu.br.<br />
101 IN PTR ns.redes.edu.br.<br />
102 IN PTR www.redes.edu.br.<br />
108 IN PTR ftp.redes.edu.br.<br />
109 IN PTR mail.redes.edu.br. </syntaxhighlight><br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 8 - Desvendando o UDP - Básico}}<br />
<br />
===Objetivos===<br />
<br />
*Familiarizar-se com o UDP<br />
*Entender a estrutura do pacote UDP<br />
*Entender o conceito de portas<br />
*Entender o conceito de multiplexação<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/UDP%20Basico.pdf Introdução a camada de transporte e UDP básico]<br />
<br />
===Parte 1 - Fluxo único UDP===<br />
<br />
#Combinar equipes com dois computadores para execução do experimento.<br />
#*Uma equipe escutará na porta 5000 e a outra equipe transmitirá uma mensagem nessa porta. Os processos de transmissão e recepção podem ocorrer simultaneamente, em terminais distintos.<br />
#*Cada equipe deve identificar os IPs ('''IP_DEST''') das máquinas de seus pares.<br />
#Cada equipe deve abrir uma Janela de terminal.<br />
#Cada equipe deve preparar o '''Wireshark''', interfaces '''any''', para escuta das portas no protocolo UDP usando um filtro:<syntaxhighlight lang=bash><br />
udp.port==5000</syntaxhighlight><br />
#A equipe da escuta na porta 5000 executa no terminal: <syntaxhighlight lang=bash><br />
netcat -u -l -p 5000 </syntaxhighlight><br />
#A equipe que irá transmitir para a porta 5000 executa no terminal: <syntaxhighlight lang=bash><br />
netcat -u IP_DEST 5000 </syntaxhighlight><br />
#*Em seguida escreve no terminal uma mensagem de até 20 caracteres, ao teclar <Enter> a mensagem será enviada.<br />
#*O wireshark deve ter capturado os pacotes UDP <br />
#Identifique e anote os seguintes dados na captura do wireshark:<br />
#*IP FONTE e DESTINO<br />
#*PORTAS FONTE E DESTINO para ambas comunicações<br />
#*Campo de protocolo no pacote IP<br />
#*Campo de tamanho (anote o tamanho) e ''checksum'' no pacote (datagrama) UDP<br />
#*O campo de dados no pacote UDP<br />
#Troquem os papéis das equipes: quem houvia agora transmite mensagens.<br />
#Cada equipe pode transmitir sequencialmente várias mensagens, devendo identificar múltiplos datagramas UDP.<br />
#PERGUNTAS baseadas na captura:<br />
##Qual o tamanho de cada campo do cabeçalho do pacote UDP?<br />
##Qual o tamanho máximo do número de porta?<br />
##Qual o tamanho máximo da área de dados (payload) do pacote?<br />
##Qual o número identificador de protocolo UDP no pacote IP? <br />
##Em algum momento foi identificado algum procedimento para estabelecimento de conexão? <br />
##Em algum campo do UDP existe numeração de mensagens?<br />
<br />
===Parte 2 - Experimento com UDP - MUX e DEMUX===<br />
<br />
#Conceber um adendo ao experimento anterior para demonstrar a multiplexação e demultiplexação de informação.<br />
#*Lembre-se que a demultiplexação permitirá que diferentes fluxos sejam encaminhados para diferentes processos. Nesse sentido, por exemplo, em uma mesma máquina pode-se abrir dois os mais terminais onde, em cada um deles, pode-se gerar ou aguardar fluxos distintos (diferenciados pelas portas).<br />
#Capture os pacotes com o Wireshark e caracterize quais pacotes pertencem a cada fluxo (porta).<br />
#Mostre o experimento ao professor, que projetará o mesmo no telão.<br />
<br />
'''DESAFIO''' (para casa?): capture e anote byte a byte o conteúdo de um pequeno pacote UDP (e dados IP) e calcule o CHECKSUM do mesmo (pesquise no google como fazer).<br />
{{Collapse bottom}}<br />
{{Collapse top |Laboratório 9 - Desvendando o TCP - Básico}}<br />
<br />
===Objetivos===<br />
<br />
*Verificar o comportamento básico do Protocolo TCP:<br />
**Fase de Estabelecimento de Conexão<br />
**Troca de Dados<br />
**Finalização da Conexão<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/TCP%20Basico.pdf Camada de transporte: TCP básico]<br />
<br />
==Configuração do Laboratório==<br />
O netkit2 deve ser atualizado manualmente com este procedimento:<br />
# Abrir um terminal<br />
# Baixar o programa do ''Netkit2'' com o comando: <syntaxhighlight lang=bash><br />
wget http://tele.sj.ifsc.edu.br/~msobral/netkit2/bin/netkit2<br />
</syntaxhighlight><br />
# Copiá-lo para o diretório do Netkit2 com o comando: <syntaxhighlight lang=bash><br />
cp netkit2 ${NETKIT2_HOME}/bin/<br />
</syntaxhighlight><br />
<br />
O roteiro será executado sobre 3 máquinas virtuais, através do uso do [[Netkit2 | Netkit2]]. Copie o texto abaixo no '''Gedit''' e salve com o nome '''/home/aluno/TCP.conf'''. <br />
<syntaxhighlight lang=text><br />
PC1[type]=generic<br />
PC2[type]=generic<br />
PC3[type]=generic<br />
<br />
<br />
PC1[eth0]=lan0:ip=10.0.0.1/24<br />
PC2[eth0]=lan0:ip=10.0.0.2/24<br />
PC3[eth0]=lan0:ip=10.0.0.3/24<br />
</syntaxhighlight><br />
<br />
===Verificando o estabelecimento, troca de dados e finalização da conexão===<br />
<br />
#Executar a configuração do laboratório no Netkit. Abra o NetKit2 e abra o arquivo de configuração: <syntaxhighlight lang=bash><br />
File > Load and Run </syntaxhighlight><br />
#*Perceba que abrirá uma janela com três abas inferiores, representando três máquina virtuais criadas pelo Netkit, denominadas: PC1, PC2 e PC3. Cada uma dessas abas é o terminal de configuração da respectiva máquina virtual.<br />
#Executar no PC2 um servidor TCP aguardando na porta 5555 na forma: <syntaxhighlight lang=bash> netcat -l 5555 </syntaxhighlight><br />
#*Obs.: para copiar texto para as máquinas do NetKit, pode-se copiar normalmente o texto e em seguida, no terminal do NetKit apropriado, clique na "rodinha" do mouse.<br />
#*Em uma comunicação TCP um processo é servidor (aguarda pedido de conexão) e um processo é o cliente, que gera um pedido de conexão<br />
#Executar no PC3 o tcpdump com foco na porta tcp 5555 e para salvar pacotes em arquivo: <syntaxhighlight lang=bash> tcpdump -i eth0 tcp port 5555 -s 1024 -U -w /hostlab/shared/pc3.cap </syntaxhighlight><br />
#Executar no PC1 um cliente TCP que solicita uma conexão ao servidor: <syntaxhighlight lang=bash> netcat 10.0.0.2 5555 </syntaxhighlight><br />
#Enviar uma pequena mensagem de 5 caracteres, e no final teclar ENTER e depois CTRL+D.<br />
#*O CTRL-D encerra a conexão no netcat<br />
#Vá até o terminal do PC3 e encerre a captura de pacotes do '''tcpdump''' digitando CTRL+C.<br />
#Abrir o arquivo de captura gravado no PC3 com o Wireshark. Temos duas possibilidades para fazer isso, escolha uma das duas:<br />
##Abrir o Wireshark e ir no menu File > Open > Pasta Pessoal > lab > shared > pc3.pcap<br />
##Abrir o "navegador de arquivos" e encontrar procurar o arquivo na pasta aluno/lab/shared/pc3.pcap (/home/aluno/lab/shared/pc3.pcap).<br />
#Todos pacotes TCP, desde o estabelecimento até a desconexão devem estar capturados. Um exemplo dessa captura encontra-se na Figura 1.<br />
[[Arquivo:WiresharkTCP.png |thumb | 600px| Fig.1 -- Protocolo TCP]]<br />
#O processo de conexão do TCP envolve a troca de 3 pacotes e é sempre iniciado pelo cliente. O cliente envia um pacote SYN, o servidor responde com um SYN-ACK e o cliente finalmente responde com ACK. Observe estes pacotes no wireshark.<br />
#*Pratique seu inglês e leia um pouco sobre este processo de estabelecimento de conexão em [https://en.wikipedia.org/wiki/Transmission_Control_Protocol#Connection_establishment Connection Establishment] <br />
#Baseado na captura de pacotes realizada responda:<br />
##Quais foram as portas de origem e destino usadas?<br />
##Quais os tamanhos das janelas informadas, tanto pelo cliente quanto pelo servidor?<br />
##Quais os números de sequência informado pelo Wireshark e o número que consta no campo Data em bytes. Qual é relação entre esses números?<br />
##Em qual mensagem (número) aparece a texto que você digitou?<br />
##Qual o número identificador de protocolo TCP no pacote IP?<br />
#*Um dos objetivos do processo de conexão é sincronizar o número de sequência. Cada lado fica sabendo do número de sequência do outro. O número de sequência não começa com zero.<br />
#*O Wireshark converte a numeração para mostrar a partir do 0 mas o número inicial de sequência é criado randomicamente por cada lado. (ver [https://wiki.wireshark.org/TCP_Relative_Sequence_Numbers])<br />
#Volte ao wireshark e analise o processo de termino da conexão (iniciado pelo cliente neste caso, no momento do CTRL+D).<br />
#*Note que qualquer uma das partes pode realizar esta finalização.<br />
#*Pode ser observado que o cliente envia um pacote TCP com flag FIN.<br />
#*O servidor responde com um FIN-ACK.<br />
#*Finalmente o cliente faz um ACK. <br />
#*Veja se confere com a figura [http://www.tcpipguide.com/free/t_TCPConnectionTermination-2.htm Término de conexão TCP] ou com os [http://docente.ifsc.edu.br/odilson/RCO60803/TCP%20Basico.pdf slides] apresentados no início da aula.<br />
#Gere com o wireshark um diagrama da comunicação, ou diagrama de troca de mensagens, fazendo: Statistics > Flow Graph > OK<br />
#Analise esse diagrama, observando qual pacote contém os dados, ou seja, o texto que você digitou.<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 10 - Desvendando o TCP - Número de Sequência, Controle de Erros e Funcionamento Full-Duplex}}<br />
<br />
===Objetivos===<br />
<br />
*Verificar:<br />
**Controle de Erros: Significado de Número de Sequência, ACK<br />
**Controle de Fluxo: Significado do campo Windows Size; Funcionamento do controle de fluxo;<br />
**Comportamento Full-Duplex<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/TCP%20controle%20de%20erros.pdf TCP - Controle de Erros]<br />
<br />
==Configuração do Laboratório==<br />
O roteiro será executado sobre máquinas virtuais, através do uso do [[Netkit2 | Netkit2]]. Copie o texto abaixo, abra o editor Gedit, cole o texto e salve o arquivo em /home/aluno/TCP.conf.<br />
<syntaxhighlight lang=bash><br />
PC1[type]=generic<br />
PC2[type]=generic<br />
PC3[type]=generic<br />
<br />
<br />
PC1[eth0]=lan0:ip=10.0.0.1/24<br />
PC2[eth0]=lan0:ip=10.0.0.2/24<br />
PC3[eth0]=lan0:ip=10.0.0.3/24<br />
</syntaxhighlight><br />
<br />
===PARTE 1 - Transmissão sem erros: Verificação de Número de Sequência, Reconhecimentos e Controle de Fluxo===<br />
#Executar a configuração do laboratório no Netkit. Abra o NetKit2 e abra o arquivo de configuração: <syntaxhighlight lang=bash><br />
File > Load and Run </syntaxhighlight><br />
#*Perceba que abrirá uma janela com três abas inferiores, representando três máquina virtuais criadas pelo Netkit, denominadas: PC1, PC2 e PC3. Cada uma dessas abas é o terminal de configuração da respectiva máquina virtual.<br />
#Utilize o editor de texto '''gedit''' da máquina real, inclua o texto abaixo, e salve como '''/home/aluno/lab/shared/arq.tx''' <syntaxhighlight lang=bash><br />
ABCDEFGHIJKLMNOPQRSTUVXZW1234 </syntaxhighlight><br />
#Execute o tcpdump no PC3 <syntaxhighlight lang=bash><br />
tcpdump -i eth0 tcp port 5555 -s 1024 -U -w /hostlab/shared/pc3.pcap </syntaxhighlight><br />
#Execute os comandos abaixo no PC2 (copie e cole).<br />
##O primeiro comando limita sua capacidade de recepção em cerca de 20 bytes (tamanho do ''buffer''). Isto permitirá ver a quebra do arquivo de 30 bytes em alguns segmentos TCP.<br />
##O segundo comando abre a porta 5555, através do netcat, e espera a chegada dos dados.<syntaxhighlight lang=bash><br />
sysctl -w net.ipv4.tcp_rmem='20 20 20'<br />
netcat -l 5555 > arq.rx </syntaxhighlight><br />
#Envie o arquivo arq.tx a partir do PC1 com o comando:<syntaxhighlight lang=bash><br />
netcat 10.0.0.2 5555 < /hostlab/shared/arq.tx </syntaxhighlight><br />
#No PC3 faça CTRL+C, para parar a captura de pacotes.<br />
#Abra o arquivo de captura gravado no PC3 (/home/aluno/lab/shared/pc3.pcap) com o Wireshark:<br />
##Abrir o Wireshark e ir no menu File > Open > Pasta Pessoal > lab > shared > pc3.pcap<br />
#Você terá algo parecido com o apresentado na Figura 1.[[Arquivo:WiresharkTCPPerdaDePacotes.png |thumb | 600px| Fig.1 -- Protocolo TCP]]<br />
#Analise como os dados foram transmitidos e reconhecidos.<br />
====Perguntas====<br />
#Qual o número de sequência (normalizado pelo Wireshark) de cada segmento de dados transmitido (de PC1 para PC2) e qual o significado do número de reconhecimento em cada um deles? <br />
#Como foi reconhecido cada segmento enviado? <br />
#*Relate esta análise por segmento usando os timestamps (coluna Time) como referência.<br />
<br />
====Arquivo CAP deste experimento====<br />
<br />
*[https://www.dropbox.com/s/cv82wa1r3jatvgp/tcp_parte1-pc3-sequencia-controle-fluxo.cap Sequencia.cap]<br />
<br />
===PARTE 2 - Transmissão com erros: retransmissões===<br />
<br />
#Repetir todo a parte 1 mas substituir o item 4 por: <syntaxhighlight lang=bash><br />
sysctl -w net.ipv4.tcp_rmem='20 20 20'<br />
tc qdisc add dev eth0 root netem loss 50% <br />
netcat -l 5555 > arq.rx </syntaxhighlight><br />
Perguntas:<br />
#Qual o número de sequência (normalizado pelo Wireshark) de cada segmento de dados transmitido (de PC1 para PC2) e qual o significado do número de reconhecimento em cada um deles?<br />
#Como foi reconhecido cada segmento enviado?<br />
#Houve perda de pacotes? Como você identificou isso?<br />
#Os pacotes perdidos foram retransmitidos? Justifique.<br />
<br />
====arquivo cap deste experimento====<br />
<br />
*[https://www.dropbox.com/s/fb9izlu3ykin4yt/pc3-retransmissoes.cap retransmissoes.cap]<br />
<br />
===PARTE 3 - Testando a capacidade do TCP de enviar dados de forma duplex===<br />
<br />
*Agora vamos deixar de lado o netkit para fazer um pequeno teste de transmissão de arquivos entre dois colegas.<br />
*No experimento, o arquivo de um aluno será transmitido para outro e vice-versa.<br />
<br />
#Em um terminal da máquina real, crie um diretório de trabalho e entre no mesmo <syntaxhighlight lang=bash><br />
mkdir teste<br />
cd teste </syntaxhighlight><br />
#Com o '''gedit''' construa um arquivo de cerca de 2000 bytes. Coloque neste arquivo o seu poema ou letra de canção preferida. Salve o arquivo com nome '''/home/aluno/teste/arq.tx'''.<br />
#Escolha um colega para transferir o arquivo.<br />
##Negocie quem será o servidor e quem será o cliente.<br />
##No processo, o arquivo criado por um aluno será enviado ao colega e vice-versa (tx, rx).<br />
#O servidor deve fazer <syntaxhighlight lang=bash><br />
netcat -l 5555 < arq.tx > arq.rx </syntaxhighlight><br />
#*Ao término da transmissão, o arq.rx conterá os dados recebidos.<br />
#O cliente deve fazer, <span style="color: red;">lembre-se de adequar o IP_SERVIDOR<syntaxhighlight lang=bash><br />
netcat IP_SERVIDOR 5555 < arq.tx > arq.rx </syntaxhighlight><br />
#*<span style="color: black;">Ao término da transmissão, o arq.rx conterá os dados recebidos.<br />
#Abra o arquivo recebido do colega (arq.rx) com o '''gedit''' e confira o conteúdo.<br />
Perguntas:<br />
#Onde pode ser observado a comunicação ''full-duplex''?<br />
#Qual é a relação entre os comandos do cliente e servidor com a comunicação ''full-duplex''?<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 11 - Controle de congestionamento e equidade do TCP}}<br />
<br />
===Objetivos===<br />
*Tem como objetivo gerar um gráfico para facilitar a visualização do '''controle de congestionamento''' e a consequente '''equidade''' do protocolo TCP.<br />
*Utilizar o software [https://iperf.fr/ Iperf] (iperf –h para help) para gerar tráfego entre duas máquinas, '''cliente''' e '''servidor'''.<br />
*Utilizar o software [[netkit2]].<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/TCP%20controle%20de%20congestionbamento%20e%20equidade.pdf TCP - Controle de Congestionamento e Equidade]<br />
*[https://media.pearsoncmg.com/aw/ecs_kurose_compnetwork_7/cw/content/interactiveanimations/tcp-congestion/index.html Animação do controle de congestinamento]<br />
<br />
===Roteiro===<br />
*O roteiro será executado sobre máquinas virtuais, através do uso do [[Netkit2 | Netkit2]].<br />
*Para realização dos ensaios será montada a rede virtual apresentada na Figura 1. <br />
<br />
[[Arquivo:TCP_Rede_Controle_de_Fluxo.png |thumb | 200px| Figura 1 - Rede ara testes]]<br />
#Copie o texto abaixo e crie um arquivo com o '''Gedit''', salve-o como /home/aluno/TCP.conf.<syntaxhighlight lang=bash><br />
# Definição das máquinas<br />
R1[type]=router<br />
PC1[type]=generic<br />
PC2[type]=generic<br />
PC3[type]=generic<br />
<br />
# Definição dos roteadores padrão<br />
PC1[default_gateway]=10.0.0.254<br />
PC2[default_gateway]=10.0.1.254<br />
PC3[default_gateway]=10.0.1.254<br />
<br />
# Definição das interfaces do roteador <br />
R1[eth0]=lan0:ip=10.0.0.254/24:rate=10000<br />
R1[eth1]=lan1:ip=10.0.1.254/24:rate=10000<br />
<br />
# Definição das interfaces dos PCs<br />
PC1[eth0]=lan0:ip=10.0.0.1/24:rate=10000<br />
PC2[eth0]=lan1:ip=10.0.1.2/24:rate=10000<br />
PC3[eth0]=lan1:ip=10.0.1.3/24:rate=10000 </syntaxhighlight><br />
#Execute o NetKit2.<br />
#Carregue o arquivo de configuração: <syntaxhighlight lang=bash><br />
File > Load and Run </syntaxhighlight><br />
#*Perceba que abrirá uma janela com quatro abas inferiores, representando um roteador e três máquina virtuais criadas pelo Netkit, denominadas: R1, PC1, PC2 e PC3. Cada uma dessas abas é o terminal de configuração do respectivo equipamento.<br />
#*Ao clicar no menu '''File - Graph''', pode-se ter uma visão da rede a ser simulada e conferir se é equivalente ao diagrama proposto.<br />
#Execute no PC3 o tcpdump para salvar a troca de dados entre o PC1 e o PC2 num arquivo: <syntaxhighlight lang=bash><br />
tcpdump -i eth0 -w /hostlab/shared/pc3.cap </syntaxhighlight><br />
#*Para copiar comando para os terminais das máquinas virtuais: copie o texto desejado, no Netkit selecione o terminal da máquina desejada e clique sobre a "rodinha" do mouse que o texto será colado.<br />
#No PC1 (servidor) execute: <syntaxhighlight lang=bash><br />
iperf -s -p 2000 & iperf -s -p 2001 & iperf -s -p 2002 & </syntaxhighlight><br />
#No PC2 (cliente) execute (copie a três linhas e cole no terminal adequado e em seguida tecle <Enter>): <syntaxhighlight lang=bash><br />
iperf -c 10.0.0.1 -f m -i 1 -t 90 -p 2000 -l 1300 & \<br />
(sleep 20; iperf -c 10.0.0.1 -f m -i 1 -t 70 -p 2001 -l 1300) & \<br />
(sleep 30; iperf -c 10.0.0.1 -f m -i 1 -t 60 -p 2002 -l 1300) & </syntaxhighlight><br />
#Fique monitorando o PC2 até a tela parar de ser atualizada, aproximadamente 90 s.<br />
#Pare os processos nos três PCs utilizando CTRL-C.<br />
#Abra o Wireshark.<br />
#Abra o arquivo <syntaxhighlight lang=bash><br />
File > Open > /home/aluno/lab/shared/pc3.cap </syntaxhighlight><br />
#No wireshark acesse '''Statistics''' >> '''IO Graph''' e, na tela que abrir, ajuste TODOS os parâmetros para obter um gráfico similar ao apresentado na Figura 2.<br />
#*Perceba que todos os botões '''Graph 1...4''' devem ser clicados, e os filtros aplicados (tcp.port==2000; tcp.port==2001; tcp.port==2002) isso fará com que o Wireshark mostre as respectivas curvas. [[Arquivo:TCP_Wireshark.png |thumb | 400px| Figura 2 - Captura de 3 fluxos de dados]]<br />
#Responda:<br />
##Explique detalhadamente o significado de cada parâmetro dos comandos dos itens 5 e 6 acima, tanto do cliente quanto do servidor.<br />
##Explique os filtros aplicados no gráfico do Wireshark.<br />
##*Quais são os 4 gráficos apresentados?<br />
##*Há uma relação de valor entre as curvas?<br />
##*Qual é esta relação?<br />
##Por que a curva vermelha se sobrepõe a curva preta nos primeiros 20 segundos? Considere o início do tempo onde há início de tráfego!<br />
##Qual é a relação entre a curva preta e as curvas vermelha e verde no intervalo entre 20 e 30 segundos?<br />
##Explique a relação entre as 4 curvas e o comando do cliente (item 5) no intervalo entre 20 e 40 segundos.<br />
##Qual é o mecanismo do TCP que explica a grande oscilação das curvas, principalmente percebida no intervalo entre 20 e 30 segundos?<br />
<br />
=====Incluindo UDP=====<br />
Agora vamos dificultar a vida do TCP incluindo um tráfego UDP. O gráfico gerado deverá apresentar a competição pelo meio de transmissão entre os diversos fluxos de dados.<br />
#Deslique o NetKit2, para limpar todos os processos e ''buffers'': <syntaxhighlight lang=bash><br />
File > Quit </syntaxhighlight><br />
#Copie o texto abaixo e crie um arquivo, salve-o como /home/aluno/TCPxUDP.conf: <syntaxhighlight lang=bash><br />
# Definição das máquinas<br />
R1[type]=router<br />
PC1[type]=generic<br />
PC2[type]=generic<br />
PC3[type]=generic<br />
PC4[type]=generic<br />
<br />
# Definição dos roteadores padrão<br />
PC1[default_gateway]=10.0.0.254<br />
PC2[default_gateway]=10.0.1.254<br />
PC3[default_gateway]=10.0.1.254<br />
PC4[default_gateway]=10.0.1.254<br />
<br />
# Definição das interfaces do roteador <br />
R1[eth0]=lan0:ip=10.0.0.254/24:rate=10000<br />
R1[eth1]=lan1:ip=10.0.1.254/24:rate=10000<br />
<br />
# Definição das interfaces dos PCs<br />
PC1[eth0]=lan0:ip=10.0.0.1/24:rate=10000<br />
PC2[eth0]=lan1:ip=10.0.1.2/24:rate=10000<br />
PC3[eth0]=lan1:ip=10.0.1.3/24:rate=10000<br />
PC4[eth0]=lan1:ip=10.0.1.4/24:rate=10000 </syntaxhighlight><br />
#Execute o NetKit2 e carregue o arquivo de configuração.<br />
#No PC4 execute: <syntaxhighlight lang=bash><br />
tcpdump -i eth0 -w /hostlab/shared/pc4.cap </syntaxhighlight><br />
#No PC1 execute: <syntaxhighlight lang=bash><br />
iperf -s -u -p 2000 & iperf -s -p 2001 & </syntaxhighlight><br />
#A próxima etapa deve ser executada "simultaneamente" nos PC2 e PC3.<br />
##Para isso copie o texto abaixo e cole no terminal do PC2, ainda NÃO tecle <Enter>: <syntaxhighlight lang=bash><br />
iperf -u -c 10.0.0.1 -f m -i 1 -t 60 -p 2000 -l 1300 -b 10000000 </syntaxhighlight><br />
##Copie o texto abaixo e cole no terminal do PC3, ainda NÃO tecle <Enter>: <syntaxhighlight lang=bash><br />
iperf -c 10.0.0.1 -f m -i 1 -t 90 -p 2001 -l 1300 </syntaxhighlight><br />
##Tecle <Enter> no PC3 e PC2, NESSA ORDEM, "simultaneamente".<br />
#Fique monitorando o PC3 a tela parar de ser atualizada, aproximadamente 90 s.<br />
#Pare os processos nos quatro PCs utilizando CTRL-C.<br />
#Rode o Wireshark e abra o arquivo /home/aluno/lab/shared/pc4.cap.<br />
#Baseado na Figura 3, no '''Graph 2''' altere o filtro para '''udp.port==2000''' e no '''Graph 3''' altere o filtro para '''tcp.port==2001'''. Salve o gráfico gerado.<br />
[[Arquivo:TCPxUDP_Wireshark.png |thumb | 400px| Figura 3 - Captura de 2 fluxos de dados TCP e UDP]]<br />
#Responda as mesmas questões do item anterior, '''todas'''.<br />
#Explique o comportamento dos vários fluxos de dados com e sem o UDP.<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 12 - TCP x UDP}}<br />
<br />
===Objetivos===<br />
*O objetivo desses experimentos é evidenciar as diferenças entre os protocolos TCP e UDP.<br />
*Ambos protocolos de transporte podem ser usados por aplicações que precisem se comunicar. Porém cada um deles têm certas propriedades, então a escolha precisa ser realizada baseada no tipo de comunicação a ser feita pela aplicação.<br />
<br />
==== Experimento 1 ====<br />
<span style="color: red;">Antes de qualquer experimento deve-se desabilitar algumas funcionalidades do kernel do LINUX, para que os experimentos reflitam a teoria. Caso sua interface de rede não seja a '''eth0''' adapte o comando, caso reiniciar a máquina repita-o:</span><br />
<syntaxhighlight lang=bash>sudo ethtool --offload eth0 gso off tso off sg off gro off </syntaxhighlight><br />
<br />
O que aconteceria se um arquivo fosse transferido de um computador a outro com ambos protocolos?<br />
<br />
# Abra um terminal e execute o seguinte comando para fazer o download de um arquivo a ser usado no experimento: <syntaxhighlight lang=bash><br />
wget http://tele.sj.ifsc.edu.br/~odilson/RED29004/jogo.exe<br />
</syntaxhighlight><br />
# Observe o tamanho do arquivo transferido ... ele deve ter exatamente 332831416 bytes (cerca de 318 MB). Você pode fazer isso com o comando '''ls -l jogo.exe''', ou executando o gerenciador de arquivos e visualizando as propriedades desse arquivo.<br />
# Escolha um colega para fazer o experimento em que o arquivo será transferido de um computador para o outro. NÃO pode ser na própria máquina. Um será o '''receptor''' e outro o '''transmissor'''.<br />
=====A primeira transferência será feita usando o protocolo TCP da seguinte forma=====<br />
#Execute o WireShark e deixe-o capturando pacotes '''somente''' durante a transferência do arquivo. Como o o comportamento padrão do wireshark é redefinir o número de sequência para sempre iniciar em um e isso pode atrapalhar nossos experimentos, vamos '''desabilitar/desativar''' essa funcionalidade: <syntaxhighlight lang=bash><br />
Edit >> Preferences >> Protocols >> TCP >> Relative sequence numbers </syntaxhighlight><br />
#No computador '''receptor''' execute o '''netcat''' ('''nc''') (utilize '''man nc''' para saber os detalhes das ''flags'' utilizadas) que abrirá uma conexão TCP na porta, por exemplo, 5555 e salvará os dados transferidos em '''arquivo''': <syntaxhighlight lang=bash><br />
nc -vvnl 5555 > arquivoTCP<br />
</syntaxhighlight><br />
#No computador '''transmissor''' execute, após o processo do '''receptor''' estar executando ('''adeque o ip_do_receptor para o devido número IP'''): <syntaxhighlight lang=bash><br />
time nc -vvn ip_do_receptor 5555 < jogo.exe<br />
</syntaxhighlight><br />
#Quando completar a transferência, pare o Wireshark.<br />
#Verifique o tamanho do arquivo recebido. Ele é igual ao arquivo original? E quanto tempo levou para transmiti-lo? No terminal digite: <syntaxhighlight lang=bash><br />
ls -l </syntaxhighlight><br />
#Analisando a captura de pacotes do WireShark responda:<br />
## Quais as portas origem e destino escolhidas pelo cliente e servidor?<br />
## Qual é o número de sequência do primeiro e do último pacote?<br />
## Qual é o número de sequência do primeiro e do último ACK?<br />
## Qual o Tamanho Máximo de Segmento (MSS) escolhidos pelo cliente e servidor na conexão.<br />
## É possível calcular o tamanho do arquivo pela análise dos pacotes? Qual é a maneira mais fácil? Apresente os cálculos ou descreva a maneira de obtenção do valor.<br />
## Qual é o tamanho do último segmento de dados recebido?<br />
## Todos os segmentos trocados entre as máquinas contém dados ou alguns são somente de controle? Qual o percentual aproximado de segmentos de controle?<br />
<br />
=====A segunda transferência será feita usando o protocolo UDP=====<br />
#Execute o WireShark e deixe-o capturando pacotes '''somente''' durante a transferência do arquivo.<br />
#Combine com um colega e estabeleça quem suem será o transmissor e quem será o receptor. No computador '''receptor''' baixe o programa '''receptor''', acrescente a ele permissão de execução e o execute, conforme a sequência de comandos abaixo: <syntaxhighlight lang=bash><br />
wget http://tele.sj.ifsc.edu.br/~odilson/RED29004/receptor<br />
chmod +x receptor<br />
./receptor 5555 > arquivoUDP<br />
</syntaxhighlight><br />
#No computador '''transmissor''' baixe o programa '''transmissor''', acrescente a ele permissão de execução e o execute, conforme a sequência de comandos abaixo: <syntaxhighlight lang=bash><br />
wget http://tele.sj.ifsc.edu.br/~odilson/RED29004/transmissor<br />
chmod +x transmissor </syntaxhighlight><br />
#Inicie a transferência do arquivo ('''adeque o ip_do_receptor para o número IP do colega'''): <syntaxhighlight lang=bash><br />
./transmissor ip_do_receptor 5555 < jogo.exe<br />
</syntaxhighlight><br />
#Quando completar a transferência (vai aparecer a mensagem no '''transmissor''' "Levou XXXXX segundos para transmitir XXXXX bytes).<br />
#No '''receptor''' digite <CTRL + C><br />
#Verifique o tamanho do arquivo recebido.<br />
##Ele é igual ao arquivo original?<br />
##Quanto tempo levou para transmiti-lo?<br />
#Analisando a captura de pacotes do WireShark responda:<br />
## Qual é o número de sequência do primeiro e do último pacote? Existe?<br />
## É possível calcular o tamanho do arquivo pela análise dos pacotes? É mais fácil ou difícil que no caso da transferência via TCP?<br />
## Há segmentos de controle ou somente segmentos de dados?<br />
## Qual é o tamanho do último segmento de dados recebido?<br />
# Compare as transferências feitas com os protocolos TCP e UDP.<br />
## O que eles têm em comum?<br />
## Que diferenças lhe pareceram mais pronunciadas?<br />
## Como isso deve afetar as aplicações que usam esses protocolos?<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 13 - Interligação de duas redes locais via um roteador}}<br />
<br />
===Objetivos===<br />
<br />
*Introdução ao mundo IP<br />
*Verificação das configurações de interfaces<br />
*Verificação de tabelas de roteamento nos hospedeiros e no roteador<br />
*Verificação de roteamento no roteador<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IP%20Basico.pdf Introdução a Camada de Rede]<br />
*[http://tele.sj.ifsc.edu.br/~eraldo/AULAS/2018-2/RCO-INTEGRADO/MACxIP.pdf Endereçamento MAC x Endereçamento IP]<br />
<br />
===Procedimento===<br />
<br />
#Construir uma rede no Netkit com dois PCs e um roteador. Use um arquivo lab.conf da forma: <syntaxhighlight lang=text><br />
r1[type]=router<br />
<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
r1[eth0]=lan0:ip=192.168.200.254/24<br />
r1[eth1]=lan1:ip=192.168.100.254/24<br />
<br />
pc1[eth0]=lan0:ip=192.168.200.1/24<br />
pc1[default_gateway]=192.168.200.254<br />
<br />
pc2[eth0]=lan0:ip=192.168.200.2/24<br />
pc2[default_gateway]=192.168.200.254<br />
<br />
pc3[eth0]=lan1<br />
<br />
pc4[eth0]=lan1:ip=192.168.100.2/24<br />
pc4[default_gateway]=192.168.100.254<br />
</syntaxhighlight><br />
#Chamar o netkit2 (Aplicativos >> Educativo >> Netkit2)<br />
#Forçar a atualização do Netkit2: <syntaxhighlight lang=text> General >> Update </syntaxhighlight><br />
#Carregar o arquivo '''lab.conf''' a partir do Netkit2:<syntaxhighlight lang=bash><br />
File >> Load Only<br />
</syntaxhighlight><br />
#Visualizar a rede a ser implementada:<syntaxhighlight lang=bash><br />
File >> Graph<br />
</syntaxhighlight><br />
#Executar a rede: <syntaxhighlight lang=bash><br />
Network >> Start<br />
</syntaxhighlight><br />
#Copie o diagrama da rede para o papel e, para todas interfaces de rede apresentadas no diagrama, anote, baseados nos comandos dos itens seguintes:<br />
##Endereço IP<br />
##Endereço MAC<br />
##Roteador padrão<br />
#Observar os endereços de hardware (ou MAC) e IP de cada dispositivo na rede. No terminal de cada '''pc''' execute: <syntaxhighlight lang=bash><br />
ifconfig </syntaxhighlight><br />
#Observar e interpretar a tabela de roteamento nos hospedeiros '''pc1''' e '''pc4'''. Identificar os ''default gateways'' em cada '''pc'''.<syntaxhighlight lang=bash><br />
route -n<br />
</syntaxhighlight><br />
#Observar e interpretar a tabela de roteamento no roteador ('''r1''')<syntaxhighlight lang=bash><br />
exit<br />
route -n<br />
</syntaxhighlight><br />
#Observar e "provar" que pacotes indo de '''pc1''' para '''pc4''' são encaminhados ao roteador e, em seguida, entregues ao destino, ou seja, entrega indireta.<br />
#*Use o '''ping''', '''tcpdump''' e seu diagrama de rede como apoio.<br />
#*Lembre-se que você pode verificar o fluxo de dados individualmente em cada interface de rede e, portanto, se certificar que se há ou não pacotes atravessando o roteador:<br />
#**Num primeiro momento em '''r1''':<syntaxhighlight lang=bash><br />
tcpdump -i eth0 -n -e</syntaxhighlight><br />
#**Em seguida, ainda em '''r1''': <syntaxhighlight lang=bash><br />
tcpdump -i eth1 -n -e</syntaxhighlight><br />
#**Ver: [http://www.tcpdump.org/tcpdump_man.html manpage do tcpdump]<br />
#Observar e "provar" que pacotes indo de '''pc1''' para '''pc2''' na '''lan0''' são enviados diretamente para '''pc2''', ou seja, entrega direta.<br />
#*Use o '''ping''' e '''tcpdump''' como apoio, adequando os comandos apresentados no item anterior.<br />
<br />
===Configuração básica de interface de rede===<br />
#Configure a interface de rede no '''pc3'''.<br />
#*O mesmo deverá ser capaz de "pingar" para qualquer outro PC ou ser "pingado".<br />
#*Dica: observe a configuração de rede do '''pc4''' e tente adaptá-la para o '''pc3'''.<br />
#*Dica de ferramentas de configuração: use os comandos '''ifconfig''' e '''route'''. Use o '''man''' ou procure na web como utilizar esses comandos.<br />
#Execute o comando ping do '''pc3''' para o '''pc4'''. Obteve sucesso?<br />
#Execute o comando ping do '''pc3''' para o '''pc1'''. Obteve sucesso?<br />
#Execute o comando ping do '''pc2''' para o '''pc3'''. Obteve sucesso?<br />
<br />
====Referências adicionais====<br />
<br />
* [http://linux-ip.net/html Guia de Administração da Camada IP no Linux<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 14 - Roteamento Estático em Redes }}<br />
<br />
===Objetivo===<br />
<br />
*Proporcionar ao aluno uma visão prática de roteamento IP.<br />
*Princípios de configuração de rotas.<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IP%20Roteamento.pdf Introdução ao Roteamento]<br />
<br />
====PARTE 1 - Rede com 3 roteadores====<br />
<br />
:Laboratório a ser montado no netkit.<br />
<br />
[[Image:LabRoteamento-RCO1-2017-2.png |thumb | 800px| Figura 1 - Rede para roteamento]]<br />
<br />
#Construir a rede apresentada na Figura 1, usando como apoio a configuração do netkit descrita na sequência. As sub-redes (SN) a serem utilizadas na parte 1 e 2 são:<br />
## SN1 : 200.10.1.0/24<br />
## SN2 : 200.10.2.0/24 <br />
## SN3 : 200.10.3.0/24<br />
## SN4 : 200.10.4.0/24<br />
## SN5 : 200.10.5.0/24 <br />
## SN6 : 200.10.6.0/24 <br />
## SN7 : 200.10.7.0/24 <br />
## SN8 : 200.10.8.0/24<br />
#Abaixo o arquivo de configuração para o NetKit. Copie e salve como '''/home/aluno/roteamento.conf'''.<syntaxhighlight lang=text><br />
<br />
H1[type]=generic<br />
H2[type]=generic<br />
<br />
R1[type]=generic<br />
R2[type]=generic<br />
R3[type]=generic<br />
<br />
<br />
H1[eth0]=SN1:ip=200.10.1.1/24<br />
H2[eth0]=SN8:ip=200.10.8.1/24<br />
<br />
R1[eth0]=SN1:ip=200.10.1.254/24<br />
R1[eth1]=SN4:ip=200.10.4.1/24<br />
R1[eth2]=SN2:ip=200.10.2.1/24<br />
<br />
<br />
R2[eth0]=SN8:ip=200.10.8.254/24<br />
R2[eth1]=SN4:ip=200.10.4.2/24<br />
R2[eth2]=SN7:ip=200.10.7.1/24<br />
<br />
R3[eth0]=SN2:ip=200.10.2.2/24<br />
R3[eth1]=SN7:ip=200.10.7.2/24 </syntaxhighlight><br />
#Inicie o Netkit e carregue o arquivo de configuração e execute-o.<br />
#Execute comandos de ping entre os hosts e roteadores.<br />
##O ping entre as interfaces/equipamentos pertencentes a mesma sub-rede funcionam, por quê?<br />
##O ping entre interfaces/equipamentos de sub-redes distintas não funcionam, por quê?<br />
#Usando como apoio os comandos de inserção de rota insira as rotas default em H1 e H2:<br />
##H1: <syntaxhighlight lang=bash> route add default gw 200.10.1.254 </syntaxhighlight><br />
##H2: <syntaxhighlight lang=bash> route add default gw 200.10.8.254 </syntaxhighlight><br />
#Habilitar o roteamento e instalar rotas em cada roteador para que pacotes vindos de H1 para H2 passem por R1, R3 e R2. O retorno deve ser via R2 e R1.<br />
##R1: <syntaxhighlight lang=bash><br />
echo 1 > /proc/sys/net/ipv4/ip_forward<br />
echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth0/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth1/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth2/rp_filter<br />
route add -net 200.10.8.0/24 gw 200.10.2.2 </syntaxhighlight><br />
##R2: <syntaxhighlight lang=bash><br />
echo 1 > /proc/sys/net/ipv4/ip_forward<br />
echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth0/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth1/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth2/rp_filter<br />
route add -net 200.10.1.0/24 gw 200.10.4.1 </syntaxhighlight><br />
##R3: <syntaxhighlight lang=bash><br />
echo 1 > /proc/sys/net/ipv4/ip_forward<br />
echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth0/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth1/rp_filter<br />
route add -net 200.10.8.0/24 gw 200.10.7.1<br />
route add -net 200.10.1.0/24 gw 200.10.2.1 <br />
</syntaxhighlight><br />
#Teste a conectividade IP com o comando ping.<br />
##O ping entre as interfaces/equipamentos pertencentes a mesma sub-rede funcionam, por quê?<br />
##O ping entre interfaces/equipamentos de sub-redes distintas não funcionam, por quê?<br />
#Confirme os caminhos estabelecidos monitorando as interfaces com o tcpdump e/ou traceroute.<br />
<br />
====PARTE 2 - Desafio: Rede com 4 roteadores====<br />
<br />
#Crie um arquivo de configuração que descreva a rede abaixo no '''netkit'''.<br />
##Observe que essa rede tem somente um roteador a mais que a rede apresentada anteriormente.<br />
##As rotas devem ser configuradas de forma que pacotes que trafegam de H1 para H2 passem por R1, R3, R4 e R2.<br />
##O retorno (H2 ==> H1) deve ser por R2, R4 e R1.<br />
##Cada sub-rede SN está em uma rede ethernet separada.<br />
##Chame o professor e mostre que os roteamentos estão sendo realizados corretamente, com o apoio do tcpdump e tracerotue.<br />
<br />
* SN1 : 200.10.1.0/24<br />
* SN2 : 200.10.2.0/24 <br />
* SN3 : 200.10.3.0/24 <br />
* SN4 : 200.10.4.0/24 <br />
* SN5 : 200.10.5.0/24 <br />
* SN6 : 200.10.6.0/24 <br />
* SN7 : 200.10.7.0/24 <br />
* SN8 : 200.10.8.0/24<br />
<br />
[[Image:ExercicioConfEstaticaZebra.png]]<br />
<br />
====PARTE 3 - Criando loop para verificar o campo TTL====<br />
<br />
#Crie um conjunto de rotas que façam que um pacote vindo de H1 para H2 entre em um loop entre R1, R3, R2, R1.<br />
#Envie um pacote único com o ping de H1 para H2.<br />
#Rastreie com o tcpdump o pacote em loop e verifique o momento em que o pacote sai de circulação.<br />
<br />
==Links de Referência==<br />
<br />
* [http://en.wikipedia.org/wiki/Longest_prefix_match Prefixo Mais Longo]<br />
<br />
* [http://jodies.de/ipcalc?host=192.168.20.19&mask1=28&mask2= Calculador IP]<br />
<br />
* [http://linux-ip.net/html Guia de Administração da Camada IP no Linux]<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 15 - Sub-redes}}<br />
<br />
===Objetivos===<br />
*Compreender endereçamento IPv4.<br />
*Compreender o processo de alocação de faixas de IPs.<br />
*Compreender e manipular os números IPs.<br />
*Compreender e manipular as máscaras de rede.<br />
===Fonte Base===<br />
*[https://www.todoespacoonline.com/w/2015/06/calculo-de-sub-redes-ipv4/ Cálculo de Sub-rede IPv4]<br />
<br />
===Exercícios===<br />
#Considere um endereço IP 200.135.233.8/21. Determine:<br />
##O endereço da rede ao qual pertence;<br />
##O endereço de broadcast da rede;<br />
##A faixa de endereçamento que podem ser usados por hospedeiros desta rede.<br />
#Suponha que um administrador de rede tenha recebido o bloco de endereços 200.40.8.0/21 e que deseja dividir este bloco em 8 blocos de endereços iguais, de menor tamanho, para ser alocado a 8 sub-redes administradas por ele.<br />
##Determine o tamanho total do bloco de endereços.<br />
##Determine o tamanho de cada sub-bloco.<br />
##Determine o endereço/máscara de rede de cada sub-rede.<br />
#Quantas estações (''hosts'') uma rede 223.1.10.0/24 suporta? <br />
#Um provedor de acesso com bloco de IPs 200.23.16.0/20 deseja montar 8 sub-redes. Mostre como isso é possível e como ficaria os endereços de cada uma dessas sub-redes.<br />
#Um provedor de acesso a Internet possui o seguinte bloco de endereços IP: 12.17.192.0/18. Os endereços IP de 12.17.192.0 até 12.17.207.255 já estão alocados para clientes deste provedor. Este provedor precisa atender a quatro novos clientes, um deles necessita de rede com pelo menos 1000 endereços de IP válidos e os outros três necessitam de rede com pelo menos 30 IP válidos. Faça uma proposta para alocação de endereços IP para estes clientes. Os endereços reservados para estes novos clientes devem ser alocados a partir da numeração mais baixa disponível. Procure também responder as questões abaixo:<br />
##Qual o total de endereços que dispõe o provedor em questão?<br />
##Quantos endereços IP já estão utilizados?<br />
##Quantos endereços IP este provedor possui livres para alocar aos novos clientes?<br />
##Qual o endereço identificador de cada sub-rede dos novos clientes?<br />
##Qual o a máscara de rede de cada sub-rede dos novos clientes?<br />
##Qual o endereço de broadcast de cada sub-rede dos novos clientes?<br />
##Quantos endereços IP ainda sobrarão ao provedor após atender a estes clientes?<br />
#Um administrador precisa montar uma rede experimental conforme mostrada na Figura 1. Na sub-rede 1 ele precisará instalar cerca 25 ''hosts'', e nas sub-redes 2 e 3 ele precisará instalar cerca de 12 ''hosts''. O administrador dispõe do bloco de endereços IP 192.168.10.0/24 para ser utilizado no endereçamento da rede experimental. Faça uma proposta para alocação de endereços IP para cada sub-rede (rede 1, 2 e 3), incluindo também as sub-redes relativas aos enlaces ponto-a-ponto (rede AB, AC e BC). Responda ainda:<br />
##Qual o endereço identificador de rede de cada sub-rede (1, 2, 3, AB, AC e BC)?<br />
##Qual o a máscara de rede de cada sub-rede (1, 2, 3, AB, AC e BC)?<br />
##Quais os endereços IP que serão atribuídos a cada interface de rede nos enlaces ponto-a-ponto dos roteadores (enlaces relativos as redes AB, AC e BC)? [[Arquivo:CdrEx.png |thumb | 400px| Figura 1 - Rede experimental]]<br />
<br />
*Para conferir seu cálculos utilize, por exemplo, as seguintes ferramentas:<br />
**Terminal Linux: '''ipcalc'''<br />
**Site web: [http://jodies.de/ipcalc ipcalc]<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 16 - Sub-redes e Roteamento Estático em Redes }}<br />
<br />
===Objetivos===<br />
*Compreender endereçamento IPv4.<br />
*Compreender o processo de alocação de faixas de IPs.<br />
*Compreender e manipular os números IPs.<br />
*Compreender e manipular as máscaras de rede.<br />
*Proporcionar ao aluno uma visão prática de roteamento IP.<br />
<br />
===Fonte Básica===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IP_DHCP_NAT.pdf DHCP e NAT]<br />
*[http://www.davidc.net/sites/default/subnets/subnets.html Cálculo de sub-redes]<br />
<br />
===Roteiro===<br />
<br />
#Um administrador precisa montar uma rede experimental conforme mostrada na Figura 1. Na sub-rede 1 ele precisará instalar cerca 50 ''hosts'', e nas sub-redes 2 e 3 ele precisará instalar cerca de 20 ''hosts''. O administrador dispõe do bloco de endereços IP 192.168.10.0/24 para ser utilizado no endereçamento da rede experimental. Faça uma proposta para alocação de endereços IP para cada sub-rede (rede 1, 2 e 3), incluindo também as sub-redes relativas aos enlaces ponto-a-ponto (rede AB, AC e BC). Responda ainda:<br />
##Qual o endereço identificador de rede de cada sub-rede (1, 2, 3, AB, AC e BC)?<br />
##Qual o a máscara de rede de cada sub-rede (1, 2, 3, AB, AC e BC)?<br />
##Quais os endereços IP que serão atribuídos a cada interface de rede nos enlaces ponto-a-ponto dos roteadores (enlaces relativos as redes AB, AC e BC)? [[Arquivo:CdrEx.png |thumb | 400px| Figura 1 - Rede experimental]]<br />
#Baseado no arquivo exemplo abaixo, crie um arquivo de configuração para o NetKit que implemente sua proposta. O arquivo deve contemplar todas as configurações necessárias para o perfeito funcionamento da rede, ou seja, ao carregar o arquivo todos os hosts deverão ser capazes de "pingar" uma ao outro. <br />
##Faça testes de conectividade entre os hosts.<br />
##Demostre para o professor o perfeito funcionamento de sua rede.<br />
*O arquivo de configuração do Netkit abaixo, é a definição para o perfeito funcionamento da simulação da rede apresentada na Figura 2. [[Arquivo:DynamicRoutingTriangle.png |thumb | 400px| Figura 2 - Rede exemplo]]<br />
<syntaxhighlight lang=bash><br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=link0:ip=192.168.0.1/24<br />
pc2[eth0]=link1:ip=192.168.1.1/24<br />
pc3[eth0]=link2:ip=192.168.2.1/24<br />
<br />
# Default gateways definitions<br />
pc1[default_gateway]=192.168.0.254<br />
pc2[default_gateway]=192.168.1.254<br />
pc3[default_gateway]=192.168.2.254<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
r3[type]=gateway<br />
<br />
# Routers' interfaces to local networks<br />
r1[eth0]=link0:ip=192.168.0.254/24<br />
r2[eth0]=link1:ip=192.168.1.254/24<br />
r3[eth0]=link2:ip=192.168.2.254/24<br />
<br />
# Network "backbone" links<br />
r1[eth1]=backbone0:ip=10.0.0.1/30<br />
r1[eth2]=backbone1:ip=10.0.1.1/30<br />
<br />
r2[eth1]=backbone0:ip=10.0.0.2/30<br />
r2[eth2]=backbone2:ip=10.0.2.1/30<br />
<br />
r3[eth1]=backbone1:ip=10.0.1.2/30<br />
r3[eth2]=backbone2:ip=10.0.2.2/30 <br />
<br />
# Routes definition<br />
r1[route]=192.168.2.0/24:gateway=10.0.1.2<br />
r1[route]=192.168.1.0/24:gateway=10.0.0.2<br />
r1[route]=10.0.2.0/30:gateway=10.0.0.2<br />
r2[route]=192.168.0.0/24:gateway=10.0.0.1<br />
r2[route]=192.168.2.0/24:gateway=10.0.2.2<br />
r2[route]=10.0.1.0/30:gateway=10.0.2.2<br />
r3[route]=192.168.0.0/24:gateway=10.0.1.1<br />
r3[route]=192.168.1.0/24:gateway=10.0.2.1<br />
r3[route]=10.0.0.0/30:gateway=10.0.2.1</syntaxhighlight><br />
<br />
===Referencia===<br />
<br />
*[http://www.davidc.net/sites/default/subnets/subnets.html Link Calculador Online de Subnets]<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 17 - Tecnologia de Enlace Ethernet }}<br />
<br />
===Objetivos===<br />
<br />
*Compreender que Ethernet não é Internet e que não é necessário o mundo IP para haver comunicação.<br />
*Diferenciar Hub de Switch<br />
*Compreender o papel do protocolo ARP<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/Camada%20de%20enlace.pdf Camada de Enlace]<br />
<br />
===Animação Pearson/Kurose===<br />
<br />
*[https://media.pearsoncmg.com/aw/ecs_kurose_compnetwork_7/cw/content/interactiveanimations/csma-cd/index.html Animação CSMA/CD]<br />
<br />
===PARTE 1===<br />
<br />
Neste experimento vamos conectar quatro computadores através de um Hub Ethernet. Este dispositivo faz com que todos os computadores se conectem tal como um cabo. Quando um PC envia uma mensagem para outro PC, TODOS os computadores podem ver esta mensagem. Para haver comunicação basta que um computador envie um frame ETHERNET direcionado para o endereço de hardware do computador destino. NÃO é necessário que as interfaces dos computadores estejam configuradas com endereços IP.<br />
<br />
[[Arquivo:RCO-Animacao_HUB.gif | thumb | 400px| Figura 2 - Funcionamento de um Hub]]<br />
<br />
#Contruir um arquivo '''\home\aluno\hub.conf''' com a seguinte configuração <syntaxhighlight lang=bash><br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
pc1[eth0]=lan0<br />
pc2[eth0]=lan0<br />
pc3[eth0]=lan0<br />
pc4[eth0]=lan0<br />
</syntaxhighlight><br />
#Carregar e executar a configuração no Netkit.<br />
#Baixar o arquivo sendraw.py: [http://tele.sj.ifsc.edu.br/~eraldo/AULAS/2018/RCO-INTEGRADO/sendraw.py sendraw.py] para o diretório /home/aluno<br />
#Copiar o arquivo para a Máquina Virtual, no terminal da máquina real digite:<syntaxhighlight lang=bash><br />
cp /home/aluno/sendraw.py /home/aluno/lab/shared </syntaxhighlight><br />
#Identificar o endereço de Hardware (MAC) do PC2. Use o '''ifconfig'''. Note que NÃO existe endereço IPv4 configurado.<br />
#Executar o tcpdump no PC2:<syntaxhighlight lang=bash><br />
tcpdump -i eth0 -e -X -vvv -s 50</syntaxhighlight><br />
#Executar o tcpdump no PC3:<syntaxhighlight lang=bash><br />
tcpdump -i eth0 -e -X -vvv -s 50</syntaxhighlight><br />
#Executar o tcpdump no PC4:<syntaxhighlight lang=bash><br />
tcpdump -i eth0 -e -X -vvv -s 50</syntaxhighlight><br />
#No PC1 enviar uma mensagem para o PC2 usando o endereço de hardware identificado anteriormente, <span style="color: red;">lembre-se se substituir o ENDERECO_MAC pelo MAC adequado:<syntaxhighlight lang=bash><br />
python /hostlab/shared/sendraw.py -d ENDERECO_MAC -i Alo-Mundo</syntaxhighlight> <span style="color: black;"><blockquote style="background: lime; border: 1px solid black; padding: 1em;"> Observe que a mensagem chega a todos os PCs embora foi enviada somente para o PC2. </blockquote><br />
#O que explica o comportamento de broadcast para esse caso?<br />
#Pode existir colisão em um sistema com HUBs simples como este do experimento?<br />
<br />
===PARTE 2 - Explorando o SWITCH e o endereço de Broadcast Ethernet===<br />
<br />
[[Arquivo:RCO-Animacao_SWITCH.gif | thumb | 370px| Figura 2 - Funcionamento de um Switch]]<br />
<br />
#Construir um arquivo '''/home/aluno/switch.conf''' com a seguinte configuração: <syntaxhighlight lang=bash><br />
switchA[type]=switch<br />
<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
switchA[eth0]=port0<br />
switchA[eth1]=port1<br />
switchA[eth2]=port2<br />
switchA[eth3]=port3<br />
<br />
pc1[eth0]=port0<br />
pc2[eth0]=port1<br />
pc3[eth0]=port2<br />
pc4[eth0]=port3<br />
</syntaxhighlight><br />
#Carregar e executar a configuração no Netkit.<br />
#Baixar o arquivo sendraw.py do site: [http://tele.sj.ifsc.edu.br/~eraldo/AULAS/2018/RCO-INTEGRADO/sendraw.py sendraw.py] para o /home/aluno.<br />
#Copiar o arquivo para a Máquina Virtual. No terminal da máquina real digite:<syntaxhighlight lang=bash><br />
cp /home/aluno/sendraw.py /home/aluno/lab/shared/ </syntaxhighlight><br />
#Identificar o endereço de Hardware (MAC) do PC2. Use o ifconfig. Note que NÃO existe endereço IPv4 configurado<br />
#Executar o tcpdump no PC2, PC3 e PC4 com o comando:<syntaxhighlight lang=bash><br />
tcpdump -i eth0 -e -X -vvv -s 50</syntaxhighlight><br />
#No PC1 enviar uma mensagem para o PC2 usando o endereço de hardware identificado anteriormente, <span style="color: red;">Lembre-se se substituir o ENDERECO_MAC pelo MAC adequado:<syntaxhighlight lang=bash><br />
python /hostlab/shared/sendraw.py -d ENDERECO_MAC -i Alo-Mundo </syntaxhighlight> <span style="color: black;"><blockquote style="background: lime; border: 1px solid black; padding: 1em;"> Agora somente o PC2 deve receber pois o ''switch'' entrega o quadro somente para a porta de saída associada ao respectivo MAC destino. </blockquote><blockquote style="background: red; border: 1px solid black; padding: 1em;"> CASO todos tenham recebido, é devido ao fato que por algum motivo o switch ainda não aprendeu quem está conectado nas portas. Neste caso envie pacotes do PC2 para o PC1 e depois retome o experimento do item 4. </blockquote><br />
#No PC1 enviar uma mensagem em broadcast (endereço FF:FF:FF:FF:FF:FF)<syntaxhighlight lang=bash><br />
python /hostlab/shared/sendraw.py -d FF:FF:FF:FF:FF:FF -i Mensagem_Broadcast </syntaxhighlight><br />
<blockquote style="background: lime; border: 1px solid black; padding: 1em;"><br />
Note que neste caso todos os computadores recebem a mensagem em ''broadcast'', mesmo sendo um '''switch'''.<br />
</blockquote><br />
<br />
===PARTE 3 - Explorando o ARP===<br />
<br />
O protocolo ARP serve como apoio para descoberta do endereço MAC dado que se sabe o endereço IP de uma máquina. Quando um PC deseja enviar um pacote IP para uma máquina na rede local, ele necessita descobrir o endereço MAC desta máquina. O protocolo ARP usa o broadcast ETHERNET para perguntar para todas as máquinas na rede QUEM tem o endereço IP em questão. A máquina que possui o endereço responderá informando o seu MAC.<br />
<br />
#Configure endereços IP em todas as máquinas do laboratório anterior. Use exemplo a rede 10.10.10.0/24<br />
#Rode o wireshark no '''PC2''' com os procedimentos:<br />
##Clique sobre a aba do '''PC2'''.<br />
##Menu: Wireshark >> any<br />
#Faça um ping do PC1 no PC2 e observe a sequência de pacotes trocados. Faça um diagrama no tempo mostrando a troca de pacotes até a realização do ECHO REQUEST do ping. Os resultados do Wireshark devem ser similares a: [[Arquivo:RCO-TelaARP.jpg | 700px| Troca de pacotes ARP e PING]]<br />
#Confira o cache do arp no PC1 fazendo:<syntaxhighlight lang=bash><br />
arp -a</syntaxhighlight><br />
#Confira o cache do arp no PC2 fazendo:<syntaxhighlight lang=bash><br />
arp -a</syntaxhighlight><br />
#Faça um ping do PC1 no PC3.<br />
#Confira novamente o cache do arp no PC1 fazendo:<syntaxhighlight lang=bash><br />
arp -a</syntaxhighlight><br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 18 - IPv6: Endereços e ''Neighbor Discovery''}}<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IPv6.pdf IPv6]<br />
<br />
Fontes Extras<br />
*Este roteiro foi baseado no material disponível no Livro - [http://www.paulogurgel.com.br/ Laboratório de IPv6].<br />
*[http://docente.ifsc.edu.br/odilson/RED29004/enderec-v6.pdf Guia didático de endereçamento IPv6] obtido de http://ipv6.br/.<br />
<br />
===Objetivos do laboratório:===<br />
*Um primeiro contato com o protocolo [https://pt.wikipedia.org/wiki/IPv6 IPv6].<br />
*Compreender o funcionando do ''Neighbor Discovery'', o equivalente ao ARP (''Address Resolution Protocol'') do IPv4, que em resumo é uma tabela contendo a relação ente IPs e MACs.<br />
*Aprender configurações básicas de interfaces IPv6 no Linux.<br />
<br />
===Introdução teórica===<br />
Obs.: texto copiado literalmente de: [http://ipv6.br/lab/ Laboratório de IPv6].<br />
<br />
A '''descoberta de vizinhança''' por meio do protocolo ''Neighbor Discovery'' no<br />
IPv6 é um procedimento realizado pelos nós de uma rede para descobrir endereços físicos dos dispositivos vizinhos presentes no mesmo enlace. A função deste protocolo se assemelha à função do ARP e do RARP no IPv4.<br />
*O procedimento é iniciado quando um dispositivo tenta enviar um pacote cujo endereço físico de destino é desconhecido. O nó solicitante envia uma mensagem ''Neighbor Solicitation'' (NS) para todos os nós do enlace pertencentes ao grupo ''multicast solicited-node'' (ff02::1:ffXX:XXXX), de modo que XX:XXXX são os últimos 24 bits do endereço IPv6 em que está interessado.<br />
*É possível notar que, por uma coincidência dos últimos 24 bits, é bastante provável que apenas o nó de destino faça realmente parte deste grupo. Isto é um ''truque'' interessante do IPv6 para diminuir o tráfego deste tipo de pacote na rede.<br />
*Na mensagem NS, o endereço IPv6 a ser resolvido é informado no campo ''Target''. O campo ''Source link-layer address'' informa ao nó de destino o endereço MAC do nó de origem, poupando-o de ter que fazer o mesmo procedimento no sentido inverso.<br />
*O nó de destino, dono do IPv6 requisitado, ao receber este pacote, envia uma mensagem ''Neighbor Advertisement'' (NA) como resposta diretamente ao nó requisitante. O seu endereço físico será informado no campo ''Target link-layer address''.<br />
*A informação de mapeamento entre endereços IP e endereços físicos é armazenada em uma tabela chamada ''neighbor cache''. Nela também fica registrado o ''status'' de cada destino, informando se o mesmo é alcançável ou não.<br />
<br />
===Roteiro de atividades: ETAPA 1===<br />
<br />
A figura abaixo apresenta o diagrama esquemático da rede a ser montada/analisada. Observe que todos os IPv6 ''Global Unicast'' já estão definidos na mesma, são esses IPs que utilizaremos em nosso experimento.<br />
<br />
[[Arquivo:Diagrama_rede_IPv6.jpg]]<br />
<br />
#Crie em seu computador um arquivo com nome '''/home/aluno/IPv6.conf''', com o seguinte conteúdo: <syntaxhighlight lang=bash><br />
#Ligacao das maquinas nos dominios de colisao<br />
#Duas pequenas redes interligadas pelo backbone<br />
<br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=link0:ipv6=2001:bcc:faca:1::101/64<br />
pc2[eth0]=link1:ipv6=2001:bcc:cafe:1::102/64<br />
pc3[eth0]=HUB1:ipv6=2001:bcc:1f0:1::103/64<br />
pc4[eth0]=HUB1<br />
<br />
#Default Gateways definitions<br />
pc1[route]=default6:gateway=2001:bcc:faca:1::1<br />
pc2[route]=default6:gateway=2001:bcc:cafe:1::1<br />
pc3[route]=default6:gateway=2001:bcc:1f0:1::1<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
#Routers interfaces definitions<br />
r1[eth0]=backbone0:ipv6=2001:db8:dead:1::1/64<br />
r1[eth1]=link0:ipv6=2001:bcc:faca:1::1/64<br />
r1[eth2]=link1:ipv6=2001:bcc:cafe:1::1/64<br />
<br />
r2[eth0]=backbone0:ipv6=2001:db8:dead:1::2/64<br />
r2[eth1]=HUB1:ipv6=2001:bcc:1f0:1::1/64<br />
<br />
#Routers definitions<br />
r1[route]=2001:bcc:1f0:1::0/64:gateway=2001:db8:dead:1::2<br />
r2[route]=2001:bcc:faca:1::0/64:gateway=2001:db8:dead:1::1<br />
r2[route]=2001:bcc:cafe:1::0/64:gateway=2001:db8:dead:1::1<br />
</syntaxhighlight><br />
#Tenha certeza que o Netkit2 estja atualizado: General >> Update.<br />
#Rode o NetKit em seu computador. Em um terminal digite: <syntaxhighlight lang=bash><br />
netkit2 & </syntaxhighlight><br />
#No menu '''File''' - '''Load and Run''', procure o arquivo '''/home/aluno/IPv6.conf''' e clique em OK. Abrirá uma janela com 6 abas, onde cada uma delas é um terminal de configuração do respectivo equipamento: '''pc1-4''' ou '''r1-2'''.<br />
#Observe que o '''pc4''' não está com sua interface configurada.<br />
#Ao clicar no menu '''File''' - '''Graph''', pode-se ter uma visão da rede a ser simulada e conferir se é equivalente ao diagrama proposto.<br />
#Faça um '''ping6''' entre o '''pc1''' ao '''pc3''': <syntaxhighlight lang=bash><br />
ping6 -c4 2001:bcc:1f0:1::103 </syntaxhighlight><br />
#Faça um '''ping6''' entre o '''pc1''' e '''pc2'''.<br />
#No '''pc4''' use o seguinte comando para adicionar o endereço IPv6 à interface de rede: <syntaxhighlight lang=bash><br />
ip addr add 2001:bcc:1f0:1::104/64 dev eth0 </syntaxhighlight><br />
#No '''pc4''', acrescente o ''default gateway'' com o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add default via 2001:bcc:1f0:1::1 dev eth0 </syntaxhighlight><br />
#No '''pc1''' use o seguinte comando para verificar como ficou a configuração dos endereços da interface de rede. O resultado é similar ao apresentado pelo comando '''ifconfig''': <syntaxhighlight lang=bash><br />
ip addr show dev eth0 </syntaxhighlight><br />
#Todo o roteamento está pronto, mas caso desejássemos poderíamos acrescentar rotas com comando similares aos já utilizados. Por exemplo, no '''r1''', para adicionar uma rota estática para a rede dos '''pc3''' e '''pc4''' utilizaríamos o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add 2001:bcc:1f0:1::/64 via 2001:db8:dead:1::2 dev eth0 </syntaxhighlight><br />
#Confira as rotas estabelecidas em todos os ''hosts'' com o comando abaixo. <br />
##São coerentes com os dados apresentados no diagrama acima?<syntaxhighlight lang=bash><br />
ip -6 route show </syntaxhighlight><br />
#No '''pc1''' use os seguintes comandos para ver a rota para alguns vizinhos: <syntaxhighlight lang=bash><br />
traceroute6 2001:bcc:1f0:1::103<br />
traceroute6 2001:bcc:1f0:1::104 </syntaxhighlight><br />
#*Anote as rotas.<br />
#Deixe um '''ping6''' entre o '''pc1''' ao '''pc3''' rodando: <syntaxhighlight lang=bash><br />
ping6 2001:bcc:1f0:1::103 </syntaxhighlight><br />
#Rode o wireshark no '''r1''' com os procedimentos:<br />
##Clique sobre a aba do '''r1'''.<br />
##Menu: Wireshark >> any<br />
#Analisando a captura do Wireshark, você verá os pacotes relativos ao ping6 e também pacotes parecidos com: <syntaxhighlight lang=bash> fe80::4cd6:19ff:fedc:2b52 2001:db8:dead:1::1 ICMPv6 86 Neighbor Solicitation for 2001:db8:dead:1::1 from 4e:d6:19:dc:2b:52<br />
2001:db8:dead:1::1 fe80::4cd6:19ff:fedc:2b52 ICMPv6 78 Neighbor Advertisement 2001:db8:dead:1::1 (rtr, sol) </syntaxhighlight><br />
#Explique o processo de descoberta de vizinhança (''Neighbor Discovery'' / ''Neighbor Solicitation'' - '''NS''' e ''Neighbor Advertisement'' - '''NA'''), citando o endereço '''link local''' utilizado.<br />
#*Alguns exemplos de campos visualizáveis para uma mensagem do tipo ''Neighbor Advertisement'':<br />
##Destination (camada Ethernet)<br />
##*O endereço MAC do nó requisitante que foi obtido por meio da mensagem NS enviada anteriormente.<br />
##Source (camada Ethernet)<br />
##*A origem é o endereço MAC da interface do dispositivo que enviou a resposta.<br />
##Type (camada Ethernet)<br />
##*Indica que a mensagem utiliza IPv6.<br />
##Next header (camada IPv6)<br />
##*Indica qual é o próximo cabeçalho. Neste caso, o valor 58 (0x3a) refere-se a uma mensagem ICMPv6.<br />
##Source (camada IPv6)<br />
##*A origem é o endereço IP da interface diretamente ligada ao enlace em que a requisição foi recebida.<br />
##Destination (camada IPv6)<br />
##*Diferentemente da mensagem NS, a mensagem NA possui como destino o endereço IPv6 global do nó requisitante.<br />
##Type (camada ICMPv6)<br />
##*Indica que a mensagem é do tipo 136 (Neighbor Advertisement).<br />
##Flags (camada ICMPv6)<br />
##*Uma mensagem NA possui três flags:<br />
###Indica se quem está enviando é um roteador. Neste caso, o valor marcado é 0, pois não é um roteador.<br />
###Indica se a mensagem é uma resposta a um NS. Neste caso, o valor marcado é 1, pois é uma resposta.<br />
###Indica se a informação carregada na mensagem é uma atualização de endereço de algum nó da rede. Neste caso, o valor marcado é 1, pois está informando o endereço pela primeira vez.<br />
##Target Address (camada ICMPv6)<br />
##*Indica o endereço IP associado às informações das flags. Neste caso, é o próprio endereço da interface do dispositivo em questão.<br />
##ICMPv6 option (camada ICMPv6)<br />
##*Indica as opções do pacote ICMPv6:<br />
###Target link-layer address<br />
##Type<br />
##*Indica o tipo de opção. Neste caso, Target link-layer address.<br />
##Link-layer address<br />
##*Indica o endereço MAC da interface do dispositivo em questão.<br />
#Em todos os ''hosts'' rode o comando <syntaxhighlight lang=bash> ip -6 neighbor show </syntaxhighlight><br />
##Qual é a funcionalidade desse comando?<br />
##Qual é o significado do conteúdo dessa tabela?<br />
##A tabela mostrada em cada um dos casos é compatível com o diagrama da rede montado?<br />
##Por que, por exemplo, na tabela do '''pc3''' não há uma referência explícita ao '''pc1'''?<br />
<br />
===Roteiro de atividades: ETAPA 2 - DESAFIO===<br />
<br />
Acrescentar um terceiro roteador ligado a R1 e R2 (backbone0). Acrescentar uma rede ethernet ligada a este roteador. Configure a rede com endereços IPv6 colocando pelo menos um PC adicional. Acrescente os roteamentos necessários para que este PC seja pingável a partir de PC1.<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 19 - Configurando uma Rede Doméstica}}<br />
<br />
===Objetivos===<br />
*Entender os componentes e princípio de funcionamento de uma rede residencial.<br />
*Configurar um roteador sem fio.<br />
*Testa a rede configurada através do acesso da mesma via Telefone Celular.<br />
<br />
===Fonte Base===<br />
<br />
*[https://esr.rnp.br/publicacoes/sistemas/proinfo?download=d2ddea18f00665ce8623e36bd4e3c7c5 Livro da Escola Superior de Redes (ESR): Formação de suporte técnico PROINFO]<br />
<br />
===Analisando o roteador===<br />
#Roteador ??????. Descrição Geral do aparelho: <br />
##Fonte de alimentação. Cuidar com tensão cc e polaridade.<br />
##Porta WAN (''Wide Area Network'')<br />
##Portas LAN (''Local Area Network'')<br />
##Antena ou antenas <br />
##Botão reset. Normalmente configura LAN em 192.168.0.0/24 ou 192.168.1.0/24<br />
##Parte frontal, LEDs: Power, Status, WAN, WLAN, 1...4.<br />
#Descrição dos modos de uso básicos.<br />
#Ligar o aparelho na tomada.<br />
##LED Power acendeu?<br />
<br />
====Montando uma rede básica====<br />
#Conectar o computador numa das portas LAN do roteador sem fio.<br />
#Conectar a porta WAN num dos pontos de rede do laboratório.<br />
#Pressionar o botão Reset.<br />
#Teste a rede de seu computador, caso não esteja funcionando desconecte e reconecte o cabo de rede entre seu computador e uma porta LAN do roteador sem fio.<br />
#Com o navegador acesse 192.168.0.1. '''Usuário: admin''', '''senha: em branco'''. Caso não consiga acesso, pressione novamente o botão reset.<br />
#Redefina a senha do administrador do roteador para RCO60803.<br />
#Aba Home:<br />
##Clique no menu esquerdo WAN. Discutir a funcionalidade.<br />
##Clique no menu esquerdo LAN. Discutir a funcionalidade.<br />
##Clique no menu esquerdo DHCP. Discutir a funcionalidade.<br />
##Clique no menu esquerdo Wireless. Discutir a funcionalidade.<br />
##Clique no menu esquerdo Wizard. Discutir a funcionalidade.<br />
#Aba Status:<br />
##Device Info. Discutir a funcionalidade.<br />
##Wireless. Discutir a funcionalidade.<br />
#Reconfigure o roteador sem fio para alugar os endereços 192.168.X.20-60, onde X é igual ao último dígito do número IP de sua máquina. Por exemplo, para a máquina 192.168.1.7, X=7.<br />
#Para verificar o funcionamento, num terminal da máquina (real) execute o comando abaixo. Caso tudo esteja funcionando corretamente, sua máquina configurará uma nova interface de rede com o número IP fornecido por seu roteador ou um roteador de um colega. <syntaxhighlight lang=bash> sudo dhclient eth0:0 </syntaxhighlight><br />
#Reconfigure o WiFi de seu roteador:<br />
##Troque o SSID (''Service Set IDentifier'') de seu roteador, colocando seu primeiro nome como nome de rede.<br />
##Configure a segurança para WPA2 (''Wireless Security Setup'').<br />
##Ajuste a senha para RCO60803 (respeite as maiúsculas).<br />
##Salve e reinicie o roteador para as alterações terem validade.<br />
#Teste a configuração, acessando a sua rede sem fio através de seu telefone celular.<br />
<br />
{{Collapse bottom}}<br />
<br />
==Projeto Final==<br />
{{Collapse top |Descrição do Projeto}}<br />
<br />
===Objetivos===<br />
<br />
*Aplicar os conhecimentos adquiridos durante o curso de redes através da confecção de uma rede múltiplos domínios simulando a Internet.<br />
**Dado uma topologia de rede definida a um grupo, calcular as sub-redes de acordo com os requisitos colocados;<br />
**Implementar a proposta de sub-redes no arquivo de configuração do netkit de tal modo a rede ficar plenamente operacional;<br />
**Estabelecer um roteamento global entre todos os domínios das equipes;<br />
**Estabelecer um serviço WEB sobre a rede construída;<br />
**Construir páginas WEB de acordo com os requisitos;<br />
**Estabelecer um serviço de configuração automática de hospedeiros (DHCP);<br />
<!--**Estabelecer um serviço de conexão sem fio sobre cada domínio.--><br />
**Trabalhar o conceito de ''shell script'' para automatizar tarefas.<br />
<br />
A arquitetura da rede é mostrada na Figura abaixo. <br />
<br />
[[Image:RCO3-TrabalhoFinal-2017-2.png|500px]]<br />
<br />
===Especificações do Projeto===<br />
<br />
#Fazer um desenho da '''topologia''' do domínio com todos IPs alocados e apresentar os cálculos das subredes conforme restrições abaixo. <br />
##Construir as tabelas de roteamento para que a rede fique plenamente operacional. Apresentar as '''tabelas de roteamento na página WEB do projeto''';<br />
##Apresentar o desenho da '''topologia na página WEB do projeto'''. Utilize o modelo ao lado. Observe que o modelo está propositalmente incompleto; [[Image:Modelo_de_diagrama_do_projeto.png|300px]]<br />
##Enlaces ponto-a-ponto devem obrigatoriamente ter máscara /30;<br />
##Enlaces multiponto devem obrigatoriamente comportar no mínimo 50 hospedeiros;<br />
##Todas as rotas devem ser colocadas no arquivo '''projeto.conf''' do netkit. Apresentar esse arquivo na '''página WEB do projeto''';<br />
#Na sub-rede onde existe um cliente (notebook) acrescentar um servidor '''[[Netkit2#Usando_DHCP | DHCP]]''' (máquina adicional) com os seguintes requisitos:<br />
##Com uma faixa de aluguel de pelo menos 5 números IP;<br />
##Explicar a configuração do '''DHCP na página WEB do projeto''';<br />
#Estabelecer o serviço '''Apache''' no servidor previsto no domínio com os seguintes requisitos:<br />
##uma página WEB com a descrição integral do projeto;<br />
##uma segunda página WEB com conteúdo de sua preferência com os seguintes requisitos:<br />
###a página deve ser em inglês ou espanhol;<br />
###texto com no mínimo 500 palavras; <br />
###no mínimo uma figura deve aparecer;<br />
###no mínimo um link para uma página WEB de uma outra equipe.<br />
##Todas as páginas devem devem ser mantidas em um diretório de nome ''/home/aluno/lab/shared/WEB''.<br />
##Elaborar um ''shell script'' para automação do serviço WEB. Sítio para treinamento de [http://www.compileonline.com/execute_bash_online.php shell script]. <br />
#O '''roteamento global''' deve permitir conectividade entre todas as equipes. Para evitar possíveis erros advindos de filtros do Netkit2, execute os seguintes comandos em todos os seus roteadores (copie e cole): <syntaxhighlight lang=bash><br />
echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth0/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth1/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth2/rp_filter <br />
echo 0 > /proc/sys/net/ipv4/conf/eth3/rp_filter </syntaxhighlight><br />
<br />
* Exemplo de arquivo '''projeto.conf'''.<br />
**No roteiro do '''Laboratório 16''' também é apresentado um arquivo de configuração de uma rede plenamente funcional para o Netkit, utilize-o como exemplo para entendimento das configurações requisitadas.<br />
**O arquivo deverá ser adaptado para a topologia de cada equipe.<br />
<syntaxhighlight lang=bash><br />
H1[type]=generic<br />
H2[type]=generic<br />
<br />
R1[type]=gateway<br />
R2[type]=gateway<br />
R3[type]=gateway<br />
<br />
H1[eth0]=SR2:ip=10.9.2.2/24<br />
H1[default_gateway]=10.9.2.1<br />
<br />
H2[eth0]=SR4:ip=10.9.4.2/24<br />
H2[default_gateway]=10.9.4.1<br />
<br />
R1[eth0]=uplink:bridge=eth0:ip=192.168.1.190/24<br />
R1[eth1]=SR1:ip=10.9.1.1/24<br />
R1[eth2]=SR5:ip=10.9.5.1/24<br />
R1[route]=10.9.2.0/24:gateway=10.9.1.2<br />
R1[route]=10.9.4.0/24:gateway=10.9.5.2<br />
<br />
R2[eth0]=SR1:ip=10.9.1.2/24<br />
R2[eth1]=SR2:ip=10.9.2.1/24<br />
R2[eth2]=SR3:ip=10.9.3.1/24<br />
R2[default_gateway]=10.9.1.1<br />
<br />
R3[eth0]=SR3:ip=10.9.3.2/24<br />
R3[eth1]=SR4:ip=10.9.4.1/24<br />
R3[eth2]=SR5:ip=10.9.5.2/24<br />
R3[default_gateway]=10.9.5.1<br />
</syntaxhighlight><br />
<br />
*Como trabalhar com o shell script<br />
<br />
#O shell script será executado na máquina virtual do apache, e portanto deverá ser copiado para o /home/aluno/shared/lab/config_apache.sh<br />
##Na máquina virtual do apache deve-se tornar o arquivo do script executável e em seguida executá-lo:<syntaxhighlight lang=bash><br />
chmod +x /hostlab/shared/config_apache.sh<br />
/hostlab/shared/config_apache.sh <br />
</syntaxhighlight><br />
<br />
* Exemplo de arquivo ''shell script''. Este arquivo deve ser adaptado para a topologia de cada equipe. <br />
<br />
#Editar o arquivo com gedit com nome ''config_apache.sh''. Qualquer comando executado no terminal pode ser colocado com exata sintaxe no ''shell script'', e vários comandos podem ser colocados em várias linhas.<br />
#Construir o arquivo da forma:<br />
<syntaxhighlight lang=bash><br />
#!/bin/bash<br />
#comentario: copiar um arquivo<br />
cp /home/aluno/teste.txt /var/www<br />
<br />
#renomeando o arquivo copiado teste.txt para index.html<br />
mv /var/www/teste.txt /var/www/index.html<br />
<br />
#iniciando um serviço<br />
/etc/init.d/ssh start<br />
</syntaxhighlight><br />
<br />
*Dar permissão de execução do script no Apache<br />
<br />
Copiar o script para o /home/aluno/lab/shared e apartir do Apache fazer:<br />
Dar direito de execução do script:<br />
<br />
chmod 777 /hostlab/shared/config_apache.sh<br />
<br />
*Executar o script no apache<br />
/hostlab/shared/config_apache.sh<br />
<br />
<br />
* Teste do acesso ao Servidor Apache a partir da linha de comando:<br />
<br />
Note que como todas as máquinas virtuais do netkit são em modo de comando (não tem interface gráfica) então o uso de browsers para teste<br />
do acesso a páginas html fica limitado. Entretanto, para teste rápido é possível usar o comando lynx:<br />
<br />
lynx IP_SERVIDOR_APACHE<br />
<br />
Note que o servidor deve ter conectividade IP (faça ping antes para testar);<br />
<br />
* Acesso pleno as páginas html a partir da Virtualbox<br />
<br />
Um problema que nos deparamos ao usar o netkit para acesso de páginas hospedadas em suas Máquinas Virtuais é o fato de não termos a interface gráfica. Uma interface gráfica é necessária para um browser do tipo Firefox. Uma alternativa é o uso de browser em modo texo do tipo "lynx". Para testes rápidos pode ser interessante mas para visualizarmos em plenitude a página não é a melhor solução.<br />
<br />
Para contornar este problema vamos usar uma máquina VirtualBox que estará conectada na rede do laboratório. Faremos o default gateway desta máquina apontar para o roteador de borda do domínio da equipe garantindo que a mesma conduza todo o tráfego indireto para este roteador. Para garantir que exista rota reversa vamos colocar em cada roteador do domínio uma rota default gateway para o roteador de borda. Vamos elaborar passo a passo estes procedimentos:<br />
<br />
#Iniciar na máquina real uma VirtualBox com Ubuntu e Interface Gráfica;<br />
#Abrir um terminal e verificar a rota para o default gateway usando:<syntaxhighlight lang=bash>route -n </syntaxhighlight><br />
#Adicionar uma rota para a sua rede: <syntaxhighlight lang=bash> sudo route add -net 10.X.0.0/16 gw 192.168.1.XX </syntaxhighlight> onde 192.168.1.XX é o endereço externo do roteador de borda do domínio onde está o servidor APACHE.<br />
#Para garantir a rota reversa vamos colocar rotas ''default'' também nos roteadores dos domínios (roteadores no netkit). Para tanto coloque no projeto.conf esta informação de rota para cada roteador que não está na borda: <syntaxhighlight lang=bash> Rx[route]=default:gateway=Y.Y.Y.Y <br />
ou<br />
Rx[default_gateway]=Y.Y.Y.Y<br />
</syntaxhighlight>onde Y.Y.Y.Y é uma interface do roteador de borda ligado a Rx ou, caso não esteja diretamente ligado a este, deve ser um endereço de roteador vizinho que tenha rota para o roteador de borda.<br />
{{Collapse bottom}}<br />
<br />
==Listas de Exercícios==<br />
{{Collapse top |Lista de exercícios 1 - Introdução}}<br />
<br />
#Qual é a diferença entre um hospedeiro e um sistema final? Cite os tipos de sistemas finais. Um servidor web é um sistema final?<br />
#O que caracteriza um protocolo? Dê um exemplo de um protocolo.<br />
#Por que os padrões são importantes para os protocolos?<br />
#O que é um programa cliente? O que é um programa servidor? Um programa servidor requisita e recebe serviços de um programa cliente? <br />
#Quais são os dois tipos de serviços de transporte que a Internet provê às suas aplicações? Cite algumas características de cada um desses serviços. (pg.38)<br />
#Explique o que é e quais são as vantagens de uma rede de comutação de circuitos em relação a uma rede de comutação de pacotes? <br />
#O que é uma rede de acesso?<br />
#FTTH, HFC e ADSL são usados para acesso residencial. Para cada uma dessas tecnologias de acesso, cite uma faixa de taxas de transmissão e comente se a largura de banda é compartilhada ou dedicada.<br />
#Cite tecnologias de acesso residencial disponíveis na grande Florianópolis. Para cada tipo de acesso, apresente a taxa de ''downstream'', a taxa de ''upstream'' e o preço mensal anunciados.<br />
#Qual é a taxa de transmissão de LANs Ethernet?<br />
#Porque dividimos a arquitetura da Internet (e de redes de comutação de pacotes em geral) em camadas? Por que dizemos que uma camada inferior presta um serviço a camada superior?<br />
#Quais são as cinco camadas da pilha de protocolo da Internet? Quais as principais responsabilidades de cada uma dessas camadas? <br />
#O que significa o processo de encapsulamento e desencapsulamento de pacotes no contexto da rede organizada em camadas?<br />
#O que é uma mensagem de camada de aplicação? Um segmento da camada de transporte? Um datagrama da camada de rede? Um quadro de camada de enlace? Qual a relação entre eles?<br />
#Que camadas da pilha de protocolo da Internet um roteador implementa? Que camadas um comutador de enlace implementa? Que camadas um sistema final implementa?<br />
#Imagine que você queira enviar, com urgência, 40 terabytes de dados de São José a Manaus. Você tem disponível um enlace dedicado de 100 Mbps para a transferência de dados. Você escolheria transferir os dados pelo enlace ou mandar mídias por Sedex 10? Explique.<br />
#Para pensar I: um celular tipo smartphone acessa normalmente quantas redes? Quais tecnologias sao usadas? Elas são de comutação de pacotes ou de circuitos?<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Lista de exercícios 2 - Camada de Aplicação}}<br />
#Relacione cinco aplicações da Internet não proprietárias e os protocolos da camada de aplicação que elas usam. <br />
#Qual é a diferença entre arquitetura de rede e arquitetura de aplicação? <br />
#De que modo um mensageiro instantâneo é um híbrido das arquiteturas cliente-servidor e P2P? <br />
#Para uma sessão de comunicação entre um par de processos, qual processo é o cliente e qual é o servidor? <br />
#Que informação é usada por um processo que está rodando em um hospedeiro para identificar um processo que está rodando em outro hospedeiro? <br />
#Porque o HTTP, FTP, SMTP, POP3 e IMAP rodam sobre TCP e não sobre UDP? <br />
#Por que se diz que o FTP envia informações de controle “fora da banda”? <br />
#Suponha que Aline envie uma mensagem a Eduardo por meio de uma conta de e-mail da web (como o gmail), e que Eduardo acesse seu e-mail por seu servidor utilizando POP3. Descreva como a mensagem vai do hospedeiro Aline até o hospedeiro de Eduardo. Não se esqueça de relacionar a série de protocolos de camada de aplicação usados para movimentar as mensagens entre os hospedeiros.<br />
#Em uma aplicação de compartilhamento de arquivos P2P, você concorda com a afirmação: ”não existe nenhuma noção de lados cliente e servidor de uma sessão de comunicação”? Por que sim ou por que não? <br />
#Relacione alguns agentes de usuário de aplicação de rede que você utiliza no dia-a-dia. <br />
#Considere um site de comércio eletrônico que quer manter um registro de compras para cada um de seus clientes. Descreva como isso pode ser feito com cookies. <br />
#Descreva uma aplicação que requeira “não perda de dados” e seja também altamente sensível ao atraso.<br />
#Quais informações básicas estão em um cabeçalho do pacote IP?<br />
#Um pacote IP pode ser colocado diretamente na rede física? Ele chegará a seu destino?<br />
#Os pacotes ECHO request e ECHO reply são de que protocolo? Eles trafegam dentro de qual pacote?<br />
#Para pensar II: Quando você usa o uma aplicação tipo whatsapp para conversação você está usando rede de comutação de circuitos ou de pacote?<br />
<br />
ADICIONAIS PARTE 2- HTTP<br />
<br />
#Cite pelo menos dois clientes http.<br />
#O que é o servidor Apache?<br />
#O protocolo http deve se executar em todos os roteadores do caminho entre cliente e servidor? Explique.<br />
#Se um hospedeiro colocar um pacote de aplicação HTTP diretamente na rede física ele chegará a seu destino?<br />
#Considere que um cliente acessa uma página HTML de servidor WEB e nesta página existem dois links para dois objetos JPG que residem no mesmo servidor. Quantos comandos GETS no total deveriam ser realizados pelo cliente? Todos eles serão realizados sobre a mesma conexão TCP?<br />
#Em uma página HTML pode existir um link para um objeto que esteja armazenado em outro site? O que o browser deve fazer neste caso? <br />
#No pacote http de resposta de um servidor normalmente existem duas partes. Quais são elas?<br />
#Imagine que uma página html está sendo mostrada para o usuário cliente. Se o usuário pedir para que a página seja atualizada, o browser vai requisitar o objeto novamente? O servidor vai retornar o objeto mesmo que ele não tenha sido alterado?<br />
#O que é um cookie? Considere um site de comércio eletrônico que quer manter um registro de compras para cada um de seus clientes. Descreva como isso pode ser feito com cookies.<br />
#Qual é a diferença entre HTTP persistente com ''pipelining'' e HTTP persistente sem ''pipelining''. Qual dos dois é utilizado pelo HTTP/1.1? <br />
#Descreva como o cache Web pode reduzir o atraso na recepção de um objeto desejado. O cachê Web reduzirá o atraso para todos os objetos requisitados por um usuário ou somente para alguns objetos? Por quê? <br />
#Um servidor Web, quando recebe uma requisição necessita saber para qual porta deve responder na máquina requisitante? Se positivo, esta porta seria sempre a mesma?<br />
#Por que um servidor Web espera na porta TCP número 80 em geral?<br />
#O que é um proxy Web server?<br />
#Um browser pode fazer cache local? Qual a diferença entre cache local e cache em um servidor proxy?<br />
<br />
ADICIONAIS PARTE 3- DNS<br />
#Porque o DNS não é centralizado? <br />
#O que são consultas recursivas e interativas em uma consulta DNS? <br />
#Quais os três tipos de servidores DNS?<br />
#Em um hospedeiro normalmente existe pelo menos um servidor DNS configurado. Que servidor deve estar configurado? Onde ele se localiza normalmente?<br />
#Quando um servidor local não consegue resolver um endereço IP olhando em seu cache, para quem ele deve encaminhar a consulta?<br />
#Um servidor sempre sabe resolver um nome solicitado? Explique.<br />
#É possível que um servidor DNS local seja um servidor com autoridade?<br />
#O que é um nome canônico e um apelido no contexto de DNS?<br />
#O que é e qual o formato de uma RR?<br />
#Explique os seguintes tipos de RR: A, NS, CNAME, MX e PTR.<br />
#Em um comando ping www.ifsc.edu.br quantas transações no mínimo serão realizadas até o último ECHO REPLY?<br />
#Por que um ping normalmente realiza uma consulta PTR?<br />
#Faça um esquema mostrando uma consulta de um cliente a um servidor local mostrando uma consulta interativa entre o servidor raiz e recursiva com um servidor de autoridade. <br />
#Cite o nome de servidor DNS bastante utilizado.<br />
#Quantos servidores raízes temos no mundo? Qual comando permite que possamos "ver" estes servidores em um hospedeiro?<br />
#Foi realizado um comando '''dig www.ifsc.edu.br''' tendo sido retornado: <br />
#:<br />
#: www.ifsc.edu.br. 240 IN A 200.135.190.95<br />
#:<br />
#Em seguida foi realizado um '''dig ifsc.edu.br MX''' com resposta:<br />
#:<br />
#: ;; ANSWER SECTION:<br />
#: ifsc.edu.br. 1327 IN MX 15 zimbra.ifsc.edu.br.<br />
#: <br />
#: ;; AUTHORITY SECTION:<br />
#: ifsc.edu.br. 2082 IN NS ns1.ifsc.edu.br.<br />
#: ifsc.edu.br. 2082 IN NS adns1.pop-sc.rnp.br.<br />
#: ifsc.edu.br. 2082 IN NS ns2.ifsc.edu.br.<br />
#: ifsc.edu.br. 2082 IN NS adns2.pop-sc.rnp.br.<br />
#: <br />
#: ;; ADDITIONAL SECTION:<br />
#: zimbra.ifsc.edu.br. 78 IN A 200.135.190.2<br />
#:<br />
#O que se pode concluir sobre a resolução do nome baseando-se nestas respostas?<br />
<br />
<!--RESPOSTAS <br />
<br />
#Qual é a diferença entre um hospedeiro e um sistema final? Cite os tipos de sistemas finais. Um servidor web é um sistema final?<br />
R.Segundo Kurose[1] os sistemas hospedeiros são sistemas finais, ou seja são considerados sinônimos. São os computadores do nosso dia a dia e que se encontram na periferia da rede executando aplicações que usufruem dos serviços da rede. Estas aplicações executam protocolos específicos para seu funcionamento (protocolos de aplicação).<br />
#O que caracteriza um protocolo? Dê um exemplo de um protocolo.<br />
R.Um conjunto de regras e formatos que viabilizam a comunicação entre duas ou mais entidades comunicantes. No caso de uma rede define as regras para troca de mensagens entre processos da rede (ações a serem realizadas no envio e no recebimento de mensagens), bem como o formato das mensagens trocadas. Em uma rede, as entidades comunicantes se encontram em uma mesma camada.<br />
#Por que os padrões são importantes para os protocolos?<br />
R.Para que exista compatibilidade na comunicação entre processos e equipamentos de rede, além de facilitar a implementação dos mesmos.<br />
#O que é um programa cliente? O que é um programa servidor? Um programa servidor requisita e recebe serviços de um programa cliente?<br />
R.Um programa cliente é uma parte de uma aplicação distribuída que requisita serviços de um outro programa chamado servidor. Tanto cliente como servidor se executam em sistemas finais. O servidor normalmente fica aguardando por uma requisição de algum recurso solicitado por um cliente. Ex: servidor Web e cliente Mozilla ou Chrome. <br />
#Quais são os dois tipos de serviços de transporte que a Internet provê às suas aplicações? Cite algumas características de cada um desses serviços.<br />
Os dois tipos básicos são serviços com conexão e sem conexão. Um serviço com conexão faz com que (em geral) duas entidades de aplicação que pretendem se comunicar, troquem mensagens de controle no sentido de manter informações mútuas de forma a permitir a execução de serviços adicionais do tipo: transferência confiável de dados, controle de fluxo de dados para não sobrecarregar o receptor e controle de congestionamento para evitar o congestionamento de pacotes na rede. Fluxos de pacotes podem ser direcionados a uma determinada conexão. Importante notar que os componentes intermediários da rede desconhecem as conexões. Na Internet, o protocolo que garante o serviço com conexão é o TCP.<br />
Já no serviço sem conexão as entidades comunicantes enviam pacotes (datagramas) sem nenhuma apresentação prévia (troca de mensagens de controle). Cada pacote é enviado de forma independente não tendo garantia de entrega. Na internet o protocolo associado a este comportamento é o UDP. Vale lembrar que por não ter nenhum procedimento associado, a troca de mensagens com UDP tem maior desempenho do que o TCP.<br />
#Quais são as vantagens de uma rede de comutação de circuitos em relação a uma rede de comutação de pacotes? <br />
Em uma rede de comutação de circuitos (ex: rede telefônica clássica) é estabelecido um canal dedicado para a a comunicação entre entidades comunicantes. Normalmente a alocação do canal dedicado é precedido de um processo de sinalização (discar o número, verificar se o destino está disponível, conectar). Uma canal dedicado não pode ser compartilhado por outras comunicações, mesmo quando fica ocioso (ex: duas pessoas na linha telefônica sem conversar). Já em uma rede de pacotes a informação é organizada em pacotes que podem compartilhar canais. Pacotes são comutados para seus destino por equipamentos do tipo roteadores. O roteamento é baseado em informações do cabeçalho do pacote. <br />
#Cite 5 tecnologias de acesso. Classifique cada uma delas nas categorias acesso residencial, acesso corporativo ou acesso móvel. <br />
#FTTH, HFC e ADSL são usados para acesso residencial. Para cada uma dessas tecnologias de acesso, cite uma faixa de taxas de transmissão e comente se a largura de banda é compartilhada ou dedicada.<br />
#Cite tecnologias de acesso residencial disponíveis na grande Florianópolis. Para cada tipo de acesso, apresente a taxa de ''downstream'', a taxa de ''upstream'' e o preço mensal anunciados.<br />
#Qual é a taxa de transmissão de LANs Ethernet?<br />
#Qual é a vantagem de uma rede de comutação de circuitos em relação a uma de comutação de pacotes?<br />
#Porque dividimos a arquitetura da Internet (e de redes de comutação de pacotes em geral) em camadas? Por que dizemos que uma camada inferior presta um serviço a camada superior?<br />
#Quais são as cinco camadas da pilha de protocolo da Internet? Quais as principais responsabilidades de cada uma dessas camadas? <br />
#O que significa o processo de encapsulamento e desencapsulamento de pacotes no contexto da rede organizada em camadas?<br />
#O que é uma mensagem de camada de aplicação? Um segmento da camada de transporte? Um datagrama da camada de rede? Um quadro de camada de enlace? Qual a relação entre eles?<br />
#Que camadas da pilha de protocolo da Internet um roteador implementa? Que camadas um comutador de enlace implementa? Que camadas um sistema final implementa?<br />
#A noção de portas é criada pela camada de transporte na arquitetura TCP/IP. Qual a funcionalidade que as portas permitem implementar?<br />
#Descreva todo o processo de ''download'' de um arquivo utilizando a ferramenta Bittorrent. Considere que o usuário acabou de instalar a mesma.<br />
#Imagine que você queira enviar, com urgência, 40 terabytes de dados de São José a Manaus. Você tem disponível um enlace dedicado de 100 Mbps para a transferência de dados. Você escolheria transferir os dados pelo enlace ou mandar mídias por Sedex 10? Explique.<br />
#Para pensar I: um celular tipo smartphone acessa normalmente quantas redes? Quais tecnologias sao usadas? Elas são de comutação de pacotes ou de circuitos?<br />
--><br />
{{Collapse bottom}}<br />
{{Collapse top |Lista de exercícios 3 - Camada de Transporte}}<br />
#Considere uma conexão TCP entre o hospedeiro A e o hospedeiro B. Suponha que os segmentos TCP que trafegam do hospedeiro A para o hospedeiro B tenham número de porta fonte x e número de porta destino y. Quais são os números de porta fonte e do destino para os segmentos que trafegam do hospedeiro B para o hospedeiro A? <br />
#Descreva porque um desenvolvedor de aplicação pode escolher rodar uma aplicação sobre UDP em vez de sobre TCP. <br />
#O que são os serviços de multiplexação e demultiplexação implementados pela camada de transporte? <br />
#Porque se diz que o UDP é um protocolo não orientado para conexão? <br />
#Qual o papel das informações de porta origem e destino contidas nos segmentos TCP e UDP? <br />
#Porque é dito que o TCP fornece transferência confiável de dados sobre um canal não confiável?<br />
#Cite 3 diferenças entre os serviços oferecidos pelo TCP e UDP.<br />
#Para que serve um ''checksum'' em um segmento TCP ou UDP? Como ele é formado?<br />
#Cite um motivo para um protocolo de transmissão confiável adicionar um número de seqüência em cada pacote transmitido. Justifique o uso dessa informação explicando o problema que ocorreria caso ela não fosse usada.<br />
#Para que serve um ''timeout'' em um protocolo de transmissão confiável?<br />
#O que é uma reconhecimento cumulativo? [[Arquivo:WiresharkUDP.png |thumb | 600px| Figura 1 -- Captura 1 - Wireshark]]<br />
#Baseado na Figura 1, responda as seguintes perguntas:<br />
##Quais os IP fonte e destino?<br />
##Qual o protocolo da camada de transporte utilizado?<br />
##Quais as portas fonte e destino.<br />
##Qual o conteúdo do campo de tamanho (anote o tamanho) e ''checksum'' no pacote (datagrama)?<br />
##Quantos bits possui o ''checksum''? Como você calculou?<br />
##Qual o significado do campo '''Data: 74657374650a'''? Qual é a mensagem contida? Como você chegou a essa conclusão? [[Arquivo:WiresharkTCP.png |thumb | 600px| Figura 2 -- Captura 2 - Wireshark]]<br />
#Baseado na Figura 2, responda as seguintes perguntas:<br />
##Quais os IP fonte e destino?<br />
##Qual o protocolo da camada de transporte utilizado?<br />
##Quais as portas fonte e destino.<br />
##Qual o conteúdo do campo de tamanho (anote o tamanho) no pacote (datagrama)? O tamanho apresentado significa bits ou bytes?<br />
##Qual o significado do campo '''Data: 74657374650a'''? Qual é a mensagem contida? Como você chegou a essa conclusão? [[Arquivo:WiresharkTCPPerdaDePacotes.png |thumb | 600px| Figura 3 -- Captura 3 - Wireshark]]<br />
#Baseado na Figura 3, responda as seguintes perguntas:<br />
##Quais os IP fonte e destino?<br />
##Qual o protocolo da camada de transporte utilizado?<br />
##Quais as portas fonte e destino.<br />
##Qual o número de sequência (normalizado pelo Wireshark) de cada segmento de dados transmitido, e qual o significado do número de reconhecimento em cada um deles?<br />
##Como foi reconhecido cada segmento enviado?<br />
##Qual o significado do conjunto de mensagens de número (No.) 1 à 3? Explique essas 3 mensagens.<br />
##Qual o significado do conjunto de mensagens de número (No.) 17 à 19? Explique essas 3 mensagens.<br />
##Qual o significado do conjunto de mensagens de número (No.) 6, 11 e 16? Explique essas 3 mensagens.<br />
##Qual é o tamanho "médio" de janela de cado um dos ''hosts''?<br />
##Qual a utilizade das mensagens com fundo preto?<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Lista de exercícios 4 - Camada de Rede}}<br />
#Quais são as principais características de uma rede de datagramas?<br />
#Roteadores possuem endereços IP? Quantos endereços IP um roteador possui?<br />
#Para que serve o protocolo ICMP? <br />
#Para que serve o campo “Time to Live” (sobrevida) em um datagrama IP? <br />
#Quantos hosts podem ser endereçados com um bloco IP 200.23.16.0/20? Como podemos montar 8 sub-redes a partir deste bloco de endereços IP?<br />
#Um provedor de serviços ISP possui cerca de 2000 clientes cadastrados atualmente. Porém um levantamento realizado recentemente pelo administrador da rede constatou que nunca mais do que 450 clientes estão on-line ao mesmo tempo. Qual o bloco de endereços IP na forma CIDR (a.b.c.d/x) deve ser contratado pelo ISP, considerando o estudo realizado pelo administrador da rede?<br />
#Um administrador precisa montar uma rede experimental conforme mostrada na figura. Na sub-rede 1 ele precisará instalar cerca 25 hosts, e nas sub-redes 2 e 3 ele precisará instalar cerca de 12 hosts. O administrador dispõe do bloco de endereços IP 192.168.10.0/24 para ser utilizado no endereçamento da rede experimental. Faça uma proposta para alocação de endereços IP para cada sub-rede (rede 1, 2 e 3), incluindo também as sub-redes relativas aos enlaces ponto-a-ponto (rede AB, AC e BC). Responda ainda:<br />
##Qual o endereço identificador de rede de cada sub-rede (1, 2 e 3)?<br />
##Qual o a máscara de rede de cada sub-rede (1, 2 e 3)?<br />
##Quais os endereços IP que serão atribuídos a cada interface de rede nos enlaces ponto-a-ponto dos roteadores (enlaces relativos as redes AB, AC e BC)[[Arquivo:CdrEx.png]]<br />
#Suponha que um administrador de rede tenha recebido o bloco de endereços 200.40.8.0/21 e que deseja dividir este bloco em 8 blocos de endereços iguais, de menor tamanho, para ser alocado a 8 sub-redes administradas por ele.<br />
##Determine o tamanho total do bloco de endereços.<br />
##Determine o tamanho de cada sub-bloco.<br />
##Determine o endereço/máscara de rede de cada sub-rede.<br />
#Um provedor de acesso a Internet possui o seguinte bloco de endereços IP: 12.17.192.0/18. Os endereços IP de 12.17.192.1 até 12.17.207.255 já estão alocados para clientes deste provedor. Este provedor precisa atender a quatro novos clientes, um deles necessita de rede com pelo menos 1000 endereços de IP válidos e os outros três necessitam de rede com pelo menos 30 IP válidos. Faça uma proposta para alocação de endereços IP para estes clientes. Os endereços reservados para estes novos clientes devem ser alocados a partir da numeração mais baixa disponível. Procure também responder as questões abaixo:<br />
##Qual o total de endereços que dispõe o provedor em questão?<br />
##Quantos endereços IP já estão utilizados?<br />
##Quantos endereços IP este provedor possui livres para alocar aos novos clientes?<br />
##Qual o endereço identificador de cada sub-rede dos novos clientes?<br />
##Qual o a máscara de rede de cada sub-rede dos novos clientes?<br />
##Qual o endereço de broadcast de cada sub-rede dos novos clientes?<br />
##Quantos endereços IP ainda sobrarão ao provedor após atender a estes clientes?<br />
#Quantas estações uma rede 223.1.10.0/24 suporta? <br />
#Uma rede com bloco de IPs 200.23.16.0/20 deseja montar 8 subredes. Mostre como isso é possível e como ficaria os endereços de cada uma dessas subredes.<br />
#Um datagrama enviado para uma estação da mesma rede precisa passar por um roteador?<br />
#Suponha que entre o hospedeiro de origem A e o hospedeiro de destino B os datagramas estejam limitados a 1500 bytes (incluindo cabeçalho). Admitindo um cabeçalho IP de 20 bytes, quantos datagramas seriam necessários para enviar um arquivo MP3 de 5 milhões de bytes? Explique como você obteve a resposta.<br />
#Descreva e detalhe o processo de obtenção de um endereço IP através do protocolo DHCP. [[Image:ExercicioConfEstaticaZebra.png]]<br />
#Considere a rede apresetanda na Figura, onde todas as sub-redes apresentam máscara de rede /24 (255.255.255.0), e tendo os dados do Host1 e Roteador 4 apresentados no quadro abaixo, responda: <syntaxhighlight lang=bash><br />
root@H1:~# ifconfig <br />
eth0 Link encap:Ethernet HWaddr 7a:a6:f4:ca:51:0e <br />
inet addr:200.10.1.1 Bcast:200.10.1.255 Mask:255.255.255.0<br />
<br />
root@H1:~# route -n<br />
Kernel IP routing table<br />
Destination Gateway Genmask Flags Metric Ref Use Iface<br />
0.0.0.0 200.10.1.254 0.0.0.0 UG 0 0 0 eth0<br />
200.10.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0<br />
<br />
root@R4:~# route -n<br />
Kernel IP routing table<br />
Destination Gateway Genmask Flags Metric Ref Use Iface<br />
200.10.1.0 200.10.3.1 255.255.255.0 UG 0 0 0 eth0<br />
200.10.3.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0<br />
200.10.5.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1<br />
200.10.6.0 0.0.0.0 255.255.255.0 U 0 0 0 eth2<br />
200.10.8.0 200.10.6.1 255.255.255.0 UG 0 0 0 eth2 </syntaxhighlight><br />
##Observando a tabela do hospedeiro (H1) é possível dizer quem é seu roteador default?<br />
##Se o hospedeiro (H1) tiver um pacote para entregar para o IP 200.10.1.20 ele utilizará entrega direta ou utilizará seu roteador padrão? Explique o significado da entrega direta e indireta (via roteador).<br />
##Se o hospedeiro (H1) tiver um pacote para entregar para o IP 200.10.8.1 ele utilizará entrega direta ou utilizará seu roteador padrão?<br />
##Se o roteador (R4) receber um pacote cujo IP de destino é 200.10.1.10 para qual roteador ele entregará tal pacote e por qual interface? Será uma entrega direta ou indireta?<br />
##Se o roteador (R4) receber um pacote cujo IP de destino é 200.10.6.1 para qual roteador ele entregará tal pacote e por qual interface? Será uma entrega direta ou indireta?<br />
##Se o roteador (R4) receber um pacote cujo IP de destino é 200.10.1.10, cuja carga segmento TCP com destino a porta 80, para qual roteador ele entregará tal pacote e por qual interface? Será uma entrega direta ou indireta?<br />
##Se o roteador (R4) receber um pacote cujo IP de destino é 122.10.4.7 para qual roteador ele entregará tal pacote e por qual interface? Explique.<br />
##Qual comando que você executaria no roteador (R4) para acrescentar uma rota para a rede SN2? Explique seu comando.<br />
##Considerando a pergunta anterior, a rota acrescentada garantiria que se você fizer um ping para um host da rede SN2 você obteria sucesso? Explique todas as possibilidades.<br />
##Explique o significado dos campos das colunas 1, 2, 3 e 8 da última linha da tabela do roteador (R4).<br />
{{Collapse bottom}}</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)&diff=162007Curso Técnico Integrado de Telecomunicações - Redes de Computadores (RCO)2019-10-03T19:52:11Z<p>127.0.0.1: /* Laboratórios */</p>
<hr />
<div>__NOTOC__<br />
<br />
{{DivulgueEngtelecom}}<br />
==Informações Gerais==<br />
*[[RCO-IntTel|Carga horária, Ementas, Bibliografia]]<br />
*[[RCO-IntTel (Plano de Ensino) | Plano de Ensino]]<br />
*[[Cronograma de atividades (RCO-IntTel) | Cronograma de atividades]]<br />
<br />
==Edições==<br />
*[[RCO60803 2019-1|RCO60803 2019-1 - Trabalho dirigido - Prof. Odilson Tadeu Valle]]<br />
*[[RCO60803 2018-2|RCO60803 2018-2 - Prof. Odilson Tadeu Valle / Prof. Eraldo Silveira e Silva]]<br />
*[[RCO60803 2018-1|RCO60803 2018-1 - Prof. Odilson Tadeu Valle / Prof. Eraldo Silveira e Silva]]<br />
*[[RCO60803 2017-2|RCO60803 2017-2 - Prof. Odilson Tadeu Valle / Prof. Eraldo Silveira e Silva]]<br />
*[[RCO60803 2017-1|RCO60803 2017-1 - Prof. Juliano de Souza / Prof. Eraldo Silveira e Silva]]<br />
*[[RCO60803 2016-2|RCO60803 2016-2 - Prof. Juliano de Souza / Prof. Luciano Barreto]]<br />
*[[RCO60803 2016-1|RCO60803 2016-1 - Prof. Fernando Rodrigues Santos / Prof. Juliano de Souza]]<br />
*[[RCO60803-2015-2|RCO60803 2015-2 - Prof. Simara Sonaglio]]<br />
*[[RCO60803-2015-1|RCO60803 2015-1 - Prof. Arliones Hoeller / Prof. Túlio Ribeiro]]<br />
*[[RCO60803-2014-2|RCO60803 2014-2 - Prof. Arliones Hoeller / Prof. Tomás Grimm / Prof. José Clair]]<br />
<br />
= Material de apoio =<br />
<br />
==''Applets'' do Kurose==<br />
Vários [http://wps.pearsoned.com/ecs_kurose_compnetw_6/216/55463/14198700.cw/ aplicativos] com representação dinâmica de características das redes de computadores.<br />
==Transparências utilizadas durante as aulas==<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/slides-kurose-cap1.pdf Capítulo 1 - Introdução]<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/slides-kurose-cap2.pdf Capítulo 2 - Camada de Aplicação]<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/PPTs%20-%20Cap%C3%ADtulo%202%20-%20FTP%20-%20Email%20-%20P2P.pdf Capítulo 2 - Camada de Aplicação - FTP + EMAIL + P2P]<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/slides-kurose-cap3.pdf Capítulo 3 - Camada de Transporte]<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/PPTs%20-%20Cap%C3%ADtulo%204%20A%20camada%20de%20REDE.pdf Capítulo 4 - Camada de Rede]<br />
<br />
==Slides de Outras Universidades==<br />
<br />
*[https://www.google.com.br/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0ahUKEwiO0aDJu_LTAhWJlZAKHX8JA2wQFggjMAA&url=http%3A%2F%2Fwww.eecs.yorku.ca%2Fcourse_archive%2F2015-16%2FW%2F3214%2FCSE3214_14_TCP_2_2016_posted_part2.pdf&usg=AFQjCNEJh3yITWuyOPZ17bbObT54JqrLCw&sig2=jJwHLo13iooIUaI5F2m-kA TCP Error Control- EECS - LASSONDE]<br />
*[https://www.google.com.br/url?sa=t&rct=j&q=&esrc=s&source=web&cd=2&cad=rja&uact=8&ved=0ahUKEwiO0aDJu_LTAhWJlZAKHX8JA2wQFggpMAE&url=http%3A%2F%2Fwww.eecs.yorku.ca%2Fcourse_archive%2F2015-16%2FW%2F3214%2FCSE3214_14_TCP_2_2016_posted_part1.pdf&usg=AFQjCNHNz8hZ4GHyiDZkcMgomCQBR4KTaA&sig2=nS8450rR2x6C_EM9tT0yWw TCP- Flow and Error Control - LASSONDE]<br />
*[https://www.google.com.br/url?sa=t&rct=j&q=&esrc=s&source=web&cd=3&ved=0ahUKEwjUvtPAmJjUAhXHHZAKHfSBAEgQFghCMAI&url=http%3A%2F%2Fwww.eecs.yorku.ca%2Fcourse_archive%2F2015-16%2FW%2F3214%2FCSE3214_14_TCP_3_2016_posted.pdf&usg=AFQjCNHFkmBZT2Pn_G6e-AuDvJHL6FuZzg&sig2=UxXTDU_OKoMp2jC3K1O-jg Congestion Control - LASSONDE]<br />
*[https://www.cpe.ku.ac.th/~cpj/204325/ Slides/Aula Faculty of Engineering, Kasetsart University]<br />
<br />
== Curiosidades ==<br />
<br />
* [http://www.pop-sc.rnp.br/publico/monitoramento.php Monitoramento do tráfego RNP - PoP-SC]<br />
* [http://memoria.rnp.br/ceo/trafego/panorama.php Monitoramento do tráfego RNP - Nacional]<br />
* [http://www.redclara.net/index.php/pt/red/redclara/topologia-actual-de-la-red Rede Clara Internacional]<br />
* [https://eventos.rnp.br/sites/default/files/activity/activity-presentation/apresentacao_wrnp_2017_eduardo_grizenid_v_1.2.pdf Futura infraestrutura de rede da RNP]<br />
* [https://www.youtube.com/watch?v=IlAJJI-qG2k Animated map shows the undersea cables that power the internet]<br />
* [http://submarine-cable-map-2018.telegeography.com/ Submarine Cable Map 2018]<br />
* [https://www.youtube.com/watch?v=A5dD2x2iQx8 ''History of the Internet'' - legendado]<br />
* [https://www.youtube.com/watch?v=O_xG0ay5Vqs ''Warriors of the Net'' - legendado]<br />
* [https://www.youtube.com/watch?v=1G3SUTmioQE ''Browser Wars'' - legendado]<br />
* [https://www.youtube.com/watch?v=0nz-lcuv3TM ''Browser Wars'' - dublado]<br />
* [https://db-ip.com/200.135.37.65 Localização geográfica de IPs]<br />
* [http://ipv6.br/ '''IPv6 no Brasil''']<br />
* [http://ipv6.br/lab/ Laboratório de IPv6 - Livro didático contendo vários roteiros para entendimento do IPv6]<br />
* [https://www.google.com/intl/pt-BR/ipv6/statistics.html#tab=per-country-ipv6-adoption&tab=per-country-ipv6-adoption Estatísticas Google sobre IPv6]<br />
<br />
=Laboratórios=<br />
<br />
{{Collapse top |Laboratório 1 - Ferramentas de Rede e Conceitos Básicos}}<br />
<br />
===Objetivos===<br />
<br />
*Familiarização com a infraestrutura dos laboratórios de redes<br />
*Familiarização com ferramentas de rede: ifconfig, ping, traceroute;<br />
*Desenvolver a noção de endereçamentos de rede IP e de endereço de hardware (MAC)<br />
*Desenvolver a noção de rotas em redes IP<br />
*Testar a conectividade IP com ping<br />
<br />
===Conceitos introdutórios para uso do laboratório===<br />
<br />
<br />
====Estrutura do Laboratório====<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/Ferramentas%20de%20rede%20e%20conceitos%20basicos.pdf Conceitos Básicos]<br />
<br />
[http://tele.sj.ifsc.edu.br/~eraldo/AULAS/2018-2/RCO-INTEGRADO/MACxIP.pdf Endereçamento MAC x Endereçamento IP]<br />
<br />
A rede do laboratório em uso segue o modelo apresentado no diagrama da Figura 1 (endereçamento pode ser diferente).<br />
<br />
[[Arquivo:Diagrama_rede_IFSC_lab_redes_I.jpeg |thumb | 400px| Figura 1 - Diagrama da rede do laboratório]]<br />
<br />
Os Laboratórios de Redes de Computadores estão equipados com N+1 (N = número de computadores para alunos) computadores conectados em rede e com acesso a Internet. A rede local do laboratório tem endereço IP 192.168.1.0/24. A máscara de rede '''/24''' indica que o último ''byte'' do endereço é utilizado para identificar cada máquina, por exemplo 192.168.1.1, 192.168.1.2, etc.<br />
<br />
===Roteiro de atividades===<br />
====Parte 1: Observando interfaces do sistema com ifconfig====<br />
O aplicativo '''ifconfig''' pode ser utilizado para visualizar a configuração ou configurar uma interface de host em redes TCP/IP. Se nenhum argumento for passado na chamada do '''ifconfig''', o comando mostra a configuração atual de cada interface de rede.<br />
<br />
NOTA: o ifconfig está sendo substituído pelo comando ip. A última versão do Uuntu já não traz mais o ifconfig por default.<br />
<br />
Consultar as páginas ''man ifconfig'' do Linux para maiores detalhes sobre o funcionamento deste aplicativo, o qual permite ativar/desativar a interface, configurar o endereço IP, definir o tamanho da MTU, redefinir o endereço de hardware se a interface suporta, redefinir a interrupção utilizada pelo dispositivo, entre outros.<br />
<br />
<br />
#Analisando os dados obtidos do seguinte exemplo <syntaxhighlight lang=bash>ifconfig <br />
eth0 Link encap:Ethernet Endereço de HW 64:51:06:1a:f3:da <br />
inet end.: 172.18.18.14 Bcast:172.18.63.255 Masc:255.255.192.0<br />
endereço inet6: fe80::6651:6ff:fe1a:f3da/64 Escopo:Link<br />
UP BROADCAST RUNNING MULTICAST MTU:1500 Métrica:1<br />
pacotes RX:415237 erros:0 descartados:0 excesso:0 quadro:0<br />
Pacotes TX:118109 erros:0 descartados:0 excesso:0 portadora:0<br />
colisões:0 txqueuelen:1000 <br />
RX bytes:364658695 (364.6 MB) TX bytes:18315199 (18.3 MB)<br />
IRQ:18 <br />
<br />
lo Link encap:Loopback Local <br />
inet end.: 127.0.0.1 Masc:255.0.0.0<br />
endereço inet6: ::1/128 Escopo:Máquina<br />
UP LOOPBACK RUNNING MTU:65536 Métrica:1<br />
pacotes RX:6688 erros:0 descartados:0 excesso:0 quadro:0<br />
Pacotes TX:6688 erros:0 descartados:0 excesso:0 portadora:0<br />
colisões:0 txqueuelen:0 <br />
RX bytes:1057934 (1.0 MB) TX bytes:1057934 (1.0 MB) </syntaxhighlight><br />
##O sistema em questão possui duas interfaces de rede: '''eth0''' e '''lo'''<br />
##'''Link encap:Ethernet''': Configuração da interface '''Eth'''ernet 0 (primeira)<br />
##'''Endereço de HW 64:51:06:1a:f3:da''': É o endereço da placa de rede, camada 2<br />
##'''inet end.: 172.18.18.14 Bcast:172.18.63.255 Masc:255.255.192.0''': Endereço IPv4 associado a interface, seu respectivo endereço de ''broadcast'' e mascara de rede<br />
##endereço inet6: fe80::6651:6ff:fe1a:f3da/64 Escopo:Link: Endereço IPv6 de escopo local gerado por autoconfiguração<br />
##'''UP BROADCAST RUNNING MULTICAST''': Significa que a interface está ativa (UP), responde a requisições de broadcast (pode ser desabilitado no kernel) e também pode ser associada a tráfegos ''multicast''<br />
##'''MTU: 1500''': ''Maximum Transfer Unit'' – Tamanho máximo do pacote suportado pelo enlace que é do tipo Ethernet<br />
##Os demais parâmetros são estatísticas da respectiva interface, como por exemplo, pacotes transmitidos, recebidos etc<br />
##A interface '''lo''': Qualquer tráfego que um computador envie em uma rede ''loopback'' é endereçada ao mesmo computador. O endereço IP mais usado para tal finalidade é 127.0.0.1 no IPv4 e ::1 no IPv6. O nome de domínio padrão para tal endereço é ''localhost''. Em sistemas Unix, a interface loopback é geralmente chamada de lo ou lo0.<br />
#Agora utilize o comando '''ifconfig''' para verificar o estado de suas interfaces e responda:<br />
##Quantas e quais interfaces de rede sua máquina possui? Liste.<br />
##Quais são os endereços da camada 2 atribuído as mesmas? De onde o sistema obteve esses endereços?<br />
##Quais são os endereços IPv4? De onde o sistema obteve esses endereços?<br />
##Suas interfaces tem IPv6 configurado? Qual o endereço e escopo dos mesmos? Como foram obtidos? Qual o alcance (é roteável) do mesmo?<br />
##Use o link *[http://jodies.de/ipcalc Verificando a estrutura do endereço IP] para explorar a estrutura do seu endereço IPv4.<br />
<br />
====Parte 2: Testando a conectividade com o ping====<br />
<br />
Aplicativo '''ping''' permite a um usuário verificar se um ''host'' remoto está ativo. É bastante utilizado para detectar problemas de comunicação na rede.<br />
O '''ping''' está baseado no envio de mensagens de solicitação de eco (''echo request'') e de resposta de eco (''echo reply''). Estas mensagens fazem parte do rol de mensagens do protocolo ICMP, que é um protocolo de reportagem de erros, a ser estudado mais tarde, componente do protocolo IP.<br />
<br />
O '''ping''' é um dos principais comandos a disposição do administrador de rede no sentido de verificar a conectividade em rede. Por exemplo, se houver resposta de um ping a partir de um servidor remoto, significa que a máquina local está rodando corretamente o TCP/IP, o enlace local está funcionando corretamente, o roteamento entre a origem e o destino está operando, e por fim, a máquina remota também está rodando corretamente o TCP/IP.<br />
<br />
Consultar as páginas ''man'' do ping para verificar as possibilidades de uso deste aplicativo.<br />
<br />
#Exemplo 1: <syntaxhighlight lang=bash><br />
ping 191.36.0.94<br />
PING 191.36.0.94 (191.36.0.94) 56(84) bytes of data.<br />
64 bytes from 191.36.0.94: icmp_seq=1 ttl=60 time=2.46 ms<br />
64 bytes from 191.36.0.94: icmp_seq=2 ttl=60 time=0.513 ms<br />
64 bytes from 191.36.0.94: icmp_seq=3 ttl=60 time=0.573 ms<br />
64 bytes from 191.36.0.94: icmp_seq=4 ttl=60 time=0.558 ms<br />
^C<br />
--- 191.36.0.94 ping statistics ---<br />
4 packets transmitted, 4 received, 0% packet loss, time 3001ms<br />
rtt min/avg/max/mdev = 0.513/1.026/2.463/0.830 ms </syntaxhighlight><br />
<br />
##No exemplo foram enviados quatro pacotes ICMP, cada um com um número de seqüência (''icmp_seq''), os quais foram recebidos com sucesso com o tempo de viagem assinalado (''time'')<br />
##Cada pacote tem ainda um tempo de vida (''ttl'' – ''time to live''), o qual é decrementado em cada roteador, sendo o pacote descartado quando chegar a zero; isto evita pacotes perdidos na rede<br />
##Quando o ping é interrompido ('''CRTL-C'''), uma estatística é apresentada indicando o percentual de pacotes transmitidos, recebidos e perdidos<br />
##O tempo de viagem (''rtt'' – ''round trip time'') mínimo (''min''), médio (''avg'') e máximo (''max'') é calculado, assim como o desvio padrão (''mdev'')<br />
#Como exercício envie '''ping''' para diferentes ''hosts'' e compare os tempos de resposta:<br />
##no endereço local de loopback;<br />
##máquina de um colega do laboratório;<br />
##servidor e roteador da rede da escola;<br />
##servidores externos: <syntaxhighlight lang=bash><br />
www.ifsc.edu.br<br />
www.uol.com.br<br />
www.nasa.com </syntaxhighlight> e explique as possíveis diferenças entre os tempos de resposta dos ping realizados.<br />
#Consulte as páginas ''man'' e teste o '''ping''' com os parâmetros abaixo e descreva suas funcionalidades:<br />
##-c count<br />
##-i intervalo<br />
##-s packetsize<br />
##-t ttl (para um site distante inicie com 1 e vá incrementando, observe as mensagens)<br />
#Observe que também é possível realizar ping em endereços no formato IPv6, por exemplo: <syntaxhighlight lang=bash> ping6 www.sj.ifsc.edu.br </syntaxhighlight><br />
#Tente o ping6 para outros sites.<br />
<br />
====Parte 3: Verificando rotas com o traceroute====<br />
O '''traceroute''' é capaz de traçar uma rota aproximada entre dois ''hosts''. Este comando usa mensagens ICMP. Para determinar o nome e o endereço dos roteadores entre a fonte e o destino, o traceroute na fonte envia uma série de datagramas IP ordinários ao destino. O primeiro datagrama tem o TTL (''time to live'' – tempo de vida) igual a 1, o segundo 2, o terceiro 3, e assim por diante, e inicia temporizadores para cada datagrama. Quando o enésimo datagrama chega ao enésimo roteador, este verifica que o tempo de sobrevida do datagrama acaba de terminar. Pelas regras do IP, o datagrama é então descartado e uma mensagem ICMP de advertência tempo de vida excedido é enviada a fonte com o nome do roteador e seu endereço IP. Quando a resposta chega de volta a fonte, a mesma calcula o tempo de viagem em função dos temporizadores.<br />
<br />
O '''traceroute''' envia datagramas IP encapsulados em segmentos UDP a um host destino. Todavia escolhe um número de porta destino com um valor desconhecido (maior que 30000), tornando improvável que o host destino esteja usando esta porta. Quando o datagrama chega ao destino uma mensagem ICMP porta inalcançável é gerada e enviada a origem. O programa traceroute precisa saber diferenciar as mensagens ICMP recebidas – tempo excedido e porta inalcançável – para saber quando a rota foi concluída.<br />
<br />
#Exemplo: <syntaxhighlight lang=bash><br />
sudo traceroute -I 200.135.37.65<br />
traceroute to 200.135.37.65 (200.135.37.65), 30 hops max, 60 byte packets<br />
1 192.168.1.1 (192.168.1.1) 0.225 ms 0.216 ms 0.368 ms<br />
2 172.18.0.254 (172.18.0.254) 1.236 ms 1.235 ms 1.343 ms<br />
3 hendrix.sj.ifsc.edu.br (200.135.37.65) 1.331 ms 1.313 ms 1.414 ms </syntaxhighlight><br />
O exemplo mostra a rota dos pacotes entre um computador do Lab. Redes (192.168.1.1) e o servidor ''hendrix'' (200.135.37.65). Observe que para cada roteador são realizados três amostras de tempo de ida e volta. Veja pelo mapa da rede do Campus São José que entre estes dois computadores, sistemas finais, existem dois roteadores intermediários, máquina do professor e Switch camada 3 (VLANs).<br />
#Traçar a rota dos pacotes entre seu computador e diferentes hosts:<br />
##máquina de um colega do laboratório<br />
##servidor e roteador da rede da escola<br />
##servidores externos.<br />
#Explique as possíveis diferenças entre os tempos de resposta de cada uma das amostras do '''traceroute'''<br />
#Explique as linhas com o caracter *.<br />
#Fazendo uso das ferramentas desse laboratório, refaça o diagrama da rede do campus apontando claramente os novos endereços IPs associados aos roteadores.<br />
#Observe que também é possível realizar traceroute em endereços no formato IPv6, por exemplo: <syntaxhighlight lang=bash> sudo traceroute -I6 ipv6.br </syntaxhighlight><br />
#Tente o traceroute no IPv6 para outros sites.<br />
<br />
====Referências adcionais====<br />
<br />
* [http://linux-ip.net/html Guia de Administração da Camada IP no Linux<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 2 - Wireshark e encapsulamento}}<br />
<br />
===Objetivos===<br />
<br />
*Familiarização com o ''sniffer'' de rede WireShark<br />
*Observar o comportamento do ''ping'' e se familiarizar com o processo de encapsulamento;<br />
<br />
====WireShark====<br />
2005 KUROSE, J.F & ROSS, K. W. Todos os direitos reservados <br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/Wireshark%20e%20encapsulamento.pdf Wireshark e encapsulamento]<br />
*Introdução<br />
O entendimento de protocolos de redes pode ser bastante aprofundado através da “observação de protocolos funcionando” e “da manipulação de protocolos” - observando a sequência de mensagens trocadas entre duas entidades, entrando nos detalhes da operação do protocolo, e fazendo com que os protocolos realizem certas ações e então observando estas ações e as consequências. <br />
<br />
A ferramenta básica para observar as mensagens trocadas entre as entidades em execução é chamada de ''sniffer''. Como o nome sugere, um ''sniffer'' captura mensagens sendo enviadas/recebidas pelo seu computador; ele também tipicamente armazena e/ou apresenta os conteúdos dos vários campos dos protocolos nestas mensagens capturadas. Um ''sniffer'' isoladamente é um elemento passivo. Ele observa as mensagens sendo enviadas e recebidas pelas aplicações e protocolos executando no seu computador, mas jamais envia pacotes. Similarmente, os pacotes recebidos nunca são explicitamente endereçados ao ''sniffer''. Ao invés disso, um ''sniffer'' recebe uma cópia de pacotes que são enviados/recebidos para/de aplicações e protocolos executando no seu computador. <br />
<br />
A Figura 2 mostra a estrutura de um ''sniffer''. À direita da Figura 2 estão os protocolos (neste caso, protocolos da Internet) e aplicações (tais como navegador web ou cliente FTP) que normalmente executam no seu computador. O ''sniffer'', exibido dentro do retângulo tracejado na Figura 2 é uma adição aos softwares usuais no seu computador, e consiste de duas partes: a biblioteca de captura de pacotes e o analisador de pacotes. A biblioteca de captura de pacotes recebe uma cópia de cada quadro da camada de enlace que é enviado do ou recebido pelo seu computador. Lembre que mensagens trocadas por protocolos das camadas mais altas tais como HTTP, FTP, TCP, UDP, DNS ou IP, são todos eventualmente encapsulados em quadros que são transmitidos para o meio físico como um cabo Ethernet. Na Figura 2, assume-se que o meio físico é uma Ethernet, e desta forma, os protocolos das camadas superiores são eventualmente encapsulados em um quadro Ethernet. Capturar todos os quadros fornece todas as mensagens enviadas/recebidas de/por todos os protocolos e aplicações executando em seu computador.<br />
<br />
[[Arquivo:Sniffer_estrutura.png |thumb | 500px| Figura 2 - Estrutura de um ''sniffer'']]<br />
<br />
O analisador de pacotes exibe os conteúdos de todos os campos dentro de uma mensagem de protocolo. Para que isso seja feito, o analisador de pacotes deve “entender” a estrutura de todas as mensagens trocadas pelos protocolos. Por exemplo, suponha que estamos interessados em mostrar os vários campos nas mensagens trocadas pelo protocolo HTTP na Figura 5. O analisador de pacotes entende o formato dos quadros Ethernet, e desta forma pode identificar o datagrama IP dentro de um quadro. Ele também entende o formato do datagrama IP, para que ele possa extrair o segmento TCP dentro do datagrama IP. Ele entende a estrutura do segmento TCP, para que possa extrair a mensagem HTTP contida no segmento. Finalmente, ele entende o protocolo HTTP e então, por exemplo, sabe que os primeiros bytes de uma mensagem HTTP contém a cadeia “GET”, “POST” ou “HEAD”. Nós utilizaremos o ''sniffer'' Wireshark (http://www.wireshark.org) para estes laboratórios, o que nos permite exibir os conteúdos das mensagens sendo enviadas/recebidas de/por protocolos em diferentes camadas da pilha de protocolos. Tecnicamente falando, Wireshark é um analisador de pacotes que pode ser executado em computadores com Windows, Linux/UNIX e MAC.<br />
<br />
É um analisador de pacotes ideal para nossos laboratórios, pois é estável, tem uma grande base de usuários e é bem documentado incluindo um guia de usuário (http://www.wireshark.org/docs/wsug_html/), páginas de manual (http://www.wireshark.org/docs/man-pages/), e uma seção de FAQ detalhada (http://www.wireshark.org/faq.html), funcionalidade rica que inclui a capacidade de analisar mais que 500 protocolos, e uma interface com o usuário bem projetada. Ele funciona em computadores ligados a uma Ethernet para conectar-se à Internet, bem como protocolos ponto a ponto, tal como PPP.<br />
<br />
*Analisando os campos da interface do Wireshark <br />
Quando você executar o programa Wireshark, a interface com o usuário exibida na Figura 3 aparecerá. Inicialmente, nenhum dado será apresentado nas janelas. A interface do Wireshark tem seis componentes principais: <br />
#Os menus de comandos são localizados no topo da janela. Por enquanto, interessam apenas os menus ''File'' e ''Capture''. O menu ''File'' permite salvar dados de capturas de pacotes ou abrir um arquivo contendo dados de capturas de pacotes previamente realizadas, e sair da aplicação. O menu ''Capture'' permite iniciar uma captura de pacotes; <br />
#A barra de ferramentas contém os comandos de menu que são mais frequentemente utilizados. Há atalhos para abrir ou salvar dados de captura de pacotes e para iniciar ou parar uma captura de pacotes; <br />
#Abaixo da barra de ferramentas, está o campo de filtragem de pacotes exibidos. Nele podem ser digitados nome de protocolo ou outra informação apresentada na janela de listagem de pacotes. Apenas os pacotes que correspondem ao filtro são exibidos; <br />
#A janela de listagem de pacotes apresenta um resumo de uma linha para cada pacote capturado, incluindo o número do pacote (atribuído pelo Wireshark; este não é o número do pacote contido no cabeçalho de qualquer protocolo), o tempo que o pacote foi capturado, os endereços fonte e destino do pacote, o tipo de protocolo, e informação específica do protocolo contida no pacote. A lista de pacotes pode ser ordenada conforme qualquer uma destas categorias clicando no nome de uma coluna correspondente. O campo tipo do protocolo lista o protocolo de mais alto nível que enviou ou recebeu este pacote, i.e., o protocolo que é a fonte ou o último sorvedouro para este pacote; <br />
#A janela de detalhes de cabeçalho de pacotes fornece detalhes sobre o pacote selecionado na janela de listagem de pacotes. Para selecionar um pacote, basta clicar sobre ele com o botão esquerdo do mouse na janela de listagem de pacotes. Os detalhes apresentados incluem informações sobre o quadro Ethernet e o datagrama IP que contém o pacote. A quantidade de detalhes exibida pode ser expandida ou contraída. Se o pacote foi carregado sobre TCP ou UDP, detalhes correspondentes também são apresentados, os quais também podem ser contraídos ou expandidos. Finalmente, detalhes sobre o protocolo de mais alto nível que enviou ou recebeu este pacote também são apresentados; <br />
#A janela de conteúdo de pacotes mostra o conteúdo inteiro do quadro capturado, nos formatos ASCII e hexadecimal.<br />
<br />
[[Arquivo:Wireshark_interface_usuario.png | 700px| Figura 3 - Interface com o usuário do Wireshark]]<br />
<br />
====Roteiro de atividades====<br />
<br />
=====Etapa 1===== <br />
#Inicie o navegador web; <br />
#Inicie o Wireshark. Inicialmente as janelas estarão vazias, pois não há captura de pacotes em progresso; <br />
#Para iniciar uma captura de pacotes, selecione o menu Capture e depois Interfaces. Provavelmente sua interface de rede será a '''eth0'''. <br />
#Isso faz com que a janela de interfaces de rede disponíveis seja apresentada (Figura 4); [[Arquivo:Wireshark_interfaces_rede.png |thumb | 400px| Figura 4 - Interfaces de rede no Wireshark]]<br />
#O botão ''Start'' da interface '''eth0''' deve ser selecionado. Na Figura 4, no Wireshark foi selecionada a interface wlan; <br />
#Como nada está acontecendo na rede, a janela apresenta o conteúdo vazio;<br />
#Execute um comando ping (endereço na saída da nossa rede - ver aula anterior):<syntaxhighlight lang=bash><br />
ping 200.237.201.153</syntaxhighlight><br />
#Ao voltar para a janela do Wireshark, houve a captura de todos os pacotes envolvidos no process;<br />
#Antes de continuar, vamos parar a captura de pacotes e trabalhar com o que temos. Basta clicar em ''Capture'' e depois em ''Stop''; <br />
#Para testar as capacidades de filtragem, vamos inserir a cadeia “icmp” (sem as aspas e em minúsculo) no especificação do filtro de exibição e depois selecionar ''Apply'' (ou Aplicar). Observe que somente os pacotes envolvidos no ping estão sendo mostrados. Os resultados obtidos devem ser similar a tela mostrada na Figura 5. <br />
#Selecione a primeira mensagem ECHO REQUEST: as informações dos cabeçalhos do quadro Ethernet, do datagrama IP, do pacote ICMP aparecem na janela de cabeçalhos de pacotes. É possível ver os detalhes, expandido ou comprimindo os itens com um clique na seta ao lado deles.<br />
#Selecione uma mensagem ECHO REPLY. Analise o pacote: endereço fonte, endereço destino etc;<br />
#Saia do Wireshark.<br />
<br />
[[Arquivo:TelaWiresharkPing.png | 700px| Figura 5 - Tela Wireshark - Ping]]<br />
<br />
=====Etapa 2=====<br />
<br />
#Com Wireshark ativo (Abra-o novamente) faça um pingue para um site conhecido (você pode usar o nome: www.ifsc.edu.br por exemplo):<br />
#Teste outros filtros, por exemplo, mostre somente pacotes originados e/ou destinados a um determinado ''host'' ('''ip.addr == 192.168...''', ip.src, ip.dst).<br />
#Qual é o endereço IP do sítio navegado? Qual é o endereço IP da interface de rede do seu computador? Qual o endereço MAC de sua máquina?<br />
<br />
<br />
=====Etapa 3 - Desafios=====<br />
<br />
#Solicite um endereço IP de um colega e faça um experimento para descobrir o endereço MAC do computador dele.<br />
#Tente elaborar um experimento para descobrir o endereço MAC do servidor de www.ifsc.edu.br. É possível? Explique para o professor...<br />
<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 3 - Conceituando protocolos}}<br />
<br />
===Objetivos===<br />
<br />
*Desenvolver o conceito de protocolo<br />
*Conceber um protocolo/serviço de calculadora pela rede<br />
<br />
===Introdução===<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/Conceituando%20protocolos.pdf Conceituando protocolos]<br />
<br />
O entendimento de protocolos de redes pode ser bastante aprofundado através da “observação de protocolos funcionando” e “da manipulação de protocolos” - observando a sequência de mensagens trocadas entre duas entidades, entrando nos detalhes da operação do protocolo, e fazendo com que os protocolos realizem certas ações e então observando estas ações e as consequências.<br />
<br />
Um protocolo de camada de aplicação define:<br />
#Os tipos de mensagens trocadas.<br />
#A sintaxe dos vários tipos de mensagens, tais como os campos da mensagem e como os campos são delineados.<br />
#A semântica dos campos, isto é, o significado da informação nos campos.<br />
#Regras para determinar quando e como um processo envia mensagens e responde a mensagens.<br />
<br />
Neste experimento será proposto a construção de um protocolo de aplicação para prestar serviços na área de operações matemáticas. Na implementação deste serviço todos grupos serão clientes, solicitando respostas a desafios matemáticos, e servidores, enviando respostas as solicitações, de serviço. Deve ser observado que para não se tornar complexo será usado o transporte de informação através do ICMP (usando o ping). O ping possui uma facilidade para transportar bytes de dados (flag -p). A observação destes dados será feita usando o wireshark (captura de pacotes). Pode-se dizer que o programa ping juntamente com o wireshark e a própria interpretação de pacotes pelo grupo constituem a camada de aplicação.<br />
A camada de transporte foi de certa forma subsituída pelo ICMP que na prática é posicionado na camada de rede (por ser um protocolo auxiliar no funcionamento da camada IP).<br />
<br />
[[Arquivo:AppRCO.png | 500px | Estrutura Applicação'']]<br />
<br />
<br />
*Definição do protocolo a ser criado<br />
#Vamos criar uma calculadora em rede através de um protocolo bem simples, utilizando como ferramenta de comunicação o ping.<br />
##O protocolo tem por objetivo dar suporte a uma calculadora em rede.<br />
##Um aluno cria uma mensagem e envia, sem aviso prévio, a um colega. Este será o cliente da arquitetura cliente-servidor.<br />
##O colega, ao receber a mensagem, deverá interpretá-la, elaborar uma resposta à pergunta e retorná-la ao colega. Este será o servidor da arquitetura cliente-servidor.<br />
##A estrutura básica de um pacote que flui do cliente para o servidor e vice-versa é apresentada na figura abaixo. Essa estrutura deverá ser absolutamente respeitada, caso contrário, o servidor poderá não conseguir interpretá-la e descartará a mensagem. <br />
[[Arquivo:RCOestrutura-pacote.png | 400px | Estrutura do Pacote'']]<br />
<br />
<br />
Para auxiliar na interpretação das mensagens utilize:<br />
#[http://iris.sel.eesc.usp.br/sel433a/ASCII.pdf Tabela ASCII]<br />
#[http://www.rapidtables.com/convert/number/hex-to-ascii.htm Ferramenta para conversão ASCII <==> Hexadecimal]<br />
#[http://xor.pw/ XOR CALCULATOR]<br />
<br />
*Roteiro de Atividades:<br />
#Inicie o Wireshark.<br />
#Inicie a captura de pacotes em sua interface de rede e adicione o filtro '''icmp'''.<br />
#Cada estudante vai construir uma mensagem, respeitando o formato estabelecido, de solicitação (lado cliente). Para construir a mensagem utilize o código ASCII. Essa mensagem deverá explicitar:<br />
##O tipo (requisição ou resposta, ver figura).<br />
##Como endereço de destino (DEST) e fonte (FONTE) utilize o último campo do endereço IP de sua máquina e do colega para qual a mensagem se destina. Por exemplo, a máquina do professor possui o IP 192.168.1.1 e, portanto, seu endereço seria 01.<br />
##Um desafio matemático, por exemplo: 2+2.<br />
#Envie essa mensagem através do comando '''ping''' com a ''flag'' ''pattern''. Um exemplo de mensagem é: <syntaxhighlight lang=bash> ping -p FFFF02001001322B322B03FFFF 192.168.1.10 </syntaxhighlight><br />
##Verifique com Wireshark se a mensagem é para o seu grupo e decifre a mensagem.<br />
#Ao receber uma ou mais mensagens de colegas no wireshark, interprete-a verificando quem é o emitente e realizando a operação aritmética solicitada.<br />
##Monte uma resposta e utilize o comando '''ping''' para responder ao emitente.<br />
##Certifique-se que o colega conseguiu interpretar a mensagem<br />
#Desafio:<br />
#*Em equipes, 2 alunos, proponha um novo padrão de mensagens de um protocolo que dê suporte a um Quiz, perguntas e repostas, sobre o tema geografia. Perguntas do tipo: qual é a capital da Austrália?<br />
#*Implemente o protocolo e teste seus conhecimentos e de seus colegas sobre o tema.<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 4 - Desvendando o HTTP com Wireshark - BÁSICO}}<br />
<br />
===Sobre este Laboratório===<br />
<br />
*Baseado na pequena introdução ao Wireshark apresentada no '''Laboratório 2''' e no '''Laboratório Conceituando Protocolos''' , agora estamos prontos para utilizar o Wireshark para investigar protocolos de aplicação reais em operação. Neste laboratório o protocolo HTTP é explorado nas suas características básicas<br />
<br />
===Fonte base===<br />
<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/Desvendando%20o%20HTTP%20basico.pdf SLIDES DE APOIO: Desvendando o HTTP - Básico - Baseado na Pearson/Kurose]<br />
*[http://www.ebah.com.br/content/ABAAABZ6QAD/wireshark-http Wireshark - HTTP]<br />
*[https://pt.wikipedia.org/wiki/Hypertext_Transfer_Protocol HTTP na Wikipedia]<br />
<br />
===Objetivos===<br />
<br />
*Explorar vários aspectos do protocolo HTTP:<br />
*a interação básica GET/resposta do HTTP,<br />
*formatos de mensagens HTTP;<br />
*diferenças http 1.0 e 1.1 / persistência<br />
<br />
===PARTE 1 - Interação Básica GET/Resposta do HTTP===<br />
<br />
Vamos iniciar a nossa exploração do HTTP baixando um arquivo em HTML simples - bastante pequeno, que não contém objetos incluídos. Faça o seguinte:<br />
#inicie o navegador;<br />
#limpe o cache do mesmo (teclas de atalho para o Firefox: '''Ctrl + Shift + Del''');<br />
#inicie o Wireshark, como descrito no '''Laboratório 1''';<br />
#inicie a captura de pacotes;<br />
#digite o seguinte URL no navegador http://tele.sj.ifsc.edu.br/~odilson/RED29004/RED29004.html;<br />
#pare a captura de pacotes;<br />
#digite “http” (somente as letras, sem as aspas) na caixa de texto de especificação do filtro de exibição, de tal forma que apenas as mensagens HTTP capturadas serão exibidas na janela de listagem de pacotes. (Só estamos interessados em HTTP desta vez, e não desejamos ver todos os pacotes capturados).<br />
#No ''browser'', clique o botão da direita e visualize o código fonte da página adquirida em html.<br />
[[Arquivo:HTTP_Wireshark.png |thumb | 300px| Fig.1 Requisição e Resposta HTTP]]<br />
<br />
O exemplo da figura 1 mostra na janela de listagem de pacotes duas mensagens HTTP capturadas:<br />
#A mensagem GET (do seu navegador para o servidor web www.sj.ifsc.edu.br) e a mensagem de resposta do servidor para o seu navegador.<br />
#A janela de conteúdos de pacotes mostra detalhes da mensagem selecionada (neste caso a mensagem HTTP GET /~odilson/RED29004//RED29004.html, que está em destaque na janela de listagem de pacotes).<br />
#A mensagem HTTP transportada em um segmento TCP, que é carregado em um datagrama IP, que é levado em um quadro Ethernet com 5728 bits no fio. Isso é observado de baixo para cima na janela de detalhes do cabeçalho do pacote selecionado. O Wireshark exibe informações sobre o quadro, IP, TCP e HTTP. Você deve expandir as informações, por exemplo, do HTTP clicando na seta ao lado esquerdo de “Hypertext Transfer Protocol”. Observando as informações das mensagens HTTP GET e de resposta. Você consegue inclusive enxergar a mensagem mostrada no navegador: '''RED29004! Página de teste.'''<br />
<br />
Responda às seguintes perguntas e imprima as mensagens GET e a resposta e indique em que parte da mensagem você encontrou a informação que responde às questões.<br />
#O seu navegador executa HTTP 1.0 ou 1.1?<br />
#Qual a versão de HTTP do servidor?<br />
#Quais idiomas (se algum) o seu navegador indica ao servidor que pode aceitar?<br />
#Qual o endereço IP do seu computador?<br />
#E do servidor tele.sj.ifsc.edu.br?<br />
#Qual o número da porta utilizada no seu computador? Note que esta pergunta se refere a porta do protocolo de transporte TCP, portanto, verifique o header TCP;<br />
#E do servidor tele.sj.ifsc.edu.br?<br />
#Qual o código de status retornado do servidor para o seu navegador?<br />
#Quando o arquivo em HTML que você baixou foi modificado no servidor pela última vez?<br />
#Quantos bytes de conteúdo são baixados pelo seu navegador?<br />
#Encontre a mensagem '''RED29004! Página de teste'''. Onde (em qual campo) encontra-se?<br />
#Qual a diferença entre os endereços (IP) de origem e destino entre a mensagem GET e a de resposta do HTTP?<br />
<br />
===PARTE 2 - Interação Básica GET/Resposta do HTTP usando TELNET e REQUISIÇÃO MANUAL===<br />
<br />
Para esta etapa temos que recordar que o browser é responsável por:<br />
*se conectar ao servidor usando uma porta TCP 80 (default) e <br />
*gerar uma mensagem GET para apanhar um recurso no servidor;<br />
*receber e mostrar a página<br />
Mas será que podemos "emular" o comportamento do browser usando uma outra ferramenta? Por exemplo, o telnet permite abrir uma conexão na porta 80. O que for teclado após a conexão será enviado para o servidor pela conexão estabelecida.<br />
<br />
Aproveitando o comportamento acima, vamos montar na MÃO o pacote de aplicação (que o browser gera) e receber a página do servidor como resposta. Claro que agora não teremos a facilidade do browser em mostrar a página para nós. O que veremos é um código HTML, que é um formato de documentos WEB.<br />
<br />
# Vamos repetir o acesso aos links acima, porém sem usar o navegador. A ideia é que nós façamos o papel de navegador. Isso deve ser feito com os seguintes passos:<br />
#* Coloque o Wireshark para capturar pacotes <br />
#* Abra um terminal de texto no Linux (menu ''Aplicativos->Acessórios->Terminal'').<br />
#* Execute este comando: <syntaxhighlight lang=bash><br />
telnet tele.sj.ifsc.edu.br 80<br />
</syntaxhighlight><br />
#* Após aparecer esta linha: <syntaxhighlight lang=text><br />
Trying 200.135.37.75...<br />
Connected to integrado.sj.ifsc.edu.br.<br />
Escape character is '^]'.<br />
</syntaxhighlight>digite o seguinte:<syntaxhighlight lang=text><br />
GET /~odilson/RED29004//RED29004.html HTTP/1.0<br />
</syntaxhighlight> e em seguida tecle ENTER duas vezes.<br />
#* Identifique a página html que foi enviada como resposta.<br />
#* No WireShark, compare o resultado das execuções desses comandos com o resultado anteriormente visto no navegador. Qual a diferença em ambos os casos?<br />
#* Identifique os componentes do sistema de comunicação de dados nesse acesso direto (quem é cliente, quem é servidor)<br />
#* Refaça um pedido em que o recurso é inexistente no servidor (ex: página html com nome inexistente, GET /~odilson/RED29004//Nada.html HTTP/1.0). Observe a resposta. Qual o código (número) de resposta recebido? <syntaxhighlight lang=bash> telnet tele.sj.ifsc.edu.br 80<br />
GET /~odilson/RED29004//Nada.html HTTP/1.0 </syntaxhighlight><br />
#* Refaça um pedido para o recurso ''default'' e veja o código de resposta:<syntaxhighlight lang=bash> telnet tele.sj.ifsc.edu.br 80<br />
GET / HTTP/1.0</syntaxhighlight><br />
#* Refaça o pedido usando o HTTP/1.1 e tente inferir a diferença da versão 1.0. Note que o GET nesta versão deve ser realizado com o campo Host:<syntaxhighlight lang=bash><br />
telnet tele.sj.ifsc.edu.br 80<br />
GET /~odilson/RED29004//RED29004.html HTTP/1.1<br />
Host: tele.sj.ifsc.edu.br</syntaxhighlight><br />
#'''Nesse teste você deve ter observado que a conexão se manteve aberta'''. Experimente refazer o pedido para um outro recurso na mesma conexão:<syntaxhighlight lang=bash><br />
GET /~odilson/RED29004//RED29004_arq2.html HTTP/1.1<br />
Host: tele.sj.ifsc.edu.br<br />
</syntaxhighlight><br />
Esta característica é a "persistência" do http versão 1.1, que permite reutilizar a mesma conexão para adquirir múltiplos recursos.<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 5 - Desvendando o HTTP com Wireshark - AVANÇADO}}<br />
<br />
===Objetivos===<br />
<br />
*Explorar GET Condicional/Resposta no protocolo HTTP:<br />
*Analisar documentos HTML com Objetos Incluídos<br />
*Comparar as mensagens nos protocolos HTTP X HTTP.<br />
<br />
===Fonte base===<br />
<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/Desvendando%20o%20HTTP%20avancado.pdf SLIDES DE APOIO: Desvendando o HTTP - Avançado - Baseado na Pearson/Kurose]<br />
*[http://www.ebah.com.br/content/ABAAABZ6QAD/wireshark-http Wireshark - HTTP]<br />
*[https://pt.wikipedia.org/wiki/Hypertext_Transfer_Protocol HTTP na Wikipedia]<br />
<br />
===PARTE 1 - A Interação HTTP GET Condicional/Resposta===<br />
<br />
A maioria dos navegadores web tem um cache (seção 2.2.6 do livro) e, desta forma, realizam GET condicional quando baixam um objeto HTTP. Execute os seguintes passos:<br />
#inicie o navegador web;<br />
#limpe o cache do seu navegador('''Ctrl + Shift + Del''');<br />
#inicie o Wireshark;<br />
#digite o URL no navegador http://tele.sj.ifsc.edu.br/~odilson/RED29004//RED29004.html seu navegador deve exibir um arquivo em HTML muito simples com duas linhas;<br />
#pressione o botão “refresh” ('''F5''') no navegador (ou digite o URL novamente);<br />
#pare a captura de pacotes, e digite “http” na caixa de texto de especificação de filtro, para que apenas as mensagens HTTP sejam apresentadas na janela de listagem de pacotes. Se você realizou o procedimento corretamente, você visualizará um total de 6 mensagens no Wireshark: três GETs e três respostas. Obs: Para finas de análise, despreze a solicitação e resposta relativa ao ''fiveicon'', que é relativa ao ''download'' do ícone do IFSC.<br />
<br />
Responda às seguintes questões:<br />
#Inspecione o conteúdo da primeira mensagem HTTP GET do seu navegador para o servidor tele.sj.ifsc.edu.br. Você vê uma linha “If-Modified-Since”?<br />
#Inspecione o conteúdo da primeira resposta do servidor. O servidor retornou explicitamente o conteúdo do arquivo? Como você pode dizer isso?<br />
#Agora inspecione o conteúdo da segunda mensagem HTTP GET do seu navegador para o servidor. Você vê uma linha “If-Modified-Since”? Caso a resposta seja afirmativa, qual informação segue o cabeçalho “If-Modified-Since”?<br />
#Qual é o código de status e a frase retornada do servidor na resposta à segunda mensagem HTTP GET? É diferente do código de retorno da primeira mensagem?<br />
#O servidor retornou explicitamente o conteúdo do arquivo? Explique.<br />
#Qual o tamanho da primeira e segunda mensagem de retorno do servidor?<br />
<br />
===PARTE 2 -Documentos HTML com Objetos Incluídos===<br />
<br />
Agora que vimos como o Wireshark mostra o tráfego capturado para arquivos em HTML grandes, nós podemos observar o que acontece quando o seu browser baixa um arquivo com objetos incluídos, no nosso exemplo, imagens que estão armazenadas em outros servidores. Faça o seguinte:<br />
#inicie o navegador web;<br />
#limpe o cache do seu navegador;<br />
#inicie o Wireshark;<br />
#digite o URL no navegador http://tele.sj.ifsc.edu.br/~odilson/RED29004/RED29004_arq3.html seu navegador deve exibir um arquivo pequeno em HTML com duas imagens incluídas. Estas duas imagens estão referenciadas no arquivo em HTML. Isto é, as imagens não estão no arquivo em HTML, ao invés disso, há um URL para cada imagem no arquivo em HTML. Como discutido no livro, seu navegador terá que baixar estas imagens dos locais correspondentes. As imagens estão em docente.ifsc.edu.br;<br />
#Verifique o código fonte da página, clicando com o botão direito sobre ela. Observe os links dentro do código html.<br />
#digite o URL no navegador http://tele.sj.ifsc.edu.br/~odilson/RED29004/RED29004_arq4.html seu navegador deve exibir um arquivo pequeno em HTML com cinco imagens incluídas. Estas cinco imagens,diferentemente do caso anterior, estão depositadas no próprio sítio do professor;<br />
#Verifique o código fonte da página, clicando com o botão direito sobre ela. Observe os links dentro do código html.<br />
#pare a captura de pacotes, e digite “http” na caixa de texto de especificação de filtro, para que apenas as mensagens HTTP seja exibidas.<br />
<br />
Responda às seguintes questões:<br />
#Quantas mensagens HTTP GET foram enviadas pelo seu navegador em cada acesso?<br />
#Para quais endereços na Internet estas mensagens foram enviadas em cada acesso?<br />
#Você consegue dizer se o seu navegador baixou imagens com ou sem paralelismo? Explique e diferencie o comportamento em cada um dos casos.<br />
<br />
===PARTE 3 -Segurança com HTTPS===<br />
Para finalizar, vamos capturar sequências de mensagens HTTPS, somente a título de comparação. Execute os seguintes procedimentos:<br />
#inicie o navegador web;<br />
#limpe o cache do seu navegador;<br />
#inicie o Wireshark;<br />
#digite o seguinte URL no navegador https://www.ssllabs.com/ssltest/;<br />
#pare a captura de pacotes e digite "ssl" na caixa de texto de especificação de filtro, para que apenas as mensagens criptografadas sejam exibidas.<br />
<br />
Responda:<br />
#Compare a sequência de troca de mensagens (GET e resposta) entre o HTTP (das seções anteriores) com o ssl, existe alguma similaridade?<br />
#Que tipos de campos são mais presentes nesse tipo de mensagens?<br />
#Você consegue identificar o conteúdo de alguma nas mensagens ssl, como no caso das mensagens http?<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 6 - Servidor Apache e Construção de Página HTML}}<br />
<br />
===Objetivos===<br />
*Introdução a ferramenta de simulação de redes Netkit.<br />
*Configurando o servidor Apache para disponibilizar páginas HTML.<br />
*Construindo e disponibilizando páginas HTML.<br />
*Noções de ''shell script'' para automatizar tarefas.<br />
<br />
===Fonte base===<br />
<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/ServidorApache.pdf SLIDES DE APOIO: Introdução à Programação “para Web”]. Baseado no resumo destes material Introdução à Programação para Web de Carlos Bazilio: [http://www.ic.uff.br/~bazilio/cursos/java/slides/Introducao.pptm]<br />
*[https://www.apache.org/ Apache]<br />
<br />
===Máquinas Virtuais UML / Netkit2===<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/SlidesApoioMaquinaVirtual.pdf Conceitos de máquinas virtuais]<br />
<br />
Para esta aula de laboratório estaremos usando o [https://wiki.sj.ifsc.edu.br/index.php/Netkit2 netkit2] do Prof. Sobral, uma extensão do [http://wiki.netkit.org/index.php/Main_Page netkit] da '''Universidade Roma Tre'''.<br />
Trata-se de uma ferramenta que que permite criar máquinas virtuais leves sobre o linux. Estas máquinas podem ser ligadas em rede. Neste laboratório conectaremos uma máquina virtual na REDE do Laboratório através de uma bridge.<br />
<br />
===O Servidor Apache===<br />
<br />
Neste laboratório vamos criar uma página html e hospedá-la em um máquina virtual com o [http://www.apache.org/ Web Server Apache]. Para maiores informações consulte [http://softwarelivre.org/php/servidor-web-apache Visão Geral do Apache ].<br />
<br />
===PARTE 1 - Colocando o servidor Apache no ar no Netkit===<br />
<br />
#Inicialmente vamos colocar um Máquina Virtual (VM) Netkit conectada com uma bridge para que possamos acessá-la de qualquer lugar do laboratório. Utilize o editor de texto Gedit e salve as definições do laboratório abaixo em um arquivo '''/home/aluno/lab.conf''':<syntaxhighlight lang=bash><br />
pc1[type]=generic<br />
pc1[eth0]=uplink:bridge=eth0:ip=dhcp<br />
</syntaxhighlight><br />
#Rode o '''netKit''' em seu computador. Em um terminal digite: <syntaxhighlight lang=bash> mkdir .netkit<br />
netkit2 & </syntaxhighlight><br />
#Caso surja uma mensagem recomendando atualizar o Netkit, faça-o através do menu: '''<General> <Update>'''. Aguarde a finalização do processo.<br />
#No menu '''<File> <Load and Run>''', procure o arquivo '''/home/aluno/lab.conf''' e clique em OK. Abrirá um terminal da máquina virtual (VM) que estará rodando servidor Apache que vamos utilizar, onde é possível fazer a configuração do mesmo.<br />
#<span style="color: red;">Dica: não tente alterar o tamanho da janela do Netkit. Se isso for feito não consegue-se mais voltar ao tamnho original.<br />
#Ao clicar no menu '''<File> <Graph>''', pode-se ter uma visão da rede a ser simulada e conferir se é equivalente ao diagrama proposto.<br />
#Identifique o IP da VM usando o comando '''ifconfig'''. Esse será, doravante, seu '''''endereço_IP'''''.<br />
#*<span style="color: blue;">Dica: para copiar textos para o Netkit, copie normalmente o texto, por exemplo, da Wiki, com o < Ctrl > + < C > e cole clicando sobre a rodinha (''scroll'') do mouse.<br />
#Teste a conectividade entre a máquina virtual e a máquina hospedeira com o comando ping. Na VM execute: <syntaxhighlight lang=bash><br />
ping 192.168.1.1 </syntaxhighlight><br />
#Coloque o servidor apache em execução. Este servidor escutará na porta 80 por requisições de páginas (objetos HTTP). Execute no terminal da VM: <syntaxhighlight lang=bash> /etc/init.d/apache2 start </syntaxhighlight><br />
#Inicie o Wireshark em sua máquina.<br />
#Abra o Firefox na sua máquina (hospedeira) e coloque como endereço: <syntaxhighlight lang=bash> http://endereco_IP </syntaxhighlight><br />
#Pronto. Você está acessando a página ''default'' do Apache da VM.<br />
#Você pode verificar o arquivo de definição da página ''default'' na VM com o comando: <syntaxhighlight lang=bash> cat /var/www/index.html </syntaxhighlight><br />
#Com sua experiência com o Wireshark filtre as mensagens trocadas entre o servidor da VM e seu navegador. <br />
##Localize os comandos GET e a resposta do servidor. <br />
##Observe quais são os IPs de destino e fonte da requisição e resposta.<br />
##Observe as portas de destino e fonte da requisição e resposta.<br />
##Qual versão do HTTP está sendo usada?<br />
#Escolha um servidor web de um colega, acesse a página HTML desse colega e repita as capturas de pacotes.<br />
<br />
===PARTE 2 - Colocando no ar a sua página HTML===<br />
<br />
Nesta parte do experimento vamos editar um código HTML e disponibilizá-la em um diretório especial por você criado. Observe que vamos editar a página no hospedeiro e salvá-la em um diretório compartilhado entre a máquina hospedeira e a MV.<br />
<br />
#Usando o Gedit, salve o código html abaixo como no arquivo '''/home/aluno/lab/shared/index.html''' da sua máquina hospedeira.<syntaxhighlight lang=bash><br />
<!DOCTYPE html><br />
<html><br />
<body><br />
<br />
<h1>Alo Mundo</h1><br />
<br />
<p>Estamos sendo visitados por extraterrestres...</p><br />
<br />
</body><br />
</syntaxhighlight><br />
#Crie a adapte para o seu caso um [https://pt.wikipedia.org/wiki/Shell_script Shell Script] com o conteúdo exemplo abaixo. Com o Gedit crie um arquivo e salve como '''/home/aluno/lab/shared/config_apache.sh''' <syntaxhighlight lang=bash><br />
#!/bin/bash<br />
mkdir /var/www/ET<br />
chmod 755 /var/www/ET<br />
cp /hostlab/shared/index.html /var/www/ET<br />
chmod 555 /var/www/ET/index.html<br />
service apache2 restart </syntaxhighlight><br />
#Em sua máquina hospedeira transforme o script em executável. Num terminal digite: <syntaxhighlight lang=bash> chmod +x /home/aluno/lab/shared/config_apache.sh </syntaxhighlight><br />
#O shell script será executado na máquina virtual do apache, portanto, abra o terminal da mesma no Netkit e digite: <syntaxhighlight lang=bash><br />
/hostlab/shared/config_apache.sh <br />
</syntaxhighlight><br />
#Agora você deve ser capaz de acessar a página recém criada através do seu navegador no hospedeiro usando o endereço: <syntaxhighlight lang=bash> http://endereco_IP/ET </syntaxhighlight><br />
#Personalize a página HTML acrescentando novas frases de sua preferência. Para isso repita os passos: 1, 3 e 4.<br />
#Avise o professor para que ele mostre no telão sua página através do Epoptes.<br />
#Acesse as páginas HTML personalizadas dos demais colegas.<br />
#Se desejar, crie outras páginas, para isto basta executar os passos 1 a 5, só que criando diretórios com nomes distintos dos demais já existentes. Cada novo diretório poderá conter uma nova página.<br />
#Também se desejar incremente suas novas páginas com figuras (objetos). Lembre-se de copiar esse objetos para o diretório pertinente na VM.<br />
#*Com o navegador acesse as novas páginas criadas.<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 7 - Serviço de Nomes (DNS)}}<br />
<br />
===Objetivos===<br />
O Domain Name System (DNS) traduz nomes de hosts em endereços Internet Protocol (IP), preenchendo uma lacuna crítica na infraestrutura da Internet. Neste laboratório, observaremos mais de perto:<br />
#O lado cliente do DNS.<br />
#Uma pequena análise do protocolo e<br />
#Consultas AAAA<br />
<br />
Lembre-se de que o papel do cliente no DNS é relativamente simples - um cliente envia uma consulta ao seu DNS, e obtém uma resposta. Muito pode acontecer “por baixo dos panos”, de forma invisível aos clientes DNS, enquanto os servidores DNS, organizados hierarquicamente, comunicam-se entre si para, ou recursivamente ou iterativamente, resolver uma consulta DNS de um cliente. Do ponto de vista do cliente DNS, contudo, o protocolo é bastante simples - uma consulta é feita ao seu servidor DNS e uma resposta é recebida deste servidor.<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/Servico%20de%20Nomes%20DNS.pdf Serviço de Nomes - DNS]<br />
<br />
===PARTE 1: Consulta simples ao DNS gerada a partir de um comando ping===<br />
<br />
O comando ping pode ser usado tanto com um endereço IP como com um nome de host. Em última instância, ele sempre enviará pacotes para um endereço IP. No caso de ser usado o endereço de host, ele tentará resolver (mapear) este nome em um endereço IP usando um servidor DNS (local). Ele gera uma pergunta para o servidor (ou para os servidores, caso exista mais de um configurado). Esta experiência mostra como verificar os servidores instalados e, através de uma captura de pacote mostra a estrutura dos cabeçalhos DNS.<br />
<br />
#Inicialmente consulte e anote quem são os servidores DNS instados na sua máquina. É para estes servidores que serão conduzidas as perguntas DNS. Use a ferramenta nm-tool ou acesso ao arquivo de configuração do sistema:<syntaxhighlight lang=bash><br />
cat /etc/resolv.conf</syntaxhighlight><br />
#Prepare o wireshark para capturar pacotes.<br />
#Execute o ping para um endereço de host conhecido <syntaxhighlight lang=bash><br />
ping www.ifsc.edu.br</syntaxhighlight><br />
#Pare a captura de pacotes no Wireshark e coloque um filtro de display para mostrar apenas mensagens DNS e de ICMP<syntaxhighlight lang=bash><br />
dns || icmp </syntaxhighlight><br />
#Observe os pacotes capturados. Em particular foque no pacote de pergunta que deve ser similar ao mostrado abaixo e deve estar direcionado a um dos servidores DNS. Nos ''flags'' do header do pacote DNS é possível observar que é um QUERY (pergunta) a ser resolvido de forma recursiva. A pergunta propriamente dita está no campo QUERIES, onde é colocado o nome a ser resolvido e o tipo do registro solicitado (tipo A) que indica resolução de nome. <br />
#:<br />
#:[[Arquivo:DNS-Tela1-Wireshark.jpg | 900px| Estrutura de uma pergunta simples DNS]]<br />
#:<br />
#:<br />
#Foque agora um pacote de resposta do servidor para o cliente. Deve ter uma estrutura similar ao mostrado abaixo. Nos flags do header do pacote DNS é possível observar que é uma resposta. A resposta propriamente dita está no campo ANSWERS (ele também repete a pergunta no campo QUERIES). Note que podem haver vários registros (RR) retornados, cada um com um tipo. No exemplo abaixo também é retornada uma lista de servidores autorizados (RR tipo NS). Também é retornado o endereço IP destes servidores através de RRs adicionais do tipo A (inclusive endereços IPv6).<br />
#:<br />
#:<br />
#:[[Arquivo:DNS-Tela2-Wireshark.jpg | 900px| Estrutura de uma resposta simples DNS]]<br />
#Perguntas a serem respondidas, baseado nos pacotes "''Standard query''" e "''Standard query response''":<br />
##Quem são os servidores DNS da sua máquina?<br />
##O ping gerou pergunta para cada um deles?<br />
##Qual o tipo da RR associada a pergunta (''Queries''). O que significa?<br />
##Qual endereço IP retornado para o www.ifsc.edu.br?<br />
##Qual endereço IP usado no ping (ver pacote REQUEST ICMP)?<br />
##Qual protocolo de transporte, camada 4, que foi usado para transportar as mensagens de aplicação DNS?<br />
##Quais os servidores autorizados (''Authoritative nameservers'') foram repassados em resposta a sua consulta?<br />
#Logo após o primeiro ping existe mais uma consulta DNS. Esta pergunta é realizada através de uma mensagem do tipo PTR. O ping está tentando verificar qual é o nome da máquina que realmente está respondendo. É o DNS reverso, nesse tipo de colsulta se fornece um IP e o servidor devolve o nome da máquina.<br />
#Perguntas a serem respondidas:<br />
##Qual o IP que se pretende resolver?<br />
##Qual o nome retornado?<br />
##O nome retornado é www.ifsc.edu.br? Sim ou não? Explique.<br />
<br />
===PARTE 2 - Consultas DNS por meio de ferramentas especializadas===<br />
# Usando o programa [http://manpages.ubuntu.com/manpages/precise/man5/hosts.5.html host], [http://manpages.ubuntu.com/manpages/trusty/en/man1/nslookup.1.html Nslookup] ou [http://manpages.ubuntu.com/manpages/precise/man1/dig.1.html dig], que são executados no terminal, descubra e anote no relatório os endereços IP associados aos seguintes nomes de hosts (máquinas):<br />
#* mail.ifsc.edu.br<br />
#* www.google.com<br />
#* www.gmail.com<br />
# Agora descubra e anote no relatório quem é o servidor DNS responsável por cada um dos domínios dos nomes acima. Para isso consulte o valor do registro NS associado a esses domínios. Por exemplo, com o programa ''host'' ou ''dig'' isso pode ser feito assim: <syntaxhighlight lang=bash><br />
host -t ns ifsc.edu.br<br />
dig -t ns ifsc.edu.br<br />
</syntaxhighlight><br />
# O serviço DNS fornece outras informações além do endereço IP associado a cada nome de domínio e/ou máquina. Por exemplo, como ele pode-se descobrir que ''host'' recebe emails em um determinado domínio. Isso é utilizado pelos MTA (''Mail Transfer Agent'') mundo afora para entregarem emails para seus destinatários (lembre que isso se faz com o protocolo SMTP). Para descobrir essa informação, deve-se consultar o registro MX (''Mail eXchange'') de um domínio. Novamente as ferramentas a ser utilizada nesse caso podem ser ''host'' ou ''dig''. Por exemplo: <syntaxhighlight lang=bash><br />
host -t mx ifsc.edu.br<br />
dig -t mx ifsc.edu.br<br />
</syntaxhighlight>Descubra e anote no relatório quem é o servidor de emails nos seguintes domínios:<br />
#* gmail.com<br />
#* hotmail.com<br />
#* ifsc.edu.br<br />
# Outra informação útil guardada por servidores DNS é a tradução de endereço IP para nome de domínio. Isso é chamado de tradução reversa (ou DNS reverso). Usando os programas de diagnóstico já vistos, isso pode ser feito assim: <syntaxhighlight lang=bash><br />
dig -x 200.135.37.65<br />
</syntaxhighlight> ... o ''dig'' tem um resultado um pouco mais carregado que os outros utilitários (''host'' e ''nslookup''), porém neste caso é mais prático. Veja o resultado da consulta logo após a linha '';; ANSWER SECTION:''. Experimente fazer a resolução reversa para cada um dos IP obtidos nas consultas realizadas no primeiro exercício desta atividade. Pode-se também usar a variante do ''dig'' para respostas curtas: <syntaxhighlight lang=bash><br />
dig -x 200.135.37.65 +short<br />
</syntaxhighlight><br />
#Faça uma consulta iterativa com dig e responda:<syntaxhighlight lang=bash><br />
dig +trace mail.ru. </syntaxhighlight><br />
##Qual foi o RLD (''Root Level Domain'') consultado?<br />
##Qual o TLD (''Top Level Domain'') consultado?<br />
##Qual o SLD (''Second Level Domain'') consultado?<br />
##Como você sabe que foram esses os LDs consultados?<br />
#Consultando um servidor explícito(@)<syntaxhighlight lang=bash><br />
dig @j.root-servers.net. +trace www.sj.ifsc.edu.br. </syntaxhighlight><br />
#AVANÇADO. Execute somente se tiver curiosidade. Como explicado durante a aula e visto no exercício anterior, DNS é um banco de dados distribuído. Isso quer dizer que suas informações estão espalhadas em milhares (ou milhões?) de servidores DNS mundo afora. Cada servidor DNS mantém os dados dos domínios por que é responsável. Será que é possível rastrear todos os servidores DNS que devem ser consultados até chegar ao servidor do domínio procurado? Posto de outro modo, vamos fazer todo o processo de requisição interativa, do exercício anterior, manualmente, ou seja, descobrir quem é o ''Root Level Domain'', o ''Top Level Domain'' e o ''Second Level Domain''. Anote no relatório.<br />
## Descubra quem são os servidores raiz (topo de hierarquia DNS): <syntaxhighlight lang=bash><br />
host -t ns .<br />
dig -t ns .<br />
</syntaxhighlight><br />
## Escolha um dos servidores TLD listados, e use-o para fazer as consultas. Por exemplo: <syntaxhighlight lang=bash><br />
host -v -t a www.sj.ifsc.edu.br. j.root-servers.net.<br />
</syntaxhighlight>... e observe a seção '';; AUTHORITY SECTION:''. Ele contém a listagem de servidores DNS que podem atender sua consulta.<br />
## Continue fazendo as consultas aos servidores DNS listados, até conseguir traduzir o nome requisitado. Por exemplo: <syntaxhighlight lang=bash><br />
host -v -t a www.sj.ifsc.edu.br. b.dns.br </syntaxhighlight><br />
## Quantos servidores DNS foram necessários consultar no total?<br />
<br />
===Algumas consultas AAAA===<br />
Vamos expandir um pouco nossos horizontes e fazer algumas consultas envolvendo IPv6.<br />
#No terminal de sua máquina faça uma consulta e responda: qual o endereço IPv6 dos hosts? Por exemplo: <syntaxhighlight lang=bash><br />
dig AAAA google.com<br />
host -t AAAA google.com </syntaxhighlight><br />
##webmail.ufsc.br<br />
##www.sj.ifsc.edu.br<br />
##www.nyt.com<br />
##ipv6.br<br />
##www.microsoft.com<br />
#Agora vamos fazer a consulta reversa. Qual é o nome de host dos seguintes endereços? Por exemplo: <syntaxhighlight lang=bash><br />
dig -x 2001:12ff::10<br />
dig -x 2001:12ff::10 +short<br />
host 2001:12ff::10 </syntaxhighlight><br />
##2801:84:0:2::10<br />
##2001:12d0:0:126::183:244<br />
##2001:12ff::10<br />
##2804:1454:1004:100::2<br />
<br />
===Analisando o protocolo via Wireshark===<br />
Agora que já está ficando claro como funcionam as consultas DNS, deve-se investigar como se dá a comunicação entre seu computador e seu servidor DNS.<br />
#abra o navegador web e limpe o cache do mesmo;<br />
#abra o Wireshark e escolha a interface e inicie a captura de pacotes;<br />
#inicie a captura de pacotes no Wireshark;<br />
#no terminal digite '''dig +trace canon.jp''' (isso vai provocar a consulta DNS);<br />
#pare a captura de pacotes;<br />
#No Wireshark digite “dns” no filtro (sem as aspas);<br />
Com base nisso identifique o seguinte:<br />
#quantas mensagens são trocadas entre cliente e servidor DNS para cada consulta?<br />
#que protocolo de transporte é usado?<br />
#que portas de origem e destino são utilizadas?<br />
#qual o formato das mensagens DNS? Elas são textuais como as mensagens HTTP?<br />
#qual o tipo de registro DNS acessado em cada consulta?<br />
#que informações estão contidas nas respostas DNS? Há algo além do que foi pedido?<br />
#qual o tamanho das mensagens DNS?<br />
#qual endereço IP a mensagem de consulta DNS é enviada? Foi o mesmo ip obtido na seção anterior: seu servidor DNS?<br />
#examine a mensagem de consulta DNS. Qual o campo “type” desta mensagem?<br />
#a mensagem de consulta contém algum campo “answer”?<br />
#examine a mensagem de resposta DNS. Quantos campos com “answer” existem?<br />
#quais são os benefícios de usar o UDP ao invés do TCP como protocolo de transporte para o DNS?<br />
<br />
===Exemplos de arquivos de um ''Second Level Domain'' fictício===<br />
*Exemplo de arquivos de configuração de um servidor [https://www.isc.org/downloads/bind/ BIND]<br />
/etc/bind/db.redes <syntaxhighlight lang=bash><br />
$TTL 86400<br />
@ IN SOA ns.redes.edu.br. root (<br />
2016090900 ; Serial<br />
604800 ; Refresh<br />
86400 ; Retry<br />
2419200 ; Expire<br />
86400 ) ; Negative Cache TTL<br />
;<br />
@ IN NS ns.redes.edu.br.<br />
@ IN MX 10 mail.redes.edu.br.<br />
$ORIGIN redes.edu.br.<br />
ns A 192.168.1.101<br />
www A 192.168.1.102<br />
www A 192.168.1.103<br />
www A 192.168.1.104<br />
www A 192.168.1.105<br />
www A 192.168.1.106<br />
www A 192.168.1.107<br />
ftp A 192.168.1.108<br />
mail A 192.168.1.109 </syntaxhighlight><br />
<br />
/etc/bind/db.2.168.192 (Zona reversa) <syntaxhighlight lang=bash><br />
$TTL 86400<br />
@ IN SOA ns.redes.edu.br. root (<br />
2016090900 ; Serial<br />
604800 ; Refresh<br />
86400 ; Retry<br />
2419200 ; Expire<br />
86400 ) ; Negative Cache TTL<br />
;<br />
IN NS ns.redes.edu.br.<br />
101 IN PTR ns.redes.edu.br.<br />
102 IN PTR www.redes.edu.br.<br />
108 IN PTR ftp.redes.edu.br.<br />
109 IN PTR mail.redes.edu.br. </syntaxhighlight><br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 8 - Desvendando o UDP - Básico}}<br />
<br />
===Objetivos===<br />
<br />
*Familiarizar-se com o UDP<br />
*Entender a estrutura do pacote UDP<br />
*Entender o conceito de portas<br />
*Entender o conceito de multiplexação<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/UDP%20Basico.pdf Introdução a camada de transporte e UDP básico]<br />
<br />
===Parte 1 - Fluxo único UDP===<br />
<br />
#Combinar equipes com dois computadores para execução do experimento.<br />
#*Uma equipe escutará na porta 5000 e a outra equipe transmitirá uma mensagem nessa porta. Os processos de transmissão e recepção podem ocorrer simultaneamente, em terminais distintos.<br />
#*Cada equipe deve identificar os IPs ('''IP_DEST''') das máquinas de seus pares.<br />
#Cada equipe deve abrir uma Janela de terminal.<br />
#Cada equipe deve preparar o '''Wireshark''', interfaces '''any''', para escuta das portas no protocolo UDP usando um filtro:<syntaxhighlight lang=bash><br />
udp.port==5000</syntaxhighlight><br />
#A equipe da escuta na porta 5000 executa no terminal: <syntaxhighlight lang=bash><br />
netcat -u -l -p 5000 </syntaxhighlight><br />
#A equipe que irá transmitir para a porta 5000 executa no terminal: <syntaxhighlight lang=bash><br />
netcat -u IP_DEST 5000 </syntaxhighlight><br />
#*Em seguida escreve no terminal uma mensagem de até 20 caracteres, ao teclar <Enter> a mensagem será enviada.<br />
#*O wireshark deve ter capturado os pacotes UDP <br />
#Identifique e anote os seguintes dados na captura do wireshark:<br />
#*IP FONTE e DESTINO<br />
#*PORTAS FONTE E DESTINO para ambas comunicações<br />
#*Campo de protocolo no pacote IP<br />
#*Campo de tamanho (anote o tamanho) e ''checksum'' no pacote (datagrama) UDP<br />
#*O campo de dados no pacote UDP<br />
#Troquem os papéis das equipes: quem houvia agora transmite mensagens.<br />
#Cada equipe pode transmitir sequencialmente várias mensagens, devendo identificar múltiplos datagramas UDP.<br />
#PERGUNTAS baseadas na captura:<br />
##Qual o tamanho de cada campo do cabeçalho do pacote UDP?<br />
##Qual o tamanho máximo do número de porta?<br />
##Qual o tamanho máximo da área de dados (payload) do pacote?<br />
##Qual o número identificador de protocolo UDP no pacote IP? <br />
##Em algum momento foi identificado algum procedimento para estabelecimento de conexão? <br />
##Em algum campo do UDP existe numeração de mensagens?<br />
<br />
===Parte 2 - Experimento com UDP - MUX e DEMUX===<br />
<br />
#Conceber um adendo ao experimento anterior para demonstrar a multiplexação e demultiplexação de informação.<br />
#*Lembre-se que a demultiplexação permitirá que diferentes fluxos sejam encaminhados para diferentes processos. Nesse sentido, por exemplo, em uma mesma máquina pode-se abrir dois os mais terminais onde, em cada um deles, pode-se gerar ou aguardar fluxos distintos (diferenciados pelas portas).<br />
#Capture os pacotes com o Wireshark e caracterize quais pacotes pertencem a cada fluxo (porta).<br />
#Mostre o experimento ao professor, que projetará o mesmo no telão.<br />
<br />
'''DESAFIO''' (para casa?): capture e anote byte a byte o conteúdo de um pequeno pacote UDP (e dados IP) e calcule o CHECKSUM do mesmo (pesquise no google como fazer).<br />
{{Collapse bottom}}<br />
{{Collapse top |Laboratório 9 - Desvendando o TCP - Básico}}<br />
<br />
===Objetivos===<br />
<br />
*Verificar o comportamento básico do Protocolo TCP:<br />
**Fase de Estabelecimento de Conexão<br />
**Troca de Dados<br />
**Finalização da Conexão<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/TCP%20Basico.pdf Camada de transporte: TCP básico]<br />
<br />
==Configuração do Laboratório==<br />
O netkit2 deve ser atualizado manualmente com este procedimento:<br />
# Abrir um terminal<br />
# Baixar o programa do ''Netkit2'' com o comando: <syntaxhighlight lang=bash><br />
wget http://tele.sj.ifsc.edu.br/~msobral/netkit2/bin/netkit2<br />
</syntaxhighlight><br />
# Copiá-lo para o diretório do Netkit2 com o comando: <syntaxhighlight lang=bash><br />
cp netkit2 ${NETKIT2_HOME}/bin/<br />
</syntaxhighlight><br />
<br />
O roteiro será executado sobre 3 máquinas virtuais, através do uso do [[Netkit2 | Netkit2]]. Copie o texto abaixo no '''Gedit''' e salve com o nome '''/home/aluno/TCP.conf'''. <br />
<syntaxhighlight lang=text><br />
PC1[type]=generic<br />
PC2[type]=generic<br />
PC3[type]=generic<br />
<br />
<br />
PC1[eth0]=lan0:ip=10.0.0.1/24<br />
PC2[eth0]=lan0:ip=10.0.0.2/24<br />
PC3[eth0]=lan0:ip=10.0.0.3/24<br />
</syntaxhighlight><br />
<br />
===Verificando o estabelecimento, troca de dados e finalização da conexão===<br />
<br />
#Executar a configuração do laboratório no Netkit. Abra o NetKit2 e abra o arquivo de configuração: <syntaxhighlight lang=bash><br />
File > Load and Run </syntaxhighlight><br />
#*Perceba que abrirá uma janela com três abas inferiores, representando três máquina virtuais criadas pelo Netkit, denominadas: PC1, PC2 e PC3. Cada uma dessas abas é o terminal de configuração da respectiva máquina virtual.<br />
#Executar no PC2 um servidor TCP aguardando na porta 5555 na forma: <syntaxhighlight lang=bash> netcat -l 5555 </syntaxhighlight><br />
#*Obs.: para copiar texto para as máquinas do NetKit, pode-se copiar normalmente o texto e em seguida, no terminal do NetKit apropriado, clique na "rodinha" do mouse.<br />
#*Em uma comunicação TCP um processo é servidor (aguarda pedido de conexão) e um processo é o cliente, que gera um pedido de conexão<br />
#Executar no PC3 o tcpdump com foco na porta tcp 5555 e para salvar pacotes em arquivo: <syntaxhighlight lang=bash> tcpdump -i eth0 tcp port 5555 -s 1024 -U -w /hostlab/shared/pc3.cap </syntaxhighlight><br />
#Executar no PC1 um cliente TCP que solicita uma conexão ao servidor: <syntaxhighlight lang=bash> netcat 10.0.0.2 5555 </syntaxhighlight><br />
#Enviar uma pequena mensagem de 5 caracteres, e no final teclar ENTER e depois CTRL+D.<br />
#*O CTRL-D encerra a conexão no netcat<br />
#Vá até o terminal do PC3 e encerre a captura de pacotes do '''tcpdump''' digitando CTRL+C.<br />
#Abrir o arquivo de captura gravado no PC3 com o Wireshark. Temos duas possibilidades para fazer isso, escolha uma das duas:<br />
##Abrir o Wireshark e ir no menu File > Open > Pasta Pessoal > lab > shared > pc3.pcap<br />
##Abrir o "navegador de arquivos" e encontrar procurar o arquivo na pasta aluno/lab/shared/pc3.pcap (/home/aluno/lab/shared/pc3.pcap).<br />
#Todos pacotes TCP, desde o estabelecimento até a desconexão devem estar capturados. Um exemplo dessa captura encontra-se na Figura 1.<br />
[[Arquivo:WiresharkTCP.png |thumb | 600px| Fig.1 -- Protocolo TCP]]<br />
#O processo de conexão do TCP envolve a troca de 3 pacotes e é sempre iniciado pelo cliente. O cliente envia um pacote SYN, o servidor responde com um SYN-ACK e o cliente finalmente responde com ACK. Observe estes pacotes no wireshark.<br />
#*Pratique seu inglês e leia um pouco sobre este processo de estabelecimento de conexão em [https://en.wikipedia.org/wiki/Transmission_Control_Protocol#Connection_establishment Connection Establishment] <br />
#Baseado na captura de pacotes realizada responda:<br />
##Quais foram as portas de origem e destino usadas?<br />
##Quais os tamanhos das janelas informadas, tanto pelo cliente quanto pelo servidor?<br />
##Quais os números de sequência informado pelo Wireshark e o número que consta no campo Data em bytes. Qual é relação entre esses números?<br />
##Em qual mensagem (número) aparece a texto que você digitou?<br />
##Qual o número identificador de protocolo TCP no pacote IP?<br />
#*Um dos objetivos do processo de conexão é sincronizar o número de sequência. Cada lado fica sabendo do número de sequência do outro. O número de sequência não começa com zero.<br />
#*O Wireshark converte a numeração para mostrar a partir do 0 mas o número inicial de sequência é criado randomicamente por cada lado. (ver [https://wiki.wireshark.org/TCP_Relative_Sequence_Numbers])<br />
#Volte ao wireshark e analise o processo de termino da conexão (iniciado pelo cliente neste caso, no momento do CTRL+D).<br />
#*Note que qualquer uma das partes pode realizar esta finalização.<br />
#*Pode ser observado que o cliente envia um pacote TCP com flag FIN.<br />
#*O servidor responde com um FIN-ACK.<br />
#*Finalmente o cliente faz um ACK. <br />
#*Veja se confere com a figura [http://www.tcpipguide.com/free/t_TCPConnectionTermination-2.htm Término de conexão TCP] ou com os [http://docente.ifsc.edu.br/odilson/RCO60803/TCP%20Basico.pdf slides] apresentados no início da aula.<br />
#Gere com o wireshark um diagrama da comunicação, ou diagrama de troca de mensagens, fazendo: Statistics > Flow Graph > OK<br />
#Analise esse diagrama, observando qual pacote contém os dados, ou seja, o texto que você digitou.<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 10 - Desvendando o TCP - Número de Sequência, Controle de Erros e Funcionamento Full-Duplex}}<br />
<br />
===Objetivos===<br />
<br />
*Verificar:<br />
**Controle de Erros: Significado de Número de Sequência, ACK<br />
**Controle de Fluxo: Significado do campo Windows Size; Funcionamento do controle de fluxo;<br />
**Comportamento Full-Duplex<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/TCP%20controle%20de%20erros.pdf TCP - Controle de Erros]<br />
<br />
==Configuração do Laboratório==<br />
O roteiro será executado sobre máquinas virtuais, através do uso do [[Netkit2 | Netkit2]]. Copie o texto abaixo, abra o editor Gedit, cole o texto e salve o arquivo em /home/aluno/TCP.conf.<br />
<syntaxhighlight lang=bash><br />
PC1[type]=generic<br />
PC2[type]=generic<br />
PC3[type]=generic<br />
<br />
<br />
PC1[eth0]=lan0:ip=10.0.0.1/24<br />
PC2[eth0]=lan0:ip=10.0.0.2/24<br />
PC3[eth0]=lan0:ip=10.0.0.3/24<br />
</syntaxhighlight><br />
<br />
===PARTE 1 - Transmissão sem erros: Verificação de Número de Sequência, Reconhecimentos e Controle de Fluxo===<br />
#Executar a configuração do laboratório no Netkit. Abra o NetKit2 e abra o arquivo de configuração: <syntaxhighlight lang=bash><br />
File > Load and Run </syntaxhighlight><br />
#*Perceba que abrirá uma janela com três abas inferiores, representando três máquina virtuais criadas pelo Netkit, denominadas: PC1, PC2 e PC3. Cada uma dessas abas é o terminal de configuração da respectiva máquina virtual.<br />
#Utilize o editor de texto '''gedit''' da máquina real, inclua o texto abaixo, e salve como '''/home/aluno/lab/shared/arq.tx''' <syntaxhighlight lang=bash><br />
ABCDEFGHIJKLMNOPQRSTUVXZW1234 </syntaxhighlight><br />
#Execute o tcpdump no PC3 <syntaxhighlight lang=bash><br />
tcpdump -i eth0 tcp port 5555 -s 1024 -U -w /hostlab/shared/pc3.pcap </syntaxhighlight><br />
#Execute os comandos abaixo no PC2 (copie e cole).<br />
##O primeiro comando limita sua capacidade de recepção em cerca de 20 bytes (tamanho do ''buffer''). Isto permitirá ver a quebra do arquivo de 30 bytes em alguns segmentos TCP.<br />
##O segundo comando abre a porta 5555, através do netcat, e espera a chegada dos dados.<syntaxhighlight lang=bash><br />
sysctl -w net.ipv4.tcp_rmem='20 20 20'<br />
netcat -l 5555 > arq.rx </syntaxhighlight><br />
#Envie o arquivo arq.tx a partir do PC1 com o comando:<syntaxhighlight lang=bash><br />
netcat 10.0.0.2 5555 < /hostlab/shared/arq.tx </syntaxhighlight><br />
#No PC3 faça CTRL+C, para parar a captura de pacotes.<br />
#Abra o arquivo de captura gravado no PC3 (/home/aluno/lab/shared/pc3.pcap) com o Wireshark:<br />
##Abrir o Wireshark e ir no menu File > Open > Pasta Pessoal > lab > shared > pc3.pcap<br />
#Você terá algo parecido com o apresentado na Figura 1.[[Arquivo:WiresharkTCPPerdaDePacotes.png |thumb | 600px| Fig.1 -- Protocolo TCP]]<br />
#Analise como os dados foram transmitidos e reconhecidos.<br />
====Perguntas====<br />
#Qual o número de sequência (normalizado pelo Wireshark) de cada segmento de dados transmitido (de PC1 para PC2) e qual o significado do número de reconhecimento em cada um deles? <br />
#Como foi reconhecido cada segmento enviado? <br />
#*Relate esta análise por segmento usando os timestamps (coluna Time) como referência.<br />
<br />
====Arquivo CAP deste experimento====<br />
<br />
*[https://www.dropbox.com/s/cv82wa1r3jatvgp/tcp_parte1-pc3-sequencia-controle-fluxo.cap Sequencia.cap]<br />
<br />
===PARTE 2 - Transmissão com erros: retransmissões===<br />
<br />
#Repetir todo a parte 1 mas substituir o item 4 por: <syntaxhighlight lang=bash><br />
sysctl -w net.ipv4.tcp_rmem='20 20 20'<br />
tc qdisc add dev eth0 root netem loss 50% <br />
netcat -l 5555 > arq.rx </syntaxhighlight><br />
Perguntas:<br />
#Qual o número de sequência (normalizado pelo Wireshark) de cada segmento de dados transmitido (de PC1 para PC2) e qual o significado do número de reconhecimento em cada um deles?<br />
#Como foi reconhecido cada segmento enviado?<br />
#Houve perda de pacotes? Como você identificou isso?<br />
#Os pacotes perdidos foram retransmitidos? Justifique.<br />
<br />
====arquivo cap deste experimento====<br />
<br />
*[https://www.dropbox.com/s/fb9izlu3ykin4yt/pc3-retransmissoes.cap retransmissoes.cap]<br />
<br />
===PARTE 3 - Testando a capacidade do TCP de enviar dados de forma duplex===<br />
<br />
*Agora vamos deixar de lado o netkit para fazer um pequeno teste de transmissão de arquivos entre dois colegas.<br />
*No experimento, o arquivo de um aluno será transmitido para outro e vice-versa.<br />
<br />
#Em um terminal da máquina real, crie um diretório de trabalho e entre no mesmo <syntaxhighlight lang=bash><br />
mkdir teste<br />
cd teste </syntaxhighlight><br />
#Com o '''gedit''' construa um arquivo de cerca de 2000 bytes. Coloque neste arquivo o seu poema ou letra de canção preferida. Salve o arquivo com nome '''/home/aluno/teste/arq.tx'''.<br />
#Escolha um colega para transferir o arquivo.<br />
##Negocie quem será o servidor e quem será o cliente.<br />
##No processo, o arquivo criado por um aluno será enviado ao colega e vice-versa (tx, rx).<br />
#O servidor deve fazer <syntaxhighlight lang=bash><br />
netcat -l 5555 < arq.tx > arq.rx </syntaxhighlight><br />
#*Ao término da transmissão, o arq.rx conterá os dados recebidos.<br />
#O cliente deve fazer, <span style="color: red;">lembre-se de adequar o IP_SERVIDOR<syntaxhighlight lang=bash><br />
netcat IP_SERVIDOR 5555 < arq.tx > arq.rx </syntaxhighlight><br />
#*<span style="color: black;">Ao término da transmissão, o arq.rx conterá os dados recebidos.<br />
#Abra o arquivo recebido do colega (arq.rx) com o '''gedit''' e confira o conteúdo.<br />
Perguntas:<br />
#Onde pode ser observado a comunicação ''full-duplex''?<br />
#Qual é a relação entre os comandos do cliente e servidor com a comunicação ''full-duplex''?<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 11 - Controle de congestionamento e equidade do TCP}}<br />
<br />
===Objetivos===<br />
*Tem como objetivo gerar um gráfico para facilitar a visualização do '''controle de congestionamento''' e a consequente '''equidade''' do protocolo TCP.<br />
*Utilizar o software [https://iperf.fr/ Iperf] (iperf –h para help) para gerar tráfego entre duas máquinas, '''cliente''' e '''servidor'''.<br />
*Utilizar o software [[netkit2]].<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/TCP%20controle%20de%20congestionbamento%20e%20equidade.pdf TCP - Controle de Congestionamento e Equidade]<br />
*[https://media.pearsoncmg.com/aw/ecs_kurose_compnetwork_7/cw/content/interactiveanimations/tcp-congestion/index.html Animação do controle de congestinamento]<br />
<br />
===Roteiro===<br />
*O roteiro será executado sobre máquinas virtuais, através do uso do [[Netkit2 | Netkit2]].<br />
*Para realização dos ensaios será montada a rede virtual apresentada na Figura 1. <br />
<br />
[[Arquivo:TCP_Rede_Controle_de_Fluxo.png |thumb | 200px| Figura 1 - Rede ara testes]]<br />
#Copie o texto abaixo e crie um arquivo com o '''Gedit''', salve-o como /home/aluno/TCP.conf.<syntaxhighlight lang=bash><br />
# Definição das máquinas<br />
R1[type]=router<br />
PC1[type]=generic<br />
PC2[type]=generic<br />
PC3[type]=generic<br />
<br />
# Definição dos roteadores padrão<br />
PC1[default_gateway]=10.0.0.254<br />
PC2[default_gateway]=10.0.1.254<br />
PC3[default_gateway]=10.0.1.254<br />
<br />
# Definição das interfaces do roteador <br />
R1[eth0]=lan0:ip=10.0.0.254/24:rate=10000<br />
R1[eth1]=lan1:ip=10.0.1.254/24:rate=10000<br />
<br />
# Definição das interfaces dos PCs<br />
PC1[eth0]=lan0:ip=10.0.0.1/24:rate=10000<br />
PC2[eth0]=lan1:ip=10.0.1.2/24:rate=10000<br />
PC3[eth0]=lan1:ip=10.0.1.3/24:rate=10000 </syntaxhighlight><br />
#Execute o NetKit2.<br />
#Carregue o arquivo de configuração: <syntaxhighlight lang=bash><br />
File > Load and Run </syntaxhighlight><br />
#*Perceba que abrirá uma janela com quatro abas inferiores, representando um roteador e três máquina virtuais criadas pelo Netkit, denominadas: R1, PC1, PC2 e PC3. Cada uma dessas abas é o terminal de configuração do respectivo equipamento.<br />
#*Ao clicar no menu '''File - Graph''', pode-se ter uma visão da rede a ser simulada e conferir se é equivalente ao diagrama proposto.<br />
#Execute no PC3 o tcpdump para salvar a troca de dados entre o PC1 e o PC2 num arquivo: <syntaxhighlight lang=bash><br />
tcpdump -i eth0 -w /hostlab/shared/pc3.cap </syntaxhighlight><br />
#*Para copiar comando para os terminais das máquinas virtuais: copie o texto desejado, no Netkit selecione o terminal da máquina desejada e clique sobre a "rodinha" do mouse que o texto será colado.<br />
#No PC1 (servidor) execute: <syntaxhighlight lang=bash><br />
iperf -s -p 2000 & iperf -s -p 2001 & iperf -s -p 2002 & </syntaxhighlight><br />
#No PC2 (cliente) execute (copie a três linhas e cole no terminal adequado e em seguida tecle <Enter>): <syntaxhighlight lang=bash><br />
iperf -c 10.0.0.1 -f m -i 1 -t 90 -p 2000 -l 1300 & \<br />
(sleep 20; iperf -c 10.0.0.1 -f m -i 1 -t 70 -p 2001 -l 1300) & \<br />
(sleep 30; iperf -c 10.0.0.1 -f m -i 1 -t 60 -p 2002 -l 1300) & </syntaxhighlight><br />
#Fique monitorando o PC2 até a tela parar de ser atualizada, aproximadamente 90 s.<br />
#Pare os processos nos três PCs utilizando CTRL-C.<br />
#Abra o Wireshark.<br />
#Abra o arquivo <syntaxhighlight lang=bash><br />
File > Open > /home/aluno/lab/shared/pc3.cap </syntaxhighlight><br />
#No wireshark acesse '''Statistics''' >> '''IO Graph''' e, na tela que abrir, ajuste TODOS os parâmetros para obter um gráfico similar ao apresentado na Figura 2.<br />
#*Perceba que todos os botões '''Graph 1...4''' devem ser clicados, e os filtros aplicados (tcp.port==2000; tcp.port==2001; tcp.port==2002) isso fará com que o Wireshark mostre as respectivas curvas. [[Arquivo:TCP_Wireshark.png |thumb | 400px| Figura 2 - Captura de 3 fluxos de dados]]<br />
#Responda:<br />
##Explique detalhadamente o significado de cada parâmetro dos comandos dos itens 5 e 6 acima, tanto do cliente quanto do servidor.<br />
##Explique os filtros aplicados no gráfico do Wireshark.<br />
##*Quais são os 4 gráficos apresentados?<br />
##*Há uma relação de valor entre as curvas?<br />
##*Qual é esta relação?<br />
##Por que a curva vermelha se sobrepõe a curva preta nos primeiros 20 segundos? Considere o início do tempo onde há início de tráfego!<br />
##Qual é a relação entre a curva preta e as curvas vermelha e verde no intervalo entre 20 e 30 segundos?<br />
##Explique a relação entre as 4 curvas e o comando do cliente (item 5) no intervalo entre 20 e 40 segundos.<br />
##Qual é o mecanismo do TCP que explica a grande oscilação das curvas, principalmente percebida no intervalo entre 20 e 30 segundos?<br />
<br />
=====Incluindo UDP=====<br />
Agora vamos dificultar a vida do TCP incluindo um tráfego UDP. O gráfico gerado deverá apresentar a competição pelo meio de transmissão entre os diversos fluxos de dados.<br />
#Deslique o NetKit2, para limpar todos os processos e ''buffers'': <syntaxhighlight lang=bash><br />
File > Quit </syntaxhighlight><br />
#Copie o texto abaixo e crie um arquivo, salve-o como /home/aluno/TCPxUDP.conf: <syntaxhighlight lang=bash><br />
# Definição das máquinas<br />
R1[type]=router<br />
PC1[type]=generic<br />
PC2[type]=generic<br />
PC3[type]=generic<br />
PC4[type]=generic<br />
<br />
# Definição dos roteadores padrão<br />
PC1[default_gateway]=10.0.0.254<br />
PC2[default_gateway]=10.0.1.254<br />
PC3[default_gateway]=10.0.1.254<br />
PC4[default_gateway]=10.0.1.254<br />
<br />
# Definição das interfaces do roteador <br />
R1[eth0]=lan0:ip=10.0.0.254/24:rate=10000<br />
R1[eth1]=lan1:ip=10.0.1.254/24:rate=10000<br />
<br />
# Definição das interfaces dos PCs<br />
PC1[eth0]=lan0:ip=10.0.0.1/24:rate=10000<br />
PC2[eth0]=lan1:ip=10.0.1.2/24:rate=10000<br />
PC3[eth0]=lan1:ip=10.0.1.3/24:rate=10000<br />
PC4[eth0]=lan1:ip=10.0.1.4/24:rate=10000 </syntaxhighlight><br />
#Execute o NetKit2 e carregue o arquivo de configuração.<br />
#No PC4 execute: <syntaxhighlight lang=bash><br />
tcpdump -i eth0 -w /hostlab/shared/pc4.cap </syntaxhighlight><br />
#No PC1 execute: <syntaxhighlight lang=bash><br />
iperf -s -u -p 2000 & iperf -s -p 2001 & </syntaxhighlight><br />
#A próxima etapa deve ser executada "simultaneamente" nos PC2 e PC3.<br />
##Para isso copie o texto abaixo e cole no terminal do PC2, ainda NÃO tecle <Enter>: <syntaxhighlight lang=bash><br />
iperf -u -c 10.0.0.1 -f m -i 1 -t 60 -p 2000 -l 1300 -b 10000000 </syntaxhighlight><br />
##Copie o texto abaixo e cole no terminal do PC3, ainda NÃO tecle <Enter>: <syntaxhighlight lang=bash><br />
iperf -c 10.0.0.1 -f m -i 1 -t 90 -p 2001 -l 1300 </syntaxhighlight><br />
##Tecle <Enter> no PC3 e PC2, NESSA ORDEM, "simultaneamente".<br />
#Fique monitorando o PC3 a tela parar de ser atualizada, aproximadamente 90 s.<br />
#Pare os processos nos quatro PCs utilizando CTRL-C.<br />
#Rode o Wireshark e abra o arquivo /home/aluno/lab/shared/pc4.cap.<br />
#Baseado na Figura 3, no '''Graph 2''' altere o filtro para '''udp.port==2000''' e no '''Graph 3''' altere o filtro para '''tcp.port==2001'''. Salve o gráfico gerado.<br />
[[Arquivo:TCPxUDP_Wireshark.png |thumb | 400px| Figura 3 - Captura de 2 fluxos de dados TCP e UDP]]<br />
#Responda as mesmas questões do item anterior, '''todas'''.<br />
#Explique o comportamento dos vários fluxos de dados com e sem o UDP.<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 12 - TCP x UDP}}<br />
<br />
===Objetivos===<br />
*O objetivo desses experimentos é evidenciar as diferenças entre os protocolos TCP e UDP.<br />
*Ambos protocolos de transporte podem ser usados por aplicações que precisem se comunicar. Porém cada um deles têm certas propriedades, então a escolha precisa ser realizada baseada no tipo de comunicação a ser feita pela aplicação.<br />
<br />
==== Experimento 1 ====<br />
<span style="color: red;">Antes de qualquer experimento deve-se desabilitar algumas funcionalidades do kernel do LINUX, para que os experimentos reflitam a teoria. Caso sua interface de rede não seja a '''eth0''' adapte o comando, caso reiniciar a máquina repita-o:</span><br />
<syntaxhighlight lang=bash>sudo ethtool --offload eth0 gso off tso off sg off gro off </syntaxhighlight><br />
<br />
O que aconteceria se um arquivo fosse transferido de um computador a outro com ambos protocolos?<br />
<br />
# Abra um terminal e execute o seguinte comando para fazer o download de um arquivo a ser usado no experimento: <syntaxhighlight lang=bash><br />
wget http://tele.sj.ifsc.edu.br/~odilson/RED29004/jogo.exe<br />
</syntaxhighlight><br />
# Observe o tamanho do arquivo transferido ... ele deve ter exatamente 332831416 bytes (cerca de 318 MB). Você pode fazer isso com o comando '''ls -l jogo.exe''', ou executando o gerenciador de arquivos e visualizando as propriedades desse arquivo.<br />
# Escolha um colega para fazer o experimento em que o arquivo será transferido de um computador para o outro. NÃO pode ser na própria máquina. Um será o '''receptor''' e outro o '''transmissor'''.<br />
=====A primeira transferência será feita usando o protocolo TCP da seguinte forma=====<br />
#Execute o WireShark e deixe-o capturando pacotes '''somente''' durante a transferência do arquivo. Como o o comportamento padrão do wireshark é redefinir o número de sequência para sempre iniciar em um e isso pode atrapalhar nossos experimentos, vamos '''desabilitar/desativar''' essa funcionalidade: <syntaxhighlight lang=bash><br />
Edit >> Preferences >> Protocols >> TCP >> Relative sequence numbers </syntaxhighlight><br />
#No computador '''receptor''' execute o '''netcat''' ('''nc''') (utilize '''man nc''' para saber os detalhes das ''flags'' utilizadas) que abrirá uma conexão TCP na porta, por exemplo, 5555 e salvará os dados transferidos em '''arquivo''': <syntaxhighlight lang=bash><br />
nc -vvnl 5555 > arquivoTCP<br />
</syntaxhighlight><br />
#No computador '''transmissor''' execute, após o processo do '''receptor''' estar executando ('''adeque o ip_do_receptor para o devido número IP'''): <syntaxhighlight lang=bash><br />
time nc -vvn ip_do_receptor 5555 < jogo.exe<br />
</syntaxhighlight><br />
#Quando completar a transferência, pare o Wireshark.<br />
#Verifique o tamanho do arquivo recebido. Ele é igual ao arquivo original? E quanto tempo levou para transmiti-lo? No terminal digite: <syntaxhighlight lang=bash><br />
ls -l </syntaxhighlight><br />
#Analisando a captura de pacotes do WireShark responda:<br />
## Quais as portas origem e destino escolhidas pelo cliente e servidor?<br />
## Qual é o número de sequência do primeiro e do último pacote?<br />
## Qual é o número de sequência do primeiro e do último ACK?<br />
## Qual o Tamanho Máximo de Segmento (MSS) escolhidos pelo cliente e servidor na conexão.<br />
## É possível calcular o tamanho do arquivo pela análise dos pacotes? Qual é a maneira mais fácil? Apresente os cálculos ou descreva a maneira de obtenção do valor.<br />
## Qual é o tamanho do último segmento de dados recebido?<br />
## Todos os segmentos trocados entre as máquinas contém dados ou alguns são somente de controle? Qual o percentual aproximado de segmentos de controle?<br />
<br />
=====A segunda transferência será feita usando o protocolo UDP=====<br />
#Execute o WireShark e deixe-o capturando pacotes '''somente''' durante a transferência do arquivo.<br />
#Combine com um colega e estabeleça quem suem será o transmissor e quem será o receptor. No computador '''receptor''' baixe o programa '''receptor''', acrescente a ele permissão de execução e o execute, conforme a sequência de comandos abaixo: <syntaxhighlight lang=bash><br />
wget http://tele.sj.ifsc.edu.br/~odilson/RED29004/receptor<br />
chmod +x receptor<br />
./receptor 5555 > arquivoUDP<br />
</syntaxhighlight><br />
#No computador '''transmissor''' baixe o programa '''transmissor''', acrescente a ele permissão de execução e o execute, conforme a sequência de comandos abaixo: <syntaxhighlight lang=bash><br />
wget http://tele.sj.ifsc.edu.br/~odilson/RED29004/transmissor<br />
chmod +x transmissor </syntaxhighlight><br />
#Inicie a transferência do arquivo ('''adeque o ip_do_receptor para o número IP do colega'''): <syntaxhighlight lang=bash><br />
./transmissor ip_do_receptor 5555 < jogo.exe<br />
</syntaxhighlight><br />
#Quando completar a transferência (vai aparecer a mensagem no '''transmissor''' "Levou XXXXX segundos para transmitir XXXXX bytes).<br />
#No '''receptor''' digite <CTRL + C><br />
#Verifique o tamanho do arquivo recebido.<br />
##Ele é igual ao arquivo original?<br />
##Quanto tempo levou para transmiti-lo?<br />
#Analisando a captura de pacotes do WireShark responda:<br />
## Qual é o número de sequência do primeiro e do último pacote? Existe?<br />
## É possível calcular o tamanho do arquivo pela análise dos pacotes? É mais fácil ou difícil que no caso da transferência via TCP?<br />
## Há segmentos de controle ou somente segmentos de dados?<br />
## Qual é o tamanho do último segmento de dados recebido?<br />
# Compare as transferências feitas com os protocolos TCP e UDP.<br />
## O que eles têm em comum?<br />
## Que diferenças lhe pareceram mais pronunciadas?<br />
## Como isso deve afetar as aplicações que usam esses protocolos?<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 13 - Interligação de duas redes locais via um roteador}}<br />
<br />
===Objetivos===<br />
<br />
*Introdução ao mundo IP<br />
*Verificação das configurações de interfaces<br />
*Verificação de tabelas de roteamento nos hospedeiros e no roteador<br />
*Verificação de roteamento no roteador<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IP%20Basico.pdf Introdução a Camada de Rede]<br />
*[http://tele.sj.ifsc.edu.br/~eraldo/AULAS/2018-2/RCO-INTEGRADO/MACxIP.pdf Endereçamento MAC x Endereçamento IP]<br />
<br />
===Procedimento===<br />
<br />
#Construir uma rede no Netkit com dois PCs e um roteador. Use um arquivo lab.conf da forma: <syntaxhighlight lang=text><br />
r1[type]=router<br />
<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
r1[eth0]=lan0:ip=192.168.200.254/24<br />
r1[eth1]=lan1:ip=192.168.100.254/24<br />
<br />
pc1[eth0]=lan0:ip=192.168.200.1/24<br />
pc1[default_gateway]=192.168.200.254<br />
<br />
pc2[eth0]=lan0:ip=192.168.200.2/24<br />
pc2[default_gateway]=192.168.200.254<br />
<br />
pc3[eth0]=lan1<br />
<br />
pc4[eth0]=lan1:ip=192.168.100.2/24<br />
pc4[default_gateway]=192.168.100.254<br />
</syntaxhighlight><br />
#Chamar o netkit2 (Aplicativos >> Educativo >> Netkit2)<br />
#Forçar a atualização do Netkit2: <syntaxhighlight lang=text> General >> Update </syntaxhighlight><br />
#Carregar o arquivo '''lab.conf''' a partir do Netkit2:<syntaxhighlight lang=bash><br />
File >> Load Only<br />
</syntaxhighlight><br />
#Visualizar a rede a ser implementada:<syntaxhighlight lang=bash><br />
File >> Graph<br />
</syntaxhighlight><br />
#Executar a rede: <syntaxhighlight lang=bash><br />
Network >> Start<br />
</syntaxhighlight><br />
#Copie o diagrama da rede para o papel e, para todas interfaces de rede apresentadas no diagrama, anote, baseados nos comandos dos itens seguintes:<br />
##Endereço IP<br />
##Endereço MAC<br />
##Roteador padrão<br />
#Observar os endereços de hardware (ou MAC) e IP de cada dispositivo na rede. No terminal de cada '''pc''' execute: <syntaxhighlight lang=bash><br />
ifconfig </syntaxhighlight><br />
#Observar e interpretar a tabela de roteamento nos hospedeiros '''pc1''' e '''pc4'''. Identificar os ''default gateways'' em cada '''pc'''.<syntaxhighlight lang=bash><br />
route -n<br />
</syntaxhighlight><br />
#Observar e interpretar a tabela de roteamento no roteador ('''r1''')<syntaxhighlight lang=bash><br />
exit<br />
route -n<br />
</syntaxhighlight><br />
#Observar e "provar" que pacotes indo de '''pc1''' para '''pc4''' são encaminhados ao roteador e, em seguida, entregues ao destino, ou seja, entrega indireta.<br />
#*Use o '''ping''', '''tcpdump''' e seu diagrama de rede como apoio.<br />
#*Lembre-se que você pode verificar o fluxo de dados individualmente em cada interface de rede e, portanto, se certificar que se há ou não pacotes atravessando o roteador:<br />
#**Num primeiro momento em '''r1''':<syntaxhighlight lang=bash><br />
tcpdump -i eth0 -n -e</syntaxhighlight><br />
#**Em seguida, ainda em '''r1''': <syntaxhighlight lang=bash><br />
tcpdump -i eth1 -n -e</syntaxhighlight><br />
#**Ver: [http://www.tcpdump.org/tcpdump_man.html manpage do tcpdump]<br />
#Observar e "provar" que pacotes indo de '''pc1''' para '''pc2''' na '''lan0''' são enviados diretamente para '''pc2''', ou seja, entrega direta.<br />
#*Use o '''ping''' e '''tcpdump''' como apoio, adequando os comandos apresentados no item anterior.<br />
<br />
===Configuração básica de interface de rede===<br />
#Configure a interface de rede no '''pc3'''.<br />
#*O mesmo deverá ser capaz de "pingar" para qualquer outro PC ou ser "pingado".<br />
#*Dica: observe a configuração de rede do '''pc4''' e tente adaptá-la para o '''pc3'''.<br />
#*Dica de ferramentas de configuração: use os comandos '''ifconfig''' e '''route'''. Use o '''man''' ou procure na web como utilizar esses comandos.<br />
#Execute o comando ping do '''pc3''' para o '''pc4'''. Obteve sucesso?<br />
#Execute o comando ping do '''pc3''' para o '''pc1'''. Obteve sucesso?<br />
#Execute o comando ping do '''pc2''' para o '''pc3'''. Obteve sucesso?<br />
<br />
====Referências adicionais====<br />
<br />
* [http://linux-ip.net/html Guia de Administração da Camada IP no Linux<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 14 - Roteamento Estático em Redes }}<br />
<br />
===Objetivo===<br />
<br />
*Proporcionar ao aluno uma visão prática de roteamento IP.<br />
*Princípios de configuração de rotas.<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IP%20Roteamento.pdf Introdução ao Roteamento]<br />
<br />
====PARTE 1 - Rede com 3 roteadores====<br />
<br />
:Laboratório a ser montado no netkit.<br />
<br />
[[Image:LabRoteamento-RCO1-2017-2.png |thumb | 800px| Figura 1 - Rede para roteamento]]<br />
<br />
#Construir a rede apresentada na Figura 1, usando como apoio a configuração do netkit descrita na sequência. As sub-redes (SN) a serem utilizadas na parte 1 e 2 são:<br />
## SN1 : 200.10.1.0/24<br />
## SN2 : 200.10.2.0/24 <br />
## SN3 : 200.10.3.0/24<br />
## SN4 : 200.10.4.0/24<br />
## SN5 : 200.10.5.0/24 <br />
## SN6 : 200.10.6.0/24 <br />
## SN7 : 200.10.7.0/24 <br />
## SN8 : 200.10.8.0/24<br />
#Abaixo o arquivo de configuração para o NetKit. Copie e salve como '''/home/aluno/roteamento.conf'''.<syntaxhighlight lang=text><br />
<br />
H1[type]=generic<br />
H2[type]=generic<br />
<br />
R1[type]=generic<br />
R2[type]=generic<br />
R3[type]=generic<br />
<br />
<br />
H1[eth0]=SN1:ip=200.10.1.1/24<br />
H2[eth0]=SN8:ip=200.10.8.1/24<br />
<br />
R1[eth0]=SN1:ip=200.10.1.254/24<br />
R1[eth1]=SN4:ip=200.10.4.1/24<br />
R1[eth2]=SN2:ip=200.10.2.1/24<br />
<br />
<br />
R2[eth0]=SN8:ip=200.10.8.254/24<br />
R2[eth1]=SN4:ip=200.10.4.2/24<br />
R2[eth2]=SN7:ip=200.10.7.1/24<br />
<br />
R3[eth0]=SN2:ip=200.10.2.2/24<br />
R3[eth1]=SN7:ip=200.10.7.2/24 </syntaxhighlight><br />
#Inicie o Netkit e carregue o arquivo de configuração e execute-o.<br />
#Execute comandos de ping entre os hosts e roteadores.<br />
##O ping entre as interfaces/equipamentos pertencentes a mesma sub-rede funcionam, por quê?<br />
##O ping entre interfaces/equipamentos de sub-redes distintas não funcionam, por quê?<br />
#Usando como apoio os comandos de inserção de rota insira as rotas default em H1 e H2:<br />
##H1: <syntaxhighlight lang=bash> route add default gw 200.10.1.254 </syntaxhighlight><br />
##H2: <syntaxhighlight lang=bash> route add default gw 200.10.8.254 </syntaxhighlight><br />
#Habilitar o roteamento e instalar rotas em cada roteador para que pacotes vindos de H1 para H2 passem por R1, R3 e R2. O retorno deve ser via R2 e R1.<br />
##R1: <syntaxhighlight lang=bash><br />
echo 1 > /proc/sys/net/ipv4/ip_forward<br />
echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth0/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth1/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth2/rp_filter<br />
route add -net 200.10.8.0/24 gw 200.10.2.2 </syntaxhighlight><br />
##R2: <syntaxhighlight lang=bash><br />
echo 1 > /proc/sys/net/ipv4/ip_forward<br />
echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth0/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth1/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth2/rp_filter<br />
route add -net 200.10.1.0/24 gw 200.10.4.1 </syntaxhighlight><br />
##R3: <syntaxhighlight lang=bash><br />
echo 1 > /proc/sys/net/ipv4/ip_forward<br />
echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth0/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth1/rp_filter<br />
route add -net 200.10.8.0/24 gw 200.10.7.1<br />
route add -net 200.10.1.0/24 gw 200.10.2.1 <br />
</syntaxhighlight><br />
#Teste a conectividade IP com o comando ping.<br />
##O ping entre as interfaces/equipamentos pertencentes a mesma sub-rede funcionam, por quê?<br />
##O ping entre interfaces/equipamentos de sub-redes distintas não funcionam, por quê?<br />
#Confirme os caminhos estabelecidos monitorando as interfaces com o tcpdump e/ou traceroute.<br />
<br />
====PARTE 2 - Desafio: Rede com 4 roteadores====<br />
<br />
#Crie um arquivo de configuração que descreva a rede abaixo no '''netkit'''.<br />
##Observe que essa rede tem somente um roteador a mais que a rede apresentada anteriormente.<br />
##As rotas devem ser configuradas de forma que pacotes que trafegam de H1 para H2 passem por R1, R3, R4 e R2.<br />
##O retorno (H2 ==> H1) deve ser por R2, R4 e R1.<br />
##Cada sub-rede SN está em uma rede ethernet separada.<br />
##Chame o professor e mostre que os roteamentos estão sendo realizados corretamente, com o apoio do tcpdump e tracerotue.<br />
<br />
* SN1 : 200.10.1.0/24<br />
* SN2 : 200.10.2.0/24 <br />
* SN3 : 200.10.3.0/24 <br />
* SN4 : 200.10.4.0/24 <br />
* SN5 : 200.10.5.0/24 <br />
* SN6 : 200.10.6.0/24 <br />
* SN7 : 200.10.7.0/24 <br />
* SN8 : 200.10.8.0/24<br />
<br />
[[Image:ExercicioConfEstaticaZebra.png]]<br />
<br />
====PARTE 3 - Criando loop para verificar o campo TTL====<br />
<br />
#Crie um conjunto de rotas que façam que um pacote vindo de H1 para H2 entre em um loop entre R1, R3, R2, R1.<br />
#Envie um pacote único com o ping de H1 para H2.<br />
#Rastreie com o tcpdump o pacote em loop e verifique o momento em que o pacote sai de circulação.<br />
<br />
==Links de Referência==<br />
<br />
* [http://en.wikipedia.org/wiki/Longest_prefix_match Prefixo Mais Longo]<br />
<br />
* [http://jodies.de/ipcalc?host=192.168.20.19&mask1=28&mask2= Calculador IP]<br />
<br />
* [http://linux-ip.net/html Guia de Administração da Camada IP no Linux]<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 15 - Sub-redes}}<br />
<br />
===Objetivos===<br />
*Compreender endereçamento IPv4.<br />
*Compreender o processo de alocação de faixas de IPs.<br />
*Compreender e manipular os números IPs.<br />
*Compreender e manipular as máscaras de rede.<br />
===Fonte Base===<br />
*[https://www.todoespacoonline.com/w/2015/06/calculo-de-sub-redes-ipv4/ Cálculo de Sub-rede IPv4]<br />
<br />
===Exercícios===<br />
#Considere um endereço IP 200.135.233.8/21. Determine:<br />
##O endereço da rede ao qual pertence;<br />
##O endereço de broadcast da rede;<br />
##A faixa de endereçamento que podem ser usados por hospedeiros desta rede.<br />
#Suponha que um administrador de rede tenha recebido o bloco de endereços 200.40.8.0/21 e que deseja dividir este bloco em 8 blocos de endereços iguais, de menor tamanho, para ser alocado a 8 sub-redes administradas por ele.<br />
##Determine o tamanho total do bloco de endereços.<br />
##Determine o tamanho de cada sub-bloco.<br />
##Determine o endereço/máscara de rede de cada sub-rede.<br />
#Quantas estações (''hosts'') uma rede 223.1.10.0/24 suporta? <br />
#Um provedor de acesso com bloco de IPs 200.23.16.0/20 deseja montar 8 sub-redes. Mostre como isso é possível e como ficaria os endereços de cada uma dessas sub-redes.<br />
#Um provedor de acesso a Internet possui o seguinte bloco de endereços IP: 12.17.192.0/18. Os endereços IP de 12.17.192.0 até 12.17.207.255 já estão alocados para clientes deste provedor. Este provedor precisa atender a quatro novos clientes, um deles necessita de rede com pelo menos 1000 endereços de IP válidos e os outros três necessitam de rede com pelo menos 30 IP válidos. Faça uma proposta para alocação de endereços IP para estes clientes. Os endereços reservados para estes novos clientes devem ser alocados a partir da numeração mais baixa disponível. Procure também responder as questões abaixo:<br />
##Qual o total de endereços que dispõe o provedor em questão?<br />
##Quantos endereços IP já estão utilizados?<br />
##Quantos endereços IP este provedor possui livres para alocar aos novos clientes?<br />
##Qual o endereço identificador de cada sub-rede dos novos clientes?<br />
##Qual o a máscara de rede de cada sub-rede dos novos clientes?<br />
##Qual o endereço de broadcast de cada sub-rede dos novos clientes?<br />
##Quantos endereços IP ainda sobrarão ao provedor após atender a estes clientes?<br />
#Um administrador precisa montar uma rede experimental conforme mostrada na Figura 1. Na sub-rede 1 ele precisará instalar cerca 25 ''hosts'', e nas sub-redes 2 e 3 ele precisará instalar cerca de 12 ''hosts''. O administrador dispõe do bloco de endereços IP 192.168.10.0/24 para ser utilizado no endereçamento da rede experimental. Faça uma proposta para alocação de endereços IP para cada sub-rede (rede 1, 2 e 3), incluindo também as sub-redes relativas aos enlaces ponto-a-ponto (rede AB, AC e BC). Responda ainda:<br />
##Qual o endereço identificador de rede de cada sub-rede (1, 2, 3, AB, AC e BC)?<br />
##Qual o a máscara de rede de cada sub-rede (1, 2, 3, AB, AC e BC)?<br />
##Quais os endereços IP que serão atribuídos a cada interface de rede nos enlaces ponto-a-ponto dos roteadores (enlaces relativos as redes AB, AC e BC)? [[Arquivo:CdrEx.png |thumb | 400px| Figura 1 - Rede experimental]]<br />
<br />
*Para conferir seu cálculos utilize, por exemplo, as seguintes ferramentas:<br />
**Terminal Linux: '''ipcalc'''<br />
**Site web: [http://jodies.de/ipcalc ipcalc]<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 16 - Sub-redes e Roteamento Estático em Redes }}<br />
<br />
===Objetivos===<br />
*Compreender endereçamento IPv4.<br />
*Compreender o processo de alocação de faixas de IPs.<br />
*Compreender e manipular os números IPs.<br />
*Compreender e manipular as máscaras de rede.<br />
*Proporcionar ao aluno uma visão prática de roteamento IP.<br />
<br />
===Fonte Básica===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IP_DHCP_NAT.pdf DHCP e NAT]<br />
*[http://www.davidc.net/sites/default/subnets/subnets.html Cálculo de sub-redes]<br />
<br />
===Roteiro===<br />
<br />
#Um administrador precisa montar uma rede experimental conforme mostrada na Figura 1. Na sub-rede 1 ele precisará instalar cerca 50 ''hosts'', e nas sub-redes 2 e 3 ele precisará instalar cerca de 20 ''hosts''. O administrador dispõe do bloco de endereços IP 192.168.10.0/24 para ser utilizado no endereçamento da rede experimental. Faça uma proposta para alocação de endereços IP para cada sub-rede (rede 1, 2 e 3), incluindo também as sub-redes relativas aos enlaces ponto-a-ponto (rede AB, AC e BC). Responda ainda:<br />
##Qual o endereço identificador de rede de cada sub-rede (1, 2, 3, AB, AC e BC)?<br />
##Qual o a máscara de rede de cada sub-rede (1, 2, 3, AB, AC e BC)?<br />
##Quais os endereços IP que serão atribuídos a cada interface de rede nos enlaces ponto-a-ponto dos roteadores (enlaces relativos as redes AB, AC e BC)? [[Arquivo:CdrEx.png |thumb | 400px| Figura 1 - Rede experimental]]<br />
#Baseado no arquivo exemplo abaixo, crie um arquivo de configuração para o NetKit que implemente sua proposta. O arquivo deve contemplar todas as configurações necessárias para o perfeito funcionamento da rede, ou seja, ao carregar o arquivo todos os hosts deverão ser capazes de "pingar" uma ao outro. <br />
##Faça testes de conectividade entre os hosts.<br />
##Demostre para o professor o perfeito funcionamento de sua rede.<br />
*O arquivo de configuração do Netkit abaixo, é a definição para o perfeito funcionamento da simulação da rede apresentada na Figura 2. [[Arquivo:DynamicRoutingTriangle.png |thumb | 400px| Figura 2 - Rede exemplo]]<br />
<syntaxhighlight lang=bash><br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=link0:ip=192.168.0.1/24<br />
pc2[eth0]=link1:ip=192.168.1.1/24<br />
pc3[eth0]=link2:ip=192.168.2.1/24<br />
<br />
# Default gateways definitions<br />
pc1[default_gateway]=192.168.0.254<br />
pc2[default_gateway]=192.168.1.254<br />
pc3[default_gateway]=192.168.2.254<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
r3[type]=gateway<br />
<br />
# Routers' interfaces to local networks<br />
r1[eth0]=link0:ip=192.168.0.254/24<br />
r2[eth0]=link1:ip=192.168.1.254/24<br />
r3[eth0]=link2:ip=192.168.2.254/24<br />
<br />
# Network "backbone" links<br />
r1[eth1]=backbone0:ip=10.0.0.1/30<br />
r1[eth2]=backbone1:ip=10.0.1.1/30<br />
<br />
r2[eth1]=backbone0:ip=10.0.0.2/30<br />
r2[eth2]=backbone2:ip=10.0.2.1/30<br />
<br />
r3[eth1]=backbone1:ip=10.0.1.2/30<br />
r3[eth2]=backbone2:ip=10.0.2.2/30 <br />
<br />
# Routes definition<br />
r1[route]=192.168.2.0/24:gateway=10.0.1.2<br />
r1[route]=192.168.1.0/24:gateway=10.0.0.2<br />
r1[route]=10.0.2.0/30:gateway=10.0.0.2<br />
r2[route]=192.168.0.0/24:gateway=10.0.0.1<br />
r2[route]=192.168.2.0/24:gateway=10.0.2.2<br />
r2[route]=10.0.1.0/30:gateway=10.0.2.2<br />
r3[route]=192.168.0.0/24:gateway=10.0.1.1<br />
r3[route]=192.168.1.0/24:gateway=10.0.2.1<br />
r3[route]=10.0.0.0/30:gateway=10.0.2.1</syntaxhighlight><br />
<br />
===Referencia===<br />
<br />
*[http://www.davidc.net/sites/default/subnets/subnets.html Link Calculador Online de Subnets]<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 17 - Tecnologia de Enlace Ethernet }}<br />
<br />
===Objetivos===<br />
<br />
*Compreender que Ethernet não é Internet e que não é necessário o mundo IP para haver comunicação.<br />
*Diferenciar Hub de Switch<br />
*Compreender o papel do protocolo ARP<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/Camada%20de%20enlace.pdf Camada de Enlace]<br />
<br />
===Animação Pearson/Kurose===<br />
<br />
*[https://media.pearsoncmg.com/aw/ecs_kurose_compnetwork_7/cw/content/interactiveanimations/csma-cd/index.html Animação CSMA/CD]<br />
<br />
===PARTE 1===<br />
<br />
Neste experimento vamos conectar quatro computadores através de um Hub Ethernet. Este dispositivo faz com que todos os computadores se conectem tal como um cabo. Quando um PC envia uma mensagem para outro PC, TODOS os computadores podem ver esta mensagem. Para haver comunicação basta que um computador envie um frame ETHERNET direcionado para o endereço de hardware do computador destino. NÃO é necessário que as interfaces dos computadores estejam configuradas com endereços IP.<br />
<br />
[[Arquivo:RCO-Animacao_HUB.gif | thumb | 400px| Figura 2 - Funcionamento de um Hub]]<br />
<br />
#Contruir um arquivo '''\home\aluno\hub.conf''' com a seguinte configuração <syntaxhighlight lang=bash><br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
pc1[eth0]=lan0<br />
pc2[eth0]=lan0<br />
pc3[eth0]=lan0<br />
pc4[eth0]=lan0<br />
</syntaxhighlight><br />
#Carregar e executar a configuração no Netkit.<br />
#Baixar o arquivo sendraw.py: [http://tele.sj.ifsc.edu.br/~eraldo/AULAS/2018/RCO-INTEGRADO/sendraw.py sendraw.py] para o diretório /home/aluno<br />
#Copiar o arquivo para a Máquina Virtual, no terminal da máquina real digite:<syntaxhighlight lang=bash><br />
cp /home/aluno/sendraw.py /home/aluno/lab/shared </syntaxhighlight><br />
#Identificar o endereço de Hardware (MAC) do PC2. Use o '''ifconfig'''. Note que NÃO existe endereço IPv4 configurado.<br />
#Executar o tcpdump no PC2:<syntaxhighlight lang=bash><br />
tcpdump -i eth0 -e -X -vvv -s 50</syntaxhighlight><br />
#Executar o tcpdump no PC3:<syntaxhighlight lang=bash><br />
tcpdump -i eth0 -e -X -vvv -s 50</syntaxhighlight><br />
#Executar o tcpdump no PC4:<syntaxhighlight lang=bash><br />
tcpdump -i eth0 -e -X -vvv -s 50</syntaxhighlight><br />
#No PC1 enviar uma mensagem para o PC2 usando o endereço de hardware identificado anteriormente, <span style="color: red;">lembre-se se substituir o ENDERECO_MAC pelo MAC adequado:<syntaxhighlight lang=bash><br />
python /hostlab/shared/sendraw.py -d ENDERECO_MAC -i Alo-Mundo</syntaxhighlight> <span style="color: black;"><blockquote style="background: lime; border: 1px solid black; padding: 1em;"> Observe que a mensagem chega a todos os PCs embora foi enviada somente para o PC2. </blockquote><br />
#O que explica o comportamento de broadcast para esse caso?<br />
#Pode existir colisão em um sistema com HUBs simples como este do experimento?<br />
<br />
===PARTE 2 - Explorando o SWITCH e o endereço de Broadcast Ethernet===<br />
<br />
[[Arquivo:RCO-Animacao_SWITCH.gif | thumb | 370px| Figura 2 - Funcionamento de um Switch]]<br />
<br />
#Construir um arquivo '''/home/aluno/switch.conf''' com a seguinte configuração: <syntaxhighlight lang=bash><br />
switchA[type]=switch<br />
<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
switchA[eth0]=port0<br />
switchA[eth1]=port1<br />
switchA[eth2]=port2<br />
switchA[eth3]=port3<br />
<br />
pc1[eth0]=port0<br />
pc2[eth0]=port1<br />
pc3[eth0]=port2<br />
pc4[eth0]=port3<br />
</syntaxhighlight><br />
#Carregar e executar a configuração no Netkit.<br />
#Baixar o arquivo sendraw.py do site: [http://tele.sj.ifsc.edu.br/~eraldo/AULAS/2018/RCO-INTEGRADO/sendraw.py sendraw.py] para o /home/aluno.<br />
#Copiar o arquivo para a Máquina Virtual. No terminal da máquina real digite:<syntaxhighlight lang=bash><br />
cp /home/aluno/sendraw.py /home/aluno/lab/shared/ </syntaxhighlight><br />
#Identificar o endereço de Hardware (MAC) do PC2. Use o ifconfig. Note que NÃO existe endereço IPv4 configurado<br />
#Executar o tcpdump no PC2, PC3 e PC4 com o comando:<syntaxhighlight lang=bash><br />
tcpdump -i eth0 -e -X -vvv -s 50</syntaxhighlight><br />
#No PC1 enviar uma mensagem para o PC2 usando o endereço de hardware identificado anteriormente, <span style="color: red;">Lembre-se se substituir o ENDERECO_MAC pelo MAC adequado:<syntaxhighlight lang=bash><br />
python /hostlab/shared/sendraw.py -d ENDERECO_MAC -i Alo-Mundo </syntaxhighlight> <span style="color: black;"><blockquote style="background: lime; border: 1px solid black; padding: 1em;"> Agora somente o PC2 deve receber pois o ''switch'' entrega o quadro somente para a porta de saída associada ao respectivo MAC destino. </blockquote><blockquote style="background: red; border: 1px solid black; padding: 1em;"> CASO todos tenham recebido, é devido ao fato que por algum motivo o switch ainda não aprendeu quem está conectado nas portas. Neste caso envie pacotes do PC2 para o PC1 e depois retome o experimento do item 4. </blockquote><br />
#No PC1 enviar uma mensagem em broadcast (endereço FF:FF:FF:FF:FF:FF)<syntaxhighlight lang=bash><br />
python /hostlab/shared/sendraw.py -d FF:FF:FF:FF:FF:FF -i Mensagem_Broadcast </syntaxhighlight><br />
<blockquote style="background: lime; border: 1px solid black; padding: 1em;"><br />
Note que neste caso todos os computadores recebem a mensagem em ''broadcast'', mesmo sendo um '''switch'''.<br />
</blockquote><br />
<br />
===PARTE 3 - Explorando o ARP===<br />
<br />
O protocolo ARP serve como apoio para descoberta do endereço MAC dado que se sabe o endereço IP de uma máquina. Quando um PC deseja enviar um pacote IP para uma máquina na rede local, ele necessita descobrir o endereço MAC desta máquina. O protocolo ARP usa o broadcast ETHERNET para perguntar para todas as máquinas na rede QUEM tem o endereço IP em questão. A máquina que possui o endereço responderá informando o seu MAC.<br />
<br />
#Configure endereços IP em todas as máquinas do laboratório anterior. Use exemplo a rede 10.10.10.0/24<br />
#Rode o wireshark no '''PC2''' com os procedimentos:<br />
##Clique sobre a aba do '''PC2'''.<br />
##Menu: Wireshark >> any<br />
#Faça um ping do PC1 no PC2 e observe a sequência de pacotes trocados. Faça um diagrama no tempo mostrando a troca de pacotes até a realização do ECHO REQUEST do ping. Os resultados do Wireshark devem ser similares a: [[Arquivo:RCO-TelaARP.jpg | 700px| Troca de pacotes ARP e PING]]<br />
#Confira o cache do arp no PC1 fazendo:<syntaxhighlight lang=bash><br />
arp -a</syntaxhighlight><br />
#Confira o cache do arp no PC2 fazendo:<syntaxhighlight lang=bash><br />
arp -a</syntaxhighlight><br />
#Faça um ping do PC1 no PC3.<br />
#Confira novamente o cache do arp no PC1 fazendo:<syntaxhighlight lang=bash><br />
arp -a</syntaxhighlight><br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 18 - IPv6: Endereços e ''Neighbor Discovery''}}<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IPv6.pdf IPv6]<br />
<br />
Fontes Extras<br />
*Este roteiro foi baseado no material disponível no Livro - [http://www.paulogurgel.com.br/ Laboratório de IPv6].<br />
*[http://docente.ifsc.edu.br/odilson/RED29004/enderec-v6.pdf Guia didático de endereçamento IPv6] obtido de http://ipv6.br/.<br />
<br />
===Objetivos do laboratório:===<br />
*Um primeiro contato com o protocolo [https://pt.wikipedia.org/wiki/IPv6 IPv6].<br />
*Compreender o funcionando do ''Neighbor Discovery'', o equivalente ao ARP (''Address Resolution Protocol'') do IPv4, que em resumo é uma tabela contendo a relação ente IPs e MACs.<br />
*Aprender configurações básicas de interfaces IPv6 no Linux.<br />
<br />
===Introdução teórica===<br />
Obs.: texto copiado literalmente de: [http://ipv6.br/lab/ Laboratório de IPv6].<br />
<br />
A '''descoberta de vizinhança''' por meio do protocolo ''Neighbor Discovery'' no<br />
IPv6 é um procedimento realizado pelos nós de uma rede para descobrir endereços físicos dos dispositivos vizinhos presentes no mesmo enlace. A função deste protocolo se assemelha à função do ARP e do RARP no IPv4.<br />
*O procedimento é iniciado quando um dispositivo tenta enviar um pacote cujo endereço físico de destino é desconhecido. O nó solicitante envia uma mensagem ''Neighbor Solicitation'' (NS) para todos os nós do enlace pertencentes ao grupo ''multicast solicited-node'' (ff02::1:ffXX:XXXX), de modo que XX:XXXX são os últimos 24 bits do endereço IPv6 em que está interessado.<br />
*É possível notar que, por uma coincidência dos últimos 24 bits, é bastante provável que apenas o nó de destino faça realmente parte deste grupo. Isto é um ''truque'' interessante do IPv6 para diminuir o tráfego deste tipo de pacote na rede.<br />
*Na mensagem NS, o endereço IPv6 a ser resolvido é informado no campo ''Target''. O campo ''Source link-layer address'' informa ao nó de destino o endereço MAC do nó de origem, poupando-o de ter que fazer o mesmo procedimento no sentido inverso.<br />
*O nó de destino, dono do IPv6 requisitado, ao receber este pacote, envia uma mensagem ''Neighbor Advertisement'' (NA) como resposta diretamente ao nó requisitante. O seu endereço físico será informado no campo ''Target link-layer address''.<br />
*A informação de mapeamento entre endereços IP e endereços físicos é armazenada em uma tabela chamada ''neighbor cache''. Nela também fica registrado o ''status'' de cada destino, informando se o mesmo é alcançável ou não.<br />
<br />
===Roteiro de atividades: ETAPA 1===<br />
<br />
A figura abaixo apresenta o diagrama esquemático da rede a ser montada/analisada. Observe que todos os IPv6 ''Global Unicast'' já estão definidos na mesma, são esses IPs que utilizaremos em nosso experimento.<br />
<br />
[[Arquivo:Diagrama_rede_IPv6.jpg]]<br />
<br />
#Crie em seu computador um arquivo com nome '''/home/aluno/IPv6.conf''', com o seguinte conteúdo: <syntaxhighlight lang=bash><br />
#Ligacao das maquinas nos dominios de colisao<br />
#Duas pequenas redes interligadas pelo backbone<br />
<br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=link0:ipv6=2001:bcc:faca:1::101/64<br />
pc2[eth0]=link1:ipv6=2001:bcc:cafe:1::102/64<br />
pc3[eth0]=HUB1:ipv6=2001:bcc:1f0:1::103/64<br />
pc4[eth0]=HUB1<br />
<br />
#Default Gateways definitions<br />
pc1[route]=default6:gateway=2001:bcc:faca:1::1<br />
pc2[route]=default6:gateway=2001:bcc:cafe:1::1<br />
pc3[route]=default6:gateway=2001:bcc:1f0:1::1<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
#Routers interfaces definitions<br />
r1[eth0]=backbone0:ipv6=2001:db8:dead:1::1/64<br />
r1[eth1]=link0:ipv6=2001:bcc:faca:1::1/64<br />
r1[eth2]=link1:ipv6=2001:bcc:cafe:1::1/64<br />
<br />
r2[eth0]=backbone0:ipv6=2001:db8:dead:1::2/64<br />
r2[eth1]=HUB1:ipv6=2001:bcc:1f0:1::1/64<br />
<br />
#Routers definitions<br />
r1[route]=2001:bcc:1f0:1::0/64:gateway=2001:db8:dead:1::2<br />
r2[route]=2001:bcc:faca:1::0/64:gateway=2001:db8:dead:1::1<br />
r2[route]=2001:bcc:cafe:1::0/64:gateway=2001:db8:dead:1::1<br />
</syntaxhighlight><br />
#Tenha certeza que o Netkit2 estja atualizado: General >> Update.<br />
#Rode o NetKit em seu computador. Em um terminal digite: <syntaxhighlight lang=bash><br />
netkit2 & </syntaxhighlight><br />
#No menu '''File''' - '''Load and Run''', procure o arquivo '''/home/aluno/IPv6.conf''' e clique em OK. Abrirá uma janela com 6 abas, onde cada uma delas é um terminal de configuração do respectivo equipamento: '''pc1-4''' ou '''r1-2'''.<br />
#Observe que o '''pc4''' não está com sua interface configurada.<br />
#Ao clicar no menu '''File''' - '''Graph''', pode-se ter uma visão da rede a ser simulada e conferir se é equivalente ao diagrama proposto.<br />
#Faça um '''ping6''' entre o '''pc1''' ao '''pc3''': <syntaxhighlight lang=bash><br />
ping6 -c4 2001:bcc:1f0:1::103 </syntaxhighlight><br />
#Faça um '''ping6''' entre o '''pc1''' e '''pc2'''.<br />
#No '''pc4''' use o seguinte comando para adicionar o endereço IPv6 à interface de rede: <syntaxhighlight lang=bash><br />
ip addr add 2001:bcc:1f0:1::104/64 dev eth0 </syntaxhighlight><br />
#No '''pc4''', acrescente o ''default gateway'' com o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add default via 2001:bcc:1f0:1::1 dev eth0 </syntaxhighlight><br />
#No '''pc1''' use o seguinte comando para verificar como ficou a configuração dos endereços da interface de rede. O resultado é similar ao apresentado pelo comando '''ifconfig''': <syntaxhighlight lang=bash><br />
ip addr show dev eth0 </syntaxhighlight><br />
#Todo o roteamento está pronto, mas caso desejássemos poderíamos acrescentar rotas com comando similares aos já utilizados. Por exemplo, no '''r1''', para adicionar uma rota estática para a rede dos '''pc3''' e '''pc4''' utilizaríamos o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add 2001:bcc:1f0:1::/64 via 2001:db8:dead:1::2 dev eth0 </syntaxhighlight><br />
#Confira as rotas estabelecidas em todos os ''hosts'' com o comando abaixo. <br />
##São coerentes com os dados apresentados no diagrama acima?<syntaxhighlight lang=bash><br />
ip -6 route show </syntaxhighlight><br />
#No '''pc1''' use os seguintes comandos para ver a rota para alguns vizinhos: <syntaxhighlight lang=bash><br />
traceroute6 2001:bcc:1f0:1::103<br />
traceroute6 2001:bcc:1f0:1::104 </syntaxhighlight><br />
#*Anote as rotas.<br />
#Deixe um '''ping6''' entre o '''pc1''' ao '''pc3''' rodando: <syntaxhighlight lang=bash><br />
ping6 2001:bcc:1f0:1::103 </syntaxhighlight><br />
#Rode o wireshark no '''r1''' com os procedimentos:<br />
##Clique sobre a aba do '''r1'''.<br />
##Menu: Wireshark >> any<br />
#Analisando a captura do Wireshark, você verá os pacotes relativos ao ping6 e também pacotes parecidos com: <syntaxhighlight lang=bash> fe80::4cd6:19ff:fedc:2b52 2001:db8:dead:1::1 ICMPv6 86 Neighbor Solicitation for 2001:db8:dead:1::1 from 4e:d6:19:dc:2b:52<br />
2001:db8:dead:1::1 fe80::4cd6:19ff:fedc:2b52 ICMPv6 78 Neighbor Advertisement 2001:db8:dead:1::1 (rtr, sol) </syntaxhighlight><br />
#Explique o processo de descoberta de vizinhança (''Neighbor Discovery'' / ''Neighbor Solicitation'' - '''NS''' e ''Neighbor Advertisement'' - '''NA'''), citando o endereço '''link local''' utilizado.<br />
#*Alguns exemplos de campos visualizáveis para uma mensagem do tipo ''Neighbor Advertisement'':<br />
##Destination (camada Ethernet)<br />
##*O endereço MAC do nó requisitante que foi obtido por meio da mensagem NS enviada anteriormente.<br />
##Source (camada Ethernet)<br />
##*A origem é o endereço MAC da interface do dispositivo que enviou a resposta.<br />
##Type (camada Ethernet)<br />
##*Indica que a mensagem utiliza IPv6.<br />
##Next header (camada IPv6)<br />
##*Indica qual é o próximo cabeçalho. Neste caso, o valor 58 (0x3a) refere-se a uma mensagem ICMPv6.<br />
##Source (camada IPv6)<br />
##*A origem é o endereço IP da interface diretamente ligada ao enlace em que a requisição foi recebida.<br />
##Destination (camada IPv6)<br />
##*Diferentemente da mensagem NS, a mensagem NA possui como destino o endereço IPv6 global do nó requisitante.<br />
##Type (camada ICMPv6)<br />
##*Indica que a mensagem é do tipo 136 (Neighbor Advertisement).<br />
##Flags (camada ICMPv6)<br />
##*Uma mensagem NA possui três flags:<br />
###Indica se quem está enviando é um roteador. Neste caso, o valor marcado é 0, pois não é um roteador.<br />
###Indica se a mensagem é uma resposta a um NS. Neste caso, o valor marcado é 1, pois é uma resposta.<br />
###Indica se a informação carregada na mensagem é uma atualização de endereço de algum nó da rede. Neste caso, o valor marcado é 1, pois está informando o endereço pela primeira vez.<br />
##Target Address (camada ICMPv6)<br />
##*Indica o endereço IP associado às informações das flags. Neste caso, é o próprio endereço da interface do dispositivo em questão.<br />
##ICMPv6 option (camada ICMPv6)<br />
##*Indica as opções do pacote ICMPv6:<br />
###Target link-layer address<br />
##Type<br />
##*Indica o tipo de opção. Neste caso, Target link-layer address.<br />
##Link-layer address<br />
##*Indica o endereço MAC da interface do dispositivo em questão.<br />
#Em todos os ''hosts'' rode o comando <syntaxhighlight lang=bash> ip -6 neighbor show </syntaxhighlight><br />
##Qual é a funcionalidade desse comando?<br />
##Qual é o significado do conteúdo dessa tabela?<br />
##A tabela mostrada em cada um dos casos é compatível com o diagrama da rede montado?<br />
##Por que, por exemplo, na tabela do '''pc3''' não há uma referência explícita ao '''pc1'''?<br />
<br />
===Roteiro de atividades: ETAPA 2 - DESAFIO===<br />
<br />
Acrescentar um terceiro roteador ligado a R1 e R2 (backbone0). Acrescentar uma rede ethernet ligada a este roteador. Configure a rede com endereços IPv6 colocando pelo menos um PC adicional. Acrescente os roteamentos necessários para que este PC seja pingável a partir de PC1.<br />
<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Laboratório 19 - Configurando uma Rede Doméstica}}<br />
<br />
===Objetivos===<br />
*Entender os componentes e princípio de funcionamento de uma rede residencial.<br />
*Configurar um roteador sem fio.<br />
*Testa a rede configurada através do acesso da mesma via Telefone Celular.<br />
<br />
===Fonte Base===<br />
<br />
*[https://esr.rnp.br/publicacoes/sistemas/proinfo?download=d2ddea18f00665ce8623e36bd4e3c7c5 Livro da Escola Superior de Redes (ESR): Formação de suporte técnico PROINFO]<br />
<br />
===Analisando o roteador===<br />
#Roteador ??????. Descrição Geral do aparelho: <br />
##Fonte de alimentação. Cuidar com tensão cc e polaridade.<br />
##Porta WAN (''Wide Area Network'')<br />
##Portas LAN (''Local Area Network'')<br />
##Antena ou antenas <br />
##Botão reset. Normalmente configura LAN em 192.168.0.0/24 ou 192.168.1.0/24<br />
##Parte frontal, LEDs: Power, Status, WAN, WLAN, 1...4.<br />
#Descrição dos modos de uso básicos.<br />
#Ligar o aparelho na tomada.<br />
##LED Power acendeu?<br />
<br />
====Montando uma rede básica====<br />
#Conectar o computador numa das portas LAN do roteador sem fio.<br />
#Conectar a porta WAN num dos pontos de rede do laboratório.<br />
#Pressionar o botão Reset.<br />
#Teste a rede de seu computador, caso não esteja funcionando desconecte e reconecte o cabo de rede entre seu computador e uma porta LAN do roteador sem fio.<br />
#Com o navegador acesse 192.168.0.1. '''Usuário: admin''', '''senha: em branco'''. Caso não consiga acesso, pressione novamente o botão reset.<br />
#Redefina a senha do administrador do roteador para RCO60803.<br />
#Aba Home:<br />
##Clique no menu esquerdo WAN. Discutir a funcionalidade.<br />
##Clique no menu esquerdo LAN. Discutir a funcionalidade.<br />
##Clique no menu esquerdo DHCP. Discutir a funcionalidade.<br />
##Clique no menu esquerdo Wireless. Discutir a funcionalidade.<br />
##Clique no menu esquerdo Wizard. Discutir a funcionalidade.<br />
#Aba Status:<br />
##Device Info. Discutir a funcionalidade.<br />
##Wireless. Discutir a funcionalidade.<br />
#Reconfigure o roteador sem fio para alugar os endereços 192.168.X.20-60, onde X é igual ao último dígito do número IP de sua máquina. Por exemplo, para a máquina 192.168.1.7, X=7.<br />
#Para verificar o funcionamento, num terminal da máquina (real) execute o comando abaixo. Caso tudo esteja funcionando corretamente, sua máquina configurará uma nova interface de rede com o número IP fornecido por seu roteador ou um roteador de um colega. <syntaxhighlight lang=bash> sudo dhclient eth0:0 </syntaxhighlight><br />
#Reconfigure o WiFi de seu roteador:<br />
##Troque o SSID (''Service Set IDentifier'') de seu roteador, colocando seu primeiro nome como nome de rede.<br />
##Configure a segurança para WPA2 (''Wireless Security Setup'').<br />
##Ajuste a senha para RCO60803 (respeite as maiúsculas).<br />
##Salve e reinicie o roteador para as alterações terem validade.<br />
#Teste a configuração, acessando a sua rede sem fio através de seu telefone celular.<br />
<br />
{{Collapse bottom}}<br />
<br />
==Projeto Final==<br />
{{Collapse top |Descrição do Projeto}}<br />
<br />
===Objetivos===<br />
<br />
*Aplicar os conhecimentos adquiridos durante o curso de redes através da confecção de uma rede múltiplos domínios simulando a Internet.<br />
**Dado uma topologia de rede definida a um grupo, calcular as sub-redes de acordo com os requisitos colocados;<br />
**Implementar a proposta de sub-redes no arquivo de configuração do netkit de tal modo a rede ficar plenamente operacional;<br />
**Estabelecer um roteamento global entre todos os domínios das equipes;<br />
**Estabelecer um serviço WEB sobre a rede construída;<br />
**Construir páginas WEB de acordo com os requisitos;<br />
**Estabelecer um serviço de configuração automática de hospedeiros (DHCP);<br />
<!--**Estabelecer um serviço de conexão sem fio sobre cada domínio.--><br />
**Trabalhar o conceito de ''shell script'' para automatizar tarefas.<br />
<br />
A arquitetura da rede é mostrada na Figura abaixo. <br />
<br />
[[Image:RCO3-TrabalhoFinal-2017-2.png|500px]]<br />
<br />
===Especificações do Projeto===<br />
<br />
#Fazer um desenho da '''topologia''' do domínio com todos IPs alocados e apresentar os cálculos das subredes conforme restrições abaixo. <br />
##Construir as tabelas de roteamento para que a rede fique plenamente operacional. Apresentar as '''tabelas de roteamento na página WEB do projeto''';<br />
##Apresentar o desenho da '''topologia na página WEB do projeto'''. Utilize o modelo ao lado. Observe que o modelo está propositalmente incompleto; [[Image:Modelo_de_diagrama_do_projeto.png|300px]]<br />
##Enlaces ponto-a-ponto devem obrigatoriamente ter máscara /30;<br />
##Enlaces multiponto devem obrigatoriamente comportar no mínimo 50 hospedeiros;<br />
##Todas as rotas devem ser colocadas no arquivo '''projeto.conf''' do netkit. Apresentar esse arquivo na '''página WEB do projeto''';<br />
#Na sub-rede onde existe um cliente (notebook) acrescentar um servidor '''[[Netkit2#Usando_DHCP | DHCP]]''' (máquina adicional) com os seguintes requisitos:<br />
##Com uma faixa de aluguel de pelo menos 5 números IP;<br />
##Explicar a configuração do '''DHCP na página WEB do projeto''';<br />
#Estabelecer o serviço '''Apache''' no servidor previsto no domínio com os seguintes requisitos:<br />
##uma página WEB com a descrição integral do projeto;<br />
##uma segunda página WEB com conteúdo de sua preferência com os seguintes requisitos:<br />
###a página deve ser em inglês ou espanhol;<br />
###texto com no mínimo 500 palavras; <br />
###no mínimo uma figura deve aparecer;<br />
###no mínimo um link para uma página WEB de uma outra equipe.<br />
##Todas as páginas devem devem ser mantidas em um diretório de nome ''/home/aluno/lab/shared/WEB''.<br />
##Elaborar um ''shell script'' para automação do serviço WEB. Sítio para treinamento de [http://www.compileonline.com/execute_bash_online.php shell script]. <br />
#O '''roteamento global''' deve permitir conectividade entre todas as equipes. Para evitar possíveis erros advindos de filtros do Netkit2, execute os seguintes comandos em todos os seus roteadores (copie e cole): <syntaxhighlight lang=bash><br />
echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth0/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth1/rp_filter<br />
echo 0 > /proc/sys/net/ipv4/conf/eth2/rp_filter <br />
echo 0 > /proc/sys/net/ipv4/conf/eth3/rp_filter </syntaxhighlight><br />
<br />
* Exemplo de arquivo '''projeto.conf'''.<br />
**No roteiro do '''Laboratório 16''' também é apresentado um arquivo de configuração de uma rede plenamente funcional para o Netkit, utilize-o como exemplo para entendimento das configurações requisitadas.<br />
**O arquivo deverá ser adaptado para a topologia de cada equipe.<br />
<syntaxhighlight lang=bash><br />
H1[type]=generic<br />
H2[type]=generic<br />
<br />
R1[type]=gateway<br />
R2[type]=gateway<br />
R3[type]=gateway<br />
<br />
H1[eth0]=SR2:ip=10.9.2.2/24<br />
H1[default_gateway]=10.9.2.1<br />
<br />
H2[eth0]=SR4:ip=10.9.4.2/24<br />
H2[default_gateway]=10.9.4.1<br />
<br />
R1[eth0]=uplink:bridge=eth0:ip=192.168.1.190/24<br />
R1[eth1]=SR1:ip=10.9.1.1/24<br />
R1[eth2]=SR5:ip=10.9.5.1/24<br />
R1[route]=10.9.2.0/24:gateway=10.9.1.2<br />
R1[route]=10.9.4.0/24:gateway=10.9.5.2<br />
<br />
R2[eth0]=SR1:ip=10.9.1.2/24<br />
R2[eth1]=SR2:ip=10.9.2.1/24<br />
R2[eth2]=SR3:ip=10.9.3.1/24<br />
R2[default_gateway]=10.9.1.1<br />
<br />
R3[eth0]=SR3:ip=10.9.3.2/24<br />
R3[eth1]=SR4:ip=10.9.4.1/24<br />
R3[eth2]=SR5:ip=10.9.5.2/24<br />
R3[default_gateway]=10.9.5.1<br />
</syntaxhighlight><br />
<br />
*Como trabalhar com o shell script<br />
<br />
#O shell script será executado na máquina virtual do apache, e portanto deverá ser copiado para o /home/aluno/shared/lab/config_apache.sh<br />
##Na máquina virtual do apache deve-se tornar o arquivo do script executável e em seguida executá-lo:<syntaxhighlight lang=bash><br />
chmod +x /hostlab/shared/config_apache.sh<br />
/hostlab/shared/config_apache.sh <br />
</syntaxhighlight><br />
<br />
* Exemplo de arquivo ''shell script''. Este arquivo deve ser adaptado para a topologia de cada equipe. <br />
<br />
#Editar o arquivo com gedit com nome ''config_apache.sh''. Qualquer comando executado no terminal pode ser colocado com exata sintaxe no ''shell script'', e vários comandos podem ser colocados em várias linhas.<br />
#Construir o arquivo da forma:<br />
<syntaxhighlight lang=bash><br />
#!/bin/bash<br />
#comentario: copiar um arquivo<br />
cp /home/aluno/teste.txt /var/www<br />
<br />
#renomeando o arquivo copiado teste.txt para index.html<br />
mv /var/www/teste.txt /var/www/index.html<br />
<br />
#iniciando um serviço<br />
/etc/init.d/ssh start<br />
</syntaxhighlight><br />
<br />
*Dar permissão de execução do script no Apache<br />
<br />
Copiar o script para o /home/aluno/lab/shared e apartir do Apache fazer:<br />
Dar direito de execução do script:<br />
<br />
chmod 777 /hostlab/shared/config_apache.sh<br />
<br />
*Executar o script no apache<br />
/hostlab/shared/config_apache.sh<br />
<br />
<br />
* Teste do acesso ao Servidor Apache a partir da linha de comando:<br />
<br />
Note que como todas as máquinas virtuais do netkit são em modo de comando (não tem interface gráfica) então o uso de browsers para teste<br />
do acesso a páginas html fica limitado. Entretanto, para teste rápido é possível usar o comando lynx:<br />
<br />
lynx IP_SERVIDOR_APACHE<br />
<br />
Note que o servidor deve ter conectividade IP (faça ping antes para testar);<br />
<br />
* Acesso pleno as páginas html a partir da Virtualbox<br />
<br />
Um problema que nos deparamos ao usar o netkit para acesso de páginas hospedadas em suas Máquinas Virtuais é o fato de não termos a interface gráfica. Uma interface gráfica é necessária para um browser do tipo Firefox. Uma alternativa é o uso de browser em modo texo do tipo "lynx". Para testes rápidos pode ser interessante mas para visualizarmos em plenitude a página não é a melhor solução.<br />
<br />
Para contornar este problema vamos usar uma máquina VirtualBox que estará conectada na rede do laboratório. Faremos o default gateway desta máquina apontar para o roteador de borda do domínio da equipe garantindo que a mesma conduza todo o tráfego indireto para este roteador. Para garantir que exista rota reversa vamos colocar em cada roteador do domínio uma rota default gateway para o roteador de borda. Vamos elaborar passo a passo estes procedimentos:<br />
<br />
#Iniciar na máquina real uma VirtualBox com Ubuntu e Interface Gráfica;<br />
#Abrir um terminal e verificar a rota para o default gateway usando:<syntaxhighlight lang=bash>route -n </syntaxhighlight><br />
#Adicionar uma rota para a sua rede: <syntaxhighlight lang=bash> sudo route add -net 10.X.0.0/16 gw 192.168.1.XX </syntaxhighlight> onde 192.168.1.XX é o endereço externo do roteador de borda do domínio onde está o servidor APACHE.<br />
#Para garantir a rota reversa vamos colocar rotas ''default'' também nos roteadores dos domínios (roteadores no netkit). Para tanto coloque no projeto.conf esta informação de rota para cada roteador que não está na borda: <syntaxhighlight lang=bash> Rx[route]=default:gateway=Y.Y.Y.Y <br />
ou<br />
Rx[default_gateway]=Y.Y.Y.Y<br />
</syntaxhighlight>onde Y.Y.Y.Y é uma interface do roteador de borda ligado a Rx ou, caso não esteja diretamente ligado a este, deve ser um endereço de roteador vizinho que tenha rota para o roteador de borda.<br />
{{Collapse bottom}}<br />
<br />
==Listas de Exercícios==<br />
{{Collapse top |Lista de exercícios 1 - Introdução}}<br />
<br />
#Qual é a diferença entre um hospedeiro e um sistema final? Cite os tipos de sistemas finais. Um servidor web é um sistema final?<br />
#O que caracteriza um protocolo? Dê um exemplo de um protocolo.<br />
#Por que os padrões são importantes para os protocolos?<br />
#O que é um programa cliente? O que é um programa servidor? Um programa servidor requisita e recebe serviços de um programa cliente? <br />
#Quais são os dois tipos de serviços de transporte que a Internet provê às suas aplicações? Cite algumas características de cada um desses serviços. (pg.38)<br />
#Explique o que é e quais são as vantagens de uma rede de comutação de circuitos em relação a uma rede de comutação de pacotes? <br />
#O que é uma rede de acesso?<br />
#FTTH, HFC e ADSL são usados para acesso residencial. Para cada uma dessas tecnologias de acesso, cite uma faixa de taxas de transmissão e comente se a largura de banda é compartilhada ou dedicada.<br />
#Cite tecnologias de acesso residencial disponíveis na grande Florianópolis. Para cada tipo de acesso, apresente a taxa de ''downstream'', a taxa de ''upstream'' e o preço mensal anunciados.<br />
#Qual é a taxa de transmissão de LANs Ethernet?<br />
#Porque dividimos a arquitetura da Internet (e de redes de comutação de pacotes em geral) em camadas? Por que dizemos que uma camada inferior presta um serviço a camada superior?<br />
#Quais são as cinco camadas da pilha de protocolo da Internet? Quais as principais responsabilidades de cada uma dessas camadas? <br />
#O que significa o processo de encapsulamento e desencapsulamento de pacotes no contexto da rede organizada em camadas?<br />
#O que é uma mensagem de camada de aplicação? Um segmento da camada de transporte? Um datagrama da camada de rede? Um quadro de camada de enlace? Qual a relação entre eles?<br />
#Que camadas da pilha de protocolo da Internet um roteador implementa? Que camadas um comutador de enlace implementa? Que camadas um sistema final implementa?<br />
#Imagine que você queira enviar, com urgência, 40 terabytes de dados de São José a Manaus. Você tem disponível um enlace dedicado de 100 Mbps para a transferência de dados. Você escolheria transferir os dados pelo enlace ou mandar mídias por Sedex 10? Explique.<br />
#Para pensar I: um celular tipo smartphone acessa normalmente quantas redes? Quais tecnologias sao usadas? Elas são de comutação de pacotes ou de circuitos?<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Lista de exercícios 2 - Camada de Aplicação}}<br />
#Relacione cinco aplicações da Internet não proprietárias e os protocolos da camada de aplicação que elas usam. <br />
#Qual é a diferença entre arquitetura de rede e arquitetura de aplicação? <br />
#De que modo um mensageiro instantâneo é um híbrido das arquiteturas cliente-servidor e P2P? <br />
#Para uma sessão de comunicação entre um par de processos, qual processo é o cliente e qual é o servidor? <br />
#Que informação é usada por um processo que está rodando em um hospedeiro para identificar um processo que está rodando em outro hospedeiro? <br />
#Porque o HTTP, FTP, SMTP, POP3 e IMAP rodam sobre TCP e não sobre UDP? <br />
#Por que se diz que o FTP envia informações de controle “fora da banda”? <br />
#Suponha que Aline envie uma mensagem a Eduardo por meio de uma conta de e-mail da web (como o gmail), e que Eduardo acesse seu e-mail por seu servidor utilizando POP3. Descreva como a mensagem vai do hospedeiro Aline até o hospedeiro de Eduardo. Não se esqueça de relacionar a série de protocolos de camada de aplicação usados para movimentar as mensagens entre os hospedeiros.<br />
#Em uma aplicação de compartilhamento de arquivos P2P, você concorda com a afirmação: ”não existe nenhuma noção de lados cliente e servidor de uma sessão de comunicação”? Por que sim ou por que não? <br />
#Relacione alguns agentes de usuário de aplicação de rede que você utiliza no dia-a-dia. <br />
#Considere um site de comércio eletrônico que quer manter um registro de compras para cada um de seus clientes. Descreva como isso pode ser feito com cookies. <br />
#Descreva uma aplicação que requeira “não perda de dados” e seja também altamente sensível ao atraso.<br />
#Quais informações básicas estão em um cabeçalho do pacote IP?<br />
#Um pacote IP pode ser colocado diretamente na rede física? Ele chegará a seu destino?<br />
#Os pacotes ECHO request e ECHO reply são de que protocolo? Eles trafegam dentro de qual pacote?<br />
#Para pensar II: Quando você usa o uma aplicação tipo whatsapp para conversação você está usando rede de comutação de circuitos ou de pacote?<br />
<br />
ADICIONAIS PARTE 2- HTTP<br />
<br />
#Cite pelo menos dois clientes http.<br />
#O que é o servidor Apache?<br />
#O protocolo http deve se executar em todos os roteadores do caminho entre cliente e servidor? Explique.<br />
#Se um hospedeiro colocar um pacote de aplicação HTTP diretamente na rede física ele chegará a seu destino?<br />
#Considere que um cliente acessa uma página HTML de servidor WEB e nesta página existem dois links para dois objetos JPG que residem no mesmo servidor. Quantos comandos GETS no total deveriam ser realizados pelo cliente? Todos eles serão realizados sobre a mesma conexão TCP?<br />
#Em uma página HTML pode existir um link para um objeto que esteja armazenado em outro site? O que o browser deve fazer neste caso? <br />
#No pacote http de resposta de um servidor normalmente existem duas partes. Quais são elas?<br />
#Imagine que uma página html está sendo mostrada para o usuário cliente. Se o usuário pedir para que a página seja atualizada, o browser vai requisitar o objeto novamente? O servidor vai retornar o objeto mesmo que ele não tenha sido alterado?<br />
#O que é um cookie? Considere um site de comércio eletrônico que quer manter um registro de compras para cada um de seus clientes. Descreva como isso pode ser feito com cookies.<br />
#Qual é a diferença entre HTTP persistente com ''pipelining'' e HTTP persistente sem ''pipelining''. Qual dos dois é utilizado pelo HTTP/1.1? <br />
#Descreva como o cache Web pode reduzir o atraso na recepção de um objeto desejado. O cachê Web reduzirá o atraso para todos os objetos requisitados por um usuário ou somente para alguns objetos? Por quê? <br />
#Um servidor Web, quando recebe uma requisição necessita saber para qual porta deve responder na máquina requisitante? Se positivo, esta porta seria sempre a mesma?<br />
#Por que um servidor Web espera na porta TCP número 80 em geral?<br />
#O que é um proxy Web server?<br />
#Um browser pode fazer cache local? Qual a diferença entre cache local e cache em um servidor proxy?<br />
<br />
ADICIONAIS PARTE 3- DNS<br />
#Porque o DNS não é centralizado? <br />
#O que são consultas recursivas e interativas em uma consulta DNS? <br />
#Quais os três tipos de servidores DNS?<br />
#Em um hospedeiro normalmente existe pelo menos um servidor DNS configurado. Que servidor deve estar configurado? Onde ele se localiza normalmente?<br />
#Quando um servidor local não consegue resolver um endereço IP olhando em seu cache, para quem ele deve encaminhar a consulta?<br />
#Um servidor sempre sabe resolver um nome solicitado? Explique.<br />
#É possível que um servidor DNS local seja um servidor com autoridade?<br />
#O que é um nome canônico e um apelido no contexto de DNS?<br />
#O que é e qual o formato de uma RR?<br />
#Explique os seguintes tipos de RR: A, NS, CNAME, MX e PTR.<br />
#Em um comando ping www.ifsc.edu.br quantas transações no mínimo serão realizadas até o último ECHO REPLY?<br />
#Por que um ping normalmente realiza uma consulta PTR?<br />
#Faça um esquema mostrando uma consulta de um cliente a um servidor local mostrando uma consulta interativa entre o servidor raiz e recursiva com um servidor de autoridade. <br />
#Cite o nome de servidor DNS bastante utilizado.<br />
#Quantos servidores raízes temos no mundo? Qual comando permite que possamos "ver" estes servidores em um hospedeiro?<br />
#Foi realizado um comando '''dig www.ifsc.edu.br''' tendo sido retornado: <br />
#:<br />
#: www.ifsc.edu.br. 240 IN A 200.135.190.95<br />
#:<br />
#Em seguida foi realizado um '''dig ifsc.edu.br MX''' com resposta:<br />
#:<br />
#: ;; ANSWER SECTION:<br />
#: ifsc.edu.br. 1327 IN MX 15 zimbra.ifsc.edu.br.<br />
#: <br />
#: ;; AUTHORITY SECTION:<br />
#: ifsc.edu.br. 2082 IN NS ns1.ifsc.edu.br.<br />
#: ifsc.edu.br. 2082 IN NS adns1.pop-sc.rnp.br.<br />
#: ifsc.edu.br. 2082 IN NS ns2.ifsc.edu.br.<br />
#: ifsc.edu.br. 2082 IN NS adns2.pop-sc.rnp.br.<br />
#: <br />
#: ;; ADDITIONAL SECTION:<br />
#: zimbra.ifsc.edu.br. 78 IN A 200.135.190.2<br />
#:<br />
#O que se pode concluir sobre a resolução do nome baseando-se nestas respostas?<br />
<br />
<!--RESPOSTAS <br />
<br />
#Qual é a diferença entre um hospedeiro e um sistema final? Cite os tipos de sistemas finais. Um servidor web é um sistema final?<br />
R.Segundo Kurose[1] os sistemas hospedeiros são sistemas finais, ou seja são considerados sinônimos. São os computadores do nosso dia a dia e que se encontram na periferia da rede executando aplicações que usufruem dos serviços da rede. Estas aplicações executam protocolos específicos para seu funcionamento (protocolos de aplicação).<br />
#O que caracteriza um protocolo? Dê um exemplo de um protocolo.<br />
R.Um conjunto de regras e formatos que viabilizam a comunicação entre duas ou mais entidades comunicantes. No caso de uma rede define as regras para troca de mensagens entre processos da rede (ações a serem realizadas no envio e no recebimento de mensagens), bem como o formato das mensagens trocadas. Em uma rede, as entidades comunicantes se encontram em uma mesma camada.<br />
#Por que os padrões são importantes para os protocolos?<br />
R.Para que exista compatibilidade na comunicação entre processos e equipamentos de rede, além de facilitar a implementação dos mesmos.<br />
#O que é um programa cliente? O que é um programa servidor? Um programa servidor requisita e recebe serviços de um programa cliente?<br />
R.Um programa cliente é uma parte de uma aplicação distribuída que requisita serviços de um outro programa chamado servidor. Tanto cliente como servidor se executam em sistemas finais. O servidor normalmente fica aguardando por uma requisição de algum recurso solicitado por um cliente. Ex: servidor Web e cliente Mozilla ou Chrome. <br />
#Quais são os dois tipos de serviços de transporte que a Internet provê às suas aplicações? Cite algumas características de cada um desses serviços.<br />
Os dois tipos básicos são serviços com conexão e sem conexão. Um serviço com conexão faz com que (em geral) duas entidades de aplicação que pretendem se comunicar, troquem mensagens de controle no sentido de manter informações mútuas de forma a permitir a execução de serviços adicionais do tipo: transferência confiável de dados, controle de fluxo de dados para não sobrecarregar o receptor e controle de congestionamento para evitar o congestionamento de pacotes na rede. Fluxos de pacotes podem ser direcionados a uma determinada conexão. Importante notar que os componentes intermediários da rede desconhecem as conexões. Na Internet, o protocolo que garante o serviço com conexão é o TCP.<br />
Já no serviço sem conexão as entidades comunicantes enviam pacotes (datagramas) sem nenhuma apresentação prévia (troca de mensagens de controle). Cada pacote é enviado de forma independente não tendo garantia de entrega. Na internet o protocolo associado a este comportamento é o UDP. Vale lembrar que por não ter nenhum procedimento associado, a troca de mensagens com UDP tem maior desempenho do que o TCP.<br />
#Quais são as vantagens de uma rede de comutação de circuitos em relação a uma rede de comutação de pacotes? <br />
Em uma rede de comutação de circuitos (ex: rede telefônica clássica) é estabelecido um canal dedicado para a a comunicação entre entidades comunicantes. Normalmente a alocação do canal dedicado é precedido de um processo de sinalização (discar o número, verificar se o destino está disponível, conectar). Uma canal dedicado não pode ser compartilhado por outras comunicações, mesmo quando fica ocioso (ex: duas pessoas na linha telefônica sem conversar). Já em uma rede de pacotes a informação é organizada em pacotes que podem compartilhar canais. Pacotes são comutados para seus destino por equipamentos do tipo roteadores. O roteamento é baseado em informações do cabeçalho do pacote. <br />
#Cite 5 tecnologias de acesso. Classifique cada uma delas nas categorias acesso residencial, acesso corporativo ou acesso móvel. <br />
#FTTH, HFC e ADSL são usados para acesso residencial. Para cada uma dessas tecnologias de acesso, cite uma faixa de taxas de transmissão e comente se a largura de banda é compartilhada ou dedicada.<br />
#Cite tecnologias de acesso residencial disponíveis na grande Florianópolis. Para cada tipo de acesso, apresente a taxa de ''downstream'', a taxa de ''upstream'' e o preço mensal anunciados.<br />
#Qual é a taxa de transmissão de LANs Ethernet?<br />
#Qual é a vantagem de uma rede de comutação de circuitos em relação a uma de comutação de pacotes?<br />
#Porque dividimos a arquitetura da Internet (e de redes de comutação de pacotes em geral) em camadas? Por que dizemos que uma camada inferior presta um serviço a camada superior?<br />
#Quais são as cinco camadas da pilha de protocolo da Internet? Quais as principais responsabilidades de cada uma dessas camadas? <br />
#O que significa o processo de encapsulamento e desencapsulamento de pacotes no contexto da rede organizada em camadas?<br />
#O que é uma mensagem de camada de aplicação? Um segmento da camada de transporte? Um datagrama da camada de rede? Um quadro de camada de enlace? Qual a relação entre eles?<br />
#Que camadas da pilha de protocolo da Internet um roteador implementa? Que camadas um comutador de enlace implementa? Que camadas um sistema final implementa?<br />
#A noção de portas é criada pela camada de transporte na arquitetura TCP/IP. Qual a funcionalidade que as portas permitem implementar?<br />
#Descreva todo o processo de ''download'' de um arquivo utilizando a ferramenta Bittorrent. Considere que o usuário acabou de instalar a mesma.<br />
#Imagine que você queira enviar, com urgência, 40 terabytes de dados de São José a Manaus. Você tem disponível um enlace dedicado de 100 Mbps para a transferência de dados. Você escolheria transferir os dados pelo enlace ou mandar mídias por Sedex 10? Explique.<br />
#Para pensar I: um celular tipo smartphone acessa normalmente quantas redes? Quais tecnologias sao usadas? Elas são de comutação de pacotes ou de circuitos?<br />
--><br />
{{Collapse bottom}}<br />
{{Collapse top |Lista de exercícios 3 - Camada de Transporte}}<br />
#Considere uma conexão TCP entre o hospedeiro A e o hospedeiro B. Suponha que os segmentos TCP que trafegam do hospedeiro A para o hospedeiro B tenham número de porta fonte x e número de porta destino y. Quais são os números de porta fonte e do destino para os segmentos que trafegam do hospedeiro B para o hospedeiro A? <br />
#Descreva porque um desenvolvedor de aplicação pode escolher rodar uma aplicação sobre UDP em vez de sobre TCP. <br />
#O que são os serviços de multiplexação e demultiplexação implementados pela camada de transporte? <br />
#Porque se diz que o UDP é um protocolo não orientado para conexão? <br />
#Qual o papel das informações de porta origem e destino contidas nos segmentos TCP e UDP? <br />
#Porque é dito que o TCP fornece transferência confiável de dados sobre um canal não confiável?<br />
#Cite 3 diferenças entre os serviços oferecidos pelo TCP e UDP.<br />
#Para que serve um ''checksum'' em um segmento TCP ou UDP? Como ele é formado?<br />
#Cite um motivo para um protocolo de transmissão confiável adicionar um número de seqüência em cada pacote transmitido. Justifique o uso dessa informação explicando o problema que ocorreria caso ela não fosse usada.<br />
#Para que serve um ''timeout'' em um protocolo de transmissão confiável?<br />
#O que é uma reconhecimento cumulativo? [[Arquivo:WiresharkUDP.png |thumb | 600px| Figura 1 -- Captura 1 - Wireshark]]<br />
#Baseado na Figura 1, responda as seguintes perguntas:<br />
##Quais os IP fonte e destino?<br />
##Qual o protocolo da camada de transporte utilizado?<br />
##Quais as portas fonte e destino.<br />
##Qual o conteúdo do campo de tamanho (anote o tamanho) e ''checksum'' no pacote (datagrama)?<br />
##Quantos bits possui o ''checksum''? Como você calculou?<br />
##Qual o significado do campo '''Data: 74657374650a'''? Qual é a mensagem contida? Como você chegou a essa conclusão? [[Arquivo:WiresharkTCP.png |thumb | 600px| Figura 2 -- Captura 2 - Wireshark]]<br />
#Baseado na Figura 2, responda as seguintes perguntas:<br />
##Quais os IP fonte e destino?<br />
##Qual o protocolo da camada de transporte utilizado?<br />
##Quais as portas fonte e destino.<br />
##Qual o conteúdo do campo de tamanho (anote o tamanho) no pacote (datagrama)? O tamanho apresentado significa bits ou bytes?<br />
##Qual o significado do campo '''Data: 74657374650a'''? Qual é a mensagem contida? Como você chegou a essa conclusão? [[Arquivo:WiresharkTCPPerdaDePacotes.png |thumb | 600px| Figura 3 -- Captura 3 - Wireshark]]<br />
#Baseado na Figura 3, responda as seguintes perguntas:<br />
##Quais os IP fonte e destino?<br />
##Qual o protocolo da camada de transporte utilizado?<br />
##Quais as portas fonte e destino.<br />
##Qual o número de sequência (normalizado pelo Wireshark) de cada segmento de dados transmitido, e qual o significado do número de reconhecimento em cada um deles?<br />
##Como foi reconhecido cada segmento enviado?<br />
##Qual o significado do conjunto de mensagens de número (No.) 1 à 3? Explique essas 3 mensagens.<br />
##Qual o significado do conjunto de mensagens de número (No.) 17 à 19? Explique essas 3 mensagens.<br />
##Qual o significado do conjunto de mensagens de número (No.) 6, 11 e 16? Explique essas 3 mensagens.<br />
##Qual é o tamanho "médio" de janela de cado um dos ''hosts''?<br />
##Qual a utilizade das mensagens com fundo preto?<br />
{{Collapse bottom}}<br />
<br />
{{Collapse top |Lista de exercícios 4 - Camada de Rede}}<br />
#Quais são as principais características de uma rede de datagramas?<br />
#Roteadores possuem endereços IP? Quantos endereços IP um roteador possui?<br />
#Para que serve o protocolo ICMP? <br />
#Para que serve o campo “Time to Live” (sobrevida) em um datagrama IP? <br />
#Quantos hosts podem ser endereçados com um bloco IP 200.23.16.0/20? Como podemos montar 8 sub-redes a partir deste bloco de endereços IP?<br />
#Um provedor de serviços ISP possui cerca de 2000 clientes cadastrados atualmente. Porém um levantamento realizado recentemente pelo administrador da rede constatou que nunca mais do que 450 clientes estão on-line ao mesmo tempo. Qual o bloco de endereços IP na forma CIDR (a.b.c.d/x) deve ser contratado pelo ISP, considerando o estudo realizado pelo administrador da rede?<br />
#Um administrador precisa montar uma rede experimental conforme mostrada na figura. Na sub-rede 1 ele precisará instalar cerca 25 hosts, e nas sub-redes 2 e 3 ele precisará instalar cerca de 12 hosts. O administrador dispõe do bloco de endereços IP 192.168.10.0/24 para ser utilizado no endereçamento da rede experimental. Faça uma proposta para alocação de endereços IP para cada sub-rede (rede 1, 2 e 3), incluindo também as sub-redes relativas aos enlaces ponto-a-ponto (rede AB, AC e BC). Responda ainda:<br />
##Qual o endereço identificador de rede de cada sub-rede (1, 2 e 3)?<br />
##Qual o a máscara de rede de cada sub-rede (1, 2 e 3)?<br />
##Quais os endereços IP que serão atribuídos a cada interface de rede nos enlaces ponto-a-ponto dos roteadores (enlaces relativos as redes AB, AC e BC)[[Arquivo:CdrEx.png]]<br />
#Suponha que um administrador de rede tenha recebido o bloco de endereços 200.40.8.0/21 e que deseja dividir este bloco em 8 blocos de endereços iguais, de menor tamanho, para ser alocado a 8 sub-redes administradas por ele.<br />
##Determine o tamanho total do bloco de endereços.<br />
##Determine o tamanho de cada sub-bloco.<br />
##Determine o endereço/máscara de rede de cada sub-rede.<br />
#Um provedor de acesso a Internet possui o seguinte bloco de endereços IP: 12.17.192.0/18. Os endereços IP de 12.17.192.1 até 12.17.207.255 já estão alocados para clientes deste provedor. Este provedor precisa atender a quatro novos clientes, um deles necessita de rede com pelo menos 1000 endereços de IP válidos e os outros três necessitam de rede com pelo menos 30 IP válidos. Faça uma proposta para alocação de endereços IP para estes clientes. Os endereços reservados para estes novos clientes devem ser alocados a partir da numeração mais baixa disponível. Procure também responder as questões abaixo:<br />
##Qual o total de endereços que dispõe o provedor em questão?<br />
##Quantos endereços IP já estão utilizados?<br />
##Quantos endereços IP este provedor possui livres para alocar aos novos clientes?<br />
##Qual o endereço identificador de cada sub-rede dos novos clientes?<br />
##Qual o a máscara de rede de cada sub-rede dos novos clientes?<br />
##Qual o endereço de broadcast de cada sub-rede dos novos clientes?<br />
##Quantos endereços IP ainda sobrarão ao provedor após atender a estes clientes?<br />
#Quantas estações uma rede 223.1.10.0/24 suporta? <br />
#Uma rede com bloco de IPs 200.23.16.0/20 deseja montar 8 subredes. Mostre como isso é possível e como ficaria os endereços de cada uma dessas subredes.<br />
#Um datagrama enviado para uma estação da mesma rede precisa passar por um roteador?<br />
#Suponha que entre o hospedeiro de origem A e o hospedeiro de destino B os datagramas estejam limitados a 1500 bytes (incluindo cabeçalho). Admitindo um cabeçalho IP de 20 bytes, quantos datagramas seriam necessários para enviar um arquivo MP3 de 5 milhões de bytes? Explique como você obteve a resposta.<br />
#Descreva e detalhe o processo de obtenção de um endereço IP através do protocolo DHCP. [[Image:ExercicioConfEstaticaZebra.png]]<br />
#Considere a rede apresetanda na Figura, onde todas as sub-redes apresentam máscara de rede /24 (255.255.255.0), e tendo os dados do Host1 e Roteador 4 apresentados no quadro abaixo, responda: <syntaxhighlight lang=bash><br />
root@H1:~# ifconfig <br />
eth0 Link encap:Ethernet HWaddr 7a:a6:f4:ca:51:0e <br />
inet addr:200.10.1.1 Bcast:200.10.1.255 Mask:255.255.255.0<br />
<br />
root@H1:~# route -n<br />
Kernel IP routing table<br />
Destination Gateway Genmask Flags Metric Ref Use Iface<br />
0.0.0.0 200.10.1.254 0.0.0.0 UG 0 0 0 eth0<br />
200.10.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0<br />
<br />
root@R4:~# route -n<br />
Kernel IP routing table<br />
Destination Gateway Genmask Flags Metric Ref Use Iface<br />
200.10.1.0 200.10.3.1 255.255.255.0 UG 0 0 0 eth0<br />
200.10.3.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0<br />
200.10.5.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1<br />
200.10.6.0 0.0.0.0 255.255.255.0 U 0 0 0 eth2<br />
200.10.8.0 200.10.6.1 255.255.255.0 UG 0 0 0 eth2 </syntaxhighlight><br />
##Observando a tabela do hospedeiro (H1) é possível dizer quem é seu roteador default?<br />
##Se o hospedeiro (H1) tiver um pacote para entregar para o IP 200.10.1.20 ele utilizará entrega direta ou utilizará seu roteador padrão? Explique o significado da entrega direta e indireta (via roteador).<br />
##Se o hospedeiro (H1) tiver um pacote para entregar para o IP 200.10.8.1 ele utilizará entrega direta ou utilizará seu roteador padrão?<br />
##Se o roteador (R4) receber um pacote cujo IP de destino é 200.10.1.10 para qual roteador ele entregará tal pacote e por qual interface? Será uma entrega direta ou indireta?<br />
##Se o roteador (R4) receber um pacote cujo IP de destino é 200.10.6.1 para qual roteador ele entregará tal pacote e por qual interface? Será uma entrega direta ou indireta?<br />
##Se o roteador (R4) receber um pacote cujo IP de destino é 200.10.1.10, cuja carga segmento TCP com destino a porta 80, para qual roteador ele entregará tal pacote e por qual interface? Será uma entrega direta ou indireta?<br />
##Se o roteador (R4) receber um pacote cujo IP de destino é 122.10.4.7 para qual roteador ele entregará tal pacote e por qual interface? Explique.<br />
##Qual comando que você executaria no roteador (R4) para acrescentar uma rota para a rede SN2? Explique seu comando.<br />
##Considerando a pergunta anterior, a rota acrescentada garantiria que se você fizer um ping para um host da rede SN2 você obteria sucesso? Explique todas as possibilidades.<br />
##Explique o significado dos campos das colunas 1, 2, 3 e 8 da última linha da tabela do roteador (R4).<br />
{{Collapse bottom}}</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=ISL-FicLinux_(p%C3%A1gina)&diff=162005ISL-FicLinux (página)2019-10-03T19:50:52Z<p>127.0.0.1: /* Cronograma Tentativa */</p>
<hr />
<div>__NOTOC__<br />
= Introdução ao Sistema Operacional Linux / Redes com Linux =<br />
<br />
*'''Encontros:''' Terças e Quintas das 19:00 às 22:00.<br />
*'''Local:''' Laboratório de Redes de Computadores (Redes 1).<br />
<br />
*[[ISL-FicLinux_(Plano_de_Ensino)| Plano de Ensino]]<br />
<br />
==Curso FIC Linux 2019==<br />
<br />
{{collapse top | Semestre 2019-2 - Prof. Eraldo Silveira e Silva}}<br />
<br />
==Cronograma Tentativa==<br />
<br />
Horários: 19h às 22h.<br />
<br />
{| class="wikitable"|<br />
| AULA || DATA || Professor || Conteúdo<br />
|-<br />
| 1 || 27/09/2019 || ERALDO || Programa da Disciplina.Forma de Avaliação. O computador: hardware e software. SO Linux: histórico e distribuições. Ligando/Logando/Desligando a Máquina. Conceitos básico de Sistema de Arquivos e Processos.<br />
|-<br />
| 2 || 29/09/2019 || ERALDO || Gerenciamento de Arquivos I: Operações sobre arquivos e diretórios usando o terminale o Nautilus.<br />
|-<br />
| 3 || 3/09/2019 || ERALDO || Gerenciamento de Arquivos II: continuação Operações sobre arquivos e diretórios. Links Simbólicos, Criação de Arquivo com vi e outros editores.<br />
|-<br />
| 4 || 5/09/2019 || ERALDO || Interfaces Gráficas: X11, Gnome. KDE e outras. Instalação de Programas via Gerenciador de Pacotes.<br />
|-<br />
| 5 || 10/09/2019 || ERALDO || Administração de contas de usuários I<br />
|-<br />
| 6 || 12/09/2019 || ERALDO || Administração de contas de usuários II<br />
|-<br />
| 7 || 17/09/2019 || ERALDO || Permissionamento de Arquivos<br />
|-<br />
| 8 || 19/09/2019 || ERALDO || Gerenciamento de Processos<br />
|-<br />
| 9 || 24/09/2019 || ERALDO || Introdução ao Shell Script<br />
|-<br />
| 10 || 26/09/2019 || ERALDO || Introdução ao Shell Script<br />
|-<br />
| 11 || 1/10/2019 || ERALDO || Introdução a Redes. Conceito de Protocolos. Ferramentas de Rede no Linux.<br />
|-<br />
| 12 || 3/10/2019 || ERALDO || Conceito de Protocolos. Protocolos de Aplicação: exemplo http. Protocolo DNS<br />
|-<br />
| 13 || 8/10/2019 || ERALDO || Camada de Transporte: protocolo UDP. Protocolo TCP. Diferenças dos protocolos de Transporte TCP/UDP. <br />
|-<br />
| 14 || 10/10/2019 || ERALDO || Camada IP e aspectos da configuração da mesma sob o Linux<br />
|-<br />
| 15 || 15/10/2019 || ERALDO || Camada de Enlace/Física. Hubs X Switches. O Papel do Protocolo ARP. Outros serviços/protocolos: Serviço DHCP e NAT<br />
|-<br />
| 16 || 17/10/2019 || ERALDO|| Segmentação Redes IP. Cálculo de subredes. <br />
|-<br />
| 17 || 22/10/2019 || ERALDO || Introdução ao IPV6. Introdução ao Access Point TPLINK N750: configuração da LAN e WAN<br />
|-<br />
| 18 || 24/10/2019 || ERALDO || Serviço SSH no Linux. Acesso a rede WIFI. Conceitos básicos de redes sem fio.<br />
|-<br />
| 19 || 29/10/2009 || ERALDO || Tópicos Adicionais sobre redes no Linux: Configuração Manual X NetworkManager. Relatório Avaliativo 1.<br />
|-<br />
| 20 || 31/10/2019 || ERALDO || Relatório Avaliativo 2<br />
|}<br />
<br />
=Curso FIC Linux 2019-2=<br />
<br />
==Professor==<br />
<br />
:*Prof. [[Eraldo Silveira e Silva]]<br />
:*email: eraldo@ifsc.edu.br<br />
:*sala: Sala de I de Professores da Área de Telecomunicações (primeira sala lado da Biblioteca - direção esquerda)<br />
<br />
=27/08/2019=<br />
<br />
==Objetivos==<br />
<br />
===Parte 1===<br />
<br />
*Apresentar o IFSC: estrutura, câmpus e serviços<br />
*Apresentar o curso: perfil do egresso, competências gerais, áreas de atuação do egresso e conteúdos previstos<br />
*Apresentar o Cronograma Tentativa (ver SIGA A)<br />
*Apresentar metodologia e forma de avaliação<br />
<br />
===Parte 2===<br />
<br />
*Conceitos de Hardware, Software e Firmware<br />
*Arquiteturas de processadores<br />
*Classificação de softwares<br />
*Conceitos de Sistemas Operacionais e exemplos<br />
<br />
===Parte 3===<br />
<br />
*Histórico do Linux<br />
*Linux e GNU/Linux<br />
*Instalando o Linux<br />
*Arquitetura do Linux<br />
*Distribuições<br />
*Distribuições usadas no IFSC/SJ<br />
*Ligando e Desligando o Sistema<br />
*Primeiros contatos.<br />
<br />
==Professores do FIC Linux Edição 2019-2==<br />
<br />
*Prof. [[Eraldo Silveira e Silva]] (Introdução ao Linux e Redes com Linux)<br />
<br />
==Apresentação do IFSC==<br />
<br />
*[http://www.ifsc.edu.br/estrutura-organizacional-inicio Página do IFSC]<br />
*[https://www.sj.ifsc.edu.br/index.php Página do Câmpus]<br />
<br />
==Apresentação do Curso==<br />
<br />
*[[ISL-FicLinux_(Plano_de_Ensino) | Introdução ao Linux]]<br />
*[https://wiki.sj.ifsc.edu.br/index.php/PRL-FicLinux_(Plano_de_Ensino) Projeto de Rede Residencial com o Linux]<br />
*[[Curso_de_Formação_Continuada_de_Configuração_de_Redes_de_Computadores_Linux | PPC do Curso e Outras Regulamentações]]<br />
<br />
==Cronograma Tentativa==<br />
<br />
Horários: 19h às 22h.<br />
<br />
VER SIGA A [https://sig.ifsc.edu.br/sigaa/verTelaLogin.do]<br />
<br />
==Metodologia, Avaliação e Critérios de Aprovação==<br />
<br />
*Aulas expositivas e aulas práticas no laboratório. Nas aulas práticas serão desenvolvidos exercícios e trabalhos individuais.<br />
*Avaliações individuais: Listas de exercícios com aproveitamento e entregues no prazo. <br />
*Critérios para aprovação: Serão considerados aprovados os alunos que obtiverem conceito final 6 ou superior em cada componente curricular. ATENÇÃO: Possuir no mínimo 75% de presença<br />
<br />
==Bibliografia==<br />
<br />
#Odilson Tadeu Valle<br />
##Administração de redes com Linux: fundamentos e práticas<br />
##Editora IFSC, 2010<br />
#Gleydson Mazioli da Silva<br />
##Guia Foca Linux<br />
##http://www.guiafoca.org/<br />
#Luiz Carlos Lobato Lobo de Medeiros e Wendel Soares<br />
##Formação de suporte técnico PROINFO<br />
##https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo<br />
#Ari Frazão Jr e Marcelo Braga<br />
##Administração de Sistemas Linux<br />
##https://pt.scribd.com/doc/128912228/Administracao-de-Sistemas-Linux<br />
<br />
==Conceitos de Hardware, Software e Firmware==<br />
<br />
*Em informática, o hardware consiste nos equipamentos<br />
**Ex: Computador, teclado, mouse, monitor<br />
*Software é um aplicativo, desenvolvido em uma linguagem de programação<br />
**Ex: Windows, Linux, Mozilla Firefox, Google Chrome<br />
*Firmware é um conjunto de instruções básicas e específicas para um hardware<br />
**Ex: BIOS nos computadores, sistemas de controle das máquinas de lavar, etc.<br />
<br />
==Estrutura de um Computador e Arquitetura de Processadores==<br />
<br />
*Material de Referência: https://www.dropbox.com/s/fn3l9os4l7gh9o5/AULA%201.odp?dl=0<br />
<br />
===Outros Links Interessantes===<br />
<br />
*Bits, [https://pt.wikipedia.org/wiki/Byte Bytes] e tamanho de memória;<br />
*Representação de Caracteres: [https://pt.wikipedia.org/wiki/ASCII Tabela ASCII];<br />
*O [https://pt.wikipedia.org/wiki/Microprocessador microprocessador], barramentos e memórias semicondutoras: RAM,ROM, E2PROM, FLASH;<br />
*Memórias cache e memórias secundárias;<br />
*[https://pt.wikipedia.org/wiki/Mem%C3%B3ria_virtual Memória Virtual] e Swapping;<br />
*Registradores de 32bits ou 64bits<br />
*Arquitetura [https://pt.wikipedia.org/wiki/X86 x86] / [https://pt.wikipedia.org/wiki/AMD64 x86-64] – presente nos computadores pessoais<br />
*Arquitetura ARM – presente em sistemas embarcados e dispositivos móveis<br />
*Múltiplos núcleos (core)<br />
*Máquinas Virtuas: VirtualBox, UML (User Mode Linux).<br />
<br />
==O papel do Sistema Operacional==<br />
<br />
*O [https://pt.wikipedia.org/wiki/Sistema_operativo SO] é um programa (software) que controla a máquina e a torna utilizável para o usuário;<br />
*Abstrações do Sistema: arquivos e processos;<br />
*Pode ser multitarefa e multiusuário;<br />
*[https://en.wikipedia.org/wiki/Device_driver Driver] de dispositivo<br />
*[https://pt.wikipedia.org/wiki/Multi_boot Múltiplos OS instalados] em um computador. É possível??<br />
<br />
==Sistema de Arquivos==<br />
<br />
*Forma como estão estruturados/organizados os arquivos/dados em uma determinada mídia [https://pt.wikipedia.org/wiki/Sistema_de_ficheiros];<br />
*Um sistema operacional deve saber como acessar e operar sobre este sistema;<br />
*Tipos de sistemas: ext4, NTFS, VFAT32<br />
<br />
==Exemplos de SO==<br />
<br />
*Unix<br />
*Microsoft DOS<br />
*IBM<br />
*Microsoft Windows<br />
*netBSD, freeBSD, openBSD<br />
*Linux<br />
*macOS<br />
*Android<br />
*iOS<br />
<br />
==Histórico do Linux==<br />
<br />
*O início de tudo: UNIX;<br />
*Surgiu em 1991 quando Linus Torvalds, um estudante finlandês, resolveu desenvolver um sistema operacional compatível com a POSIX, por em que pudesse ser executado em arquitetura x86;<br />
*Linux está sob uma licença de software livre e diversas pessoas e empresas contribuem para o desenvolvimento do mesmo.<br />
*E o que é [https://pt.wikipedia.org/wiki/POSIX POSIX]? Define padrões para a interface de programação de aplicações (API) de um OS de forma a manter compatibilidade com o UNIX;<br />
<br />
==Arquitetura do Linux==<br />
<br />
===Material de Referência===<br />
<br />
*[https://www.dropbox.com/s/zvpo7zw19ns7rmk/AULA%202.odp?dl=0 Slides Introdução ao SO Linux]<br />
*Ver pg.16 a 19 de [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo]<br />
<br />
==Distribuições==<br />
<br />
Uma distribuição Linux consiste de um kernel Linux e uma coleção de software utilitários e aplicativos de usuário (baseado slides Prof. Emerson)<br />
**Redhat<br />
**Slackware<br />
**Debian<br />
**Ubuntu<br />
**OpenSuse<br />
**Fedora<br />
**CentOS<br />
**Kali<br />
<br />
<br />
Algumas distribuições podem ser executadas diretamente no CD/pendrive<br />
sem a necessidade de fazer sua instalação no disco rígido do computador<br />
<br />
==Distribuições aqui no IFSC SJ==<br />
<br />
*Ubuntu<br />
*Ubuntu Mate (fork do Ubuntu)<br />
*Debian<br />
<br />
==Instalando o Linux==<br />
<br />
*Fazer Download do arquivo ISO em [http://mirror.pop-sc.rnp.br/mirror/ubuntu-releases/18.04/] versão Ubuntu 18.04.3 LTS;<br />
*Instalar a VirtualBox (já está instalada no nosso Lab). Baixar de [https://www.virtualbox.org/wiki/Downloads] e selecionar para a máquina hospedeira alvo;<br />
*Seguir o procedimento colocado pelo professor.<br />
<br />
*[Ver https://www.dropbox.com/s/4xfdhqq8lruvq8m/LinuxSobreVM.odp?dl=0 Slides de Instalação]<br />
<br />
==Ligando e Desligando o Sistema Linux==<br />
<br />
*Cuidado ao desligar um OS como o Linux!!! Dados podem ser perdidos.<br />
*Ver [https://pt.wikibooks.org/wiki/Guia_do_Linux/Iniciante%2BIntermedi%C3%A1rio/Introdu%C3%A7%C3%A3o/Ligando_o_computador]<br />
<br />
==O Desktop do Ubuntu - Primeiras Considerações==<br />
<br />
*O Desktop no Ubuntu ver[https://help.ubuntu.com/stable/ubuntu-help/shell-overview.html]<br />
<br />
=AULA 2 - Dia 29/08/2019=<br />
<br />
==Objetivos==<br />
<br />
===PARTE 1===<br />
<br />
*Revisão da aula passada;<br />
*repassar itens não mencionados na aula passada;<br />
**Paginação e Memória [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo pg.19]<br />
**Estrutura do Linux [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo pg.18]<br />
<br />
===PARTE 2===<br />
<br />
*Operações com arquivos e diretórios usando o terminal;<br />
*formato de um comando básico;<br />
*quase tudo no Linux é arquivo: tipos de arquivos, diretórios, arquivos ordinários;<br />
*conceito de sistema de arquivos;<br />
*conceito de referência absoluta e relativa;<br />
*conceito de diretório de entrada, diretório de trabalho;<br />
*mudando de diretório com cd;<br />
*listando diretórios e arquivos com ls;<br />
*vendo o significado de um comando com man;<br />
*criando diretórios com mkdir;<br />
*removendo diretórios e arquivos com rmdir e rm;<br />
*referência com . .. - ~<br />
*criando arquivos ordinários com touch;<br />
*arquivos e diretórios escondidos;<br />
*copiando arquivos;<br />
*movendo e renomeando arquivos;<br />
*vendo a história de comandos com history;<br />
<br />
===Slides===<br />
<br />
*[https://www.dropbox.com/s/wtc479wmrtle9m4/SistemaDeArquivos.odp?dl=0 Slides Sistema de Arquivos]<br />
<br />
==Conceito de sistemas de arquivos, arquivos e diretórios==<br />
<br />
* [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Sistemas de Arquivos pg.18]<br />
* [Estrutura básica de diretórios do Sistema Linux]<br />
<br />
==Comandos no Linux==<br />
<br />
* [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Comandos e Interpretador de Comandos no Linux pg.18]<br />
<br />
==Tipos de Arquivos==<br />
<br />
* [https://pt.scribd.com/doc/128912228/Administracao-de-Sistemas-Linux Tipos de Arquivos 12,13 e 14 ]<br />
<br />
==Os comandos de operação sobre arquivos e diretórios==<br />
<br />
*[https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Interpretador de comandos - Comandos Básicos - pg.20 e 21]<br />
*[https://www.dropbox.com/s/mv6qpa8bqimiwzg/Aula1_Linux%282%29.pdf Ver lista de exercícios da Aula 2]<br />
<!-- *[https://www.dropbox.com/s/g3xr3wimffde2zm/Aula2_Linux_OperacoesComArquivos_2.pdf Ver lista de exercícios da Aula 3] --><br />
<br />
=AULA 3 - Dia 03/09/2019=<br />
<br />
<br />
===Mirros do Ubuntu Download e Outros===<br />
<br />
<br />
*[http://mirror.pop-sc.rnp.br/mirror/ubuntu-releases/18.04.3/ Ununtu 18.04.3 Mirror Brazil]<br />
<br />
*[https://linuxmint.com/edition.php?id=267 Linux Mint]<br />
<br />
*[https://software.opensuse.org/distributions/leap Opensuse]<br />
<br />
*[https://elementary.io/ Elementary Os]<br />
<br />
*[https://lubuntu.net/ Lubuntu]<br />
<br />
*[https://www.debian.org/CD/live/ Debian]<br />
<br />
*[https://kubuntu.org/getkubuntu/ Kubuntu]<br />
<br />
*[https://peppermintos.com/ Peppermint]<br />
<br />
*[https://www.linuxliteos.com/ Linux Lite]<br />
<br />
*[https://www.lxle.net/download/ LXLE para PCs Antigos...]<br />
<br />
*[https://www.bodhilinux.com/ Bodhi Linux]<br />
<br />
===Como verificar se o arquivo está correto?===<br />
<br />
*[https://help.ubuntu.com/community/HowToMD5SUM HowToMD5SUM] <br />
<br />
===Instalar e Preparar 3 transparências no Oppenoffice===<br />
<br />
*Nome da Equipe e da Distribuição - colar a desktop no slide<br />
*O que tem de interessante nesta distro<br />
*Requisitos da Distribuição<br />
<br />
*Gerar pdf e Enviar para o Siga a<br />
<br />
=AULA 4 - Dia 03/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Ainda operações com arquivos;<br />
*Uso de Coringas<br />
*Editor de texto sobre Ubuntu<br />
*Redirecionamento de Entradas e Saídas<br />
*Aspectos da Interface Gnome no Ubuntu 18.04<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/zti7nn0xq25x8ne/Aula2_Linux_OperacoesComArquivos_2.pdf Ainda Operações com Arquivos]<br />
*[https://www.dropbox.com/s/af3jolkvrb24g8c/Aula3_Linux_LinksSimb_licos_gedit_cat.pdf Edição de Texto]<br />
*[https://www.dropbox.com/s/vihh5r9186d40uj/Aula3_Linux_Parte4_RedirecionamentoEntradasSaidas.pdf Redirecionamento de Entradas e Saídas]<br />
<br />
=AULA 5 - Dia 10/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Gerenciamento de Processos - Parte 1<br />
*Permissionamento de Arquivos - Parte 1<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/4i1n2wqsds18eol/Aula5_Linux_GerenciamentoDeProcessos_Parte1.pdf?dl=0 Gerenciamento de Processos - Parte 1]<br />
*[https://www.dropbox.com/s/3z61r8r0b9wpftr/Aula4_Linux_PermissionamentoDeAcesso_Parte1.pdf Permissionamento de Arquivos - Parte 1]<br />
<br />
=AULA 6 - Dia 12/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Aval1<br />
<br />
==Comand wget==<br />
<br />
Para fazer o downloiad do Linux Ubuntu via linha de comando:<br />
<br />
wget http://mirror.pop-sc.rnp.br/mirror/ubuntu-releases/18.04.3/ubuntu-18.04.3-desktop-amd64.iso<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/fdl5kzq0ba2nv3v/Aula4_Linux_PermissionamentoDeAcesso_Parte2.pdf Permissionamento Parte 2 ]<br />
<br />
=AULA 7 - Dia 12/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Instalação do Ubuntu em partições separadas<br />
*Permissionamento de Grupos e Outros<br />
*Criação de Contas de Usuários<br />
*Camandos adicionais para gerenciamento de processos<br />
<br />
==Instalação==<br />
<br />
Considere a estrutura de sistemas de arquivos abaixo. Montar um sistema de arquivos da forma abaixo considerando que sb1 seria um segundo hd máquina virtual.<br />
<br />
[[arquivo:SOP2019-1-ExemploMontagemSistema.png]]<br />
<br />
Logar no sistema e usando o terminal verificar as configurações estabelecidas.<br />
<br />
df -h<br />
cd /home<br />
ls spock<br />
<br />
Usar o comando gparted para criar uma partição adicional no segundo disco.<br />
<br />
sudo apt-get install gparted<br />
sudo gparted<br />
<br />
Redimensionar a partição original para poder criar uma adicional.<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/fdl5kzq0ba2nv3v/Aula4_Linux_PermissionamentoDeAcesso_Parte2.pdf Permissionamento Parte 2 ]<br />
<br />
*[https://www.dropbox.com/s/ozjd3qz0yblcj43/Aula6_Comandos_Adicionais_de_Gerenciamento_de_Processos.pdf Gerenciamento de Processos Parte 2]<br />
<br />
=AULA 8 - Dia 12/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Permissionamento de Grupos e Outros<br />
*Criação de Contas de Usuários<br />
*Reparticionamento de Disco após instalação. Montagem de sistemas com mount.<br />
<br />
==Desafio Final==<br />
<br />
Na máquina instalada na aula anterior fazer as seguintes operações:<br />
<br />
*Reparticionar o disco 2 (/dev/sdb) em 2 partições de 5G (usar o comando gparted) (redimensionar a partição do spock)<br />
*Criar uma conta para o usuário uhura<br />
*Criar dois subdiretórios no diretório home de uhura. Estes diretórios serão pontos de montagem dos dois sistemas de arquivos criados no segundo disco.<br />
*Montar os sistemas de arquivos usando o comando mounthttps://wiki.sj.ifsc.edu.br/index.php/ISL-FicLinux_(Plano_de_Ensino)<br />
*Mudar o dono destes diretórios (usuário e grupo) )para o novo dono (uhura)<br />
*Verificar o sistema montado (comando df)<br />
*Testar o acesso entrando como <br />
<br />
==Continuando o o permissionamento de Grupos e Outros==<br />
<br />
Ver material de referência<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/fdl5kzq0ba2nv3v/Aula4_Linux_PermissionamentoDeAcesso_Parte2.pdf Permissionamento Parte 2 ]<br />
*[https://www.dropbox.com/s/ozjd3qz0yblcj43/Aula6_Comandos_Adicionais_de_Gerenciamento_de_Processos.pdf Gerenciamento de Processos Parte 2]<br />
<br />
=AULA 9 - Dia 24/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*ainda criação de usuários<br />
*ainda gerenciamento de processos: crontab<br />
*compactação e backups em linha de comando<br />
<br />
<br />
==Material de Referência==<br />
<br />
<br />
*[Ainda Gerenciamento de Usuários https://www.dropbox.com/s/8vsg0yeforcsuq9/Aula7_GerenciamentoDeUsuarios_Parte1.pdf?dl=0]<br />
*[https://www.dropbox.com/s/ozjd3qz0yblcj43/Aula6_Comandos_Adicionais_de_Gerenciamento_de_Processos.pdf Gerenciamento de Processos Parte 2]<br />
*[https://www.dropbox.com/s/61n9is9c8o7bgbz/Aula3_Linux_Parte3_vi.pdf?dl=0 Introdução ao VI]<br />
<br />
=AULA 10 - Dia 26/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Finalização da aula anterior: arquivo sudoers<br />
*Introdução ao shell script<br />
*Um pouco sobre instalação de pacotes<br />
*exercicício avaliativo 2<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/54tnv5rjwguzppd/Aula8_ShellScript_Parte1.pdf?dl=0 Introdução ao Shell script]<br />
*[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula9-pacotes.pdf Instalação de Pacotes (Prof.Luciano Barreto)]<br />
<br />
=AULA 11 - Dia 1/10/2019=<br />
<br />
Introdução a Redes de Computadores<br />
**Conceito Básicos em Redes e Protocolos<br />
**Ferramentas de Redes<br />
**Exemplo de Protocolo de Aplicação: http<br />
**O processo de encapsulamento<br />
<br />
==Plano de Ensino==<br />
<br />
*[https://wiki.sj.ifsc.edu.br/index.php/PRL-FicLinux_(Plano_de_Ensino) Plano de Ensino]<br />
<br />
<br />
==Laboratório 1 - Ferramentas de Rede e Conceitos Básicos==<br />
<br />
*Familiarização com a infraestrutura dos laboratórios de redes<br />
*Familiarização com ferramentas de rede: ifconfig, ping, traceroute;<br />
*Desenvolver a noção de endereçamentos de rede IP e de endereço de hardware (MAC)<br />
*Desenvolver a noção de rotas em redes IP<br />
*Testar a conectividade IP com ping<br />
<br />
*Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)]<br />
<br />
==Laboratório 2 - Wireshark e encapsulamento==<br />
<br />
*Familiarização com o sniffer de rede WireShark<br />
*Observar o comportamento do ping e se familiarizar com o processo de encapsulamento;<br />
<br />
**Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)]<br />
<br />
==Conceituando Protocolos e Aplicações de Rede==<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/Conceituando%20protocolos.pdf Conceituando protocolos]<br />
<br />
<br />
=AULA 12 - Dia 03/10/2019=<br />
<br />
==Objetivos==<br />
<br />
*Conceituando protocolos<br />
*Protocolos de aplicação: exemplo http<br />
<br />
==Laboratório 3 - Conceituando protocolo==<br />
<br />
Ver [https://wiki.sj.ifsc.edu.br/index.php?title=ISL-FicLinux_(p%C3%A1gina)&action=edit&section=69]<br />
<br />
==Laboratório 4 - Desvendando o HTTP com Wireshark - BÁSICO==<br />
<br />
Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)#Parte_1:_Observando_interfaces_do_sistema_com_ifconfig]<br />
<br />
<br />
{{collapse bottom}}<br />
<br />
<br />
<br />
{{collapse top | Semestre 2019-1 - Prof. Tiago Semprebom e Eraldo Silveira e Silva}}<br />
<br />
=Professor=<br />
<br />
:*Prof. [[Tiago Semprebom]]<br />
:*email: tisemp@ifsc.edu.br<br />
:*sala: Sala de II de Professores da Área de Telecomunicações (primeira sala lado da Biblioteca - direção esquerda)<br />
<br />
=12/03/2019=<br />
<br />
==Objetivos==<br />
<br />
===Parte 1===<br />
*Apresentar os professores e o coordenador;<br />
*Apresentar o IFSC: estrutura, câmpus e serviços<br />
*Apresentar o curso: perfil do egresso, competências gerais, áreas de atuação do egresso e conteúdos previstos<br />
*Apresentar o Cronograma Tentativa<br />
*Apresentar metodologia e forma de avaliação<br />
<br />
===Parte 2===<br />
<br />
*Conceitos de Hardware, Software e Firmware<br />
*Arquiteturas de processadores<br />
*Classificação de softwares<br />
*Conceitos de Sistemas Operacionais e exemplos<br />
<br />
===Parte 3===<br />
<br />
*Histórico do Linux<br />
*Linux e GNU/Linux<br />
*Arquitetura do Linux<br />
*Distribuições<br />
*Distribuições usadas no IFSC/SJ<br />
*Ligando e Desligando o Sistema<br />
*Primeiros contatos.<br />
<br />
==Professores do FIC Linux Edição 2019-1==<br />
*Prof. [[Tiago Semprebom]] (Introdução ao Linux)<br />
*Prof. [[Eraldo Silveira e Silva]] (Redes com Linux)<br />
<br />
==Apresentação do IFSC==<br />
<br />
*[http://www.ifsc.edu.br/estrutura-organizacional-inicio Página do IFSC]<br />
*[https://www.sj.ifsc.edu.br/index.php Página do Câmpus]<br />
<br />
==Apresentação do Curso==<br />
<br />
*[[ISL-FicLinux_(Plano_de_Ensino) | Introdução ao Linux]]<br />
*[[PRL-FicLinux (página) | Projeto de Rede Residencial com o Linux]]<br />
*[[Curso_de_Formação_Continuada_de_Configuração_de_Redes_de_Computadores_Linux | PPC do Curso e Outras Regulamentações]]<br />
<br />
==Cronograma Tentativa==<br />
<br />
Horários: 19h às 22h.<br />
<br />
{| class="wikitable"|<br />
| AULA || DATA || Professor || Conteúdo<br />
|-<br />
| 1 || 12/03/2019 || TIAGO || Programa da Disciplina.Forma de Avaliação. O computador: hardware e software. SO Linux: histórico e distribuições. Ligando/Logando/Desligando a Máquina. Conceitos básico de Sistema de Arquivos e Processos.<br />
|-<br />
| 2 || 14/03/2019 || TIAGO || Gerenciamento de Arquivos I: Operações sobre arquivos e diretórios usando o terminale o Nautilus.<br />
|-<br />
| 3 || 21/03/2019 || TIAGO || Gerenciamento de Arquivos II: continuação Operações sobre arquivos e diretórios. Links Simbólicos, Criação de Arquivo com vi e outros editores.<br />
|-<br />
| 4 || 26/03/2019 || TIAGO || Interfaces Gráficas: X11, Gnome. KDE e outras. Instalação de Programas via Gerenciador de Pacotes.<br />
|-<br />
| 5 || 28/03/2019 || TIAGO || Administração de contas de usuários I<br />
|-<br />
| 6 || 02/04/2019 || TIAGO || Administração de contas de usuários II<br />
|-<br />
| 7 || 04/04/2019 || TIAGO || Permissionamento de Arquivos<br />
|-<br />
| 8 || 09/04/2019 || TIAGO || Gerenciamento de Processos<br />
|-<br />
| 9 || 11/04/2019 || TIAGO || Introdução ao Shell Script<br />
|-<br />
| 10 || 16/04/2019 || TIAGO || Avaliação 1 - Introdução ao Sistema Operacional Linux<br />
|-<br />
| 11 || 09/10/2019 || ERALDO || Introdução a Redes. Conceito de Protocolos. Ferramentas de Rede.<br />
|-<br />
| 12 || 11/10/2019 || ERALDO || Protocolos de Aplicação: exemplo http <br />
|-<br />
| 13 || 16/10/2019 || ERALDO || O DNS como protocolo de Aplicação; Camada de Transporte: protocolo UDP <br />
|-<br />
| 14 || 18/10/2019 || ERALDO || Protocolo TCP. Diferenças dos protocolos de Transporte TCP/UDP. Camada IP e aspectos da configuração da mesma sob o Linux<br />
|-<br />
| 15 || 23/10/2017 || ERALDO || Camada de Enlace/Física. Hubs X Switches. O Papel do Protocolo ARP. Outros serviços/protocolos: Serviço DHCP e NAT<br />
|-<br />
| 16 || 25/10/2017 || ERALDO (TIAGO) || Segmentação Redes IP. Cálculo de subredes. <br />
|-<br />
| 17 || 30/10/2017 || ERALDO || Introdução ao IPV6. Introdução ao Access Point TPLINK N750: configuração da LAN e WAN<br />
|-<br />
| 18 || 01/11/2017 || ERALDO || Serviço SSH no Linux. Acesso a rede WIFI. Conceitos básicos de redes sem fio.<br />
|-<br />
| 19 || 06/11/2007 || ERALDO || Tópicos Adicionais sobre redes no Linux: Configuração Manual X NetworkManager. Relatório Avaliativo 1.<br />
|-<br />
| 20 || 08/11/2017 || ERALDO || Relatório Avaliativo 2<br />
|}<br />
<br />
==Metodologia, Avaliação e Critérios de Aprovação==<br />
<br />
*Aaulas expositivas e aulas práticas no laboratório. Nas aulas práticas serão desenvolvidos exercícios e trabalhos individuais.<br />
*Avaliações individuais: Listas de exercícios com aproveitamento e entregues no prazo. <br />
*Critérios para aprovação: Serão considerados aprovados os alunos que obtiverem conceito final 6 ou superior em cada componente curricular. ATENÇÂO: Possuir no mínimo 75% de presença<br />
<br />
==Bibliografia==<br />
<br />
#Odilson Tadeu Valle<br />
##Administração de redes com Linux: fundamentos e práticas<br />
##Editora IFSC, 2010<br />
#Gleydson Mazioli da Silva<br />
##Guia Foca Linux<br />
##http://www.guiafoca.org/<br />
#Luiz Carlos Lobato Lobo de Medeiros e Wendel Soares<br />
##Formação de suporte técnico PROINFO<br />
##https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo<br />
#Ari Frazão Jr e Marcelo Braga<br />
##Administração de Sistemas Linux<br />
##https://pt.scribd.com/doc/128912228/Administracao-de-Sistemas-Linux<br />
<br />
==Conceitos de Hardware, Software e Firmware==<br />
<br />
*Em informática, o hardware consiste nos equipamentos<br />
**Ex: Computador, teclado, mouse, monitor<br />
*Software é um aplicativo, desenvolvido em uma linguagem de programação<br />
**Ex: Windows, Linux, Mozilla Firefox, Google Chrome<br />
*Firmware é um conjunto de instruções básicas e específicas para um hardware<br />
**Ex: BIOS nos computadores, sistemas de controle das máquinas de lavar, etc.<br />
<br />
==Estrutura de um Computador e Arquitetura de Processadores==<br />
<br />
*Bits, [https://pt.wikipedia.org/wiki/Byte Bytes] e tamanho de memória;<br />
*Representação de Caracteres: [https://pt.wikipedia.org/wiki/ASCII Tabela ASCII];<br />
*O [https://pt.wikipedia.org/wiki/Microprocessador microprocessador], barramentos e memórias semicondutoras: RAM,ROM, E2PROM, FLASH;<br />
*Memórias cache e memórias secundárias;<br />
*[https://pt.wikipedia.org/wiki/Mem%C3%B3ria_virtual Memória Virtual] e Swapping;<br />
*Registradores de 32bits ou 64bits<br />
*Arquitetura [https://pt.wikipedia.org/wiki/X86 x86] / [https://pt.wikipedia.org/wiki/AMD64 x86-64] – presente nos computadores pessoais<br />
*Arquitetura ARM – presente em sistemas embarcados e dispositivos móveis<br />
*Múltiplos núcleos (core)<br />
*Máquinas Virtuas: VirtualBox, UML (User Mode Linux).<br />
<br />
==O papel do Sistema Operacional==<br />
<br />
*O [https://pt.wikipedia.org/wiki/Sistema_operativo SO] é um programa (software) que controla a máquina e a torna utilizável para o usuário;<br />
*Abstrações do Sistema: arquivos e processos;<br />
*Pode ser multitarefa e multiusuário;<br />
*[https://en.wikipedia.org/wiki/Device_driver Driver] de dispositivo<br />
*[https://pt.wikipedia.org/wiki/Multi_boot Múltiplos OS instalados] em um computador. É possível??<br />
<br />
==Sistema de Arquivos==<br />
<br />
*Forma como estão estruturados/organizados os arquivos/dados em uma determinada mídia [https://pt.wikipedia.org/wiki/Sistema_de_ficheiros];<br />
*Um sistema operacional deve saber como acessar e operar sobre este sistema;<br />
*Tipos de sistemas: ext4, NTFS, VFAT32<br />
<br />
==Exemplos de SO==<br />
<br />
*Unix<br />
*Microsoft DOS<br />
*IBM<br />
*Microsoft Windows<br />
*netBSD, freeBSD, openBSD<br />
*Linux<br />
*macOS<br />
*Android<br />
*iOS<br />
<br />
==Histórico do Linux==<br />
<br />
*O início de tudo: UNIX;<br />
*Surgiu em 1991 quando Linus Torvalds, um estudante finlandês, resolveu desenvolver um sistema operacional compatível com a POSIX, por em que pudesse ser executado em arquitetura x86;<br />
*Linux está sob uma licença de software livre e diversas pessoas e empresas contribuem para o desenvolvimento do mesmo.<br />
*E o que é [https://pt.wikipedia.org/wiki/POSIX POSIX]? Define padrões para a interface de programação de aplicações (API) de um OS de forma a manter compatibilidade com o UNIX;<br />
<br />
==Arquitetura do Linux==<br />
<br />
*Ver pg.16 a 19 de [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo]<br />
<br />
==Distribuições==<br />
<br />
Uma distribuição Linux consiste de um kernel Linux e uma coleção de software utilitários e aplicativos de usuário (baseado slides Prof. Emerson)<br />
**Redhat<br />
**Slackware<br />
**Debian<br />
**Ubuntu<br />
**OpenSuse<br />
**Fedora<br />
**CentOS<br />
**Kali<br />
<br />
<br />
Algumas distribuições podem ser executadas diretamente no CD/pendrive<br />
sem a necessidade de fazer sua instalação no disco rígido do computador<br />
<br />
==Distribuições aqui no IFSC SJ==<br />
<br />
*Ubuntu<br />
*Ubuntu Mate (fork do Ubuntu)<br />
*Debian<br />
<br />
==Ligando e Desligando o Sistema Linux==<br />
<br />
*Cuidado ao desligar um OS como o Linux!!! Dados podem ser perdidos.<br />
*Ver [https://pt.wikibooks.org/wiki/Guia_do_Linux/Iniciante%2BIntermedi%C3%A1rio/Introdu%C3%A7%C3%A3o/Ligando_o_computador]<br />
<br />
==O Desktop do Ubuntu - Primeiras Considerações==<br />
<br />
*O Desktop no Ubuntu ver[https://help.ubuntu.com/stable/ubuntu-help/shell-overview.html]<br />
<br />
=AULA 2 - Dia 14/03/2019=<br />
<br />
==Objetivos==<br />
<br />
===PARTE 1===<br />
<br />
*Revisão da aula passada;<br />
*repassar itens não mencionados na aula passada;<br />
**Paginação e Memória [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo pg.19]<br />
**Estrutura do Linux [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo pg.18]<br />
<br />
===PARTE 2===<br />
<br />
*Operações com arquivos e diretórios usando o terminal;<br />
*formato de um comando básico;<br />
*quase tudo no Linux é arquivo: tipos de arquivos, diretórios, arquivos ordinários;<br />
*conceito de sistema de arquivos;<br />
*conceito de referência absoluta e relativa;<br />
*conceito de diretório de entrada, diretório de trabalho;<br />
*mudando de diretório com cd;<br />
*listando diretórios e arquivos com ls;<br />
*vendo o significado de um comando com man;<br />
*criando diretórios com mkdir;<br />
*removendo diretórios e arquivos com rmdir e rm;<br />
*referência com . .. - ~<br />
*criando arquivos ordinários com touch;<br />
*arquivos e diretórios escondidos;<br />
*copiando arquivos;<br />
*movendo e renomeando arquivos;<br />
*vendo a história de comandos com history;<br />
<br />
==Conceito de sistemas de arquivos, arquivos e diretórios==<br />
<br />
* [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Sistemas de Arquivos pg.18]<br />
* [Estrutura básica de diretórios do Sistema Linux]<br />
<br />
==Comandos no Linux==<br />
<br />
* [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Comandos e Interpretador de Comandos no Linux pg.18]<br />
<br />
==Tipos de Arquivos==<br />
<br />
* [https://pt.scribd.com/doc/128912228/Administracao-de-Sistemas-Linux Tipos de Arquivos 12,13 e 14 ]<br />
<br />
==Os comandos de operação sobre arquivos e diretórios==<br />
<br />
*[https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Interpretador de comandos - Comandos Básicos - pg.20 e 21]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_2_FICLinux.pdf Ver lista de exercícios da Aula 2]<br />
<!-- *[https://www.dropbox.com/s/g3xr3wimffde2zm/Aula2_Linux_OperacoesComArquivos_2.pdf Ver lista de exercícios da Aula 3] --><br />
<br />
=AULA 3 - Dia 21/03/2019 (aula com Prof. Eraldo)=<br />
<br />
==Objetivos==<br />
<br />
===PARTE 1===<br />
<br />
*Rever comandos básicos de operações sobre arquivos;<br />
*Usar coringas<br />
*usar opções do comando ls<br />
<br />
===PARTE 2===<br />
<br />
*uso do editor gedit para criar arquivos texto;<br />
*usar comandos cat, more e less para visualizar conteúdos de arquivos.<br />
<br />
===PARTE 3===<br />
<br />
*Criar Links simbólicos<br />
<br />
===Parte 4===<br />
<br />
*Redirecionamento de entradas e saídas;<br />
*Pipes<br />
<br />
==Exercícios para esta aula==<br />
'''Créditos e agradecimentos ao Prof. Eraldo pelo desenvolvimento das listas utilizadas''':<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_3_FICLinux.pdf Mais operações Sobre Arquivos e Diretórios]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_4_FICLinux.pdf Editor Gedit, Link Simbólico]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_5_FICLinux.pdf Editor vi]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_6_FICLinux.pdf Entradas e Saídas]<br />
<br />
=AULA 4 - Dia 26/03/2019=<br />
<br />
==Objetivos==<br />
<br />
===PARTE 1===<br />
<br />
*Revisão geral<br />
<br />
<br />
===PARTE 2===<br />
<br />
*Redirecionamento de entradas e saídas: continuação;<br />
*Pipes<br />
<br />
===PARTE 3===<br />
<br />
*Permissão no acesso a arquivos;<br />
*Owner, grupo e outros<br />
<br />
==Exercícios para esta aula==<br />
<br />
=Referências=<br />
<br />
[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_7_FICLinux.pdf Permissão de Acesso a Arquivos: parte 1]<br />
<br />
[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_8_FICLinux.pdf Permissão de Acesso a Arquivos: parte 2]<br />
<br />
=AULA 5 - Dia 28/03/2019=<br />
<br />
==Objetivos==<br />
<br />
*Revisão e preparação para teste;<br />
*introdução ao gerenciamento de processos;<br />
**conceito de processo<br />
**escalonamento de processos<br />
**PID e PPID<br />
**fork/exec<br />
**espaço de endereçamento de um processo;<br />
**estados de um processo: Running, Stopped, Sleeping, Zombie<br />
<br />
https://www.tecmint.com/linux-process-management/<br />
<br />
==Referências==<br />
<br />
[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_9_FICLinux.pdf Gerenciamento De Processos Parte 1]<br />
[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_10_FICLinux.pdf Gerenciamento De Processos Parte 2]<br />
<br />
[https://www.dropbox.com/s/gm1sv856ailny2e/Aula5_TreinamentoTeste.pdf Treinamento Teste 1]<br />
<br />
=AULA 6 - Dia 02/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*Comandos adicionais de gerenciamento de processos;<br />
*Mudança de prioridade com nice e renice;<br />
*Agendamento de processos com crontab<br />
*Aplicações do crontab: conectividade de rede e backup<br />
*Ferramentas de compactação;<br />
*Execução de comandos inseridos em outros comandos;<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/z1d0itcz9ommhrm/Aula6_Aval1.pdf Avaliação 1]<br />
<br />
=AULA 7 - Dia 04/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*Comandos adicionais de manipulação de arquivos:<br />
**comando grep;<br />
**comando find;<br />
*Gerenciamento de usuários:<br />
**adição e remoção de usuários e grupos<br />
**arquivo sudoers<br />
<br />
<br />
==Exercícios==<br />
<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_11_FICLinux.pdf Comandos Adicionais] <br />
<!--*[https://www.dropbox.com/s/h0v122is4aj9ogr/Aula7_GerenciamentoDeUsuarios_Parte1.pdf Aula 7 - Parte 2]--><br />
<br />
=AULA 8 - Dia 09/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*Introdução ao Shell script<br />
*variáveis<br />
*Comando if<br />
<br />
==Referências==<br />
<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_14_FICLinux.pdf Outros comando gerenciamento de processos]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_12_FICLinux.pdf Shell Parte 1]<br />
<br />
{{collapse top | script DESAFIO (a)}}<br />
<syntaxhighlight lang=c><br />
#!/bin/bash<br />
<br />
FILE="$1"<br />
<br />
if [ ! $# -eq 1 ]; then<br />
echo opa! Algo errado...<br />
echo uso: script parametro<br />
exit<br />
fi<br />
<br />
<br />
if [ -h $FILE ]; then<br />
echo $FILE é um link simbólico<br />
else<br />
echo $FILE não é um link simbólico<br />
fi<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
{{collapse top | script DESAFIO (b)}}<br />
<syntaxhighlight lang=c><br />
<br />
#!/bin/bash<br />
<br />
FILE="$1"<br />
<br />
if [ ! $# -eq 1 ]; then<br />
echo opa! Algo errado...<br />
echo uso: script parametro<br />
exit<br />
fi<br />
<br />
<br />
if [[ -w $FILE && -O $FILE ]]; then<br />
echo Possui permissao de escrita de $FILE<br />
else<br />
echo Colocando permissão de escrita para $FILE<br />
chmod u+w $FILE<br />
echo permissoes adicionadas com sucesso para $FILE ver abaixo<br />
ls -l $FILE<br />
<br />
fi<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
{{collapse top | script DESAFIO (c)}}<br />
<syntaxhighlight lang=c><br />
#!/bin/bash<br />
<br />
FILE1="$1"<br />
FILE2="$2"<br />
<br />
if [ ! $# -eq 2 ]; then<br />
echo opa! Algo errado...<br />
echo uso: script parametro<br />
exit<br />
fi<br />
<br />
if [[ -f $FILE1 && -r $FILE1 ]]; then<br />
echo $1 É regular e possui permissao de leitura<br />
mv $FILE1 $FILE2<br />
echo Mudei o nome de $FILE1 para $FILE2<br />
else<br />
echo $FILE1 não tem permissao...<br />
fi<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
=AULA 9 - Dia 11/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*ainda shell script<br />
*comando for<br />
*comando while<br />
<br />
==Referências==<br />
<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_13_FICLinux.pdf Shell Parte 2]<br />
<br />
=AULA 10 - Dia 16/04/2019=<br />
<br />
*Avaliação da disciplina<br />
<br />
=Tópicos extras=<br />
<br />
==Objetivos==<br />
<br />
*mais alguns tópicos sobre criação de usuários;<br />
*servidores de janelas: X11, <br />
*gerenciadores de janelas e desktops: Gnome, KDE<br />
*instalação de pacotes;<br />
*o Linux e o Software Livre<br />
*avaliação<br />
<br />
==Servidores de Janelas==<br />
<br />
[https://pt.wikipedia.org/wiki/X_Window_System X Windows System]<br />
<br />
[https://en.wikipedia.org/wiki/X_Window_System_protocols_and_architecture Arquitetura do X]<br />
<br />
==Desktops e Geneciadores de Janelas==<br />
<br />
[https://pt.wikipedia.org/wiki/Interface_gr%C3%A1fica_do_utilizador Interfaces Gráficas]<br />
<br />
==Instalando pacotes==<br />
<br />
[https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Ver pg.43 do Formacao-de-Suporte-Tecnico-Proinfo]<br />
<br />
[http://www.hardware.com.br/tutoriais/tutorial-completo-apt-get/ uso do apt-get]<br />
<br />
Exercício: instalar e executar um servidor ssh:<br />
<br />
sudo apt-get update<br />
sudo apt-get install openssh-server<br />
sudo service start ssh<br />
<br />
Acessar o ssh de outra máquina<br />
ssh usuario@numero_ip<br />
<br />
Exportar o display e executar o comando remoto:<br />
export DISPLAY=IP_cliente_ssh:0.0<br />
firefox &<br />
<br />
Conferir se o firefox realmente está se executando (use o ps)<br />
<br />
Remover o pacote ssh server:<br />
<br />
sudo apt-get remove openssh-server<br />
<br />
==Linux = Software Livre==<br />
<br />
[https://pt.wikipedia.org/wiki/Software_livre]<br />
<br />
<br />
<br />
[https://www.novell.com/coolsolutions/feature/1532.html]<br />
<br />
==Onde baixar o Ubuntu==<br />
<br />
[https://www.ubuntu.com/download/desktop Baixar Ubuntu daqui]<br />
<br />
==Sobre o Boot==<br />
<br />
[http://www.rodsbooks.com/linux-uefi/ by Roderick W. Smith]<br />
<br />
[https://www.happyassassin.net/2014/01/25/uefi-boot-how-does-that-actually-work-then/ AdamW on Linux and more]<br />
<br />
==Sobre o Desktop Environment e o Desktop Shell==<br />
<br />
[https://ittutorials.net/linux/ubuntu/desktop-guide/ /desktop-guide]<br />
<br />
==Instalar Ubuntu no Virtual Box==<br />
<br />
[http://www.edivaldobrito.com.br/virtualbox-no-linux/ Instalar VirtualBox no Linux]<br />
<br />
[http://www.bosontreinamentos.com.br/virtualizacao/como-instalar-o-virtualbox-no-windows-para-criacao-de-maquinas-virtuais/ Instalar VirtualBox no Windows]<br />
<br />
[http://www.techtudo.com.br/dicas-e-tutoriais/noticia/2016/04/como-instalar-o-ubuntu-com-o-virtualbox.html Instalar Linux no VirtualBox]<br />
<br />
=AULA 11 - Dia 23/04/2019=<br />
<br />
*Introdução a Redes de Computadores<br />
**Conceito Básicos em Redes e Protocolos<br />
**Ferramentas de Redes<br />
**Exemplo de Protocolo de Aplicação: http<br />
**O processo de encapsulamento<br />
<br />
==Plano de Ensino==<br />
<br />
*[https://wiki.sj.ifsc.edu.br/index.php/PRL-FicLinux_(Plano_de_Ensino) Plano de Ensino]<br />
<br />
<br />
==Laboratório 1 - Ferramentas de Rede e Conceitos Básicos==<br />
<br />
*Familiarização com a infraestrutura dos laboratórios de redes<br />
*Familiarização com ferramentas de rede: ifconfig, ping, traceroute;<br />
*Desenvolver a noção de endereçamentos de rede IP e de endereço de hardware (MAC)<br />
*Desenvolver a noção de rotas em redes IP<br />
*Testar a conectividade IP com ping<br />
<br />
*Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)]<br />
<br />
==Laboratório 2 - Wireshark e encapsulamento==<br />
<br />
*Familiarização com o sniffer de rede WireShark<br />
*Observar o comportamento do ping e se familiarizar com o processo de encapsulamento;<br />
<br />
**Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)]<br />
<br />
==Conceituando Protocolos e Aplicações de Rede==<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/Conceituando%20protocolos.pdf Conceituando protocolos]<br />
<br />
=AULA 12 - Dia 25/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*Protocolos de aplicação: exemplo http<br />
<br />
==Laboratório 4 - Desvendando o HTTP com Wireshark - BÁSICO==<br />
<br />
Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)#Parte_1:_Observando_interfaces_do_sistema_com_ifconfig]<br />
<br />
=AULA 13 - Dia 30/04/2019=<br />
<br />
*Revisão do Conceito de Protocolo ([-] Laboratório 3 - Conceituando protocolos )<br />
*O DNS como protocolo de Aplicação;<br />
*Camada de Transporte: protocolo UDP<br />
<br />
==Revisão dos Conceitos de Protocolo==<br />
<br />
Laboratório 3 - Conceituando protocolos [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)#Parte_1:_Observando_interfaces_do_sistema_com_ifconfig]<br />
<br />
==O DNS como protocolo de Aplicação==<br />
<br />
Laboratório 7 - Serviço de Nomes (DNS) [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)#Parte_1:_Observando_interfaces_do_sistema_com_ifconfig]<br />
<br />
==O Protocolo UDP==<br />
<br />
Laboratório 8 - Desvendando o UDP - Básico <br />
<br />
=AULA 14 - Dia 02/05/2019=<br />
<br />
==Objetivos==<br />
<br />
*Explorar o papel e diferenças dos protocolos de Transporte TCP/UDP<br />
*Explorar a Camada IP e aspectos da configuração da mesma sob o Linux<br />
<br />
<br />
===TCP e UDP===<br />
<br />
*docente.ifsc.edu.br/odilson/RCO60803/TCP%20controle%20de%20erros.pdf<br />
*docente.ifsc.edu.br/odilson/RCO60803/UDP%20Basico.pdf<br />
<br />
==Camada IP no Linux: Configuração das Interfaces usando ifconfig e ip addr==<br />
<br />
Usando a ferramenta Netkit2, que permite construir redes virtuais com o Linux vamos construir DUAS redes locais interligadas por um roteador. Em cada rede colocaremos dois PCs. As interfaces estarão completamente desconfiguradas:<br />
<br />
<ol><br />
<li><br />
Construir um arquivo texto de nome rede.conf usando o editor de texto gedit.<br />
<code>gedit rede.conf &</syntaxhighlight> <br />
</li><br />
<li><br />
Criar a seguinte topologia:<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=generic<br />
<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
#Definição da Topologia da Rede<br />
<br />
pc1[eth0]=lan0<br />
pc2[eth0]=lan0<br />
<br />
pc3[eth0]=lan1<br />
pc4[eth0]=lan1<br />
<br />
r1[eth0]=lan0<br />
r1[eth1]=lan1<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Executar netkit fazendo (atualize se necessário - pergunte para o professor como fazer):<br />
Aplicativos >> Educativo >> Netkit2 <br />
</li><br />
<li><br />
Carregar o arquivo lab.conf a partir do Netkit2:<br />
<code>File >> Load Only</syntaxhighlight><br />
</li><br />
<li><br />
Visualizar a rede a ser implementada:<br />
<code>File >> Graph</syntaxhighlight><br />
</li><br />
<li> <br />
Executar a configuração:<br />
<code>Network >> Start</syntaxhighlight><br />
</li><br />
<li><br />
Verificar o estado de todas interfaces (se UP ou DOWN) com:<br />
<code>ifconfig -a</syntaxhighlight><br />
<code>ip addr</syntaxhighlight> <br />
Note que nas últimas versões do Linux o comando ip vem sendo recomendado (embora o ifconfig ainda esteja disponível).<br />
</li><br />
<li><br />
Vamos configurar as interfaces. Para tanto vamos assumir que teremos duas sub-redes:<br />
<code>lan0 - endereço da rede 10.10.10.0/24</syntaxhighlight><br />
<code>lan1 - endereço da rede 20.20.20.0/24</syntaxhighlight><br />
A interface eth0 de PC1 receberá o endereço 10.10.10.1/24 e a interface eth0 de PC2 recebera 10.10.10.2/24. A interface do roteador NA lan0 também deve receber um endereço: 10.10.10.254/24:<br />
<br />
No PC1:<br />
<code>ifconfig eth0 10.10.10.1/24</syntaxhighlight><br />
No PC2:<br />
<code>ifconfig eth0 10.10.10.2/24</syntaxhighlight><br />
No R1:<br />
<code>ifconfig eth0 10.10.10.254/24</syntaxhighlight><br />
</li> <br />
<li><br />
Seguindo a mesma lógica configure as máquinas e o roteador na lan1<br />
</li><br />
<li> Um ponto importante a ser lembrado é que quando uma interface é configurada com um número IP, a tabela de roteamento do sistema é alimentada com o número correspondente da rede associada ao número. Isto pode ser observado em TODAS as máquinas, inclusive no roteador:<br />
<code> route -n </syntaxhighlight><br />
ou <br />
<code> ip route </syntaxhighlight><br />
</li><br />
</ol><br />
<br />
==Camada IP no Linux: verificando e configurando rotas - configuração da rota default ==<br />
<br />
<ol><br />
<li> Um ponto importante a ser lembrado é que quando uma interface é configurada com um número IP, a tabela de roteamento do sistema é alimentada com o número correspondente da rede associada ao número. Isto pode ser observado em TODAS as máquinas, inclusive no roteador:<br />
<code> route -n </syntaxhighlight><br />
ou <br />
<code> ip route </syntaxhighlight><br />
Esta informação é importante pois define a entrega DIRETA de pacotes na rede, ou seja, se PC1 quiser enviar um pacote para PC2, esta linha na tabela de roteamento garante que o pacote IP seja despachado diretamente para o PC2 através de um frame ETHERNET endereçado para o MAC do PC1.<br />
</li><br />
<li> Confira os endereços MAC e IP das interfaces dos PC1 e PC2 e anote. Faça um ping no PC1 em direção a PC2.<br />
<code>root@pc1:~# ping 10.10.10.2</syntaxhighlight><br />
</li><br />
<li> Use um capturador de pacotes em modo texto para observar o tráfego na eth0 do PC2. Observe os endereços MAC do Frame Ethernet e os endereços IP do pacote IP.<br />
<code>root@pc2:~# tcpdump -i eth0 -e</syntaxhighlight><br />
ENTÃO? O que se pode concluir? É uma entrega direta ou indireta? <br />
</li><br />
<li> Uma curiosidade. Tente observar o tráfego na interface eth0 do Roteador R1. É possível observar algo? O que se pode concluir? Pare agora o ping e os tcpdumps executados.<br />
</li><br />
<li> Qualquer máquina IP acaba tomando uma decisão de roteamento. O PC1, ao observar que PC2 está na sua própria rede 10.10.10.0/24, entrega diretamente o pacote. E se PC1 tentar entregar para PC3? Faça um ping e observe o que acontece:<br />
<code>root@pc1:~#ping 20.20.20.1</syntaxhighlight><br />
Não deve ter funcionado :-(<br />
Um primeiro problema é que simplesmente a camada IP observa que o endereço não é entrega DIRETA mas não tem informação (linha) na tabela de roteamento dizendo para quem deve ser entregue o pacote. <br />
</li><br />
<li> Vamos acrescentar uma linha na tabela de PC1 dizendo como fazer esta entrega INDIRETA. Usaremos o conceito de gateway default. Ou seja, se não tiver para quem entregar explicitamente, o pacote será entregue para o gateway default:<br />
<code>root@pc1:~# route add default gateway 10.10.10.254</syntaxhighlight><br />
confira o estabelocimento da rota:<br />
<code>root@pc1:~# route -n</syntaxhighlight><br />
tente o ping novamente escutando com o tcpdump na interface eth0 de R1. Ainda não funcionou mas o R1 já recebe os pacotes. Confira o MAC de destino do pacote. Deve ser o MAC do roteador. <br />
</li> <br />
<li><br />
POR QUE NÃO FUNCIONOU: será que R1 não sabe como entregar o pacote para PC3? Confira se o pacote sai de R1 na rede lan1:<br />
<code>root@r1:~# tcpdump -i eth2 -e</syntaxhighlight><br />
</li> <br />
<li><br />
Temos um problema ainda que o nosso roteador Linux NÃO está habilitado a ser roteador. Isto pode ser feito com:<br />
<code>echo 1 > /proc/sys/net/ipv4/ip_forward</syntaxhighlight><br />
</li> <br />
<li> Tente novamente o ping de PC1 para PC3. Ainda não funcionará mas escute a interface eth1 de R1 e a interface eth0 de PC3 e verá que os pacotes do ICMP REQUEST estão chegando. Confira inclusive os MACs envolvidos...<br />
</li><br />
<li><br />
O que estaria faltando ainda para que PC3 responda aos ECHO REQUEST? O problema é de entrega indireta. O PC3 não sabe como entregar pacotes "externos". Acrescente um gateway default.<br />
</li><br />
<li><br />
Exercício adicional com 2 roteadores. Ver manual:<br />
* [http://linux-ip.net/html Guia de Administração da Camada IP no Linux<br />
</li><br />
</ol><br />
<br />
==Exercício: acrescentando uma lan2 com com 2 PCs no roteador==<br />
<br />
Acrescente uma rede 30.30.30.0/24 (lan2) no roteador R1. Acrescente 2 PCs e configure o sistema.<br />
Teste a conectividade entre todos os PCs.<br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
pc5[type]=generic<br />
pc6[type]=generic<br />
<br />
pc7[type]=generic<br />
pc8[type]=generic<br />
<br />
<br />
#Definição da Topologia da Rede<br />
<br />
pc1[eth0]=lan0:ip=10.10.10.1/24<br />
pc1[default_gateway]=10.10.10.254<br />
<br />
pc2[eth0]=lan0:ip=10.10.10.2/24<br />
pc2[default_gateway]=10.10.10.254<br />
<br />
pc3[eth0]=lan1:ip=20.20.20.1/24<br />
pc3[default_gateway]=20.20.20.254<br />
<br />
pc4[eth0]=lan1:ip=20.20.20.2/24<br />
pc4[default_gateway]=20.20.20.254<br />
<br />
pc5[eth0]=lan2:ip=30.30.30.1/24<br />
pc5[default_gateway]=30.30.30.254<br />
<br />
pc6[eth0]=lan2:ip=30.30.30.2/24<br />
pc6[default_gateway]=30.30.30.254<br />
<br />
pc7[eth0]=lan4:ip=40.40.40.1/24<br />
pc7[default_gateway]=40.40.40.254<br />
<br />
pc8[eth0]=lan3:ip=50.50.50.1/24<br />
pc8[default_gateway]=40.40.40.254<br />
<br />
<br />
r1[eth0]=lan0:ip=10.10.10.254/24<br />
r1[eth1]=lan1:ip=20.20.20.254/24<br />
r1[eth2]=lan2:ip=30.30.30.254/24<br />
r1[eth3]=lan3:ip=50.50.50.253/24<br />
r2[eth1]=lan3:ip=50.50.50.254/24<br />
r2[eth0]=lan4:ip=40.40.40.254/24<br />
<br />
r2[route]=10.10.10.0/24:gateway=50.50.50.253<br />
<br />
</syntaxhighlight><br />
<br />
=AULA 15 - Dia 7/05/2019=<br />
<br />
*Hubs X Switches. O Papel do Protocolo ARP<br />
<br />
<br />
*Serviço DHCP e NAT<br />
[-] Laboratório 16 - Sub-redes e Roteamento Estático em Redes <br />
<br />
==Hubs, Switches. Protocolo ARP==<br />
<br />
[Laboratório 17 - Tecnologia de Enlace Ethernet]<br />
<br />
==Serviço DHCP==<br />
<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IP_DHCP_NAT.pdf DHCP e NAT]<br />
<br />
Construir uma rede simular a aula anterior mas deixar PC1 e PC2 desconfigurados. Criar uma máquina para atuar como servidor DHCP. <br />
<br />
<ol><br />
<li><br />
Editar o arquivo de configuração do dhcp server:<br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=gateway #já habilitado para forward<br />
<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
pcdhcp[type]=generic<br />
<br />
<br />
#Definição da Topologia da Rede<br />
<br />
pc1[eth0]=lan0 #desconfigurada...<br />
<br />
pc2[eth0]=lan0:ip=10.10.10.2/24<br />
pc2[default_gateway]=10.10.10.254<br />
<br />
pcdhcp[eth0]=lan0:ip=10.10.10.3/24<br />
pcdhcp[default_gateway]=10.10.10.254 <br />
<br />
pc3[eth0]=lan1:ip=20.20.20.1/24<br />
pc3[default_gateway]=20.20.20.254<br />
<br />
pc4[eth0]=lan1:ip=20.20.20.2/24<br />
pc4[default_gateway]=20.20.20.254<br />
<br />
<br />
r1[eth0]=lan0:ip=10.10.10.254/24<br />
r1[eth1]=lan1:ip=20.20.20.254/24<br />
<br />
</syntaxhighlight><br />
</li><br />
<li> No server estabelecer a configuração desejada:<br />
<br />
nano /etc/dhcp/dhcpd.conf<br />
<br />
com:<br />
<br />
<code><br />
<br />
subnet 10.10.10.0 netmask 255.255.255.0 {<br />
range 10.10.10.10 10.10.10.50;<br />
option routers 10.10.10.254;<br />
option broadcast-address 10.10.10.255;<br />
default-lease-time 600;<br />
max-lease-time 7200;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
</li><br />
<li><br />
Rodar o servidor DHCP na máquina pc_dhcp:<br />
<code><br />
/usr/sbin/dhcpd -q -4 -pf /run/dhcp-server/dhcpd.pid -cf /etc/dhcp/dhcpd.conf eth0<br />
</syntaxhighlight><br />
</li><br />
<li><br />
No cliente (PC1) fazer:<br />
<code><br />
dhclient -v eth0<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Usando o ifconfig e route confira se o PC1 está completamente configurado. Faça teste com o ping<br />
</li><br />
<li> Rode o tcpdump na eth0 de r1 para "verificar" os pacotes DHCP:<br />
<code><br />
tcpdump -i eth0<br />
</syntaxhighlight><br />
</li><br />
<li> Repetir a operação no PC2. Baixe a interface antes:<br />
<code><br />
ifconfig eth0 down<br />
dhclient -v eth0<br />
</syntaxhighlight><br />
</li><br />
</ol><br />
<br />
==O NAT==<br />
<br />
Vamos tentar elaborar um laboratório usando o NAT MASQUERADE<br />
https://www.karlrupp.net/en/computer/nat_tutorial<br />
<br />
Construir uma rede com 3 LANs e 2 roteadores como na aula passada. Executar o APACHE em uma máquina da lan3 (exemplo PC4). Não colocar rotas para lan0 em r2. Desta forma PC1 não deve pingar em PC4. <br />
<br />
<code><br />
LAN0 <-R1-> LAN1 <-R2 -> LAN3<br />
</syntaxhighlight><br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
pc1[type]=generic<br />
apache[type]=generic<br />
<br />
<br />
pc1[eth0]=lan0:ip=10.10.10.1/24<br />
pc1[default_gateway]=10.10.10.254<br />
<br />
<br />
r1[eth0]=lan0:ip=10.10.10.254/24<br />
r1[eth1]=lan1:ip=20.20.20.254/24<br />
r1[route]=30.30.30.0/24:gateway=20.20.20.253<br />
<br />
r2[eth0]=lan1:ip=20.20.20.253/24<br />
r2[eth1]=lan2:ip=30.30.30.254/24<br />
<br />
apache[eth0]=lan2:ip=30.30.30.1/24<br />
apache[default_gateway]=30.30.30.254<br />
</syntaxhighlight><br />
<br />
<ol><br />
<li> Rodar o apache em PC4:<br />
<code> /etc/init.d/apache2 start </syntaxhighlight><br />
</li><br />
<li> Testar se o Apache é acessível a partir de PC3<br />
<code>lynx END_PC3 </syntaxhighlight><br />
<li><br />
Em R1 fazer:<br />
<code>iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE</syntaxhighlight><br />
</li><br />
<li> Monitorar os pacotes que chegam e saem da eth0 de PC4.<br />
</li><br />
<li> Fazer em PC1:<br />
lynx END_PC4 #endereço de PC4.<br />
O que se pode concluir?<br />
</li><br />
<br />
</ol><br />
<br />
=AULA 16 - Dia 09/05/2019=<br />
*Endereçamento IPv4.<br />
*Exercícios segmentação Redes. <br />
<br />
===Objetivos===<br />
*Compreender endereçamento IPv4.<br />
*Compreender o processo de alocação de faixas de IPs.<br />
*Compreender e manipular os números IPs.<br />
*Compreender e manipular as máscaras de rede.<br />
*Proporcionar ao aluno uma visão prática de roteamento IP.<br />
<br />
===Fonte Básica===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IP_DHCP_NAT.pdf DHCP e NAT]<br />
*[http://www.davidc.net/sites/default/subnets/subnets.html Cálculo de sub-redes]<br />
<br />
===Roteiro===<br />
<br />
#Baseado no arquivo exemplo abaixo, crie um arquivo de configuração para o NetKit que implemente sua proposta. O arquivo deve contemplar todas as configurações necessárias para o perfeito funcionamento da rede, ou seja, ao carregar o arquivo todos os hosts deverão ser capazes de "pingar" uma ao outro. <br />
##Faça testes de conectividade entre os hosts.<br />
##Demonstre para o professor o perfeito funcionamento de sua rede.<br />
*O arquivo de configuração do Netkit abaixo, é a definição para o funcionamento da simulação da rede apresentada na Figura 2. Falta adicionar as rotas.<br />
<br />
[[Arquivo:DynamicRoutingTriangle.png |thumb | 400px| Figura 2 - Rede exemplo]]<br />
<br />
<code><br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=link0:ip=192.168.0.1/24<br />
pc2[eth0]=link1:ip=192.168.1.1/24<br />
pc3[eth0]=link2:ip=192.168.2.1/24<br />
<br />
# Default gateways definitions<br />
pc1[default_gateway]=192.168.0.254<br />
pc2[default_gateway]=192.168.1.254<br />
pc3[default_gateway]=192.168.2.254<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
r3[type]=gateway<br />
<br />
# Routers' interfaces to local networks<br />
r1[eth0]=link0:ip=192.168.0.254/24<br />
r2[eth0]=link1:ip=192.168.1.254/24<br />
r3[eth0]=link2:ip=192.168.2.254/24<br />
<br />
# Network "backbone" links<br />
r1[eth1]=backbone0:ip=10.0.0.1/30<br />
r1[eth2]=backbone1:ip=10.0.1.1/30<br />
<br />
r2[eth1]=backbone0:ip=10.0.0.2/30<br />
r2[eth2]=backbone2:ip=10.0.2.1/30<br />
<br />
r3[eth1]=backbone1:ip=10.0.1.2/30<br />
r3[eth2]=backbone2:ip=10.0.2.2/30 <br />
<br />
# Routes definition<br />
r1[route]=192.168.2.0/24:gateway=10.0.1.2<br />
r1[route]=192.168.1.0/24:gateway=10.0.0.2<br />
r1[route]=10.0.2.0/30:gateway=10.0.0.2<br />
<br />
r2[route]=192.168.0.0/24:gateway=10.0.0.1 <br />
r2[route]=192.168.2.0/24:gateway=10.0.2.2<br />
r2[route]=10.0.1.0/30:gateway=10.0.2.2<br />
<br />
r3[route]=192.168.0.0/24:gateway=10.0.1.1<br />
r3[route]=192.168.1.0/24:gateway=10.0.2.1<br />
r3[route]=10.0.0.0/30:gateway=10.0.2.1<br />
</syntaxhighlight><br />
<br />
===Exercícios Extras (resolvidos)===<br />
*[[Arquivo:exercicios_CIDR.pdf]]<br />
<br />
===Referencia===<br />
*[http://www.davidc.net/sites/default/subnets/subnets.html Link Calculador Online de Subnets]<br />
<br />
=AULA 17 - Dia 14/05/2019=<br />
<br />
*Finalização do Laboratório do NAT<br />
*Laboratório de Introdução ao IPV6<br />
*Introdução ao Access Point TPLINK N750: configuração da LAN e WAN<br />
<br />
==LAboratório de Introdução ao IPv6==<br />
<br />
===Material de REferência===<br />
<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IPv6.pdf IPv6]<br />
<br />
===Roteiro de atividades sobre o IPv6===<br />
<br />
A figura abaixo apresenta o diagrama esquemático da rede a ser montada/analisada. Observe que todos os IPv6 ''Global Unicast'' já estão definidos na mesma, são esses IPs que utilizaremos em nosso experimento.<br />
<br />
[[Arquivo:Diagrama_rede_IPv6.jpg]]<br />
<br />
#Crie em seu computador um arquivo com nome '''/home/aluno/IPv6.conf''', com o seguinte conteúdo: <syntaxhighlight lang=bash><br />
#Ligacao das maquinas nos dominios de colisao<br />
#Duas pequenas redes interligadas pelo backbone<br />
<br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=link0:ipv6=2001:bcc:faca:1::101/64<br />
pc2[eth0]=link1:ipv6=2001:bcc:cafe:1::102/64<br />
pc3[eth0]=HUB1:ipv6=2001:bcc:1f0:1::103/64<br />
pc4[eth0]=HUB1<br />
<br />
#Default Gateways definitions<br />
pc1[route]=default6:gateway=2001:bcc:faca:1::1<br />
pc2[route]=default6:gateway=2001:bcc:cafe:1::1<br />
pc3[route]=default6:gateway=2001:bcc:1f0:1::1<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
#Routers interfaces definitions<br />
r1[eth0]=backbone0:ipv6=2001:db8:dead:1::1/64<br />
r1[eth1]=link0:ipv6=2001:bcc:faca:1::1/64<br />
r1[eth2]=link1:ipv6=2001:bcc:cafe:1::1/64<br />
<br />
r2[eth0]=backbone0:ipv6=2001:db8:dead:1::2/64<br />
r2[eth1]=HUB1:ipv6=2001:bcc:1f0:1::1/64<br />
<br />
#Routers definitions<br />
r1[route]=2001:bcc:1f0:1::0/64:gateway=2001:db8:dead:1::2<br />
r2[route]=2001:bcc:faca:1::0/64:gateway=2001:db8:dead:1::1<br />
r2[route]=2001:bcc:cafe:1::0/64:gateway=2001:db8:dead:1::1<br />
</syntaxhighlight><br />
#Tenha certeza que o Netkit2 estja atualizado: General >> Update.<br />
#Rode o NetKit em seu computador. Em um terminal digite: <syntaxhighlight lang=bash><br />
netkit2 & </syntaxhighlight><br />
#No menu '''File''' - '''Load and Run''', procure o arquivo '''/home/aluno/IPv6.conf''' e clique em OK. Abrirá uma janela com 6 abas, onde cada uma delas é um terminal de configuração do respectivo equipamento: '''pc1-4''' ou '''r1-2'''.<br />
#Observe que o '''pc4''' não está com sua interface configurada.<br />
#Ao clicar no menu '''File''' - '''Graph''', pode-se ter uma visão da rede a ser simulada e conferir se é equivalente ao diagrama proposto.<br />
#Faça um '''ping6''' entre o '''pc1''' ao '''pc3''': <syntaxhighlight lang=bash><br />
ping6 -c4 2001:bcc:1f0:1::103 </syntaxhighlight><br />
#Faça um '''ping6''' entre o '''pc1''' e '''pc2'''.<br />
#No '''pc4''' use o seguinte comando para adicionar o endereço IPv6 à interface de rede: <syntaxhighlight lang=bash><br />
ip addr add 2001:bcc:1f0:1::104/64 dev eth0 </syntaxhighlight><br />
#No '''pc4''', acrescente o ''default gateway'' com o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add default via 2001:bcc:1f0:1::1 dev eth0 </syntaxhighlight><br />
#No '''pc1''' use o seguinte comando para verificar como ficou a configuração dos endereços da interface de rede. O resultado é similar ao apresentado pelo comando '''ifconfig''': <syntaxhighlight lang=bash><br />
ip addr show dev eth0 </syntaxhighlight><br />
#Todo o roteamento está pronto, mas caso desejássemos poderíamos acrescentar rotas com comando similares aos já utilizados. Por exemplo, no '''r1''', para adicionar uma rota estática para a rede dos '''pc3''' e '''pc4''' utilizaríamos o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add 2001:bcc:1f0:1::/64 via 2001:db8:dead:1::2 dev eth0 </syntaxhighlight><br />
#Confira as rotas estabelecidas em todos os ''hosts'' com o comando abaixo. <br />
##São coerentes com os dados apresentados no diagrama acima?<syntaxhighlight lang=bash><br />
ip -6 route show </syntaxhighlight><br />
#No '''pc1''' use os seguintes comandos para ver a rota para alguns vizinhos: <syntaxhighlight lang=bash><br />
traceroute6 2001:bcc:1f0:1::103<br />
traceroute6 2001:bcc:1f0:1::104 </syntaxhighlight><br />
#*Anote as rotas.<br />
#Deixe um '''ping6''' entre o '''pc1''' ao '''pc3''' rodando: <syntaxhighlight lang=bash><br />
ping6 2001:bcc:1f0:1::103 </syntaxhighlight><br />
<br />
==Introdução ao Roteador-AP da TP-Link==<br />
<br />
Ver manual https://www.tp-link.com/us/support/download/tl-wdr4300/<br />
<br />
===Configuração Básica===<br />
<br />
Seguir as instruções do professor para a seguinte configuração:<br />
<br />
#Retirar o plugue cabo ethernet que liga o PC do Lab a rede do IFSC. Conectar o PC a uma das portas LAN do AP;<br />
#Conectar a WAN do AP ao Lab. do IFSC;<br />
#Em um terminal do PC aplique o comando:<br />
sudo dhclient eth0<br />
#No browser do PC acesse o AP colocando o endereço:<br />
http://tplinklogin.net<br />
#Entrar com user admin e senha admin<br />
#Configurar a WAN para DHCP (IP dinâmico)<br />
#Configurar a LAN para DHCP na faixa 192.168.0.10 a 192.168.0.100<br />
#Usar uma máquina virtual para testar a aquisição do IP:<br />
pc1[type]=generic<br />
pc1[eth0]=uplink:bridge=eth0<br />
<br />
DESAFIO 1: Elabore um experimento para mostrar que a LAN do AP funciona como um switch.<br />
Sugestão: Use uma máquina adicional colocada em uma porta do AP.<br />
<br />
DESAFIO 2: Elabore um experimento para mostrar como o NAT funciona no AP. Se inspire no experimento realizado sobre o NAT.<br />
<br />
=AULA 18 - Dia 16/05/2019=<br />
<br />
==Objetivos==<br />
<br />
<br />
PARTE 0 - Exercício de Revisão<br />
<br />
PARTE 1 - Serviços de rede sobre o Linux<br />
<br />
*serviço SSH no Linux<br />
<br />
PARTE 2 - Acesso a rede WIFI<br />
<br />
*conceitos básicos de redes sem fio: pg.103 de [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo]<br />
*configuração da WIFI no Access Point e Acesso via Linux<br />
<br />
===PARTE 0===<br />
<br />
Considere a rede abaixo definida pelo arquivo do netkit. Configure as redes com os seguintes prefixos:<br />
<br />
*lan0: 50.50.50.0/24<br />
*lan1: 60.60.60.0/24<br />
*lan2: 70.70.70.0/24<br />
<br />
O pc2dhcp deve ser configurado como servidor DHCP e deverá liberar IPs na faixa de 50.50.50.100/24 a 50.50.50.200/24. Todos os PCs receberão IP estáticos com exceção do PC1 que deverá receber dinamicamente o endereço. Toda a configuração deve ser realizada manualmente.<br />
<br />
Teste a conectividade entre todos os PCs. Usando o tcpdump demonstre que quando PC2 faz um ping em PC4 a entrega será indireta. Demonstre usando o MAC address das máquinas como apoio. Chame o professor para demonstrar.<br />
<br />
ALGUNS COMANDOS NOTÁVEIS:<br />
<br />
ifconfig<br />
ifconfig eth0 10.10.10.1/24<br />
route -n<br />
route add default gw 200.10.1.254<br />
route del -net 200.10.1.0/24 gw 200.10.2.1<br />
route add -net 200.10.1.0/24 gw 200.10.2.1<br />
<br />
tcpdump -i eth1 -n -e<br />
<br />
<code><br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2dhcp[type]=generic<br />
<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=lan0<br />
pc2dhcp[eth0]=lan0<br />
<br />
pc3[eth0]=lan1<br />
<br />
pc4[eth0]=lan2<br />
<br />
r1[eth0]=lan0<br />
r1[eth1]=lan1<br />
<br />
r2[eth0]=lan1<br />
r2[eth1]=lan2<br />
</syntaxhighlight><br />
<br />
Solução:<br />
R1:<br />
ifconfig eth0 50.50.50.254/24<br />
ifconfig eth1 60.60.60.254/24<br />
route add -net 70.70.70.0/254 gw 60.60.60.253<br />
R2:<br />
ifconfig eth1 70.70.70.254/24<br />
ifconfig eth0 60.60.60.253/24<br />
route add -net 50.50.50.0/24 gw 60.60.60.254<br />
PC2DHCP:<br />
ifconfig eth0 50.50.50.2/24<br />
route add default gateway 50.50.50.254<br />
configurar server: nano /etc/dhcp/dhcpd.conf<br />
# A slightly different configuration for an internal subnet.<br />
subnet 50.50.50.0 netmask 255.255.255.0 {<br />
range 50.50.50.100 50.50.50.200;<br />
# option domain-name-servers ns1.internal.example.org;<br />
# option domain-name "internal.example.org";<br />
option routers 50.50.50.254;<br />
option broadcast-address 50.50.50.255;<br />
default-lease-time 600;<br />
max-lease-time 7200;<br />
}<br />
<br />
/usr/sbin/dhcpd -q -4 -pf /run/dhcp-server/dhcpd.pid -cf /etc/dhcp/dhcpd.conf eth0<br />
PC3:<br />
ifconfig eth0 60.60.60.1/24<br />
route add default gw 60.60.60.254 #note que poderia ser para o outro roteador (R2)<br />
PC4:<br />
ifconfig eth0 70.70.70.1/24<br />
route add default gw 70.70.70.254<br />
PC1:<br />
dhclient eth0 -v<br />
<br />
==Serviço SSH==<br />
<br />
O Serviço SSH se utiliza do modelo cliente-servidor. Deve-se executar um servidora ssh na máquina que permitirá o acesso remoto.<br />
Um cliente a partir de uma outra máquina poderá logar remotamente usando um cliente ssh ou poderá fazer outras operações, tipo cópia remota<br />
de arquivos.<br />
<br />
===ETAPA 1 - Rodando o servidor SSH===<br />
*Baseado no Material do Prof.Odilson Valle<br />
<br />
No Ubuntu server:<br />
<ol><br />
<li><br />
<code>sudo su</syntaxhighlight><br />
<code>apt-get update</syntaxhighlight><br />
<code>apt-get install ssh</syntaxhighlight> O SSH já estará funcionando normalmente.<br />
Para configurações extras deve-se editar o arquivo /etc/ssh/sshd_config e acrescentar, por exemplo:<br />
*X11Forwarding yes (no) ### habilita/desabilita acesso com ambiente gráfico remoto<br />
*AllowUsers Fred Wilma ### Libera o acesso somente para os usuários Fred e Wilma<br />
*DenyUsers Dino Pebbles ### Bloqueia o acesso aos usuários Dino e Pebbles e libera para os demais usuários<br />
*AllowGroups admin ### Libera o acesso somente para o grupo admin.<br />
</li><br />
<li><br />
Após modificar o arquivo de configuração deve-se reiniciar o serviço: <code>service ssh restart</syntaxhighlight><br />
</li><br />
<li><br />
Criar um usuário na máquina servidora:<br />
<code>adduser alien</syntaxhighlight><br />
</li><br />
<li><br />
Logar como alien:<br />
<code>su alien</syntaxhighlight><br />
</li><br />
</ol><br />
<br />
===ETAPA 2 - Logando remotamente===<br />
<br />
<ol><br />
<li><br />
Para acessar o servidor basta digitar em um terminal: <br />
<code>ssh alien@ip_do_servidor. </syntaxhighlight> Será solicitado a senha.<br />
</li><br />
<li><br />
Confira que está "dentro" da máquina remota:<code>hostname</syntaxhighlight><br />
</li><br />
<li><br />
Confira os arquivos do diretório corrente:<code>ls -l</syntaxhighlight><br />
</li><br />
</ol><br />
<br />
<br />
===ETAPA 3 - Cópia Remota de aquivos===<br />
<br />
#Na máquina hospedeira/cliente, EM OUTRO TERMINAL, criar um arquivo qualquer usando um editor de texto:<code>gedit teste.txt &</syntaxhighlight><br />
#Envie o arquivo para a máquina servidora: <code>scp teste.txt alien@IP_MAQUINA_SERVIDORA:./</syntaxhighlight><br />
#No terminal onde está logado remotamente confira se o arquivo está copiado: <code>ls -l</syntaxhighlight><br />
#Mude o nome do arquivo: <code>mv teste.txt alfat.txt</syntaxhighlight><br />
#No terminal da máquina cliente traga novamente o arquivo: <code>scp alien@IP_MAQUINA_SERVIDORA:./alfa.txt .</syntaxhighlight><br />
#Confira se o arquivo foi copiado corretamente: <code>ls -l</syntaxhighlight><br />
<br />
==PARTE 2 - Configuração do Access Point na rede de 2.4Ghz==<br />
<br />
#Entrar na configuração do AP conforme aula anterior.<br />
#Conectara a WAN do AP na rede do laboratório e o PC em uma porta da LAN do AP.<br />
#Configurar a WAN para IP dinâmico.<br />
#Configurar a rede WIreless 2.4 Ghz:<br />
##Nome SSID: nome FIC-NomeAluno<br />
##Configurar canal AUTO e channel width para AUTO<br />
##Habilite o broadcast da rede.<br />
#Configurar segurança (Wireless Security) para WPA versão Automática, Criptografia AES e password ABCDEF<br />
#Configurar o DHCP na LAN para distribuir endereços entre 192.168.0.100 e 192.168.0.200<br />
#Salve as configurações<br />
#Reboote o roteador<br />
<br />
==Acessando a rede de dispostivo Celular==<br />
<br />
#Teste o acesso a rede a partir de um celular. No Androi ligue e desligue o wifi. Deve aparecer a lista de dispositivos.<br />
<br />
==Habilitando Filtros por MAC==<br />
<br />
*Na configuração da WLAN entre em Wireless MAC Filtering<br />
*Em Filtering Rules coloque Deny (negar)<br />
*Adicione um terminal que deseja bloquear o acesso. Utilize o MAC do seu celular (veja em configurações do telefone ou anote na opção Wireless Statistics)<br />
*Habilite o Filtro e tente se conectar<br />
<br />
OBS: Este filtro é interessante para ter maior segurança na rede, garantindo que somente dispositivos gabilitados possam acessá-la.<br />
<br />
==Coloque no ar a rede 5Ghz==<br />
<br />
Repita o procedimento da rede de 2.4Ghz e coloque-a no ar.<br />
<br />
Teste a conectividade com o celular.<br />
<br />
<br />
<br />
=AULA 19 - Dia 21/05/2019=<br />
<br />
==Objetivos==<br />
<br />
*Tópicos Adicionais sobre redes no Linux: Configuração Manual X NetworkManager<br />
**Opções de Acesso a Internet: ADSL, Cabo<br />
**Sistema de Arquivos em Rede: Samba Server<br />
*Relatório de Avaliação 1<br />
*Opções de Extensão da Rede Wireless<br />
<br />
==Tópicos Adicionais sobre redes no Linux==<br />
<br />
===Configuração da Rede no Linux - o NetworkManager===<br />
<br />
Ao longo do curso estudamos vários comandos para ver e modificar parâmetros de rede. Entretanto, em uma instalação padrão de um sistema Linux Ubuntu vamos verificar que existe um serviço de suporte a estas configurações que permite configurar interfaces graficamente e reconectar/escolher uma rede. Trata-se do NetworkManager. Ver alguns detalhes aqui [https://www.hardware.com.br/dicas/entendendo-networkmanager.html] e aqui[https://wiki.debian.org/pt_BR/NetworkManager]. Este serviço tenta fornecer a melhor conectividade possível usando as interfaces disponíveis. O serviço é composto por:<br />
<br />
*um processo do sistema (roda como serviço) monitorando constantemente as interfaces;<br />
*uma applet para interação com o usuário (canto direito da interface);<br />
<br />
O NetworkManager vai ignorar as configurações das interfaces realizadas em /etc/network/interfaces<br />
<br />
Teste o uso do NetworkManager. Clique no topo do desktop a direita e inspecione as interfaces disponíveis.<br />
<br />
Em algumas situações pode ser desejável desabilitar o NetworkManager. Na linha de comando pode ser executado:<br />
<br />
sudo service network-manager stop<br />
<br />
===Configurando interfaces de forma manual ===<br />
<br />
TEXTO baseado nas anotações do Prog.Marcelo Sobral:<br />
<br />
O arquivo ''/etc/network/interfaces'' contém declarações para configurar as interfaces de rede. Um exemplo de configuração básica contida nesse arquivo pode ser vista a seguir:<br />
<br />
<syntaxhighlight lang=text><br />
auto lo eth0<br />
iface lo inet loopback<br />
iface eth0 inet dhcp<br />
</syntaxhighlight><br />
<br />
Esse exemplo pode ser interpretado assim:<br />
* ''Linha 1'': declara que as interfaces ''lo'' e ''eth0'' devem ser ativadas automaticamente no boot. Se uma interface não aparecer em uma declaração como esta, então ela não será ativada. OBS: interface ativadas desta forma NÃO são controladas pelo ''NetworkManager''.<br />
* ''Linha 2'': configura a interface ''lo'' como sendo do tiupo ''loopback''. Essa é uma interface especial criada puramente em software (uma interface de rede virtual), usada para comunicação entre processos de um mesmo computador.<br />
* ''Linha 3'': configura a interface ''eth0'' de forma dinâmica usando [[GER-2010-1#DHCP|DHCP]]. A configuração de rede é solicitada usando a própria rede. Ness ecaso, deve existir algum equipamento ou computador nessa rede que seja um servidor DHCP, capaz de responder com uma mensagem contendo a configuração de rede a ser utilizada.<br />
<br />
<br />
O exemplo anterior é bastante simplificado, uma vez que a configuração de rede de fato é obtida dinamicamente com DHCP. Isso pode ser suficiente para computadores usados somente para acesso a Internet, mas não para computadores que sejam servidores. Nesse caso, é melhor definir uma configuração de rede estática, como mostrado a seguir:<br />
<br />
<syntaxhighlight lang=text><br />
auto lo eth0<br />
iface lo inet loopback<br />
iface eth0 inet static<br />
address 172.18.80.251<br />
netmask 255.255.128.0<br />
gateway 172.18.0.254<br />
dns-nameservers 191.36.8.2 191.36.8.3<br />
</syntaxhighlight><br />
<br />
<br />
A diferença em relação ao caso anterior está na declaração da interface ''eth0''. Ao invés de configurá-la com ''DHCP'', declararam-se todas as informações de rede. Assim, essa interface sempre será ativada com essas informações configuradas. No exemplo apresentado, as configurações de rede são:<br />
* ''address 172.18.80.251'': endereço IP da interface<br />
* ''netmask 255.255.128.0'': máscara de rede<br />
* ''gateway 172.18.0.254'': endereço do gateway (ou roteador ''default'')<br />
* ''dns-nameservers 191.36.8.2 191.36.8.3'': servidores DNS a serem utilizados (podem-se especificar um ou mais endereços IP)<br />
<br />
O [http://manpages.ubuntu.com/manpages/trusty/en/man5/interfaces.5.html manual do arquivo /etc/network/interfaces] apresenta muitos outros detalhes sobre possíveis configurações de rede.<br />
<br />
Antes da alteração de configuração de uma interface é interessante desativá-la:<br />
ifdown eth0<br />
Alterar o arquivo /etc/network/interfaces<br />
<br />
E na sequência ativá-la novamente:<br />
ifup eth0<br />
ou<br />
sudo /etc/init.d/networking restart<br />
<br />
O comando ifup vai consultar o arquivo e alterar as configurações. Indiretamente, o script networking também usa o ifup para ativar as configurações (e todas demais que forem realizadas).<br />
<br />
==Relatório Avaliativo 1==<br />
<br />
Criar um arquivo no OpenOffice nomeando-o SeuNomeSemEspaco-FICLinux-2019-A1<br />
<br />
Copiar e responder as questões abaixo:<br />
<br />
1.Faça um ifconfig na interface eth0. Cole um recorte da tela no espaço abaixo e faça um texto indicando qual o endereço de hardware associado a esta interface, qual o endereço IPv4 e qual a máscara de subrede.<br />
<br />
<br />
2.Faça um experimento usando o ping e o wireshark mostrando como o DNS atua para resolver o nome que está sendo "pingando". Informe em texto abaixo qual o IP do servidor DNS local e qual o IP do site que está sendo "pingado".<br />
<br />
<br />
3,Execute o laboratório do Netkit da forma e cole abaixo a figura da rede fornecida pelo netkit:<br />
<code><br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
<br />
# Hosts' interfaces to local routers<br />
<br />
r1[eth0]=lan0<br />
r1[eth1]=lan1<br />
<br />
pc1[eth0]=lan0<br />
pc2[eth0]=lan0<br />
pc3[eth0]=lan1<br />
</syntaxhighlight><br />
<br />
<br />
4.Configure todas as interfaces dos PC usando para lan0 o prefixo 50.50.50.0/24 e para lan1 use no lugar de 50 o dia de seu nascimento.<br />
Cole uma tela mostrando PC1 pingando PC3. <br />
<br />
5.Informe abaixo o MAC da eth0 do roteador.<br />
<br />
6.Usando o tcpdump na eth0 do roteador mostre que a entrega é indireta.<br />
<br />
==Estendendo a rede através da LAN usando segundo AP e WAN==<br />
<br />
Conecte um segundo AP (WAN do segundo AP a LAN do primeiro AP). Teste a conectividade colocando uma máquina Linux na LAN do segundo AP.<br />
Esta configuração deve funcionar mas impõe um overhead adicional devido ao NAT realizado duas vezes... <br />
<br />
DESAFIO: mostrar que o NAT está sendo duplicado.<br />
<br />
[[Arquivo:WLAN-2PAs-viaWAN.png]]<br />
<br />
==Estendendo a rede através da LAN usando segundo AP e LAN==<br />
<br />
Discuta com o colega ao lado e pense como poderia conectar o segundo AP via LAN. Uma configuração adicional será necessária.<br />
<br />
==Estendendo a rede através do Wireless (WDS)==<br />
<br />
Estude no manual como poderia estender a rede Sem Fio usando conexão via WDS.<br />
<br />
=AULA 20 - Dia 18/04/2019=<br />
<br />
*Tópicos Adicionais sobre redes no Linux:<br />
**Opções de Acesso a Internet: ADSL, Cabo<br />
**Sistema de Arquivos em Rede: Samba Server (http://www.guiafoca.org/cgs/guia/avancado/ch-s-samba.html)<br />
*Relatório Avaliativo 2<br />
<br />
==Relatório Avaliativo==<br />
<br />
===PARTE 1=== <br />
<br />
Usando a configuração abaixo do netkit2 e uma máquina Virtualbox devidamente configurada implementar a configuração abaixo:<br />
<br />
ATENÇÂO: Vamos substituir a VirtualBox por uma máquina Netkit executada em OUTRO PC com a configuração:<br />
<br />
INSTRUÇÔES para virtual box:<br />
*colocar rede como bridge<br />
*desabilitar o network manager<br />
sudo service network-manager stop<br />
*baixar a interface<br />
sudo ifconfig enp0s3 down<br />
*reconfigurar a interface (usar o endereço do seu grupo)<br />
sudo ifconfig enp0s3 50.50.50.11/24<br />
*colocar a rota direta (que se perdeu) (usar o endereço do seu grupo)<br />
sudo route add -net 50.50.50.0/24 dev enp0s3<br />
*colocar gateway default (usar o endereço do seu grupo)<br />
sudo route add default gateway 50.50.50.1<br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
<br />
pc1[type]=generic<br />
pc1[eth0]=uplink:bridge=eth0:ip=dhcp<br />
<br />
</syntaxhighlight><br />
<br />
<br />
[[Arquivo:Aval2-Parte1-FICLinux2019-2.png]]<br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
pc1[type]=generic<br />
<br />
pc1[eth0]=lan1<br />
<br />
r1[eth0]=uplink:bridge=eth0:ip=VER COM PROFESSOR<br />
r1[eth1]=lan2<br />
<br />
r2[eth0]=lan1<br />
r2[eth1]=lan2<br />
</syntaxhighlight><br />
<br />
Construir um doc conforme aula anterior com as seguintes informações:<br />
<br />
#Coloque a tela de um píng funcionando de R1 para PC1<br />
#Cole a tela da tabela de roteamento de R2<br />
#Cole a tela de um ping de uma máquina VirtualBox (netkit) no R1 (uplink)<br />
#Cole a tela de um ping funcionando uma máquina VirtualBox (netkit) no PC1<br />
<br />
Note que o gateway default da máquina virtual deverá ser reconfigurado para PC1.<br />
<br />
ADENDO: Coloque em R1 rotas para as redes dos PC1 dos demais grupos.<br />
<br />
===PARTE 2===<br />
<br />
Acrescente na sua rede um AP configurado como indicado abaixo:<br />
<br />
OBS: Para este exercício configuramos estaticamente todos os endereços para o lado do backbone (Laboratório). Usamos 50.50.50.0/24<br />
<br />
[[Arquivo:Aval2-Parte2-FICLinux2019-2.png]]<br />
<br />
<br />
=ATIVIDADE DE RECUPERAÇÃO 1=<br />
<br />
Refazer o relatório Avaliativo 1 proposto anteriormente. Enviar doc para o SIGA A<br />
<br />
=ATIVIDADE DE RECUPERAÇÃO 2=<br />
<br />
Registre em um DOC e faça um post no SIGA A colando a imagem das telas das saídas de cada comando!<br />
<br />
===Roteiro de atividades sobre o IPv6===<br />
<br />
A figura abaixo apresenta o diagrama esquemático da rede a ser montada/analisada. Observe que todos os IPv6 ''Global Unicast'' já estão definidos na mesma, são esses IPs que utilizaremos em nosso experimento.<br />
<br />
[[Arquivo:Diagrama_rede_IPv6.jpg]]<br />
<br />
#Crie em seu computador um arquivo com nome '''/home/aluno/IPv6.conf''', com o seguinte conteúdo: <syntaxhighlight lang=bash><br />
#Ligacao das maquinas nos dominios de colisao<br />
#Duas pequenas redes interligadas pelo backbone<br />
<br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=link0:ipv6=2001:bcc:faca:1::101/64<br />
pc2[eth0]=link1:ipv6=2001:bcc:cafe:1::102/64<br />
pc3[eth0]=HUB1:ipv6=2001:bcc:1f0:1::103/64<br />
pc4[eth0]=HUB1<br />
<br />
#Default Gateways definitions<br />
pc1[route]=default6:gateway=2001:bcc:faca:1::1<br />
pc2[route]=default6:gateway=2001:bcc:cafe:1::1<br />
pc3[route]=default6:gateway=2001:bcc:1f0:1::1<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
#Routers interfaces definitions<br />
r1[eth0]=backbone0:ipv6=2001:db8:dead:1::1/64<br />
r1[eth1]=link0:ipv6=2001:bcc:faca:1::1/64<br />
r1[eth2]=link1:ipv6=2001:bcc:cafe:1::1/64<br />
<br />
r2[eth0]=backbone0:ipv6=2001:db8:dead:1::2/64<br />
r2[eth1]=HUB1:ipv6=2001:bcc:1f0:1::1/64<br />
<br />
#Routers definitions<br />
r1[route]=2001:bcc:1f0:1::0/64:gateway=2001:db8:dead:1::2<br />
r2[route]=2001:bcc:faca:1::0/64:gateway=2001:db8:dead:1::1<br />
r2[route]=2001:bcc:cafe:1::0/64:gateway=2001:db8:dead:1::1<br />
</syntaxhighlight><br />
#Tenha certeza que o Netkit2 estja atualizado: General >> Update.<br />
#Rode o NetKit em seu computador. Em um terminal digite: <syntaxhighlight lang=bash><br />
netkit2 & </syntaxhighlight><br />
#No menu '''File''' - '''Load and Run''', procure o arquivo '''/home/aluno/IPv6.conf''' e clique em OK. Abrirá uma janela com 6 abas, onde cada uma delas é um terminal de configuração do respectivo equipamento: '''pc1-4''' ou '''r1-2'''.<br />
#Observe que o '''pc4''' não está com sua interface configurada.<br />
#Ao clicar no menu '''File''' - '''Graph''', pode-se ter uma visão da rede a ser simulada e conferir se é equivalente ao diagrama proposto.<br />
#Faça um '''ping6''' entre o '''pc1''' ao '''pc3''': <syntaxhighlight lang=bash><br />
ping6 -c4 2001:bcc:1f0:1::103 </syntaxhighlight><br />
#Faça um '''ping6''' entre o '''pc1''' e '''pc2'''.<br />
#No '''pc4''' use o seguinte comando para adicionar o endereço IPv6 à interface de rede: <syntaxhighlight lang=bash><br />
ip addr add 2001:bcc:1f0:1::104/64 dev eth0 </syntaxhighlight><br />
#No '''pc4''', acrescente o ''default gateway'' com o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add default via 2001:bcc:1f0:1::1 dev eth0 </syntaxhighlight><br />
#No '''pc1''' use o seguinte comando para verificar como ficou a configuração dos endereços da interface de rede. O resultado é similar ao apresentado pelo comando '''ifconfig''': <syntaxhighlight lang=bash><br />
ip addr show dev eth0 </syntaxhighlight><br />
#Todo o roteamento está pronto, mas caso desejássemos poderíamos acrescentar rotas com comando similares aos já utilizados. Por exemplo, no '''r1''', para adicionar uma rota estática para a rede dos '''pc3''' e '''pc4''' utilizaríamos o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add 2001:bcc:1f0:1::/64 via 2001:db8:dead:1::2 dev eth0 </syntaxhighlight><br />
#Confira as rotas estabelecidas em todos os ''hosts'' com o comando abaixo. <br />
##São coerentes com os dados apresentados no diagrama acima?<syntaxhighlight lang=bash><br />
ip -6 route show </syntaxhighlight><br />
#No '''pc1''' use os seguintes comandos para ver a rota para alguns vizinhos: <syntaxhighlight lang=bash><br />
traceroute6 2001:bcc:1f0:1::103<br />
traceroute6 2001:bcc:1f0:1::104 </syntaxhighlight><br />
#*Anote as rotas.<br />
#Deixe um '''ping6''' entre o '''pc1''' ao '''pc3''' rodando: <syntaxhighlight lang=bash><br />
ping6 2001:bcc:1f0:1::103 </syntaxhighlight><br />
<br />
=ATIVIDADE DE RECUPERAÇÃO 3=<br />
<br />
Registre em um DOC e faça um post no SIGA A colando a imagem das telas das saídas de cada comando! Coloque também a resposta as perguntas.<br />
<br />
===Objetivos===<br />
<br />
*Familiarizar-se com o UDP<br />
*Entender a estrutura do pacote UDP<br />
*Entender o conceito de portas<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/UDP%20Basico.pdf Introdução a camada de transporte e UDP básico]<br />
<br />
===Parte 1 - Fluxo único UDP===<br />
<br />
#Combinar equipes com dois computadores para execução do experimento.<br />
#*Uma equipe escutará na porta 5000 e a outra equipe transmitirá uma mensagem nessa porta. Os processos de transmissão e recepção podem ocorrer simultaneamente, em terminais distintos.<br />
#*Cada equipe deve identificar os IPs ('''IP_DEST''') das máquinas de seus pares.<br />
#Cada equipe deve abrir uma Janela de terminal.<br />
#Cada equipe deve preparar o '''Wireshark''', interfaces '''any''', para escuta das portas no protocolo UDP usando um filtro:<syntaxhighlight lang=bash><br />
udp.port==5000</syntaxhighlight><br />
#A equipe da escuta na porta 5000 executa no terminal: <syntaxhighlight lang=bash><br />
netcat -u -l -p 5000 </syntaxhighlight><br />
#A equipe que irá transmitir para a porta 5000 executa no terminal: <syntaxhighlight lang=bash><br />
netcat -u IP_DEST 5000 </syntaxhighlight><br />
#*Em seguida escreve no terminal uma mensagem de até 20 caracteres, ao teclar <Enter> a mensagem será enviada.<br />
#*O wireshark deve ter capturado os pacotes UDP <br />
#Identifique e anote os seguintes dados na captura do wireshark:<br />
#*IP FONTE e DESTINO<br />
#*PORTAS FONTE E DESTINO para ambas comunicações<br />
#*Campo de protocolo no pacote IP<br />
#*Campo de tamanho (anote o tamanho) e ''checksum'' no pacote (datagrama) UDP<br />
#*O campo de dados no pacote UDP<br />
#Troquem os papéis das equipes: quem houvia agora transmite mensagens.<br />
#Cada equipe pode transmitir sequencialmente várias mensagens, devendo identificar múltiplos datagramas UDP.<br />
#PERGUNTAS baseadas na captura:<br />
##Qual o tamanho de cada campo do cabeçalho do pacote UDP?<br />
##Qual o tamanho máximo do número de porta?<br />
##Qual o tamanho máximo da área de dados (payload) do pacote?<br />
##Qual o número identificador de protocolo UDP no pacote IP? <br />
##Em algum momento foi identificado algum procedimento para estabelecimento de conexão? <br />
##Em algum campo do UDP existe numeração de mensagens?<br />
<br />
=AULA 20 - Dia 18/04/2019=<br />
<br />
{{collapse bottom}}<br />
<br />
==Curso FIC Linux 2018==<br />
<br />
{{collapse top|Semestre 2018-2 - Prof. André D'Amato}}<br />
<br />
== Introdução ao Sistema Operacional Linux ==<br />
<br />
'''10/09/18: Aula01'''<br />
<br />
Apresentação da Disciplina, Introdução a Informática e Memória e Armazenamento<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula01.pdf Aula 01]<br />
<br />
{{collapse bottom}}<br />
<br />
==Curso FIC Linux 2016==<br />
<br />
{{collapse top|Semestre 2016-2 - Prof. Luciano Barreto}}<br />
<br />
== Introdução ao Sistema Operacional Linux ==<br />
<br />
'''04/10/16: Aula01'''<br />
<br />
Apresentação da Disciplina, Introdução a Informática e Memória e Armazenamento<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula01.pdf Aula 01]<br />
<br />
'''06/10/16: Aula 02'''<br />
<br />
Introdução ao Linux, Sistema de Arquivos e Conhecendo o Terminal<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula02.pdf Aula 02]<br />
<br />
''' 11/10/2016: Aula 03'''<br />
<br />
Continuação Comandos no Terminal<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula03.pdf Aula 03]<br />
<br />
''' 13/10/2016: Aula 04''' <br />
<br />
Continuação Comandos no Terminal<br />
<br />
''' 18/10/2016: Aula 05''' <br />
<br />
Lista de Exercícios<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/ficlinux-aula05-exercicios.pdf Aula 05 - Lista de Exercícios]<br />
<br />
''' 20/10/2016: Aula 06'''<br />
<br />
Introdução ao Gerenciamento de Processos<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula06-processos.pdf Aula 06 - Gerenciamento de Processos]<br />
<br />
''' 25/10/2016: Aula 07''' <br />
<br />
Gerenciamento de Usuários<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula07-usuariosgrupos.pdf Aula 07 - Gerenciamento de Usuários]<br />
<br />
Permissionamento<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula07-permissionamento.pdf Aula 07 - Permissionamento]<br />
<br />
''' 27/10/2016: Aula 08'''<br />
<br />
Continuação Permissionamento<br />
<br />
Instalação Linux<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula8-instalacao.pdf Aula 08 - Instalação Linux] <br />
<br />
''' 01/11/2016: Aula 09'''<br />
<br />
Continuação Instalação Linux<br />
<br />
Instalação de Pacotes via Apt<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula9-pacotes.pdf Aula 09 - Instalação Pacotes] <br />
<br />
''' 03/11/2016: Aula 10'''<br />
Continuação Lista Exercícios (47 - 60)<br />
<br />
=AULA 11 - Dia 18/04/2019=<br />
<br />
=AULA 12 - Dia 18/04/2019=<br />
<br />
=AULA 13 - Dia 18/04/2019=<br />
<br />
=AULA 14 - Dia 18/04/2019=<br />
<br />
=AULA 15 - Dia 18/04/2019=<br />
<br />
=AULA 16 - Dia 18/04/2019=<br />
<br />
=AULA 17 - Dia 18/04/2019=<br />
<br />
=AULA 18 - Dia 18/04/2019=<br />
<br />
=AULA 19 - Dia 18/04/2019=<br />
<br />
=AULA 20 - Dia 18/04/2019=<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top|Semestre 2016-1 - Prof. Luciano Barreto}}<br />
<br />
= Diário de Aulas 2016 - 1 =<br />
<br />
==29/03/16: Apresentação do curso==<br />
Apresentação do curso, Visão geral de funções, responsabilidades e estruturas de um SO.<br />
<br />
==31/03/16: Introdução a Sistema de Arquivos e Terminal==<br />
Estrutura do Sistema de Arquivos Linux, Introdução a comandos no Terminal.<br />
<br />
==04/04/16: Continuação Terminal==<br />
Continuação de comandos no terminal, redirecionamento de saída e caracteres coringa.<br />
<br />
==07/04/16: Introdução a Processos e Usuários==<br />
Conhecendo Processos e Gerenciamento de usuários<br />
<br />
==12/04/16: Lista de Exercícios de Comandos no Terminal==<br />
<br />
[http://bellard.org/jslinux/ Emulador de Terminal no navegador (demora um pouquinho pra abrir)]<br />
<br />
==14/04/16: Usuários, Grupos e Permissões==<br />
Administração de usuários, grupos e adicionando permissões a arquivos.<br />
<br />
==19/04/16: Instalação do Linux==<br />
Instalação do Sistema Linux em modo texto, gráfico e dualboot.<br />
<br />
==26/04/16: Introdução ao Shell Script==<br />
Introdução ao Shell Script<br />
<br />
==28/04/16: Continuação ao Shell Script==<br />
Introdução ao Shell Script<br />
<br />
==03/05/16: Lista de Exercícios==<br />
Lista de Exercícios até a aula de 28/04/16<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top|Semestre 2015-2}}<br />
<br />
*'''Professores:''' [[Ana Paula Rosa Negri]] e [[Francisco de Assis Souza dos Santos]]<br />
<br />
{| style="background-color:#ABCDEF; font-family:verdana,Arial, Helvetica, sans-serif; font-size:100%; margin:0; border: 1px solid #C7D0F8; padding:7px 7px 0px 7px; text-align:center;" width="100%"<br />
| | Bem-vindo ao<br /><br />
<span style="font-size:200%">'''Curso de Formação Continuada de Configuração de Redes de Computadores Linux''' <br />do Instituto Federal de Santa Catarina - Campus São José</span><br />
|}<br />
<br />
Introdução ao Sistema Operacional Linux<br />
<br />
*'''Professores:''' [[Ana Paula Rosa Negri]] e [[Francisco de Assis Souza dos Santos]]<br />
*'''Encontros:''' Terças e quintas das 19:00 às 22:00 no Laboratório de Apoio ao Ensino.<br />
<br />
*[[ISL-FicLinux_(Plano_de_Ensino)| Plano de Ensino]]<br />
*[[Cronograma de atividades (ISL-FicLinux) | Cronograma]]<br />
<br />
= Diário de Aulas 2015 =<br />
== 13/10 ==<br />
'''Parte 1:'''<br />
Slides da aula:<br />
[[Arquivo:introducao.pdf]]<br />
<br>Exercício sobre taxa de transferência:<br />
[[Arquivo:Exercicio_taxa_Transferencia.pdf]]<br />
<br><br />
<br />
'''Parte 2:'''<br />
Slides da Aula:<br />
[[Arquivo:LinuxModoTexto.pdf]]<br />
<br>Exercícios sobre comandos básicos do Linux:<br />
[[Arquivo:ExercícioLinuxTexto.pdf]]<br />
<br />
== 15/10 ==<br />
'''Parte 3:'''<br />
Slides da Aula:<br />
[[Arquivo:Parte3.pdf]]<br />
== 20/10 ==<br />
'''Parte 4:'''<br />
Slides caracteres coringas: [[Arquivo:Coringas.pdf]]<br />
<br />
Exercícios caracteres coringas: [[Arquivo:Exercício CB03 Pokemon.pdf]]<br />
<br />
'''Parte 5:'''<br />
Sildes Redirecionamento: [[Arquivo: Redirecionamento.pdf]]<br />
<br />
Exercícios redirecionamento e pipe: [[Arquivo: ex_pipe.pdf]]<br />
<br />
== 22/10 ==<br />
'''Parte 6:'''<br />
Slides Processos: [[Arquivo:FICLinux_Processos.pdf]]<br />
<br />
== 27/10 ==<br />
'''Parte 7:''''<br />
Slides Usuários e Grupos: [[Arquivo:UserGroup.pdf]]<br />
<br>Exercícios: [[Arquivo:usuarios.pdf]]<br />
<br>Exercícios (.odt): [[Arquivo:usuarios.odt]]<br />
<br />
== 29/10 ==<br />
'''Parte 8:'''<br />
Slides Introducao a Redes: [[Arquivo:FICLinux_Introducao_Redes.pdf]]<br />
<br />
== 03/11 ==<br />
<br />
'''Parte 9:'''<br />
Slides permissionamento: [[Arquivo:permissionamento.odp]]<br><br />
Exercícios permissionamento: [[Arquivo: Exercício Perm02.odt]]<br><br />
Outro exercício permissionamento: [[Arquivo: Exercício Perm04 GatosRatosCães.odt]]<br />
<br />
== 05/11 ==<br />
<br />
'''Parte 10:'''<br />
Slides Redes - Broadcast: [[Arquivo:FICLinux_Introducao_Redes_Broadcast_01.pdf]]<br><br />
<br />
== 10/11 ==<br />
<br />
'''Parte 11:'''<br />
Slides Script: [[Arquivo:Scripts do Linux.odp]]<br />
<br>Exercícios Scripts: [[Arquivo:Exercício Scripts01 pdfmerger.odt]]<br />
<br />
== 12/11 ==<br />
<br />
'''Parte 12:'''<br />
Introdução para comandos em Bash: [[Arquivo:Introdução ao Shell_2015_1.pdf]]<br />
<br />
{{collapse bottom}}</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=ISL-FicLinux_(p%C3%A1gina)&diff=162002ISL-FicLinux (página)2019-10-03T19:42:58Z<p>127.0.0.1: /* Cronograma Tentativa */</p>
<hr />
<div>__NOTOC__<br />
= Introdução ao Sistema Operacional Linux / Redes com Linux =<br />
<br />
*'''Encontros:''' Terças e Quintas das 19:00 às 22:00.<br />
*'''Local:''' Laboratório de Redes de Computadores (Redes 1).<br />
<br />
*[[ISL-FicLinux_(Plano_de_Ensino)| Plano de Ensino]]<br />
<br />
==Curso FIC Linux 2019==<br />
<br />
{{collapse top | Semestre 2019-2 - Prof. Eraldo Silveira e Silva}}<br />
<br />
==Cronograma Tentativa==<br />
<br />
Horários: 19h às 22h.<br />
<br />
{| class="wikitable"|<br />
| AULA || DATA || Professor || Conteúdo<br />
|-<br />
| 1 || 27/09/2019 || ERALDO || Programa da Disciplina.Forma de Avaliação. O computador: hardware e software. SO Linux: histórico e distribuições. Ligando/Logando/Desligando a Máquina. Conceitos básico de Sistema de Arquivos e Processos.<br />
|-<br />
| 2 || 29/09/2019 || ERALDO || Gerenciamento de Arquivos I: Operações sobre arquivos e diretórios usando o terminale o Nautilus.<br />
|-<br />
| 3 || 3/09/2019 || ERALDO || Gerenciamento de Arquivos II: continuação Operações sobre arquivos e diretórios. Links Simbólicos, Criação de Arquivo com vi e outros editores.<br />
|-<br />
| 4 || 5/09/2019 || ERALDO || Interfaces Gráficas: X11, Gnome. KDE e outras. Instalação de Programas via Gerenciador de Pacotes.<br />
|-<br />
| 5 || 10/09/2019 || ERALDO || Administração de contas de usuários I<br />
|-<br />
| 6 || 12/09/2019 || ERALDO || Administração de contas de usuários II<br />
|-<br />
| 7 || 17/09/2019 || ERALDO || Permissionamento de Arquivos<br />
|-<br />
| 8 || 19/09/2019 || ERALDO || Gerenciamento de Processos<br />
|-<br />
| 9 || 24/09/2019 || ERALDO || Introdução ao Shell Script<br />
|-<br />
| 10 || 26/09/2019 || ERALDO || Introdução ao Shell Script<br />
|-<br />
| 11 || 1/10/2019 || ERALDO || Introdução a Redes. Conceito de Protocolos. Ferramentas de Rede no Linux.<br />
|-<br />
| 12 || 3/10/2019 || ERALDO || Protocolos de Aplicação: exemplo http <br />
|-<br />
| 13 || 8/10/2019 || ERALDO || O DNS como protocolo de Aplicação; Camada de Transporte: protocolo UDP <br />
|-<br />
| 14 || 10/10/2019 || ERALDO || Protocolo TCP. Diferenças dos protocolos de Transporte TCP/UDP. Camada IP e aspectos da configuração da mesma sob o Linux<br />
|-<br />
| 15 || 15/10/2019 || ERALDO || Camada de Enlace/Física. Hubs X Switches. O Papel do Protocolo ARP. Outros serviços/protocolos: Serviço DHCP e NAT<br />
|-<br />
| 16 || 17/10/2019 || ERALDO|| Segmentação Redes IP. Cálculo de subredes. <br />
|-<br />
| 17 || 22/10/2019 || ERALDO || Introdução ao IPV6. Introdução ao Access Point TPLINK N750: configuração da LAN e WAN<br />
|-<br />
| 18 || 24/10/2019 || ERALDO || Serviço SSH no Linux. Acesso a rede WIFI. Conceitos básicos de redes sem fio.<br />
|-<br />
| 19 || 29/10/2009 || ERALDO || Tópicos Adicionais sobre redes no Linux: Configuração Manual X NetworkManager. Relatório Avaliativo 1.<br />
|-<br />
| 20 || 31/10/2019 || ERALDO || Relatório Avaliativo 2<br />
|}<br />
<br />
=Curso FIC Linux 2019-2=<br />
<br />
==Professor==<br />
<br />
:*Prof. [[Eraldo Silveira e Silva]]<br />
:*email: eraldo@ifsc.edu.br<br />
:*sala: Sala de I de Professores da Área de Telecomunicações (primeira sala lado da Biblioteca - direção esquerda)<br />
<br />
=27/08/2019=<br />
<br />
==Objetivos==<br />
<br />
===Parte 1===<br />
<br />
*Apresentar o IFSC: estrutura, câmpus e serviços<br />
*Apresentar o curso: perfil do egresso, competências gerais, áreas de atuação do egresso e conteúdos previstos<br />
*Apresentar o Cronograma Tentativa (ver SIGA A)<br />
*Apresentar metodologia e forma de avaliação<br />
<br />
===Parte 2===<br />
<br />
*Conceitos de Hardware, Software e Firmware<br />
*Arquiteturas de processadores<br />
*Classificação de softwares<br />
*Conceitos de Sistemas Operacionais e exemplos<br />
<br />
===Parte 3===<br />
<br />
*Histórico do Linux<br />
*Linux e GNU/Linux<br />
*Instalando o Linux<br />
*Arquitetura do Linux<br />
*Distribuições<br />
*Distribuições usadas no IFSC/SJ<br />
*Ligando e Desligando o Sistema<br />
*Primeiros contatos.<br />
<br />
==Professores do FIC Linux Edição 2019-2==<br />
<br />
*Prof. [[Eraldo Silveira e Silva]] (Introdução ao Linux e Redes com Linux)<br />
<br />
==Apresentação do IFSC==<br />
<br />
*[http://www.ifsc.edu.br/estrutura-organizacional-inicio Página do IFSC]<br />
*[https://www.sj.ifsc.edu.br/index.php Página do Câmpus]<br />
<br />
==Apresentação do Curso==<br />
<br />
*[[ISL-FicLinux_(Plano_de_Ensino) | Introdução ao Linux]]<br />
*[https://wiki.sj.ifsc.edu.br/index.php/PRL-FicLinux_(Plano_de_Ensino) Projeto de Rede Residencial com o Linux]<br />
*[[Curso_de_Formação_Continuada_de_Configuração_de_Redes_de_Computadores_Linux | PPC do Curso e Outras Regulamentações]]<br />
<br />
==Cronograma Tentativa==<br />
<br />
Horários: 19h às 22h.<br />
<br />
VER SIGA A [https://sig.ifsc.edu.br/sigaa/verTelaLogin.do]<br />
<br />
==Metodologia, Avaliação e Critérios de Aprovação==<br />
<br />
*Aulas expositivas e aulas práticas no laboratório. Nas aulas práticas serão desenvolvidos exercícios e trabalhos individuais.<br />
*Avaliações individuais: Listas de exercícios com aproveitamento e entregues no prazo. <br />
*Critérios para aprovação: Serão considerados aprovados os alunos que obtiverem conceito final 6 ou superior em cada componente curricular. ATENÇÃO: Possuir no mínimo 75% de presença<br />
<br />
==Bibliografia==<br />
<br />
#Odilson Tadeu Valle<br />
##Administração de redes com Linux: fundamentos e práticas<br />
##Editora IFSC, 2010<br />
#Gleydson Mazioli da Silva<br />
##Guia Foca Linux<br />
##http://www.guiafoca.org/<br />
#Luiz Carlos Lobato Lobo de Medeiros e Wendel Soares<br />
##Formação de suporte técnico PROINFO<br />
##https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo<br />
#Ari Frazão Jr e Marcelo Braga<br />
##Administração de Sistemas Linux<br />
##https://pt.scribd.com/doc/128912228/Administracao-de-Sistemas-Linux<br />
<br />
==Conceitos de Hardware, Software e Firmware==<br />
<br />
*Em informática, o hardware consiste nos equipamentos<br />
**Ex: Computador, teclado, mouse, monitor<br />
*Software é um aplicativo, desenvolvido em uma linguagem de programação<br />
**Ex: Windows, Linux, Mozilla Firefox, Google Chrome<br />
*Firmware é um conjunto de instruções básicas e específicas para um hardware<br />
**Ex: BIOS nos computadores, sistemas de controle das máquinas de lavar, etc.<br />
<br />
==Estrutura de um Computador e Arquitetura de Processadores==<br />
<br />
*Material de Referência: https://www.dropbox.com/s/fn3l9os4l7gh9o5/AULA%201.odp?dl=0<br />
<br />
===Outros Links Interessantes===<br />
<br />
*Bits, [https://pt.wikipedia.org/wiki/Byte Bytes] e tamanho de memória;<br />
*Representação de Caracteres: [https://pt.wikipedia.org/wiki/ASCII Tabela ASCII];<br />
*O [https://pt.wikipedia.org/wiki/Microprocessador microprocessador], barramentos e memórias semicondutoras: RAM,ROM, E2PROM, FLASH;<br />
*Memórias cache e memórias secundárias;<br />
*[https://pt.wikipedia.org/wiki/Mem%C3%B3ria_virtual Memória Virtual] e Swapping;<br />
*Registradores de 32bits ou 64bits<br />
*Arquitetura [https://pt.wikipedia.org/wiki/X86 x86] / [https://pt.wikipedia.org/wiki/AMD64 x86-64] – presente nos computadores pessoais<br />
*Arquitetura ARM – presente em sistemas embarcados e dispositivos móveis<br />
*Múltiplos núcleos (core)<br />
*Máquinas Virtuas: VirtualBox, UML (User Mode Linux).<br />
<br />
==O papel do Sistema Operacional==<br />
<br />
*O [https://pt.wikipedia.org/wiki/Sistema_operativo SO] é um programa (software) que controla a máquina e a torna utilizável para o usuário;<br />
*Abstrações do Sistema: arquivos e processos;<br />
*Pode ser multitarefa e multiusuário;<br />
*[https://en.wikipedia.org/wiki/Device_driver Driver] de dispositivo<br />
*[https://pt.wikipedia.org/wiki/Multi_boot Múltiplos OS instalados] em um computador. É possível??<br />
<br />
==Sistema de Arquivos==<br />
<br />
*Forma como estão estruturados/organizados os arquivos/dados em uma determinada mídia [https://pt.wikipedia.org/wiki/Sistema_de_ficheiros];<br />
*Um sistema operacional deve saber como acessar e operar sobre este sistema;<br />
*Tipos de sistemas: ext4, NTFS, VFAT32<br />
<br />
==Exemplos de SO==<br />
<br />
*Unix<br />
*Microsoft DOS<br />
*IBM<br />
*Microsoft Windows<br />
*netBSD, freeBSD, openBSD<br />
*Linux<br />
*macOS<br />
*Android<br />
*iOS<br />
<br />
==Histórico do Linux==<br />
<br />
*O início de tudo: UNIX;<br />
*Surgiu em 1991 quando Linus Torvalds, um estudante finlandês, resolveu desenvolver um sistema operacional compatível com a POSIX, por em que pudesse ser executado em arquitetura x86;<br />
*Linux está sob uma licença de software livre e diversas pessoas e empresas contribuem para o desenvolvimento do mesmo.<br />
*E o que é [https://pt.wikipedia.org/wiki/POSIX POSIX]? Define padrões para a interface de programação de aplicações (API) de um OS de forma a manter compatibilidade com o UNIX;<br />
<br />
==Arquitetura do Linux==<br />
<br />
===Material de Referência===<br />
<br />
*[https://www.dropbox.com/s/zvpo7zw19ns7rmk/AULA%202.odp?dl=0 Slides Introdução ao SO Linux]<br />
*Ver pg.16 a 19 de [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo]<br />
<br />
==Distribuições==<br />
<br />
Uma distribuição Linux consiste de um kernel Linux e uma coleção de software utilitários e aplicativos de usuário (baseado slides Prof. Emerson)<br />
**Redhat<br />
**Slackware<br />
**Debian<br />
**Ubuntu<br />
**OpenSuse<br />
**Fedora<br />
**CentOS<br />
**Kali<br />
<br />
<br />
Algumas distribuições podem ser executadas diretamente no CD/pendrive<br />
sem a necessidade de fazer sua instalação no disco rígido do computador<br />
<br />
==Distribuições aqui no IFSC SJ==<br />
<br />
*Ubuntu<br />
*Ubuntu Mate (fork do Ubuntu)<br />
*Debian<br />
<br />
==Instalando o Linux==<br />
<br />
*Fazer Download do arquivo ISO em [http://mirror.pop-sc.rnp.br/mirror/ubuntu-releases/18.04/] versão Ubuntu 18.04.3 LTS;<br />
*Instalar a VirtualBox (já está instalada no nosso Lab). Baixar de [https://www.virtualbox.org/wiki/Downloads] e selecionar para a máquina hospedeira alvo;<br />
*Seguir o procedimento colocado pelo professor.<br />
<br />
*[Ver https://www.dropbox.com/s/4xfdhqq8lruvq8m/LinuxSobreVM.odp?dl=0 Slides de Instalação]<br />
<br />
==Ligando e Desligando o Sistema Linux==<br />
<br />
*Cuidado ao desligar um OS como o Linux!!! Dados podem ser perdidos.<br />
*Ver [https://pt.wikibooks.org/wiki/Guia_do_Linux/Iniciante%2BIntermedi%C3%A1rio/Introdu%C3%A7%C3%A3o/Ligando_o_computador]<br />
<br />
==O Desktop do Ubuntu - Primeiras Considerações==<br />
<br />
*O Desktop no Ubuntu ver[https://help.ubuntu.com/stable/ubuntu-help/shell-overview.html]<br />
<br />
=AULA 2 - Dia 29/08/2019=<br />
<br />
==Objetivos==<br />
<br />
===PARTE 1===<br />
<br />
*Revisão da aula passada;<br />
*repassar itens não mencionados na aula passada;<br />
**Paginação e Memória [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo pg.19]<br />
**Estrutura do Linux [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo pg.18]<br />
<br />
===PARTE 2===<br />
<br />
*Operações com arquivos e diretórios usando o terminal;<br />
*formato de um comando básico;<br />
*quase tudo no Linux é arquivo: tipos de arquivos, diretórios, arquivos ordinários;<br />
*conceito de sistema de arquivos;<br />
*conceito de referência absoluta e relativa;<br />
*conceito de diretório de entrada, diretório de trabalho;<br />
*mudando de diretório com cd;<br />
*listando diretórios e arquivos com ls;<br />
*vendo o significado de um comando com man;<br />
*criando diretórios com mkdir;<br />
*removendo diretórios e arquivos com rmdir e rm;<br />
*referência com . .. - ~<br />
*criando arquivos ordinários com touch;<br />
*arquivos e diretórios escondidos;<br />
*copiando arquivos;<br />
*movendo e renomeando arquivos;<br />
*vendo a história de comandos com history;<br />
<br />
===Slides===<br />
<br />
*[https://www.dropbox.com/s/wtc479wmrtle9m4/SistemaDeArquivos.odp?dl=0 Slides Sistema de Arquivos]<br />
<br />
==Conceito de sistemas de arquivos, arquivos e diretórios==<br />
<br />
* [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Sistemas de Arquivos pg.18]<br />
* [Estrutura básica de diretórios do Sistema Linux]<br />
<br />
==Comandos no Linux==<br />
<br />
* [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Comandos e Interpretador de Comandos no Linux pg.18]<br />
<br />
==Tipos de Arquivos==<br />
<br />
* [https://pt.scribd.com/doc/128912228/Administracao-de-Sistemas-Linux Tipos de Arquivos 12,13 e 14 ]<br />
<br />
==Os comandos de operação sobre arquivos e diretórios==<br />
<br />
*[https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Interpretador de comandos - Comandos Básicos - pg.20 e 21]<br />
*[https://www.dropbox.com/s/mv6qpa8bqimiwzg/Aula1_Linux%282%29.pdf Ver lista de exercícios da Aula 2]<br />
<!-- *[https://www.dropbox.com/s/g3xr3wimffde2zm/Aula2_Linux_OperacoesComArquivos_2.pdf Ver lista de exercícios da Aula 3] --><br />
<br />
=AULA 3 - Dia 03/09/2019=<br />
<br />
<br />
===Mirros do Ubuntu Download e Outros===<br />
<br />
<br />
*[http://mirror.pop-sc.rnp.br/mirror/ubuntu-releases/18.04.3/ Ununtu 18.04.3 Mirror Brazil]<br />
<br />
*[https://linuxmint.com/edition.php?id=267 Linux Mint]<br />
<br />
*[https://software.opensuse.org/distributions/leap Opensuse]<br />
<br />
*[https://elementary.io/ Elementary Os]<br />
<br />
*[https://lubuntu.net/ Lubuntu]<br />
<br />
*[https://www.debian.org/CD/live/ Debian]<br />
<br />
*[https://kubuntu.org/getkubuntu/ Kubuntu]<br />
<br />
*[https://peppermintos.com/ Peppermint]<br />
<br />
*[https://www.linuxliteos.com/ Linux Lite]<br />
<br />
*[https://www.lxle.net/download/ LXLE para PCs Antigos...]<br />
<br />
*[https://www.bodhilinux.com/ Bodhi Linux]<br />
<br />
===Como verificar se o arquivo está correto?===<br />
<br />
*[https://help.ubuntu.com/community/HowToMD5SUM HowToMD5SUM] <br />
<br />
===Instalar e Preparar 3 transparências no Oppenoffice===<br />
<br />
*Nome da Equipe e da Distribuição - colar a desktop no slide<br />
*O que tem de interessante nesta distro<br />
*Requisitos da Distribuição<br />
<br />
*Gerar pdf e Enviar para o Siga a<br />
<br />
=AULA 4 - Dia 03/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Ainda operações com arquivos;<br />
*Uso de Coringas<br />
*Editor de texto sobre Ubuntu<br />
*Redirecionamento de Entradas e Saídas<br />
*Aspectos da Interface Gnome no Ubuntu 18.04<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/zti7nn0xq25x8ne/Aula2_Linux_OperacoesComArquivos_2.pdf Ainda Operações com Arquivos]<br />
*[https://www.dropbox.com/s/af3jolkvrb24g8c/Aula3_Linux_LinksSimb_licos_gedit_cat.pdf Edição de Texto]<br />
*[https://www.dropbox.com/s/vihh5r9186d40uj/Aula3_Linux_Parte4_RedirecionamentoEntradasSaidas.pdf Redirecionamento de Entradas e Saídas]<br />
<br />
=AULA 5 - Dia 10/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Gerenciamento de Processos - Parte 1<br />
*Permissionamento de Arquivos - Parte 1<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/4i1n2wqsds18eol/Aula5_Linux_GerenciamentoDeProcessos_Parte1.pdf?dl=0 Gerenciamento de Processos - Parte 1]<br />
*[https://www.dropbox.com/s/3z61r8r0b9wpftr/Aula4_Linux_PermissionamentoDeAcesso_Parte1.pdf Permissionamento de Arquivos - Parte 1]<br />
<br />
=AULA 6 - Dia 12/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Aval1<br />
<br />
==Comand wget==<br />
<br />
Para fazer o downloiad do Linux Ubuntu via linha de comando:<br />
<br />
wget http://mirror.pop-sc.rnp.br/mirror/ubuntu-releases/18.04.3/ubuntu-18.04.3-desktop-amd64.iso<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/fdl5kzq0ba2nv3v/Aula4_Linux_PermissionamentoDeAcesso_Parte2.pdf Permissionamento Parte 2 ]<br />
<br />
=AULA 7 - Dia 12/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Instalação do Ubuntu em partições separadas<br />
*Permissionamento de Grupos e Outros<br />
*Criação de Contas de Usuários<br />
*Camandos adicionais para gerenciamento de processos<br />
<br />
==Instalação==<br />
<br />
Considere a estrutura de sistemas de arquivos abaixo. Montar um sistema de arquivos da forma abaixo considerando que sb1 seria um segundo hd máquina virtual.<br />
<br />
[[arquivo:SOP2019-1-ExemploMontagemSistema.png]]<br />
<br />
Logar no sistema e usando o terminal verificar as configurações estabelecidas.<br />
<br />
df -h<br />
cd /home<br />
ls spock<br />
<br />
Usar o comando gparted para criar uma partição adicional no segundo disco.<br />
<br />
sudo apt-get install gparted<br />
sudo gparted<br />
<br />
Redimensionar a partição original para poder criar uma adicional.<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/fdl5kzq0ba2nv3v/Aula4_Linux_PermissionamentoDeAcesso_Parte2.pdf Permissionamento Parte 2 ]<br />
<br />
*[https://www.dropbox.com/s/ozjd3qz0yblcj43/Aula6_Comandos_Adicionais_de_Gerenciamento_de_Processos.pdf Gerenciamento de Processos Parte 2]<br />
<br />
=AULA 8 - Dia 12/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Permissionamento de Grupos e Outros<br />
*Criação de Contas de Usuários<br />
*Reparticionamento de Disco após instalação. Montagem de sistemas com mount.<br />
<br />
==Desafio Final==<br />
<br />
Na máquina instalada na aula anterior fazer as seguintes operações:<br />
<br />
*Reparticionar o disco 2 (/dev/sdb) em 2 partições de 5G (usar o comando gparted) (redimensionar a partição do spock)<br />
*Criar uma conta para o usuário uhura<br />
*Criar dois subdiretórios no diretório home de uhura. Estes diretórios serão pontos de montagem dos dois sistemas de arquivos criados no segundo disco.<br />
*Montar os sistemas de arquivos usando o comando mounthttps://wiki.sj.ifsc.edu.br/index.php/ISL-FicLinux_(Plano_de_Ensino)<br />
*Mudar o dono destes diretórios (usuário e grupo) )para o novo dono (uhura)<br />
*Verificar o sistema montado (comando df)<br />
*Testar o acesso entrando como <br />
<br />
==Continuando o o permissionamento de Grupos e Outros==<br />
<br />
Ver material de referência<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/fdl5kzq0ba2nv3v/Aula4_Linux_PermissionamentoDeAcesso_Parte2.pdf Permissionamento Parte 2 ]<br />
*[https://www.dropbox.com/s/ozjd3qz0yblcj43/Aula6_Comandos_Adicionais_de_Gerenciamento_de_Processos.pdf Gerenciamento de Processos Parte 2]<br />
<br />
=AULA 9 - Dia 24/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*ainda criação de usuários<br />
*ainda gerenciamento de processos: crontab<br />
*compactação e backups em linha de comando<br />
<br />
<br />
==Material de Referência==<br />
<br />
<br />
*[Ainda Gerenciamento de Usuários https://www.dropbox.com/s/8vsg0yeforcsuq9/Aula7_GerenciamentoDeUsuarios_Parte1.pdf?dl=0]<br />
*[https://www.dropbox.com/s/ozjd3qz0yblcj43/Aula6_Comandos_Adicionais_de_Gerenciamento_de_Processos.pdf Gerenciamento de Processos Parte 2]<br />
*[https://www.dropbox.com/s/61n9is9c8o7bgbz/Aula3_Linux_Parte3_vi.pdf?dl=0 Introdução ao VI]<br />
<br />
=AULA 10 - Dia 26/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Finalização da aula anterior: arquivo sudoers<br />
*Introdução ao shell script<br />
*Um pouco sobre instalação de pacotes<br />
*exercicício avaliativo 2<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/54tnv5rjwguzppd/Aula8_ShellScript_Parte1.pdf?dl=0 Introdução ao Shell script]<br />
*[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula9-pacotes.pdf Instalação de Pacotes (Prof.Luciano Barreto)]<br />
<br />
=AULA 11 - Dia 1/10/2019=<br />
<br />
Introdução a Redes de Computadores<br />
**Conceito Básicos em Redes e Protocolos<br />
**Ferramentas de Redes<br />
**Exemplo de Protocolo de Aplicação: http<br />
**O processo de encapsulamento<br />
<br />
==Plano de Ensino==<br />
<br />
*[https://wiki.sj.ifsc.edu.br/index.php/PRL-FicLinux_(Plano_de_Ensino) Plano de Ensino]<br />
<br />
<br />
==Laboratório 1 - Ferramentas de Rede e Conceitos Básicos==<br />
<br />
*Familiarização com a infraestrutura dos laboratórios de redes<br />
*Familiarização com ferramentas de rede: ifconfig, ping, traceroute;<br />
*Desenvolver a noção de endereçamentos de rede IP e de endereço de hardware (MAC)<br />
*Desenvolver a noção de rotas em redes IP<br />
*Testar a conectividade IP com ping<br />
<br />
*Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)]<br />
<br />
==Laboratório 2 - Wireshark e encapsulamento==<br />
<br />
*Familiarização com o sniffer de rede WireShark<br />
*Observar o comportamento do ping e se familiarizar com o processo de encapsulamento;<br />
<br />
**Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)]<br />
<br />
==Conceituando Protocolos e Aplicações de Rede==<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/Conceituando%20protocolos.pdf Conceituando protocolos]<br />
<br />
<br />
=AULA 12 - Dia 03/10/2019=<br />
<br />
==Objetivos==<br />
<br />
*Conceituando protocolos<br />
*Protocolos de aplicação: exemplo http<br />
<br />
==Laboratório 3 - Conceituando protocolo==<br />
<br />
Ver [https://wiki.sj.ifsc.edu.br/index.php?title=ISL-FicLinux_(p%C3%A1gina)&action=edit&section=69]<br />
<br />
==Laboratório 4 - Desvendando o HTTP com Wireshark - BÁSICO==<br />
<br />
Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)#Parte_1:_Observando_interfaces_do_sistema_com_ifconfig]<br />
<br />
<br />
{{collapse bottom}}<br />
<br />
<br />
<br />
{{collapse top | Semestre 2019-1 - Prof. Tiago Semprebom e Eraldo Silveira e Silva}}<br />
<br />
=Professor=<br />
<br />
:*Prof. [[Tiago Semprebom]]<br />
:*email: tisemp@ifsc.edu.br<br />
:*sala: Sala de II de Professores da Área de Telecomunicações (primeira sala lado da Biblioteca - direção esquerda)<br />
<br />
=12/03/2019=<br />
<br />
==Objetivos==<br />
<br />
===Parte 1===<br />
*Apresentar os professores e o coordenador;<br />
*Apresentar o IFSC: estrutura, câmpus e serviços<br />
*Apresentar o curso: perfil do egresso, competências gerais, áreas de atuação do egresso e conteúdos previstos<br />
*Apresentar o Cronograma Tentativa<br />
*Apresentar metodologia e forma de avaliação<br />
<br />
===Parte 2===<br />
<br />
*Conceitos de Hardware, Software e Firmware<br />
*Arquiteturas de processadores<br />
*Classificação de softwares<br />
*Conceitos de Sistemas Operacionais e exemplos<br />
<br />
===Parte 3===<br />
<br />
*Histórico do Linux<br />
*Linux e GNU/Linux<br />
*Arquitetura do Linux<br />
*Distribuições<br />
*Distribuições usadas no IFSC/SJ<br />
*Ligando e Desligando o Sistema<br />
*Primeiros contatos.<br />
<br />
==Professores do FIC Linux Edição 2019-1==<br />
*Prof. [[Tiago Semprebom]] (Introdução ao Linux)<br />
*Prof. [[Eraldo Silveira e Silva]] (Redes com Linux)<br />
<br />
==Apresentação do IFSC==<br />
<br />
*[http://www.ifsc.edu.br/estrutura-organizacional-inicio Página do IFSC]<br />
*[https://www.sj.ifsc.edu.br/index.php Página do Câmpus]<br />
<br />
==Apresentação do Curso==<br />
<br />
*[[ISL-FicLinux_(Plano_de_Ensino) | Introdução ao Linux]]<br />
*[[PRL-FicLinux (página) | Projeto de Rede Residencial com o Linux]]<br />
*[[Curso_de_Formação_Continuada_de_Configuração_de_Redes_de_Computadores_Linux | PPC do Curso e Outras Regulamentações]]<br />
<br />
==Cronograma Tentativa==<br />
<br />
Horários: 19h às 22h.<br />
<br />
{| class="wikitable"|<br />
| AULA || DATA || Professor || Conteúdo<br />
|-<br />
| 1 || 12/03/2019 || TIAGO || Programa da Disciplina.Forma de Avaliação. O computador: hardware e software. SO Linux: histórico e distribuições. Ligando/Logando/Desligando a Máquina. Conceitos básico de Sistema de Arquivos e Processos.<br />
|-<br />
| 2 || 14/03/2019 || TIAGO || Gerenciamento de Arquivos I: Operações sobre arquivos e diretórios usando o terminale o Nautilus.<br />
|-<br />
| 3 || 21/03/2019 || TIAGO || Gerenciamento de Arquivos II: continuação Operações sobre arquivos e diretórios. Links Simbólicos, Criação de Arquivo com vi e outros editores.<br />
|-<br />
| 4 || 26/03/2019 || TIAGO || Interfaces Gráficas: X11, Gnome. KDE e outras. Instalação de Programas via Gerenciador de Pacotes.<br />
|-<br />
| 5 || 28/03/2019 || TIAGO || Administração de contas de usuários I<br />
|-<br />
| 6 || 02/04/2019 || TIAGO || Administração de contas de usuários II<br />
|-<br />
| 7 || 04/04/2019 || TIAGO || Permissionamento de Arquivos<br />
|-<br />
| 8 || 09/04/2019 || TIAGO || Gerenciamento de Processos<br />
|-<br />
| 9 || 11/04/2019 || TIAGO || Introdução ao Shell Script<br />
|-<br />
| 10 || 16/04/2019 || TIAGO || Avaliação 1 - Introdução ao Sistema Operacional Linux<br />
|-<br />
| 11 || 09/10/2019 || ERALDO || Introdução a Redes. Conceito de Protocolos. Ferramentas de Rede.<br />
|-<br />
| 12 || 11/10/2019 || ERALDO || Protocolos de Aplicação: exemplo http <br />
|-<br />
| 13 || 16/10/2019 || ERALDO || O DNS como protocolo de Aplicação; Camada de Transporte: protocolo UDP <br />
|-<br />
| 14 || 18/10/2019 || ERALDO || Protocolo TCP. Diferenças dos protocolos de Transporte TCP/UDP. Camada IP e aspectos da configuração da mesma sob o Linux<br />
|-<br />
| 15 || 23/10/2017 || ERALDO || Camada de Enlace/Física. Hubs X Switches. O Papel do Protocolo ARP. Outros serviços/protocolos: Serviço DHCP e NAT<br />
|-<br />
| 16 || 25/10/2017 || ERALDO (TIAGO) || Segmentação Redes IP. Cálculo de subredes. <br />
|-<br />
| 17 || 30/10/2017 || ERALDO || Introdução ao IPV6. Introdução ao Access Point TPLINK N750: configuração da LAN e WAN<br />
|-<br />
| 18 || 01/11/2017 || ERALDO || Serviço SSH no Linux. Acesso a rede WIFI. Conceitos básicos de redes sem fio.<br />
|-<br />
| 19 || 06/11/2007 || ERALDO || Tópicos Adicionais sobre redes no Linux: Configuração Manual X NetworkManager. Relatório Avaliativo 1.<br />
|-<br />
| 20 || 08/11/2017 || ERALDO || Relatório Avaliativo 2<br />
|}<br />
<br />
==Metodologia, Avaliação e Critérios de Aprovação==<br />
<br />
*Aaulas expositivas e aulas práticas no laboratório. Nas aulas práticas serão desenvolvidos exercícios e trabalhos individuais.<br />
*Avaliações individuais: Listas de exercícios com aproveitamento e entregues no prazo. <br />
*Critérios para aprovação: Serão considerados aprovados os alunos que obtiverem conceito final 6 ou superior em cada componente curricular. ATENÇÂO: Possuir no mínimo 75% de presença<br />
<br />
==Bibliografia==<br />
<br />
#Odilson Tadeu Valle<br />
##Administração de redes com Linux: fundamentos e práticas<br />
##Editora IFSC, 2010<br />
#Gleydson Mazioli da Silva<br />
##Guia Foca Linux<br />
##http://www.guiafoca.org/<br />
#Luiz Carlos Lobato Lobo de Medeiros e Wendel Soares<br />
##Formação de suporte técnico PROINFO<br />
##https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo<br />
#Ari Frazão Jr e Marcelo Braga<br />
##Administração de Sistemas Linux<br />
##https://pt.scribd.com/doc/128912228/Administracao-de-Sistemas-Linux<br />
<br />
==Conceitos de Hardware, Software e Firmware==<br />
<br />
*Em informática, o hardware consiste nos equipamentos<br />
**Ex: Computador, teclado, mouse, monitor<br />
*Software é um aplicativo, desenvolvido em uma linguagem de programação<br />
**Ex: Windows, Linux, Mozilla Firefox, Google Chrome<br />
*Firmware é um conjunto de instruções básicas e específicas para um hardware<br />
**Ex: BIOS nos computadores, sistemas de controle das máquinas de lavar, etc.<br />
<br />
==Estrutura de um Computador e Arquitetura de Processadores==<br />
<br />
*Bits, [https://pt.wikipedia.org/wiki/Byte Bytes] e tamanho de memória;<br />
*Representação de Caracteres: [https://pt.wikipedia.org/wiki/ASCII Tabela ASCII];<br />
*O [https://pt.wikipedia.org/wiki/Microprocessador microprocessador], barramentos e memórias semicondutoras: RAM,ROM, E2PROM, FLASH;<br />
*Memórias cache e memórias secundárias;<br />
*[https://pt.wikipedia.org/wiki/Mem%C3%B3ria_virtual Memória Virtual] e Swapping;<br />
*Registradores de 32bits ou 64bits<br />
*Arquitetura [https://pt.wikipedia.org/wiki/X86 x86] / [https://pt.wikipedia.org/wiki/AMD64 x86-64] – presente nos computadores pessoais<br />
*Arquitetura ARM – presente em sistemas embarcados e dispositivos móveis<br />
*Múltiplos núcleos (core)<br />
*Máquinas Virtuas: VirtualBox, UML (User Mode Linux).<br />
<br />
==O papel do Sistema Operacional==<br />
<br />
*O [https://pt.wikipedia.org/wiki/Sistema_operativo SO] é um programa (software) que controla a máquina e a torna utilizável para o usuário;<br />
*Abstrações do Sistema: arquivos e processos;<br />
*Pode ser multitarefa e multiusuário;<br />
*[https://en.wikipedia.org/wiki/Device_driver Driver] de dispositivo<br />
*[https://pt.wikipedia.org/wiki/Multi_boot Múltiplos OS instalados] em um computador. É possível??<br />
<br />
==Sistema de Arquivos==<br />
<br />
*Forma como estão estruturados/organizados os arquivos/dados em uma determinada mídia [https://pt.wikipedia.org/wiki/Sistema_de_ficheiros];<br />
*Um sistema operacional deve saber como acessar e operar sobre este sistema;<br />
*Tipos de sistemas: ext4, NTFS, VFAT32<br />
<br />
==Exemplos de SO==<br />
<br />
*Unix<br />
*Microsoft DOS<br />
*IBM<br />
*Microsoft Windows<br />
*netBSD, freeBSD, openBSD<br />
*Linux<br />
*macOS<br />
*Android<br />
*iOS<br />
<br />
==Histórico do Linux==<br />
<br />
*O início de tudo: UNIX;<br />
*Surgiu em 1991 quando Linus Torvalds, um estudante finlandês, resolveu desenvolver um sistema operacional compatível com a POSIX, por em que pudesse ser executado em arquitetura x86;<br />
*Linux está sob uma licença de software livre e diversas pessoas e empresas contribuem para o desenvolvimento do mesmo.<br />
*E o que é [https://pt.wikipedia.org/wiki/POSIX POSIX]? Define padrões para a interface de programação de aplicações (API) de um OS de forma a manter compatibilidade com o UNIX;<br />
<br />
==Arquitetura do Linux==<br />
<br />
*Ver pg.16 a 19 de [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo]<br />
<br />
==Distribuições==<br />
<br />
Uma distribuição Linux consiste de um kernel Linux e uma coleção de software utilitários e aplicativos de usuário (baseado slides Prof. Emerson)<br />
**Redhat<br />
**Slackware<br />
**Debian<br />
**Ubuntu<br />
**OpenSuse<br />
**Fedora<br />
**CentOS<br />
**Kali<br />
<br />
<br />
Algumas distribuições podem ser executadas diretamente no CD/pendrive<br />
sem a necessidade de fazer sua instalação no disco rígido do computador<br />
<br />
==Distribuições aqui no IFSC SJ==<br />
<br />
*Ubuntu<br />
*Ubuntu Mate (fork do Ubuntu)<br />
*Debian<br />
<br />
==Ligando e Desligando o Sistema Linux==<br />
<br />
*Cuidado ao desligar um OS como o Linux!!! Dados podem ser perdidos.<br />
*Ver [https://pt.wikibooks.org/wiki/Guia_do_Linux/Iniciante%2BIntermedi%C3%A1rio/Introdu%C3%A7%C3%A3o/Ligando_o_computador]<br />
<br />
==O Desktop do Ubuntu - Primeiras Considerações==<br />
<br />
*O Desktop no Ubuntu ver[https://help.ubuntu.com/stable/ubuntu-help/shell-overview.html]<br />
<br />
=AULA 2 - Dia 14/03/2019=<br />
<br />
==Objetivos==<br />
<br />
===PARTE 1===<br />
<br />
*Revisão da aula passada;<br />
*repassar itens não mencionados na aula passada;<br />
**Paginação e Memória [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo pg.19]<br />
**Estrutura do Linux [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo pg.18]<br />
<br />
===PARTE 2===<br />
<br />
*Operações com arquivos e diretórios usando o terminal;<br />
*formato de um comando básico;<br />
*quase tudo no Linux é arquivo: tipos de arquivos, diretórios, arquivos ordinários;<br />
*conceito de sistema de arquivos;<br />
*conceito de referência absoluta e relativa;<br />
*conceito de diretório de entrada, diretório de trabalho;<br />
*mudando de diretório com cd;<br />
*listando diretórios e arquivos com ls;<br />
*vendo o significado de um comando com man;<br />
*criando diretórios com mkdir;<br />
*removendo diretórios e arquivos com rmdir e rm;<br />
*referência com . .. - ~<br />
*criando arquivos ordinários com touch;<br />
*arquivos e diretórios escondidos;<br />
*copiando arquivos;<br />
*movendo e renomeando arquivos;<br />
*vendo a história de comandos com history;<br />
<br />
==Conceito de sistemas de arquivos, arquivos e diretórios==<br />
<br />
* [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Sistemas de Arquivos pg.18]<br />
* [Estrutura básica de diretórios do Sistema Linux]<br />
<br />
==Comandos no Linux==<br />
<br />
* [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Comandos e Interpretador de Comandos no Linux pg.18]<br />
<br />
==Tipos de Arquivos==<br />
<br />
* [https://pt.scribd.com/doc/128912228/Administracao-de-Sistemas-Linux Tipos de Arquivos 12,13 e 14 ]<br />
<br />
==Os comandos de operação sobre arquivos e diretórios==<br />
<br />
*[https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Interpretador de comandos - Comandos Básicos - pg.20 e 21]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_2_FICLinux.pdf Ver lista de exercícios da Aula 2]<br />
<!-- *[https://www.dropbox.com/s/g3xr3wimffde2zm/Aula2_Linux_OperacoesComArquivos_2.pdf Ver lista de exercícios da Aula 3] --><br />
<br />
=AULA 3 - Dia 21/03/2019 (aula com Prof. Eraldo)=<br />
<br />
==Objetivos==<br />
<br />
===PARTE 1===<br />
<br />
*Rever comandos básicos de operações sobre arquivos;<br />
*Usar coringas<br />
*usar opções do comando ls<br />
<br />
===PARTE 2===<br />
<br />
*uso do editor gedit para criar arquivos texto;<br />
*usar comandos cat, more e less para visualizar conteúdos de arquivos.<br />
<br />
===PARTE 3===<br />
<br />
*Criar Links simbólicos<br />
<br />
===Parte 4===<br />
<br />
*Redirecionamento de entradas e saídas;<br />
*Pipes<br />
<br />
==Exercícios para esta aula==<br />
'''Créditos e agradecimentos ao Prof. Eraldo pelo desenvolvimento das listas utilizadas''':<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_3_FICLinux.pdf Mais operações Sobre Arquivos e Diretórios]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_4_FICLinux.pdf Editor Gedit, Link Simbólico]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_5_FICLinux.pdf Editor vi]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_6_FICLinux.pdf Entradas e Saídas]<br />
<br />
=AULA 4 - Dia 26/03/2019=<br />
<br />
==Objetivos==<br />
<br />
===PARTE 1===<br />
<br />
*Revisão geral<br />
<br />
<br />
===PARTE 2===<br />
<br />
*Redirecionamento de entradas e saídas: continuação;<br />
*Pipes<br />
<br />
===PARTE 3===<br />
<br />
*Permissão no acesso a arquivos;<br />
*Owner, grupo e outros<br />
<br />
==Exercícios para esta aula==<br />
<br />
=Referências=<br />
<br />
[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_7_FICLinux.pdf Permissão de Acesso a Arquivos: parte 1]<br />
<br />
[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_8_FICLinux.pdf Permissão de Acesso a Arquivos: parte 2]<br />
<br />
=AULA 5 - Dia 28/03/2019=<br />
<br />
==Objetivos==<br />
<br />
*Revisão e preparação para teste;<br />
*introdução ao gerenciamento de processos;<br />
**conceito de processo<br />
**escalonamento de processos<br />
**PID e PPID<br />
**fork/exec<br />
**espaço de endereçamento de um processo;<br />
**estados de um processo: Running, Stopped, Sleeping, Zombie<br />
<br />
https://www.tecmint.com/linux-process-management/<br />
<br />
==Referências==<br />
<br />
[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_9_FICLinux.pdf Gerenciamento De Processos Parte 1]<br />
[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_10_FICLinux.pdf Gerenciamento De Processos Parte 2]<br />
<br />
[https://www.dropbox.com/s/gm1sv856ailny2e/Aula5_TreinamentoTeste.pdf Treinamento Teste 1]<br />
<br />
=AULA 6 - Dia 02/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*Comandos adicionais de gerenciamento de processos;<br />
*Mudança de prioridade com nice e renice;<br />
*Agendamento de processos com crontab<br />
*Aplicações do crontab: conectividade de rede e backup<br />
*Ferramentas de compactação;<br />
*Execução de comandos inseridos em outros comandos;<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/z1d0itcz9ommhrm/Aula6_Aval1.pdf Avaliação 1]<br />
<br />
=AULA 7 - Dia 04/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*Comandos adicionais de manipulação de arquivos:<br />
**comando grep;<br />
**comando find;<br />
*Gerenciamento de usuários:<br />
**adição e remoção de usuários e grupos<br />
**arquivo sudoers<br />
<br />
<br />
==Exercícios==<br />
<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_11_FICLinux.pdf Comandos Adicionais] <br />
<!--*[https://www.dropbox.com/s/h0v122is4aj9ogr/Aula7_GerenciamentoDeUsuarios_Parte1.pdf Aula 7 - Parte 2]--><br />
<br />
=AULA 8 - Dia 09/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*Introdução ao Shell script<br />
*variáveis<br />
*Comando if<br />
<br />
==Referências==<br />
<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_14_FICLinux.pdf Outros comando gerenciamento de processos]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_12_FICLinux.pdf Shell Parte 1]<br />
<br />
{{collapse top | script DESAFIO (a)}}<br />
<syntaxhighlight lang=c><br />
#!/bin/bash<br />
<br />
FILE="$1"<br />
<br />
if [ ! $# -eq 1 ]; then<br />
echo opa! Algo errado...<br />
echo uso: script parametro<br />
exit<br />
fi<br />
<br />
<br />
if [ -h $FILE ]; then<br />
echo $FILE é um link simbólico<br />
else<br />
echo $FILE não é um link simbólico<br />
fi<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
{{collapse top | script DESAFIO (b)}}<br />
<syntaxhighlight lang=c><br />
<br />
#!/bin/bash<br />
<br />
FILE="$1"<br />
<br />
if [ ! $# -eq 1 ]; then<br />
echo opa! Algo errado...<br />
echo uso: script parametro<br />
exit<br />
fi<br />
<br />
<br />
if [[ -w $FILE && -O $FILE ]]; then<br />
echo Possui permissao de escrita de $FILE<br />
else<br />
echo Colocando permissão de escrita para $FILE<br />
chmod u+w $FILE<br />
echo permissoes adicionadas com sucesso para $FILE ver abaixo<br />
ls -l $FILE<br />
<br />
fi<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
{{collapse top | script DESAFIO (c)}}<br />
<syntaxhighlight lang=c><br />
#!/bin/bash<br />
<br />
FILE1="$1"<br />
FILE2="$2"<br />
<br />
if [ ! $# -eq 2 ]; then<br />
echo opa! Algo errado...<br />
echo uso: script parametro<br />
exit<br />
fi<br />
<br />
if [[ -f $FILE1 && -r $FILE1 ]]; then<br />
echo $1 É regular e possui permissao de leitura<br />
mv $FILE1 $FILE2<br />
echo Mudei o nome de $FILE1 para $FILE2<br />
else<br />
echo $FILE1 não tem permissao...<br />
fi<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
=AULA 9 - Dia 11/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*ainda shell script<br />
*comando for<br />
*comando while<br />
<br />
==Referências==<br />
<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_13_FICLinux.pdf Shell Parte 2]<br />
<br />
=AULA 10 - Dia 16/04/2019=<br />
<br />
*Avaliação da disciplina<br />
<br />
=Tópicos extras=<br />
<br />
==Objetivos==<br />
<br />
*mais alguns tópicos sobre criação de usuários;<br />
*servidores de janelas: X11, <br />
*gerenciadores de janelas e desktops: Gnome, KDE<br />
*instalação de pacotes;<br />
*o Linux e o Software Livre<br />
*avaliação<br />
<br />
==Servidores de Janelas==<br />
<br />
[https://pt.wikipedia.org/wiki/X_Window_System X Windows System]<br />
<br />
[https://en.wikipedia.org/wiki/X_Window_System_protocols_and_architecture Arquitetura do X]<br />
<br />
==Desktops e Geneciadores de Janelas==<br />
<br />
[https://pt.wikipedia.org/wiki/Interface_gr%C3%A1fica_do_utilizador Interfaces Gráficas]<br />
<br />
==Instalando pacotes==<br />
<br />
[https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Ver pg.43 do Formacao-de-Suporte-Tecnico-Proinfo]<br />
<br />
[http://www.hardware.com.br/tutoriais/tutorial-completo-apt-get/ uso do apt-get]<br />
<br />
Exercício: instalar e executar um servidor ssh:<br />
<br />
sudo apt-get update<br />
sudo apt-get install openssh-server<br />
sudo service start ssh<br />
<br />
Acessar o ssh de outra máquina<br />
ssh usuario@numero_ip<br />
<br />
Exportar o display e executar o comando remoto:<br />
export DISPLAY=IP_cliente_ssh:0.0<br />
firefox &<br />
<br />
Conferir se o firefox realmente está se executando (use o ps)<br />
<br />
Remover o pacote ssh server:<br />
<br />
sudo apt-get remove openssh-server<br />
<br />
==Linux = Software Livre==<br />
<br />
[https://pt.wikipedia.org/wiki/Software_livre]<br />
<br />
<br />
<br />
[https://www.novell.com/coolsolutions/feature/1532.html]<br />
<br />
==Onde baixar o Ubuntu==<br />
<br />
[https://www.ubuntu.com/download/desktop Baixar Ubuntu daqui]<br />
<br />
==Sobre o Boot==<br />
<br />
[http://www.rodsbooks.com/linux-uefi/ by Roderick W. Smith]<br />
<br />
[https://www.happyassassin.net/2014/01/25/uefi-boot-how-does-that-actually-work-then/ AdamW on Linux and more]<br />
<br />
==Sobre o Desktop Environment e o Desktop Shell==<br />
<br />
[https://ittutorials.net/linux/ubuntu/desktop-guide/ /desktop-guide]<br />
<br />
==Instalar Ubuntu no Virtual Box==<br />
<br />
[http://www.edivaldobrito.com.br/virtualbox-no-linux/ Instalar VirtualBox no Linux]<br />
<br />
[http://www.bosontreinamentos.com.br/virtualizacao/como-instalar-o-virtualbox-no-windows-para-criacao-de-maquinas-virtuais/ Instalar VirtualBox no Windows]<br />
<br />
[http://www.techtudo.com.br/dicas-e-tutoriais/noticia/2016/04/como-instalar-o-ubuntu-com-o-virtualbox.html Instalar Linux no VirtualBox]<br />
<br />
=AULA 11 - Dia 23/04/2019=<br />
<br />
*Introdução a Redes de Computadores<br />
**Conceito Básicos em Redes e Protocolos<br />
**Ferramentas de Redes<br />
**Exemplo de Protocolo de Aplicação: http<br />
**O processo de encapsulamento<br />
<br />
==Plano de Ensino==<br />
<br />
*[https://wiki.sj.ifsc.edu.br/index.php/PRL-FicLinux_(Plano_de_Ensino) Plano de Ensino]<br />
<br />
<br />
==Laboratório 1 - Ferramentas de Rede e Conceitos Básicos==<br />
<br />
*Familiarização com a infraestrutura dos laboratórios de redes<br />
*Familiarização com ferramentas de rede: ifconfig, ping, traceroute;<br />
*Desenvolver a noção de endereçamentos de rede IP e de endereço de hardware (MAC)<br />
*Desenvolver a noção de rotas em redes IP<br />
*Testar a conectividade IP com ping<br />
<br />
*Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)]<br />
<br />
==Laboratório 2 - Wireshark e encapsulamento==<br />
<br />
*Familiarização com o sniffer de rede WireShark<br />
*Observar o comportamento do ping e se familiarizar com o processo de encapsulamento;<br />
<br />
**Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)]<br />
<br />
==Conceituando Protocolos e Aplicações de Rede==<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/Conceituando%20protocolos.pdf Conceituando protocolos]<br />
<br />
=AULA 12 - Dia 25/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*Protocolos de aplicação: exemplo http<br />
<br />
==Laboratório 4 - Desvendando o HTTP com Wireshark - BÁSICO==<br />
<br />
Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)#Parte_1:_Observando_interfaces_do_sistema_com_ifconfig]<br />
<br />
=AULA 13 - Dia 30/04/2019=<br />
<br />
*Revisão do Conceito de Protocolo ([-] Laboratório 3 - Conceituando protocolos )<br />
*O DNS como protocolo de Aplicação;<br />
*Camada de Transporte: protocolo UDP<br />
<br />
==Revisão dos Conceitos de Protocolo==<br />
<br />
Laboratório 3 - Conceituando protocolos [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)#Parte_1:_Observando_interfaces_do_sistema_com_ifconfig]<br />
<br />
==O DNS como protocolo de Aplicação==<br />
<br />
Laboratório 7 - Serviço de Nomes (DNS) [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)#Parte_1:_Observando_interfaces_do_sistema_com_ifconfig]<br />
<br />
==O Protocolo UDP==<br />
<br />
Laboratório 8 - Desvendando o UDP - Básico <br />
<br />
=AULA 14 - Dia 02/05/2019=<br />
<br />
==Objetivos==<br />
<br />
*Explorar o papel e diferenças dos protocolos de Transporte TCP/UDP<br />
*Explorar a Camada IP e aspectos da configuração da mesma sob o Linux<br />
<br />
<br />
===TCP e UDP===<br />
<br />
*docente.ifsc.edu.br/odilson/RCO60803/TCP%20controle%20de%20erros.pdf<br />
*docente.ifsc.edu.br/odilson/RCO60803/UDP%20Basico.pdf<br />
<br />
==Camada IP no Linux: Configuração das Interfaces usando ifconfig e ip addr==<br />
<br />
Usando a ferramenta Netkit2, que permite construir redes virtuais com o Linux vamos construir DUAS redes locais interligadas por um roteador. Em cada rede colocaremos dois PCs. As interfaces estarão completamente desconfiguradas:<br />
<br />
<ol><br />
<li><br />
Construir um arquivo texto de nome rede.conf usando o editor de texto gedit.<br />
<code>gedit rede.conf &</syntaxhighlight> <br />
</li><br />
<li><br />
Criar a seguinte topologia:<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=generic<br />
<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
#Definição da Topologia da Rede<br />
<br />
pc1[eth0]=lan0<br />
pc2[eth0]=lan0<br />
<br />
pc3[eth0]=lan1<br />
pc4[eth0]=lan1<br />
<br />
r1[eth0]=lan0<br />
r1[eth1]=lan1<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Executar netkit fazendo (atualize se necessário - pergunte para o professor como fazer):<br />
Aplicativos >> Educativo >> Netkit2 <br />
</li><br />
<li><br />
Carregar o arquivo lab.conf a partir do Netkit2:<br />
<code>File >> Load Only</syntaxhighlight><br />
</li><br />
<li><br />
Visualizar a rede a ser implementada:<br />
<code>File >> Graph</syntaxhighlight><br />
</li><br />
<li> <br />
Executar a configuração:<br />
<code>Network >> Start</syntaxhighlight><br />
</li><br />
<li><br />
Verificar o estado de todas interfaces (se UP ou DOWN) com:<br />
<code>ifconfig -a</syntaxhighlight><br />
<code>ip addr</syntaxhighlight> <br />
Note que nas últimas versões do Linux o comando ip vem sendo recomendado (embora o ifconfig ainda esteja disponível).<br />
</li><br />
<li><br />
Vamos configurar as interfaces. Para tanto vamos assumir que teremos duas sub-redes:<br />
<code>lan0 - endereço da rede 10.10.10.0/24</syntaxhighlight><br />
<code>lan1 - endereço da rede 20.20.20.0/24</syntaxhighlight><br />
A interface eth0 de PC1 receberá o endereço 10.10.10.1/24 e a interface eth0 de PC2 recebera 10.10.10.2/24. A interface do roteador NA lan0 também deve receber um endereço: 10.10.10.254/24:<br />
<br />
No PC1:<br />
<code>ifconfig eth0 10.10.10.1/24</syntaxhighlight><br />
No PC2:<br />
<code>ifconfig eth0 10.10.10.2/24</syntaxhighlight><br />
No R1:<br />
<code>ifconfig eth0 10.10.10.254/24</syntaxhighlight><br />
</li> <br />
<li><br />
Seguindo a mesma lógica configure as máquinas e o roteador na lan1<br />
</li><br />
<li> Um ponto importante a ser lembrado é que quando uma interface é configurada com um número IP, a tabela de roteamento do sistema é alimentada com o número correspondente da rede associada ao número. Isto pode ser observado em TODAS as máquinas, inclusive no roteador:<br />
<code> route -n </syntaxhighlight><br />
ou <br />
<code> ip route </syntaxhighlight><br />
</li><br />
</ol><br />
<br />
==Camada IP no Linux: verificando e configurando rotas - configuração da rota default ==<br />
<br />
<ol><br />
<li> Um ponto importante a ser lembrado é que quando uma interface é configurada com um número IP, a tabela de roteamento do sistema é alimentada com o número correspondente da rede associada ao número. Isto pode ser observado em TODAS as máquinas, inclusive no roteador:<br />
<code> route -n </syntaxhighlight><br />
ou <br />
<code> ip route </syntaxhighlight><br />
Esta informação é importante pois define a entrega DIRETA de pacotes na rede, ou seja, se PC1 quiser enviar um pacote para PC2, esta linha na tabela de roteamento garante que o pacote IP seja despachado diretamente para o PC2 através de um frame ETHERNET endereçado para o MAC do PC1.<br />
</li><br />
<li> Confira os endereços MAC e IP das interfaces dos PC1 e PC2 e anote. Faça um ping no PC1 em direção a PC2.<br />
<code>root@pc1:~# ping 10.10.10.2</syntaxhighlight><br />
</li><br />
<li> Use um capturador de pacotes em modo texto para observar o tráfego na eth0 do PC2. Observe os endereços MAC do Frame Ethernet e os endereços IP do pacote IP.<br />
<code>root@pc2:~# tcpdump -i eth0 -e</syntaxhighlight><br />
ENTÃO? O que se pode concluir? É uma entrega direta ou indireta? <br />
</li><br />
<li> Uma curiosidade. Tente observar o tráfego na interface eth0 do Roteador R1. É possível observar algo? O que se pode concluir? Pare agora o ping e os tcpdumps executados.<br />
</li><br />
<li> Qualquer máquina IP acaba tomando uma decisão de roteamento. O PC1, ao observar que PC2 está na sua própria rede 10.10.10.0/24, entrega diretamente o pacote. E se PC1 tentar entregar para PC3? Faça um ping e observe o que acontece:<br />
<code>root@pc1:~#ping 20.20.20.1</syntaxhighlight><br />
Não deve ter funcionado :-(<br />
Um primeiro problema é que simplesmente a camada IP observa que o endereço não é entrega DIRETA mas não tem informação (linha) na tabela de roteamento dizendo para quem deve ser entregue o pacote. <br />
</li><br />
<li> Vamos acrescentar uma linha na tabela de PC1 dizendo como fazer esta entrega INDIRETA. Usaremos o conceito de gateway default. Ou seja, se não tiver para quem entregar explicitamente, o pacote será entregue para o gateway default:<br />
<code>root@pc1:~# route add default gateway 10.10.10.254</syntaxhighlight><br />
confira o estabelocimento da rota:<br />
<code>root@pc1:~# route -n</syntaxhighlight><br />
tente o ping novamente escutando com o tcpdump na interface eth0 de R1. Ainda não funcionou mas o R1 já recebe os pacotes. Confira o MAC de destino do pacote. Deve ser o MAC do roteador. <br />
</li> <br />
<li><br />
POR QUE NÃO FUNCIONOU: será que R1 não sabe como entregar o pacote para PC3? Confira se o pacote sai de R1 na rede lan1:<br />
<code>root@r1:~# tcpdump -i eth2 -e</syntaxhighlight><br />
</li> <br />
<li><br />
Temos um problema ainda que o nosso roteador Linux NÃO está habilitado a ser roteador. Isto pode ser feito com:<br />
<code>echo 1 > /proc/sys/net/ipv4/ip_forward</syntaxhighlight><br />
</li> <br />
<li> Tente novamente o ping de PC1 para PC3. Ainda não funcionará mas escute a interface eth1 de R1 e a interface eth0 de PC3 e verá que os pacotes do ICMP REQUEST estão chegando. Confira inclusive os MACs envolvidos...<br />
</li><br />
<li><br />
O que estaria faltando ainda para que PC3 responda aos ECHO REQUEST? O problema é de entrega indireta. O PC3 não sabe como entregar pacotes "externos". Acrescente um gateway default.<br />
</li><br />
<li><br />
Exercício adicional com 2 roteadores. Ver manual:<br />
* [http://linux-ip.net/html Guia de Administração da Camada IP no Linux<br />
</li><br />
</ol><br />
<br />
==Exercício: acrescentando uma lan2 com com 2 PCs no roteador==<br />
<br />
Acrescente uma rede 30.30.30.0/24 (lan2) no roteador R1. Acrescente 2 PCs e configure o sistema.<br />
Teste a conectividade entre todos os PCs.<br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
pc5[type]=generic<br />
pc6[type]=generic<br />
<br />
pc7[type]=generic<br />
pc8[type]=generic<br />
<br />
<br />
#Definição da Topologia da Rede<br />
<br />
pc1[eth0]=lan0:ip=10.10.10.1/24<br />
pc1[default_gateway]=10.10.10.254<br />
<br />
pc2[eth0]=lan0:ip=10.10.10.2/24<br />
pc2[default_gateway]=10.10.10.254<br />
<br />
pc3[eth0]=lan1:ip=20.20.20.1/24<br />
pc3[default_gateway]=20.20.20.254<br />
<br />
pc4[eth0]=lan1:ip=20.20.20.2/24<br />
pc4[default_gateway]=20.20.20.254<br />
<br />
pc5[eth0]=lan2:ip=30.30.30.1/24<br />
pc5[default_gateway]=30.30.30.254<br />
<br />
pc6[eth0]=lan2:ip=30.30.30.2/24<br />
pc6[default_gateway]=30.30.30.254<br />
<br />
pc7[eth0]=lan4:ip=40.40.40.1/24<br />
pc7[default_gateway]=40.40.40.254<br />
<br />
pc8[eth0]=lan3:ip=50.50.50.1/24<br />
pc8[default_gateway]=40.40.40.254<br />
<br />
<br />
r1[eth0]=lan0:ip=10.10.10.254/24<br />
r1[eth1]=lan1:ip=20.20.20.254/24<br />
r1[eth2]=lan2:ip=30.30.30.254/24<br />
r1[eth3]=lan3:ip=50.50.50.253/24<br />
r2[eth1]=lan3:ip=50.50.50.254/24<br />
r2[eth0]=lan4:ip=40.40.40.254/24<br />
<br />
r2[route]=10.10.10.0/24:gateway=50.50.50.253<br />
<br />
</syntaxhighlight><br />
<br />
=AULA 15 - Dia 7/05/2019=<br />
<br />
*Hubs X Switches. O Papel do Protocolo ARP<br />
<br />
<br />
*Serviço DHCP e NAT<br />
[-] Laboratório 16 - Sub-redes e Roteamento Estático em Redes <br />
<br />
==Hubs, Switches. Protocolo ARP==<br />
<br />
[Laboratório 17 - Tecnologia de Enlace Ethernet]<br />
<br />
==Serviço DHCP==<br />
<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IP_DHCP_NAT.pdf DHCP e NAT]<br />
<br />
Construir uma rede simular a aula anterior mas deixar PC1 e PC2 desconfigurados. Criar uma máquina para atuar como servidor DHCP. <br />
<br />
<ol><br />
<li><br />
Editar o arquivo de configuração do dhcp server:<br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=gateway #já habilitado para forward<br />
<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
pcdhcp[type]=generic<br />
<br />
<br />
#Definição da Topologia da Rede<br />
<br />
pc1[eth0]=lan0 #desconfigurada...<br />
<br />
pc2[eth0]=lan0:ip=10.10.10.2/24<br />
pc2[default_gateway]=10.10.10.254<br />
<br />
pcdhcp[eth0]=lan0:ip=10.10.10.3/24<br />
pcdhcp[default_gateway]=10.10.10.254 <br />
<br />
pc3[eth0]=lan1:ip=20.20.20.1/24<br />
pc3[default_gateway]=20.20.20.254<br />
<br />
pc4[eth0]=lan1:ip=20.20.20.2/24<br />
pc4[default_gateway]=20.20.20.254<br />
<br />
<br />
r1[eth0]=lan0:ip=10.10.10.254/24<br />
r1[eth1]=lan1:ip=20.20.20.254/24<br />
<br />
</syntaxhighlight><br />
</li><br />
<li> No server estabelecer a configuração desejada:<br />
<br />
nano /etc/dhcp/dhcpd.conf<br />
<br />
com:<br />
<br />
<code><br />
<br />
subnet 10.10.10.0 netmask 255.255.255.0 {<br />
range 10.10.10.10 10.10.10.50;<br />
option routers 10.10.10.254;<br />
option broadcast-address 10.10.10.255;<br />
default-lease-time 600;<br />
max-lease-time 7200;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
</li><br />
<li><br />
Rodar o servidor DHCP na máquina pc_dhcp:<br />
<code><br />
/usr/sbin/dhcpd -q -4 -pf /run/dhcp-server/dhcpd.pid -cf /etc/dhcp/dhcpd.conf eth0<br />
</syntaxhighlight><br />
</li><br />
<li><br />
No cliente (PC1) fazer:<br />
<code><br />
dhclient -v eth0<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Usando o ifconfig e route confira se o PC1 está completamente configurado. Faça teste com o ping<br />
</li><br />
<li> Rode o tcpdump na eth0 de r1 para "verificar" os pacotes DHCP:<br />
<code><br />
tcpdump -i eth0<br />
</syntaxhighlight><br />
</li><br />
<li> Repetir a operação no PC2. Baixe a interface antes:<br />
<code><br />
ifconfig eth0 down<br />
dhclient -v eth0<br />
</syntaxhighlight><br />
</li><br />
</ol><br />
<br />
==O NAT==<br />
<br />
Vamos tentar elaborar um laboratório usando o NAT MASQUERADE<br />
https://www.karlrupp.net/en/computer/nat_tutorial<br />
<br />
Construir uma rede com 3 LANs e 2 roteadores como na aula passada. Executar o APACHE em uma máquina da lan3 (exemplo PC4). Não colocar rotas para lan0 em r2. Desta forma PC1 não deve pingar em PC4. <br />
<br />
<code><br />
LAN0 <-R1-> LAN1 <-R2 -> LAN3<br />
</syntaxhighlight><br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
pc1[type]=generic<br />
apache[type]=generic<br />
<br />
<br />
pc1[eth0]=lan0:ip=10.10.10.1/24<br />
pc1[default_gateway]=10.10.10.254<br />
<br />
<br />
r1[eth0]=lan0:ip=10.10.10.254/24<br />
r1[eth1]=lan1:ip=20.20.20.254/24<br />
r1[route]=30.30.30.0/24:gateway=20.20.20.253<br />
<br />
r2[eth0]=lan1:ip=20.20.20.253/24<br />
r2[eth1]=lan2:ip=30.30.30.254/24<br />
<br />
apache[eth0]=lan2:ip=30.30.30.1/24<br />
apache[default_gateway]=30.30.30.254<br />
</syntaxhighlight><br />
<br />
<ol><br />
<li> Rodar o apache em PC4:<br />
<code> /etc/init.d/apache2 start </syntaxhighlight><br />
</li><br />
<li> Testar se o Apache é acessível a partir de PC3<br />
<code>lynx END_PC3 </syntaxhighlight><br />
<li><br />
Em R1 fazer:<br />
<code>iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE</syntaxhighlight><br />
</li><br />
<li> Monitorar os pacotes que chegam e saem da eth0 de PC4.<br />
</li><br />
<li> Fazer em PC1:<br />
lynx END_PC4 #endereço de PC4.<br />
O que se pode concluir?<br />
</li><br />
<br />
</ol><br />
<br />
=AULA 16 - Dia 09/05/2019=<br />
*Endereçamento IPv4.<br />
*Exercícios segmentação Redes. <br />
<br />
===Objetivos===<br />
*Compreender endereçamento IPv4.<br />
*Compreender o processo de alocação de faixas de IPs.<br />
*Compreender e manipular os números IPs.<br />
*Compreender e manipular as máscaras de rede.<br />
*Proporcionar ao aluno uma visão prática de roteamento IP.<br />
<br />
===Fonte Básica===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IP_DHCP_NAT.pdf DHCP e NAT]<br />
*[http://www.davidc.net/sites/default/subnets/subnets.html Cálculo de sub-redes]<br />
<br />
===Roteiro===<br />
<br />
#Baseado no arquivo exemplo abaixo, crie um arquivo de configuração para o NetKit que implemente sua proposta. O arquivo deve contemplar todas as configurações necessárias para o perfeito funcionamento da rede, ou seja, ao carregar o arquivo todos os hosts deverão ser capazes de "pingar" uma ao outro. <br />
##Faça testes de conectividade entre os hosts.<br />
##Demonstre para o professor o perfeito funcionamento de sua rede.<br />
*O arquivo de configuração do Netkit abaixo, é a definição para o funcionamento da simulação da rede apresentada na Figura 2. Falta adicionar as rotas.<br />
<br />
[[Arquivo:DynamicRoutingTriangle.png |thumb | 400px| Figura 2 - Rede exemplo]]<br />
<br />
<code><br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=link0:ip=192.168.0.1/24<br />
pc2[eth0]=link1:ip=192.168.1.1/24<br />
pc3[eth0]=link2:ip=192.168.2.1/24<br />
<br />
# Default gateways definitions<br />
pc1[default_gateway]=192.168.0.254<br />
pc2[default_gateway]=192.168.1.254<br />
pc3[default_gateway]=192.168.2.254<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
r3[type]=gateway<br />
<br />
# Routers' interfaces to local networks<br />
r1[eth0]=link0:ip=192.168.0.254/24<br />
r2[eth0]=link1:ip=192.168.1.254/24<br />
r3[eth0]=link2:ip=192.168.2.254/24<br />
<br />
# Network "backbone" links<br />
r1[eth1]=backbone0:ip=10.0.0.1/30<br />
r1[eth2]=backbone1:ip=10.0.1.1/30<br />
<br />
r2[eth1]=backbone0:ip=10.0.0.2/30<br />
r2[eth2]=backbone2:ip=10.0.2.1/30<br />
<br />
r3[eth1]=backbone1:ip=10.0.1.2/30<br />
r3[eth2]=backbone2:ip=10.0.2.2/30 <br />
<br />
# Routes definition<br />
r1[route]=192.168.2.0/24:gateway=10.0.1.2<br />
r1[route]=192.168.1.0/24:gateway=10.0.0.2<br />
r1[route]=10.0.2.0/30:gateway=10.0.0.2<br />
<br />
r2[route]=192.168.0.0/24:gateway=10.0.0.1 <br />
r2[route]=192.168.2.0/24:gateway=10.0.2.2<br />
r2[route]=10.0.1.0/30:gateway=10.0.2.2<br />
<br />
r3[route]=192.168.0.0/24:gateway=10.0.1.1<br />
r3[route]=192.168.1.0/24:gateway=10.0.2.1<br />
r3[route]=10.0.0.0/30:gateway=10.0.2.1<br />
</syntaxhighlight><br />
<br />
===Exercícios Extras (resolvidos)===<br />
*[[Arquivo:exercicios_CIDR.pdf]]<br />
<br />
===Referencia===<br />
*[http://www.davidc.net/sites/default/subnets/subnets.html Link Calculador Online de Subnets]<br />
<br />
=AULA 17 - Dia 14/05/2019=<br />
<br />
*Finalização do Laboratório do NAT<br />
*Laboratório de Introdução ao IPV6<br />
*Introdução ao Access Point TPLINK N750: configuração da LAN e WAN<br />
<br />
==LAboratório de Introdução ao IPv6==<br />
<br />
===Material de REferência===<br />
<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IPv6.pdf IPv6]<br />
<br />
===Roteiro de atividades sobre o IPv6===<br />
<br />
A figura abaixo apresenta o diagrama esquemático da rede a ser montada/analisada. Observe que todos os IPv6 ''Global Unicast'' já estão definidos na mesma, são esses IPs que utilizaremos em nosso experimento.<br />
<br />
[[Arquivo:Diagrama_rede_IPv6.jpg]]<br />
<br />
#Crie em seu computador um arquivo com nome '''/home/aluno/IPv6.conf''', com o seguinte conteúdo: <syntaxhighlight lang=bash><br />
#Ligacao das maquinas nos dominios de colisao<br />
#Duas pequenas redes interligadas pelo backbone<br />
<br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=link0:ipv6=2001:bcc:faca:1::101/64<br />
pc2[eth0]=link1:ipv6=2001:bcc:cafe:1::102/64<br />
pc3[eth0]=HUB1:ipv6=2001:bcc:1f0:1::103/64<br />
pc4[eth0]=HUB1<br />
<br />
#Default Gateways definitions<br />
pc1[route]=default6:gateway=2001:bcc:faca:1::1<br />
pc2[route]=default6:gateway=2001:bcc:cafe:1::1<br />
pc3[route]=default6:gateway=2001:bcc:1f0:1::1<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
#Routers interfaces definitions<br />
r1[eth0]=backbone0:ipv6=2001:db8:dead:1::1/64<br />
r1[eth1]=link0:ipv6=2001:bcc:faca:1::1/64<br />
r1[eth2]=link1:ipv6=2001:bcc:cafe:1::1/64<br />
<br />
r2[eth0]=backbone0:ipv6=2001:db8:dead:1::2/64<br />
r2[eth1]=HUB1:ipv6=2001:bcc:1f0:1::1/64<br />
<br />
#Routers definitions<br />
r1[route]=2001:bcc:1f0:1::0/64:gateway=2001:db8:dead:1::2<br />
r2[route]=2001:bcc:faca:1::0/64:gateway=2001:db8:dead:1::1<br />
r2[route]=2001:bcc:cafe:1::0/64:gateway=2001:db8:dead:1::1<br />
</syntaxhighlight><br />
#Tenha certeza que o Netkit2 estja atualizado: General >> Update.<br />
#Rode o NetKit em seu computador. Em um terminal digite: <syntaxhighlight lang=bash><br />
netkit2 & </syntaxhighlight><br />
#No menu '''File''' - '''Load and Run''', procure o arquivo '''/home/aluno/IPv6.conf''' e clique em OK. Abrirá uma janela com 6 abas, onde cada uma delas é um terminal de configuração do respectivo equipamento: '''pc1-4''' ou '''r1-2'''.<br />
#Observe que o '''pc4''' não está com sua interface configurada.<br />
#Ao clicar no menu '''File''' - '''Graph''', pode-se ter uma visão da rede a ser simulada e conferir se é equivalente ao diagrama proposto.<br />
#Faça um '''ping6''' entre o '''pc1''' ao '''pc3''': <syntaxhighlight lang=bash><br />
ping6 -c4 2001:bcc:1f0:1::103 </syntaxhighlight><br />
#Faça um '''ping6''' entre o '''pc1''' e '''pc2'''.<br />
#No '''pc4''' use o seguinte comando para adicionar o endereço IPv6 à interface de rede: <syntaxhighlight lang=bash><br />
ip addr add 2001:bcc:1f0:1::104/64 dev eth0 </syntaxhighlight><br />
#No '''pc4''', acrescente o ''default gateway'' com o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add default via 2001:bcc:1f0:1::1 dev eth0 </syntaxhighlight><br />
#No '''pc1''' use o seguinte comando para verificar como ficou a configuração dos endereços da interface de rede. O resultado é similar ao apresentado pelo comando '''ifconfig''': <syntaxhighlight lang=bash><br />
ip addr show dev eth0 </syntaxhighlight><br />
#Todo o roteamento está pronto, mas caso desejássemos poderíamos acrescentar rotas com comando similares aos já utilizados. Por exemplo, no '''r1''', para adicionar uma rota estática para a rede dos '''pc3''' e '''pc4''' utilizaríamos o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add 2001:bcc:1f0:1::/64 via 2001:db8:dead:1::2 dev eth0 </syntaxhighlight><br />
#Confira as rotas estabelecidas em todos os ''hosts'' com o comando abaixo. <br />
##São coerentes com os dados apresentados no diagrama acima?<syntaxhighlight lang=bash><br />
ip -6 route show </syntaxhighlight><br />
#No '''pc1''' use os seguintes comandos para ver a rota para alguns vizinhos: <syntaxhighlight lang=bash><br />
traceroute6 2001:bcc:1f0:1::103<br />
traceroute6 2001:bcc:1f0:1::104 </syntaxhighlight><br />
#*Anote as rotas.<br />
#Deixe um '''ping6''' entre o '''pc1''' ao '''pc3''' rodando: <syntaxhighlight lang=bash><br />
ping6 2001:bcc:1f0:1::103 </syntaxhighlight><br />
<br />
==Introdução ao Roteador-AP da TP-Link==<br />
<br />
Ver manual https://www.tp-link.com/us/support/download/tl-wdr4300/<br />
<br />
===Configuração Básica===<br />
<br />
Seguir as instruções do professor para a seguinte configuração:<br />
<br />
#Retirar o plugue cabo ethernet que liga o PC do Lab a rede do IFSC. Conectar o PC a uma das portas LAN do AP;<br />
#Conectar a WAN do AP ao Lab. do IFSC;<br />
#Em um terminal do PC aplique o comando:<br />
sudo dhclient eth0<br />
#No browser do PC acesse o AP colocando o endereço:<br />
http://tplinklogin.net<br />
#Entrar com user admin e senha admin<br />
#Configurar a WAN para DHCP (IP dinâmico)<br />
#Configurar a LAN para DHCP na faixa 192.168.0.10 a 192.168.0.100<br />
#Usar uma máquina virtual para testar a aquisição do IP:<br />
pc1[type]=generic<br />
pc1[eth0]=uplink:bridge=eth0<br />
<br />
DESAFIO 1: Elabore um experimento para mostrar que a LAN do AP funciona como um switch.<br />
Sugestão: Use uma máquina adicional colocada em uma porta do AP.<br />
<br />
DESAFIO 2: Elabore um experimento para mostrar como o NAT funciona no AP. Se inspire no experimento realizado sobre o NAT.<br />
<br />
=AULA 18 - Dia 16/05/2019=<br />
<br />
==Objetivos==<br />
<br />
<br />
PARTE 0 - Exercício de Revisão<br />
<br />
PARTE 1 - Serviços de rede sobre o Linux<br />
<br />
*serviço SSH no Linux<br />
<br />
PARTE 2 - Acesso a rede WIFI<br />
<br />
*conceitos básicos de redes sem fio: pg.103 de [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo]<br />
*configuração da WIFI no Access Point e Acesso via Linux<br />
<br />
===PARTE 0===<br />
<br />
Considere a rede abaixo definida pelo arquivo do netkit. Configure as redes com os seguintes prefixos:<br />
<br />
*lan0: 50.50.50.0/24<br />
*lan1: 60.60.60.0/24<br />
*lan2: 70.70.70.0/24<br />
<br />
O pc2dhcp deve ser configurado como servidor DHCP e deverá liberar IPs na faixa de 50.50.50.100/24 a 50.50.50.200/24. Todos os PCs receberão IP estáticos com exceção do PC1 que deverá receber dinamicamente o endereço. Toda a configuração deve ser realizada manualmente.<br />
<br />
Teste a conectividade entre todos os PCs. Usando o tcpdump demonstre que quando PC2 faz um ping em PC4 a entrega será indireta. Demonstre usando o MAC address das máquinas como apoio. Chame o professor para demonstrar.<br />
<br />
ALGUNS COMANDOS NOTÁVEIS:<br />
<br />
ifconfig<br />
ifconfig eth0 10.10.10.1/24<br />
route -n<br />
route add default gw 200.10.1.254<br />
route del -net 200.10.1.0/24 gw 200.10.2.1<br />
route add -net 200.10.1.0/24 gw 200.10.2.1<br />
<br />
tcpdump -i eth1 -n -e<br />
<br />
<code><br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2dhcp[type]=generic<br />
<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=lan0<br />
pc2dhcp[eth0]=lan0<br />
<br />
pc3[eth0]=lan1<br />
<br />
pc4[eth0]=lan2<br />
<br />
r1[eth0]=lan0<br />
r1[eth1]=lan1<br />
<br />
r2[eth0]=lan1<br />
r2[eth1]=lan2<br />
</syntaxhighlight><br />
<br />
Solução:<br />
R1:<br />
ifconfig eth0 50.50.50.254/24<br />
ifconfig eth1 60.60.60.254/24<br />
route add -net 70.70.70.0/254 gw 60.60.60.253<br />
R2:<br />
ifconfig eth1 70.70.70.254/24<br />
ifconfig eth0 60.60.60.253/24<br />
route add -net 50.50.50.0/24 gw 60.60.60.254<br />
PC2DHCP:<br />
ifconfig eth0 50.50.50.2/24<br />
route add default gateway 50.50.50.254<br />
configurar server: nano /etc/dhcp/dhcpd.conf<br />
# A slightly different configuration for an internal subnet.<br />
subnet 50.50.50.0 netmask 255.255.255.0 {<br />
range 50.50.50.100 50.50.50.200;<br />
# option domain-name-servers ns1.internal.example.org;<br />
# option domain-name "internal.example.org";<br />
option routers 50.50.50.254;<br />
option broadcast-address 50.50.50.255;<br />
default-lease-time 600;<br />
max-lease-time 7200;<br />
}<br />
<br />
/usr/sbin/dhcpd -q -4 -pf /run/dhcp-server/dhcpd.pid -cf /etc/dhcp/dhcpd.conf eth0<br />
PC3:<br />
ifconfig eth0 60.60.60.1/24<br />
route add default gw 60.60.60.254 #note que poderia ser para o outro roteador (R2)<br />
PC4:<br />
ifconfig eth0 70.70.70.1/24<br />
route add default gw 70.70.70.254<br />
PC1:<br />
dhclient eth0 -v<br />
<br />
==Serviço SSH==<br />
<br />
O Serviço SSH se utiliza do modelo cliente-servidor. Deve-se executar um servidora ssh na máquina que permitirá o acesso remoto.<br />
Um cliente a partir de uma outra máquina poderá logar remotamente usando um cliente ssh ou poderá fazer outras operações, tipo cópia remota<br />
de arquivos.<br />
<br />
===ETAPA 1 - Rodando o servidor SSH===<br />
*Baseado no Material do Prof.Odilson Valle<br />
<br />
No Ubuntu server:<br />
<ol><br />
<li><br />
<code>sudo su</syntaxhighlight><br />
<code>apt-get update</syntaxhighlight><br />
<code>apt-get install ssh</syntaxhighlight> O SSH já estará funcionando normalmente.<br />
Para configurações extras deve-se editar o arquivo /etc/ssh/sshd_config e acrescentar, por exemplo:<br />
*X11Forwarding yes (no) ### habilita/desabilita acesso com ambiente gráfico remoto<br />
*AllowUsers Fred Wilma ### Libera o acesso somente para os usuários Fred e Wilma<br />
*DenyUsers Dino Pebbles ### Bloqueia o acesso aos usuários Dino e Pebbles e libera para os demais usuários<br />
*AllowGroups admin ### Libera o acesso somente para o grupo admin.<br />
</li><br />
<li><br />
Após modificar o arquivo de configuração deve-se reiniciar o serviço: <code>service ssh restart</syntaxhighlight><br />
</li><br />
<li><br />
Criar um usuário na máquina servidora:<br />
<code>adduser alien</syntaxhighlight><br />
</li><br />
<li><br />
Logar como alien:<br />
<code>su alien</syntaxhighlight><br />
</li><br />
</ol><br />
<br />
===ETAPA 2 - Logando remotamente===<br />
<br />
<ol><br />
<li><br />
Para acessar o servidor basta digitar em um terminal: <br />
<code>ssh alien@ip_do_servidor. </syntaxhighlight> Será solicitado a senha.<br />
</li><br />
<li><br />
Confira que está "dentro" da máquina remota:<code>hostname</syntaxhighlight><br />
</li><br />
<li><br />
Confira os arquivos do diretório corrente:<code>ls -l</syntaxhighlight><br />
</li><br />
</ol><br />
<br />
<br />
===ETAPA 3 - Cópia Remota de aquivos===<br />
<br />
#Na máquina hospedeira/cliente, EM OUTRO TERMINAL, criar um arquivo qualquer usando um editor de texto:<code>gedit teste.txt &</syntaxhighlight><br />
#Envie o arquivo para a máquina servidora: <code>scp teste.txt alien@IP_MAQUINA_SERVIDORA:./</syntaxhighlight><br />
#No terminal onde está logado remotamente confira se o arquivo está copiado: <code>ls -l</syntaxhighlight><br />
#Mude o nome do arquivo: <code>mv teste.txt alfat.txt</syntaxhighlight><br />
#No terminal da máquina cliente traga novamente o arquivo: <code>scp alien@IP_MAQUINA_SERVIDORA:./alfa.txt .</syntaxhighlight><br />
#Confira se o arquivo foi copiado corretamente: <code>ls -l</syntaxhighlight><br />
<br />
==PARTE 2 - Configuração do Access Point na rede de 2.4Ghz==<br />
<br />
#Entrar na configuração do AP conforme aula anterior.<br />
#Conectara a WAN do AP na rede do laboratório e o PC em uma porta da LAN do AP.<br />
#Configurar a WAN para IP dinâmico.<br />
#Configurar a rede WIreless 2.4 Ghz:<br />
##Nome SSID: nome FIC-NomeAluno<br />
##Configurar canal AUTO e channel width para AUTO<br />
##Habilite o broadcast da rede.<br />
#Configurar segurança (Wireless Security) para WPA versão Automática, Criptografia AES e password ABCDEF<br />
#Configurar o DHCP na LAN para distribuir endereços entre 192.168.0.100 e 192.168.0.200<br />
#Salve as configurações<br />
#Reboote o roteador<br />
<br />
==Acessando a rede de dispostivo Celular==<br />
<br />
#Teste o acesso a rede a partir de um celular. No Androi ligue e desligue o wifi. Deve aparecer a lista de dispositivos.<br />
<br />
==Habilitando Filtros por MAC==<br />
<br />
*Na configuração da WLAN entre em Wireless MAC Filtering<br />
*Em Filtering Rules coloque Deny (negar)<br />
*Adicione um terminal que deseja bloquear o acesso. Utilize o MAC do seu celular (veja em configurações do telefone ou anote na opção Wireless Statistics)<br />
*Habilite o Filtro e tente se conectar<br />
<br />
OBS: Este filtro é interessante para ter maior segurança na rede, garantindo que somente dispositivos gabilitados possam acessá-la.<br />
<br />
==Coloque no ar a rede 5Ghz==<br />
<br />
Repita o procedimento da rede de 2.4Ghz e coloque-a no ar.<br />
<br />
Teste a conectividade com o celular.<br />
<br />
<br />
<br />
=AULA 19 - Dia 21/05/2019=<br />
<br />
==Objetivos==<br />
<br />
*Tópicos Adicionais sobre redes no Linux: Configuração Manual X NetworkManager<br />
**Opções de Acesso a Internet: ADSL, Cabo<br />
**Sistema de Arquivos em Rede: Samba Server<br />
*Relatório de Avaliação 1<br />
*Opções de Extensão da Rede Wireless<br />
<br />
==Tópicos Adicionais sobre redes no Linux==<br />
<br />
===Configuração da Rede no Linux - o NetworkManager===<br />
<br />
Ao longo do curso estudamos vários comandos para ver e modificar parâmetros de rede. Entretanto, em uma instalação padrão de um sistema Linux Ubuntu vamos verificar que existe um serviço de suporte a estas configurações que permite configurar interfaces graficamente e reconectar/escolher uma rede. Trata-se do NetworkManager. Ver alguns detalhes aqui [https://www.hardware.com.br/dicas/entendendo-networkmanager.html] e aqui[https://wiki.debian.org/pt_BR/NetworkManager]. Este serviço tenta fornecer a melhor conectividade possível usando as interfaces disponíveis. O serviço é composto por:<br />
<br />
*um processo do sistema (roda como serviço) monitorando constantemente as interfaces;<br />
*uma applet para interação com o usuário (canto direito da interface);<br />
<br />
O NetworkManager vai ignorar as configurações das interfaces realizadas em /etc/network/interfaces<br />
<br />
Teste o uso do NetworkManager. Clique no topo do desktop a direita e inspecione as interfaces disponíveis.<br />
<br />
Em algumas situações pode ser desejável desabilitar o NetworkManager. Na linha de comando pode ser executado:<br />
<br />
sudo service network-manager stop<br />
<br />
===Configurando interfaces de forma manual ===<br />
<br />
TEXTO baseado nas anotações do Prog.Marcelo Sobral:<br />
<br />
O arquivo ''/etc/network/interfaces'' contém declarações para configurar as interfaces de rede. Um exemplo de configuração básica contida nesse arquivo pode ser vista a seguir:<br />
<br />
<syntaxhighlight lang=text><br />
auto lo eth0<br />
iface lo inet loopback<br />
iface eth0 inet dhcp<br />
</syntaxhighlight><br />
<br />
Esse exemplo pode ser interpretado assim:<br />
* ''Linha 1'': declara que as interfaces ''lo'' e ''eth0'' devem ser ativadas automaticamente no boot. Se uma interface não aparecer em uma declaração como esta, então ela não será ativada. OBS: interface ativadas desta forma NÃO são controladas pelo ''NetworkManager''.<br />
* ''Linha 2'': configura a interface ''lo'' como sendo do tiupo ''loopback''. Essa é uma interface especial criada puramente em software (uma interface de rede virtual), usada para comunicação entre processos de um mesmo computador.<br />
* ''Linha 3'': configura a interface ''eth0'' de forma dinâmica usando [[GER-2010-1#DHCP|DHCP]]. A configuração de rede é solicitada usando a própria rede. Ness ecaso, deve existir algum equipamento ou computador nessa rede que seja um servidor DHCP, capaz de responder com uma mensagem contendo a configuração de rede a ser utilizada.<br />
<br />
<br />
O exemplo anterior é bastante simplificado, uma vez que a configuração de rede de fato é obtida dinamicamente com DHCP. Isso pode ser suficiente para computadores usados somente para acesso a Internet, mas não para computadores que sejam servidores. Nesse caso, é melhor definir uma configuração de rede estática, como mostrado a seguir:<br />
<br />
<syntaxhighlight lang=text><br />
auto lo eth0<br />
iface lo inet loopback<br />
iface eth0 inet static<br />
address 172.18.80.251<br />
netmask 255.255.128.0<br />
gateway 172.18.0.254<br />
dns-nameservers 191.36.8.2 191.36.8.3<br />
</syntaxhighlight><br />
<br />
<br />
A diferença em relação ao caso anterior está na declaração da interface ''eth0''. Ao invés de configurá-la com ''DHCP'', declararam-se todas as informações de rede. Assim, essa interface sempre será ativada com essas informações configuradas. No exemplo apresentado, as configurações de rede são:<br />
* ''address 172.18.80.251'': endereço IP da interface<br />
* ''netmask 255.255.128.0'': máscara de rede<br />
* ''gateway 172.18.0.254'': endereço do gateway (ou roteador ''default'')<br />
* ''dns-nameservers 191.36.8.2 191.36.8.3'': servidores DNS a serem utilizados (podem-se especificar um ou mais endereços IP)<br />
<br />
O [http://manpages.ubuntu.com/manpages/trusty/en/man5/interfaces.5.html manual do arquivo /etc/network/interfaces] apresenta muitos outros detalhes sobre possíveis configurações de rede.<br />
<br />
Antes da alteração de configuração de uma interface é interessante desativá-la:<br />
ifdown eth0<br />
Alterar o arquivo /etc/network/interfaces<br />
<br />
E na sequência ativá-la novamente:<br />
ifup eth0<br />
ou<br />
sudo /etc/init.d/networking restart<br />
<br />
O comando ifup vai consultar o arquivo e alterar as configurações. Indiretamente, o script networking também usa o ifup para ativar as configurações (e todas demais que forem realizadas).<br />
<br />
==Relatório Avaliativo 1==<br />
<br />
Criar um arquivo no OpenOffice nomeando-o SeuNomeSemEspaco-FICLinux-2019-A1<br />
<br />
Copiar e responder as questões abaixo:<br />
<br />
1.Faça um ifconfig na interface eth0. Cole um recorte da tela no espaço abaixo e faça um texto indicando qual o endereço de hardware associado a esta interface, qual o endereço IPv4 e qual a máscara de subrede.<br />
<br />
<br />
2.Faça um experimento usando o ping e o wireshark mostrando como o DNS atua para resolver o nome que está sendo "pingando". Informe em texto abaixo qual o IP do servidor DNS local e qual o IP do site que está sendo "pingado".<br />
<br />
<br />
3,Execute o laboratório do Netkit da forma e cole abaixo a figura da rede fornecida pelo netkit:<br />
<code><br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
<br />
# Hosts' interfaces to local routers<br />
<br />
r1[eth0]=lan0<br />
r1[eth1]=lan1<br />
<br />
pc1[eth0]=lan0<br />
pc2[eth0]=lan0<br />
pc3[eth0]=lan1<br />
</syntaxhighlight><br />
<br />
<br />
4.Configure todas as interfaces dos PC usando para lan0 o prefixo 50.50.50.0/24 e para lan1 use no lugar de 50 o dia de seu nascimento.<br />
Cole uma tela mostrando PC1 pingando PC3. <br />
<br />
5.Informe abaixo o MAC da eth0 do roteador.<br />
<br />
6.Usando o tcpdump na eth0 do roteador mostre que a entrega é indireta.<br />
<br />
==Estendendo a rede através da LAN usando segundo AP e WAN==<br />
<br />
Conecte um segundo AP (WAN do segundo AP a LAN do primeiro AP). Teste a conectividade colocando uma máquina Linux na LAN do segundo AP.<br />
Esta configuração deve funcionar mas impõe um overhead adicional devido ao NAT realizado duas vezes... <br />
<br />
DESAFIO: mostrar que o NAT está sendo duplicado.<br />
<br />
[[Arquivo:WLAN-2PAs-viaWAN.png]]<br />
<br />
==Estendendo a rede através da LAN usando segundo AP e LAN==<br />
<br />
Discuta com o colega ao lado e pense como poderia conectar o segundo AP via LAN. Uma configuração adicional será necessária.<br />
<br />
==Estendendo a rede através do Wireless (WDS)==<br />
<br />
Estude no manual como poderia estender a rede Sem Fio usando conexão via WDS.<br />
<br />
=AULA 20 - Dia 18/04/2019=<br />
<br />
*Tópicos Adicionais sobre redes no Linux:<br />
**Opções de Acesso a Internet: ADSL, Cabo<br />
**Sistema de Arquivos em Rede: Samba Server (http://www.guiafoca.org/cgs/guia/avancado/ch-s-samba.html)<br />
*Relatório Avaliativo 2<br />
<br />
==Relatório Avaliativo==<br />
<br />
===PARTE 1=== <br />
<br />
Usando a configuração abaixo do netkit2 e uma máquina Virtualbox devidamente configurada implementar a configuração abaixo:<br />
<br />
ATENÇÂO: Vamos substituir a VirtualBox por uma máquina Netkit executada em OUTRO PC com a configuração:<br />
<br />
INSTRUÇÔES para virtual box:<br />
*colocar rede como bridge<br />
*desabilitar o network manager<br />
sudo service network-manager stop<br />
*baixar a interface<br />
sudo ifconfig enp0s3 down<br />
*reconfigurar a interface (usar o endereço do seu grupo)<br />
sudo ifconfig enp0s3 50.50.50.11/24<br />
*colocar a rota direta (que se perdeu) (usar o endereço do seu grupo)<br />
sudo route add -net 50.50.50.0/24 dev enp0s3<br />
*colocar gateway default (usar o endereço do seu grupo)<br />
sudo route add default gateway 50.50.50.1<br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
<br />
pc1[type]=generic<br />
pc1[eth0]=uplink:bridge=eth0:ip=dhcp<br />
<br />
</syntaxhighlight><br />
<br />
<br />
[[Arquivo:Aval2-Parte1-FICLinux2019-2.png]]<br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
pc1[type]=generic<br />
<br />
pc1[eth0]=lan1<br />
<br />
r1[eth0]=uplink:bridge=eth0:ip=VER COM PROFESSOR<br />
r1[eth1]=lan2<br />
<br />
r2[eth0]=lan1<br />
r2[eth1]=lan2<br />
</syntaxhighlight><br />
<br />
Construir um doc conforme aula anterior com as seguintes informações:<br />
<br />
#Coloque a tela de um píng funcionando de R1 para PC1<br />
#Cole a tela da tabela de roteamento de R2<br />
#Cole a tela de um ping de uma máquina VirtualBox (netkit) no R1 (uplink)<br />
#Cole a tela de um ping funcionando uma máquina VirtualBox (netkit) no PC1<br />
<br />
Note que o gateway default da máquina virtual deverá ser reconfigurado para PC1.<br />
<br />
ADENDO: Coloque em R1 rotas para as redes dos PC1 dos demais grupos.<br />
<br />
===PARTE 2===<br />
<br />
Acrescente na sua rede um AP configurado como indicado abaixo:<br />
<br />
OBS: Para este exercício configuramos estaticamente todos os endereços para o lado do backbone (Laboratório). Usamos 50.50.50.0/24<br />
<br />
[[Arquivo:Aval2-Parte2-FICLinux2019-2.png]]<br />
<br />
<br />
=ATIVIDADE DE RECUPERAÇÃO 1=<br />
<br />
Refazer o relatório Avaliativo 1 proposto anteriormente. Enviar doc para o SIGA A<br />
<br />
=ATIVIDADE DE RECUPERAÇÃO 2=<br />
<br />
Registre em um DOC e faça um post no SIGA A colando a imagem das telas das saídas de cada comando!<br />
<br />
===Roteiro de atividades sobre o IPv6===<br />
<br />
A figura abaixo apresenta o diagrama esquemático da rede a ser montada/analisada. Observe que todos os IPv6 ''Global Unicast'' já estão definidos na mesma, são esses IPs que utilizaremos em nosso experimento.<br />
<br />
[[Arquivo:Diagrama_rede_IPv6.jpg]]<br />
<br />
#Crie em seu computador um arquivo com nome '''/home/aluno/IPv6.conf''', com o seguinte conteúdo: <syntaxhighlight lang=bash><br />
#Ligacao das maquinas nos dominios de colisao<br />
#Duas pequenas redes interligadas pelo backbone<br />
<br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=link0:ipv6=2001:bcc:faca:1::101/64<br />
pc2[eth0]=link1:ipv6=2001:bcc:cafe:1::102/64<br />
pc3[eth0]=HUB1:ipv6=2001:bcc:1f0:1::103/64<br />
pc4[eth0]=HUB1<br />
<br />
#Default Gateways definitions<br />
pc1[route]=default6:gateway=2001:bcc:faca:1::1<br />
pc2[route]=default6:gateway=2001:bcc:cafe:1::1<br />
pc3[route]=default6:gateway=2001:bcc:1f0:1::1<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
#Routers interfaces definitions<br />
r1[eth0]=backbone0:ipv6=2001:db8:dead:1::1/64<br />
r1[eth1]=link0:ipv6=2001:bcc:faca:1::1/64<br />
r1[eth2]=link1:ipv6=2001:bcc:cafe:1::1/64<br />
<br />
r2[eth0]=backbone0:ipv6=2001:db8:dead:1::2/64<br />
r2[eth1]=HUB1:ipv6=2001:bcc:1f0:1::1/64<br />
<br />
#Routers definitions<br />
r1[route]=2001:bcc:1f0:1::0/64:gateway=2001:db8:dead:1::2<br />
r2[route]=2001:bcc:faca:1::0/64:gateway=2001:db8:dead:1::1<br />
r2[route]=2001:bcc:cafe:1::0/64:gateway=2001:db8:dead:1::1<br />
</syntaxhighlight><br />
#Tenha certeza que o Netkit2 estja atualizado: General >> Update.<br />
#Rode o NetKit em seu computador. Em um terminal digite: <syntaxhighlight lang=bash><br />
netkit2 & </syntaxhighlight><br />
#No menu '''File''' - '''Load and Run''', procure o arquivo '''/home/aluno/IPv6.conf''' e clique em OK. Abrirá uma janela com 6 abas, onde cada uma delas é um terminal de configuração do respectivo equipamento: '''pc1-4''' ou '''r1-2'''.<br />
#Observe que o '''pc4''' não está com sua interface configurada.<br />
#Ao clicar no menu '''File''' - '''Graph''', pode-se ter uma visão da rede a ser simulada e conferir se é equivalente ao diagrama proposto.<br />
#Faça um '''ping6''' entre o '''pc1''' ao '''pc3''': <syntaxhighlight lang=bash><br />
ping6 -c4 2001:bcc:1f0:1::103 </syntaxhighlight><br />
#Faça um '''ping6''' entre o '''pc1''' e '''pc2'''.<br />
#No '''pc4''' use o seguinte comando para adicionar o endereço IPv6 à interface de rede: <syntaxhighlight lang=bash><br />
ip addr add 2001:bcc:1f0:1::104/64 dev eth0 </syntaxhighlight><br />
#No '''pc4''', acrescente o ''default gateway'' com o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add default via 2001:bcc:1f0:1::1 dev eth0 </syntaxhighlight><br />
#No '''pc1''' use o seguinte comando para verificar como ficou a configuração dos endereços da interface de rede. O resultado é similar ao apresentado pelo comando '''ifconfig''': <syntaxhighlight lang=bash><br />
ip addr show dev eth0 </syntaxhighlight><br />
#Todo o roteamento está pronto, mas caso desejássemos poderíamos acrescentar rotas com comando similares aos já utilizados. Por exemplo, no '''r1''', para adicionar uma rota estática para a rede dos '''pc3''' e '''pc4''' utilizaríamos o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add 2001:bcc:1f0:1::/64 via 2001:db8:dead:1::2 dev eth0 </syntaxhighlight><br />
#Confira as rotas estabelecidas em todos os ''hosts'' com o comando abaixo. <br />
##São coerentes com os dados apresentados no diagrama acima?<syntaxhighlight lang=bash><br />
ip -6 route show </syntaxhighlight><br />
#No '''pc1''' use os seguintes comandos para ver a rota para alguns vizinhos: <syntaxhighlight lang=bash><br />
traceroute6 2001:bcc:1f0:1::103<br />
traceroute6 2001:bcc:1f0:1::104 </syntaxhighlight><br />
#*Anote as rotas.<br />
#Deixe um '''ping6''' entre o '''pc1''' ao '''pc3''' rodando: <syntaxhighlight lang=bash><br />
ping6 2001:bcc:1f0:1::103 </syntaxhighlight><br />
<br />
=ATIVIDADE DE RECUPERAÇÃO 3=<br />
<br />
Registre em um DOC e faça um post no SIGA A colando a imagem das telas das saídas de cada comando! Coloque também a resposta as perguntas.<br />
<br />
===Objetivos===<br />
<br />
*Familiarizar-se com o UDP<br />
*Entender a estrutura do pacote UDP<br />
*Entender o conceito de portas<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/UDP%20Basico.pdf Introdução a camada de transporte e UDP básico]<br />
<br />
===Parte 1 - Fluxo único UDP===<br />
<br />
#Combinar equipes com dois computadores para execução do experimento.<br />
#*Uma equipe escutará na porta 5000 e a outra equipe transmitirá uma mensagem nessa porta. Os processos de transmissão e recepção podem ocorrer simultaneamente, em terminais distintos.<br />
#*Cada equipe deve identificar os IPs ('''IP_DEST''') das máquinas de seus pares.<br />
#Cada equipe deve abrir uma Janela de terminal.<br />
#Cada equipe deve preparar o '''Wireshark''', interfaces '''any''', para escuta das portas no protocolo UDP usando um filtro:<syntaxhighlight lang=bash><br />
udp.port==5000</syntaxhighlight><br />
#A equipe da escuta na porta 5000 executa no terminal: <syntaxhighlight lang=bash><br />
netcat -u -l -p 5000 </syntaxhighlight><br />
#A equipe que irá transmitir para a porta 5000 executa no terminal: <syntaxhighlight lang=bash><br />
netcat -u IP_DEST 5000 </syntaxhighlight><br />
#*Em seguida escreve no terminal uma mensagem de até 20 caracteres, ao teclar <Enter> a mensagem será enviada.<br />
#*O wireshark deve ter capturado os pacotes UDP <br />
#Identifique e anote os seguintes dados na captura do wireshark:<br />
#*IP FONTE e DESTINO<br />
#*PORTAS FONTE E DESTINO para ambas comunicações<br />
#*Campo de protocolo no pacote IP<br />
#*Campo de tamanho (anote o tamanho) e ''checksum'' no pacote (datagrama) UDP<br />
#*O campo de dados no pacote UDP<br />
#Troquem os papéis das equipes: quem houvia agora transmite mensagens.<br />
#Cada equipe pode transmitir sequencialmente várias mensagens, devendo identificar múltiplos datagramas UDP.<br />
#PERGUNTAS baseadas na captura:<br />
##Qual o tamanho de cada campo do cabeçalho do pacote UDP?<br />
##Qual o tamanho máximo do número de porta?<br />
##Qual o tamanho máximo da área de dados (payload) do pacote?<br />
##Qual o número identificador de protocolo UDP no pacote IP? <br />
##Em algum momento foi identificado algum procedimento para estabelecimento de conexão? <br />
##Em algum campo do UDP existe numeração de mensagens?<br />
<br />
=AULA 20 - Dia 18/04/2019=<br />
<br />
{{collapse bottom}}<br />
<br />
==Curso FIC Linux 2018==<br />
<br />
{{collapse top|Semestre 2018-2 - Prof. André D'Amato}}<br />
<br />
== Introdução ao Sistema Operacional Linux ==<br />
<br />
'''10/09/18: Aula01'''<br />
<br />
Apresentação da Disciplina, Introdução a Informática e Memória e Armazenamento<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula01.pdf Aula 01]<br />
<br />
{{collapse bottom}}<br />
<br />
==Curso FIC Linux 2016==<br />
<br />
{{collapse top|Semestre 2016-2 - Prof. Luciano Barreto}}<br />
<br />
== Introdução ao Sistema Operacional Linux ==<br />
<br />
'''04/10/16: Aula01'''<br />
<br />
Apresentação da Disciplina, Introdução a Informática e Memória e Armazenamento<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula01.pdf Aula 01]<br />
<br />
'''06/10/16: Aula 02'''<br />
<br />
Introdução ao Linux, Sistema de Arquivos e Conhecendo o Terminal<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula02.pdf Aula 02]<br />
<br />
''' 11/10/2016: Aula 03'''<br />
<br />
Continuação Comandos no Terminal<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula03.pdf Aula 03]<br />
<br />
''' 13/10/2016: Aula 04''' <br />
<br />
Continuação Comandos no Terminal<br />
<br />
''' 18/10/2016: Aula 05''' <br />
<br />
Lista de Exercícios<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/ficlinux-aula05-exercicios.pdf Aula 05 - Lista de Exercícios]<br />
<br />
''' 20/10/2016: Aula 06'''<br />
<br />
Introdução ao Gerenciamento de Processos<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula06-processos.pdf Aula 06 - Gerenciamento de Processos]<br />
<br />
''' 25/10/2016: Aula 07''' <br />
<br />
Gerenciamento de Usuários<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula07-usuariosgrupos.pdf Aula 07 - Gerenciamento de Usuários]<br />
<br />
Permissionamento<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula07-permissionamento.pdf Aula 07 - Permissionamento]<br />
<br />
''' 27/10/2016: Aula 08'''<br />
<br />
Continuação Permissionamento<br />
<br />
Instalação Linux<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula8-instalacao.pdf Aula 08 - Instalação Linux] <br />
<br />
''' 01/11/2016: Aula 09'''<br />
<br />
Continuação Instalação Linux<br />
<br />
Instalação de Pacotes via Apt<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula9-pacotes.pdf Aula 09 - Instalação Pacotes] <br />
<br />
''' 03/11/2016: Aula 10'''<br />
Continuação Lista Exercícios (47 - 60)<br />
<br />
=AULA 11 - Dia 18/04/2019=<br />
<br />
=AULA 12 - Dia 18/04/2019=<br />
<br />
=AULA 13 - Dia 18/04/2019=<br />
<br />
=AULA 14 - Dia 18/04/2019=<br />
<br />
=AULA 15 - Dia 18/04/2019=<br />
<br />
=AULA 16 - Dia 18/04/2019=<br />
<br />
=AULA 17 - Dia 18/04/2019=<br />
<br />
=AULA 18 - Dia 18/04/2019=<br />
<br />
=AULA 19 - Dia 18/04/2019=<br />
<br />
=AULA 20 - Dia 18/04/2019=<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top|Semestre 2016-1 - Prof. Luciano Barreto}}<br />
<br />
= Diário de Aulas 2016 - 1 =<br />
<br />
==29/03/16: Apresentação do curso==<br />
Apresentação do curso, Visão geral de funções, responsabilidades e estruturas de um SO.<br />
<br />
==31/03/16: Introdução a Sistema de Arquivos e Terminal==<br />
Estrutura do Sistema de Arquivos Linux, Introdução a comandos no Terminal.<br />
<br />
==04/04/16: Continuação Terminal==<br />
Continuação de comandos no terminal, redirecionamento de saída e caracteres coringa.<br />
<br />
==07/04/16: Introdução a Processos e Usuários==<br />
Conhecendo Processos e Gerenciamento de usuários<br />
<br />
==12/04/16: Lista de Exercícios de Comandos no Terminal==<br />
<br />
[http://bellard.org/jslinux/ Emulador de Terminal no navegador (demora um pouquinho pra abrir)]<br />
<br />
==14/04/16: Usuários, Grupos e Permissões==<br />
Administração de usuários, grupos e adicionando permissões a arquivos.<br />
<br />
==19/04/16: Instalação do Linux==<br />
Instalação do Sistema Linux em modo texto, gráfico e dualboot.<br />
<br />
==26/04/16: Introdução ao Shell Script==<br />
Introdução ao Shell Script<br />
<br />
==28/04/16: Continuação ao Shell Script==<br />
Introdução ao Shell Script<br />
<br />
==03/05/16: Lista de Exercícios==<br />
Lista de Exercícios até a aula de 28/04/16<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top|Semestre 2015-2}}<br />
<br />
*'''Professores:''' [[Ana Paula Rosa Negri]] e [[Francisco de Assis Souza dos Santos]]<br />
<br />
{| style="background-color:#ABCDEF; font-family:verdana,Arial, Helvetica, sans-serif; font-size:100%; margin:0; border: 1px solid #C7D0F8; padding:7px 7px 0px 7px; text-align:center;" width="100%"<br />
| | Bem-vindo ao<br /><br />
<span style="font-size:200%">'''Curso de Formação Continuada de Configuração de Redes de Computadores Linux''' <br />do Instituto Federal de Santa Catarina - Campus São José</span><br />
|}<br />
<br />
Introdução ao Sistema Operacional Linux<br />
<br />
*'''Professores:''' [[Ana Paula Rosa Negri]] e [[Francisco de Assis Souza dos Santos]]<br />
*'''Encontros:''' Terças e quintas das 19:00 às 22:00 no Laboratório de Apoio ao Ensino.<br />
<br />
*[[ISL-FicLinux_(Plano_de_Ensino)| Plano de Ensino]]<br />
*[[Cronograma de atividades (ISL-FicLinux) | Cronograma]]<br />
<br />
= Diário de Aulas 2015 =<br />
== 13/10 ==<br />
'''Parte 1:'''<br />
Slides da aula:<br />
[[Arquivo:introducao.pdf]]<br />
<br>Exercício sobre taxa de transferência:<br />
[[Arquivo:Exercicio_taxa_Transferencia.pdf]]<br />
<br><br />
<br />
'''Parte 2:'''<br />
Slides da Aula:<br />
[[Arquivo:LinuxModoTexto.pdf]]<br />
<br>Exercícios sobre comandos básicos do Linux:<br />
[[Arquivo:ExercícioLinuxTexto.pdf]]<br />
<br />
== 15/10 ==<br />
'''Parte 3:'''<br />
Slides da Aula:<br />
[[Arquivo:Parte3.pdf]]<br />
== 20/10 ==<br />
'''Parte 4:'''<br />
Slides caracteres coringas: [[Arquivo:Coringas.pdf]]<br />
<br />
Exercícios caracteres coringas: [[Arquivo:Exercício CB03 Pokemon.pdf]]<br />
<br />
'''Parte 5:'''<br />
Sildes Redirecionamento: [[Arquivo: Redirecionamento.pdf]]<br />
<br />
Exercícios redirecionamento e pipe: [[Arquivo: ex_pipe.pdf]]<br />
<br />
== 22/10 ==<br />
'''Parte 6:'''<br />
Slides Processos: [[Arquivo:FICLinux_Processos.pdf]]<br />
<br />
== 27/10 ==<br />
'''Parte 7:''''<br />
Slides Usuários e Grupos: [[Arquivo:UserGroup.pdf]]<br />
<br>Exercícios: [[Arquivo:usuarios.pdf]]<br />
<br>Exercícios (.odt): [[Arquivo:usuarios.odt]]<br />
<br />
== 29/10 ==<br />
'''Parte 8:'''<br />
Slides Introducao a Redes: [[Arquivo:FICLinux_Introducao_Redes.pdf]]<br />
<br />
== 03/11 ==<br />
<br />
'''Parte 9:'''<br />
Slides permissionamento: [[Arquivo:permissionamento.odp]]<br><br />
Exercícios permissionamento: [[Arquivo: Exercício Perm02.odt]]<br><br />
Outro exercício permissionamento: [[Arquivo: Exercício Perm04 GatosRatosCães.odt]]<br />
<br />
== 05/11 ==<br />
<br />
'''Parte 10:'''<br />
Slides Redes - Broadcast: [[Arquivo:FICLinux_Introducao_Redes_Broadcast_01.pdf]]<br><br />
<br />
== 10/11 ==<br />
<br />
'''Parte 11:'''<br />
Slides Script: [[Arquivo:Scripts do Linux.odp]]<br />
<br>Exercícios Scripts: [[Arquivo:Exercício Scripts01 pdfmerger.odt]]<br />
<br />
== 12/11 ==<br />
<br />
'''Parte 12:'''<br />
Introdução para comandos em Bash: [[Arquivo:Introdução ao Shell_2015_1.pdf]]<br />
<br />
{{collapse bottom}}</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=ISL-FicLinux_(p%C3%A1gina)&diff=162001ISL-FicLinux (página)2019-10-03T19:40:40Z<p>127.0.0.1: /* AULA 11 - Dia 1/10/2019 */</p>
<hr />
<div>__NOTOC__<br />
= Introdução ao Sistema Operacional Linux / Redes com Linux =<br />
<br />
*'''Encontros:''' Terças e Quintas das 19:00 às 22:00.<br />
*'''Local:''' Laboratório de Redes de Computadores (Redes 1).<br />
<br />
*[[ISL-FicLinux_(Plano_de_Ensino)| Plano de Ensino]]<br />
<br />
==Curso FIC Linux 2019==<br />
<br />
{{collapse top | Semestre 2019-2 - Prof. Eraldo Silveira e Silva}}<br />
<br />
==Cronograma Tentativa==<br />
<br />
Horários: 19h às 22h.<br />
<br />
{| class="wikitable"|<br />
| AULA || DATA || Professor || Conteúdo<br />
|-<br />
| 1 || 27/09/2019 || ERALDO || Programa da Disciplina.Forma de Avaliação. O computador: hardware e software. SO Linux: histórico e distribuições. Ligando/Logando/Desligando a Máquina. Conceitos básico de Sistema de Arquivos e Processos.<br />
|-<br />
| 2 || 29/09/2019 || ERALDO || Gerenciamento de Arquivos I: Operações sobre arquivos e diretórios usando o terminale o Nautilus.<br />
|-<br />
| 3 || 3/09/2019 || ERALDO || Gerenciamento de Arquivos II: continuação Operações sobre arquivos e diretórios. Links Simbólicos, Criação de Arquivo com vi e outros editores.<br />
|-<br />
| 4 || 5/09/2019 || ERALDO || Interfaces Gráficas: X11, Gnome. KDE e outras. Instalação de Programas via Gerenciador de Pacotes.<br />
|-<br />
| 5 || 10/09/2019 || ERALDO || Administração de contas de usuários I<br />
|-<br />
| 6 || 12/09/2019 || ERALDO || Administração de contas de usuários II<br />
|-<br />
| 7 || 17/09/2019 || ERALDO || Permissionamento de Arquivos<br />
|-<br />
| 8 || 19/09/2019 || ERALDO || Gerenciamento de Processos<br />
|-<br />
| 9 || 24/09/2019 || ERALDO || Introdução ao Shell Script<br />
|-<br />
| 10 || 26/09/2019 || ERALDO || Introdução ao Shell Script<br />
|-<br />
| 11 || 1/10/2019 || ERALDO || Introdução a Redes. Conceito de Protocolos. Ferramentas de Rede.<br />
|-<br />
| 12 || 3/10/2019 || ERALDO || Protocolos de Aplicação: exemplo http <br />
|-<br />
| 13 || 8/10/2019 || ERALDO || O DNS como protocolo de Aplicação; Camada de Transporte: protocolo UDP <br />
|-<br />
| 14 || 10/10/2019 || ERALDO || Protocolo TCP. Diferenças dos protocolos de Transporte TCP/UDP. Camada IP e aspectos da configuração da mesma sob o Linux<br />
|-<br />
| 15 || 15/10/2019 || ERALDO || Camada de Enlace/Física. Hubs X Switches. O Papel do Protocolo ARP. Outros serviços/protocolos: Serviço DHCP e NAT<br />
|-<br />
| 16 || 17/10/2019 || ERALDO|| Segmentação Redes IP. Cálculo de subredes. <br />
|-<br />
| 17 || 22/10/2019 || ERALDO || Introdução ao IPV6. Introdução ao Access Point TPLINK N750: configuração da LAN e WAN<br />
|-<br />
| 18 || 24/10/2019 || ERALDO || Serviço SSH no Linux. Acesso a rede WIFI. Conceitos básicos de redes sem fio.<br />
|-<br />
| 19 || 29/10/2009 || ERALDO || Tópicos Adicionais sobre redes no Linux: Configuração Manual X NetworkManager. Relatório Avaliativo 1.<br />
|-<br />
| 20 || 31/10/2019 || ERALDO || Relatório Avaliativo 2<br />
|}<br />
<br />
=Curso FIC Linux 2019-2=<br />
<br />
==Professor==<br />
<br />
:*Prof. [[Eraldo Silveira e Silva]]<br />
:*email: eraldo@ifsc.edu.br<br />
:*sala: Sala de I de Professores da Área de Telecomunicações (primeira sala lado da Biblioteca - direção esquerda)<br />
<br />
=27/08/2019=<br />
<br />
==Objetivos==<br />
<br />
===Parte 1===<br />
<br />
*Apresentar o IFSC: estrutura, câmpus e serviços<br />
*Apresentar o curso: perfil do egresso, competências gerais, áreas de atuação do egresso e conteúdos previstos<br />
*Apresentar o Cronograma Tentativa (ver SIGA A)<br />
*Apresentar metodologia e forma de avaliação<br />
<br />
===Parte 2===<br />
<br />
*Conceitos de Hardware, Software e Firmware<br />
*Arquiteturas de processadores<br />
*Classificação de softwares<br />
*Conceitos de Sistemas Operacionais e exemplos<br />
<br />
===Parte 3===<br />
<br />
*Histórico do Linux<br />
*Linux e GNU/Linux<br />
*Instalando o Linux<br />
*Arquitetura do Linux<br />
*Distribuições<br />
*Distribuições usadas no IFSC/SJ<br />
*Ligando e Desligando o Sistema<br />
*Primeiros contatos.<br />
<br />
==Professores do FIC Linux Edição 2019-2==<br />
<br />
*Prof. [[Eraldo Silveira e Silva]] (Introdução ao Linux e Redes com Linux)<br />
<br />
==Apresentação do IFSC==<br />
<br />
*[http://www.ifsc.edu.br/estrutura-organizacional-inicio Página do IFSC]<br />
*[https://www.sj.ifsc.edu.br/index.php Página do Câmpus]<br />
<br />
==Apresentação do Curso==<br />
<br />
*[[ISL-FicLinux_(Plano_de_Ensino) | Introdução ao Linux]]<br />
*[https://wiki.sj.ifsc.edu.br/index.php/PRL-FicLinux_(Plano_de_Ensino) Projeto de Rede Residencial com o Linux]<br />
*[[Curso_de_Formação_Continuada_de_Configuração_de_Redes_de_Computadores_Linux | PPC do Curso e Outras Regulamentações]]<br />
<br />
==Cronograma Tentativa==<br />
<br />
Horários: 19h às 22h.<br />
<br />
VER SIGA A [https://sig.ifsc.edu.br/sigaa/verTelaLogin.do]<br />
<br />
==Metodologia, Avaliação e Critérios de Aprovação==<br />
<br />
*Aulas expositivas e aulas práticas no laboratório. Nas aulas práticas serão desenvolvidos exercícios e trabalhos individuais.<br />
*Avaliações individuais: Listas de exercícios com aproveitamento e entregues no prazo. <br />
*Critérios para aprovação: Serão considerados aprovados os alunos que obtiverem conceito final 6 ou superior em cada componente curricular. ATENÇÃO: Possuir no mínimo 75% de presença<br />
<br />
==Bibliografia==<br />
<br />
#Odilson Tadeu Valle<br />
##Administração de redes com Linux: fundamentos e práticas<br />
##Editora IFSC, 2010<br />
#Gleydson Mazioli da Silva<br />
##Guia Foca Linux<br />
##http://www.guiafoca.org/<br />
#Luiz Carlos Lobato Lobo de Medeiros e Wendel Soares<br />
##Formação de suporte técnico PROINFO<br />
##https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo<br />
#Ari Frazão Jr e Marcelo Braga<br />
##Administração de Sistemas Linux<br />
##https://pt.scribd.com/doc/128912228/Administracao-de-Sistemas-Linux<br />
<br />
==Conceitos de Hardware, Software e Firmware==<br />
<br />
*Em informática, o hardware consiste nos equipamentos<br />
**Ex: Computador, teclado, mouse, monitor<br />
*Software é um aplicativo, desenvolvido em uma linguagem de programação<br />
**Ex: Windows, Linux, Mozilla Firefox, Google Chrome<br />
*Firmware é um conjunto de instruções básicas e específicas para um hardware<br />
**Ex: BIOS nos computadores, sistemas de controle das máquinas de lavar, etc.<br />
<br />
==Estrutura de um Computador e Arquitetura de Processadores==<br />
<br />
*Material de Referência: https://www.dropbox.com/s/fn3l9os4l7gh9o5/AULA%201.odp?dl=0<br />
<br />
===Outros Links Interessantes===<br />
<br />
*Bits, [https://pt.wikipedia.org/wiki/Byte Bytes] e tamanho de memória;<br />
*Representação de Caracteres: [https://pt.wikipedia.org/wiki/ASCII Tabela ASCII];<br />
*O [https://pt.wikipedia.org/wiki/Microprocessador microprocessador], barramentos e memórias semicondutoras: RAM,ROM, E2PROM, FLASH;<br />
*Memórias cache e memórias secundárias;<br />
*[https://pt.wikipedia.org/wiki/Mem%C3%B3ria_virtual Memória Virtual] e Swapping;<br />
*Registradores de 32bits ou 64bits<br />
*Arquitetura [https://pt.wikipedia.org/wiki/X86 x86] / [https://pt.wikipedia.org/wiki/AMD64 x86-64] – presente nos computadores pessoais<br />
*Arquitetura ARM – presente em sistemas embarcados e dispositivos móveis<br />
*Múltiplos núcleos (core)<br />
*Máquinas Virtuas: VirtualBox, UML (User Mode Linux).<br />
<br />
==O papel do Sistema Operacional==<br />
<br />
*O [https://pt.wikipedia.org/wiki/Sistema_operativo SO] é um programa (software) que controla a máquina e a torna utilizável para o usuário;<br />
*Abstrações do Sistema: arquivos e processos;<br />
*Pode ser multitarefa e multiusuário;<br />
*[https://en.wikipedia.org/wiki/Device_driver Driver] de dispositivo<br />
*[https://pt.wikipedia.org/wiki/Multi_boot Múltiplos OS instalados] em um computador. É possível??<br />
<br />
==Sistema de Arquivos==<br />
<br />
*Forma como estão estruturados/organizados os arquivos/dados em uma determinada mídia [https://pt.wikipedia.org/wiki/Sistema_de_ficheiros];<br />
*Um sistema operacional deve saber como acessar e operar sobre este sistema;<br />
*Tipos de sistemas: ext4, NTFS, VFAT32<br />
<br />
==Exemplos de SO==<br />
<br />
*Unix<br />
*Microsoft DOS<br />
*IBM<br />
*Microsoft Windows<br />
*netBSD, freeBSD, openBSD<br />
*Linux<br />
*macOS<br />
*Android<br />
*iOS<br />
<br />
==Histórico do Linux==<br />
<br />
*O início de tudo: UNIX;<br />
*Surgiu em 1991 quando Linus Torvalds, um estudante finlandês, resolveu desenvolver um sistema operacional compatível com a POSIX, por em que pudesse ser executado em arquitetura x86;<br />
*Linux está sob uma licença de software livre e diversas pessoas e empresas contribuem para o desenvolvimento do mesmo.<br />
*E o que é [https://pt.wikipedia.org/wiki/POSIX POSIX]? Define padrões para a interface de programação de aplicações (API) de um OS de forma a manter compatibilidade com o UNIX;<br />
<br />
==Arquitetura do Linux==<br />
<br />
===Material de Referência===<br />
<br />
*[https://www.dropbox.com/s/zvpo7zw19ns7rmk/AULA%202.odp?dl=0 Slides Introdução ao SO Linux]<br />
*Ver pg.16 a 19 de [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo]<br />
<br />
==Distribuições==<br />
<br />
Uma distribuição Linux consiste de um kernel Linux e uma coleção de software utilitários e aplicativos de usuário (baseado slides Prof. Emerson)<br />
**Redhat<br />
**Slackware<br />
**Debian<br />
**Ubuntu<br />
**OpenSuse<br />
**Fedora<br />
**CentOS<br />
**Kali<br />
<br />
<br />
Algumas distribuições podem ser executadas diretamente no CD/pendrive<br />
sem a necessidade de fazer sua instalação no disco rígido do computador<br />
<br />
==Distribuições aqui no IFSC SJ==<br />
<br />
*Ubuntu<br />
*Ubuntu Mate (fork do Ubuntu)<br />
*Debian<br />
<br />
==Instalando o Linux==<br />
<br />
*Fazer Download do arquivo ISO em [http://mirror.pop-sc.rnp.br/mirror/ubuntu-releases/18.04/] versão Ubuntu 18.04.3 LTS;<br />
*Instalar a VirtualBox (já está instalada no nosso Lab). Baixar de [https://www.virtualbox.org/wiki/Downloads] e selecionar para a máquina hospedeira alvo;<br />
*Seguir o procedimento colocado pelo professor.<br />
<br />
*[Ver https://www.dropbox.com/s/4xfdhqq8lruvq8m/LinuxSobreVM.odp?dl=0 Slides de Instalação]<br />
<br />
==Ligando e Desligando o Sistema Linux==<br />
<br />
*Cuidado ao desligar um OS como o Linux!!! Dados podem ser perdidos.<br />
*Ver [https://pt.wikibooks.org/wiki/Guia_do_Linux/Iniciante%2BIntermedi%C3%A1rio/Introdu%C3%A7%C3%A3o/Ligando_o_computador]<br />
<br />
==O Desktop do Ubuntu - Primeiras Considerações==<br />
<br />
*O Desktop no Ubuntu ver[https://help.ubuntu.com/stable/ubuntu-help/shell-overview.html]<br />
<br />
=AULA 2 - Dia 29/08/2019=<br />
<br />
==Objetivos==<br />
<br />
===PARTE 1===<br />
<br />
*Revisão da aula passada;<br />
*repassar itens não mencionados na aula passada;<br />
**Paginação e Memória [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo pg.19]<br />
**Estrutura do Linux [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo pg.18]<br />
<br />
===PARTE 2===<br />
<br />
*Operações com arquivos e diretórios usando o terminal;<br />
*formato de um comando básico;<br />
*quase tudo no Linux é arquivo: tipos de arquivos, diretórios, arquivos ordinários;<br />
*conceito de sistema de arquivos;<br />
*conceito de referência absoluta e relativa;<br />
*conceito de diretório de entrada, diretório de trabalho;<br />
*mudando de diretório com cd;<br />
*listando diretórios e arquivos com ls;<br />
*vendo o significado de um comando com man;<br />
*criando diretórios com mkdir;<br />
*removendo diretórios e arquivos com rmdir e rm;<br />
*referência com . .. - ~<br />
*criando arquivos ordinários com touch;<br />
*arquivos e diretórios escondidos;<br />
*copiando arquivos;<br />
*movendo e renomeando arquivos;<br />
*vendo a história de comandos com history;<br />
<br />
===Slides===<br />
<br />
*[https://www.dropbox.com/s/wtc479wmrtle9m4/SistemaDeArquivos.odp?dl=0 Slides Sistema de Arquivos]<br />
<br />
==Conceito de sistemas de arquivos, arquivos e diretórios==<br />
<br />
* [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Sistemas de Arquivos pg.18]<br />
* [Estrutura básica de diretórios do Sistema Linux]<br />
<br />
==Comandos no Linux==<br />
<br />
* [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Comandos e Interpretador de Comandos no Linux pg.18]<br />
<br />
==Tipos de Arquivos==<br />
<br />
* [https://pt.scribd.com/doc/128912228/Administracao-de-Sistemas-Linux Tipos de Arquivos 12,13 e 14 ]<br />
<br />
==Os comandos de operação sobre arquivos e diretórios==<br />
<br />
*[https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Interpretador de comandos - Comandos Básicos - pg.20 e 21]<br />
*[https://www.dropbox.com/s/mv6qpa8bqimiwzg/Aula1_Linux%282%29.pdf Ver lista de exercícios da Aula 2]<br />
<!-- *[https://www.dropbox.com/s/g3xr3wimffde2zm/Aula2_Linux_OperacoesComArquivos_2.pdf Ver lista de exercícios da Aula 3] --><br />
<br />
=AULA 3 - Dia 03/09/2019=<br />
<br />
<br />
===Mirros do Ubuntu Download e Outros===<br />
<br />
<br />
*[http://mirror.pop-sc.rnp.br/mirror/ubuntu-releases/18.04.3/ Ununtu 18.04.3 Mirror Brazil]<br />
<br />
*[https://linuxmint.com/edition.php?id=267 Linux Mint]<br />
<br />
*[https://software.opensuse.org/distributions/leap Opensuse]<br />
<br />
*[https://elementary.io/ Elementary Os]<br />
<br />
*[https://lubuntu.net/ Lubuntu]<br />
<br />
*[https://www.debian.org/CD/live/ Debian]<br />
<br />
*[https://kubuntu.org/getkubuntu/ Kubuntu]<br />
<br />
*[https://peppermintos.com/ Peppermint]<br />
<br />
*[https://www.linuxliteos.com/ Linux Lite]<br />
<br />
*[https://www.lxle.net/download/ LXLE para PCs Antigos...]<br />
<br />
*[https://www.bodhilinux.com/ Bodhi Linux]<br />
<br />
===Como verificar se o arquivo está correto?===<br />
<br />
*[https://help.ubuntu.com/community/HowToMD5SUM HowToMD5SUM] <br />
<br />
===Instalar e Preparar 3 transparências no Oppenoffice===<br />
<br />
*Nome da Equipe e da Distribuição - colar a desktop no slide<br />
*O que tem de interessante nesta distro<br />
*Requisitos da Distribuição<br />
<br />
*Gerar pdf e Enviar para o Siga a<br />
<br />
=AULA 4 - Dia 03/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Ainda operações com arquivos;<br />
*Uso de Coringas<br />
*Editor de texto sobre Ubuntu<br />
*Redirecionamento de Entradas e Saídas<br />
*Aspectos da Interface Gnome no Ubuntu 18.04<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/zti7nn0xq25x8ne/Aula2_Linux_OperacoesComArquivos_2.pdf Ainda Operações com Arquivos]<br />
*[https://www.dropbox.com/s/af3jolkvrb24g8c/Aula3_Linux_LinksSimb_licos_gedit_cat.pdf Edição de Texto]<br />
*[https://www.dropbox.com/s/vihh5r9186d40uj/Aula3_Linux_Parte4_RedirecionamentoEntradasSaidas.pdf Redirecionamento de Entradas e Saídas]<br />
<br />
=AULA 5 - Dia 10/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Gerenciamento de Processos - Parte 1<br />
*Permissionamento de Arquivos - Parte 1<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/4i1n2wqsds18eol/Aula5_Linux_GerenciamentoDeProcessos_Parte1.pdf?dl=0 Gerenciamento de Processos - Parte 1]<br />
*[https://www.dropbox.com/s/3z61r8r0b9wpftr/Aula4_Linux_PermissionamentoDeAcesso_Parte1.pdf Permissionamento de Arquivos - Parte 1]<br />
<br />
=AULA 6 - Dia 12/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Aval1<br />
<br />
==Comand wget==<br />
<br />
Para fazer o downloiad do Linux Ubuntu via linha de comando:<br />
<br />
wget http://mirror.pop-sc.rnp.br/mirror/ubuntu-releases/18.04.3/ubuntu-18.04.3-desktop-amd64.iso<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/fdl5kzq0ba2nv3v/Aula4_Linux_PermissionamentoDeAcesso_Parte2.pdf Permissionamento Parte 2 ]<br />
<br />
=AULA 7 - Dia 12/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Instalação do Ubuntu em partições separadas<br />
*Permissionamento de Grupos e Outros<br />
*Criação de Contas de Usuários<br />
*Camandos adicionais para gerenciamento de processos<br />
<br />
==Instalação==<br />
<br />
Considere a estrutura de sistemas de arquivos abaixo. Montar um sistema de arquivos da forma abaixo considerando que sb1 seria um segundo hd máquina virtual.<br />
<br />
[[arquivo:SOP2019-1-ExemploMontagemSistema.png]]<br />
<br />
Logar no sistema e usando o terminal verificar as configurações estabelecidas.<br />
<br />
df -h<br />
cd /home<br />
ls spock<br />
<br />
Usar o comando gparted para criar uma partição adicional no segundo disco.<br />
<br />
sudo apt-get install gparted<br />
sudo gparted<br />
<br />
Redimensionar a partição original para poder criar uma adicional.<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/fdl5kzq0ba2nv3v/Aula4_Linux_PermissionamentoDeAcesso_Parte2.pdf Permissionamento Parte 2 ]<br />
<br />
*[https://www.dropbox.com/s/ozjd3qz0yblcj43/Aula6_Comandos_Adicionais_de_Gerenciamento_de_Processos.pdf Gerenciamento de Processos Parte 2]<br />
<br />
=AULA 8 - Dia 12/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Permissionamento de Grupos e Outros<br />
*Criação de Contas de Usuários<br />
*Reparticionamento de Disco após instalação. Montagem de sistemas com mount.<br />
<br />
==Desafio Final==<br />
<br />
Na máquina instalada na aula anterior fazer as seguintes operações:<br />
<br />
*Reparticionar o disco 2 (/dev/sdb) em 2 partições de 5G (usar o comando gparted) (redimensionar a partição do spock)<br />
*Criar uma conta para o usuário uhura<br />
*Criar dois subdiretórios no diretório home de uhura. Estes diretórios serão pontos de montagem dos dois sistemas de arquivos criados no segundo disco.<br />
*Montar os sistemas de arquivos usando o comando mounthttps://wiki.sj.ifsc.edu.br/index.php/ISL-FicLinux_(Plano_de_Ensino)<br />
*Mudar o dono destes diretórios (usuário e grupo) )para o novo dono (uhura)<br />
*Verificar o sistema montado (comando df)<br />
*Testar o acesso entrando como <br />
<br />
==Continuando o o permissionamento de Grupos e Outros==<br />
<br />
Ver material de referência<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/fdl5kzq0ba2nv3v/Aula4_Linux_PermissionamentoDeAcesso_Parte2.pdf Permissionamento Parte 2 ]<br />
*[https://www.dropbox.com/s/ozjd3qz0yblcj43/Aula6_Comandos_Adicionais_de_Gerenciamento_de_Processos.pdf Gerenciamento de Processos Parte 2]<br />
<br />
=AULA 9 - Dia 24/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*ainda criação de usuários<br />
*ainda gerenciamento de processos: crontab<br />
*compactação e backups em linha de comando<br />
<br />
<br />
==Material de Referência==<br />
<br />
<br />
*[Ainda Gerenciamento de Usuários https://www.dropbox.com/s/8vsg0yeforcsuq9/Aula7_GerenciamentoDeUsuarios_Parte1.pdf?dl=0]<br />
*[https://www.dropbox.com/s/ozjd3qz0yblcj43/Aula6_Comandos_Adicionais_de_Gerenciamento_de_Processos.pdf Gerenciamento de Processos Parte 2]<br />
*[https://www.dropbox.com/s/61n9is9c8o7bgbz/Aula3_Linux_Parte3_vi.pdf?dl=0 Introdução ao VI]<br />
<br />
=AULA 10 - Dia 26/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Finalização da aula anterior: arquivo sudoers<br />
*Introdução ao shell script<br />
*Um pouco sobre instalação de pacotes<br />
*exercicício avaliativo 2<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/54tnv5rjwguzppd/Aula8_ShellScript_Parte1.pdf?dl=0 Introdução ao Shell script]<br />
*[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula9-pacotes.pdf Instalação de Pacotes (Prof.Luciano Barreto)]<br />
<br />
=AULA 11 - Dia 1/10/2019=<br />
<br />
Introdução a Redes de Computadores<br />
**Conceito Básicos em Redes e Protocolos<br />
**Ferramentas de Redes<br />
**Exemplo de Protocolo de Aplicação: http<br />
**O processo de encapsulamento<br />
<br />
==Plano de Ensino==<br />
<br />
*[https://wiki.sj.ifsc.edu.br/index.php/PRL-FicLinux_(Plano_de_Ensino) Plano de Ensino]<br />
<br />
<br />
==Laboratório 1 - Ferramentas de Rede e Conceitos Básicos==<br />
<br />
*Familiarização com a infraestrutura dos laboratórios de redes<br />
*Familiarização com ferramentas de rede: ifconfig, ping, traceroute;<br />
*Desenvolver a noção de endereçamentos de rede IP e de endereço de hardware (MAC)<br />
*Desenvolver a noção de rotas em redes IP<br />
*Testar a conectividade IP com ping<br />
<br />
*Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)]<br />
<br />
==Laboratório 2 - Wireshark e encapsulamento==<br />
<br />
*Familiarização com o sniffer de rede WireShark<br />
*Observar o comportamento do ping e se familiarizar com o processo de encapsulamento;<br />
<br />
**Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)]<br />
<br />
==Conceituando Protocolos e Aplicações de Rede==<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/Conceituando%20protocolos.pdf Conceituando protocolos]<br />
<br />
<br />
=AULA 12 - Dia 03/10/2019=<br />
<br />
==Objetivos==<br />
<br />
*Conceituando protocolos<br />
*Protocolos de aplicação: exemplo http<br />
<br />
==Laboratório 3 - Conceituando protocolo==<br />
<br />
Ver [https://wiki.sj.ifsc.edu.br/index.php?title=ISL-FicLinux_(p%C3%A1gina)&action=edit&section=69]<br />
<br />
==Laboratório 4 - Desvendando o HTTP com Wireshark - BÁSICO==<br />
<br />
Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)#Parte_1:_Observando_interfaces_do_sistema_com_ifconfig]<br />
<br />
<br />
{{collapse bottom}}<br />
<br />
<br />
<br />
{{collapse top | Semestre 2019-1 - Prof. Tiago Semprebom e Eraldo Silveira e Silva}}<br />
<br />
=Professor=<br />
<br />
:*Prof. [[Tiago Semprebom]]<br />
:*email: tisemp@ifsc.edu.br<br />
:*sala: Sala de II de Professores da Área de Telecomunicações (primeira sala lado da Biblioteca - direção esquerda)<br />
<br />
=12/03/2019=<br />
<br />
==Objetivos==<br />
<br />
===Parte 1===<br />
*Apresentar os professores e o coordenador;<br />
*Apresentar o IFSC: estrutura, câmpus e serviços<br />
*Apresentar o curso: perfil do egresso, competências gerais, áreas de atuação do egresso e conteúdos previstos<br />
*Apresentar o Cronograma Tentativa<br />
*Apresentar metodologia e forma de avaliação<br />
<br />
===Parte 2===<br />
<br />
*Conceitos de Hardware, Software e Firmware<br />
*Arquiteturas de processadores<br />
*Classificação de softwares<br />
*Conceitos de Sistemas Operacionais e exemplos<br />
<br />
===Parte 3===<br />
<br />
*Histórico do Linux<br />
*Linux e GNU/Linux<br />
*Arquitetura do Linux<br />
*Distribuições<br />
*Distribuições usadas no IFSC/SJ<br />
*Ligando e Desligando o Sistema<br />
*Primeiros contatos.<br />
<br />
==Professores do FIC Linux Edição 2019-1==<br />
*Prof. [[Tiago Semprebom]] (Introdução ao Linux)<br />
*Prof. [[Eraldo Silveira e Silva]] (Redes com Linux)<br />
<br />
==Apresentação do IFSC==<br />
<br />
*[http://www.ifsc.edu.br/estrutura-organizacional-inicio Página do IFSC]<br />
*[https://www.sj.ifsc.edu.br/index.php Página do Câmpus]<br />
<br />
==Apresentação do Curso==<br />
<br />
*[[ISL-FicLinux_(Plano_de_Ensino) | Introdução ao Linux]]<br />
*[[PRL-FicLinux (página) | Projeto de Rede Residencial com o Linux]]<br />
*[[Curso_de_Formação_Continuada_de_Configuração_de_Redes_de_Computadores_Linux | PPC do Curso e Outras Regulamentações]]<br />
<br />
==Cronograma Tentativa==<br />
<br />
Horários: 19h às 22h.<br />
<br />
{| class="wikitable"|<br />
| AULA || DATA || Professor || Conteúdo<br />
|-<br />
| 1 || 12/03/2019 || TIAGO || Programa da Disciplina.Forma de Avaliação. O computador: hardware e software. SO Linux: histórico e distribuições. Ligando/Logando/Desligando a Máquina. Conceitos básico de Sistema de Arquivos e Processos.<br />
|-<br />
| 2 || 14/03/2019 || TIAGO || Gerenciamento de Arquivos I: Operações sobre arquivos e diretórios usando o terminale o Nautilus.<br />
|-<br />
| 3 || 21/03/2019 || TIAGO || Gerenciamento de Arquivos II: continuação Operações sobre arquivos e diretórios. Links Simbólicos, Criação de Arquivo com vi e outros editores.<br />
|-<br />
| 4 || 26/03/2019 || TIAGO || Interfaces Gráficas: X11, Gnome. KDE e outras. Instalação de Programas via Gerenciador de Pacotes.<br />
|-<br />
| 5 || 28/03/2019 || TIAGO || Administração de contas de usuários I<br />
|-<br />
| 6 || 02/04/2019 || TIAGO || Administração de contas de usuários II<br />
|-<br />
| 7 || 04/04/2019 || TIAGO || Permissionamento de Arquivos<br />
|-<br />
| 8 || 09/04/2019 || TIAGO || Gerenciamento de Processos<br />
|-<br />
| 9 || 11/04/2019 || TIAGO || Introdução ao Shell Script<br />
|-<br />
| 10 || 16/04/2019 || TIAGO || Avaliação 1 - Introdução ao Sistema Operacional Linux<br />
|-<br />
| 11 || 09/10/2019 || ERALDO || Introdução a Redes. Conceito de Protocolos. Ferramentas de Rede.<br />
|-<br />
| 12 || 11/10/2019 || ERALDO || Protocolos de Aplicação: exemplo http <br />
|-<br />
| 13 || 16/10/2019 || ERALDO || O DNS como protocolo de Aplicação; Camada de Transporte: protocolo UDP <br />
|-<br />
| 14 || 18/10/2019 || ERALDO || Protocolo TCP. Diferenças dos protocolos de Transporte TCP/UDP. Camada IP e aspectos da configuração da mesma sob o Linux<br />
|-<br />
| 15 || 23/10/2017 || ERALDO || Camada de Enlace/Física. Hubs X Switches. O Papel do Protocolo ARP. Outros serviços/protocolos: Serviço DHCP e NAT<br />
|-<br />
| 16 || 25/10/2017 || ERALDO (TIAGO) || Segmentação Redes IP. Cálculo de subredes. <br />
|-<br />
| 17 || 30/10/2017 || ERALDO || Introdução ao IPV6. Introdução ao Access Point TPLINK N750: configuração da LAN e WAN<br />
|-<br />
| 18 || 01/11/2017 || ERALDO || Serviço SSH no Linux. Acesso a rede WIFI. Conceitos básicos de redes sem fio.<br />
|-<br />
| 19 || 06/11/2007 || ERALDO || Tópicos Adicionais sobre redes no Linux: Configuração Manual X NetworkManager. Relatório Avaliativo 1.<br />
|-<br />
| 20 || 08/11/2017 || ERALDO || Relatório Avaliativo 2<br />
|}<br />
<br />
==Metodologia, Avaliação e Critérios de Aprovação==<br />
<br />
*Aaulas expositivas e aulas práticas no laboratório. Nas aulas práticas serão desenvolvidos exercícios e trabalhos individuais.<br />
*Avaliações individuais: Listas de exercícios com aproveitamento e entregues no prazo. <br />
*Critérios para aprovação: Serão considerados aprovados os alunos que obtiverem conceito final 6 ou superior em cada componente curricular. ATENÇÂO: Possuir no mínimo 75% de presença<br />
<br />
==Bibliografia==<br />
<br />
#Odilson Tadeu Valle<br />
##Administração de redes com Linux: fundamentos e práticas<br />
##Editora IFSC, 2010<br />
#Gleydson Mazioli da Silva<br />
##Guia Foca Linux<br />
##http://www.guiafoca.org/<br />
#Luiz Carlos Lobato Lobo de Medeiros e Wendel Soares<br />
##Formação de suporte técnico PROINFO<br />
##https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo<br />
#Ari Frazão Jr e Marcelo Braga<br />
##Administração de Sistemas Linux<br />
##https://pt.scribd.com/doc/128912228/Administracao-de-Sistemas-Linux<br />
<br />
==Conceitos de Hardware, Software e Firmware==<br />
<br />
*Em informática, o hardware consiste nos equipamentos<br />
**Ex: Computador, teclado, mouse, monitor<br />
*Software é um aplicativo, desenvolvido em uma linguagem de programação<br />
**Ex: Windows, Linux, Mozilla Firefox, Google Chrome<br />
*Firmware é um conjunto de instruções básicas e específicas para um hardware<br />
**Ex: BIOS nos computadores, sistemas de controle das máquinas de lavar, etc.<br />
<br />
==Estrutura de um Computador e Arquitetura de Processadores==<br />
<br />
*Bits, [https://pt.wikipedia.org/wiki/Byte Bytes] e tamanho de memória;<br />
*Representação de Caracteres: [https://pt.wikipedia.org/wiki/ASCII Tabela ASCII];<br />
*O [https://pt.wikipedia.org/wiki/Microprocessador microprocessador], barramentos e memórias semicondutoras: RAM,ROM, E2PROM, FLASH;<br />
*Memórias cache e memórias secundárias;<br />
*[https://pt.wikipedia.org/wiki/Mem%C3%B3ria_virtual Memória Virtual] e Swapping;<br />
*Registradores de 32bits ou 64bits<br />
*Arquitetura [https://pt.wikipedia.org/wiki/X86 x86] / [https://pt.wikipedia.org/wiki/AMD64 x86-64] – presente nos computadores pessoais<br />
*Arquitetura ARM – presente em sistemas embarcados e dispositivos móveis<br />
*Múltiplos núcleos (core)<br />
*Máquinas Virtuas: VirtualBox, UML (User Mode Linux).<br />
<br />
==O papel do Sistema Operacional==<br />
<br />
*O [https://pt.wikipedia.org/wiki/Sistema_operativo SO] é um programa (software) que controla a máquina e a torna utilizável para o usuário;<br />
*Abstrações do Sistema: arquivos e processos;<br />
*Pode ser multitarefa e multiusuário;<br />
*[https://en.wikipedia.org/wiki/Device_driver Driver] de dispositivo<br />
*[https://pt.wikipedia.org/wiki/Multi_boot Múltiplos OS instalados] em um computador. É possível??<br />
<br />
==Sistema de Arquivos==<br />
<br />
*Forma como estão estruturados/organizados os arquivos/dados em uma determinada mídia [https://pt.wikipedia.org/wiki/Sistema_de_ficheiros];<br />
*Um sistema operacional deve saber como acessar e operar sobre este sistema;<br />
*Tipos de sistemas: ext4, NTFS, VFAT32<br />
<br />
==Exemplos de SO==<br />
<br />
*Unix<br />
*Microsoft DOS<br />
*IBM<br />
*Microsoft Windows<br />
*netBSD, freeBSD, openBSD<br />
*Linux<br />
*macOS<br />
*Android<br />
*iOS<br />
<br />
==Histórico do Linux==<br />
<br />
*O início de tudo: UNIX;<br />
*Surgiu em 1991 quando Linus Torvalds, um estudante finlandês, resolveu desenvolver um sistema operacional compatível com a POSIX, por em que pudesse ser executado em arquitetura x86;<br />
*Linux está sob uma licença de software livre e diversas pessoas e empresas contribuem para o desenvolvimento do mesmo.<br />
*E o que é [https://pt.wikipedia.org/wiki/POSIX POSIX]? Define padrões para a interface de programação de aplicações (API) de um OS de forma a manter compatibilidade com o UNIX;<br />
<br />
==Arquitetura do Linux==<br />
<br />
*Ver pg.16 a 19 de [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo]<br />
<br />
==Distribuições==<br />
<br />
Uma distribuição Linux consiste de um kernel Linux e uma coleção de software utilitários e aplicativos de usuário (baseado slides Prof. Emerson)<br />
**Redhat<br />
**Slackware<br />
**Debian<br />
**Ubuntu<br />
**OpenSuse<br />
**Fedora<br />
**CentOS<br />
**Kali<br />
<br />
<br />
Algumas distribuições podem ser executadas diretamente no CD/pendrive<br />
sem a necessidade de fazer sua instalação no disco rígido do computador<br />
<br />
==Distribuições aqui no IFSC SJ==<br />
<br />
*Ubuntu<br />
*Ubuntu Mate (fork do Ubuntu)<br />
*Debian<br />
<br />
==Ligando e Desligando o Sistema Linux==<br />
<br />
*Cuidado ao desligar um OS como o Linux!!! Dados podem ser perdidos.<br />
*Ver [https://pt.wikibooks.org/wiki/Guia_do_Linux/Iniciante%2BIntermedi%C3%A1rio/Introdu%C3%A7%C3%A3o/Ligando_o_computador]<br />
<br />
==O Desktop do Ubuntu - Primeiras Considerações==<br />
<br />
*O Desktop no Ubuntu ver[https://help.ubuntu.com/stable/ubuntu-help/shell-overview.html]<br />
<br />
=AULA 2 - Dia 14/03/2019=<br />
<br />
==Objetivos==<br />
<br />
===PARTE 1===<br />
<br />
*Revisão da aula passada;<br />
*repassar itens não mencionados na aula passada;<br />
**Paginação e Memória [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo pg.19]<br />
**Estrutura do Linux [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo pg.18]<br />
<br />
===PARTE 2===<br />
<br />
*Operações com arquivos e diretórios usando o terminal;<br />
*formato de um comando básico;<br />
*quase tudo no Linux é arquivo: tipos de arquivos, diretórios, arquivos ordinários;<br />
*conceito de sistema de arquivos;<br />
*conceito de referência absoluta e relativa;<br />
*conceito de diretório de entrada, diretório de trabalho;<br />
*mudando de diretório com cd;<br />
*listando diretórios e arquivos com ls;<br />
*vendo o significado de um comando com man;<br />
*criando diretórios com mkdir;<br />
*removendo diretórios e arquivos com rmdir e rm;<br />
*referência com . .. - ~<br />
*criando arquivos ordinários com touch;<br />
*arquivos e diretórios escondidos;<br />
*copiando arquivos;<br />
*movendo e renomeando arquivos;<br />
*vendo a história de comandos com history;<br />
<br />
==Conceito de sistemas de arquivos, arquivos e diretórios==<br />
<br />
* [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Sistemas de Arquivos pg.18]<br />
* [Estrutura básica de diretórios do Sistema Linux]<br />
<br />
==Comandos no Linux==<br />
<br />
* [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Comandos e Interpretador de Comandos no Linux pg.18]<br />
<br />
==Tipos de Arquivos==<br />
<br />
* [https://pt.scribd.com/doc/128912228/Administracao-de-Sistemas-Linux Tipos de Arquivos 12,13 e 14 ]<br />
<br />
==Os comandos de operação sobre arquivos e diretórios==<br />
<br />
*[https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Interpretador de comandos - Comandos Básicos - pg.20 e 21]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_2_FICLinux.pdf Ver lista de exercícios da Aula 2]<br />
<!-- *[https://www.dropbox.com/s/g3xr3wimffde2zm/Aula2_Linux_OperacoesComArquivos_2.pdf Ver lista de exercícios da Aula 3] --><br />
<br />
=AULA 3 - Dia 21/03/2019 (aula com Prof. Eraldo)=<br />
<br />
==Objetivos==<br />
<br />
===PARTE 1===<br />
<br />
*Rever comandos básicos de operações sobre arquivos;<br />
*Usar coringas<br />
*usar opções do comando ls<br />
<br />
===PARTE 2===<br />
<br />
*uso do editor gedit para criar arquivos texto;<br />
*usar comandos cat, more e less para visualizar conteúdos de arquivos.<br />
<br />
===PARTE 3===<br />
<br />
*Criar Links simbólicos<br />
<br />
===Parte 4===<br />
<br />
*Redirecionamento de entradas e saídas;<br />
*Pipes<br />
<br />
==Exercícios para esta aula==<br />
'''Créditos e agradecimentos ao Prof. Eraldo pelo desenvolvimento das listas utilizadas''':<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_3_FICLinux.pdf Mais operações Sobre Arquivos e Diretórios]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_4_FICLinux.pdf Editor Gedit, Link Simbólico]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_5_FICLinux.pdf Editor vi]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_6_FICLinux.pdf Entradas e Saídas]<br />
<br />
=AULA 4 - Dia 26/03/2019=<br />
<br />
==Objetivos==<br />
<br />
===PARTE 1===<br />
<br />
*Revisão geral<br />
<br />
<br />
===PARTE 2===<br />
<br />
*Redirecionamento de entradas e saídas: continuação;<br />
*Pipes<br />
<br />
===PARTE 3===<br />
<br />
*Permissão no acesso a arquivos;<br />
*Owner, grupo e outros<br />
<br />
==Exercícios para esta aula==<br />
<br />
=Referências=<br />
<br />
[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_7_FICLinux.pdf Permissão de Acesso a Arquivos: parte 1]<br />
<br />
[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_8_FICLinux.pdf Permissão de Acesso a Arquivos: parte 2]<br />
<br />
=AULA 5 - Dia 28/03/2019=<br />
<br />
==Objetivos==<br />
<br />
*Revisão e preparação para teste;<br />
*introdução ao gerenciamento de processos;<br />
**conceito de processo<br />
**escalonamento de processos<br />
**PID e PPID<br />
**fork/exec<br />
**espaço de endereçamento de um processo;<br />
**estados de um processo: Running, Stopped, Sleeping, Zombie<br />
<br />
https://www.tecmint.com/linux-process-management/<br />
<br />
==Referências==<br />
<br />
[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_9_FICLinux.pdf Gerenciamento De Processos Parte 1]<br />
[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_10_FICLinux.pdf Gerenciamento De Processos Parte 2]<br />
<br />
[https://www.dropbox.com/s/gm1sv856ailny2e/Aula5_TreinamentoTeste.pdf Treinamento Teste 1]<br />
<br />
=AULA 6 - Dia 02/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*Comandos adicionais de gerenciamento de processos;<br />
*Mudança de prioridade com nice e renice;<br />
*Agendamento de processos com crontab<br />
*Aplicações do crontab: conectividade de rede e backup<br />
*Ferramentas de compactação;<br />
*Execução de comandos inseridos em outros comandos;<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/z1d0itcz9ommhrm/Aula6_Aval1.pdf Avaliação 1]<br />
<br />
=AULA 7 - Dia 04/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*Comandos adicionais de manipulação de arquivos:<br />
**comando grep;<br />
**comando find;<br />
*Gerenciamento de usuários:<br />
**adição e remoção de usuários e grupos<br />
**arquivo sudoers<br />
<br />
<br />
==Exercícios==<br />
<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_11_FICLinux.pdf Comandos Adicionais] <br />
<!--*[https://www.dropbox.com/s/h0v122is4aj9ogr/Aula7_GerenciamentoDeUsuarios_Parte1.pdf Aula 7 - Parte 2]--><br />
<br />
=AULA 8 - Dia 09/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*Introdução ao Shell script<br />
*variáveis<br />
*Comando if<br />
<br />
==Referências==<br />
<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_14_FICLinux.pdf Outros comando gerenciamento de processos]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_12_FICLinux.pdf Shell Parte 1]<br />
<br />
{{collapse top | script DESAFIO (a)}}<br />
<syntaxhighlight lang=c><br />
#!/bin/bash<br />
<br />
FILE="$1"<br />
<br />
if [ ! $# -eq 1 ]; then<br />
echo opa! Algo errado...<br />
echo uso: script parametro<br />
exit<br />
fi<br />
<br />
<br />
if [ -h $FILE ]; then<br />
echo $FILE é um link simbólico<br />
else<br />
echo $FILE não é um link simbólico<br />
fi<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
{{collapse top | script DESAFIO (b)}}<br />
<syntaxhighlight lang=c><br />
<br />
#!/bin/bash<br />
<br />
FILE="$1"<br />
<br />
if [ ! $# -eq 1 ]; then<br />
echo opa! Algo errado...<br />
echo uso: script parametro<br />
exit<br />
fi<br />
<br />
<br />
if [[ -w $FILE && -O $FILE ]]; then<br />
echo Possui permissao de escrita de $FILE<br />
else<br />
echo Colocando permissão de escrita para $FILE<br />
chmod u+w $FILE<br />
echo permissoes adicionadas com sucesso para $FILE ver abaixo<br />
ls -l $FILE<br />
<br />
fi<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
{{collapse top | script DESAFIO (c)}}<br />
<syntaxhighlight lang=c><br />
#!/bin/bash<br />
<br />
FILE1="$1"<br />
FILE2="$2"<br />
<br />
if [ ! $# -eq 2 ]; then<br />
echo opa! Algo errado...<br />
echo uso: script parametro<br />
exit<br />
fi<br />
<br />
if [[ -f $FILE1 && -r $FILE1 ]]; then<br />
echo $1 É regular e possui permissao de leitura<br />
mv $FILE1 $FILE2<br />
echo Mudei o nome de $FILE1 para $FILE2<br />
else<br />
echo $FILE1 não tem permissao...<br />
fi<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
=AULA 9 - Dia 11/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*ainda shell script<br />
*comando for<br />
*comando while<br />
<br />
==Referências==<br />
<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_13_FICLinux.pdf Shell Parte 2]<br />
<br />
=AULA 10 - Dia 16/04/2019=<br />
<br />
*Avaliação da disciplina<br />
<br />
=Tópicos extras=<br />
<br />
==Objetivos==<br />
<br />
*mais alguns tópicos sobre criação de usuários;<br />
*servidores de janelas: X11, <br />
*gerenciadores de janelas e desktops: Gnome, KDE<br />
*instalação de pacotes;<br />
*o Linux e o Software Livre<br />
*avaliação<br />
<br />
==Servidores de Janelas==<br />
<br />
[https://pt.wikipedia.org/wiki/X_Window_System X Windows System]<br />
<br />
[https://en.wikipedia.org/wiki/X_Window_System_protocols_and_architecture Arquitetura do X]<br />
<br />
==Desktops e Geneciadores de Janelas==<br />
<br />
[https://pt.wikipedia.org/wiki/Interface_gr%C3%A1fica_do_utilizador Interfaces Gráficas]<br />
<br />
==Instalando pacotes==<br />
<br />
[https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Ver pg.43 do Formacao-de-Suporte-Tecnico-Proinfo]<br />
<br />
[http://www.hardware.com.br/tutoriais/tutorial-completo-apt-get/ uso do apt-get]<br />
<br />
Exercício: instalar e executar um servidor ssh:<br />
<br />
sudo apt-get update<br />
sudo apt-get install openssh-server<br />
sudo service start ssh<br />
<br />
Acessar o ssh de outra máquina<br />
ssh usuario@numero_ip<br />
<br />
Exportar o display e executar o comando remoto:<br />
export DISPLAY=IP_cliente_ssh:0.0<br />
firefox &<br />
<br />
Conferir se o firefox realmente está se executando (use o ps)<br />
<br />
Remover o pacote ssh server:<br />
<br />
sudo apt-get remove openssh-server<br />
<br />
==Linux = Software Livre==<br />
<br />
[https://pt.wikipedia.org/wiki/Software_livre]<br />
<br />
<br />
<br />
[https://www.novell.com/coolsolutions/feature/1532.html]<br />
<br />
==Onde baixar o Ubuntu==<br />
<br />
[https://www.ubuntu.com/download/desktop Baixar Ubuntu daqui]<br />
<br />
==Sobre o Boot==<br />
<br />
[http://www.rodsbooks.com/linux-uefi/ by Roderick W. Smith]<br />
<br />
[https://www.happyassassin.net/2014/01/25/uefi-boot-how-does-that-actually-work-then/ AdamW on Linux and more]<br />
<br />
==Sobre o Desktop Environment e o Desktop Shell==<br />
<br />
[https://ittutorials.net/linux/ubuntu/desktop-guide/ /desktop-guide]<br />
<br />
==Instalar Ubuntu no Virtual Box==<br />
<br />
[http://www.edivaldobrito.com.br/virtualbox-no-linux/ Instalar VirtualBox no Linux]<br />
<br />
[http://www.bosontreinamentos.com.br/virtualizacao/como-instalar-o-virtualbox-no-windows-para-criacao-de-maquinas-virtuais/ Instalar VirtualBox no Windows]<br />
<br />
[http://www.techtudo.com.br/dicas-e-tutoriais/noticia/2016/04/como-instalar-o-ubuntu-com-o-virtualbox.html Instalar Linux no VirtualBox]<br />
<br />
=AULA 11 - Dia 23/04/2019=<br />
<br />
*Introdução a Redes de Computadores<br />
**Conceito Básicos em Redes e Protocolos<br />
**Ferramentas de Redes<br />
**Exemplo de Protocolo de Aplicação: http<br />
**O processo de encapsulamento<br />
<br />
==Plano de Ensino==<br />
<br />
*[https://wiki.sj.ifsc.edu.br/index.php/PRL-FicLinux_(Plano_de_Ensino) Plano de Ensino]<br />
<br />
<br />
==Laboratório 1 - Ferramentas de Rede e Conceitos Básicos==<br />
<br />
*Familiarização com a infraestrutura dos laboratórios de redes<br />
*Familiarização com ferramentas de rede: ifconfig, ping, traceroute;<br />
*Desenvolver a noção de endereçamentos de rede IP e de endereço de hardware (MAC)<br />
*Desenvolver a noção de rotas em redes IP<br />
*Testar a conectividade IP com ping<br />
<br />
*Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)]<br />
<br />
==Laboratório 2 - Wireshark e encapsulamento==<br />
<br />
*Familiarização com o sniffer de rede WireShark<br />
*Observar o comportamento do ping e se familiarizar com o processo de encapsulamento;<br />
<br />
**Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)]<br />
<br />
==Conceituando Protocolos e Aplicações de Rede==<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/Conceituando%20protocolos.pdf Conceituando protocolos]<br />
<br />
=AULA 12 - Dia 25/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*Protocolos de aplicação: exemplo http<br />
<br />
==Laboratório 4 - Desvendando o HTTP com Wireshark - BÁSICO==<br />
<br />
Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)#Parte_1:_Observando_interfaces_do_sistema_com_ifconfig]<br />
<br />
=AULA 13 - Dia 30/04/2019=<br />
<br />
*Revisão do Conceito de Protocolo ([-] Laboratório 3 - Conceituando protocolos )<br />
*O DNS como protocolo de Aplicação;<br />
*Camada de Transporte: protocolo UDP<br />
<br />
==Revisão dos Conceitos de Protocolo==<br />
<br />
Laboratório 3 - Conceituando protocolos [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)#Parte_1:_Observando_interfaces_do_sistema_com_ifconfig]<br />
<br />
==O DNS como protocolo de Aplicação==<br />
<br />
Laboratório 7 - Serviço de Nomes (DNS) [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)#Parte_1:_Observando_interfaces_do_sistema_com_ifconfig]<br />
<br />
==O Protocolo UDP==<br />
<br />
Laboratório 8 - Desvendando o UDP - Básico <br />
<br />
=AULA 14 - Dia 02/05/2019=<br />
<br />
==Objetivos==<br />
<br />
*Explorar o papel e diferenças dos protocolos de Transporte TCP/UDP<br />
*Explorar a Camada IP e aspectos da configuração da mesma sob o Linux<br />
<br />
<br />
===TCP e UDP===<br />
<br />
*docente.ifsc.edu.br/odilson/RCO60803/TCP%20controle%20de%20erros.pdf<br />
*docente.ifsc.edu.br/odilson/RCO60803/UDP%20Basico.pdf<br />
<br />
==Camada IP no Linux: Configuração das Interfaces usando ifconfig e ip addr==<br />
<br />
Usando a ferramenta Netkit2, que permite construir redes virtuais com o Linux vamos construir DUAS redes locais interligadas por um roteador. Em cada rede colocaremos dois PCs. As interfaces estarão completamente desconfiguradas:<br />
<br />
<ol><br />
<li><br />
Construir um arquivo texto de nome rede.conf usando o editor de texto gedit.<br />
<code>gedit rede.conf &</syntaxhighlight> <br />
</li><br />
<li><br />
Criar a seguinte topologia:<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=generic<br />
<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
#Definição da Topologia da Rede<br />
<br />
pc1[eth0]=lan0<br />
pc2[eth0]=lan0<br />
<br />
pc3[eth0]=lan1<br />
pc4[eth0]=lan1<br />
<br />
r1[eth0]=lan0<br />
r1[eth1]=lan1<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Executar netkit fazendo (atualize se necessário - pergunte para o professor como fazer):<br />
Aplicativos >> Educativo >> Netkit2 <br />
</li><br />
<li><br />
Carregar o arquivo lab.conf a partir do Netkit2:<br />
<code>File >> Load Only</syntaxhighlight><br />
</li><br />
<li><br />
Visualizar a rede a ser implementada:<br />
<code>File >> Graph</syntaxhighlight><br />
</li><br />
<li> <br />
Executar a configuração:<br />
<code>Network >> Start</syntaxhighlight><br />
</li><br />
<li><br />
Verificar o estado de todas interfaces (se UP ou DOWN) com:<br />
<code>ifconfig -a</syntaxhighlight><br />
<code>ip addr</syntaxhighlight> <br />
Note que nas últimas versões do Linux o comando ip vem sendo recomendado (embora o ifconfig ainda esteja disponível).<br />
</li><br />
<li><br />
Vamos configurar as interfaces. Para tanto vamos assumir que teremos duas sub-redes:<br />
<code>lan0 - endereço da rede 10.10.10.0/24</syntaxhighlight><br />
<code>lan1 - endereço da rede 20.20.20.0/24</syntaxhighlight><br />
A interface eth0 de PC1 receberá o endereço 10.10.10.1/24 e a interface eth0 de PC2 recebera 10.10.10.2/24. A interface do roteador NA lan0 também deve receber um endereço: 10.10.10.254/24:<br />
<br />
No PC1:<br />
<code>ifconfig eth0 10.10.10.1/24</syntaxhighlight><br />
No PC2:<br />
<code>ifconfig eth0 10.10.10.2/24</syntaxhighlight><br />
No R1:<br />
<code>ifconfig eth0 10.10.10.254/24</syntaxhighlight><br />
</li> <br />
<li><br />
Seguindo a mesma lógica configure as máquinas e o roteador na lan1<br />
</li><br />
<li> Um ponto importante a ser lembrado é que quando uma interface é configurada com um número IP, a tabela de roteamento do sistema é alimentada com o número correspondente da rede associada ao número. Isto pode ser observado em TODAS as máquinas, inclusive no roteador:<br />
<code> route -n </syntaxhighlight><br />
ou <br />
<code> ip route </syntaxhighlight><br />
</li><br />
</ol><br />
<br />
==Camada IP no Linux: verificando e configurando rotas - configuração da rota default ==<br />
<br />
<ol><br />
<li> Um ponto importante a ser lembrado é que quando uma interface é configurada com um número IP, a tabela de roteamento do sistema é alimentada com o número correspondente da rede associada ao número. Isto pode ser observado em TODAS as máquinas, inclusive no roteador:<br />
<code> route -n </syntaxhighlight><br />
ou <br />
<code> ip route </syntaxhighlight><br />
Esta informação é importante pois define a entrega DIRETA de pacotes na rede, ou seja, se PC1 quiser enviar um pacote para PC2, esta linha na tabela de roteamento garante que o pacote IP seja despachado diretamente para o PC2 através de um frame ETHERNET endereçado para o MAC do PC1.<br />
</li><br />
<li> Confira os endereços MAC e IP das interfaces dos PC1 e PC2 e anote. Faça um ping no PC1 em direção a PC2.<br />
<code>root@pc1:~# ping 10.10.10.2</syntaxhighlight><br />
</li><br />
<li> Use um capturador de pacotes em modo texto para observar o tráfego na eth0 do PC2. Observe os endereços MAC do Frame Ethernet e os endereços IP do pacote IP.<br />
<code>root@pc2:~# tcpdump -i eth0 -e</syntaxhighlight><br />
ENTÃO? O que se pode concluir? É uma entrega direta ou indireta? <br />
</li><br />
<li> Uma curiosidade. Tente observar o tráfego na interface eth0 do Roteador R1. É possível observar algo? O que se pode concluir? Pare agora o ping e os tcpdumps executados.<br />
</li><br />
<li> Qualquer máquina IP acaba tomando uma decisão de roteamento. O PC1, ao observar que PC2 está na sua própria rede 10.10.10.0/24, entrega diretamente o pacote. E se PC1 tentar entregar para PC3? Faça um ping e observe o que acontece:<br />
<code>root@pc1:~#ping 20.20.20.1</syntaxhighlight><br />
Não deve ter funcionado :-(<br />
Um primeiro problema é que simplesmente a camada IP observa que o endereço não é entrega DIRETA mas não tem informação (linha) na tabela de roteamento dizendo para quem deve ser entregue o pacote. <br />
</li><br />
<li> Vamos acrescentar uma linha na tabela de PC1 dizendo como fazer esta entrega INDIRETA. Usaremos o conceito de gateway default. Ou seja, se não tiver para quem entregar explicitamente, o pacote será entregue para o gateway default:<br />
<code>root@pc1:~# route add default gateway 10.10.10.254</syntaxhighlight><br />
confira o estabelocimento da rota:<br />
<code>root@pc1:~# route -n</syntaxhighlight><br />
tente o ping novamente escutando com o tcpdump na interface eth0 de R1. Ainda não funcionou mas o R1 já recebe os pacotes. Confira o MAC de destino do pacote. Deve ser o MAC do roteador. <br />
</li> <br />
<li><br />
POR QUE NÃO FUNCIONOU: será que R1 não sabe como entregar o pacote para PC3? Confira se o pacote sai de R1 na rede lan1:<br />
<code>root@r1:~# tcpdump -i eth2 -e</syntaxhighlight><br />
</li> <br />
<li><br />
Temos um problema ainda que o nosso roteador Linux NÃO está habilitado a ser roteador. Isto pode ser feito com:<br />
<code>echo 1 > /proc/sys/net/ipv4/ip_forward</syntaxhighlight><br />
</li> <br />
<li> Tente novamente o ping de PC1 para PC3. Ainda não funcionará mas escute a interface eth1 de R1 e a interface eth0 de PC3 e verá que os pacotes do ICMP REQUEST estão chegando. Confira inclusive os MACs envolvidos...<br />
</li><br />
<li><br />
O que estaria faltando ainda para que PC3 responda aos ECHO REQUEST? O problema é de entrega indireta. O PC3 não sabe como entregar pacotes "externos". Acrescente um gateway default.<br />
</li><br />
<li><br />
Exercício adicional com 2 roteadores. Ver manual:<br />
* [http://linux-ip.net/html Guia de Administração da Camada IP no Linux<br />
</li><br />
</ol><br />
<br />
==Exercício: acrescentando uma lan2 com com 2 PCs no roteador==<br />
<br />
Acrescente uma rede 30.30.30.0/24 (lan2) no roteador R1. Acrescente 2 PCs e configure o sistema.<br />
Teste a conectividade entre todos os PCs.<br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
pc5[type]=generic<br />
pc6[type]=generic<br />
<br />
pc7[type]=generic<br />
pc8[type]=generic<br />
<br />
<br />
#Definição da Topologia da Rede<br />
<br />
pc1[eth0]=lan0:ip=10.10.10.1/24<br />
pc1[default_gateway]=10.10.10.254<br />
<br />
pc2[eth0]=lan0:ip=10.10.10.2/24<br />
pc2[default_gateway]=10.10.10.254<br />
<br />
pc3[eth0]=lan1:ip=20.20.20.1/24<br />
pc3[default_gateway]=20.20.20.254<br />
<br />
pc4[eth0]=lan1:ip=20.20.20.2/24<br />
pc4[default_gateway]=20.20.20.254<br />
<br />
pc5[eth0]=lan2:ip=30.30.30.1/24<br />
pc5[default_gateway]=30.30.30.254<br />
<br />
pc6[eth0]=lan2:ip=30.30.30.2/24<br />
pc6[default_gateway]=30.30.30.254<br />
<br />
pc7[eth0]=lan4:ip=40.40.40.1/24<br />
pc7[default_gateway]=40.40.40.254<br />
<br />
pc8[eth0]=lan3:ip=50.50.50.1/24<br />
pc8[default_gateway]=40.40.40.254<br />
<br />
<br />
r1[eth0]=lan0:ip=10.10.10.254/24<br />
r1[eth1]=lan1:ip=20.20.20.254/24<br />
r1[eth2]=lan2:ip=30.30.30.254/24<br />
r1[eth3]=lan3:ip=50.50.50.253/24<br />
r2[eth1]=lan3:ip=50.50.50.254/24<br />
r2[eth0]=lan4:ip=40.40.40.254/24<br />
<br />
r2[route]=10.10.10.0/24:gateway=50.50.50.253<br />
<br />
</syntaxhighlight><br />
<br />
=AULA 15 - Dia 7/05/2019=<br />
<br />
*Hubs X Switches. O Papel do Protocolo ARP<br />
<br />
<br />
*Serviço DHCP e NAT<br />
[-] Laboratório 16 - Sub-redes e Roteamento Estático em Redes <br />
<br />
==Hubs, Switches. Protocolo ARP==<br />
<br />
[Laboratório 17 - Tecnologia de Enlace Ethernet]<br />
<br />
==Serviço DHCP==<br />
<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IP_DHCP_NAT.pdf DHCP e NAT]<br />
<br />
Construir uma rede simular a aula anterior mas deixar PC1 e PC2 desconfigurados. Criar uma máquina para atuar como servidor DHCP. <br />
<br />
<ol><br />
<li><br />
Editar o arquivo de configuração do dhcp server:<br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=gateway #já habilitado para forward<br />
<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
pcdhcp[type]=generic<br />
<br />
<br />
#Definição da Topologia da Rede<br />
<br />
pc1[eth0]=lan0 #desconfigurada...<br />
<br />
pc2[eth0]=lan0:ip=10.10.10.2/24<br />
pc2[default_gateway]=10.10.10.254<br />
<br />
pcdhcp[eth0]=lan0:ip=10.10.10.3/24<br />
pcdhcp[default_gateway]=10.10.10.254 <br />
<br />
pc3[eth0]=lan1:ip=20.20.20.1/24<br />
pc3[default_gateway]=20.20.20.254<br />
<br />
pc4[eth0]=lan1:ip=20.20.20.2/24<br />
pc4[default_gateway]=20.20.20.254<br />
<br />
<br />
r1[eth0]=lan0:ip=10.10.10.254/24<br />
r1[eth1]=lan1:ip=20.20.20.254/24<br />
<br />
</syntaxhighlight><br />
</li><br />
<li> No server estabelecer a configuração desejada:<br />
<br />
nano /etc/dhcp/dhcpd.conf<br />
<br />
com:<br />
<br />
<code><br />
<br />
subnet 10.10.10.0 netmask 255.255.255.0 {<br />
range 10.10.10.10 10.10.10.50;<br />
option routers 10.10.10.254;<br />
option broadcast-address 10.10.10.255;<br />
default-lease-time 600;<br />
max-lease-time 7200;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
</li><br />
<li><br />
Rodar o servidor DHCP na máquina pc_dhcp:<br />
<code><br />
/usr/sbin/dhcpd -q -4 -pf /run/dhcp-server/dhcpd.pid -cf /etc/dhcp/dhcpd.conf eth0<br />
</syntaxhighlight><br />
</li><br />
<li><br />
No cliente (PC1) fazer:<br />
<code><br />
dhclient -v eth0<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Usando o ifconfig e route confira se o PC1 está completamente configurado. Faça teste com o ping<br />
</li><br />
<li> Rode o tcpdump na eth0 de r1 para "verificar" os pacotes DHCP:<br />
<code><br />
tcpdump -i eth0<br />
</syntaxhighlight><br />
</li><br />
<li> Repetir a operação no PC2. Baixe a interface antes:<br />
<code><br />
ifconfig eth0 down<br />
dhclient -v eth0<br />
</syntaxhighlight><br />
</li><br />
</ol><br />
<br />
==O NAT==<br />
<br />
Vamos tentar elaborar um laboratório usando o NAT MASQUERADE<br />
https://www.karlrupp.net/en/computer/nat_tutorial<br />
<br />
Construir uma rede com 3 LANs e 2 roteadores como na aula passada. Executar o APACHE em uma máquina da lan3 (exemplo PC4). Não colocar rotas para lan0 em r2. Desta forma PC1 não deve pingar em PC4. <br />
<br />
<code><br />
LAN0 <-R1-> LAN1 <-R2 -> LAN3<br />
</syntaxhighlight><br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
pc1[type]=generic<br />
apache[type]=generic<br />
<br />
<br />
pc1[eth0]=lan0:ip=10.10.10.1/24<br />
pc1[default_gateway]=10.10.10.254<br />
<br />
<br />
r1[eth0]=lan0:ip=10.10.10.254/24<br />
r1[eth1]=lan1:ip=20.20.20.254/24<br />
r1[route]=30.30.30.0/24:gateway=20.20.20.253<br />
<br />
r2[eth0]=lan1:ip=20.20.20.253/24<br />
r2[eth1]=lan2:ip=30.30.30.254/24<br />
<br />
apache[eth0]=lan2:ip=30.30.30.1/24<br />
apache[default_gateway]=30.30.30.254<br />
</syntaxhighlight><br />
<br />
<ol><br />
<li> Rodar o apache em PC4:<br />
<code> /etc/init.d/apache2 start </syntaxhighlight><br />
</li><br />
<li> Testar se o Apache é acessível a partir de PC3<br />
<code>lynx END_PC3 </syntaxhighlight><br />
<li><br />
Em R1 fazer:<br />
<code>iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE</syntaxhighlight><br />
</li><br />
<li> Monitorar os pacotes que chegam e saem da eth0 de PC4.<br />
</li><br />
<li> Fazer em PC1:<br />
lynx END_PC4 #endereço de PC4.<br />
O que se pode concluir?<br />
</li><br />
<br />
</ol><br />
<br />
=AULA 16 - Dia 09/05/2019=<br />
*Endereçamento IPv4.<br />
*Exercícios segmentação Redes. <br />
<br />
===Objetivos===<br />
*Compreender endereçamento IPv4.<br />
*Compreender o processo de alocação de faixas de IPs.<br />
*Compreender e manipular os números IPs.<br />
*Compreender e manipular as máscaras de rede.<br />
*Proporcionar ao aluno uma visão prática de roteamento IP.<br />
<br />
===Fonte Básica===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IP_DHCP_NAT.pdf DHCP e NAT]<br />
*[http://www.davidc.net/sites/default/subnets/subnets.html Cálculo de sub-redes]<br />
<br />
===Roteiro===<br />
<br />
#Baseado no arquivo exemplo abaixo, crie um arquivo de configuração para o NetKit que implemente sua proposta. O arquivo deve contemplar todas as configurações necessárias para o perfeito funcionamento da rede, ou seja, ao carregar o arquivo todos os hosts deverão ser capazes de "pingar" uma ao outro. <br />
##Faça testes de conectividade entre os hosts.<br />
##Demonstre para o professor o perfeito funcionamento de sua rede.<br />
*O arquivo de configuração do Netkit abaixo, é a definição para o funcionamento da simulação da rede apresentada na Figura 2. Falta adicionar as rotas.<br />
<br />
[[Arquivo:DynamicRoutingTriangle.png |thumb | 400px| Figura 2 - Rede exemplo]]<br />
<br />
<code><br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=link0:ip=192.168.0.1/24<br />
pc2[eth0]=link1:ip=192.168.1.1/24<br />
pc3[eth0]=link2:ip=192.168.2.1/24<br />
<br />
# Default gateways definitions<br />
pc1[default_gateway]=192.168.0.254<br />
pc2[default_gateway]=192.168.1.254<br />
pc3[default_gateway]=192.168.2.254<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
r3[type]=gateway<br />
<br />
# Routers' interfaces to local networks<br />
r1[eth0]=link0:ip=192.168.0.254/24<br />
r2[eth0]=link1:ip=192.168.1.254/24<br />
r3[eth0]=link2:ip=192.168.2.254/24<br />
<br />
# Network "backbone" links<br />
r1[eth1]=backbone0:ip=10.0.0.1/30<br />
r1[eth2]=backbone1:ip=10.0.1.1/30<br />
<br />
r2[eth1]=backbone0:ip=10.0.0.2/30<br />
r2[eth2]=backbone2:ip=10.0.2.1/30<br />
<br />
r3[eth1]=backbone1:ip=10.0.1.2/30<br />
r3[eth2]=backbone2:ip=10.0.2.2/30 <br />
<br />
# Routes definition<br />
r1[route]=192.168.2.0/24:gateway=10.0.1.2<br />
r1[route]=192.168.1.0/24:gateway=10.0.0.2<br />
r1[route]=10.0.2.0/30:gateway=10.0.0.2<br />
<br />
r2[route]=192.168.0.0/24:gateway=10.0.0.1 <br />
r2[route]=192.168.2.0/24:gateway=10.0.2.2<br />
r2[route]=10.0.1.0/30:gateway=10.0.2.2<br />
<br />
r3[route]=192.168.0.0/24:gateway=10.0.1.1<br />
r3[route]=192.168.1.0/24:gateway=10.0.2.1<br />
r3[route]=10.0.0.0/30:gateway=10.0.2.1<br />
</syntaxhighlight><br />
<br />
===Exercícios Extras (resolvidos)===<br />
*[[Arquivo:exercicios_CIDR.pdf]]<br />
<br />
===Referencia===<br />
*[http://www.davidc.net/sites/default/subnets/subnets.html Link Calculador Online de Subnets]<br />
<br />
=AULA 17 - Dia 14/05/2019=<br />
<br />
*Finalização do Laboratório do NAT<br />
*Laboratório de Introdução ao IPV6<br />
*Introdução ao Access Point TPLINK N750: configuração da LAN e WAN<br />
<br />
==LAboratório de Introdução ao IPv6==<br />
<br />
===Material de REferência===<br />
<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IPv6.pdf IPv6]<br />
<br />
===Roteiro de atividades sobre o IPv6===<br />
<br />
A figura abaixo apresenta o diagrama esquemático da rede a ser montada/analisada. Observe que todos os IPv6 ''Global Unicast'' já estão definidos na mesma, são esses IPs que utilizaremos em nosso experimento.<br />
<br />
[[Arquivo:Diagrama_rede_IPv6.jpg]]<br />
<br />
#Crie em seu computador um arquivo com nome '''/home/aluno/IPv6.conf''', com o seguinte conteúdo: <syntaxhighlight lang=bash><br />
#Ligacao das maquinas nos dominios de colisao<br />
#Duas pequenas redes interligadas pelo backbone<br />
<br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=link0:ipv6=2001:bcc:faca:1::101/64<br />
pc2[eth0]=link1:ipv6=2001:bcc:cafe:1::102/64<br />
pc3[eth0]=HUB1:ipv6=2001:bcc:1f0:1::103/64<br />
pc4[eth0]=HUB1<br />
<br />
#Default Gateways definitions<br />
pc1[route]=default6:gateway=2001:bcc:faca:1::1<br />
pc2[route]=default6:gateway=2001:bcc:cafe:1::1<br />
pc3[route]=default6:gateway=2001:bcc:1f0:1::1<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
#Routers interfaces definitions<br />
r1[eth0]=backbone0:ipv6=2001:db8:dead:1::1/64<br />
r1[eth1]=link0:ipv6=2001:bcc:faca:1::1/64<br />
r1[eth2]=link1:ipv6=2001:bcc:cafe:1::1/64<br />
<br />
r2[eth0]=backbone0:ipv6=2001:db8:dead:1::2/64<br />
r2[eth1]=HUB1:ipv6=2001:bcc:1f0:1::1/64<br />
<br />
#Routers definitions<br />
r1[route]=2001:bcc:1f0:1::0/64:gateway=2001:db8:dead:1::2<br />
r2[route]=2001:bcc:faca:1::0/64:gateway=2001:db8:dead:1::1<br />
r2[route]=2001:bcc:cafe:1::0/64:gateway=2001:db8:dead:1::1<br />
</syntaxhighlight><br />
#Tenha certeza que o Netkit2 estja atualizado: General >> Update.<br />
#Rode o NetKit em seu computador. Em um terminal digite: <syntaxhighlight lang=bash><br />
netkit2 & </syntaxhighlight><br />
#No menu '''File''' - '''Load and Run''', procure o arquivo '''/home/aluno/IPv6.conf''' e clique em OK. Abrirá uma janela com 6 abas, onde cada uma delas é um terminal de configuração do respectivo equipamento: '''pc1-4''' ou '''r1-2'''.<br />
#Observe que o '''pc4''' não está com sua interface configurada.<br />
#Ao clicar no menu '''File''' - '''Graph''', pode-se ter uma visão da rede a ser simulada e conferir se é equivalente ao diagrama proposto.<br />
#Faça um '''ping6''' entre o '''pc1''' ao '''pc3''': <syntaxhighlight lang=bash><br />
ping6 -c4 2001:bcc:1f0:1::103 </syntaxhighlight><br />
#Faça um '''ping6''' entre o '''pc1''' e '''pc2'''.<br />
#No '''pc4''' use o seguinte comando para adicionar o endereço IPv6 à interface de rede: <syntaxhighlight lang=bash><br />
ip addr add 2001:bcc:1f0:1::104/64 dev eth0 </syntaxhighlight><br />
#No '''pc4''', acrescente o ''default gateway'' com o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add default via 2001:bcc:1f0:1::1 dev eth0 </syntaxhighlight><br />
#No '''pc1''' use o seguinte comando para verificar como ficou a configuração dos endereços da interface de rede. O resultado é similar ao apresentado pelo comando '''ifconfig''': <syntaxhighlight lang=bash><br />
ip addr show dev eth0 </syntaxhighlight><br />
#Todo o roteamento está pronto, mas caso desejássemos poderíamos acrescentar rotas com comando similares aos já utilizados. Por exemplo, no '''r1''', para adicionar uma rota estática para a rede dos '''pc3''' e '''pc4''' utilizaríamos o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add 2001:bcc:1f0:1::/64 via 2001:db8:dead:1::2 dev eth0 </syntaxhighlight><br />
#Confira as rotas estabelecidas em todos os ''hosts'' com o comando abaixo. <br />
##São coerentes com os dados apresentados no diagrama acima?<syntaxhighlight lang=bash><br />
ip -6 route show </syntaxhighlight><br />
#No '''pc1''' use os seguintes comandos para ver a rota para alguns vizinhos: <syntaxhighlight lang=bash><br />
traceroute6 2001:bcc:1f0:1::103<br />
traceroute6 2001:bcc:1f0:1::104 </syntaxhighlight><br />
#*Anote as rotas.<br />
#Deixe um '''ping6''' entre o '''pc1''' ao '''pc3''' rodando: <syntaxhighlight lang=bash><br />
ping6 2001:bcc:1f0:1::103 </syntaxhighlight><br />
<br />
==Introdução ao Roteador-AP da TP-Link==<br />
<br />
Ver manual https://www.tp-link.com/us/support/download/tl-wdr4300/<br />
<br />
===Configuração Básica===<br />
<br />
Seguir as instruções do professor para a seguinte configuração:<br />
<br />
#Retirar o plugue cabo ethernet que liga o PC do Lab a rede do IFSC. Conectar o PC a uma das portas LAN do AP;<br />
#Conectar a WAN do AP ao Lab. do IFSC;<br />
#Em um terminal do PC aplique o comando:<br />
sudo dhclient eth0<br />
#No browser do PC acesse o AP colocando o endereço:<br />
http://tplinklogin.net<br />
#Entrar com user admin e senha admin<br />
#Configurar a WAN para DHCP (IP dinâmico)<br />
#Configurar a LAN para DHCP na faixa 192.168.0.10 a 192.168.0.100<br />
#Usar uma máquina virtual para testar a aquisição do IP:<br />
pc1[type]=generic<br />
pc1[eth0]=uplink:bridge=eth0<br />
<br />
DESAFIO 1: Elabore um experimento para mostrar que a LAN do AP funciona como um switch.<br />
Sugestão: Use uma máquina adicional colocada em uma porta do AP.<br />
<br />
DESAFIO 2: Elabore um experimento para mostrar como o NAT funciona no AP. Se inspire no experimento realizado sobre o NAT.<br />
<br />
=AULA 18 - Dia 16/05/2019=<br />
<br />
==Objetivos==<br />
<br />
<br />
PARTE 0 - Exercício de Revisão<br />
<br />
PARTE 1 - Serviços de rede sobre o Linux<br />
<br />
*serviço SSH no Linux<br />
<br />
PARTE 2 - Acesso a rede WIFI<br />
<br />
*conceitos básicos de redes sem fio: pg.103 de [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo]<br />
*configuração da WIFI no Access Point e Acesso via Linux<br />
<br />
===PARTE 0===<br />
<br />
Considere a rede abaixo definida pelo arquivo do netkit. Configure as redes com os seguintes prefixos:<br />
<br />
*lan0: 50.50.50.0/24<br />
*lan1: 60.60.60.0/24<br />
*lan2: 70.70.70.0/24<br />
<br />
O pc2dhcp deve ser configurado como servidor DHCP e deverá liberar IPs na faixa de 50.50.50.100/24 a 50.50.50.200/24. Todos os PCs receberão IP estáticos com exceção do PC1 que deverá receber dinamicamente o endereço. Toda a configuração deve ser realizada manualmente.<br />
<br />
Teste a conectividade entre todos os PCs. Usando o tcpdump demonstre que quando PC2 faz um ping em PC4 a entrega será indireta. Demonstre usando o MAC address das máquinas como apoio. Chame o professor para demonstrar.<br />
<br />
ALGUNS COMANDOS NOTÁVEIS:<br />
<br />
ifconfig<br />
ifconfig eth0 10.10.10.1/24<br />
route -n<br />
route add default gw 200.10.1.254<br />
route del -net 200.10.1.0/24 gw 200.10.2.1<br />
route add -net 200.10.1.0/24 gw 200.10.2.1<br />
<br />
tcpdump -i eth1 -n -e<br />
<br />
<code><br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2dhcp[type]=generic<br />
<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=lan0<br />
pc2dhcp[eth0]=lan0<br />
<br />
pc3[eth0]=lan1<br />
<br />
pc4[eth0]=lan2<br />
<br />
r1[eth0]=lan0<br />
r1[eth1]=lan1<br />
<br />
r2[eth0]=lan1<br />
r2[eth1]=lan2<br />
</syntaxhighlight><br />
<br />
Solução:<br />
R1:<br />
ifconfig eth0 50.50.50.254/24<br />
ifconfig eth1 60.60.60.254/24<br />
route add -net 70.70.70.0/254 gw 60.60.60.253<br />
R2:<br />
ifconfig eth1 70.70.70.254/24<br />
ifconfig eth0 60.60.60.253/24<br />
route add -net 50.50.50.0/24 gw 60.60.60.254<br />
PC2DHCP:<br />
ifconfig eth0 50.50.50.2/24<br />
route add default gateway 50.50.50.254<br />
configurar server: nano /etc/dhcp/dhcpd.conf<br />
# A slightly different configuration for an internal subnet.<br />
subnet 50.50.50.0 netmask 255.255.255.0 {<br />
range 50.50.50.100 50.50.50.200;<br />
# option domain-name-servers ns1.internal.example.org;<br />
# option domain-name "internal.example.org";<br />
option routers 50.50.50.254;<br />
option broadcast-address 50.50.50.255;<br />
default-lease-time 600;<br />
max-lease-time 7200;<br />
}<br />
<br />
/usr/sbin/dhcpd -q -4 -pf /run/dhcp-server/dhcpd.pid -cf /etc/dhcp/dhcpd.conf eth0<br />
PC3:<br />
ifconfig eth0 60.60.60.1/24<br />
route add default gw 60.60.60.254 #note que poderia ser para o outro roteador (R2)<br />
PC4:<br />
ifconfig eth0 70.70.70.1/24<br />
route add default gw 70.70.70.254<br />
PC1:<br />
dhclient eth0 -v<br />
<br />
==Serviço SSH==<br />
<br />
O Serviço SSH se utiliza do modelo cliente-servidor. Deve-se executar um servidora ssh na máquina que permitirá o acesso remoto.<br />
Um cliente a partir de uma outra máquina poderá logar remotamente usando um cliente ssh ou poderá fazer outras operações, tipo cópia remota<br />
de arquivos.<br />
<br />
===ETAPA 1 - Rodando o servidor SSH===<br />
*Baseado no Material do Prof.Odilson Valle<br />
<br />
No Ubuntu server:<br />
<ol><br />
<li><br />
<code>sudo su</syntaxhighlight><br />
<code>apt-get update</syntaxhighlight><br />
<code>apt-get install ssh</syntaxhighlight> O SSH já estará funcionando normalmente.<br />
Para configurações extras deve-se editar o arquivo /etc/ssh/sshd_config e acrescentar, por exemplo:<br />
*X11Forwarding yes (no) ### habilita/desabilita acesso com ambiente gráfico remoto<br />
*AllowUsers Fred Wilma ### Libera o acesso somente para os usuários Fred e Wilma<br />
*DenyUsers Dino Pebbles ### Bloqueia o acesso aos usuários Dino e Pebbles e libera para os demais usuários<br />
*AllowGroups admin ### Libera o acesso somente para o grupo admin.<br />
</li><br />
<li><br />
Após modificar o arquivo de configuração deve-se reiniciar o serviço: <code>service ssh restart</syntaxhighlight><br />
</li><br />
<li><br />
Criar um usuário na máquina servidora:<br />
<code>adduser alien</syntaxhighlight><br />
</li><br />
<li><br />
Logar como alien:<br />
<code>su alien</syntaxhighlight><br />
</li><br />
</ol><br />
<br />
===ETAPA 2 - Logando remotamente===<br />
<br />
<ol><br />
<li><br />
Para acessar o servidor basta digitar em um terminal: <br />
<code>ssh alien@ip_do_servidor. </syntaxhighlight> Será solicitado a senha.<br />
</li><br />
<li><br />
Confira que está "dentro" da máquina remota:<code>hostname</syntaxhighlight><br />
</li><br />
<li><br />
Confira os arquivos do diretório corrente:<code>ls -l</syntaxhighlight><br />
</li><br />
</ol><br />
<br />
<br />
===ETAPA 3 - Cópia Remota de aquivos===<br />
<br />
#Na máquina hospedeira/cliente, EM OUTRO TERMINAL, criar um arquivo qualquer usando um editor de texto:<code>gedit teste.txt &</syntaxhighlight><br />
#Envie o arquivo para a máquina servidora: <code>scp teste.txt alien@IP_MAQUINA_SERVIDORA:./</syntaxhighlight><br />
#No terminal onde está logado remotamente confira se o arquivo está copiado: <code>ls -l</syntaxhighlight><br />
#Mude o nome do arquivo: <code>mv teste.txt alfat.txt</syntaxhighlight><br />
#No terminal da máquina cliente traga novamente o arquivo: <code>scp alien@IP_MAQUINA_SERVIDORA:./alfa.txt .</syntaxhighlight><br />
#Confira se o arquivo foi copiado corretamente: <code>ls -l</syntaxhighlight><br />
<br />
==PARTE 2 - Configuração do Access Point na rede de 2.4Ghz==<br />
<br />
#Entrar na configuração do AP conforme aula anterior.<br />
#Conectara a WAN do AP na rede do laboratório e o PC em uma porta da LAN do AP.<br />
#Configurar a WAN para IP dinâmico.<br />
#Configurar a rede WIreless 2.4 Ghz:<br />
##Nome SSID: nome FIC-NomeAluno<br />
##Configurar canal AUTO e channel width para AUTO<br />
##Habilite o broadcast da rede.<br />
#Configurar segurança (Wireless Security) para WPA versão Automática, Criptografia AES e password ABCDEF<br />
#Configurar o DHCP na LAN para distribuir endereços entre 192.168.0.100 e 192.168.0.200<br />
#Salve as configurações<br />
#Reboote o roteador<br />
<br />
==Acessando a rede de dispostivo Celular==<br />
<br />
#Teste o acesso a rede a partir de um celular. No Androi ligue e desligue o wifi. Deve aparecer a lista de dispositivos.<br />
<br />
==Habilitando Filtros por MAC==<br />
<br />
*Na configuração da WLAN entre em Wireless MAC Filtering<br />
*Em Filtering Rules coloque Deny (negar)<br />
*Adicione um terminal que deseja bloquear o acesso. Utilize o MAC do seu celular (veja em configurações do telefone ou anote na opção Wireless Statistics)<br />
*Habilite o Filtro e tente se conectar<br />
<br />
OBS: Este filtro é interessante para ter maior segurança na rede, garantindo que somente dispositivos gabilitados possam acessá-la.<br />
<br />
==Coloque no ar a rede 5Ghz==<br />
<br />
Repita o procedimento da rede de 2.4Ghz e coloque-a no ar.<br />
<br />
Teste a conectividade com o celular.<br />
<br />
<br />
<br />
=AULA 19 - Dia 21/05/2019=<br />
<br />
==Objetivos==<br />
<br />
*Tópicos Adicionais sobre redes no Linux: Configuração Manual X NetworkManager<br />
**Opções de Acesso a Internet: ADSL, Cabo<br />
**Sistema de Arquivos em Rede: Samba Server<br />
*Relatório de Avaliação 1<br />
*Opções de Extensão da Rede Wireless<br />
<br />
==Tópicos Adicionais sobre redes no Linux==<br />
<br />
===Configuração da Rede no Linux - o NetworkManager===<br />
<br />
Ao longo do curso estudamos vários comandos para ver e modificar parâmetros de rede. Entretanto, em uma instalação padrão de um sistema Linux Ubuntu vamos verificar que existe um serviço de suporte a estas configurações que permite configurar interfaces graficamente e reconectar/escolher uma rede. Trata-se do NetworkManager. Ver alguns detalhes aqui [https://www.hardware.com.br/dicas/entendendo-networkmanager.html] e aqui[https://wiki.debian.org/pt_BR/NetworkManager]. Este serviço tenta fornecer a melhor conectividade possível usando as interfaces disponíveis. O serviço é composto por:<br />
<br />
*um processo do sistema (roda como serviço) monitorando constantemente as interfaces;<br />
*uma applet para interação com o usuário (canto direito da interface);<br />
<br />
O NetworkManager vai ignorar as configurações das interfaces realizadas em /etc/network/interfaces<br />
<br />
Teste o uso do NetworkManager. Clique no topo do desktop a direita e inspecione as interfaces disponíveis.<br />
<br />
Em algumas situações pode ser desejável desabilitar o NetworkManager. Na linha de comando pode ser executado:<br />
<br />
sudo service network-manager stop<br />
<br />
===Configurando interfaces de forma manual ===<br />
<br />
TEXTO baseado nas anotações do Prog.Marcelo Sobral:<br />
<br />
O arquivo ''/etc/network/interfaces'' contém declarações para configurar as interfaces de rede. Um exemplo de configuração básica contida nesse arquivo pode ser vista a seguir:<br />
<br />
<syntaxhighlight lang=text><br />
auto lo eth0<br />
iface lo inet loopback<br />
iface eth0 inet dhcp<br />
</syntaxhighlight><br />
<br />
Esse exemplo pode ser interpretado assim:<br />
* ''Linha 1'': declara que as interfaces ''lo'' e ''eth0'' devem ser ativadas automaticamente no boot. Se uma interface não aparecer em uma declaração como esta, então ela não será ativada. OBS: interface ativadas desta forma NÃO são controladas pelo ''NetworkManager''.<br />
* ''Linha 2'': configura a interface ''lo'' como sendo do tiupo ''loopback''. Essa é uma interface especial criada puramente em software (uma interface de rede virtual), usada para comunicação entre processos de um mesmo computador.<br />
* ''Linha 3'': configura a interface ''eth0'' de forma dinâmica usando [[GER-2010-1#DHCP|DHCP]]. A configuração de rede é solicitada usando a própria rede. Ness ecaso, deve existir algum equipamento ou computador nessa rede que seja um servidor DHCP, capaz de responder com uma mensagem contendo a configuração de rede a ser utilizada.<br />
<br />
<br />
O exemplo anterior é bastante simplificado, uma vez que a configuração de rede de fato é obtida dinamicamente com DHCP. Isso pode ser suficiente para computadores usados somente para acesso a Internet, mas não para computadores que sejam servidores. Nesse caso, é melhor definir uma configuração de rede estática, como mostrado a seguir:<br />
<br />
<syntaxhighlight lang=text><br />
auto lo eth0<br />
iface lo inet loopback<br />
iface eth0 inet static<br />
address 172.18.80.251<br />
netmask 255.255.128.0<br />
gateway 172.18.0.254<br />
dns-nameservers 191.36.8.2 191.36.8.3<br />
</syntaxhighlight><br />
<br />
<br />
A diferença em relação ao caso anterior está na declaração da interface ''eth0''. Ao invés de configurá-la com ''DHCP'', declararam-se todas as informações de rede. Assim, essa interface sempre será ativada com essas informações configuradas. No exemplo apresentado, as configurações de rede são:<br />
* ''address 172.18.80.251'': endereço IP da interface<br />
* ''netmask 255.255.128.0'': máscara de rede<br />
* ''gateway 172.18.0.254'': endereço do gateway (ou roteador ''default'')<br />
* ''dns-nameservers 191.36.8.2 191.36.8.3'': servidores DNS a serem utilizados (podem-se especificar um ou mais endereços IP)<br />
<br />
O [http://manpages.ubuntu.com/manpages/trusty/en/man5/interfaces.5.html manual do arquivo /etc/network/interfaces] apresenta muitos outros detalhes sobre possíveis configurações de rede.<br />
<br />
Antes da alteração de configuração de uma interface é interessante desativá-la:<br />
ifdown eth0<br />
Alterar o arquivo /etc/network/interfaces<br />
<br />
E na sequência ativá-la novamente:<br />
ifup eth0<br />
ou<br />
sudo /etc/init.d/networking restart<br />
<br />
O comando ifup vai consultar o arquivo e alterar as configurações. Indiretamente, o script networking também usa o ifup para ativar as configurações (e todas demais que forem realizadas).<br />
<br />
==Relatório Avaliativo 1==<br />
<br />
Criar um arquivo no OpenOffice nomeando-o SeuNomeSemEspaco-FICLinux-2019-A1<br />
<br />
Copiar e responder as questões abaixo:<br />
<br />
1.Faça um ifconfig na interface eth0. Cole um recorte da tela no espaço abaixo e faça um texto indicando qual o endereço de hardware associado a esta interface, qual o endereço IPv4 e qual a máscara de subrede.<br />
<br />
<br />
2.Faça um experimento usando o ping e o wireshark mostrando como o DNS atua para resolver o nome que está sendo "pingando". Informe em texto abaixo qual o IP do servidor DNS local e qual o IP do site que está sendo "pingado".<br />
<br />
<br />
3,Execute o laboratório do Netkit da forma e cole abaixo a figura da rede fornecida pelo netkit:<br />
<code><br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
<br />
# Hosts' interfaces to local routers<br />
<br />
r1[eth0]=lan0<br />
r1[eth1]=lan1<br />
<br />
pc1[eth0]=lan0<br />
pc2[eth0]=lan0<br />
pc3[eth0]=lan1<br />
</syntaxhighlight><br />
<br />
<br />
4.Configure todas as interfaces dos PC usando para lan0 o prefixo 50.50.50.0/24 e para lan1 use no lugar de 50 o dia de seu nascimento.<br />
Cole uma tela mostrando PC1 pingando PC3. <br />
<br />
5.Informe abaixo o MAC da eth0 do roteador.<br />
<br />
6.Usando o tcpdump na eth0 do roteador mostre que a entrega é indireta.<br />
<br />
==Estendendo a rede através da LAN usando segundo AP e WAN==<br />
<br />
Conecte um segundo AP (WAN do segundo AP a LAN do primeiro AP). Teste a conectividade colocando uma máquina Linux na LAN do segundo AP.<br />
Esta configuração deve funcionar mas impõe um overhead adicional devido ao NAT realizado duas vezes... <br />
<br />
DESAFIO: mostrar que o NAT está sendo duplicado.<br />
<br />
[[Arquivo:WLAN-2PAs-viaWAN.png]]<br />
<br />
==Estendendo a rede através da LAN usando segundo AP e LAN==<br />
<br />
Discuta com o colega ao lado e pense como poderia conectar o segundo AP via LAN. Uma configuração adicional será necessária.<br />
<br />
==Estendendo a rede através do Wireless (WDS)==<br />
<br />
Estude no manual como poderia estender a rede Sem Fio usando conexão via WDS.<br />
<br />
=AULA 20 - Dia 18/04/2019=<br />
<br />
*Tópicos Adicionais sobre redes no Linux:<br />
**Opções de Acesso a Internet: ADSL, Cabo<br />
**Sistema de Arquivos em Rede: Samba Server (http://www.guiafoca.org/cgs/guia/avancado/ch-s-samba.html)<br />
*Relatório Avaliativo 2<br />
<br />
==Relatório Avaliativo==<br />
<br />
===PARTE 1=== <br />
<br />
Usando a configuração abaixo do netkit2 e uma máquina Virtualbox devidamente configurada implementar a configuração abaixo:<br />
<br />
ATENÇÂO: Vamos substituir a VirtualBox por uma máquina Netkit executada em OUTRO PC com a configuração:<br />
<br />
INSTRUÇÔES para virtual box:<br />
*colocar rede como bridge<br />
*desabilitar o network manager<br />
sudo service network-manager stop<br />
*baixar a interface<br />
sudo ifconfig enp0s3 down<br />
*reconfigurar a interface (usar o endereço do seu grupo)<br />
sudo ifconfig enp0s3 50.50.50.11/24<br />
*colocar a rota direta (que se perdeu) (usar o endereço do seu grupo)<br />
sudo route add -net 50.50.50.0/24 dev enp0s3<br />
*colocar gateway default (usar o endereço do seu grupo)<br />
sudo route add default gateway 50.50.50.1<br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
<br />
pc1[type]=generic<br />
pc1[eth0]=uplink:bridge=eth0:ip=dhcp<br />
<br />
</syntaxhighlight><br />
<br />
<br />
[[Arquivo:Aval2-Parte1-FICLinux2019-2.png]]<br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
pc1[type]=generic<br />
<br />
pc1[eth0]=lan1<br />
<br />
r1[eth0]=uplink:bridge=eth0:ip=VER COM PROFESSOR<br />
r1[eth1]=lan2<br />
<br />
r2[eth0]=lan1<br />
r2[eth1]=lan2<br />
</syntaxhighlight><br />
<br />
Construir um doc conforme aula anterior com as seguintes informações:<br />
<br />
#Coloque a tela de um píng funcionando de R1 para PC1<br />
#Cole a tela da tabela de roteamento de R2<br />
#Cole a tela de um ping de uma máquina VirtualBox (netkit) no R1 (uplink)<br />
#Cole a tela de um ping funcionando uma máquina VirtualBox (netkit) no PC1<br />
<br />
Note que o gateway default da máquina virtual deverá ser reconfigurado para PC1.<br />
<br />
ADENDO: Coloque em R1 rotas para as redes dos PC1 dos demais grupos.<br />
<br />
===PARTE 2===<br />
<br />
Acrescente na sua rede um AP configurado como indicado abaixo:<br />
<br />
OBS: Para este exercício configuramos estaticamente todos os endereços para o lado do backbone (Laboratório). Usamos 50.50.50.0/24<br />
<br />
[[Arquivo:Aval2-Parte2-FICLinux2019-2.png]]<br />
<br />
<br />
=ATIVIDADE DE RECUPERAÇÃO 1=<br />
<br />
Refazer o relatório Avaliativo 1 proposto anteriormente. Enviar doc para o SIGA A<br />
<br />
=ATIVIDADE DE RECUPERAÇÃO 2=<br />
<br />
Registre em um DOC e faça um post no SIGA A colando a imagem das telas das saídas de cada comando!<br />
<br />
===Roteiro de atividades sobre o IPv6===<br />
<br />
A figura abaixo apresenta o diagrama esquemático da rede a ser montada/analisada. Observe que todos os IPv6 ''Global Unicast'' já estão definidos na mesma, são esses IPs que utilizaremos em nosso experimento.<br />
<br />
[[Arquivo:Diagrama_rede_IPv6.jpg]]<br />
<br />
#Crie em seu computador um arquivo com nome '''/home/aluno/IPv6.conf''', com o seguinte conteúdo: <syntaxhighlight lang=bash><br />
#Ligacao das maquinas nos dominios de colisao<br />
#Duas pequenas redes interligadas pelo backbone<br />
<br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=link0:ipv6=2001:bcc:faca:1::101/64<br />
pc2[eth0]=link1:ipv6=2001:bcc:cafe:1::102/64<br />
pc3[eth0]=HUB1:ipv6=2001:bcc:1f0:1::103/64<br />
pc4[eth0]=HUB1<br />
<br />
#Default Gateways definitions<br />
pc1[route]=default6:gateway=2001:bcc:faca:1::1<br />
pc2[route]=default6:gateway=2001:bcc:cafe:1::1<br />
pc3[route]=default6:gateway=2001:bcc:1f0:1::1<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
#Routers interfaces definitions<br />
r1[eth0]=backbone0:ipv6=2001:db8:dead:1::1/64<br />
r1[eth1]=link0:ipv6=2001:bcc:faca:1::1/64<br />
r1[eth2]=link1:ipv6=2001:bcc:cafe:1::1/64<br />
<br />
r2[eth0]=backbone0:ipv6=2001:db8:dead:1::2/64<br />
r2[eth1]=HUB1:ipv6=2001:bcc:1f0:1::1/64<br />
<br />
#Routers definitions<br />
r1[route]=2001:bcc:1f0:1::0/64:gateway=2001:db8:dead:1::2<br />
r2[route]=2001:bcc:faca:1::0/64:gateway=2001:db8:dead:1::1<br />
r2[route]=2001:bcc:cafe:1::0/64:gateway=2001:db8:dead:1::1<br />
</syntaxhighlight><br />
#Tenha certeza que o Netkit2 estja atualizado: General >> Update.<br />
#Rode o NetKit em seu computador. Em um terminal digite: <syntaxhighlight lang=bash><br />
netkit2 & </syntaxhighlight><br />
#No menu '''File''' - '''Load and Run''', procure o arquivo '''/home/aluno/IPv6.conf''' e clique em OK. Abrirá uma janela com 6 abas, onde cada uma delas é um terminal de configuração do respectivo equipamento: '''pc1-4''' ou '''r1-2'''.<br />
#Observe que o '''pc4''' não está com sua interface configurada.<br />
#Ao clicar no menu '''File''' - '''Graph''', pode-se ter uma visão da rede a ser simulada e conferir se é equivalente ao diagrama proposto.<br />
#Faça um '''ping6''' entre o '''pc1''' ao '''pc3''': <syntaxhighlight lang=bash><br />
ping6 -c4 2001:bcc:1f0:1::103 </syntaxhighlight><br />
#Faça um '''ping6''' entre o '''pc1''' e '''pc2'''.<br />
#No '''pc4''' use o seguinte comando para adicionar o endereço IPv6 à interface de rede: <syntaxhighlight lang=bash><br />
ip addr add 2001:bcc:1f0:1::104/64 dev eth0 </syntaxhighlight><br />
#No '''pc4''', acrescente o ''default gateway'' com o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add default via 2001:bcc:1f0:1::1 dev eth0 </syntaxhighlight><br />
#No '''pc1''' use o seguinte comando para verificar como ficou a configuração dos endereços da interface de rede. O resultado é similar ao apresentado pelo comando '''ifconfig''': <syntaxhighlight lang=bash><br />
ip addr show dev eth0 </syntaxhighlight><br />
#Todo o roteamento está pronto, mas caso desejássemos poderíamos acrescentar rotas com comando similares aos já utilizados. Por exemplo, no '''r1''', para adicionar uma rota estática para a rede dos '''pc3''' e '''pc4''' utilizaríamos o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add 2001:bcc:1f0:1::/64 via 2001:db8:dead:1::2 dev eth0 </syntaxhighlight><br />
#Confira as rotas estabelecidas em todos os ''hosts'' com o comando abaixo. <br />
##São coerentes com os dados apresentados no diagrama acima?<syntaxhighlight lang=bash><br />
ip -6 route show </syntaxhighlight><br />
#No '''pc1''' use os seguintes comandos para ver a rota para alguns vizinhos: <syntaxhighlight lang=bash><br />
traceroute6 2001:bcc:1f0:1::103<br />
traceroute6 2001:bcc:1f0:1::104 </syntaxhighlight><br />
#*Anote as rotas.<br />
#Deixe um '''ping6''' entre o '''pc1''' ao '''pc3''' rodando: <syntaxhighlight lang=bash><br />
ping6 2001:bcc:1f0:1::103 </syntaxhighlight><br />
<br />
=ATIVIDADE DE RECUPERAÇÃO 3=<br />
<br />
Registre em um DOC e faça um post no SIGA A colando a imagem das telas das saídas de cada comando! Coloque também a resposta as perguntas.<br />
<br />
===Objetivos===<br />
<br />
*Familiarizar-se com o UDP<br />
*Entender a estrutura do pacote UDP<br />
*Entender o conceito de portas<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/UDP%20Basico.pdf Introdução a camada de transporte e UDP básico]<br />
<br />
===Parte 1 - Fluxo único UDP===<br />
<br />
#Combinar equipes com dois computadores para execução do experimento.<br />
#*Uma equipe escutará na porta 5000 e a outra equipe transmitirá uma mensagem nessa porta. Os processos de transmissão e recepção podem ocorrer simultaneamente, em terminais distintos.<br />
#*Cada equipe deve identificar os IPs ('''IP_DEST''') das máquinas de seus pares.<br />
#Cada equipe deve abrir uma Janela de terminal.<br />
#Cada equipe deve preparar o '''Wireshark''', interfaces '''any''', para escuta das portas no protocolo UDP usando um filtro:<syntaxhighlight lang=bash><br />
udp.port==5000</syntaxhighlight><br />
#A equipe da escuta na porta 5000 executa no terminal: <syntaxhighlight lang=bash><br />
netcat -u -l -p 5000 </syntaxhighlight><br />
#A equipe que irá transmitir para a porta 5000 executa no terminal: <syntaxhighlight lang=bash><br />
netcat -u IP_DEST 5000 </syntaxhighlight><br />
#*Em seguida escreve no terminal uma mensagem de até 20 caracteres, ao teclar <Enter> a mensagem será enviada.<br />
#*O wireshark deve ter capturado os pacotes UDP <br />
#Identifique e anote os seguintes dados na captura do wireshark:<br />
#*IP FONTE e DESTINO<br />
#*PORTAS FONTE E DESTINO para ambas comunicações<br />
#*Campo de protocolo no pacote IP<br />
#*Campo de tamanho (anote o tamanho) e ''checksum'' no pacote (datagrama) UDP<br />
#*O campo de dados no pacote UDP<br />
#Troquem os papéis das equipes: quem houvia agora transmite mensagens.<br />
#Cada equipe pode transmitir sequencialmente várias mensagens, devendo identificar múltiplos datagramas UDP.<br />
#PERGUNTAS baseadas na captura:<br />
##Qual o tamanho de cada campo do cabeçalho do pacote UDP?<br />
##Qual o tamanho máximo do número de porta?<br />
##Qual o tamanho máximo da área de dados (payload) do pacote?<br />
##Qual o número identificador de protocolo UDP no pacote IP? <br />
##Em algum momento foi identificado algum procedimento para estabelecimento de conexão? <br />
##Em algum campo do UDP existe numeração de mensagens?<br />
<br />
=AULA 20 - Dia 18/04/2019=<br />
<br />
{{collapse bottom}}<br />
<br />
==Curso FIC Linux 2018==<br />
<br />
{{collapse top|Semestre 2018-2 - Prof. André D'Amato}}<br />
<br />
== Introdução ao Sistema Operacional Linux ==<br />
<br />
'''10/09/18: Aula01'''<br />
<br />
Apresentação da Disciplina, Introdução a Informática e Memória e Armazenamento<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula01.pdf Aula 01]<br />
<br />
{{collapse bottom}}<br />
<br />
==Curso FIC Linux 2016==<br />
<br />
{{collapse top|Semestre 2016-2 - Prof. Luciano Barreto}}<br />
<br />
== Introdução ao Sistema Operacional Linux ==<br />
<br />
'''04/10/16: Aula01'''<br />
<br />
Apresentação da Disciplina, Introdução a Informática e Memória e Armazenamento<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula01.pdf Aula 01]<br />
<br />
'''06/10/16: Aula 02'''<br />
<br />
Introdução ao Linux, Sistema de Arquivos e Conhecendo o Terminal<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula02.pdf Aula 02]<br />
<br />
''' 11/10/2016: Aula 03'''<br />
<br />
Continuação Comandos no Terminal<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula03.pdf Aula 03]<br />
<br />
''' 13/10/2016: Aula 04''' <br />
<br />
Continuação Comandos no Terminal<br />
<br />
''' 18/10/2016: Aula 05''' <br />
<br />
Lista de Exercícios<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/ficlinux-aula05-exercicios.pdf Aula 05 - Lista de Exercícios]<br />
<br />
''' 20/10/2016: Aula 06'''<br />
<br />
Introdução ao Gerenciamento de Processos<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula06-processos.pdf Aula 06 - Gerenciamento de Processos]<br />
<br />
''' 25/10/2016: Aula 07''' <br />
<br />
Gerenciamento de Usuários<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula07-usuariosgrupos.pdf Aula 07 - Gerenciamento de Usuários]<br />
<br />
Permissionamento<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula07-permissionamento.pdf Aula 07 - Permissionamento]<br />
<br />
''' 27/10/2016: Aula 08'''<br />
<br />
Continuação Permissionamento<br />
<br />
Instalação Linux<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula8-instalacao.pdf Aula 08 - Instalação Linux] <br />
<br />
''' 01/11/2016: Aula 09'''<br />
<br />
Continuação Instalação Linux<br />
<br />
Instalação de Pacotes via Apt<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula9-pacotes.pdf Aula 09 - Instalação Pacotes] <br />
<br />
''' 03/11/2016: Aula 10'''<br />
Continuação Lista Exercícios (47 - 60)<br />
<br />
=AULA 11 - Dia 18/04/2019=<br />
<br />
=AULA 12 - Dia 18/04/2019=<br />
<br />
=AULA 13 - Dia 18/04/2019=<br />
<br />
=AULA 14 - Dia 18/04/2019=<br />
<br />
=AULA 15 - Dia 18/04/2019=<br />
<br />
=AULA 16 - Dia 18/04/2019=<br />
<br />
=AULA 17 - Dia 18/04/2019=<br />
<br />
=AULA 18 - Dia 18/04/2019=<br />
<br />
=AULA 19 - Dia 18/04/2019=<br />
<br />
=AULA 20 - Dia 18/04/2019=<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top|Semestre 2016-1 - Prof. Luciano Barreto}}<br />
<br />
= Diário de Aulas 2016 - 1 =<br />
<br />
==29/03/16: Apresentação do curso==<br />
Apresentação do curso, Visão geral de funções, responsabilidades e estruturas de um SO.<br />
<br />
==31/03/16: Introdução a Sistema de Arquivos e Terminal==<br />
Estrutura do Sistema de Arquivos Linux, Introdução a comandos no Terminal.<br />
<br />
==04/04/16: Continuação Terminal==<br />
Continuação de comandos no terminal, redirecionamento de saída e caracteres coringa.<br />
<br />
==07/04/16: Introdução a Processos e Usuários==<br />
Conhecendo Processos e Gerenciamento de usuários<br />
<br />
==12/04/16: Lista de Exercícios de Comandos no Terminal==<br />
<br />
[http://bellard.org/jslinux/ Emulador de Terminal no navegador (demora um pouquinho pra abrir)]<br />
<br />
==14/04/16: Usuários, Grupos e Permissões==<br />
Administração de usuários, grupos e adicionando permissões a arquivos.<br />
<br />
==19/04/16: Instalação do Linux==<br />
Instalação do Sistema Linux em modo texto, gráfico e dualboot.<br />
<br />
==26/04/16: Introdução ao Shell Script==<br />
Introdução ao Shell Script<br />
<br />
==28/04/16: Continuação ao Shell Script==<br />
Introdução ao Shell Script<br />
<br />
==03/05/16: Lista de Exercícios==<br />
Lista de Exercícios até a aula de 28/04/16<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top|Semestre 2015-2}}<br />
<br />
*'''Professores:''' [[Ana Paula Rosa Negri]] e [[Francisco de Assis Souza dos Santos]]<br />
<br />
{| style="background-color:#ABCDEF; font-family:verdana,Arial, Helvetica, sans-serif; font-size:100%; margin:0; border: 1px solid #C7D0F8; padding:7px 7px 0px 7px; text-align:center;" width="100%"<br />
| | Bem-vindo ao<br /><br />
<span style="font-size:200%">'''Curso de Formação Continuada de Configuração de Redes de Computadores Linux''' <br />do Instituto Federal de Santa Catarina - Campus São José</span><br />
|}<br />
<br />
Introdução ao Sistema Operacional Linux<br />
<br />
*'''Professores:''' [[Ana Paula Rosa Negri]] e [[Francisco de Assis Souza dos Santos]]<br />
*'''Encontros:''' Terças e quintas das 19:00 às 22:00 no Laboratório de Apoio ao Ensino.<br />
<br />
*[[ISL-FicLinux_(Plano_de_Ensino)| Plano de Ensino]]<br />
*[[Cronograma de atividades (ISL-FicLinux) | Cronograma]]<br />
<br />
= Diário de Aulas 2015 =<br />
== 13/10 ==<br />
'''Parte 1:'''<br />
Slides da aula:<br />
[[Arquivo:introducao.pdf]]<br />
<br>Exercício sobre taxa de transferência:<br />
[[Arquivo:Exercicio_taxa_Transferencia.pdf]]<br />
<br><br />
<br />
'''Parte 2:'''<br />
Slides da Aula:<br />
[[Arquivo:LinuxModoTexto.pdf]]<br />
<br>Exercícios sobre comandos básicos do Linux:<br />
[[Arquivo:ExercícioLinuxTexto.pdf]]<br />
<br />
== 15/10 ==<br />
'''Parte 3:'''<br />
Slides da Aula:<br />
[[Arquivo:Parte3.pdf]]<br />
== 20/10 ==<br />
'''Parte 4:'''<br />
Slides caracteres coringas: [[Arquivo:Coringas.pdf]]<br />
<br />
Exercícios caracteres coringas: [[Arquivo:Exercício CB03 Pokemon.pdf]]<br />
<br />
'''Parte 5:'''<br />
Sildes Redirecionamento: [[Arquivo: Redirecionamento.pdf]]<br />
<br />
Exercícios redirecionamento e pipe: [[Arquivo: ex_pipe.pdf]]<br />
<br />
== 22/10 ==<br />
'''Parte 6:'''<br />
Slides Processos: [[Arquivo:FICLinux_Processos.pdf]]<br />
<br />
== 27/10 ==<br />
'''Parte 7:''''<br />
Slides Usuários e Grupos: [[Arquivo:UserGroup.pdf]]<br />
<br>Exercícios: [[Arquivo:usuarios.pdf]]<br />
<br>Exercícios (.odt): [[Arquivo:usuarios.odt]]<br />
<br />
== 29/10 ==<br />
'''Parte 8:'''<br />
Slides Introducao a Redes: [[Arquivo:FICLinux_Introducao_Redes.pdf]]<br />
<br />
== 03/11 ==<br />
<br />
'''Parte 9:'''<br />
Slides permissionamento: [[Arquivo:permissionamento.odp]]<br><br />
Exercícios permissionamento: [[Arquivo: Exercício Perm02.odt]]<br><br />
Outro exercício permissionamento: [[Arquivo: Exercício Perm04 GatosRatosCães.odt]]<br />
<br />
== 05/11 ==<br />
<br />
'''Parte 10:'''<br />
Slides Redes - Broadcast: [[Arquivo:FICLinux_Introducao_Redes_Broadcast_01.pdf]]<br><br />
<br />
== 10/11 ==<br />
<br />
'''Parte 11:'''<br />
Slides Script: [[Arquivo:Scripts do Linux.odp]]<br />
<br>Exercícios Scripts: [[Arquivo:Exercício Scripts01 pdfmerger.odt]]<br />
<br />
== 12/11 ==<br />
<br />
'''Parte 12:'''<br />
Introdução para comandos em Bash: [[Arquivo:Introdução ao Shell_2015_1.pdf]]<br />
<br />
{{collapse bottom}}</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=ISL-FicLinux_(p%C3%A1gina)&diff=162000ISL-FicLinux (página)2019-10-03T19:34:45Z<p>127.0.0.1: /* Curso FIC Linux 2019 */</p>
<hr />
<div>__NOTOC__<br />
= Introdução ao Sistema Operacional Linux / Redes com Linux =<br />
<br />
*'''Encontros:''' Terças e Quintas das 19:00 às 22:00.<br />
*'''Local:''' Laboratório de Redes de Computadores (Redes 1).<br />
<br />
*[[ISL-FicLinux_(Plano_de_Ensino)| Plano de Ensino]]<br />
<br />
==Curso FIC Linux 2019==<br />
<br />
{{collapse top | Semestre 2019-2 - Prof. Eraldo Silveira e Silva}}<br />
<br />
==Cronograma Tentativa==<br />
<br />
Horários: 19h às 22h.<br />
<br />
{| class="wikitable"|<br />
| AULA || DATA || Professor || Conteúdo<br />
|-<br />
| 1 || 27/09/2019 || ERALDO || Programa da Disciplina.Forma de Avaliação. O computador: hardware e software. SO Linux: histórico e distribuições. Ligando/Logando/Desligando a Máquina. Conceitos básico de Sistema de Arquivos e Processos.<br />
|-<br />
| 2 || 29/09/2019 || ERALDO || Gerenciamento de Arquivos I: Operações sobre arquivos e diretórios usando o terminale o Nautilus.<br />
|-<br />
| 3 || 3/09/2019 || ERALDO || Gerenciamento de Arquivos II: continuação Operações sobre arquivos e diretórios. Links Simbólicos, Criação de Arquivo com vi e outros editores.<br />
|-<br />
| 4 || 5/09/2019 || ERALDO || Interfaces Gráficas: X11, Gnome. KDE e outras. Instalação de Programas via Gerenciador de Pacotes.<br />
|-<br />
| 5 || 10/09/2019 || ERALDO || Administração de contas de usuários I<br />
|-<br />
| 6 || 12/09/2019 || ERALDO || Administração de contas de usuários II<br />
|-<br />
| 7 || 17/09/2019 || ERALDO || Permissionamento de Arquivos<br />
|-<br />
| 8 || 19/09/2019 || ERALDO || Gerenciamento de Processos<br />
|-<br />
| 9 || 24/09/2019 || ERALDO || Introdução ao Shell Script<br />
|-<br />
| 10 || 26/09/2019 || ERALDO || Introdução ao Shell Script<br />
|-<br />
| 11 || 1/10/2019 || ERALDO || Introdução a Redes. Conceito de Protocolos. Ferramentas de Rede.<br />
|-<br />
| 12 || 3/10/2019 || ERALDO || Protocolos de Aplicação: exemplo http <br />
|-<br />
| 13 || 8/10/2019 || ERALDO || O DNS como protocolo de Aplicação; Camada de Transporte: protocolo UDP <br />
|-<br />
| 14 || 10/10/2019 || ERALDO || Protocolo TCP. Diferenças dos protocolos de Transporte TCP/UDP. Camada IP e aspectos da configuração da mesma sob o Linux<br />
|-<br />
| 15 || 15/10/2019 || ERALDO || Camada de Enlace/Física. Hubs X Switches. O Papel do Protocolo ARP. Outros serviços/protocolos: Serviço DHCP e NAT<br />
|-<br />
| 16 || 17/10/2019 || ERALDO|| Segmentação Redes IP. Cálculo de subredes. <br />
|-<br />
| 17 || 22/10/2019 || ERALDO || Introdução ao IPV6. Introdução ao Access Point TPLINK N750: configuração da LAN e WAN<br />
|-<br />
| 18 || 24/10/2019 || ERALDO || Serviço SSH no Linux. Acesso a rede WIFI. Conceitos básicos de redes sem fio.<br />
|-<br />
| 19 || 29/10/2009 || ERALDO || Tópicos Adicionais sobre redes no Linux: Configuração Manual X NetworkManager. Relatório Avaliativo 1.<br />
|-<br />
| 20 || 31/10/2019 || ERALDO || Relatório Avaliativo 2<br />
|}<br />
<br />
=Curso FIC Linux 2019-2=<br />
<br />
==Professor==<br />
<br />
:*Prof. [[Eraldo Silveira e Silva]]<br />
:*email: eraldo@ifsc.edu.br<br />
:*sala: Sala de I de Professores da Área de Telecomunicações (primeira sala lado da Biblioteca - direção esquerda)<br />
<br />
=27/08/2019=<br />
<br />
==Objetivos==<br />
<br />
===Parte 1===<br />
<br />
*Apresentar o IFSC: estrutura, câmpus e serviços<br />
*Apresentar o curso: perfil do egresso, competências gerais, áreas de atuação do egresso e conteúdos previstos<br />
*Apresentar o Cronograma Tentativa (ver SIGA A)<br />
*Apresentar metodologia e forma de avaliação<br />
<br />
===Parte 2===<br />
<br />
*Conceitos de Hardware, Software e Firmware<br />
*Arquiteturas de processadores<br />
*Classificação de softwares<br />
*Conceitos de Sistemas Operacionais e exemplos<br />
<br />
===Parte 3===<br />
<br />
*Histórico do Linux<br />
*Linux e GNU/Linux<br />
*Instalando o Linux<br />
*Arquitetura do Linux<br />
*Distribuições<br />
*Distribuições usadas no IFSC/SJ<br />
*Ligando e Desligando o Sistema<br />
*Primeiros contatos.<br />
<br />
==Professores do FIC Linux Edição 2019-2==<br />
<br />
*Prof. [[Eraldo Silveira e Silva]] (Introdução ao Linux e Redes com Linux)<br />
<br />
==Apresentação do IFSC==<br />
<br />
*[http://www.ifsc.edu.br/estrutura-organizacional-inicio Página do IFSC]<br />
*[https://www.sj.ifsc.edu.br/index.php Página do Câmpus]<br />
<br />
==Apresentação do Curso==<br />
<br />
*[[ISL-FicLinux_(Plano_de_Ensino) | Introdução ao Linux]]<br />
*[https://wiki.sj.ifsc.edu.br/index.php/PRL-FicLinux_(Plano_de_Ensino) Projeto de Rede Residencial com o Linux]<br />
*[[Curso_de_Formação_Continuada_de_Configuração_de_Redes_de_Computadores_Linux | PPC do Curso e Outras Regulamentações]]<br />
<br />
==Cronograma Tentativa==<br />
<br />
Horários: 19h às 22h.<br />
<br />
VER SIGA A [https://sig.ifsc.edu.br/sigaa/verTelaLogin.do]<br />
<br />
==Metodologia, Avaliação e Critérios de Aprovação==<br />
<br />
*Aulas expositivas e aulas práticas no laboratório. Nas aulas práticas serão desenvolvidos exercícios e trabalhos individuais.<br />
*Avaliações individuais: Listas de exercícios com aproveitamento e entregues no prazo. <br />
*Critérios para aprovação: Serão considerados aprovados os alunos que obtiverem conceito final 6 ou superior em cada componente curricular. ATENÇÃO: Possuir no mínimo 75% de presença<br />
<br />
==Bibliografia==<br />
<br />
#Odilson Tadeu Valle<br />
##Administração de redes com Linux: fundamentos e práticas<br />
##Editora IFSC, 2010<br />
#Gleydson Mazioli da Silva<br />
##Guia Foca Linux<br />
##http://www.guiafoca.org/<br />
#Luiz Carlos Lobato Lobo de Medeiros e Wendel Soares<br />
##Formação de suporte técnico PROINFO<br />
##https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo<br />
#Ari Frazão Jr e Marcelo Braga<br />
##Administração de Sistemas Linux<br />
##https://pt.scribd.com/doc/128912228/Administracao-de-Sistemas-Linux<br />
<br />
==Conceitos de Hardware, Software e Firmware==<br />
<br />
*Em informática, o hardware consiste nos equipamentos<br />
**Ex: Computador, teclado, mouse, monitor<br />
*Software é um aplicativo, desenvolvido em uma linguagem de programação<br />
**Ex: Windows, Linux, Mozilla Firefox, Google Chrome<br />
*Firmware é um conjunto de instruções básicas e específicas para um hardware<br />
**Ex: BIOS nos computadores, sistemas de controle das máquinas de lavar, etc.<br />
<br />
==Estrutura de um Computador e Arquitetura de Processadores==<br />
<br />
*Material de Referência: https://www.dropbox.com/s/fn3l9os4l7gh9o5/AULA%201.odp?dl=0<br />
<br />
===Outros Links Interessantes===<br />
<br />
*Bits, [https://pt.wikipedia.org/wiki/Byte Bytes] e tamanho de memória;<br />
*Representação de Caracteres: [https://pt.wikipedia.org/wiki/ASCII Tabela ASCII];<br />
*O [https://pt.wikipedia.org/wiki/Microprocessador microprocessador], barramentos e memórias semicondutoras: RAM,ROM, E2PROM, FLASH;<br />
*Memórias cache e memórias secundárias;<br />
*[https://pt.wikipedia.org/wiki/Mem%C3%B3ria_virtual Memória Virtual] e Swapping;<br />
*Registradores de 32bits ou 64bits<br />
*Arquitetura [https://pt.wikipedia.org/wiki/X86 x86] / [https://pt.wikipedia.org/wiki/AMD64 x86-64] – presente nos computadores pessoais<br />
*Arquitetura ARM – presente em sistemas embarcados e dispositivos móveis<br />
*Múltiplos núcleos (core)<br />
*Máquinas Virtuas: VirtualBox, UML (User Mode Linux).<br />
<br />
==O papel do Sistema Operacional==<br />
<br />
*O [https://pt.wikipedia.org/wiki/Sistema_operativo SO] é um programa (software) que controla a máquina e a torna utilizável para o usuário;<br />
*Abstrações do Sistema: arquivos e processos;<br />
*Pode ser multitarefa e multiusuário;<br />
*[https://en.wikipedia.org/wiki/Device_driver Driver] de dispositivo<br />
*[https://pt.wikipedia.org/wiki/Multi_boot Múltiplos OS instalados] em um computador. É possível??<br />
<br />
==Sistema de Arquivos==<br />
<br />
*Forma como estão estruturados/organizados os arquivos/dados em uma determinada mídia [https://pt.wikipedia.org/wiki/Sistema_de_ficheiros];<br />
*Um sistema operacional deve saber como acessar e operar sobre este sistema;<br />
*Tipos de sistemas: ext4, NTFS, VFAT32<br />
<br />
==Exemplos de SO==<br />
<br />
*Unix<br />
*Microsoft DOS<br />
*IBM<br />
*Microsoft Windows<br />
*netBSD, freeBSD, openBSD<br />
*Linux<br />
*macOS<br />
*Android<br />
*iOS<br />
<br />
==Histórico do Linux==<br />
<br />
*O início de tudo: UNIX;<br />
*Surgiu em 1991 quando Linus Torvalds, um estudante finlandês, resolveu desenvolver um sistema operacional compatível com a POSIX, por em que pudesse ser executado em arquitetura x86;<br />
*Linux está sob uma licença de software livre e diversas pessoas e empresas contribuem para o desenvolvimento do mesmo.<br />
*E o que é [https://pt.wikipedia.org/wiki/POSIX POSIX]? Define padrões para a interface de programação de aplicações (API) de um OS de forma a manter compatibilidade com o UNIX;<br />
<br />
==Arquitetura do Linux==<br />
<br />
===Material de Referência===<br />
<br />
*[https://www.dropbox.com/s/zvpo7zw19ns7rmk/AULA%202.odp?dl=0 Slides Introdução ao SO Linux]<br />
*Ver pg.16 a 19 de [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo]<br />
<br />
==Distribuições==<br />
<br />
Uma distribuição Linux consiste de um kernel Linux e uma coleção de software utilitários e aplicativos de usuário (baseado slides Prof. Emerson)<br />
**Redhat<br />
**Slackware<br />
**Debian<br />
**Ubuntu<br />
**OpenSuse<br />
**Fedora<br />
**CentOS<br />
**Kali<br />
<br />
<br />
Algumas distribuições podem ser executadas diretamente no CD/pendrive<br />
sem a necessidade de fazer sua instalação no disco rígido do computador<br />
<br />
==Distribuições aqui no IFSC SJ==<br />
<br />
*Ubuntu<br />
*Ubuntu Mate (fork do Ubuntu)<br />
*Debian<br />
<br />
==Instalando o Linux==<br />
<br />
*Fazer Download do arquivo ISO em [http://mirror.pop-sc.rnp.br/mirror/ubuntu-releases/18.04/] versão Ubuntu 18.04.3 LTS;<br />
*Instalar a VirtualBox (já está instalada no nosso Lab). Baixar de [https://www.virtualbox.org/wiki/Downloads] e selecionar para a máquina hospedeira alvo;<br />
*Seguir o procedimento colocado pelo professor.<br />
<br />
*[Ver https://www.dropbox.com/s/4xfdhqq8lruvq8m/LinuxSobreVM.odp?dl=0 Slides de Instalação]<br />
<br />
==Ligando e Desligando o Sistema Linux==<br />
<br />
*Cuidado ao desligar um OS como o Linux!!! Dados podem ser perdidos.<br />
*Ver [https://pt.wikibooks.org/wiki/Guia_do_Linux/Iniciante%2BIntermedi%C3%A1rio/Introdu%C3%A7%C3%A3o/Ligando_o_computador]<br />
<br />
==O Desktop do Ubuntu - Primeiras Considerações==<br />
<br />
*O Desktop no Ubuntu ver[https://help.ubuntu.com/stable/ubuntu-help/shell-overview.html]<br />
<br />
=AULA 2 - Dia 29/08/2019=<br />
<br />
==Objetivos==<br />
<br />
===PARTE 1===<br />
<br />
*Revisão da aula passada;<br />
*repassar itens não mencionados na aula passada;<br />
**Paginação e Memória [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo pg.19]<br />
**Estrutura do Linux [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo pg.18]<br />
<br />
===PARTE 2===<br />
<br />
*Operações com arquivos e diretórios usando o terminal;<br />
*formato de um comando básico;<br />
*quase tudo no Linux é arquivo: tipos de arquivos, diretórios, arquivos ordinários;<br />
*conceito de sistema de arquivos;<br />
*conceito de referência absoluta e relativa;<br />
*conceito de diretório de entrada, diretório de trabalho;<br />
*mudando de diretório com cd;<br />
*listando diretórios e arquivos com ls;<br />
*vendo o significado de um comando com man;<br />
*criando diretórios com mkdir;<br />
*removendo diretórios e arquivos com rmdir e rm;<br />
*referência com . .. - ~<br />
*criando arquivos ordinários com touch;<br />
*arquivos e diretórios escondidos;<br />
*copiando arquivos;<br />
*movendo e renomeando arquivos;<br />
*vendo a história de comandos com history;<br />
<br />
===Slides===<br />
<br />
*[https://www.dropbox.com/s/wtc479wmrtle9m4/SistemaDeArquivos.odp?dl=0 Slides Sistema de Arquivos]<br />
<br />
==Conceito de sistemas de arquivos, arquivos e diretórios==<br />
<br />
* [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Sistemas de Arquivos pg.18]<br />
* [Estrutura básica de diretórios do Sistema Linux]<br />
<br />
==Comandos no Linux==<br />
<br />
* [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Comandos e Interpretador de Comandos no Linux pg.18]<br />
<br />
==Tipos de Arquivos==<br />
<br />
* [https://pt.scribd.com/doc/128912228/Administracao-de-Sistemas-Linux Tipos de Arquivos 12,13 e 14 ]<br />
<br />
==Os comandos de operação sobre arquivos e diretórios==<br />
<br />
*[https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Interpretador de comandos - Comandos Básicos - pg.20 e 21]<br />
*[https://www.dropbox.com/s/mv6qpa8bqimiwzg/Aula1_Linux%282%29.pdf Ver lista de exercícios da Aula 2]<br />
<!-- *[https://www.dropbox.com/s/g3xr3wimffde2zm/Aula2_Linux_OperacoesComArquivos_2.pdf Ver lista de exercícios da Aula 3] --><br />
<br />
=AULA 3 - Dia 03/09/2019=<br />
<br />
<br />
===Mirros do Ubuntu Download e Outros===<br />
<br />
<br />
*[http://mirror.pop-sc.rnp.br/mirror/ubuntu-releases/18.04.3/ Ununtu 18.04.3 Mirror Brazil]<br />
<br />
*[https://linuxmint.com/edition.php?id=267 Linux Mint]<br />
<br />
*[https://software.opensuse.org/distributions/leap Opensuse]<br />
<br />
*[https://elementary.io/ Elementary Os]<br />
<br />
*[https://lubuntu.net/ Lubuntu]<br />
<br />
*[https://www.debian.org/CD/live/ Debian]<br />
<br />
*[https://kubuntu.org/getkubuntu/ Kubuntu]<br />
<br />
*[https://peppermintos.com/ Peppermint]<br />
<br />
*[https://www.linuxliteos.com/ Linux Lite]<br />
<br />
*[https://www.lxle.net/download/ LXLE para PCs Antigos...]<br />
<br />
*[https://www.bodhilinux.com/ Bodhi Linux]<br />
<br />
===Como verificar se o arquivo está correto?===<br />
<br />
*[https://help.ubuntu.com/community/HowToMD5SUM HowToMD5SUM] <br />
<br />
===Instalar e Preparar 3 transparências no Oppenoffice===<br />
<br />
*Nome da Equipe e da Distribuição - colar a desktop no slide<br />
*O que tem de interessante nesta distro<br />
*Requisitos da Distribuição<br />
<br />
*Gerar pdf e Enviar para o Siga a<br />
<br />
=AULA 4 - Dia 03/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Ainda operações com arquivos;<br />
*Uso de Coringas<br />
*Editor de texto sobre Ubuntu<br />
*Redirecionamento de Entradas e Saídas<br />
*Aspectos da Interface Gnome no Ubuntu 18.04<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/zti7nn0xq25x8ne/Aula2_Linux_OperacoesComArquivos_2.pdf Ainda Operações com Arquivos]<br />
*[https://www.dropbox.com/s/af3jolkvrb24g8c/Aula3_Linux_LinksSimb_licos_gedit_cat.pdf Edição de Texto]<br />
*[https://www.dropbox.com/s/vihh5r9186d40uj/Aula3_Linux_Parte4_RedirecionamentoEntradasSaidas.pdf Redirecionamento de Entradas e Saídas]<br />
<br />
=AULA 5 - Dia 10/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Gerenciamento de Processos - Parte 1<br />
*Permissionamento de Arquivos - Parte 1<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/4i1n2wqsds18eol/Aula5_Linux_GerenciamentoDeProcessos_Parte1.pdf?dl=0 Gerenciamento de Processos - Parte 1]<br />
*[https://www.dropbox.com/s/3z61r8r0b9wpftr/Aula4_Linux_PermissionamentoDeAcesso_Parte1.pdf Permissionamento de Arquivos - Parte 1]<br />
<br />
=AULA 6 - Dia 12/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Aval1<br />
<br />
==Comand wget==<br />
<br />
Para fazer o downloiad do Linux Ubuntu via linha de comando:<br />
<br />
wget http://mirror.pop-sc.rnp.br/mirror/ubuntu-releases/18.04.3/ubuntu-18.04.3-desktop-amd64.iso<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/fdl5kzq0ba2nv3v/Aula4_Linux_PermissionamentoDeAcesso_Parte2.pdf Permissionamento Parte 2 ]<br />
<br />
=AULA 7 - Dia 12/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Instalação do Ubuntu em partições separadas<br />
*Permissionamento de Grupos e Outros<br />
*Criação de Contas de Usuários<br />
*Camandos adicionais para gerenciamento de processos<br />
<br />
==Instalação==<br />
<br />
Considere a estrutura de sistemas de arquivos abaixo. Montar um sistema de arquivos da forma abaixo considerando que sb1 seria um segundo hd máquina virtual.<br />
<br />
[[arquivo:SOP2019-1-ExemploMontagemSistema.png]]<br />
<br />
Logar no sistema e usando o terminal verificar as configurações estabelecidas.<br />
<br />
df -h<br />
cd /home<br />
ls spock<br />
<br />
Usar o comando gparted para criar uma partição adicional no segundo disco.<br />
<br />
sudo apt-get install gparted<br />
sudo gparted<br />
<br />
Redimensionar a partição original para poder criar uma adicional.<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/fdl5kzq0ba2nv3v/Aula4_Linux_PermissionamentoDeAcesso_Parte2.pdf Permissionamento Parte 2 ]<br />
<br />
*[https://www.dropbox.com/s/ozjd3qz0yblcj43/Aula6_Comandos_Adicionais_de_Gerenciamento_de_Processos.pdf Gerenciamento de Processos Parte 2]<br />
<br />
=AULA 8 - Dia 12/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Permissionamento de Grupos e Outros<br />
*Criação de Contas de Usuários<br />
*Reparticionamento de Disco após instalação. Montagem de sistemas com mount.<br />
<br />
==Desafio Final==<br />
<br />
Na máquina instalada na aula anterior fazer as seguintes operações:<br />
<br />
*Reparticionar o disco 2 (/dev/sdb) em 2 partições de 5G (usar o comando gparted) (redimensionar a partição do spock)<br />
*Criar uma conta para o usuário uhura<br />
*Criar dois subdiretórios no diretório home de uhura. Estes diretórios serão pontos de montagem dos dois sistemas de arquivos criados no segundo disco.<br />
*Montar os sistemas de arquivos usando o comando mounthttps://wiki.sj.ifsc.edu.br/index.php/ISL-FicLinux_(Plano_de_Ensino)<br />
*Mudar o dono destes diretórios (usuário e grupo) )para o novo dono (uhura)<br />
*Verificar o sistema montado (comando df)<br />
*Testar o acesso entrando como <br />
<br />
==Continuando o o permissionamento de Grupos e Outros==<br />
<br />
Ver material de referência<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/fdl5kzq0ba2nv3v/Aula4_Linux_PermissionamentoDeAcesso_Parte2.pdf Permissionamento Parte 2 ]<br />
*[https://www.dropbox.com/s/ozjd3qz0yblcj43/Aula6_Comandos_Adicionais_de_Gerenciamento_de_Processos.pdf Gerenciamento de Processos Parte 2]<br />
<br />
=AULA 9 - Dia 24/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*ainda criação de usuários<br />
*ainda gerenciamento de processos: crontab<br />
*compactação e backups em linha de comando<br />
<br />
<br />
==Material de Referência==<br />
<br />
<br />
*[Ainda Gerenciamento de Usuários https://www.dropbox.com/s/8vsg0yeforcsuq9/Aula7_GerenciamentoDeUsuarios_Parte1.pdf?dl=0]<br />
*[https://www.dropbox.com/s/ozjd3qz0yblcj43/Aula6_Comandos_Adicionais_de_Gerenciamento_de_Processos.pdf Gerenciamento de Processos Parte 2]<br />
*[https://www.dropbox.com/s/61n9is9c8o7bgbz/Aula3_Linux_Parte3_vi.pdf?dl=0 Introdução ao VI]<br />
<br />
=AULA 10 - Dia 26/09/2019=<br />
<br />
==Objetivos==<br />
<br />
*Finalização da aula anterior: arquivo sudoers<br />
*Introdução ao shell script<br />
*Um pouco sobre instalação de pacotes<br />
*exercicício avaliativo 2<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/54tnv5rjwguzppd/Aula8_ShellScript_Parte1.pdf?dl=0 Introdução ao Shell script]<br />
*[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula9-pacotes.pdf Instalação de Pacotes (Prof.Luciano Barreto)]<br />
<br />
=AULA 11 - Dia 1/10/2019=<br />
<br />
Introdução a Redes de Computadores<br />
**Conceito Básicos em Redes e Protocolos<br />
**Ferramentas de Redes<br />
**Exemplo de Protocolo de Aplicação: http<br />
**O processo de encapsulamento<br />
<br />
==Plano de Ensino==<br />
<br />
*[https://wiki.sj.ifsc.edu.br/index.php/PRL-FicLinux_(Plano_de_Ensino) Plano de Ensino]<br />
<br />
<br />
==Laboratório 1 - Ferramentas de Rede e Conceitos Básicos==<br />
<br />
*Familiarização com a infraestrutura dos laboratórios de redes<br />
*Familiarização com ferramentas de rede: ifconfig, ping, traceroute;<br />
*Desenvolver a noção de endereçamentos de rede IP e de endereço de hardware (MAC)<br />
*Desenvolver a noção de rotas em redes IP<br />
*Testar a conectividade IP com ping<br />
<br />
*Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)]<br />
<br />
==Laboratório 2 - Wireshark e encapsulamento==<br />
<br />
*Familiarização com o sniffer de rede WireShark<br />
*Observar o comportamento do ping e se familiarizar com o processo de encapsulamento;<br />
<br />
**Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)]<br />
<br />
==Conceituando Protocolos e Aplicações de Rede==<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/Conceituando%20protocolos.pdf Conceituando protocolos]<br />
<br />
<br />
{{collapse bottom}}<br />
<br />
<br />
<br />
{{collapse top | Semestre 2019-1 - Prof. Tiago Semprebom e Eraldo Silveira e Silva}}<br />
<br />
=Professor=<br />
<br />
:*Prof. [[Tiago Semprebom]]<br />
:*email: tisemp@ifsc.edu.br<br />
:*sala: Sala de II de Professores da Área de Telecomunicações (primeira sala lado da Biblioteca - direção esquerda)<br />
<br />
=12/03/2019=<br />
<br />
==Objetivos==<br />
<br />
===Parte 1===<br />
*Apresentar os professores e o coordenador;<br />
*Apresentar o IFSC: estrutura, câmpus e serviços<br />
*Apresentar o curso: perfil do egresso, competências gerais, áreas de atuação do egresso e conteúdos previstos<br />
*Apresentar o Cronograma Tentativa<br />
*Apresentar metodologia e forma de avaliação<br />
<br />
===Parte 2===<br />
<br />
*Conceitos de Hardware, Software e Firmware<br />
*Arquiteturas de processadores<br />
*Classificação de softwares<br />
*Conceitos de Sistemas Operacionais e exemplos<br />
<br />
===Parte 3===<br />
<br />
*Histórico do Linux<br />
*Linux e GNU/Linux<br />
*Arquitetura do Linux<br />
*Distribuições<br />
*Distribuições usadas no IFSC/SJ<br />
*Ligando e Desligando o Sistema<br />
*Primeiros contatos.<br />
<br />
==Professores do FIC Linux Edição 2019-1==<br />
*Prof. [[Tiago Semprebom]] (Introdução ao Linux)<br />
*Prof. [[Eraldo Silveira e Silva]] (Redes com Linux)<br />
<br />
==Apresentação do IFSC==<br />
<br />
*[http://www.ifsc.edu.br/estrutura-organizacional-inicio Página do IFSC]<br />
*[https://www.sj.ifsc.edu.br/index.php Página do Câmpus]<br />
<br />
==Apresentação do Curso==<br />
<br />
*[[ISL-FicLinux_(Plano_de_Ensino) | Introdução ao Linux]]<br />
*[[PRL-FicLinux (página) | Projeto de Rede Residencial com o Linux]]<br />
*[[Curso_de_Formação_Continuada_de_Configuração_de_Redes_de_Computadores_Linux | PPC do Curso e Outras Regulamentações]]<br />
<br />
==Cronograma Tentativa==<br />
<br />
Horários: 19h às 22h.<br />
<br />
{| class="wikitable"|<br />
| AULA || DATA || Professor || Conteúdo<br />
|-<br />
| 1 || 12/03/2019 || TIAGO || Programa da Disciplina.Forma de Avaliação. O computador: hardware e software. SO Linux: histórico e distribuições. Ligando/Logando/Desligando a Máquina. Conceitos básico de Sistema de Arquivos e Processos.<br />
|-<br />
| 2 || 14/03/2019 || TIAGO || Gerenciamento de Arquivos I: Operações sobre arquivos e diretórios usando o terminale o Nautilus.<br />
|-<br />
| 3 || 21/03/2019 || TIAGO || Gerenciamento de Arquivos II: continuação Operações sobre arquivos e diretórios. Links Simbólicos, Criação de Arquivo com vi e outros editores.<br />
|-<br />
| 4 || 26/03/2019 || TIAGO || Interfaces Gráficas: X11, Gnome. KDE e outras. Instalação de Programas via Gerenciador de Pacotes.<br />
|-<br />
| 5 || 28/03/2019 || TIAGO || Administração de contas de usuários I<br />
|-<br />
| 6 || 02/04/2019 || TIAGO || Administração de contas de usuários II<br />
|-<br />
| 7 || 04/04/2019 || TIAGO || Permissionamento de Arquivos<br />
|-<br />
| 8 || 09/04/2019 || TIAGO || Gerenciamento de Processos<br />
|-<br />
| 9 || 11/04/2019 || TIAGO || Introdução ao Shell Script<br />
|-<br />
| 10 || 16/04/2019 || TIAGO || Avaliação 1 - Introdução ao Sistema Operacional Linux<br />
|-<br />
| 11 || 09/10/2019 || ERALDO || Introdução a Redes. Conceito de Protocolos. Ferramentas de Rede.<br />
|-<br />
| 12 || 11/10/2019 || ERALDO || Protocolos de Aplicação: exemplo http <br />
|-<br />
| 13 || 16/10/2019 || ERALDO || O DNS como protocolo de Aplicação; Camada de Transporte: protocolo UDP <br />
|-<br />
| 14 || 18/10/2019 || ERALDO || Protocolo TCP. Diferenças dos protocolos de Transporte TCP/UDP. Camada IP e aspectos da configuração da mesma sob o Linux<br />
|-<br />
| 15 || 23/10/2017 || ERALDO || Camada de Enlace/Física. Hubs X Switches. O Papel do Protocolo ARP. Outros serviços/protocolos: Serviço DHCP e NAT<br />
|-<br />
| 16 || 25/10/2017 || ERALDO (TIAGO) || Segmentação Redes IP. Cálculo de subredes. <br />
|-<br />
| 17 || 30/10/2017 || ERALDO || Introdução ao IPV6. Introdução ao Access Point TPLINK N750: configuração da LAN e WAN<br />
|-<br />
| 18 || 01/11/2017 || ERALDO || Serviço SSH no Linux. Acesso a rede WIFI. Conceitos básicos de redes sem fio.<br />
|-<br />
| 19 || 06/11/2007 || ERALDO || Tópicos Adicionais sobre redes no Linux: Configuração Manual X NetworkManager. Relatório Avaliativo 1.<br />
|-<br />
| 20 || 08/11/2017 || ERALDO || Relatório Avaliativo 2<br />
|}<br />
<br />
==Metodologia, Avaliação e Critérios de Aprovação==<br />
<br />
*Aaulas expositivas e aulas práticas no laboratório. Nas aulas práticas serão desenvolvidos exercícios e trabalhos individuais.<br />
*Avaliações individuais: Listas de exercícios com aproveitamento e entregues no prazo. <br />
*Critérios para aprovação: Serão considerados aprovados os alunos que obtiverem conceito final 6 ou superior em cada componente curricular. ATENÇÂO: Possuir no mínimo 75% de presença<br />
<br />
==Bibliografia==<br />
<br />
#Odilson Tadeu Valle<br />
##Administração de redes com Linux: fundamentos e práticas<br />
##Editora IFSC, 2010<br />
#Gleydson Mazioli da Silva<br />
##Guia Foca Linux<br />
##http://www.guiafoca.org/<br />
#Luiz Carlos Lobato Lobo de Medeiros e Wendel Soares<br />
##Formação de suporte técnico PROINFO<br />
##https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo<br />
#Ari Frazão Jr e Marcelo Braga<br />
##Administração de Sistemas Linux<br />
##https://pt.scribd.com/doc/128912228/Administracao-de-Sistemas-Linux<br />
<br />
==Conceitos de Hardware, Software e Firmware==<br />
<br />
*Em informática, o hardware consiste nos equipamentos<br />
**Ex: Computador, teclado, mouse, monitor<br />
*Software é um aplicativo, desenvolvido em uma linguagem de programação<br />
**Ex: Windows, Linux, Mozilla Firefox, Google Chrome<br />
*Firmware é um conjunto de instruções básicas e específicas para um hardware<br />
**Ex: BIOS nos computadores, sistemas de controle das máquinas de lavar, etc.<br />
<br />
==Estrutura de um Computador e Arquitetura de Processadores==<br />
<br />
*Bits, [https://pt.wikipedia.org/wiki/Byte Bytes] e tamanho de memória;<br />
*Representação de Caracteres: [https://pt.wikipedia.org/wiki/ASCII Tabela ASCII];<br />
*O [https://pt.wikipedia.org/wiki/Microprocessador microprocessador], barramentos e memórias semicondutoras: RAM,ROM, E2PROM, FLASH;<br />
*Memórias cache e memórias secundárias;<br />
*[https://pt.wikipedia.org/wiki/Mem%C3%B3ria_virtual Memória Virtual] e Swapping;<br />
*Registradores de 32bits ou 64bits<br />
*Arquitetura [https://pt.wikipedia.org/wiki/X86 x86] / [https://pt.wikipedia.org/wiki/AMD64 x86-64] – presente nos computadores pessoais<br />
*Arquitetura ARM – presente em sistemas embarcados e dispositivos móveis<br />
*Múltiplos núcleos (core)<br />
*Máquinas Virtuas: VirtualBox, UML (User Mode Linux).<br />
<br />
==O papel do Sistema Operacional==<br />
<br />
*O [https://pt.wikipedia.org/wiki/Sistema_operativo SO] é um programa (software) que controla a máquina e a torna utilizável para o usuário;<br />
*Abstrações do Sistema: arquivos e processos;<br />
*Pode ser multitarefa e multiusuário;<br />
*[https://en.wikipedia.org/wiki/Device_driver Driver] de dispositivo<br />
*[https://pt.wikipedia.org/wiki/Multi_boot Múltiplos OS instalados] em um computador. É possível??<br />
<br />
==Sistema de Arquivos==<br />
<br />
*Forma como estão estruturados/organizados os arquivos/dados em uma determinada mídia [https://pt.wikipedia.org/wiki/Sistema_de_ficheiros];<br />
*Um sistema operacional deve saber como acessar e operar sobre este sistema;<br />
*Tipos de sistemas: ext4, NTFS, VFAT32<br />
<br />
==Exemplos de SO==<br />
<br />
*Unix<br />
*Microsoft DOS<br />
*IBM<br />
*Microsoft Windows<br />
*netBSD, freeBSD, openBSD<br />
*Linux<br />
*macOS<br />
*Android<br />
*iOS<br />
<br />
==Histórico do Linux==<br />
<br />
*O início de tudo: UNIX;<br />
*Surgiu em 1991 quando Linus Torvalds, um estudante finlandês, resolveu desenvolver um sistema operacional compatível com a POSIX, por em que pudesse ser executado em arquitetura x86;<br />
*Linux está sob uma licença de software livre e diversas pessoas e empresas contribuem para o desenvolvimento do mesmo.<br />
*E o que é [https://pt.wikipedia.org/wiki/POSIX POSIX]? Define padrões para a interface de programação de aplicações (API) de um OS de forma a manter compatibilidade com o UNIX;<br />
<br />
==Arquitetura do Linux==<br />
<br />
*Ver pg.16 a 19 de [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo]<br />
<br />
==Distribuições==<br />
<br />
Uma distribuição Linux consiste de um kernel Linux e uma coleção de software utilitários e aplicativos de usuário (baseado slides Prof. Emerson)<br />
**Redhat<br />
**Slackware<br />
**Debian<br />
**Ubuntu<br />
**OpenSuse<br />
**Fedora<br />
**CentOS<br />
**Kali<br />
<br />
<br />
Algumas distribuições podem ser executadas diretamente no CD/pendrive<br />
sem a necessidade de fazer sua instalação no disco rígido do computador<br />
<br />
==Distribuições aqui no IFSC SJ==<br />
<br />
*Ubuntu<br />
*Ubuntu Mate (fork do Ubuntu)<br />
*Debian<br />
<br />
==Ligando e Desligando o Sistema Linux==<br />
<br />
*Cuidado ao desligar um OS como o Linux!!! Dados podem ser perdidos.<br />
*Ver [https://pt.wikibooks.org/wiki/Guia_do_Linux/Iniciante%2BIntermedi%C3%A1rio/Introdu%C3%A7%C3%A3o/Ligando_o_computador]<br />
<br />
==O Desktop do Ubuntu - Primeiras Considerações==<br />
<br />
*O Desktop no Ubuntu ver[https://help.ubuntu.com/stable/ubuntu-help/shell-overview.html]<br />
<br />
=AULA 2 - Dia 14/03/2019=<br />
<br />
==Objetivos==<br />
<br />
===PARTE 1===<br />
<br />
*Revisão da aula passada;<br />
*repassar itens não mencionados na aula passada;<br />
**Paginação e Memória [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo pg.19]<br />
**Estrutura do Linux [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo pg.18]<br />
<br />
===PARTE 2===<br />
<br />
*Operações com arquivos e diretórios usando o terminal;<br />
*formato de um comando básico;<br />
*quase tudo no Linux é arquivo: tipos de arquivos, diretórios, arquivos ordinários;<br />
*conceito de sistema de arquivos;<br />
*conceito de referência absoluta e relativa;<br />
*conceito de diretório de entrada, diretório de trabalho;<br />
*mudando de diretório com cd;<br />
*listando diretórios e arquivos com ls;<br />
*vendo o significado de um comando com man;<br />
*criando diretórios com mkdir;<br />
*removendo diretórios e arquivos com rmdir e rm;<br />
*referência com . .. - ~<br />
*criando arquivos ordinários com touch;<br />
*arquivos e diretórios escondidos;<br />
*copiando arquivos;<br />
*movendo e renomeando arquivos;<br />
*vendo a história de comandos com history;<br />
<br />
==Conceito de sistemas de arquivos, arquivos e diretórios==<br />
<br />
* [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Sistemas de Arquivos pg.18]<br />
* [Estrutura básica de diretórios do Sistema Linux]<br />
<br />
==Comandos no Linux==<br />
<br />
* [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Comandos e Interpretador de Comandos no Linux pg.18]<br />
<br />
==Tipos de Arquivos==<br />
<br />
* [https://pt.scribd.com/doc/128912228/Administracao-de-Sistemas-Linux Tipos de Arquivos 12,13 e 14 ]<br />
<br />
==Os comandos de operação sobre arquivos e diretórios==<br />
<br />
*[https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Interpretador de comandos - Comandos Básicos - pg.20 e 21]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_2_FICLinux.pdf Ver lista de exercícios da Aula 2]<br />
<!-- *[https://www.dropbox.com/s/g3xr3wimffde2zm/Aula2_Linux_OperacoesComArquivos_2.pdf Ver lista de exercícios da Aula 3] --><br />
<br />
=AULA 3 - Dia 21/03/2019 (aula com Prof. Eraldo)=<br />
<br />
==Objetivos==<br />
<br />
===PARTE 1===<br />
<br />
*Rever comandos básicos de operações sobre arquivos;<br />
*Usar coringas<br />
*usar opções do comando ls<br />
<br />
===PARTE 2===<br />
<br />
*uso do editor gedit para criar arquivos texto;<br />
*usar comandos cat, more e less para visualizar conteúdos de arquivos.<br />
<br />
===PARTE 3===<br />
<br />
*Criar Links simbólicos<br />
<br />
===Parte 4===<br />
<br />
*Redirecionamento de entradas e saídas;<br />
*Pipes<br />
<br />
==Exercícios para esta aula==<br />
'''Créditos e agradecimentos ao Prof. Eraldo pelo desenvolvimento das listas utilizadas''':<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_3_FICLinux.pdf Mais operações Sobre Arquivos e Diretórios]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_4_FICLinux.pdf Editor Gedit, Link Simbólico]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_5_FICLinux.pdf Editor vi]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_6_FICLinux.pdf Entradas e Saídas]<br />
<br />
=AULA 4 - Dia 26/03/2019=<br />
<br />
==Objetivos==<br />
<br />
===PARTE 1===<br />
<br />
*Revisão geral<br />
<br />
<br />
===PARTE 2===<br />
<br />
*Redirecionamento de entradas e saídas: continuação;<br />
*Pipes<br />
<br />
===PARTE 3===<br />
<br />
*Permissão no acesso a arquivos;<br />
*Owner, grupo e outros<br />
<br />
==Exercícios para esta aula==<br />
<br />
=Referências=<br />
<br />
[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_7_FICLinux.pdf Permissão de Acesso a Arquivos: parte 1]<br />
<br />
[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_8_FICLinux.pdf Permissão de Acesso a Arquivos: parte 2]<br />
<br />
=AULA 5 - Dia 28/03/2019=<br />
<br />
==Objetivos==<br />
<br />
*Revisão e preparação para teste;<br />
*introdução ao gerenciamento de processos;<br />
**conceito de processo<br />
**escalonamento de processos<br />
**PID e PPID<br />
**fork/exec<br />
**espaço de endereçamento de um processo;<br />
**estados de um processo: Running, Stopped, Sleeping, Zombie<br />
<br />
https://www.tecmint.com/linux-process-management/<br />
<br />
==Referências==<br />
<br />
[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_9_FICLinux.pdf Gerenciamento De Processos Parte 1]<br />
[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_10_FICLinux.pdf Gerenciamento De Processos Parte 2]<br />
<br />
[https://www.dropbox.com/s/gm1sv856ailny2e/Aula5_TreinamentoTeste.pdf Treinamento Teste 1]<br />
<br />
=AULA 6 - Dia 02/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*Comandos adicionais de gerenciamento de processos;<br />
*Mudança de prioridade com nice e renice;<br />
*Agendamento de processos com crontab<br />
*Aplicações do crontab: conectividade de rede e backup<br />
*Ferramentas de compactação;<br />
*Execução de comandos inseridos em outros comandos;<br />
<br />
==Material de Referência==<br />
<br />
*[https://www.dropbox.com/s/z1d0itcz9ommhrm/Aula6_Aval1.pdf Avaliação 1]<br />
<br />
=AULA 7 - Dia 04/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*Comandos adicionais de manipulação de arquivos:<br />
**comando grep;<br />
**comando find;<br />
*Gerenciamento de usuários:<br />
**adição e remoção de usuários e grupos<br />
**arquivo sudoers<br />
<br />
<br />
==Exercícios==<br />
<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_11_FICLinux.pdf Comandos Adicionais] <br />
<!--*[https://www.dropbox.com/s/h0v122is4aj9ogr/Aula7_GerenciamentoDeUsuarios_Parte1.pdf Aula 7 - Parte 2]--><br />
<br />
=AULA 8 - Dia 09/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*Introdução ao Shell script<br />
*variáveis<br />
*Comando if<br />
<br />
==Referências==<br />
<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_14_FICLinux.pdf Outros comando gerenciamento de processos]<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_12_FICLinux.pdf Shell Parte 1]<br />
<br />
{{collapse top | script DESAFIO (a)}}<br />
<syntaxhighlight lang=c><br />
#!/bin/bash<br />
<br />
FILE="$1"<br />
<br />
if [ ! $# -eq 1 ]; then<br />
echo opa! Algo errado...<br />
echo uso: script parametro<br />
exit<br />
fi<br />
<br />
<br />
if [ -h $FILE ]; then<br />
echo $FILE é um link simbólico<br />
else<br />
echo $FILE não é um link simbólico<br />
fi<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
{{collapse top | script DESAFIO (b)}}<br />
<syntaxhighlight lang=c><br />
<br />
#!/bin/bash<br />
<br />
FILE="$1"<br />
<br />
if [ ! $# -eq 1 ]; then<br />
echo opa! Algo errado...<br />
echo uso: script parametro<br />
exit<br />
fi<br />
<br />
<br />
if [[ -w $FILE && -O $FILE ]]; then<br />
echo Possui permissao de escrita de $FILE<br />
else<br />
echo Colocando permissão de escrita para $FILE<br />
chmod u+w $FILE<br />
echo permissoes adicionadas com sucesso para $FILE ver abaixo<br />
ls -l $FILE<br />
<br />
fi<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
{{collapse top | script DESAFIO (c)}}<br />
<syntaxhighlight lang=c><br />
#!/bin/bash<br />
<br />
FILE1="$1"<br />
FILE2="$2"<br />
<br />
if [ ! $# -eq 2 ]; then<br />
echo opa! Algo errado...<br />
echo uso: script parametro<br />
exit<br />
fi<br />
<br />
if [[ -f $FILE1 && -r $FILE1 ]]; then<br />
echo $1 É regular e possui permissao de leitura<br />
mv $FILE1 $FILE2<br />
echo Mudei o nome de $FILE1 para $FILE2<br />
else<br />
echo $FILE1 não tem permissao...<br />
fi<br />
</syntaxhighlight><br />
{{collapse bottom}}<br />
<br />
=AULA 9 - Dia 11/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*ainda shell script<br />
*comando for<br />
*comando while<br />
<br />
==Referências==<br />
<br />
*[http://tele.sj.ifsc.edu.br/~tisemp/FIC-Linux/listas/Aula_13_FICLinux.pdf Shell Parte 2]<br />
<br />
=AULA 10 - Dia 16/04/2019=<br />
<br />
*Avaliação da disciplina<br />
<br />
=Tópicos extras=<br />
<br />
==Objetivos==<br />
<br />
*mais alguns tópicos sobre criação de usuários;<br />
*servidores de janelas: X11, <br />
*gerenciadores de janelas e desktops: Gnome, KDE<br />
*instalação de pacotes;<br />
*o Linux e o Software Livre<br />
*avaliação<br />
<br />
==Servidores de Janelas==<br />
<br />
[https://pt.wikipedia.org/wiki/X_Window_System X Windows System]<br />
<br />
[https://en.wikipedia.org/wiki/X_Window_System_protocols_and_architecture Arquitetura do X]<br />
<br />
==Desktops e Geneciadores de Janelas==<br />
<br />
[https://pt.wikipedia.org/wiki/Interface_gr%C3%A1fica_do_utilizador Interfaces Gráficas]<br />
<br />
==Instalando pacotes==<br />
<br />
[https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo Ver pg.43 do Formacao-de-Suporte-Tecnico-Proinfo]<br />
<br />
[http://www.hardware.com.br/tutoriais/tutorial-completo-apt-get/ uso do apt-get]<br />
<br />
Exercício: instalar e executar um servidor ssh:<br />
<br />
sudo apt-get update<br />
sudo apt-get install openssh-server<br />
sudo service start ssh<br />
<br />
Acessar o ssh de outra máquina<br />
ssh usuario@numero_ip<br />
<br />
Exportar o display e executar o comando remoto:<br />
export DISPLAY=IP_cliente_ssh:0.0<br />
firefox &<br />
<br />
Conferir se o firefox realmente está se executando (use o ps)<br />
<br />
Remover o pacote ssh server:<br />
<br />
sudo apt-get remove openssh-server<br />
<br />
==Linux = Software Livre==<br />
<br />
[https://pt.wikipedia.org/wiki/Software_livre]<br />
<br />
<br />
<br />
[https://www.novell.com/coolsolutions/feature/1532.html]<br />
<br />
==Onde baixar o Ubuntu==<br />
<br />
[https://www.ubuntu.com/download/desktop Baixar Ubuntu daqui]<br />
<br />
==Sobre o Boot==<br />
<br />
[http://www.rodsbooks.com/linux-uefi/ by Roderick W. Smith]<br />
<br />
[https://www.happyassassin.net/2014/01/25/uefi-boot-how-does-that-actually-work-then/ AdamW on Linux and more]<br />
<br />
==Sobre o Desktop Environment e o Desktop Shell==<br />
<br />
[https://ittutorials.net/linux/ubuntu/desktop-guide/ /desktop-guide]<br />
<br />
==Instalar Ubuntu no Virtual Box==<br />
<br />
[http://www.edivaldobrito.com.br/virtualbox-no-linux/ Instalar VirtualBox no Linux]<br />
<br />
[http://www.bosontreinamentos.com.br/virtualizacao/como-instalar-o-virtualbox-no-windows-para-criacao-de-maquinas-virtuais/ Instalar VirtualBox no Windows]<br />
<br />
[http://www.techtudo.com.br/dicas-e-tutoriais/noticia/2016/04/como-instalar-o-ubuntu-com-o-virtualbox.html Instalar Linux no VirtualBox]<br />
<br />
=AULA 11 - Dia 23/04/2019=<br />
<br />
*Introdução a Redes de Computadores<br />
**Conceito Básicos em Redes e Protocolos<br />
**Ferramentas de Redes<br />
**Exemplo de Protocolo de Aplicação: http<br />
**O processo de encapsulamento<br />
<br />
==Plano de Ensino==<br />
<br />
*[https://wiki.sj.ifsc.edu.br/index.php/PRL-FicLinux_(Plano_de_Ensino) Plano de Ensino]<br />
<br />
<br />
==Laboratório 1 - Ferramentas de Rede e Conceitos Básicos==<br />
<br />
*Familiarização com a infraestrutura dos laboratórios de redes<br />
*Familiarização com ferramentas de rede: ifconfig, ping, traceroute;<br />
*Desenvolver a noção de endereçamentos de rede IP e de endereço de hardware (MAC)<br />
*Desenvolver a noção de rotas em redes IP<br />
*Testar a conectividade IP com ping<br />
<br />
*Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)]<br />
<br />
==Laboratório 2 - Wireshark e encapsulamento==<br />
<br />
*Familiarização com o sniffer de rede WireShark<br />
*Observar o comportamento do ping e se familiarizar com o processo de encapsulamento;<br />
<br />
**Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)]<br />
<br />
==Conceituando Protocolos e Aplicações de Rede==<br />
<br />
[http://docente.ifsc.edu.br/odilson/RCO60803/Conceituando%20protocolos.pdf Conceituando protocolos]<br />
<br />
=AULA 12 - Dia 25/04/2019=<br />
<br />
==Objetivos==<br />
<br />
*Protocolos de aplicação: exemplo http<br />
<br />
==Laboratório 4 - Desvendando o HTTP com Wireshark - BÁSICO==<br />
<br />
Ver [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)#Parte_1:_Observando_interfaces_do_sistema_com_ifconfig]<br />
<br />
=AULA 13 - Dia 30/04/2019=<br />
<br />
*Revisão do Conceito de Protocolo ([-] Laboratório 3 - Conceituando protocolos )<br />
*O DNS como protocolo de Aplicação;<br />
*Camada de Transporte: protocolo UDP<br />
<br />
==Revisão dos Conceitos de Protocolo==<br />
<br />
Laboratório 3 - Conceituando protocolos [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)#Parte_1:_Observando_interfaces_do_sistema_com_ifconfig]<br />
<br />
==O DNS como protocolo de Aplicação==<br />
<br />
Laboratório 7 - Serviço de Nomes (DNS) [https://wiki.sj.ifsc.edu.br/index.php/Curso_T%C3%A9cnico_Integrado_de_Telecomunica%C3%A7%C3%B5es_-_Redes_de_Computadores_(RCO)#Parte_1:_Observando_interfaces_do_sistema_com_ifconfig]<br />
<br />
==O Protocolo UDP==<br />
<br />
Laboratório 8 - Desvendando o UDP - Básico <br />
<br />
=AULA 14 - Dia 02/05/2019=<br />
<br />
==Objetivos==<br />
<br />
*Explorar o papel e diferenças dos protocolos de Transporte TCP/UDP<br />
*Explorar a Camada IP e aspectos da configuração da mesma sob o Linux<br />
<br />
<br />
===TCP e UDP===<br />
<br />
*docente.ifsc.edu.br/odilson/RCO60803/TCP%20controle%20de%20erros.pdf<br />
*docente.ifsc.edu.br/odilson/RCO60803/UDP%20Basico.pdf<br />
<br />
==Camada IP no Linux: Configuração das Interfaces usando ifconfig e ip addr==<br />
<br />
Usando a ferramenta Netkit2, que permite construir redes virtuais com o Linux vamos construir DUAS redes locais interligadas por um roteador. Em cada rede colocaremos dois PCs. As interfaces estarão completamente desconfiguradas:<br />
<br />
<ol><br />
<li><br />
Construir um arquivo texto de nome rede.conf usando o editor de texto gedit.<br />
<code>gedit rede.conf &</syntaxhighlight> <br />
</li><br />
<li><br />
Criar a seguinte topologia:<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=generic<br />
<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
#Definição da Topologia da Rede<br />
<br />
pc1[eth0]=lan0<br />
pc2[eth0]=lan0<br />
<br />
pc3[eth0]=lan1<br />
pc4[eth0]=lan1<br />
<br />
r1[eth0]=lan0<br />
r1[eth1]=lan1<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Executar netkit fazendo (atualize se necessário - pergunte para o professor como fazer):<br />
Aplicativos >> Educativo >> Netkit2 <br />
</li><br />
<li><br />
Carregar o arquivo lab.conf a partir do Netkit2:<br />
<code>File >> Load Only</syntaxhighlight><br />
</li><br />
<li><br />
Visualizar a rede a ser implementada:<br />
<code>File >> Graph</syntaxhighlight><br />
</li><br />
<li> <br />
Executar a configuração:<br />
<code>Network >> Start</syntaxhighlight><br />
</li><br />
<li><br />
Verificar o estado de todas interfaces (se UP ou DOWN) com:<br />
<code>ifconfig -a</syntaxhighlight><br />
<code>ip addr</syntaxhighlight> <br />
Note que nas últimas versões do Linux o comando ip vem sendo recomendado (embora o ifconfig ainda esteja disponível).<br />
</li><br />
<li><br />
Vamos configurar as interfaces. Para tanto vamos assumir que teremos duas sub-redes:<br />
<code>lan0 - endereço da rede 10.10.10.0/24</syntaxhighlight><br />
<code>lan1 - endereço da rede 20.20.20.0/24</syntaxhighlight><br />
A interface eth0 de PC1 receberá o endereço 10.10.10.1/24 e a interface eth0 de PC2 recebera 10.10.10.2/24. A interface do roteador NA lan0 também deve receber um endereço: 10.10.10.254/24:<br />
<br />
No PC1:<br />
<code>ifconfig eth0 10.10.10.1/24</syntaxhighlight><br />
No PC2:<br />
<code>ifconfig eth0 10.10.10.2/24</syntaxhighlight><br />
No R1:<br />
<code>ifconfig eth0 10.10.10.254/24</syntaxhighlight><br />
</li> <br />
<li><br />
Seguindo a mesma lógica configure as máquinas e o roteador na lan1<br />
</li><br />
<li> Um ponto importante a ser lembrado é que quando uma interface é configurada com um número IP, a tabela de roteamento do sistema é alimentada com o número correspondente da rede associada ao número. Isto pode ser observado em TODAS as máquinas, inclusive no roteador:<br />
<code> route -n </syntaxhighlight><br />
ou <br />
<code> ip route </syntaxhighlight><br />
</li><br />
</ol><br />
<br />
==Camada IP no Linux: verificando e configurando rotas - configuração da rota default ==<br />
<br />
<ol><br />
<li> Um ponto importante a ser lembrado é que quando uma interface é configurada com um número IP, a tabela de roteamento do sistema é alimentada com o número correspondente da rede associada ao número. Isto pode ser observado em TODAS as máquinas, inclusive no roteador:<br />
<code> route -n </syntaxhighlight><br />
ou <br />
<code> ip route </syntaxhighlight><br />
Esta informação é importante pois define a entrega DIRETA de pacotes na rede, ou seja, se PC1 quiser enviar um pacote para PC2, esta linha na tabela de roteamento garante que o pacote IP seja despachado diretamente para o PC2 através de um frame ETHERNET endereçado para o MAC do PC1.<br />
</li><br />
<li> Confira os endereços MAC e IP das interfaces dos PC1 e PC2 e anote. Faça um ping no PC1 em direção a PC2.<br />
<code>root@pc1:~# ping 10.10.10.2</syntaxhighlight><br />
</li><br />
<li> Use um capturador de pacotes em modo texto para observar o tráfego na eth0 do PC2. Observe os endereços MAC do Frame Ethernet e os endereços IP do pacote IP.<br />
<code>root@pc2:~# tcpdump -i eth0 -e</syntaxhighlight><br />
ENTÃO? O que se pode concluir? É uma entrega direta ou indireta? <br />
</li><br />
<li> Uma curiosidade. Tente observar o tráfego na interface eth0 do Roteador R1. É possível observar algo? O que se pode concluir? Pare agora o ping e os tcpdumps executados.<br />
</li><br />
<li> Qualquer máquina IP acaba tomando uma decisão de roteamento. O PC1, ao observar que PC2 está na sua própria rede 10.10.10.0/24, entrega diretamente o pacote. E se PC1 tentar entregar para PC3? Faça um ping e observe o que acontece:<br />
<code>root@pc1:~#ping 20.20.20.1</syntaxhighlight><br />
Não deve ter funcionado :-(<br />
Um primeiro problema é que simplesmente a camada IP observa que o endereço não é entrega DIRETA mas não tem informação (linha) na tabela de roteamento dizendo para quem deve ser entregue o pacote. <br />
</li><br />
<li> Vamos acrescentar uma linha na tabela de PC1 dizendo como fazer esta entrega INDIRETA. Usaremos o conceito de gateway default. Ou seja, se não tiver para quem entregar explicitamente, o pacote será entregue para o gateway default:<br />
<code>root@pc1:~# route add default gateway 10.10.10.254</syntaxhighlight><br />
confira o estabelocimento da rota:<br />
<code>root@pc1:~# route -n</syntaxhighlight><br />
tente o ping novamente escutando com o tcpdump na interface eth0 de R1. Ainda não funcionou mas o R1 já recebe os pacotes. Confira o MAC de destino do pacote. Deve ser o MAC do roteador. <br />
</li> <br />
<li><br />
POR QUE NÃO FUNCIONOU: será que R1 não sabe como entregar o pacote para PC3? Confira se o pacote sai de R1 na rede lan1:<br />
<code>root@r1:~# tcpdump -i eth2 -e</syntaxhighlight><br />
</li> <br />
<li><br />
Temos um problema ainda que o nosso roteador Linux NÃO está habilitado a ser roteador. Isto pode ser feito com:<br />
<code>echo 1 > /proc/sys/net/ipv4/ip_forward</syntaxhighlight><br />
</li> <br />
<li> Tente novamente o ping de PC1 para PC3. Ainda não funcionará mas escute a interface eth1 de R1 e a interface eth0 de PC3 e verá que os pacotes do ICMP REQUEST estão chegando. Confira inclusive os MACs envolvidos...<br />
</li><br />
<li><br />
O que estaria faltando ainda para que PC3 responda aos ECHO REQUEST? O problema é de entrega indireta. O PC3 não sabe como entregar pacotes "externos". Acrescente um gateway default.<br />
</li><br />
<li><br />
Exercício adicional com 2 roteadores. Ver manual:<br />
* [http://linux-ip.net/html Guia de Administração da Camada IP no Linux<br />
</li><br />
</ol><br />
<br />
==Exercício: acrescentando uma lan2 com com 2 PCs no roteador==<br />
<br />
Acrescente uma rede 30.30.30.0/24 (lan2) no roteador R1. Acrescente 2 PCs e configure o sistema.<br />
Teste a conectividade entre todos os PCs.<br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
pc5[type]=generic<br />
pc6[type]=generic<br />
<br />
pc7[type]=generic<br />
pc8[type]=generic<br />
<br />
<br />
#Definição da Topologia da Rede<br />
<br />
pc1[eth0]=lan0:ip=10.10.10.1/24<br />
pc1[default_gateway]=10.10.10.254<br />
<br />
pc2[eth0]=lan0:ip=10.10.10.2/24<br />
pc2[default_gateway]=10.10.10.254<br />
<br />
pc3[eth0]=lan1:ip=20.20.20.1/24<br />
pc3[default_gateway]=20.20.20.254<br />
<br />
pc4[eth0]=lan1:ip=20.20.20.2/24<br />
pc4[default_gateway]=20.20.20.254<br />
<br />
pc5[eth0]=lan2:ip=30.30.30.1/24<br />
pc5[default_gateway]=30.30.30.254<br />
<br />
pc6[eth0]=lan2:ip=30.30.30.2/24<br />
pc6[default_gateway]=30.30.30.254<br />
<br />
pc7[eth0]=lan4:ip=40.40.40.1/24<br />
pc7[default_gateway]=40.40.40.254<br />
<br />
pc8[eth0]=lan3:ip=50.50.50.1/24<br />
pc8[default_gateway]=40.40.40.254<br />
<br />
<br />
r1[eth0]=lan0:ip=10.10.10.254/24<br />
r1[eth1]=lan1:ip=20.20.20.254/24<br />
r1[eth2]=lan2:ip=30.30.30.254/24<br />
r1[eth3]=lan3:ip=50.50.50.253/24<br />
r2[eth1]=lan3:ip=50.50.50.254/24<br />
r2[eth0]=lan4:ip=40.40.40.254/24<br />
<br />
r2[route]=10.10.10.0/24:gateway=50.50.50.253<br />
<br />
</syntaxhighlight><br />
<br />
=AULA 15 - Dia 7/05/2019=<br />
<br />
*Hubs X Switches. O Papel do Protocolo ARP<br />
<br />
<br />
*Serviço DHCP e NAT<br />
[-] Laboratório 16 - Sub-redes e Roteamento Estático em Redes <br />
<br />
==Hubs, Switches. Protocolo ARP==<br />
<br />
[Laboratório 17 - Tecnologia de Enlace Ethernet]<br />
<br />
==Serviço DHCP==<br />
<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IP_DHCP_NAT.pdf DHCP e NAT]<br />
<br />
Construir uma rede simular a aula anterior mas deixar PC1 e PC2 desconfigurados. Criar uma máquina para atuar como servidor DHCP. <br />
<br />
<ol><br />
<li><br />
Editar o arquivo de configuração do dhcp server:<br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=gateway #já habilitado para forward<br />
<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
pcdhcp[type]=generic<br />
<br />
<br />
#Definição da Topologia da Rede<br />
<br />
pc1[eth0]=lan0 #desconfigurada...<br />
<br />
pc2[eth0]=lan0:ip=10.10.10.2/24<br />
pc2[default_gateway]=10.10.10.254<br />
<br />
pcdhcp[eth0]=lan0:ip=10.10.10.3/24<br />
pcdhcp[default_gateway]=10.10.10.254 <br />
<br />
pc3[eth0]=lan1:ip=20.20.20.1/24<br />
pc3[default_gateway]=20.20.20.254<br />
<br />
pc4[eth0]=lan1:ip=20.20.20.2/24<br />
pc4[default_gateway]=20.20.20.254<br />
<br />
<br />
r1[eth0]=lan0:ip=10.10.10.254/24<br />
r1[eth1]=lan1:ip=20.20.20.254/24<br />
<br />
</syntaxhighlight><br />
</li><br />
<li> No server estabelecer a configuração desejada:<br />
<br />
nano /etc/dhcp/dhcpd.conf<br />
<br />
com:<br />
<br />
<code><br />
<br />
subnet 10.10.10.0 netmask 255.255.255.0 {<br />
range 10.10.10.10 10.10.10.50;<br />
option routers 10.10.10.254;<br />
option broadcast-address 10.10.10.255;<br />
default-lease-time 600;<br />
max-lease-time 7200;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
</li><br />
<li><br />
Rodar o servidor DHCP na máquina pc_dhcp:<br />
<code><br />
/usr/sbin/dhcpd -q -4 -pf /run/dhcp-server/dhcpd.pid -cf /etc/dhcp/dhcpd.conf eth0<br />
</syntaxhighlight><br />
</li><br />
<li><br />
No cliente (PC1) fazer:<br />
<code><br />
dhclient -v eth0<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Usando o ifconfig e route confira se o PC1 está completamente configurado. Faça teste com o ping<br />
</li><br />
<li> Rode o tcpdump na eth0 de r1 para "verificar" os pacotes DHCP:<br />
<code><br />
tcpdump -i eth0<br />
</syntaxhighlight><br />
</li><br />
<li> Repetir a operação no PC2. Baixe a interface antes:<br />
<code><br />
ifconfig eth0 down<br />
dhclient -v eth0<br />
</syntaxhighlight><br />
</li><br />
</ol><br />
<br />
==O NAT==<br />
<br />
Vamos tentar elaborar um laboratório usando o NAT MASQUERADE<br />
https://www.karlrupp.net/en/computer/nat_tutorial<br />
<br />
Construir uma rede com 3 LANs e 2 roteadores como na aula passada. Executar o APACHE em uma máquina da lan3 (exemplo PC4). Não colocar rotas para lan0 em r2. Desta forma PC1 não deve pingar em PC4. <br />
<br />
<code><br />
LAN0 <-R1-> LAN1 <-R2 -> LAN3<br />
</syntaxhighlight><br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
pc1[type]=generic<br />
apache[type]=generic<br />
<br />
<br />
pc1[eth0]=lan0:ip=10.10.10.1/24<br />
pc1[default_gateway]=10.10.10.254<br />
<br />
<br />
r1[eth0]=lan0:ip=10.10.10.254/24<br />
r1[eth1]=lan1:ip=20.20.20.254/24<br />
r1[route]=30.30.30.0/24:gateway=20.20.20.253<br />
<br />
r2[eth0]=lan1:ip=20.20.20.253/24<br />
r2[eth1]=lan2:ip=30.30.30.254/24<br />
<br />
apache[eth0]=lan2:ip=30.30.30.1/24<br />
apache[default_gateway]=30.30.30.254<br />
</syntaxhighlight><br />
<br />
<ol><br />
<li> Rodar o apache em PC4:<br />
<code> /etc/init.d/apache2 start </syntaxhighlight><br />
</li><br />
<li> Testar se o Apache é acessível a partir de PC3<br />
<code>lynx END_PC3 </syntaxhighlight><br />
<li><br />
Em R1 fazer:<br />
<code>iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE</syntaxhighlight><br />
</li><br />
<li> Monitorar os pacotes que chegam e saem da eth0 de PC4.<br />
</li><br />
<li> Fazer em PC1:<br />
lynx END_PC4 #endereço de PC4.<br />
O que se pode concluir?<br />
</li><br />
<br />
</ol><br />
<br />
=AULA 16 - Dia 09/05/2019=<br />
*Endereçamento IPv4.<br />
*Exercícios segmentação Redes. <br />
<br />
===Objetivos===<br />
*Compreender endereçamento IPv4.<br />
*Compreender o processo de alocação de faixas de IPs.<br />
*Compreender e manipular os números IPs.<br />
*Compreender e manipular as máscaras de rede.<br />
*Proporcionar ao aluno uma visão prática de roteamento IP.<br />
<br />
===Fonte Básica===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IP_DHCP_NAT.pdf DHCP e NAT]<br />
*[http://www.davidc.net/sites/default/subnets/subnets.html Cálculo de sub-redes]<br />
<br />
===Roteiro===<br />
<br />
#Baseado no arquivo exemplo abaixo, crie um arquivo de configuração para o NetKit que implemente sua proposta. O arquivo deve contemplar todas as configurações necessárias para o perfeito funcionamento da rede, ou seja, ao carregar o arquivo todos os hosts deverão ser capazes de "pingar" uma ao outro. <br />
##Faça testes de conectividade entre os hosts.<br />
##Demonstre para o professor o perfeito funcionamento de sua rede.<br />
*O arquivo de configuração do Netkit abaixo, é a definição para o funcionamento da simulação da rede apresentada na Figura 2. Falta adicionar as rotas.<br />
<br />
[[Arquivo:DynamicRoutingTriangle.png |thumb | 400px| Figura 2 - Rede exemplo]]<br />
<br />
<code><br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=link0:ip=192.168.0.1/24<br />
pc2[eth0]=link1:ip=192.168.1.1/24<br />
pc3[eth0]=link2:ip=192.168.2.1/24<br />
<br />
# Default gateways definitions<br />
pc1[default_gateway]=192.168.0.254<br />
pc2[default_gateway]=192.168.1.254<br />
pc3[default_gateway]=192.168.2.254<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
r3[type]=gateway<br />
<br />
# Routers' interfaces to local networks<br />
r1[eth0]=link0:ip=192.168.0.254/24<br />
r2[eth0]=link1:ip=192.168.1.254/24<br />
r3[eth0]=link2:ip=192.168.2.254/24<br />
<br />
# Network "backbone" links<br />
r1[eth1]=backbone0:ip=10.0.0.1/30<br />
r1[eth2]=backbone1:ip=10.0.1.1/30<br />
<br />
r2[eth1]=backbone0:ip=10.0.0.2/30<br />
r2[eth2]=backbone2:ip=10.0.2.1/30<br />
<br />
r3[eth1]=backbone1:ip=10.0.1.2/30<br />
r3[eth2]=backbone2:ip=10.0.2.2/30 <br />
<br />
# Routes definition<br />
r1[route]=192.168.2.0/24:gateway=10.0.1.2<br />
r1[route]=192.168.1.0/24:gateway=10.0.0.2<br />
r1[route]=10.0.2.0/30:gateway=10.0.0.2<br />
<br />
r2[route]=192.168.0.0/24:gateway=10.0.0.1 <br />
r2[route]=192.168.2.0/24:gateway=10.0.2.2<br />
r2[route]=10.0.1.0/30:gateway=10.0.2.2<br />
<br />
r3[route]=192.168.0.0/24:gateway=10.0.1.1<br />
r3[route]=192.168.1.0/24:gateway=10.0.2.1<br />
r3[route]=10.0.0.0/30:gateway=10.0.2.1<br />
</syntaxhighlight><br />
<br />
===Exercícios Extras (resolvidos)===<br />
*[[Arquivo:exercicios_CIDR.pdf]]<br />
<br />
===Referencia===<br />
*[http://www.davidc.net/sites/default/subnets/subnets.html Link Calculador Online de Subnets]<br />
<br />
=AULA 17 - Dia 14/05/2019=<br />
<br />
*Finalização do Laboratório do NAT<br />
*Laboratório de Introdução ao IPV6<br />
*Introdução ao Access Point TPLINK N750: configuração da LAN e WAN<br />
<br />
==LAboratório de Introdução ao IPv6==<br />
<br />
===Material de REferência===<br />
<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/IPv6.pdf IPv6]<br />
<br />
===Roteiro de atividades sobre o IPv6===<br />
<br />
A figura abaixo apresenta o diagrama esquemático da rede a ser montada/analisada. Observe que todos os IPv6 ''Global Unicast'' já estão definidos na mesma, são esses IPs que utilizaremos em nosso experimento.<br />
<br />
[[Arquivo:Diagrama_rede_IPv6.jpg]]<br />
<br />
#Crie em seu computador um arquivo com nome '''/home/aluno/IPv6.conf''', com o seguinte conteúdo: <syntaxhighlight lang=bash><br />
#Ligacao das maquinas nos dominios de colisao<br />
#Duas pequenas redes interligadas pelo backbone<br />
<br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=link0:ipv6=2001:bcc:faca:1::101/64<br />
pc2[eth0]=link1:ipv6=2001:bcc:cafe:1::102/64<br />
pc3[eth0]=HUB1:ipv6=2001:bcc:1f0:1::103/64<br />
pc4[eth0]=HUB1<br />
<br />
#Default Gateways definitions<br />
pc1[route]=default6:gateway=2001:bcc:faca:1::1<br />
pc2[route]=default6:gateway=2001:bcc:cafe:1::1<br />
pc3[route]=default6:gateway=2001:bcc:1f0:1::1<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
#Routers interfaces definitions<br />
r1[eth0]=backbone0:ipv6=2001:db8:dead:1::1/64<br />
r1[eth1]=link0:ipv6=2001:bcc:faca:1::1/64<br />
r1[eth2]=link1:ipv6=2001:bcc:cafe:1::1/64<br />
<br />
r2[eth0]=backbone0:ipv6=2001:db8:dead:1::2/64<br />
r2[eth1]=HUB1:ipv6=2001:bcc:1f0:1::1/64<br />
<br />
#Routers definitions<br />
r1[route]=2001:bcc:1f0:1::0/64:gateway=2001:db8:dead:1::2<br />
r2[route]=2001:bcc:faca:1::0/64:gateway=2001:db8:dead:1::1<br />
r2[route]=2001:bcc:cafe:1::0/64:gateway=2001:db8:dead:1::1<br />
</syntaxhighlight><br />
#Tenha certeza que o Netkit2 estja atualizado: General >> Update.<br />
#Rode o NetKit em seu computador. Em um terminal digite: <syntaxhighlight lang=bash><br />
netkit2 & </syntaxhighlight><br />
#No menu '''File''' - '''Load and Run''', procure o arquivo '''/home/aluno/IPv6.conf''' e clique em OK. Abrirá uma janela com 6 abas, onde cada uma delas é um terminal de configuração do respectivo equipamento: '''pc1-4''' ou '''r1-2'''.<br />
#Observe que o '''pc4''' não está com sua interface configurada.<br />
#Ao clicar no menu '''File''' - '''Graph''', pode-se ter uma visão da rede a ser simulada e conferir se é equivalente ao diagrama proposto.<br />
#Faça um '''ping6''' entre o '''pc1''' ao '''pc3''': <syntaxhighlight lang=bash><br />
ping6 -c4 2001:bcc:1f0:1::103 </syntaxhighlight><br />
#Faça um '''ping6''' entre o '''pc1''' e '''pc2'''.<br />
#No '''pc4''' use o seguinte comando para adicionar o endereço IPv6 à interface de rede: <syntaxhighlight lang=bash><br />
ip addr add 2001:bcc:1f0:1::104/64 dev eth0 </syntaxhighlight><br />
#No '''pc4''', acrescente o ''default gateway'' com o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add default via 2001:bcc:1f0:1::1 dev eth0 </syntaxhighlight><br />
#No '''pc1''' use o seguinte comando para verificar como ficou a configuração dos endereços da interface de rede. O resultado é similar ao apresentado pelo comando '''ifconfig''': <syntaxhighlight lang=bash><br />
ip addr show dev eth0 </syntaxhighlight><br />
#Todo o roteamento está pronto, mas caso desejássemos poderíamos acrescentar rotas com comando similares aos já utilizados. Por exemplo, no '''r1''', para adicionar uma rota estática para a rede dos '''pc3''' e '''pc4''' utilizaríamos o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add 2001:bcc:1f0:1::/64 via 2001:db8:dead:1::2 dev eth0 </syntaxhighlight><br />
#Confira as rotas estabelecidas em todos os ''hosts'' com o comando abaixo. <br />
##São coerentes com os dados apresentados no diagrama acima?<syntaxhighlight lang=bash><br />
ip -6 route show </syntaxhighlight><br />
#No '''pc1''' use os seguintes comandos para ver a rota para alguns vizinhos: <syntaxhighlight lang=bash><br />
traceroute6 2001:bcc:1f0:1::103<br />
traceroute6 2001:bcc:1f0:1::104 </syntaxhighlight><br />
#*Anote as rotas.<br />
#Deixe um '''ping6''' entre o '''pc1''' ao '''pc3''' rodando: <syntaxhighlight lang=bash><br />
ping6 2001:bcc:1f0:1::103 </syntaxhighlight><br />
<br />
==Introdução ao Roteador-AP da TP-Link==<br />
<br />
Ver manual https://www.tp-link.com/us/support/download/tl-wdr4300/<br />
<br />
===Configuração Básica===<br />
<br />
Seguir as instruções do professor para a seguinte configuração:<br />
<br />
#Retirar o plugue cabo ethernet que liga o PC do Lab a rede do IFSC. Conectar o PC a uma das portas LAN do AP;<br />
#Conectar a WAN do AP ao Lab. do IFSC;<br />
#Em um terminal do PC aplique o comando:<br />
sudo dhclient eth0<br />
#No browser do PC acesse o AP colocando o endereço:<br />
http://tplinklogin.net<br />
#Entrar com user admin e senha admin<br />
#Configurar a WAN para DHCP (IP dinâmico)<br />
#Configurar a LAN para DHCP na faixa 192.168.0.10 a 192.168.0.100<br />
#Usar uma máquina virtual para testar a aquisição do IP:<br />
pc1[type]=generic<br />
pc1[eth0]=uplink:bridge=eth0<br />
<br />
DESAFIO 1: Elabore um experimento para mostrar que a LAN do AP funciona como um switch.<br />
Sugestão: Use uma máquina adicional colocada em uma porta do AP.<br />
<br />
DESAFIO 2: Elabore um experimento para mostrar como o NAT funciona no AP. Se inspire no experimento realizado sobre o NAT.<br />
<br />
=AULA 18 - Dia 16/05/2019=<br />
<br />
==Objetivos==<br />
<br />
<br />
PARTE 0 - Exercício de Revisão<br />
<br />
PARTE 1 - Serviços de rede sobre o Linux<br />
<br />
*serviço SSH no Linux<br />
<br />
PARTE 2 - Acesso a rede WIFI<br />
<br />
*conceitos básicos de redes sem fio: pg.103 de [https://pt.scribd.com/document/48655010/Formacao-de-Suporte-Tecnico-Proinfo]<br />
*configuração da WIFI no Access Point e Acesso via Linux<br />
<br />
===PARTE 0===<br />
<br />
Considere a rede abaixo definida pelo arquivo do netkit. Configure as redes com os seguintes prefixos:<br />
<br />
*lan0: 50.50.50.0/24<br />
*lan1: 60.60.60.0/24<br />
*lan2: 70.70.70.0/24<br />
<br />
O pc2dhcp deve ser configurado como servidor DHCP e deverá liberar IPs na faixa de 50.50.50.100/24 a 50.50.50.200/24. Todos os PCs receberão IP estáticos com exceção do PC1 que deverá receber dinamicamente o endereço. Toda a configuração deve ser realizada manualmente.<br />
<br />
Teste a conectividade entre todos os PCs. Usando o tcpdump demonstre que quando PC2 faz um ping em PC4 a entrega será indireta. Demonstre usando o MAC address das máquinas como apoio. Chame o professor para demonstrar.<br />
<br />
ALGUNS COMANDOS NOTÁVEIS:<br />
<br />
ifconfig<br />
ifconfig eth0 10.10.10.1/24<br />
route -n<br />
route add default gw 200.10.1.254<br />
route del -net 200.10.1.0/24 gw 200.10.2.1<br />
route add -net 200.10.1.0/24 gw 200.10.2.1<br />
<br />
tcpdump -i eth1 -n -e<br />
<br />
<code><br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2dhcp[type]=generic<br />
<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=lan0<br />
pc2dhcp[eth0]=lan0<br />
<br />
pc3[eth0]=lan1<br />
<br />
pc4[eth0]=lan2<br />
<br />
r1[eth0]=lan0<br />
r1[eth1]=lan1<br />
<br />
r2[eth0]=lan1<br />
r2[eth1]=lan2<br />
</syntaxhighlight><br />
<br />
Solução:<br />
R1:<br />
ifconfig eth0 50.50.50.254/24<br />
ifconfig eth1 60.60.60.254/24<br />
route add -net 70.70.70.0/254 gw 60.60.60.253<br />
R2:<br />
ifconfig eth1 70.70.70.254/24<br />
ifconfig eth0 60.60.60.253/24<br />
route add -net 50.50.50.0/24 gw 60.60.60.254<br />
PC2DHCP:<br />
ifconfig eth0 50.50.50.2/24<br />
route add default gateway 50.50.50.254<br />
configurar server: nano /etc/dhcp/dhcpd.conf<br />
# A slightly different configuration for an internal subnet.<br />
subnet 50.50.50.0 netmask 255.255.255.0 {<br />
range 50.50.50.100 50.50.50.200;<br />
# option domain-name-servers ns1.internal.example.org;<br />
# option domain-name "internal.example.org";<br />
option routers 50.50.50.254;<br />
option broadcast-address 50.50.50.255;<br />
default-lease-time 600;<br />
max-lease-time 7200;<br />
}<br />
<br />
/usr/sbin/dhcpd -q -4 -pf /run/dhcp-server/dhcpd.pid -cf /etc/dhcp/dhcpd.conf eth0<br />
PC3:<br />
ifconfig eth0 60.60.60.1/24<br />
route add default gw 60.60.60.254 #note que poderia ser para o outro roteador (R2)<br />
PC4:<br />
ifconfig eth0 70.70.70.1/24<br />
route add default gw 70.70.70.254<br />
PC1:<br />
dhclient eth0 -v<br />
<br />
==Serviço SSH==<br />
<br />
O Serviço SSH se utiliza do modelo cliente-servidor. Deve-se executar um servidora ssh na máquina que permitirá o acesso remoto.<br />
Um cliente a partir de uma outra máquina poderá logar remotamente usando um cliente ssh ou poderá fazer outras operações, tipo cópia remota<br />
de arquivos.<br />
<br />
===ETAPA 1 - Rodando o servidor SSH===<br />
*Baseado no Material do Prof.Odilson Valle<br />
<br />
No Ubuntu server:<br />
<ol><br />
<li><br />
<code>sudo su</syntaxhighlight><br />
<code>apt-get update</syntaxhighlight><br />
<code>apt-get install ssh</syntaxhighlight> O SSH já estará funcionando normalmente.<br />
Para configurações extras deve-se editar o arquivo /etc/ssh/sshd_config e acrescentar, por exemplo:<br />
*X11Forwarding yes (no) ### habilita/desabilita acesso com ambiente gráfico remoto<br />
*AllowUsers Fred Wilma ### Libera o acesso somente para os usuários Fred e Wilma<br />
*DenyUsers Dino Pebbles ### Bloqueia o acesso aos usuários Dino e Pebbles e libera para os demais usuários<br />
*AllowGroups admin ### Libera o acesso somente para o grupo admin.<br />
</li><br />
<li><br />
Após modificar o arquivo de configuração deve-se reiniciar o serviço: <code>service ssh restart</syntaxhighlight><br />
</li><br />
<li><br />
Criar um usuário na máquina servidora:<br />
<code>adduser alien</syntaxhighlight><br />
</li><br />
<li><br />
Logar como alien:<br />
<code>su alien</syntaxhighlight><br />
</li><br />
</ol><br />
<br />
===ETAPA 2 - Logando remotamente===<br />
<br />
<ol><br />
<li><br />
Para acessar o servidor basta digitar em um terminal: <br />
<code>ssh alien@ip_do_servidor. </syntaxhighlight> Será solicitado a senha.<br />
</li><br />
<li><br />
Confira que está "dentro" da máquina remota:<code>hostname</syntaxhighlight><br />
</li><br />
<li><br />
Confira os arquivos do diretório corrente:<code>ls -l</syntaxhighlight><br />
</li><br />
</ol><br />
<br />
<br />
===ETAPA 3 - Cópia Remota de aquivos===<br />
<br />
#Na máquina hospedeira/cliente, EM OUTRO TERMINAL, criar um arquivo qualquer usando um editor de texto:<code>gedit teste.txt &</syntaxhighlight><br />
#Envie o arquivo para a máquina servidora: <code>scp teste.txt alien@IP_MAQUINA_SERVIDORA:./</syntaxhighlight><br />
#No terminal onde está logado remotamente confira se o arquivo está copiado: <code>ls -l</syntaxhighlight><br />
#Mude o nome do arquivo: <code>mv teste.txt alfat.txt</syntaxhighlight><br />
#No terminal da máquina cliente traga novamente o arquivo: <code>scp alien@IP_MAQUINA_SERVIDORA:./alfa.txt .</syntaxhighlight><br />
#Confira se o arquivo foi copiado corretamente: <code>ls -l</syntaxhighlight><br />
<br />
==PARTE 2 - Configuração do Access Point na rede de 2.4Ghz==<br />
<br />
#Entrar na configuração do AP conforme aula anterior.<br />
#Conectara a WAN do AP na rede do laboratório e o PC em uma porta da LAN do AP.<br />
#Configurar a WAN para IP dinâmico.<br />
#Configurar a rede WIreless 2.4 Ghz:<br />
##Nome SSID: nome FIC-NomeAluno<br />
##Configurar canal AUTO e channel width para AUTO<br />
##Habilite o broadcast da rede.<br />
#Configurar segurança (Wireless Security) para WPA versão Automática, Criptografia AES e password ABCDEF<br />
#Configurar o DHCP na LAN para distribuir endereços entre 192.168.0.100 e 192.168.0.200<br />
#Salve as configurações<br />
#Reboote o roteador<br />
<br />
==Acessando a rede de dispostivo Celular==<br />
<br />
#Teste o acesso a rede a partir de um celular. No Androi ligue e desligue o wifi. Deve aparecer a lista de dispositivos.<br />
<br />
==Habilitando Filtros por MAC==<br />
<br />
*Na configuração da WLAN entre em Wireless MAC Filtering<br />
*Em Filtering Rules coloque Deny (negar)<br />
*Adicione um terminal que deseja bloquear o acesso. Utilize o MAC do seu celular (veja em configurações do telefone ou anote na opção Wireless Statistics)<br />
*Habilite o Filtro e tente se conectar<br />
<br />
OBS: Este filtro é interessante para ter maior segurança na rede, garantindo que somente dispositivos gabilitados possam acessá-la.<br />
<br />
==Coloque no ar a rede 5Ghz==<br />
<br />
Repita o procedimento da rede de 2.4Ghz e coloque-a no ar.<br />
<br />
Teste a conectividade com o celular.<br />
<br />
<br />
<br />
=AULA 19 - Dia 21/05/2019=<br />
<br />
==Objetivos==<br />
<br />
*Tópicos Adicionais sobre redes no Linux: Configuração Manual X NetworkManager<br />
**Opções de Acesso a Internet: ADSL, Cabo<br />
**Sistema de Arquivos em Rede: Samba Server<br />
*Relatório de Avaliação 1<br />
*Opções de Extensão da Rede Wireless<br />
<br />
==Tópicos Adicionais sobre redes no Linux==<br />
<br />
===Configuração da Rede no Linux - o NetworkManager===<br />
<br />
Ao longo do curso estudamos vários comandos para ver e modificar parâmetros de rede. Entretanto, em uma instalação padrão de um sistema Linux Ubuntu vamos verificar que existe um serviço de suporte a estas configurações que permite configurar interfaces graficamente e reconectar/escolher uma rede. Trata-se do NetworkManager. Ver alguns detalhes aqui [https://www.hardware.com.br/dicas/entendendo-networkmanager.html] e aqui[https://wiki.debian.org/pt_BR/NetworkManager]. Este serviço tenta fornecer a melhor conectividade possível usando as interfaces disponíveis. O serviço é composto por:<br />
<br />
*um processo do sistema (roda como serviço) monitorando constantemente as interfaces;<br />
*uma applet para interação com o usuário (canto direito da interface);<br />
<br />
O NetworkManager vai ignorar as configurações das interfaces realizadas em /etc/network/interfaces<br />
<br />
Teste o uso do NetworkManager. Clique no topo do desktop a direita e inspecione as interfaces disponíveis.<br />
<br />
Em algumas situações pode ser desejável desabilitar o NetworkManager. Na linha de comando pode ser executado:<br />
<br />
sudo service network-manager stop<br />
<br />
===Configurando interfaces de forma manual ===<br />
<br />
TEXTO baseado nas anotações do Prog.Marcelo Sobral:<br />
<br />
O arquivo ''/etc/network/interfaces'' contém declarações para configurar as interfaces de rede. Um exemplo de configuração básica contida nesse arquivo pode ser vista a seguir:<br />
<br />
<syntaxhighlight lang=text><br />
auto lo eth0<br />
iface lo inet loopback<br />
iface eth0 inet dhcp<br />
</syntaxhighlight><br />
<br />
Esse exemplo pode ser interpretado assim:<br />
* ''Linha 1'': declara que as interfaces ''lo'' e ''eth0'' devem ser ativadas automaticamente no boot. Se uma interface não aparecer em uma declaração como esta, então ela não será ativada. OBS: interface ativadas desta forma NÃO são controladas pelo ''NetworkManager''.<br />
* ''Linha 2'': configura a interface ''lo'' como sendo do tiupo ''loopback''. Essa é uma interface especial criada puramente em software (uma interface de rede virtual), usada para comunicação entre processos de um mesmo computador.<br />
* ''Linha 3'': configura a interface ''eth0'' de forma dinâmica usando [[GER-2010-1#DHCP|DHCP]]. A configuração de rede é solicitada usando a própria rede. Ness ecaso, deve existir algum equipamento ou computador nessa rede que seja um servidor DHCP, capaz de responder com uma mensagem contendo a configuração de rede a ser utilizada.<br />
<br />
<br />
O exemplo anterior é bastante simplificado, uma vez que a configuração de rede de fato é obtida dinamicamente com DHCP. Isso pode ser suficiente para computadores usados somente para acesso a Internet, mas não para computadores que sejam servidores. Nesse caso, é melhor definir uma configuração de rede estática, como mostrado a seguir:<br />
<br />
<syntaxhighlight lang=text><br />
auto lo eth0<br />
iface lo inet loopback<br />
iface eth0 inet static<br />
address 172.18.80.251<br />
netmask 255.255.128.0<br />
gateway 172.18.0.254<br />
dns-nameservers 191.36.8.2 191.36.8.3<br />
</syntaxhighlight><br />
<br />
<br />
A diferença em relação ao caso anterior está na declaração da interface ''eth0''. Ao invés de configurá-la com ''DHCP'', declararam-se todas as informações de rede. Assim, essa interface sempre será ativada com essas informações configuradas. No exemplo apresentado, as configurações de rede são:<br />
* ''address 172.18.80.251'': endereço IP da interface<br />
* ''netmask 255.255.128.0'': máscara de rede<br />
* ''gateway 172.18.0.254'': endereço do gateway (ou roteador ''default'')<br />
* ''dns-nameservers 191.36.8.2 191.36.8.3'': servidores DNS a serem utilizados (podem-se especificar um ou mais endereços IP)<br />
<br />
O [http://manpages.ubuntu.com/manpages/trusty/en/man5/interfaces.5.html manual do arquivo /etc/network/interfaces] apresenta muitos outros detalhes sobre possíveis configurações de rede.<br />
<br />
Antes da alteração de configuração de uma interface é interessante desativá-la:<br />
ifdown eth0<br />
Alterar o arquivo /etc/network/interfaces<br />
<br />
E na sequência ativá-la novamente:<br />
ifup eth0<br />
ou<br />
sudo /etc/init.d/networking restart<br />
<br />
O comando ifup vai consultar o arquivo e alterar as configurações. Indiretamente, o script networking também usa o ifup para ativar as configurações (e todas demais que forem realizadas).<br />
<br />
==Relatório Avaliativo 1==<br />
<br />
Criar um arquivo no OpenOffice nomeando-o SeuNomeSemEspaco-FICLinux-2019-A1<br />
<br />
Copiar e responder as questões abaixo:<br />
<br />
1.Faça um ifconfig na interface eth0. Cole um recorte da tela no espaço abaixo e faça um texto indicando qual o endereço de hardware associado a esta interface, qual o endereço IPv4 e qual a máscara de subrede.<br />
<br />
<br />
2.Faça um experimento usando o ping e o wireshark mostrando como o DNS atua para resolver o nome que está sendo "pingando". Informe em texto abaixo qual o IP do servidor DNS local e qual o IP do site que está sendo "pingado".<br />
<br />
<br />
3,Execute o laboratório do Netkit da forma e cole abaixo a figura da rede fornecida pelo netkit:<br />
<code><br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
<br />
# Hosts' interfaces to local routers<br />
<br />
r1[eth0]=lan0<br />
r1[eth1]=lan1<br />
<br />
pc1[eth0]=lan0<br />
pc2[eth0]=lan0<br />
pc3[eth0]=lan1<br />
</syntaxhighlight><br />
<br />
<br />
4.Configure todas as interfaces dos PC usando para lan0 o prefixo 50.50.50.0/24 e para lan1 use no lugar de 50 o dia de seu nascimento.<br />
Cole uma tela mostrando PC1 pingando PC3. <br />
<br />
5.Informe abaixo o MAC da eth0 do roteador.<br />
<br />
6.Usando o tcpdump na eth0 do roteador mostre que a entrega é indireta.<br />
<br />
==Estendendo a rede através da LAN usando segundo AP e WAN==<br />
<br />
Conecte um segundo AP (WAN do segundo AP a LAN do primeiro AP). Teste a conectividade colocando uma máquina Linux na LAN do segundo AP.<br />
Esta configuração deve funcionar mas impõe um overhead adicional devido ao NAT realizado duas vezes... <br />
<br />
DESAFIO: mostrar que o NAT está sendo duplicado.<br />
<br />
[[Arquivo:WLAN-2PAs-viaWAN.png]]<br />
<br />
==Estendendo a rede através da LAN usando segundo AP e LAN==<br />
<br />
Discuta com o colega ao lado e pense como poderia conectar o segundo AP via LAN. Uma configuração adicional será necessária.<br />
<br />
==Estendendo a rede através do Wireless (WDS)==<br />
<br />
Estude no manual como poderia estender a rede Sem Fio usando conexão via WDS.<br />
<br />
=AULA 20 - Dia 18/04/2019=<br />
<br />
*Tópicos Adicionais sobre redes no Linux:<br />
**Opções de Acesso a Internet: ADSL, Cabo<br />
**Sistema de Arquivos em Rede: Samba Server (http://www.guiafoca.org/cgs/guia/avancado/ch-s-samba.html)<br />
*Relatório Avaliativo 2<br />
<br />
==Relatório Avaliativo==<br />
<br />
===PARTE 1=== <br />
<br />
Usando a configuração abaixo do netkit2 e uma máquina Virtualbox devidamente configurada implementar a configuração abaixo:<br />
<br />
ATENÇÂO: Vamos substituir a VirtualBox por uma máquina Netkit executada em OUTRO PC com a configuração:<br />
<br />
INSTRUÇÔES para virtual box:<br />
*colocar rede como bridge<br />
*desabilitar o network manager<br />
sudo service network-manager stop<br />
*baixar a interface<br />
sudo ifconfig enp0s3 down<br />
*reconfigurar a interface (usar o endereço do seu grupo)<br />
sudo ifconfig enp0s3 50.50.50.11/24<br />
*colocar a rota direta (que se perdeu) (usar o endereço do seu grupo)<br />
sudo route add -net 50.50.50.0/24 dev enp0s3<br />
*colocar gateway default (usar o endereço do seu grupo)<br />
sudo route add default gateway 50.50.50.1<br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
<br />
pc1[type]=generic<br />
pc1[eth0]=uplink:bridge=eth0:ip=dhcp<br />
<br />
</syntaxhighlight><br />
<br />
<br />
[[Arquivo:Aval2-Parte1-FICLinux2019-2.png]]<br />
<br />
<code><br />
#Descrição das Máquinas e Roteadores<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
pc1[type]=generic<br />
<br />
pc1[eth0]=lan1<br />
<br />
r1[eth0]=uplink:bridge=eth0:ip=VER COM PROFESSOR<br />
r1[eth1]=lan2<br />
<br />
r2[eth0]=lan1<br />
r2[eth1]=lan2<br />
</syntaxhighlight><br />
<br />
Construir um doc conforme aula anterior com as seguintes informações:<br />
<br />
#Coloque a tela de um píng funcionando de R1 para PC1<br />
#Cole a tela da tabela de roteamento de R2<br />
#Cole a tela de um ping de uma máquina VirtualBox (netkit) no R1 (uplink)<br />
#Cole a tela de um ping funcionando uma máquina VirtualBox (netkit) no PC1<br />
<br />
Note que o gateway default da máquina virtual deverá ser reconfigurado para PC1.<br />
<br />
ADENDO: Coloque em R1 rotas para as redes dos PC1 dos demais grupos.<br />
<br />
===PARTE 2===<br />
<br />
Acrescente na sua rede um AP configurado como indicado abaixo:<br />
<br />
OBS: Para este exercício configuramos estaticamente todos os endereços para o lado do backbone (Laboratório). Usamos 50.50.50.0/24<br />
<br />
[[Arquivo:Aval2-Parte2-FICLinux2019-2.png]]<br />
<br />
<br />
=ATIVIDADE DE RECUPERAÇÃO 1=<br />
<br />
Refazer o relatório Avaliativo 1 proposto anteriormente. Enviar doc para o SIGA A<br />
<br />
=ATIVIDADE DE RECUPERAÇÃO 2=<br />
<br />
Registre em um DOC e faça um post no SIGA A colando a imagem das telas das saídas de cada comando!<br />
<br />
===Roteiro de atividades sobre o IPv6===<br />
<br />
A figura abaixo apresenta o diagrama esquemático da rede a ser montada/analisada. Observe que todos os IPv6 ''Global Unicast'' já estão definidos na mesma, são esses IPs que utilizaremos em nosso experimento.<br />
<br />
[[Arquivo:Diagrama_rede_IPv6.jpg]]<br />
<br />
#Crie em seu computador um arquivo com nome '''/home/aluno/IPv6.conf''', com o seguinte conteúdo: <syntaxhighlight lang=bash><br />
#Ligacao das maquinas nos dominios de colisao<br />
#Duas pequenas redes interligadas pelo backbone<br />
<br />
# Hosts definitions<br />
pc1[type]=generic<br />
pc2[type]=generic<br />
pc3[type]=generic<br />
pc4[type]=generic<br />
<br />
# Hosts' interfaces to local routers<br />
pc1[eth0]=link0:ipv6=2001:bcc:faca:1::101/64<br />
pc2[eth0]=link1:ipv6=2001:bcc:cafe:1::102/64<br />
pc3[eth0]=HUB1:ipv6=2001:bcc:1f0:1::103/64<br />
pc4[eth0]=HUB1<br />
<br />
#Default Gateways definitions<br />
pc1[route]=default6:gateway=2001:bcc:faca:1::1<br />
pc2[route]=default6:gateway=2001:bcc:cafe:1::1<br />
pc3[route]=default6:gateway=2001:bcc:1f0:1::1<br />
<br />
# Routers definitions<br />
r1[type]=gateway<br />
r2[type]=gateway<br />
<br />
#Routers interfaces definitions<br />
r1[eth0]=backbone0:ipv6=2001:db8:dead:1::1/64<br />
r1[eth1]=link0:ipv6=2001:bcc:faca:1::1/64<br />
r1[eth2]=link1:ipv6=2001:bcc:cafe:1::1/64<br />
<br />
r2[eth0]=backbone0:ipv6=2001:db8:dead:1::2/64<br />
r2[eth1]=HUB1:ipv6=2001:bcc:1f0:1::1/64<br />
<br />
#Routers definitions<br />
r1[route]=2001:bcc:1f0:1::0/64:gateway=2001:db8:dead:1::2<br />
r2[route]=2001:bcc:faca:1::0/64:gateway=2001:db8:dead:1::1<br />
r2[route]=2001:bcc:cafe:1::0/64:gateway=2001:db8:dead:1::1<br />
</syntaxhighlight><br />
#Tenha certeza que o Netkit2 estja atualizado: General >> Update.<br />
#Rode o NetKit em seu computador. Em um terminal digite: <syntaxhighlight lang=bash><br />
netkit2 & </syntaxhighlight><br />
#No menu '''File''' - '''Load and Run''', procure o arquivo '''/home/aluno/IPv6.conf''' e clique em OK. Abrirá uma janela com 6 abas, onde cada uma delas é um terminal de configuração do respectivo equipamento: '''pc1-4''' ou '''r1-2'''.<br />
#Observe que o '''pc4''' não está com sua interface configurada.<br />
#Ao clicar no menu '''File''' - '''Graph''', pode-se ter uma visão da rede a ser simulada e conferir se é equivalente ao diagrama proposto.<br />
#Faça um '''ping6''' entre o '''pc1''' ao '''pc3''': <syntaxhighlight lang=bash><br />
ping6 -c4 2001:bcc:1f0:1::103 </syntaxhighlight><br />
#Faça um '''ping6''' entre o '''pc1''' e '''pc2'''.<br />
#No '''pc4''' use o seguinte comando para adicionar o endereço IPv6 à interface de rede: <syntaxhighlight lang=bash><br />
ip addr add 2001:bcc:1f0:1::104/64 dev eth0 </syntaxhighlight><br />
#No '''pc4''', acrescente o ''default gateway'' com o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add default via 2001:bcc:1f0:1::1 dev eth0 </syntaxhighlight><br />
#No '''pc1''' use o seguinte comando para verificar como ficou a configuração dos endereços da interface de rede. O resultado é similar ao apresentado pelo comando '''ifconfig''': <syntaxhighlight lang=bash><br />
ip addr show dev eth0 </syntaxhighlight><br />
#Todo o roteamento está pronto, mas caso desejássemos poderíamos acrescentar rotas com comando similares aos já utilizados. Por exemplo, no '''r1''', para adicionar uma rota estática para a rede dos '''pc3''' e '''pc4''' utilizaríamos o seguinte comando: <syntaxhighlight lang=bash><br />
ip -6 route add 2001:bcc:1f0:1::/64 via 2001:db8:dead:1::2 dev eth0 </syntaxhighlight><br />
#Confira as rotas estabelecidas em todos os ''hosts'' com o comando abaixo. <br />
##São coerentes com os dados apresentados no diagrama acima?<syntaxhighlight lang=bash><br />
ip -6 route show </syntaxhighlight><br />
#No '''pc1''' use os seguintes comandos para ver a rota para alguns vizinhos: <syntaxhighlight lang=bash><br />
traceroute6 2001:bcc:1f0:1::103<br />
traceroute6 2001:bcc:1f0:1::104 </syntaxhighlight><br />
#*Anote as rotas.<br />
#Deixe um '''ping6''' entre o '''pc1''' ao '''pc3''' rodando: <syntaxhighlight lang=bash><br />
ping6 2001:bcc:1f0:1::103 </syntaxhighlight><br />
<br />
=ATIVIDADE DE RECUPERAÇÃO 3=<br />
<br />
Registre em um DOC e faça um post no SIGA A colando a imagem das telas das saídas de cada comando! Coloque também a resposta as perguntas.<br />
<br />
===Objetivos===<br />
<br />
*Familiarizar-se com o UDP<br />
*Entender a estrutura do pacote UDP<br />
*Entender o conceito de portas<br />
<br />
===Fonte Base===<br />
*[http://docente.ifsc.edu.br/odilson/RCO60803/UDP%20Basico.pdf Introdução a camada de transporte e UDP básico]<br />
<br />
===Parte 1 - Fluxo único UDP===<br />
<br />
#Combinar equipes com dois computadores para execução do experimento.<br />
#*Uma equipe escutará na porta 5000 e a outra equipe transmitirá uma mensagem nessa porta. Os processos de transmissão e recepção podem ocorrer simultaneamente, em terminais distintos.<br />
#*Cada equipe deve identificar os IPs ('''IP_DEST''') das máquinas de seus pares.<br />
#Cada equipe deve abrir uma Janela de terminal.<br />
#Cada equipe deve preparar o '''Wireshark''', interfaces '''any''', para escuta das portas no protocolo UDP usando um filtro:<syntaxhighlight lang=bash><br />
udp.port==5000</syntaxhighlight><br />
#A equipe da escuta na porta 5000 executa no terminal: <syntaxhighlight lang=bash><br />
netcat -u -l -p 5000 </syntaxhighlight><br />
#A equipe que irá transmitir para a porta 5000 executa no terminal: <syntaxhighlight lang=bash><br />
netcat -u IP_DEST 5000 </syntaxhighlight><br />
#*Em seguida escreve no terminal uma mensagem de até 20 caracteres, ao teclar <Enter> a mensagem será enviada.<br />
#*O wireshark deve ter capturado os pacotes UDP <br />
#Identifique e anote os seguintes dados na captura do wireshark:<br />
#*IP FONTE e DESTINO<br />
#*PORTAS FONTE E DESTINO para ambas comunicações<br />
#*Campo de protocolo no pacote IP<br />
#*Campo de tamanho (anote o tamanho) e ''checksum'' no pacote (datagrama) UDP<br />
#*O campo de dados no pacote UDP<br />
#Troquem os papéis das equipes: quem houvia agora transmite mensagens.<br />
#Cada equipe pode transmitir sequencialmente várias mensagens, devendo identificar múltiplos datagramas UDP.<br />
#PERGUNTAS baseadas na captura:<br />
##Qual o tamanho de cada campo do cabeçalho do pacote UDP?<br />
##Qual o tamanho máximo do número de porta?<br />
##Qual o tamanho máximo da área de dados (payload) do pacote?<br />
##Qual o número identificador de protocolo UDP no pacote IP? <br />
##Em algum momento foi identificado algum procedimento para estabelecimento de conexão? <br />
##Em algum campo do UDP existe numeração de mensagens?<br />
<br />
=AULA 20 - Dia 18/04/2019=<br />
<br />
{{collapse bottom}}<br />
<br />
==Curso FIC Linux 2018==<br />
<br />
{{collapse top|Semestre 2018-2 - Prof. André D'Amato}}<br />
<br />
== Introdução ao Sistema Operacional Linux ==<br />
<br />
'''10/09/18: Aula01'''<br />
<br />
Apresentação da Disciplina, Introdução a Informática e Memória e Armazenamento<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula01.pdf Aula 01]<br />
<br />
{{collapse bottom}}<br />
<br />
==Curso FIC Linux 2016==<br />
<br />
{{collapse top|Semestre 2016-2 - Prof. Luciano Barreto}}<br />
<br />
== Introdução ao Sistema Operacional Linux ==<br />
<br />
'''04/10/16: Aula01'''<br />
<br />
Apresentação da Disciplina, Introdução a Informática e Memória e Armazenamento<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula01.pdf Aula 01]<br />
<br />
'''06/10/16: Aula 02'''<br />
<br />
Introdução ao Linux, Sistema de Arquivos e Conhecendo o Terminal<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula02.pdf Aula 02]<br />
<br />
''' 11/10/2016: Aula 03'''<br />
<br />
Continuação Comandos no Terminal<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula03.pdf Aula 03]<br />
<br />
''' 13/10/2016: Aula 04''' <br />
<br />
Continuação Comandos no Terminal<br />
<br />
''' 18/10/2016: Aula 05''' <br />
<br />
Lista de Exercícios<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/ficlinux-aula05-exercicios.pdf Aula 05 - Lista de Exercícios]<br />
<br />
''' 20/10/2016: Aula 06'''<br />
<br />
Introdução ao Gerenciamento de Processos<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula06-processos.pdf Aula 06 - Gerenciamento de Processos]<br />
<br />
''' 25/10/2016: Aula 07''' <br />
<br />
Gerenciamento de Usuários<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula07-usuariosgrupos.pdf Aula 07 - Gerenciamento de Usuários]<br />
<br />
Permissionamento<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula07-permissionamento.pdf Aula 07 - Permissionamento]<br />
<br />
''' 27/10/2016: Aula 08'''<br />
<br />
Continuação Permissionamento<br />
<br />
Instalação Linux<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula8-instalacao.pdf Aula 08 - Instalação Linux] <br />
<br />
''' 01/11/2016: Aula 09'''<br />
<br />
Continuação Instalação Linux<br />
<br />
Instalação de Pacotes via Apt<br />
[http://tele.sj.ifsc.edu.br/~luciano.barreto/ensino/ficlinux20162/fic-aula9-pacotes.pdf Aula 09 - Instalação Pacotes] <br />
<br />
''' 03/11/2016: Aula 10'''<br />
Continuação Lista Exercícios (47 - 60)<br />
<br />
=AULA 11 - Dia 18/04/2019=<br />
<br />
=AULA 12 - Dia 18/04/2019=<br />
<br />
=AULA 13 - Dia 18/04/2019=<br />
<br />
=AULA 14 - Dia 18/04/2019=<br />
<br />
=AULA 15 - Dia 18/04/2019=<br />
<br />
=AULA 16 - Dia 18/04/2019=<br />
<br />
=AULA 17 - Dia 18/04/2019=<br />
<br />
=AULA 18 - Dia 18/04/2019=<br />
<br />
=AULA 19 - Dia 18/04/2019=<br />
<br />
=AULA 20 - Dia 18/04/2019=<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top|Semestre 2016-1 - Prof. Luciano Barreto}}<br />
<br />
= Diário de Aulas 2016 - 1 =<br />
<br />
==29/03/16: Apresentação do curso==<br />
Apresentação do curso, Visão geral de funções, responsabilidades e estruturas de um SO.<br />
<br />
==31/03/16: Introdução a Sistema de Arquivos e Terminal==<br />
Estrutura do Sistema de Arquivos Linux, Introdução a comandos no Terminal.<br />
<br />
==04/04/16: Continuação Terminal==<br />
Continuação de comandos no terminal, redirecionamento de saída e caracteres coringa.<br />
<br />
==07/04/16: Introdução a Processos e Usuários==<br />
Conhecendo Processos e Gerenciamento de usuários<br />
<br />
==12/04/16: Lista de Exercícios de Comandos no Terminal==<br />
<br />
[http://bellard.org/jslinux/ Emulador de Terminal no navegador (demora um pouquinho pra abrir)]<br />
<br />
==14/04/16: Usuários, Grupos e Permissões==<br />
Administração de usuários, grupos e adicionando permissões a arquivos.<br />
<br />
==19/04/16: Instalação do Linux==<br />
Instalação do Sistema Linux em modo texto, gráfico e dualboot.<br />
<br />
==26/04/16: Introdução ao Shell Script==<br />
Introdução ao Shell Script<br />
<br />
==28/04/16: Continuação ao Shell Script==<br />
Introdução ao Shell Script<br />
<br />
==03/05/16: Lista de Exercícios==<br />
Lista de Exercícios até a aula de 28/04/16<br />
<br />
{{collapse bottom}}<br />
<br />
{{collapse top|Semestre 2015-2}}<br />
<br />
*'''Professores:''' [[Ana Paula Rosa Negri]] e [[Francisco de Assis Souza dos Santos]]<br />
<br />
{| style="background-color:#ABCDEF; font-family:verdana,Arial, Helvetica, sans-serif; font-size:100%; margin:0; border: 1px solid #C7D0F8; padding:7px 7px 0px 7px; text-align:center;" width="100%"<br />
| | Bem-vindo ao<br /><br />
<span style="font-size:200%">'''Curso de Formação Continuada de Configuração de Redes de Computadores Linux''' <br />do Instituto Federal de Santa Catarina - Campus São José</span><br />
|}<br />
<br />
Introdução ao Sistema Operacional Linux<br />
<br />
*'''Professores:''' [[Ana Paula Rosa Negri]] e [[Francisco de Assis Souza dos Santos]]<br />
*'''Encontros:''' Terças e quintas das 19:00 às 22:00 no Laboratório de Apoio ao Ensino.<br />
<br />
*[[ISL-FicLinux_(Plano_de_Ensino)| Plano de Ensino]]<br />
*[[Cronograma de atividades (ISL-FicLinux) | Cronograma]]<br />
<br />
= Diário de Aulas 2015 =<br />
== 13/10 ==<br />
'''Parte 1:'''<br />
Slides da aula:<br />
[[Arquivo:introducao.pdf]]<br />
<br>Exercício sobre taxa de transferência:<br />
[[Arquivo:Exercicio_taxa_Transferencia.pdf]]<br />
<br><br />
<br />
'''Parte 2:'''<br />
Slides da Aula:<br />
[[Arquivo:LinuxModoTexto.pdf]]<br />
<br>Exercícios sobre comandos básicos do Linux:<br />
[[Arquivo:ExercícioLinuxTexto.pdf]]<br />
<br />
== 15/10 ==<br />
'''Parte 3:'''<br />
Slides da Aula:<br />
[[Arquivo:Parte3.pdf]]<br />
== 20/10 ==<br />
'''Parte 4:'''<br />
Slides caracteres coringas: [[Arquivo:Coringas.pdf]]<br />
<br />
Exercícios caracteres coringas: [[Arquivo:Exercício CB03 Pokemon.pdf]]<br />
<br />
'''Parte 5:'''<br />
Sildes Redirecionamento: [[Arquivo: Redirecionamento.pdf]]<br />
<br />
Exercícios redirecionamento e pipe: [[Arquivo: ex_pipe.pdf]]<br />
<br />
== 22/10 ==<br />
'''Parte 6:'''<br />
Slides Processos: [[Arquivo:FICLinux_Processos.pdf]]<br />
<br />
== 27/10 ==<br />
'''Parte 7:''''<br />
Slides Usuários e Grupos: [[Arquivo:UserGroup.pdf]]<br />
<br>Exercícios: [[Arquivo:usuarios.pdf]]<br />
<br>Exercícios (.odt): [[Arquivo:usuarios.odt]]<br />
<br />
== 29/10 ==<br />
'''Parte 8:'''<br />
Slides Introducao a Redes: [[Arquivo:FICLinux_Introducao_Redes.pdf]]<br />
<br />
== 03/11 ==<br />
<br />
'''Parte 9:'''<br />
Slides permissionamento: [[Arquivo:permissionamento.odp]]<br><br />
Exercícios permissionamento: [[Arquivo: Exercício Perm02.odt]]<br><br />
Outro exercício permissionamento: [[Arquivo: Exercício Perm04 GatosRatosCães.odt]]<br />
<br />
== 05/11 ==<br />
<br />
'''Parte 10:'''<br />
Slides Redes - Broadcast: [[Arquivo:FICLinux_Introducao_Redes_Broadcast_01.pdf]]<br><br />
<br />
== 10/11 ==<br />
<br />
'''Parte 11:'''<br />
Slides Script: [[Arquivo:Scripts do Linux.odp]]<br />
<br>Exercícios Scripts: [[Arquivo:Exercício Scripts01 pdfmerger.odt]]<br />
<br />
== 12/11 ==<br />
<br />
'''Parte 12:'''<br />
Introdução para comandos em Bash: [[Arquivo:Introdução ao Shell_2015_1.pdf]]<br />
<br />
{{collapse bottom}}</div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=PTC29008:_Gerenciamento_de_Sess%C3%A3o&diff=161998PTC29008: Gerenciamento de Sessão2019-10-03T11:36:02Z<p>127.0.0.1: /* Formato de quadro do gerenciamento de sessão */</p>
<hr />
<div>[[PTC29008:_Projeto_2:_Protocolo_de_aplicação|Próxima aula]]<br />
<br />
__toc__<br />
<br />
<br />
A próxima função do protocolo de enlace envolve o estabelecimento, manutenção e terminação de conexão. Sendo um protocolo ponto-a-ponto, deve-se estabelecer um enlace entre as duas pontas participantes antes de poder transferir dados. Isso evita que as transmissões entre um par de participantes sejam confundidas com transmissões de outros pares.<br />
<br />
Nas [http://tele.sj.ifsc.edu.br/~msobral/ptc/docs/conexoes.pdf seções 5.2 e 5.3 do capítulo 5] do livro ''Protocol Engineering, 2nd ed'', de Hartmut Konig, há uma explicação sobre o gerenciamento de conexões e diversas formas de implementá-la. No caso do protocolo de enlace, serão usados estabelecimento e terminação explícitos de conexões, e manutenção de conexão.<br />
<br />
== Estabelecimento de conexão ==<br />
<br />
Para criar uma conexão deve-se:<br />
* '''estabelecer a conexão:''' ambos participantes devem se sincronizar para aceitar ou recusar a conexão<br />
* '''negociar parâmetros de conexão:''' a conexão pode envolver parâmetros operacionais do protocolo que devem ser comuns a ambos participantes. Como exemplo, citam-se tamanho máximo de PDU e identificador de conexão.<br />
<br />
A sincronização entre os participantes implica a troca de mensagens, a qual pode ser feita com duas (''2-way handshaking'') ou 3 (''3-way handshaking'') mensagens:<br />
<br />
<br />
[[imagem:PTC-2-way_3-way.png|500px]]<br />
<br />
<br />
A sincronização do tipo ''2-way'' é adequada em comunicações unidirecionais, mas não para comunicações bidirecionais. Isso se deve ao fato de que a primeira mensagem (''CR'') contém parâmetros de conexão do participante que iniciou o processo, e a segunda mensagem (''CC'') contém parâmetros do outro participante. Se a mensagem ''CC'' for perdida, o participante iniciador da conexão não tem como saber se a conexão foi aceita e quais os parâmetros definidos pelo outro participante. Assim, uma terceira mensagem enviada pelo iniciador serve para que o outro participante saiba que a conexão foi estabelecida, e que assim ele pode usá-la para enviar dados. De forma resumida:<br />
# Ao receber a mensagem ''CC'', o iniciador já pode enviar dados pela conexão<br />
# Ao receber a terceira mensagem, o outro participante também pode enviar dados pela conexão. OBS: essa terceira mensagem pode ser uma mensagem de dados comum, pois ela serve para que o outro participante saiba que a conexão foi estabelecida com os parâmetros negociados.<br />
<br />
== Manutenção de conexão ==<br />
<br />
Um enlace pode ter momentos de ociosidade, quando não há mensagens de dados para serem transmitidas. Isso pode ser confundido com casos em que o enlace se rompe (ex: um dos participantes é desligado, ou o meio de comunicação é seccionado). Para evitar que um enlace rompido seja interpretado com um enlace ocioso (e vice-versa), o protocolo deve fazer a manutenção de conexão.<br />
<br />
A manutenção de conexão pode ser feita com o envio periódico de mensagens de verificação. Por exemplo, o protocolo PPP usa mensagens ''Keep-Alive'' enviadas a cada 10 segundos para monitorar o estado do enlace. Se três mensagens ''Keep-Alive'' consecutivas forem perdidas, o enlace é terminado. Nesse caso, após um certo tempo (ex: 30 segundos) o protocolo PPP tenta restabelecer o enlace. O protocolo TCP também possui um mecanismo opcional para manutenção de conexão chamado de [https://en.wikipedia.org/wiki/Keepalive#TCP_keepalive ''Keep Alive'']. Uma abordagem como essa poderia ser incluída no protocolo de enlace em desenvolvimento.<br />
<br />
== Terminação de conexão ==<br />
<br />
A terminação de conexão implica duas necessidades:<br />
# A sincronização entre os participantes quanto ao término da conexão (ambos participantes devem fechar a conexão)<br />
# A garantia de que todas as mensagens de dados pendentes sejam entregues<br />
<br />
<br />
A solução não é tão simples quanto parece. Uma discussão detalhada pode ser lida na [http://tele.sj.ifsc.edu.br/~msobral/ptc/docs/conexoes.pdf seção 5.3.3] do livro Protocol Engineering, 2nd ed, de Hartmut Konig. Com base nessa explicação e no fato de que o protocolo de enlace em desenvolvimento é bidirecional, deve-se usar a terminação de conexão feita por ambos participantes do enlace. Assim um participante envia uma mensagem para terminação de conexão, e após sua confirmação entra-se em estado de conexão parcialmente fechada (''half-close connection''). O outro participante envia suas mensagens pendentes, e em seguida envia sua mensagem de terminação de conexão. Após a confirmação dessa última mensagem de terminação, a conexão é considerada terminada. A figura a seguir exemplifica esse procedimento.<br />
<br />
<br />
[[imagem:PTC-Half-close.png|500px]]<br />
<br />
<br />
Uma simplificação pode ser feita se ambos participantes encerrarem a conexão simultaneamente. Nesse caso, a terminação pode ser sincronizada com três mensagens (''3-way handshake''):<br />
<br />
<br />
[[imagem:PTC-3-way-close.png|300px]]<br />
<br />
<br />
Por fim, pode acontecer de mensagens de terminação de conexão serem perdidas. Isso manteria um ou mesmo ambos participantes esperando indefinidamente pelo término de conexão. Uma solução para evitar essa situação é usar ''timeout'' para a espera de confirmação da mensagem de término de conexão.<br />
<br />
== Atividade ==<br />
<br />
* [http://tele.sj.ifsc.edu.br/~msobral/ptc/poller.tgz Versão atualizada do poller (C++)]<br />
<br />
<br />
# Identifique em que parte da estrutura do seu protocolo deve se encaixar o gerenciamento de conexão<br />
# Modele o ''gerenciamento de conexão'' do seu protocolo de enlace.<br />
<br />
<br />
[[imagem:PTC_Sessao-simetrico.jpg|700px]]<br />
<br>''MEF do gerenciamento de conexão do protocolo de enlace''<br />
<br />
<br />
'''Observações:'''<br />
* No estado ''CON'', o envio de mensagem KR ocorre somente se nada for recebido após um tempo ''CheckInterval''. Assim, a cada vez que uma mensagem for recebida no estado ''CON'', o timer deve ser reiniciado.<br />
* A subcamada ''ARQ'' deve tentar entregar uma mensagem em até ''LimitRetries'' tentativas. Se não conseguir entregá-la, deve notificar a subcamada superior (''Sessão'') de que houve um erro fatal. A subcamada ''Sessão'' deve desconectar imediatamente quando da ocorrência de um erro fatal.<br />
* Pode ser útil uma subcamada desativar temporariamente sua subcamada superior. Por exemplo, quando ''Enquadramento'' começa a receber um quadro, o envio de um novo quadro vindo de ''ARQ'' deveria ser inibido. Da mesma forma, quando ''ARQ'' envia um quadro de dados e está aguardando a recepção de sua confirmação, ''Sessão'' não deveria pedir o envio de uma nova mensagem. A classe ''Callback'' possui os métodos ''enable'' e ''disable'', que servem respectivamente para inibir ou ativar o monitoramento do descritor de arquivos do ''Callback'' (obs: o timeout do ''Callback'' não é afetado por esses métodos). No protocolo, a classe ''Layer'' poderia redefinir esses métodos, de forma a propagar para as subcamadas superiores a ação de inibir ou ativar.<br />
<br />
<br />
'''Legenda dos estados:'''<br />
* ''DISC:'' desconectado<br />
* ''HAND1:'' em aguardo por confirmação de pedido de conexão<br />
* ''HAND2:'' em aguardo por confirmação de pedido de conexão, após receber pedido de conexão do outro lado<br />
* ''HAND3:'' em aguardo por pedido de conexão<br />
* ''CON:'' conectado<br />
* ''CHECK:'' aguardando resposta para ''Keep Alive'' <br />
* ''HALF1:'' em estado de terminação de enlace (''half-close''), quando tomou a iniciativa de terminá-lo<br />
* ''HALF2:'' em estado de terminação de enlace (''half-close''), quando o outro lado tomou a iniciativa<br />
<br />
<br />
'''Legenda das transições:'''<br />
* ''CR'': pedido de conexão (''Connect.request'')<br />
* ''CC'': confirmação de conexão (''Connect.confirm'')<br />
* ''DR'': pedido de desconexão (''Disconnect.request'')<br />
* ''DC'': confirmação de desconexão (''Disconnect.confirm'')<br />
* ''KR'': pedido de ''keep alive''<br />
* ''KC'': confirmação de ''keep alive''<br />
<br />
== Formato de quadro do gerenciamento de sessão ==<br />
<br />
O gerenciamento de sessão implica estender o formato de quadro do protocolo. <br />
<br />
[[imagem:ptc-Quadro-proto1-sessao.jpg]]<br />
<br>''Quadro com campo para ID de sessão''<br />
<br />
O campo ''ID Sessão'' contém um número que identifica a sessão negociada pelo gerenciamento de sessão. Na garantia de entrega (ARQ), quadros com ''ID Sessão'' diferente do negociado devem ser ignorados.<br />
<br />
O campo ''Proto'' identifica o tipo de conteúdo contido no quadro (''Dados''). A tabela a seguir associa o tipo de conteúdo a valores predefinidos para o campo ''Proto'':<br />
<br />
<br />
{| border=1<br />
!Proto<br />
!Tipo de conteúdo<br />
|-<br />
|1 || Datagrama IPv4<br />
|-<br />
|2 ||Datagrama IPv6<br />
|-<br />
|255 || Mensagem de controle do gerenciamento de sessão<br />
|}<br />
<br />
<br />
Além dessa modificação no quadro do protocolo, é necessário definir um formato de mensagem específico para o gerenciamento de sessão. O campo ''Dados'' deve incluir um único octeto cujo conteúdo identifica o tipo de mensagem. A tabela a seguir define os valores para esse octeto:<br />
<br />
{| border=1<br />
!Valor<br />
!Descrição<br />
|-<br />
|0 || CR (Connect request)<br />
|-<br />
|1 || CC (Connect confirm)<br />
|-<br />
|2 || KR (Keep Alive Request)<br />
|-<br />
|3 || KC (Keep Alive Confirm)<br />
|-<br />
|4 || DR (Disconnect Request)<br />
|-<br />
|5 || DC (Disconnect Confirm)<br />
|}<br />
<br />
= Conclusão do projeto 1 (parte 1) =<br />
<br />
* [https://realpython.com/instance-class-and-static-methods-demystified/ Dica sobre métodos em Python]<br />
<br />
<br />
O protocolo desenvolvido no projeto 1 se destina a estabelecer enlaces ponto-a-ponto entre computadores. As funções do protocolo são:<br />
* Enquadramento<br />
* Detecção de erros com CRC-16<br />
* Garantia de entrega com ARQ do tipo pare-e-espere<br />
* Controle de acesso ao meio do tipo Aloha<br />
* Gerenciamento de sessão (conexão)<br />
<br />
<br />
A versão final do protocolo deve ser demonstrada com enlace entre dois computadores, usando o transceiver RF como camada física. Além disso, deve ser entregue um relatório contendo a especificação do protocolo e a documentação do software (ex: diagramas UML de classes e de atividade ou sequência; Pydoc; ...). O relatório deve ser entregue segundo o [https://github.com/ifsc-saojose/modelos-latex/tree/master/artigo/modelo-ifsc-proppi modelo de artigo/relatório técnico] disponibilizado pelo professor Emerson Mello.<br />
<br />
<br />
''Datas importantes:''<br />
* '''15/10''': [https://moodle.sj.ifsc.edu.br/mod/assign/view.php?id=5093 entrega do relatório e código-fonte via Moodle]<br />
* '''18/10''': prazo para apresentação e demonstração do protocolo, em horário a combinar com o professor<br />
<br />
<!--<br />
'''Programas para teste:''' inclui um programa transmissor (tx) e um receptor (rx) compilados estaticamente. Quadros ACK possuem somente o campo de controle no cabeçalho, e não possuem dados, Use o transmissor com seu programa receptor, e vice-versa. Execute-os com opção -h para obter uma ajuda.<br />
* [http://tele.sj.ifsc.edu.br/~msobral/ptc/teste_com_sessao.tgz Versão COM gerenciamento de sessão]: transmissor (tx) inicia e termina a conexão. Receptor (rx) aguarda pedido de conexão.<br />
* [http://tele.sj.ifsc.edu.br/~msobral/ptc/teste_sem_sessao.tgz Versão SEM gerenciamento de sessão]: cabeçalho de quadro não tem campo id_sessao<br />
--></div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=PTC29008:_Gerenciamento_de_Sess%C3%A3o&diff=161997PTC29008: Gerenciamento de Sessão2019-10-03T11:33:23Z<p>127.0.0.1: /* Atividade */</p>
<hr />
<div>[[PTC29008:_Projeto_2:_Protocolo_de_aplicação|Próxima aula]]<br />
<br />
__toc__<br />
<br />
<br />
A próxima função do protocolo de enlace envolve o estabelecimento, manutenção e terminação de conexão. Sendo um protocolo ponto-a-ponto, deve-se estabelecer um enlace entre as duas pontas participantes antes de poder transferir dados. Isso evita que as transmissões entre um par de participantes sejam confundidas com transmissões de outros pares.<br />
<br />
Nas [http://tele.sj.ifsc.edu.br/~msobral/ptc/docs/conexoes.pdf seções 5.2 e 5.3 do capítulo 5] do livro ''Protocol Engineering, 2nd ed'', de Hartmut Konig, há uma explicação sobre o gerenciamento de conexões e diversas formas de implementá-la. No caso do protocolo de enlace, serão usados estabelecimento e terminação explícitos de conexões, e manutenção de conexão.<br />
<br />
== Estabelecimento de conexão ==<br />
<br />
Para criar uma conexão deve-se:<br />
* '''estabelecer a conexão:''' ambos participantes devem se sincronizar para aceitar ou recusar a conexão<br />
* '''negociar parâmetros de conexão:''' a conexão pode envolver parâmetros operacionais do protocolo que devem ser comuns a ambos participantes. Como exemplo, citam-se tamanho máximo de PDU e identificador de conexão.<br />
<br />
A sincronização entre os participantes implica a troca de mensagens, a qual pode ser feita com duas (''2-way handshaking'') ou 3 (''3-way handshaking'') mensagens:<br />
<br />
<br />
[[imagem:PTC-2-way_3-way.png|500px]]<br />
<br />
<br />
A sincronização do tipo ''2-way'' é adequada em comunicações unidirecionais, mas não para comunicações bidirecionais. Isso se deve ao fato de que a primeira mensagem (''CR'') contém parâmetros de conexão do participante que iniciou o processo, e a segunda mensagem (''CC'') contém parâmetros do outro participante. Se a mensagem ''CC'' for perdida, o participante iniciador da conexão não tem como saber se a conexão foi aceita e quais os parâmetros definidos pelo outro participante. Assim, uma terceira mensagem enviada pelo iniciador serve para que o outro participante saiba que a conexão foi estabelecida, e que assim ele pode usá-la para enviar dados. De forma resumida:<br />
# Ao receber a mensagem ''CC'', o iniciador já pode enviar dados pela conexão<br />
# Ao receber a terceira mensagem, o outro participante também pode enviar dados pela conexão. OBS: essa terceira mensagem pode ser uma mensagem de dados comum, pois ela serve para que o outro participante saiba que a conexão foi estabelecida com os parâmetros negociados.<br />
<br />
== Manutenção de conexão ==<br />
<br />
Um enlace pode ter momentos de ociosidade, quando não há mensagens de dados para serem transmitidas. Isso pode ser confundido com casos em que o enlace se rompe (ex: um dos participantes é desligado, ou o meio de comunicação é seccionado). Para evitar que um enlace rompido seja interpretado com um enlace ocioso (e vice-versa), o protocolo deve fazer a manutenção de conexão.<br />
<br />
A manutenção de conexão pode ser feita com o envio periódico de mensagens de verificação. Por exemplo, o protocolo PPP usa mensagens ''Keep-Alive'' enviadas a cada 10 segundos para monitorar o estado do enlace. Se três mensagens ''Keep-Alive'' consecutivas forem perdidas, o enlace é terminado. Nesse caso, após um certo tempo (ex: 30 segundos) o protocolo PPP tenta restabelecer o enlace. O protocolo TCP também possui um mecanismo opcional para manutenção de conexão chamado de [https://en.wikipedia.org/wiki/Keepalive#TCP_keepalive ''Keep Alive'']. Uma abordagem como essa poderia ser incluída no protocolo de enlace em desenvolvimento.<br />
<br />
== Terminação de conexão ==<br />
<br />
A terminação de conexão implica duas necessidades:<br />
# A sincronização entre os participantes quanto ao término da conexão (ambos participantes devem fechar a conexão)<br />
# A garantia de que todas as mensagens de dados pendentes sejam entregues<br />
<br />
<br />
A solução não é tão simples quanto parece. Uma discussão detalhada pode ser lida na [http://tele.sj.ifsc.edu.br/~msobral/ptc/docs/conexoes.pdf seção 5.3.3] do livro Protocol Engineering, 2nd ed, de Hartmut Konig. Com base nessa explicação e no fato de que o protocolo de enlace em desenvolvimento é bidirecional, deve-se usar a terminação de conexão feita por ambos participantes do enlace. Assim um participante envia uma mensagem para terminação de conexão, e após sua confirmação entra-se em estado de conexão parcialmente fechada (''half-close connection''). O outro participante envia suas mensagens pendentes, e em seguida envia sua mensagem de terminação de conexão. Após a confirmação dessa última mensagem de terminação, a conexão é considerada terminada. A figura a seguir exemplifica esse procedimento.<br />
<br />
<br />
[[imagem:PTC-Half-close.png|500px]]<br />
<br />
<br />
Uma simplificação pode ser feita se ambos participantes encerrarem a conexão simultaneamente. Nesse caso, a terminação pode ser sincronizada com três mensagens (''3-way handshake''):<br />
<br />
<br />
[[imagem:PTC-3-way-close.png|300px]]<br />
<br />
<br />
Por fim, pode acontecer de mensagens de terminação de conexão serem perdidas. Isso manteria um ou mesmo ambos participantes esperando indefinidamente pelo término de conexão. Uma solução para evitar essa situação é usar ''timeout'' para a espera de confirmação da mensagem de término de conexão.<br />
<br />
== Atividade ==<br />
<br />
* [http://tele.sj.ifsc.edu.br/~msobral/ptc/poller.tgz Versão atualizada do poller (C++)]<br />
<br />
<br />
# Identifique em que parte da estrutura do seu protocolo deve se encaixar o gerenciamento de conexão<br />
# Modele o ''gerenciamento de conexão'' do seu protocolo de enlace.<br />
<br />
<br />
[[imagem:PTC_Sessao-simetrico.jpg|700px]]<br />
<br>''MEF do gerenciamento de conexão do protocolo de enlace''<br />
<br />
<br />
'''Observações:'''<br />
* No estado ''CON'', o envio de mensagem KR ocorre somente se nada for recebido após um tempo ''CheckInterval''. Assim, a cada vez que uma mensagem for recebida no estado ''CON'', o timer deve ser reiniciado.<br />
* A subcamada ''ARQ'' deve tentar entregar uma mensagem em até ''LimitRetries'' tentativas. Se não conseguir entregá-la, deve notificar a subcamada superior (''Sessão'') de que houve um erro fatal. A subcamada ''Sessão'' deve desconectar imediatamente quando da ocorrência de um erro fatal.<br />
* Pode ser útil uma subcamada desativar temporariamente sua subcamada superior. Por exemplo, quando ''Enquadramento'' começa a receber um quadro, o envio de um novo quadro vindo de ''ARQ'' deveria ser inibido. Da mesma forma, quando ''ARQ'' envia um quadro de dados e está aguardando a recepção de sua confirmação, ''Sessão'' não deveria pedir o envio de uma nova mensagem. A classe ''Callback'' possui os métodos ''enable'' e ''disable'', que servem respectivamente para inibir ou ativar o monitoramento do descritor de arquivos do ''Callback'' (obs: o timeout do ''Callback'' não é afetado por esses métodos). No protocolo, a classe ''Layer'' poderia redefinir esses métodos, de forma a propagar para as subcamadas superiores a ação de inibir ou ativar.<br />
<br />
<br />
'''Legenda dos estados:'''<br />
* ''DISC:'' desconectado<br />
* ''HAND1:'' em aguardo por confirmação de pedido de conexão<br />
* ''HAND2:'' em aguardo por confirmação de pedido de conexão, após receber pedido de conexão do outro lado<br />
* ''HAND3:'' em aguardo por pedido de conexão<br />
* ''CON:'' conectado<br />
* ''CHECK:'' aguardando resposta para ''Keep Alive'' <br />
* ''HALF1:'' em estado de terminação de enlace (''half-close''), quando tomou a iniciativa de terminá-lo<br />
* ''HALF2:'' em estado de terminação de enlace (''half-close''), quando o outro lado tomou a iniciativa<br />
<br />
<br />
'''Legenda das transições:'''<br />
* ''CR'': pedido de conexão (''Connect.request'')<br />
* ''CC'': confirmação de conexão (''Connect.confirm'')<br />
* ''DR'': pedido de desconexão (''Disconnect.request'')<br />
* ''DC'': confirmação de desconexão (''Disconnect.confirm'')<br />
* ''KR'': pedido de ''keep alive''<br />
* ''KC'': confirmação de ''keep alive''<br />
<br />
== Formato de quadro do gerenciamento de sessão ==<br />
<br />
O gerenciamento de sessão implica estender o formato de quadro do protocolo. <br />
<br />
[[imagem:ptc-Quadro-proto1-sessao.jpg]]<br />
<br>''Quadro com campo para ID de sessão''<br />
<br />
O campo ''ID Sessão'' contém um número que identifica a sessão negociada pelo gerenciamento de sessão. Na garantia de entrega (ARQ), quadros com ''ID Sessão'' diferente do negociado devem ser ignorados.<br />
<br />
Além dessa modificação no quadro do protocolo, é necessário definir um formato de mensagem específico para o gerenciamento de sessão. Essas mensagens são identificadas pelo valor 255 no campo ''Proto''. O campo ''Dados'' deve incluir um único octeto cujo conteúdo identifica o tipo de mensagem. A tabela a seguir define os valores para esse octeto:<br />
<br />
{| border=1<br />
!Valor<br />
!Descrição<br />
|-<br />
|0 || CR (Connect request)<br />
|-<br />
|1 || CC (Connect confirm)<br />
|-<br />
|2 || KR (Keep Alive Request)<br />
|-<br />
|3 || KC (Keep Alive Confirm)<br />
|-<br />
|4 || DR (Disconnect Request)<br />
|-<br />
|5 || DC (Disconnect Confirm)<br />
|}<br />
<br />
= Conclusão do projeto 1 (parte 1) =<br />
<br />
* [https://realpython.com/instance-class-and-static-methods-demystified/ Dica sobre métodos em Python]<br />
<br />
<br />
O protocolo desenvolvido no projeto 1 se destina a estabelecer enlaces ponto-a-ponto entre computadores. As funções do protocolo são:<br />
* Enquadramento<br />
* Detecção de erros com CRC-16<br />
* Garantia de entrega com ARQ do tipo pare-e-espere<br />
* Controle de acesso ao meio do tipo Aloha<br />
* Gerenciamento de sessão (conexão)<br />
<br />
<br />
A versão final do protocolo deve ser demonstrada com enlace entre dois computadores, usando o transceiver RF como camada física. Além disso, deve ser entregue um relatório contendo a especificação do protocolo e a documentação do software (ex: diagramas UML de classes e de atividade ou sequência; Pydoc; ...). O relatório deve ser entregue segundo o [https://github.com/ifsc-saojose/modelos-latex/tree/master/artigo/modelo-ifsc-proppi modelo de artigo/relatório técnico] disponibilizado pelo professor Emerson Mello.<br />
<br />
<br />
''Datas importantes:''<br />
* '''15/10''': [https://moodle.sj.ifsc.edu.br/mod/assign/view.php?id=5093 entrega do relatório e código-fonte via Moodle]<br />
* '''18/10''': prazo para apresentação e demonstração do protocolo, em horário a combinar com o professor<br />
<br />
<!--<br />
'''Programas para teste:''' inclui um programa transmissor (tx) e um receptor (rx) compilados estaticamente. Quadros ACK possuem somente o campo de controle no cabeçalho, e não possuem dados, Use o transmissor com seu programa receptor, e vice-versa. Execute-os com opção -h para obter uma ajuda.<br />
* [http://tele.sj.ifsc.edu.br/~msobral/ptc/teste_com_sessao.tgz Versão COM gerenciamento de sessão]: transmissor (tx) inicia e termina a conexão. Receptor (rx) aguarda pedido de conexão.<br />
* [http://tele.sj.ifsc.edu.br/~msobral/ptc/teste_sem_sessao.tgz Versão SEM gerenciamento de sessão]: cabeçalho de quadro não tem campo id_sessao<br />
--></div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=Arquivo:PTC_Sessao-simetrico.jpg&diff=161996Arquivo:PTC Sessao-simetrico.jpg2019-10-03T11:25:31Z<p>127.0.0.1: foi enviada uma nova versão de &quot;Arquivo:PTC Sessao-simetrico.jpg&quot;</p>
<hr />
<div></div>127.0.0.1https://wiki.sj.ifsc.edu.br/index.php?title=PTC29008:_Gerenciamento_de_Sess%C3%A3o&diff=161995PTC29008: Gerenciamento de Sessão2019-10-03T11:21:28Z<p>127.0.0.1: /* Formato de quadro do gerenciamento de sessão */</p>
<hr />
<div>[[PTC29008:_Projeto_2:_Protocolo_de_aplicação|Próxima aula]]<br />
<br />
__toc__<br />
<br />
<br />
A próxima função do protocolo de enlace envolve o estabelecimento, manutenção e terminação de conexão. Sendo um protocolo ponto-a-ponto, deve-se estabelecer um enlace entre as duas pontas participantes antes de poder transferir dados. Isso evita que as transmissões entre um par de participantes sejam confundidas com transmissões de outros pares.<br />
<br />
Nas [http://tele.sj.ifsc.edu.br/~msobral/ptc/docs/conexoes.pdf seções 5.2 e 5.3 do capítulo 5] do livro ''Protocol Engineering, 2nd ed'', de Hartmut Konig, há uma explicação sobre o gerenciamento de conexões e diversas formas de implementá-la. No caso do protocolo de enlace, serão usados estabelecimento e terminação explícitos de conexões, e manutenção de conexão.<br />
<br />
== Estabelecimento de conexão ==<br />
<br />
Para criar uma conexão deve-se:<br />
* '''estabelecer a conexão:''' ambos participantes devem se sincronizar para aceitar ou recusar a conexão<br />
* '''negociar parâmetros de conexão:''' a conexão pode envolver parâmetros operacionais do protocolo que devem ser comuns a ambos participantes. Como exemplo, citam-se tamanho máximo de PDU e identificador de conexão.<br />
<br />
A sincronização entre os participantes implica a troca de mensagens, a qual pode ser feita com duas (''2-way handshaking'') ou 3 (''3-way handshaking'') mensagens:<br />
<br />
<br />
[[imagem:PTC-2-way_3-way.png|500px]]<br />
<br />
<br />
A sincronização do tipo ''2-way'' é adequada em comunicações unidirecionais, mas não para comunicações bidirecionais. Isso se deve ao fato de que a primeira mensagem (''CR'') contém parâmetros de conexão do participante que iniciou o processo, e a segunda mensagem (''CC'') contém parâmetros do outro participante. Se a mensagem ''CC'' for perdida, o participante iniciador da conexão não tem como saber se a conexão foi aceita e quais os parâmetros definidos pelo outro participante. Assim, uma terceira mensagem enviada pelo iniciador serve para que o outro participante saiba que a conexão foi estabelecida, e que assim ele pode usá-la para enviar dados. De forma resumida:<br />
# Ao receber a mensagem ''CC'', o iniciador já pode enviar dados pela conexão<br />
# Ao receber a terceira mensagem, o outro participante também pode enviar dados pela conexão. OBS: essa terceira mensagem pode ser uma mensagem de dados comum, pois ela serve para que o outro participante saiba que a conexão foi estabelecida com os parâmetros negociados.<br />
<br />
== Manutenção de conexão ==<br />
<br />
Um enlace pode ter momentos de ociosidade, quando não há mensagens de dados para serem transmitidas. Isso pode ser confundido com casos em que o enlace se rompe (ex: um dos participantes é desligado, ou o meio de comunicação é seccionado). Para evitar que um enlace rompido seja interpretado com um enlace ocioso (e vice-versa), o protocolo deve fazer a manutenção de conexão.<br />
<br />
A manutenção de conexão pode ser feita com o envio periódico de mensagens de verificação. Por exemplo, o protocolo PPP usa mensagens ''Keep-Alive'' enviadas a cada 10 segundos para monitorar o estado do enlace. Se três mensagens ''Keep-Alive'' consecutivas forem perdidas, o enlace é terminado. Nesse caso, após um certo tempo (ex: 30 segundos) o protocolo PPP tenta restabelecer o enlace. O protocolo TCP também possui um mecanismo opcional para manutenção de conexão chamado de [https://en.wikipedia.org/wiki/Keepalive#TCP_keepalive ''Keep Alive'']. Uma abordagem como essa poderia ser incluída no protocolo de enlace em desenvolvimento.<br />
<br />
== Terminação de conexão ==<br />
<br />
A terminação de conexão implica duas necessidades:<br />
# A sincronização entre os participantes quanto ao término da conexão (ambos participantes devem fechar a conexão)<br />
# A garantia de que todas as mensagens de dados pendentes sejam entregues<br />
<br />
<br />
A solução não é tão simples quanto parece. Uma discussão detalhada pode ser lida na [http://tele.sj.ifsc.edu.br/~msobral/ptc/docs/conexoes.pdf seção 5.3.3] do livro Protocol Engineering, 2nd ed, de Hartmut Konig. Com base nessa explicação e no fato de que o protocolo de enlace em desenvolvimento é bidirecional, deve-se usar a terminação de conexão feita por ambos participantes do enlace. Assim um participante envia uma mensagem para terminação de conexão, e após sua confirmação entra-se em estado de conexão parcialmente fechada (''half-close connection''). O outro participante envia suas mensagens pendentes, e em seguida envia sua mensagem de terminação de conexão. Após a confirmação dessa última mensagem de terminação, a conexão é considerada terminada. A figura a seguir exemplifica esse procedimento.<br />
<br />
<br />
[[imagem:PTC-Half-close.png|500px]]<br />
<br />
<br />
Uma simplificação pode ser feita se ambos participantes encerrarem a conexão simultaneamente. Nesse caso, a terminação pode ser sincronizada com três mensagens (''3-way handshake''):<br />
<br />
<br />
[[imagem:PTC-3-way-close.png|300px]]<br />
<br />
<br />
Por fim, pode acontecer de mensagens de terminação de conexão serem perdidas. Isso manteria um ou mesmo ambos participantes esperando indefinidamente pelo término de conexão. Uma solução para evitar essa situação é usar ''timeout'' para a espera de confirmação da mensagem de término de conexão.<br />
<br />
== Atividade ==<br />
<br />
* [http://tele.sj.ifsc.edu.br/~msobral/ptc/poller.tgz Versão atualizada do poller (C++)]<br />
<br />
<br />
# Identifique em que parte da estrutura do seu protocolo deve se encaixar o gerenciamento de conexão<br />
# Modele o ''gerenciamento de conexão'' do seu protocolo de enlace.<br />
<br />
<br />
[[imagem:PTC_Sessao-simetrico.jpg|700px]]<br />
<br>''MEF do gerenciamento de conexão do protocolo de enlace''<br />
<!--<br />
<br />
<br />
'''Observações:'''<br />
* No estado ''CON'', o envio de mensagem KR ocorre somente nada for recebido após um tempo ''CheckInterval''. Assim, a cada vez que uma mensagem for recebida no estado ''CON'', o timer deve ser reiniciado.<br />
* A subcamada ''ARQ'' deve tentar entregar uma mensagem em até ''LimitRetries'' tentativas. Se não conseguir entregá-la, deve notificar a subcamada superior (''Sessão'') de que houve um erro fatal. A subcamada ''Sessão'' deve desconectar imediatamente quando da ocorrência de um erro fatal.<br />
* Pode ser útil uma subcamada desativar temporariamente sua subcamada superior. Por exemplo, quando ''Enquadramento'' começa a receber um quadro, o envio de um novo quadro vindo de ''ARQ'' deveria ser inibido. Da mesma forma, quando ''ARQ'' envia um quadro de dados e está aguardando a recepção de sua confirmação, ''Sessão'' não deveria pedir o envio de uma nova mensagem. A classe ''Callback'' possui os métodos ''enable'' e ''disable'', que servem respectivamente para inibir ou ativar o monitoramento do descritor de arquivos do ''Callback'' (obs: o timeout do ''Callback'' não é afetado por esses métodos). No protocolo, a classe ''Layer'' poderia redefinir esses métodos, de forma a propagar para as subcamadas superiores a ação de inibir ou ativar.<br />
<br />
<br />
'''Legenda dos estados:'''<br />
* ''DISC:'' desconectado<br />
* ''HAND1:'' em negociação para estabelecimento de conexão, quando tomou a iniciativa de estabelecê-la<br />
* ''HAND2:'' em negociação para estabelecimento de conexão, quando o outro lado tomou a iniciativa<br />
* ''CON:'' conectado<br />
* ''CHECK:'' aguardando resposta para ''Keep Alive'' <br />
* ''HALF1:'' em estado de terminação de enlace (''half-close''), quando tomou a iniciativa de terminá-lo<br />
* ''HALF2:'' em estado de terminação de enlace (''half-close''), quando o outro lado tomou a iniciativa<br />
<br />
<br />
'''Legenda das transições:'''<br />
* ''CR'': pedido de conexão (''Connect.request'')<br />
* ''CC'': confirmação de conexão (''Connect.confirm'')<br />
* ''CA'': reconhecimento de conexão (''ConnectAck.indication'')<br />
* ''DR'': pedido de desconexão (''Disconnect.request'')<br />
* ''DC'': confirmação de desconexão (''Disconnect.confirm'')<br />
* ''KR'': pedido de ''keep alive''<br />
* ''KC'': confirmação de ''keep alive''<br />
<br />
--><br />
<br />
== Formato de quadro do gerenciamento de sessão ==<br />
<br />
O gerenciamento de sessão implica estender o formato de quadro do protocolo. <br />
<br />
[[imagem:ptc-Quadro-proto1-sessao.jpg]]<br />
<br>''Quadro com campo para ID de sessão''<br />
<br />
O campo ''ID Sessão'' contém um número que identifica a sessão negociada pelo gerenciamento de sessão. Na garantia de entrega (ARQ), quadros com ''ID Sessão'' diferente do negociado devem ser ignorados.<br />
<br />
Além dessa modificação no quadro do protocolo, é necessário definir um formato de mensagem específico para o gerenciamento de sessão. Essas mensagens são identificadas pelo valor 255 no campo ''Proto''. O campo ''Dados'' deve incluir um único octeto cujo conteúdo identifica o tipo de mensagem. A tabela a seguir define os valores para esse octeto:<br />
<br />
{| border=1<br />
!Valor<br />
!Descrição<br />
|-<br />
|0 || CR (Connect request)<br />
|-<br />
|1 || CC (Connect confirm)<br />
|-<br />
|2 || KR (Keep Alive Request)<br />
|-<br />
|3 || KC (Keep Alive Confirm)<br />
|-<br />
|4 || DR (Disconnect Request)<br />
|-<br />
|5 || DC (Disconnect Confirm)<br />
|}<br />
<br />
= Conclusão do projeto 1 (parte 1) =<br />
<br />
* [https://realpython.com/instance-class-and-static-methods-demystified/ Dica sobre métodos em Python]<br />
<br />
<br />
O protocolo desenvolvido no projeto 1 se destina a estabelecer enlaces ponto-a-ponto entre computadores. As funções do protocolo são:<br />
* Enquadramento<br />
* Detecção de erros com CRC-16<br />
* Garantia de entrega com ARQ do tipo pare-e-espere<br />
* Controle de acesso ao meio do tipo Aloha<br />
* Gerenciamento de sessão (conexão)<br />
<br />
<br />
A versão final do protocolo deve ser demonstrada com enlace entre dois computadores, usando o transceiver RF como camada física. Além disso, deve ser entregue um relatório contendo a especificação do protocolo e a documentação do software (ex: diagramas UML de classes e de atividade ou sequência; Pydoc; ...). O relatório deve ser entregue segundo o [https://github.com/ifsc-saojose/modelos-latex/tree/master/artigo/modelo-ifsc-proppi modelo de artigo/relatório técnico] disponibilizado pelo professor Emerson Mello.<br />
<br />
<br />
''Datas importantes:''<br />
* '''15/10''': [https://moodle.sj.ifsc.edu.br/mod/assign/view.php?id=5093 entrega do relatório e código-fonte via Moodle]<br />
* '''18/10''': prazo para apresentação e demonstração do protocolo, em horário a combinar com o professor<br />
<br />
<!--<br />
'''Programas para teste:''' inclui um programa transmissor (tx) e um receptor (rx) compilados estaticamente. Quadros ACK possuem somente o campo de controle no cabeçalho, e não possuem dados, Use o transmissor com seu programa receptor, e vice-versa. Execute-os com opção -h para obter uma ajuda.<br />
* [http://tele.sj.ifsc.edu.br/~msobral/ptc/teste_com_sessao.tgz Versão COM gerenciamento de sessão]: transmissor (tx) inicia e termina a conexão. Receptor (rx) aguarda pedido de conexão.<br />
* [http://tele.sj.ifsc.edu.br/~msobral/ptc/teste_sem_sessao.tgz Versão SEM gerenciamento de sessão]: cabeçalho de quadro não tem campo id_sessao<br />
--></div>127.0.0.1