h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Conceitos básicos para desenvolvimento de sistemas
em ambiente Linux
Alexandre Mu...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Antes de mais nada...
A quem se
destina estes
slides?
Iniciantes no mundo Unix/Li...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Agenda
Conceitos Básicos
Ferramentas importantes
Um pouco de história
Uma rápida ...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Conceitos Básicos
O que é um programa?
Uma série de instruções utilizando uma lin...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Conceitos Básicos
Então agora que já sabemos o que é um programa de computador
de...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Conceitos Básicos
Então agora que já sabemos o que é um programa de computador
de...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Conceitos Básicos
Então agora que já sabemos o que é um programa de computador
de...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Agenda
Conceitos Básicos
Ferramentas importantes
Um pouco de história
Uma rápida ...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Ferramentas importantes
Para que você seja eciente desenvolvendo uma aplicação vo...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Ferramentas importantes
Controle de versão Muitas vezes iniciantes de programação...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Ferramentas importantes
Editores de texto
VIM, LaTeX, Eclipse, Geany, Emacs, MS V...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Agenda
Conceitos Básicos
Ferramentas importantes
Um pouco de história
Uma rápida ...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Um pouco de história
Talvez seja difícil de imaginar para alguns mas até 1970, ex...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Um pouco de história
E onde está o C nisso!?
Criado por Dennis Ritchie e
Ken Thom...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Agenda
Conceitos Básicos
Ferramentas importantes
Um pouco de história
Uma rápida ...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Uma rápida introdução ao C
Tipos de dados
A linguagem de programação C, diferente...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Uma rápida introdução ao C
Estrutura básica e declarações de variáveis
Um program...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Uma rápida introdução ao C
Fluxos de controle em C
Fluxos de controle são comando...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Uma rápida introdução ao C
If-then-else e o operador '?'
As formas mais simples d...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Uma rápida introdução ao C
O comando switch
O switch é chamado de 'if elegante', ...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Uma rápida introdução ao C
Funções
Protótipo é
escrito de
forma resumida
no iníci...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Uma rápida introdução ao C
Ponteiros e alocação dinâmica de memória
Um dos maiore...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Agenda
Conceitos Básicos
Ferramentas importantes
Um pouco de história
Uma rápida ...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Desenvolvendo programas
Vamos fazer o clássico Hello Worldpara começar, ele
simpl...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Desenvolvendo programas
Dessa vez vamos complicar um pouquinho mais, o objetivo d...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Desenvolvendo programas
Um simples Makele para projetos pequenos
Para automatizar...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Desenvolvendo programas
Bibliotecas comuns
Tabela de bibliotecas C ANSI C99
asser...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Agenda
Conceitos Básicos
Ferramentas importantes
Um pouco de história
Uma rápida ...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Utilizando controle de versões
Hoje em dia desenvolver qualquer coisa com mais de...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Utilizando controle de versões
Principais características encontradas nos control...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Utilizando controle de versões
Imagine o gráco ao lado
como a linha de
desenvolvi...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Utilizando controle de versões
GIT, criado por Linus Torvalds.
Abaixo podemos ver...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Agenda
Conceitos Básicos
Ferramentas importantes
Um pouco de história
Uma rápida ...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Utilizando o autotools
Lembra como compilar um programa? Como gerar um Makele!?
A...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Utilizando o autotools
Principais módulos da ferramenta autotools
Autoconf Respon...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Utilizando o autotools
Com apenas a edição de dois arquivos,
'Makele.am'
'congure...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Utilizando o autotools
O arquivo de entrada 'Makele.am'
Arquivos do projeto:
Make...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Utilizando o autotools
O arquivo de entrada 'congure.ac'
Um típico arquivo 'congu...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Utilizando o autotools
Gerando o build do projeto
mulatinho@forrest:~/repo/github...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Agenda
Conceitos Básicos
Ferramentas importantes
Um pouco de história
Uma rápida ...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Debugando seu código
Por quê debugar??
Debugar é o ato de conrmar que algo que vo...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Debugando seu código
Utilizando o GDB
O GDB é o projeto da GNU para debugar aplic...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Debugando seu código
Utilizando o GDB, parte 2
comandos descrição
run roda o prog...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Debugando seu código
Para os que não gostam de comandos de console é claro que te...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Debugando seu código
Utilizando o strace
O 'strace' é utilizado para rastrear com...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Debugando seu código
Utilizando o strace, parte 2
Também podemos analisar detalha...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Debugando seu código
Valgrind para memória
O valgrind analisa erros de softwares ...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Debugando seu código
Valgrind para memória, parte 2.
1 $ gcc -g -Wall -o gdb4 gdb...
h
ttp
:/
/
a
le
x
.m
u
la
tin
h
o
.n
e
t
Isso é tudo pessoal!
Dúvidas e Sugestões?
Alexandre Mulatinho
Twitter: @alexmulat...
Upcoming SlideShare
Loading in …5
×

Desenvolvendo em ambientes Unix

1,600 views

Published on

Programming in C using Unix environments.

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,600
On SlideShare
0
From Embeds
0
Number of Embeds
928
Actions
Shares
0
Downloads
10
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Desenvolvendo em ambientes Unix

  1. 1. h ttp :/ / a le x .m u la tin h o .n e t Conceitos básicos para desenvolvimento de sistemas em ambiente Linux Alexandre Mulatinho E-mail: alex@mulatinho.net Mulatinho's Weblog http://alex.mulatinho.net Twitter: @alexmulatinho 11 de junho de 2014 Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  2. 2. h ttp :/ / a le x .m u la tin h o .n e t Antes de mais nada... A quem se destina estes slides? Iniciantes no mundo Unix/Linux. Prossionais em busca de mais conhecimento em desenvolvimento utilizando ferramentas livres. Quem quer aprender o básico sobre: a linguagem C, desenvolvimento, controle de versões e debug em sistemas Unix. Entusiastas do uso de software livre! Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  3. 3. h ttp :/ / a le x .m u la tin h o .n e t Agenda Conceitos Básicos Ferramentas importantes Um pouco de história Uma rápida introdução ao C Desenvolvendo programas Utilizando controle de versões Utilizando o autotools Debugando seu código Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  4. 4. h ttp :/ / a le x .m u la tin h o .n e t Conceitos Básicos O que é um programa? Uma série de instruções utilizando uma linguagem de programação dentro de uma máquina capaz de interpretá-las e processá-las com um objetivo especíco. Como ele é feito? No nal um programa é constituído de 0s e 1s e só é entendido pelo computador, seria inviável desenvolvermos algo assim e por isso foram denidas palavras por programadores que contendo uma lógica adequada constroem um programa de computador. Quais ferramentas utilizo para desenvolvê-lo? Basicamente você precisa de três coisas: um editor para construir o seu código, um compilador que transformará o seu código em um objeto entendido pela arquitetura do seu computador e um linker que irá unir todos os objetos em um único binário entendido pelo seu sistema operacional. Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  5. 5. h ttp :/ / a le x .m u la tin h o .n e t Conceitos Básicos Então agora que já sabemos o que é um programa de computador devemos denir que tipos de programa existem e para quê propósito eles foram criados, tendo como base estas armações podemos classicar os programas em dois tipos: Software de sistema: são programas de computadores críticos e que trabalham entre a camada de hardware e software, eles são utilizados pelo usuário constantemente, embora usuários leigos não tenham ciência disso pois é necessário que os softwares de aplicativo façam a ponte entre eles. Software aplicativo: esses são os nossos softwares do dia a dia, que todo o usuário gosta de usar e hoje devido a necessidade de tecnologia nós seres humanos não vivemos sem eles. Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  6. 6. h ttp :/ / a le x .m u la tin h o .n e t Conceitos Básicos Então agora que já sabemos o que é um programa de computador devemos denir que tipos de programa existem e para quê propósito eles foram criados, tendo como base estas armações podemos classicar os programas em dois tipos: Software de sistema: são programas de computadores críticos e que trabalham entre a camada de hardware e software, eles são utilizados pelo usuário constantemente, embora usuários leigos não tenham ciência disso pois é necessário que os softwares de aplicativo façam a ponte entre eles. Exemplos: Firmwares, RTOS, drivers de dispositivos. Software aplicativo: esses são os nossos softwares do dia a dia, que todo o usuário gosta de usar e hoje devido a necessidade de tecnologia nós seres humanos não vivemos sem eles. Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  7. 7. h ttp :/ / a le x .m u la tin h o .n e t Conceitos Básicos Então agora que já sabemos o que é um programa de computador devemos denir que tipos de programa existem e para quê propósito eles foram criados, tendo como base estas armações podemos classicar os programas em dois tipos: Software de sistema: são programas de computadores críticos e que trabalham entre a camada de hardware e software, eles são utilizados pelo usuário constantemente, embora usuários leigos não tenham ciência disso pois é necessário que os softwares de aplicativo façam a ponte entre eles. Exemplos: Firmwares, RTOS, drivers de dispositivos. Software aplicativo: esses são os nossos softwares do dia a dia, que todo o usuário gosta de usar e hoje devido a necessidade de tecnologia nós seres humanos não vivemos sem eles. Exemplos: VIM, AWK, Firefox, Eclipse, Java, C, Nesta apresentação iremos focar apenas no segundo tipo. Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  8. 8. h ttp :/ / a le x .m u la tin h o .n e t Agenda Conceitos Básicos Ferramentas importantes Um pouco de história Uma rápida introdução ao C Desenvolvendo programas Utilizando controle de versões Utilizando o autotools Debugando seu código Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  9. 9. h ttp :/ / a le x .m u la tin h o .n e t Ferramentas importantes Para que você seja eciente desenvolvendo uma aplicação você deve obter algumas ferramentas que serão úteis durante todo o processo, algumas delas vamos discutir mais a frente, outras não, eis aqui algumas delas: Editor de texto Aqui vale a pena perder algumas horas escolhendo um editor que mais se adeque ao seu estilo, hoje em dia com a febre dos IDEs é difícil encontrar quem consiga programar sem um deles, aqui particularmente eu utilizo o VIM e algumas vezes o Geany. Compilador Para que seu código depois de editado se transforme em um binário e você possa executá-lo é crítico escolher o compilador adequado, infelizmente muitas vezes aqui você não terá opção, principalmente se estiver trabalhando com sistemas embarcados. Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  10. 10. h ttp :/ / a le x .m u la tin h o .n e t Ferramentas importantes Controle de versão Muitas vezes iniciantes de programação ou até programadores experientes ignoram o fato de que devem ter controle sobre suas versões de desenvolvimento, quando percebem que isto é muito importante já estão com o projeto todo bagunçado e é muito pior corrigir depois. Diagnóstico Muito úteis para analisar os binários como os debuggers, aqui também se encaixariam ferramentas de trace como o strace, ltrace. Auxiliares Ferramentas de auxílio como o autotools que geram para você scripts de conguração, compilação, etc. são cruciais para fazer você não perder tempo com rotinas mecânicas. Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  11. 11. h ttp :/ / a le x .m u la tin h o .n e t Ferramentas importantes Editores de texto VIM, LaTeX, Eclipse, Geany, Emacs, MS Visual C++, etc. Compiladores GCC, Visual C++, TinyC, LLVM-Clang, etc. Controles de Versão Git, Subversion, Mercurial, CVS, etc. Diagnóstico GDB, binutils, strace, ltrace, etc. Auxiliares Autoconf, Automake, Scripts Shell ou Batch, QMake, etc. Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  12. 12. h ttp :/ / a le x .m u la tin h o .n e t Agenda Conceitos Básicos Ferramentas importantes Um pouco de história Uma rápida introdução ao C Desenvolvendo programas Utilizando controle de versões Utilizando o autotools Debugando seu código Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  13. 13. h ttp :/ / a le x .m u la tin h o .n e t Um pouco de história Talvez seja difícil de imaginar para alguns mas até 1970, exceto em alguns programas especícos escritos nas linguagens modernasda epóca BASIC, COBOL, BCPL, etc., todos os outros eram escritos em Assembly, mais ou menos assim: linux x86 assembly 1 movl %eax, -44(%rbp) 2 movl $0, %edx 3 movl $1, %esi 4 movl $2, %edi 5 call socket 6 movl %eax, -4(%rbp) 7 cmpl $-1, -4(%rbp) 8 jne .L2 9 movl $1, %eax 10 jmp .L8 z80 assembly 1 org 1000h ;Origin at 1000h 2 memcpy public 3 loop ld a,b ;Test BC, 4 or c ;If BC = 0, 5 retz ; Return 6 ld a,(de) ;Load A from (DE) 7 ld (hl),a ;Store A into (HL) 8 inc de ;Increment DE 9 inc hl ;Increment HL 10 dec bc ;Decrement BC 11 jp loop ;Repeat the loop 12 end Na epóca em que desenvolver era função de programadores de verdade que tinham que lêr os manuais de arquitetura do processador, gerenciar a memória de seus programas, etc. Hoje a realidade é bem diferente, utilizamos bibliotecas e funções desenvolvidas por terceiros e as adequamos aos nossos programas. Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  14. 14. h ttp :/ / a le x .m u la tin h o .n e t Um pouco de história E onde está o C nisso!? Criado por Dennis Ritchie e Ken Thompson no período dos anos de 1969 até 1972. Estruturada, imperativa, procedural e padronizada pela ISO. Utilizada em baixo nível e alto nível. A maioria dos sistemas operacionais modernos são escritos em C, por ser capaz de realizar abstrações, mexer com bits e bytes e controlar de forma eciente a memória. C é simplesmente a linguagem que criou o Unix, o Linux, o C++ e vários outros programas utilizados até hoje. Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  15. 15. h ttp :/ / a le x .m u la tin h o .n e t Agenda Conceitos Básicos Ferramentas importantes Um pouco de história Uma rápida introdução ao C Desenvolvendo programas Utilizando controle de versões Utilizando o autotools Debugando seu código Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  16. 16. h ttp :/ / a le x .m u la tin h o .n e t Uma rápida introdução ao C Tipos de dados A linguagem de programação C, diferente das linguagens modernas, possui apenas 32 (trinta e duas) palavras reservadas por padrão. São elas: auto break case char const continue default do double else enum extern oat for goto if int long register return short signed sizeof static struct switch typedef union unsigned void volatile while Destas palavras cinco delas são tipos de dados: char int oat void double Para cada tipo de dado também existem modicadores como: . signed unsigned long short . volatile extern register auto const static Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  17. 17. h ttp :/ / a le x .m u la tin h o .n e t Uma rápida introdução ao C Estrutura básica e declarações de variáveis Um programa em C comum contém a seguinte estrutura 1 Comando do pré processador. 2 Tipos de dados denidos globalmente. 3 Protótipos de funções. 4 Funções e variáveis locais das funções. Denição de variáveis em C e seus tamanhos reais em bytes Declarações simples int i; int j = 10; int x = j * 5; char c = 'j'; char ola[5] = { 'h', 'e', 'l', 'l', 'o' }; float pi = 3.14; char nums[2][2] = { { 0, 0 }, {0, 0} }; Tamanho de tipos de dados sizeof(void): 1 byte // tipo de dado sizeof(char): 1 byte // tipo de dado sizeof(short): 2 bytes // modificador sizeof(int): 4 bytes // tipo de dado sizeof(float): 4 bytes // tipo de dado sizeof(double): 8 bytes // tipo de dado sizeof(long): 8 bytes // modificador Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  18. 18. h ttp :/ / a le x .m u la tin h o .n e t Uma rápida introdução ao C Fluxos de controle em C Fluxos de controle são comandos que desviam o programa dependendo de alguma condição ou iteração, em C existem cinco palavras chaves para executar desvios e iterações no seu programa, são elas: O comando 'while'e o 'do-while' while (!(ret = comidaPronta(forno))) { make_the_rango(); ingredientes++; } do { ret = check_the_books(); if (ret) study++; } while (!study); O comando 'for', o 'break' e 'continue' for (i=0; i10; i++) { if (i == 8) break; esle if (i % 2) continue; fprintf(stdout, Hi!n); } break, para a execução do loop. continue, vai para próxima iteração. Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  19. 19. h ttp :/ / a le x .m u la tin h o .n e t Uma rápida introdução ao C If-then-else e o operador '?' As formas mais simples de criar condições em C são através do famoso if-then-else e do operador '?', vamos aos exemplos. If-then-else e o operador '?' if (loop 10) do_math_things(); else if (!strncmp(string, recv from:, 10)) { add_mail_from(string); from++; } else return -1; ab = (ab) ? a : b; Não há muito o que dizer aqui em relação ao if-then-else, o operador '?' realiza um teste na expressão à esquerda e se a condição for falsa retorna o primeiro valor depois do operador ou se verdadeira, o segundo valor após os ':' (dois pontos). Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  20. 20. h ttp :/ / a le x .m u la tin h o .n e t Uma rápida introdução ao C O comando switch O switch é chamado de 'if elegante', ele não é tão poderoso pois trata apenas expressões simples e geralmente apenas variáveis, é muito utilizado para selecionar opções em loops de menu. Switch switch (var) { case 2: total += var; break; case 27: total *= 25; default: total++; } O case sempre deve ser um número ou um hash, lembrando que em C um número também pode ser uma letra como em 'A', 'B' ou 'C'. Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  21. 21. h ttp :/ / a le x .m u la tin h o .n e t Uma rápida introdução ao C Funções Protótipo é escrito de forma resumida no início dos fontes. O retorno da função pode ser void (nada) ou um tipo de dado. Estruturas Declaração de Struct struct Carro { float velocidade, litros; char marca[TAM_MARCA]; char modelo[TAM_STRING]; }; struct Carro *fiat; Usando novos tipos de dados typedef struct { int tipo; int idade_maxima; char nome[32]; } Animal; Animal *cachorro; Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  22. 22. h ttp :/ / a le x .m u la tin h o .n e t Uma rápida introdução ao C Ponteiros e alocação dinâmica de memória Um dos maiores problemas para programadores iniciantes em C é a questão dos ponteiros, para ajudar a entender podemos fazer algumas armações: A memória alocada é segmentada de forma linear. Em C quando usamos o operador var estamos dizendo 'o endereço da memória do ponteiro var', e quando usamos o operador *var estamos dizendo 'o valor contido no ponteiro var'. Alocação Dinâmica de Memória char *ptr = malloc(100); int *nptr = malloc(sizeof(int) * 50); nptr = realloc(nptr, (sizeof(int) * 75)); Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  23. 23. h ttp :/ / a le x .m u la tin h o .n e t Agenda Conceitos Básicos Ferramentas importantes Um pouco de história Uma rápida introdução ao C Desenvolvendo programas Utilizando controle de versões Utilizando o autotools Debugando seu código Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  24. 24. h ttp :/ / a le x .m u la tin h o .n e t Desenvolvendo programas Vamos fazer o clássico Hello Worldpara começar, ele simplesmente imprime o texto na saída do monitor, podemos vêr a estrutura básica de um programa em C e como o compilamos. 1 #include stdio.h 2 3 int main(void) 4 { 5 fprintf(stdout, Ola meu jovem!n); 6 return 0; 7 } Duas coisas a comentar aqui: A palavra #include é utilizada para incluir bibliotecas. Palavras em C terminam suas declarações com um ';' (ponto e virgula) exceto alguns uxos de controles como: if, while, else. Compilando e rodando o programa $ gcc -o prog1 prog1.c $ ./prog1 Ola meu jovem! Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  25. 25. h ttp :/ / a le x .m u la tin h o .n e t Desenvolvendo programas Dessa vez vamos complicar um pouquinho mais, o objetivo do programa é encontrar entre dois números qual é o maior, para isso separamos o programa em três arquivos distintos: func01.c #include headers.h int main(void) { int i = 2, j = 0; for (; j loop; j++) func02(i, j); return 0; } Como compilar $ gcc -o func01.o -c func01.c $ gcc -o func02.o -c func02.c $ gcc -o func func01.o func02.o headers.h #include stdio.h #define loop 5 #define myfunc_max(a, b) a b ? a : b; func02.c #include headers.h void func02(int i, int j) { int res = myfunc_max(i, j); fprintf(stdout, in(%d,%d) maximo: %dn, i, j, res); } Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  26. 26. h ttp :/ / a le x .m u la tin h o .n e t Desenvolvendo programas Um simples Makele para projetos pequenos Para automatizar nosso processo de compilação em projetos pequenos nós criamos um arquivo chamado Makele. Abaixo podemos ver um exemplo com quatro fontes distintos e três alvos diferentes para o comando 'make' Makele all: tracker tracker: ptracker_main.c gcc -W -g -ggdb -o ptracker_utils.o -c ptracker_utils.c gcc -W -g -ggdb -o ptracker_mem.o -c ptracker_mem.c gcc -W -g -ggdb -o ptracker_main.o -c ptracker_main.c gcc -W -g -ggdb -o ptracker ptracker_main.o ptracker_utils.o ptracker_mem.o test: ptracker_funcs.c gcc -W -g -ggdb -o ptracker_funcs ptracker_funcs.c clean: rm -f *.o *~ ptracker ptracker_funcs O que este alvo faz? $ make clean O que este alvo faz? $ make test O que este alvo faz? $ make Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  27. 27. h ttp :/ / a le x .m u la tin h o .n e t Desenvolvendo programas Bibliotecas comuns Tabela de bibliotecas C ANSI C99 assert.h detecção de erros lógicos dentro dos programas errno.h códigos de erro de funções de outras bibliotecas limits.h constantes númericas padrões no ANSI C locale.h internacionalização de textos e caracteres math.h funções matemáticas úteis em C signal.h sinalização de eventos e sinais stdio.h biblioteca de entrada e saída de dados padrão string.h manipulação de strings stdlib.h alocação de memória, números randomicos, etc. Compilando código com biblitoecas alternativas Utilizando POSIX Threads $ gcc -o prog prog.c -lpthread Utilizando GTK no gráco $ gcc -o gtktest gtktest.c `pkg-cong cags libs gtk+-2.0` Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  28. 28. h ttp :/ / a le x .m u la tin h o .n e t Agenda Conceitos Básicos Ferramentas importantes Um pouco de história Uma rápida introdução ao C Desenvolvendo programas Utilizando controle de versões Utilizando o autotools Debugando seu código Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  29. 29. h ttp :/ / a le x .m u la tin h o .n e t Utilizando controle de versões Hoje em dia desenvolver qualquer coisa com mais de mil linhas de código sem um controlador de versões é confusão na certa, ainda mais se esse código precisa ser compartilhado e desenvolvido por mais de uma pessoa. Denição Como o próprio nome diz ele serve para guardar informações (autor, o que foi modicado, quando foi modicado, comentários de porque houve a modicação) sobre um determinado arquivo ou projeto em um intervalo de tempo, dando possibilidade aos integradores de juntar versões diferentes ou voltar a uma determinada versão gerada em uma linha de tempo. Imagine um projeto do tamanho do Linux com mais de 5 milhões de linhas sem um controlador de versão para mandar pra dentro o que a galera adiciona ao código!?!? Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  30. 30. h ttp :/ / a le x .m u la tin h o .n e t Utilizando controle de versões Principais características encontradas nos controladores de versão Desenvolvimento descentralizado. Marcações de momentos importantes. Controle de histórico dos arquivos do projeto. Linhas de desenvolvimento paralelas(estável, instável) ou branches para adição de novas funcionalidades. Otimização de espaço, velocidade de transações, locks exclusivos. Infelizmente não poderemos vêr todas as vantagens aqui, o assunto sobre controle de versões é bastante amplo e deve car para uma apresentação especíca. Mas vamos a algumas dicas.... Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  31. 31. h ttp :/ / a le x .m u la tin h o .n e t Utilizando controle de versões Imagine o gráco ao lado como a linha de desenvolvimento de software. Note a linha do tempo de cima para baixo. Os itens de cor: Azul Representam as releases, as tags/versões ociais do produto. Amarelo Desenvolvimento bruto, onde são adicionados itens ao projeto. Rosa Novas ramicações, onde são desenvolvidos itens antes de entrar nas versões de desenvolvimento e ou release de versões. Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  32. 32. h ttp :/ / a le x .m u la tin h o .n e t Utilizando controle de versões GIT, criado por Linus Torvalds. Abaixo podemos ver uma lista de exemplos de comando do GIT e seus signicados, acredite depois de um ou dois dias mexendo isso se torna fácil e muito útil no seu dia a dia. Cria um repositório GIT $ cd projetos/super-secreto git init Clona um repositório remoto para a máquina local $ git clone https://github.com/mulatinho/sfm.git Verica as mudanças feitas no diretório local $ git status Pega as atualizações do repositório original $ git pull Mostra as diferenças feitas no arquivo libsmb.c $ git di libsmb.c Faz commit do arquivo libsmb.c $ git commit -m '2 novas funcoes' libsmb.c Envia suas modicações ao repositório remoto $ git push origin master Lista branchs criadas $ git branch Cria branch cpp-list $ git branch cpp-list Lista todas as tags do repositório $ git tag -l Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  33. 33. h ttp :/ / a le x .m u la tin h o .n e t Agenda Conceitos Básicos Ferramentas importantes Um pouco de história Uma rápida introdução ao C Desenvolvendo programas Utilizando controle de versões Utilizando o autotools Debugando seu código Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  34. 34. h ttp :/ / a le x .m u la tin h o .n e t Utilizando o autotools Lembra como compilar um programa? Como gerar um Makele!? Agora imagine se você tivesse que compilar mais de trinta arquivos um a um e depois fazer o link dos objetos na mão, centenas de vezes, quantas vezes você erraria a ordem de compilação? esqueceria um ou outro fonte/objeto? Para evitar que isso aconteça e que você não precise sempre realizar esse trabalho de maluco, a GNU desenvolveu a ferramenta chamada autotools. Quem nunca fez!? $ ./congure $ make $ make install Apesar de eles serem scripts shell que auxiliam o usuário a gerar o binário apartir dos códigos de fonte, eles não são gerados manualmente pelos programadores do projeto. Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  35. 35. h ttp :/ / a le x .m u la tin h o .n e t Utilizando o autotools Principais módulos da ferramenta autotools Autoconf Responsável por gerar o arquivo 'congure', muito útil na hora de compilar o projeto pois ele checa se todos os pré-requisitos foram atentidos, caso não tenham sido ele geralmente retorna ao usuário o software, função, etc. que está faltando para compilar o projeto. Automake Apartir dos arquivos de entrada do 'Makefile.am' ele gera o famoso 'Makele' que é responsável por processar os comandos do usuário 'make' e 'make install'. Libtool Geralmente utilizado em conjunto com o autoconf e o automake, o libtool faz a função de cross compiler, apartir das entradas do './configure' e passando argumentos como 'arch' é possível especicar para que arquitetura será compilado o projeto. Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  36. 36. h ttp :/ / a le x .m u la tin h o .n e t Utilizando o autotools Com apenas a edição de dois arquivos, 'Makele.am' 'congure.ac' e mais três comandos (listados abaixo) geramos de forma eciente no nosso projeto o sistema de builds da GNU, tornando nossa vida mais fácil. Utilizando o sistema de builds da GNU passo-a-passo % aclocal % autoconf % touch README AUTHORS NEWS ChangeLog % automake -a configure.ac: installing `./install-sh' configure.ac: installing `./mkinstalldirs' configure.ac: installing `./missing' Makefile.am: installing `./INSTALL' Makefile.am: installing `./COPYING' Makefile.am: installing `./depcomp' Então, como gerar os arquivos necessários para o projeto!? Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  37. 37. h ttp :/ / a le x .m u la tin h o .n e t Utilizando o autotools O arquivo de entrada 'Makele.am' Arquivos do projeto: Makele.am congure.ac func01.c func02.c headers.h O arquivo 'Makele.am' é a entrada que contém a especicação de todos os seus fontes, bibliotecas de compilação (CFLAGS e LDADD), arquivos de documentação e arquivos comuns do projeto, além de diretórios para build, etc. Vejamos um exemplo bem básico abaixo de seu conteúdo: Makele.am ## Makefile.am -- Processamos este arquivo para gerar o Makefile.in ## que é lido depois para gerar o 'Makefile' através do autoconf bin_PROGRAMS = funcmax funcmax_SOURCES = func01.c func02.c headers.h ## Se eu quisesse adicionar umas flags pro C aqui eu faria: ## Já no caso de bibliotecas eu faria: ## funcmax_LIBADD = -lm -lcrypto ## funcmax_LDADD = @ Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  38. 38. h ttp :/ / a le x .m u la tin h o .n e t Utilizando o autotools O arquivo de entrada 'congure.ac' Um típico arquivo 'congure.ac' é a entrada para os comandos aclocal e autoconf, ele é denido usando a descrição macro m4 e não é tão difícil de entender depois de alguns minutos lendo sua documentação, vejamos um exemplo: congure.ac dnl Isto é um comentário e é útil para documentar suas modificações dnl Checa se o autoconf é pelo o menos da versão 2.58 AC_PREREQ(2.58) dnl Define o nome, versao e e-mail do desenvolvedor AC_INIT([funcmax], [0.1], [alex@mulatinho.net]) dnl Coloca como requisito que o automake tenha versão 1.8 ou superior AM_INIT_AUTOMAKE(1.8) dnl checa se existe um compilador C, linker, ln AC_PROG_CC AC_PROG_LN_S AC_PROG_RANLIB dnl Gera um arquivo Makefile no final AC_CONFIG_FILES([Makefile]) AC_OUTPUT Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  39. 39. h ttp :/ / a le x .m u la tin h o .n e t Utilizando o autotools Gerando o build do projeto mulatinho@forrest:~/repo/github/docs/c_basics/ex$ aclocal mulatinho@forrest:~/repo/github/docs/c_basics/ex$ autoconf mulatinho@forrest:~/repo/github/docs/c_basics/ex$ touch NEWS README AUTHORS ChangeLog mulatinho@forrest:~/repo/github/docs/c_basics/ex$ automake --add-missing mulatinho@forrest:~/repo/github/docs/c_basics/ex$ ./configure checking for a BSD-compatible install... /usr/bin/ginstall -c checking whether build environment is sane... yes .... .... checking dependency style of gcc... gcc3 checking whether ln -s works... yes checking for ranlib... ranlib configure: creating ./config.status config.status: creating Makefile config.status: executing depfiles commands mulatinho@forrest:~/repo/github/docs/c_basics/ex$ make gcc -DPACKAGE_NAME=funcmax -DPACKAGE_TARNAME=funcmax -DPACKAGE_VERSION=0.1 -DPACKAGE_STRING=funcmax 0.1 -DPACKAGE_BUGREPORT=alex@mulatinho.net -DPACKAGE_URL= -DPACKAGE=funcmax -DVERSION=0.1 -I. -g -O2 -MT func01.o -MD -MP -MF .deps/func01.Tpo -c -o func01.o func01.c mv -f .deps/func01.Tpo .deps/func01.Po gcc -DPACKAGE_NAME=funcmax -DPACKAGE_TARNAME=funcmax -DPACKAGE_VERSION=0.1 -DPACKAGE_STRING=funcmax 0.1 -DPACKAGE_BUGREPORT=alex@mulatinho.net -DPACKAGE_URL= -DPACKAGE=funcmax -DVERSION=0.1 -I. -g -O2 -MT func02.o -MD -MP -MF .deps/func02.Tpo -c -o func02.o func02.c mv -f .deps/func02.Tpo .deps/func02.Po gcc -g -O2 -o funcmax func01.o func02.o Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  40. 40. h ttp :/ / a le x .m u la tin h o .n e t Agenda Conceitos Básicos Ferramentas importantes Um pouco de história Uma rápida introdução ao C Desenvolvendo programas Utilizando controle de versões Utilizando o autotools Debugando seu código Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  41. 41. h ttp :/ / a le x .m u la tin h o .n e t Debugando seu código Por quê debugar?? Debugar é o ato de conrmar que algo que você pensa que é verdadeiro de fato o é, ou que, provando passo a passo você descubra que algo não é tão verdadeiro quanto você pensava ser. Um bug nada mais do que uma condição de erro, falha ou algo que é inesperado numa série de rotinas que deveriam seguir uma lógica conhecida. Debugar então é necessário para conrmar que seu programa está seguindo todas as rotinas que você escreveu sem condições desconhecidas a você. Alguns motivos para debugar: Identicar um erro e/ou condição Acompanhar uma rotina detalhadamente Determinar loop innito, execuções de threads, variáveis, etc. Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  42. 42. h ttp :/ / a le x .m u la tin h o .n e t Debugando seu código Utilizando o GDB O GDB é o projeto da GNU para debugar aplicativos escritos principalmente em C/C++ mas também tem capacidade de interagir com muitas outras linguagens, nós vamos focar aqui na ferramenta de console para que você possa entender processos básicos na etapa de debug de um programa. Compilando programa e rodando no GDB $ gcc -g -o program1 program1.c $ gdb program1 (gdb) run argv1...argvN Principais erros buer overow stack overow memory leak loops, retornos de função, etc. gdb1.c example 1 #include stdio.h 2 int main(void) { 3 char *things[] = 4 { casa, carro, viajar }; 5 int i = 0, x = 0, j = 0; 6 while (1) { 7 if (x == 11) break; 8 printf(i=%d, x=%d, j=%d, %sn, 9 i, x, j, things[i]); 10 if (!(i % 3) i!=0) { 11 i = 0; x+=2; 12 } else 13 i++; 14 15 x++; 16 j = ((2^4) * i) + x; 17 } 18 return 0; 19 } gdb2.c example 1 #include stdio.h 2 3 void set_pointer(char *p) 4 { 5 *p = 10; 6 } 7 8 int main(void) 9 { 10 char *p = NULL; 11 12 set_pointer(p); 13 14 return 0; 15 } Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  43. 43. h ttp :/ / a le x .m u la tin h o .n e t Debugando seu código Utilizando o GDB, parte 2 comandos descrição run roda o programa em questão, pode usar argumentos. break / watch seta um breakpoint/watchpoint dentro do código fonte. step / next step, adentra na subrotina dentro da função atual. ja o next vai para a proxima linha da função atual. continue continua a execução até que o próximo breakpoint seja encontrado no código. print / display imprime o valor de uma variavel, struct, dado. info mostra informações de registradores, variáveis locais, etc. exemplo debugando com gdb, parte 1 $ gdb gdb2 (gdb) b 8 Breakpoint 1 at 0x400567: file gdb2.c, line 8. (gdb) r ..... (gdb) c Continuing. i=2, x=8, j=20, viajar Breakpoint 1, main () at gdb2.c:8 8 printf(i=%d, x=%d, j=%d, %sn, exemplo debugando com gdb,parte 2 (gdb) display things[i] 1: things[i] = 0x400440 _start 1355I211... (gdb) p i $1 = 3 (gdb) n i=3, x=9, j=27, 1ï¾ 1 2 Iï¾ 1 2 ï¾ 1 2 ^Hï¾ 1 2 .. 10 if (!(i % 3) i!=0) { .... (gdb) n 15 x++; (gdb) p x $2 = 12 Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  44. 44. h ttp :/ / a le x .m u la tin h o .n e t Debugando seu código Para os que não gostam de comandos de console é claro que temos soluções livres e grácas!! É o estilo do DDD. Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  45. 45. h ttp :/ / a le x .m u la tin h o .n e t Debugando seu código Utilizando o strace O 'strace' é utilizado para rastrear com detalhes ou de forma resumida chamadas de sistema executadas dentro de softwares Chamadas de sistema são requisições de serviços denidos diretamente no kernel com uma função especíca. Sempre que você carrega uma biblioteca, lê ou escreve em um arquivo você está executando uma chamada do sistema. No linux as chamadas do sistema estão descritas no cabeçalho /usr/include/asm/unistd.h. Como executar o strace? $ strace -c ps ax % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 61.08 0.001083 1 834 read 20.70 0.000367 1 720 6 open 11.17 0.000198 0 715 close 7.05 0.000125 0 268 10 stat ------ ----------- ----------- --------- --------- ---------------- 100.00 0.001773 2628 20 total Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  46. 46. h ttp :/ / a le x .m u la tin h o .n e t Debugando seu código Utilizando o strace, parte 2 Também podemos analisar detalhadamente cada chamada, abaixo podemos ver a simples saída do strace sem muito detalhamento mas que nos ajudam bastante 1 $ strace nc localhost 1111 2 execve(/usr/bin/nc, [nc, localhost, 1111], [/* 51 vars */]) = 0 3 open(/lib64/libssl.so.10, O_RDONLY|O_CLOEXEC) = 3 4 read(3, 177ELF2110000000003001000260203201246000..., 832) = 832 5 socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 3 6 fcntl(3, F_GETFL) = 0x2 (flags O_RDWR) 7 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0 8 connect(3, {sa_family=AF_INET, sin_port=htons(1111), 9 sin_addr=inet_addr(127.0.0.1)}, 16) = -1 EINPROGRESS (Operation now in progress) 10 select(4, [3], [3], [3], {10, 0}) = 2 (in [3], out [3], left {9, 999995}) 11 getsockopt(3, SOL_SOCKET, SO_ERROR, [111], [4]) = 0 12 write(2, Ncat: , 6Ncat: ) = 6 13 write(2, Connection refused.n, 20Connection refused.) = 20 14 +++ exited with 1 +++ Alguns itens a observar: Na linha 2 (dois) é mostrado a execução do comando na shell. Na linha 3 (três) é carregada uma biblioteca SSL. Na linha 8 (oito) vemos claramente o retorno -1 da execução do programa bem como os argumentos passados pela função connect() Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  47. 47. h ttp :/ / a le x .m u la tin h o .n e t Debugando seu código Valgrind para memória O valgrind analisa erros de softwares diretamente ligados a memória, é muito útil para descobrir memory leaks. O código ao lado mostra um programa com dois problemas: um comportamento indenido (um dos erros mais difíceis de detectar sem uma ferramenta adequada em C) e um vazamento de memória devido ao alocamento sem liberação. O valgrind aponta a quantidade de bytes escritos na memória que contém erros ou vazamento. gdb4.c example 1 #include stdio.h 2 #include stdlib.h 3 #include time.h 4 5 int main(void) 6 { 7 int i; 8 char *ptr = malloc(sizeof(int) * 100); 9 10 srand(time(NULL)); 11 for (i=0; i110; i++) 12 *(ptr + i) = (rand() % 255) + 1; 13 14 return 0; 15 } Identica a função responsável e a linha dentro do código fonte. Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  48. 48. h ttp :/ / a le x .m u la tin h o .n e t Debugando seu código Valgrind para memória, parte 2. 1 $ gcc -g -Wall -o gdb4 gdb4.c 2 $ valgrind --leak-check=full ./gdb4 3 ==18493== Memcheck, a memory error detector 4 ..... 5 ==18493== HEAP SUMMARY: 6 ==18493== in use at exit: 400 bytes in 1 blocks 7 ==18493== total heap usage: 1 allocs, 0 frees, 400 bytes allocated 8 ==18493== 9 ==18493== 400 bytes in 1 blocks are definitely lost in loss record 1 of 1 10 ==18493== at 0x4C2C5AB: malloc (vg_replace_malloc.c:270) 11 ==18493== by 0x40071A: main (gdb4.c:8) 12 ==18493== 13 ==18493== LEAK SUMMARY: 14 ==18493== definitely lost: 400 bytes in 1 blocks 15 .... Na linha 9 até a linha 11 vemos claramente que houve um vazamento de memória provocado pela linha 8 do nosso programa gdb4.c Finalmente o resumo nal conrma o vazamento de memória e informa quantos bytes foram perdidos. Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix
  49. 49. h ttp :/ / a le x .m u la tin h o .n e t Isso é tudo pessoal! Dúvidas e Sugestões? Alexandre Mulatinho Twitter: @alexmulatinho E-mail: alex@mulatinho.net Weblog: http://alex.mulatinho.net Alexandre Mulatinho E-mail: alex@mulatinho.net Introdução ao desenvolvimento em ambientes Unix

×