Ir para conteúdo
  • Cadastre-se
  • Entre para seguir isso  

    O que fazer com o C que se aprendeu na faculdade

       (0 análises)

    Fernando Mercês

    Introdução

    Em muitas faculdades brasileiras a linguagem C é ensinada aos alunos de cursos de tecnologia. Mesmo assustando os novatos, vários alunos resistem e vencem a matéria. O problema é entender por qual motivo o C foi escolhido para iniciar o curso de programação. Seria uma linguagem didática para se aprender a programar? Um teste para ver quem tem ou não o “jeito pra coisa”? Alguns diriam que o correto seria começar com Pascal, mas há quem defenda linguagens mais modernas como Python, Perl, Ruby ou PHP. E aí, para que serve o C no primeiro período? Neste artigo farei uma análise sobre o que se aprende da linguagem, o motivo pelo qual ela surge no início do curso, seu valor de mercado e o que é possível fazer com esse start que a faculdade nos dá.

    A linguagem C

    A importância histórica da linguagem C é inegável e dispensa maiores comentários. Sabemos que até hoje a maioria dos softwares mais poderosos são feitos em C e/ou C++ (um super conjunto de C, orientado à objetos). O kernel Linux e outros núcleos de SOs são feitos basicamente em C. Muitos drivers de dispositivos como placas de rede, som, vídeo etc são feitos em C. Se contarmos o C++ nesta conta, chegamos perto de 100% dos kernels e drivers. Os interpretadores e compiladores das principais linguagens de programação também não fogem à regra e são feitos em C. Existe uma frase que afirma: metade do universo é feito em C. E é bem verdade. Pelo visto, a linguagem serve para alguma coisa…

    Ensino da linguagem C

    Você acabou de entrar na faculdade, está tendo aulas desta linguagem e não está entendendo nada? Não se preocupe, você não está sozinho. Algumas instituições de ensino acham que C é uma liguagem didática, quando não é. Para se aprender a programar, usa-se pseudo-linguagem, PORTUGOL e ferramentas do gênero. Nem mesmo o Pascal, considerado mais fácil de se aprender que o C, é atraente ou interessante à primeira vista. O grande monstro que aterroriza o aluno é a pergunta: “Por que eu vou fazer isso? Para que?”. Pois é, para que escrever um programa em C que calcule a média de três alunos e imprima na tela? Qual a lição tirada disso? A resposta é simples: nenhuma. A maneira como a linguagem é lecionada tenta empurrar o C guela abaixo em estudantes que viram, por exemplo, Visual Basic e Delphi no segundo grau. Isto é, se é que estudaram tais linguagens ou lembram-se delas. Não poderia dar certo mesmo.

    Antes de criar um programa, o aluno tem que saber o que está fazendo. O que é um programa, para que serve isso, o que é um arquivo executável, um binário, bits, bytes, o processador, dentre outros conceitos importantíssimos antes de se escrever o primeiro “Hello World”.

    O resultado do ensino forçado é o alto íncide de reprovação, abandono, mudança de curso e desistência. É comum encontrar alunos que estão no fim do curso de programação mas ainda não passaram nas matérias mais básicas de C. É o terror da faculdade. Definitvamente, a linguagem C vira uma vilã e a frase mais ouvida nos corredores sobre o assunto é que “C é chato”.

    Por que a linguagem C é chata?

    Porque ela não te mima. Numa escala onde o nível mais alto é o mais próximo da linguagem usada pelo ser humano e o mais baixo, da linguagem usada pelos microprocessadores, a linguagem C é considerada de nível médio. Assembly, por exemplo, é de baixo nível, enquanto Object Pascal (usada no Delphi), de alto nível. Isso significa que para programar em C é preciso conhecer conceitos mais próximos do hardware, que as linguagens de alto nível abstraem para o programador, tornando o trabalho mais fácil. Por isso temos a impressão de que C é chato, difícil, sem sentido. Realmente, sem os conceitos básicos de computação bem sólidos, um código em C pode tornar-se incompreensível. Vejamos um exemplo.

    Um código em PHP (alto nível) para se declarar uma variável e armazenar uma frase nela:

    <?php
    $str = Essa é minha string”;
    ?>

    Um código equivalente em C, seria:

    void main(void)
    {
    	char str[] = Essa é minha string”;
    }

    No código em C, uma função teve de ser escrita (a main, que é a função principal de um programa), inclusive com seu tipo de retorno e parâmetros, onde usei void para não retornar nem receber nada. Além disso, foi criado um vetor de caracteres (char) para armazenar a frase. Em C, entende-se como string um vetor de caracteres (ou ponteiro para um conjunto deles) onde o último caracter é o NULL, código 0x00 na tabela ASCII. Tá vendo por que se precisa dos conceitos de computação até para começar uma frase em C? Agora perceba a jogada:
     

    #include <string.h>
    
    void main(void)
    {
    	char str[21];
    	strcpy(str, Veja, sou uma string”);
    }

    A função strcpy(), fornecida pelo header string.h, copia caracteres para uma variável do tipo vetor (ponteiro, na verdade, mas isto é outro assunto) de caracteres e adiciona um caractere nulo (NULL), zerado, na última posição. Perceba que iniciamos o vetor de char com 21 posições, para abrigar os 20 caracteres da frase proposta mais o NULL, que é um caractere só. As coisas começam a fazer sentido, apesar de “feias”, não?

    E assim é o C. Exigente, porém elegante. Se tem os conceitos de computação, sem dúvida não terá grandes dificuldades com a linguagem.

    Usando o C na vida e no mercado de trabalho

    Certo, você se convenceu de que C é legal de aprender, poderoso e aprendeu. E agora, faz o quê? Tem um colega seu ganhando dinheiro fazendo sites em Ruby on Rails. Outro faturando uma grana fazendo sistemas em Delphi para clientes, com imagens, botões brilhantes e multimídia. O que você, recém-estudado programador em C vai fazer com aquela tela preta pedindo dados com scanf()? Nada. Não é assim que se trabalha com C, ou pelo menos, não mais. Já foi o tempo em que os sistemas eram feitos dessa maneira. Além disso, mesmo nesse tempo a linguagem C foi rapidamente substituída neste meio pela linguagem CLIPPER no mundos dos PCs e pelo COBOL, nos mainframes.

    O forte do C hoje são aplicações desktop, inclusive as baseadas em rede e daemons (serviços). C também é útil para escrever compiladores e interpretadores para outras linguagens, por exemplo. Sabia que o PHP é escrito em C? Pois é, assim como Python, Ruby, BASH e muitos outros interpretadores. Então tem alguém ganhando dinheiro com C por aí, concorda?

    Vale a pena citar também o desenvolvimento embarcados, para microcontroladores e vários microprocessadores, incluindo ARM (usado em vários aparelhos Android).

    Em novembro do ano passado houve uma edição de um evento chamado Universidade Livre em que Olivier Hallot, diretor da ALTA (antiga BrOffice.org) falou durante alguns minutos numa faculdade carioca da dificuldade de encontrar programadores para contratar e fez um apelo para que os alunos levem a sério que o mercado está muito carente de bons programadores, principalmente em C/C++. Também em setembro do ano passado uma empresa publicou uma vaga no Rio de Janeiro buscando um profissional com os seguintes conhecimentos:

    • Sistema Operacional Linux;
    • Banco de dados MySQL;
    • Criação e manutenção de tabelas, relacionamentos, scripts, etc.;
    • Linguagem C, e das APIs: (V4L2), GTK, além de OpenGL;
    • Adobe Flex.

    O salário inicial era de R$ 5.000,00. A vaga deve estar aberta até hoje…

    Em dezembro de 2011, uma grande operadora telefônica abriu nada menos que 20 vagas para desenvolvedores em C no Rio de Janeiro. Empresas que atendem infraestrutura, telecomunicações, embarcados, móveis, desenvolvimento do Linux e kernels derivados também precisam muito de programadores deste tipo. Enfim, vagas não faltam!

    Então por que aprendo Java na faculdade?

    A faculdade tenta ser a mais moderna possível, mas esquece de verdadeiramente orientar na profissão. Java é uma linguagem potente, flexível e poderosa mas tem um fim completamente diferente da linguagem C. Com Java se programa para web, dispositivos móveis, aplicações locais (pouco usada), sistemas de informação, embarcados etc. A flexibilidade é enorme, mas o foco é outro. Não se faz uma suíte de aplicativos em Java, simplesmente porque existe o C pra isso. Um sniffer de rede ou um software ping, por exemplo, são feitos em C, porque C é pra isso. Já uma interface de um aparelho GPS, é feita em Java. Questão de adeqüação. O mercado de Java é tão grande quanto o de C no mundo, mas é maior no Brasil. No entanto, o que não pode é a faculdade tratar a linguagem C como uma introdução à programação, para que o aluno depois aprenda Java. Uma coisa não tem nada a ver com a outra. São dois nichos completamente diferentes e em ambos os casos, é possível conseguir um bom emprego e alavancar na profissão, tanto aqui quanto fora.

    Minha faculdade usa Python para ensinar a programar. É legal?

    Não creio. Python é super divertido e viciante mas não exige os conceitos de computação que todo programador deve ter. A resposta é a mesma para todas as linguagens de alto nível. Como escrevi anteriormente, se começa a programar com uma pseudo-linguagem, para desenvolver a lógica. Antes do estudo de programação médio/alto nível, é preciso estudar computação, do ponto de vista da arquitetura em si (que vai incluir Assembly, SO etc) e aí sim, subir de nível. Se bem gerenciado, é possível manter estas disciplinas em paralelo, mas o programa deve ser cuidadoso (o que as instituições não andam respeitando – Eu já vi projeto de bancos de dados no segundo período. O aluno, teoricamente, nunca usou uma mysql.h ou outras bibliotecas para acesso a SGBD’s em outras linguagens).

    Quem aprende direto no alto nível e se dá bem, ótimo – e está de parabéns. Mas o objetivo do artigo é trazer a linguagem C à tona e não competir com outras linguagens.

    Venho comprovando a tese de que aprender “de baixo para cima” dá certo. Já consegui fazer um amigo escrever um programa em Assembly do zero para calcula a média de alunos. Aí sim ele viu o que é obter dados do teclado, calcular e exibir. Teve de entender por completo a tabela ASCII, uso de registradores gerais, syscalls e interrupções de software. Quando foi para o C, não teve o menor problema.

    E o que dá pra fazer com o C aprendido na faculdade?

    Só com ele, não muita coisa, mas com um pouquinho de pesquisa e afinco, gera-se resultados. Um exemplo é o grupo Coding 40°, onde eu e mais três alunos do curso de Ciência da Computação nos unimos para estudar e acabamos desenvolvendo um pequeno software, capaz de imprimir informações sobre executáveis PE (.exe, .dll etc) na tela. Nada complicado, agora que já está pronto. rs

    Sabe quando você está no Windows e vai nas propriedades de um .exe ou .dll e há uma aba “Versão” como na imagem abaixo?

    1-versao-tab.png.8b374d53e2115d14146a1127a8d6e160.png

    A proposta inicial era criar um software capaz de conseguir essa informação, recebendo como entrada o caminho do arquivo executável. O software deveria funcionar no Linux, já que nesse SO não é possível ver esta aba “Versão” nas propriedades dos executáveis de Windows, obviamente. Foi aí que fizemos o pev. Hoje ele já exibe várias outras informações sobre o executável além da versão.

    Conclusão

    Estudar C, C++, Assembly e outras linguagens tidas como “terríveis” é, sem dúvida, uma boa pedida. Há inúmeros projetos no mundo todo precisando de bons programadores nessas linguagens. Não encare o “C de faculdade” como um vilão ou uma introdução à programação porque não é. A linguagem C é uma linguagem poderosa e comercial. Nada de dizer que C é coisa de maluco.

    Ainda não sabe o que fazer com C? Está em dúvida sobre seus aspectos modernos? Nós temos um curso de programação moderna utilizando a linguagem C para você :)

    Entre para seguir isso  


    Feedback do Usuário

    Join the conversation

    You can post now and register later. If you have an account, sign in now to post with your account.

    Visitante

  • Conteúdo Similar

    • Por Candeer
      Olá! No artigo anterior falamos sobre Signals, que é de suma importância para a comunicação entre processos, mas para construir o nosso debugger precisamos muito mais do que apenas isso, precisamos de fato ter total controle sobre um dado processo e se possível controlar até o seu própio início.
      Neste artigo será explicado o que são forks e seu uso em desenvolvimento de aplicações em sistemas UNIX. Sem mais delongas, vamos prosseguir!!!😀
      Resumidamente a syscall fork é usada para a duplicação e criação de um processo. Quando um dado processo chama a função fork(), é criada uma cópia idêntinca de seus dados. Note que apenas uma cópia é feita, o processo filho não compartilha o mesmo espaço de memória do pai.
      A syscall fork retorna um PID que é usado para indetificar em qual processos estamos e também dar acesso ao ID do processo filho. Caso o PID seja 0 estamos executando no filho, caso seja qualquer outro somos o processo pai, isso ocorre pois o pai precisa saber o PID do filho, mas o filho não necessariamente precisa saber o seu própio (da mesma maneira que o seu processo não sabe o própio PID ao menos que o mesmo peça).
      Algo interessante de se notar é que os Init System usados para subir e gerenciar serviços de sua máquina trabalham dessa mesma maneira, você pode checar sua árvore de processo usando comando pstree:
      $ pstree Dessa maneira você tem uma representação bem visual de como está dividida a sua estrutura de processos 😀. Note que todos os processos são filhos do seu Init system (seja ele SystemV, Systemd, etc). Aconselho você explorar o comando pstree para uma visão bem mais detalhada do seu sistema! Outra abordagem é usar o própio comando ps:
      $ ps -ef Rode o comando acima (dependendo da quantidade de processos use um pipe para o less 😉) e com ele teremos uma visão mais detalhada. A coluna PID representa o ID do processo em si e a coluna PPID representa o "Parent Process ID", que nada mais é que o ID do processo pai. Note que o PID 1 é o seu Init System e os seus processos rodam como filho dele!

      Vale notar que o processo Pai do própio init é o PID 0, que é conhecido como "swapper" ou "scheduler", que é o processo responsavel para realização de paging. Paging é o sistema de gerenciamento de memória que salva os dados da RAM em uma memória secundária (HD, SSD e etc) e recupera em formato de páginas (outros PID também são filhos do propio PID 0 como PID 2 que gerencia todas as threads que rodam em Kernel Land(KThread) etc).
       
      Programando Forks
      A syscall fork está na lib  <unistd.h> (Unix Standard library) e tem a seguinte construção:
      #include <sys/types.h> #include <unistd.h> pid_t fork(void); Precisamos incluir a lib <sys/types.h> para que seja possivel acessar o tipo pid_t. A função fork não espera nenhum parâmetro para a sua construção e o código abaixo demonstra o quão simples é cria um fork.
      #include <stdio.h> // Acesso a syscall #include <unistd.h> // Acesso ao tipo variavel pid_t #include <sys/types.h> int main(void) { int x; printf("Processo normal...\n"); printf("Forking...\n"); sleep(5); pid_t pid = fork(); x = 40; if (pid == 0) { printf("Eu sou o processo filho meu PID: %d\n", pid); } else { printf("Eu sou o processo pai de %d\n", pid); } sleep(5); return 0; } Compile o código acima da seguinte forma:
      $ gcc -o fork fork.c $ ./fork Note que o código se "divide" a partir da chamada fork e um if  é usado para saber se estamos executando no pai ou no filho, note também que o pai sabe o PID e o filho não.
      Para melhor visualização o código acima roda por 10 segundos (por conta da chamada ao sleep com esse tempo de espera). Abra um outro terminal e rode o comando:
      $ watch -n1 pstree O comando acima vai executar o pstree a cada 1 segundo, desta forma você verá o exato momento da criação do fork.

      Comunicando-se com o processo fork
      Agora imagine que um  processo precisa esperar o seu filho terminar algum trabalho e dependendo do seu sinal o processo pai realiza alguma ação. A comunicação entre o processo pai e o filho se da por signals. O pai pode saber exatamente o estado do seu processo filho usando a syscall wait e waitpid, ambas na lib <sys/wait.h>:
      #include <sys/types.h> #include <sys/wait.h> pid_t wait(int *status); pid_t waitpid(pid_t pid, int *status, int options); A syscall wait espera que ao menos 1 de seus processos filho troque de estado, já a waitpid espera por um processo específico. Como sabemos exatamente qual processo queremos rastrear iremos usar esta call 😀:
      #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> int main(void) { printf("Spliting work...\n"); pid_t pid = fork(); if (!pid) { int a = 0; for(int i = 0; i < 100000000; i++ ) { a += i*2 + 10 *i; } return 9; } int status; int signal; printf("Waiting child finish work...\n"); waitpid(pid, &status, 0); if (WIFEXITED(status)) { signal = WEXITSTATUS(status); printf("Child exited, status = %s\n", strsignal(signal)); } return 1; } Compile o código acima e execute:
      $ gcc -o work work.c $ ./work Spliting work... Waiting child finish work... Child exited, status = Killed Veja que após a chamada de fork nosso processo filho executa várias iterações e realiza um cálculo (um cálculo totalmente randômico) e após isso retorna 9. Este retorno em questão é apenas por motivos educativos (no artigo anterior falamos de sinais e como eles funcionam). O processo pai usa a syscall waitpid para esperar que qualquer signal seja enviada do pid especificado. Após receber um status é verificado se o fork saiu (WIFEXITED) e se sim, pegamos o signal enviado usando WEXITSTATUS(status da saída) e usamos a chamada strsignal(provida pela string.h) para recuperar uma versão em texto do signal. Nesse caso iremos recuperar o signal "KILLED", pois colocamos 9 apenas por razões educativas.
      Normalmente se tudo ocorreu bem colocamos 0 (inclusive é dessa maneira que sua shell avalia se o programa rodou certo).
      $./work && echo "Filho saiu com 0, tudo certo..." || echo "Filho saiu com 1, algo errado..." No caso acima a nossa shell irá criar um fork do nosso work, executar o nosso programa (que por sua vez também executa um fork mas não entra em questão aqui) e se o signal retornado pelo fork for 0 ele imprime uma mensagem, caso contrario ele imprime uma mensagem de erro, dessa maneira você pode orquestrar um shell scripting usando o própio retorno do processo 😉
      Tente mudar o retorno do fork acima e verifique seu status usando funções providas pela <sys/wait.h>. No exemplo acima usamos apenas a call WIFEXITED e WEXITSTATUS, mas existem várias outras.
      Forks são de extrema importância para criação e gerenciamento de processos e iremos usar forks para que seja possível executar o programa que queremos debugar, dessa maneira o software em questão vai ser filho do nosso debugger, o que nós da total controle sobre o mesmo.
      Comentarios são todos bem vindos e todos os códigos usados estão disponíveis no github! 😀

      Links úteis:
          Process Control
          fork
          wait
          Process State
          Fork Bomb - Cuidado com isso
    • Por void_
      Depois de um bom tempo programando em C e adquirindo uma paixão legítima por Assembly (essa a nem tanto tempo assim, infelizmente), resolvi dar mais uma chance a programação de alto nível. Como já tenho uma boa base em C, achei apropriado partir para o C++, já que nunca me dei bem com Java, contudo os livros não estão me animando muito. Eu comecei lendo o livro oficial do C++ (do Bjarne) e também o C++ Primer, considerado um best seller desde a primeira edição. Foi um sofrimento e tanto ler esses livros. Em ambos foram mais de cinquenta páginas de filosofia verborrágica para começar a entrar no bê-a-bá da linguagem (que obviamente me fez desanimar antes de chegar na metade). Achei esses livros muito mal estruturados. A impressão que passa é que os autores não querem ensinar nada, porque eles fazem questão de deixar o livro o mais enfadonho possível. Não digo que não é importante ensinar a parte "filosófica" da linguagem, mas acredito que seria melhor nivelar entre a prática e a teoria de forma progressiva. Enfim, não sei se sou eu que sou chato e impaciente demais ou se o problema são os livros, porque quando finalmente chega na parte "interessante", a leitura já me drenou toda a energia e vontade de continuar a leitura, aí começam os bocejos, a canseira na mente e na vista, etc. A coisa piora ainda mais porque, quando enfim chega na prática, 50% do conteúdo é herança do C que você (no caso eu) já sabe.
      Outro problema é a desatualização do material em português que temos acesso aqui. Enquanto no estrangeiro o pessoal trabalha com a versão 17, ainda estamos na 11, no máximo 14.
      Abri esse tópico para pedir alguma indicação de algum livro de C++ que fuja das questões que eu citei.
    • Por Candeer
      Olá, neste artigo compartilharei um pouco da minha pesquisa no desenvolvimento de debuggers. No momento estou trabalhando em um protótipo de debugger para Linux, mas nada tão avançado quanto um gdb ou radare (muitas coisas são necessárias para chegar neste nível de maturidade de software).
      O desenvolvimento de debuggers é uma atividade muito interessante, já que, em sua forma mais básica, pode ser resumido em uma série de chamadas de sistema (syscalls) para que seja possível o controle do processo a ser depurado (muitas vezes chamado de debuggee) e de seus recursos, mas não vamos colocar a carroça na frente dos cavalos e vamos em partes.
      Antes de começarmos a discutir detalhes mais específicos acerca da depuração de processos, é necessário um entendimento básico de como os mesmos se comunicam na plataforma que vamos desenvolver o tal debugger, no nosso caso, UNIX-like.
      Inter-process communication (IPC)
      IPC é uma forma que processos podem utilizar para se comunicar dentro de um sistema operacional. Existem diversas maneiras de comunicação: via sinais (signals), sockets, etc, mas para a criação de um debugger é apenas necessário usar sinais para a execução.
      Sinais funcionam como uma notificação que pode ser enviada à um processo específico para avisar que algum evento ocorreu.
      É possível também programar um processo para reagir aos sinais de maneira não padrão. Se você já teve um uso razoável de Linux, você provavelmente já enviou sinais à um processo. Por exemplo, quando você aperta Ctrl+C para interromper a execução de um processo, é enviado um sinal do tipo SIGINT, que nada mais é que uma abreviação para Signal Interruption. Se o processo em questão não está preparado para reagir a este sinal, o mesmo é terminado. Por exemplo, considere o seguinte código:
      #include <stdio.h> int main(void) { while(1) printf("hi\n"); return 0; } Ao compilar e executar o código acima e apertar Ctrl+C, o mesmo encerra como esperado, porém podemos verificar que um SIGINT foi enviado usando a ferramenta ltrace, que além de listar chamadas a bibliotecas também mostra os sinais enviados ao processo:
      $ gcc -o hello hello.c $ ltrace ./hello Rode o comando acima e aperte Ctrl+C para verificar o sinal enviado!
      Programando reações a sinais
      A capacidade de enviar sinais a um processo nos dá a possibilidade de saber o que esta acontecendo com algum processo específico que estejamos depurando.
      Para programar reações a algum tipo de sinal, podemos incluir a biblioteca signal, para que possamos usar a função e estrutura (struct) sigaction:
      struct sigaction { void (*sa_handler)(int); void (*sa_sigaction)(int, siginfo_t *, void *); sigset_t sa_mask; int sa_flags; void (*sa_restorer)(void); };  
      int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); A struct sigaction nos permite adicionar handlers (tratadores) para nossos sinais, enviando o endereço de nossa função que realiza algum tipo de ação baseada no sinal enviado para o campo sa_handler(sigaction handler).
      Um handler neste contexto nada mais é que uma função que sempre vai ser chamada quando um dado sinal for enviado, dessa maneira podemos executar alguma ação quando recebermos um sinal.
      Já a função sigaction recebe o número do sinal, porém uma série de macros já são pré-definidas e podemos passar como argumento apenas o nome do sinal, como SIGINT por exemplo. A função recebe também a referência da struct previamente definida (struct sigaction) e, caso precise trocar um handler por outro, também recebe no último argumento (oldact) o handler anterior, para que possa ser feita a troca pelo novo. Como não é o nosso caso, vamos passar NULL neste último argumento.
      O código abaixo simula um uso de handlers de sinais, que imprime uma mensagem quando um sinal é enviado:
      #include <stdio.h> #include <signal.h> #include <unistd.h> // sleep void simple_handler(int sig) { printf("Hello SIGINT\n"); } int main() { struct sigaction sig_handler = { simple_handler }; sigaction(SIGINT, &sig_handler, NULL); sleep(1000); return 0; } Ao executar o código acima, aperte Ctrl+C e veja que será imprimido a mensagem do nosso handler!
      O manual da signal contém uma tabela com todos os sinais usados por sistemas POSIX.
      Para enviarmos sinais facilmente em sistemas UNIX podemos usar o comando kill:
      $ kill -l O comando acima mostra todos os sinais e seus respectivos números, com isso podemos fazer algo interessante. Por exemplo, rode o código acima em um terminal separado e use o kill para se comunicar com o seu processo, assim:
      $ ps ax | grep simple_signal $ kill -2 <pid> Primeiro buscamos o PID do nosso processo então usamos o kill que espera como primeiro argumento numero do sinal (listado em kill -l) e o segundo o PID do processo alvo.
      Ao enviar o sinal, podemos ver que o nosso código reage aos sinais que foram associados a um handler especifico! Tente criar handlers para vários sinais e teste usando o comando kill. 😃
      Abaixo um código para demonstrar um uso real de um software que escreve dados aleatórios nos arquivos temporários e antes de uma finalização abrupta, é deletado o que foi usado:
      #include <stdio.h> #include <signal.h> #include <unistd.h> // Log errors void fatal(const char* err_msg) { fprintf(stderr, "Error: %s\n", err_msg); } // Escreve algo random em um arquivo void random_work() { FILE* temp_files = fopen("/tmp/foo", "w"); if (!temp_files) { fatal("Cant open foo!"); } else { fprintf(temp_files, "%s", "Random random random!\n"); fclose(temp_files); } } // Handler para deleta arquivos criados void handler_termination(int sig) { // Verifica se existe usando a function access // Caso existe usa a syscall unlink para remover o arquivo if (access("/tmp/foo", R_OK) < 0) return; unlink("/tmp/foo"); printf("All clean! closing...\n"); } int main() { //struct sigaction que recebe a function handler_termination como valor do seu handler struct sigaction interruption_handler; interruption_handler.sa_handler = handler_termination; // Syscall sigaction que associa o nosso handler para um sinal especifico // O ultimo campo NULL, espera o handler anterior para que posso tornar o novo handler o default sigaction(SIGINT, &interruption_handler, NULL); random_work(); sleep(1000); handler_termination(0); return 0; } Dica: Dê uma olhada na tabela de sinais e crie handlers para o mesmo código acima!
      Para a construção do nosso debugger iremos focar mais no signal SIGTRAP, para que seja possível detectar se o nosso processo sofreu uma "trap" da CPU. Uma trap ocorre quando acontece alguma interrupção síncrona na execução, que faz o processo ficar parado até que o sistema operacional execute alguma ação. Isto será usado para implementar e interpretar breakpoints. Veremos tudo isso com mais detalhes em breve!
      Sinta-se livre para comentar e sugerir correções e melhorias. Até o próximo artigo!
      Links úteis:
      Syscall IPC CERO 11 – Linux Syscalls Syscalls, Kernel mode vs User mode Programação em C
    • Por Eduardo Cintra
      Alguém me indica um bom livro para aprender programação utilizando sockets em C? Pode ser em inglês.

      Desde já agradeço!
    • Por Fernando Mercês
      Essas são algumas gafes que vez ou outra flagramos a galera de TI caindo. Na prática são termos confusos que já foram utilizado de forma inadequada muitas vezes e a intenção deste artigo é desmistificar, de uma vez por todas, alguns conceitos. 😌
      Programação em HTML
      HTML (HyperText Markup Language), como o próprio nome sugere, é uma linguagem sim, mas não é de programação. Para ser, esta precisaria expressar um algoritmo que pudesse utilizar-se de estruturas de controle e loop, por exemplo, recursos fundamentais para qualquer linguagem de programação. Logo, quem sabe HTML sabe criar páginas em HTML. Programar é outra história…
      Estabilizador não serve pra nada Infelizmente ele serve pra estragar sua fonte. Isso mesmo, o trabalho de estabilização feito por estes componentes é tão mal feito e lento, que ao tentar corrigir uma anomalia na energia ele atrapalha a fonte, que seria capaz de corrigir sozinha, mas é obrigada a esperar o estabilizador fazer seu trabalho porco e corrigir a anomalia duas vezes! O investimento correto deve ser feito na fonte do computador, sem economia porca. Um filtro de linha pode ser prático no caso de um spike (grandes descargas de curto prazo, como as geradas por raios) porque o fuzível dele pode abrir e proteger o da fonte (que é mais chato de trocar porque tem que tirá-la do computador e abri-la), mas proteção mesmo é na fonte e por isso é interessante adquirir uma boa, mas só faz sentido para desktops montados. No mundo atual, onde os laptops dominam, estabilizadores não servem para nada mesmo. 😝
      O positivo e negativo da tomada…
      O tipo de corrente que chega em nossas tomadas é chamado de alternada. Neste tipo não há pólos positivo ou negativo, mas sim fase e neutro. Na fase há a tal alternagem de polaridade, entre positivo e negativo, cerca de 60 vezes por segundo no caso das capitais brasileiras. O neutro é ligado à terra em algum momento e ao conectar algum componente (como uma lâmpada) entre este caminho fase-neutro você faz com que energia passe pelo componente. No caso da lâmpada, ela acende. 💡 Vale a pena estudar o básico sobre corrente contínua e corrente alternada porque o assunto é longo.
      Baixei o drive da placa de…
      Você baixou o driver, filhão. Com ‘r’ no final. Drive, sem ‘r’, diz respeito aos dispositivos físicos como drive de CD-ROM, drive de disquete, ZIP drive etc. Já driver, com ‘r’, é um programa responsável por controlar e permitir o uso de um determinado dispositivo em um sistema operacional.
      Essa placa é show, nem precisa de driver!
      Ah precisa. 🙏 O que ocorre é que seu sistema já vem com drivers para vários dispositivos e você pode notar o dispositivo funcionando sem precisar instalar nada além do próprio sistema. Na verdade o driver para aquele dispositivo não estava em uso, mas foi instalado e agora está em uso quando da inserção do dispositivo no PC.
      Vou formatar essa HD aqui Formatar é criar um formato. Não se formata HDs, mas sim partições. Dizer “vou formatar uma partição como NTFS” é correto. Tanto é que pra formatar você precisa especificar um sistema de arquivos desejado. Adicionalmente, o HD (Hard Disk), já que é um disco, possui gênero masculino, então o correto é dizer “o HD”, como em “o disco”.
      Meu HD não tá particionado!
      Em geral para instalar um sistema operacional é preciso, sim, criar nem que seja uma única partição e depois disso formatá-la com um filesystem para o qual o sistema operacional tenha driver e saiba trabalhar. Logo, seu disco deverá ter, no mínimo, uma partição e por isso ele está particionado sim. Uma partição. ☝️
      Formatar não apaga tudo, rapá!
      Formatar é criar um formato. A ilusão de que a partição está vazia após a formatação deve-se ao fato de que a estrutura do filesystem presente naquela partição foi recriada e a referência aos arquivos é perdida, por isso os arquivos não são mais exibidos, mas nenhum foi apagado. Lembrando que nos dias atuais apagar de um disco via software é impossível. Uma vez que ele tenha sido escrito/magnetizado, por assim dizer, o que se pode fazer é substituir os bytes contidos nele por exemplo, para simular deleção. Remover os bits (energia) não é impossível, mas não é comum.
      Põe o HD no congelador que ele volta a funcionar!
      Embora haja um agrupamento de moléculas sob baixas temperaturas, que são responsáveis inclusive pela falsa sensação de carga de pilhas também colocadas no congelador, o efeito não é comprovado e, caso haja algum benefício, será fulminante. Duvido muito que dê tempo para recuperar algo. HD com problema na placa lógica pode ter a placa lógica substituída, mas HDs com problemas físicos, em geral, não têm conserto.
      Faz uma formatação de baixo nível que tira os bad blocks!
      Bad blocks (ou setores defeituosos) caracterizam um problema físico, um câncer que se espalha. Não se resolve hardware com software. É como tentar anexar um suricate num e-mail. Além disso, já parou para se perguntar o que significa formatação de baixo nível, também conhecida como LLF – Low Level Formatting? Uma dica: ZeroFill (famoso programa que preenche com zeros todos os setores do disco) não é.
      É possível recuperar dados de um HD formatado até X vezes!
      Repita comigo: HD não se formata (pelo menos não mais, com a extinção da LLF). NINOVO, a formatação de uma partição dá a ela um formato. Se você formatar 4, 7, 12 ou 7038 vezes, dá no mesmo. Os dados continuam íntegros. Agora, se você fizer um zerofill uma vez, já f*** tudo. Se ao invés de zeros, escrever bytes randômicos, piorou. Como comento na gafe 8, não se apaga nada de HD, só se sobrescreve.
      Esse barulho é a agulha do HD!
      Quem tem agulha é sua avó! HD tem cabeça de leitura e gravação e ela, pasme, não enconsta na superfície do prato. É eletromagnetismo. Favor esquecer a analogia com toca-discos.
      Venho por meio deste… Segue em anexo…
      Não precisa tentar enfeitar. Se você tá escrevendo um e-mail, é óbvio que é por meio dele que vai informar alguma coisa. Difícil seria informar algo “por meio de outro e-mail”. E o que tá anexo, tá anexo. De onde vem esse “em”!?
      Nunca minha rede foi atacada, nunca pegamos vírus!
      O ataque bem sucedido não faz ‘barulho’. Quando você não sabe é justamente quando dá certo. 😈
      Instala um antivírus gratuito! Esse aqui é muito bom!
      Trabalhando na indústria de AV eu vi coisas horríveis. O esforço pra tentar ficar na frente dos criadores de vírus é gigante, caro e por vezes frustrante. Todos os antivírus mais caros das companhias com mais dinheiro sofrem para tentar chegar lá. Desculpe, mas os antivírus gratuitos não têm a menor chance de oferecer qualquer segurança. Quem não investe num antivírus pago hoje para computador e smartphone, pra mim, é maluco(a).
      Não existe vírus pra Linux
      Este sistema é o mais utilizado em webservers no mundo. Você acha mesmo que não haveria vírus capazes de se propagar neles? Faz uma busca por “linux malware” só. Ah, e o Android, sabia que já atingimos a marca de 1 milhão de vírus diferentes para esta plataforma (que é Linux)? Guarde isso: o crime segue o dinheiro. Não importa o sistema utilizado, se o cibercrime ver valor em ameaças para ele, vão surgir.
      Gateway da placa rede O Windows é craque em ensinar errado. O que ele chama de gateway na verdade é a rota padrão para pacotes fora da rede local. É Highlander: só pode haver um! Essa zona que ele cria colocando a configuração de gateway por placa de rede só confunde. E mais, tem gente que acha que sempre precisa de gateway ao configurar uma rede no Windows, o que não é verdade. Se você não vai sair da rede local (para internet ou outra rede), não precisa definir uma rota para fora dela.
      Hackers roubaram…
      Quem comete crime é criminoso. Quem faz hacking de qualquer coisa é hacker. Uma coisa não implica a outra.
      Tá fora do ar! ‘Pingei’ e ele não respondeu.
      O ping dispara pacotes ICMP. Se o alvo ignorar pacotes ICMP, você não vai ter resposta e mesmo assim ele pode estar na rede funcionando normalmente. Com o nmap você tem mais chances de saber se um host está realmente no ar ou não.
      Quebrei o SSL!
      Parece coisa de maluco mas já ouvi umas vezes. Não que seja impossível, mas não confunda man-in-the-middle com quebra da criptografia. Tem um abismo entre estes tópicos!
      Não uso software livre porque ninguém me dá suporte!
      Primeiro: sim, você já usa, mas não sabe. Segundo: várias empresas nacionais e internacionais oferecem suporte, é só procurar. Terceiro: Muitas das próprias organizações que fazem software livre oferecem versões pagas destes softwares, com suporte. Pois é, livre é diferente de gratuito. Um software pode ser gratuito e proprietário enquanto outro pode ser livre e pago. Legal né?
      Não dá pra ganhar dinheiro com software livre!
      Errou. Errou feio, errou rude. O modelo de negócios muda. Há várias empresas e investidores, grandes clientes como bancos e governos. Se você ainda pensa assim, não deve estar ganhando dinheiro no mundo proprietário também, porque o problema está em você!
      Linux é difícil
      Outro mito. Há vários casos de crianças que sempre usaram Linux dentro de casa e acharam o Windows difícil quando foram usar na casa de amigos. É questão de costume.
      MP3 com qualidade de CD
      Se existisse já seria ruim. Ao ripar de um CD há perda de qualidade, sempre. Na conversão de analógico para digital já há, por isso ainda há tantos amantes do vinil. Lembre-se que MP3 é um codec (compressor/decompressor), e se na maioria dos casos de compressão de áudio há perda, mesmo que seu ouvido não note!
      Java roda em qualquer lugar!
      Java só roda em “lugares” que possuem a JVM (Java Virtual Machine). Além disso, há várias máquinas virtuais Java diferentes, com suportes diferentes.
      Linguagem C é velha Velho é o seu professor que ensina como calcular a média de três alunos no Turbo C. A última atualização da linguagem C foi em 2011 e as principais suítes de compiladores como gcc, llvm, Visual Studio, continuam em constante desenvolvimento. Mais da metade do universo é escrito em C. Portanto, vá estudar C! 👨🏿‍💻
      Aperta o Del pra entrar na BIOS!
      Pelo sangue de Chessus, não dá pra entrar lá não. Pressionando a tecla Del, F2, F10 ou qualquer que seja no seu computador, você acessa o SETUP, que é um software de configuração do BIOS. E é “o” BIOS porque ele é um sistema (Basic Input/Output System), logo, gênero masculino.
      A voltagem e a amperagem…
      Talvez de tão faladas já sejam aceitas, mas expressões como essas não soam muito elegantes. Em português, o que é medido em Volts (V) é a tensão elétrica (às vezes chamada de força eletro-motriz ou diferença de potencial). Já o ampère (A) é usado para intensidade de corrente [elétrica]. Espero que não criem ohmagem, wattagem, metragem (opa… essa já criaram!), quilagem, hertzagem…
      Senha forte: números, letras maiúsculas e minúsculas, caracteres espaciais plunct plact zum!
      Ok, ok. Aí vem o usuário danadinho e põe “Senha1”. Assim que expira ele muda: “Senha2”. O problema dessa gafe não é a validade técnica mas a efetividade de jogar essa responsa para o coitado do usuário que mal sabe o motivo de ele ter uma senha tão chata. Se você facilita, fica fácil pra força bruta, se dificulta, ele cola no monitor. Solução: PENSA. O sucesso de um ataque de força bruta depende de duas coisas: a complexidade da senha, o que inclui tamanho, não possuir palavras de dicionário, conter alta entropia etc e o poder computacional do atacante. Mas não precisa complicar muito. Uma senha “Meng0==========” pode ser mais forte que “5!8@6_(hiKij9” (que é bem ruim de decorar). Não é feitiçaria, o nome é entropia. Como o link enaltece, o padding (sinais de igual neste caso) deve ser criado pelo usuário, ou seja, se você ensinar seu usuário a criar algo pra colocar “antes e/ou depois” da senha várias vezes, ele vai se lembrar e ainda assim terá uma senha forte. Assim, uma pessoa sensível que queria usar a senha “Amor” agora pode.. Basta adicionar os amantes felizes e saltitantes: “\0/ Amor \0/”. Mais forte, mais fácil de lembrar, mais amor pro seu coração!
      Curso de hacker Você consegue ensinar alguém a ter ideias? Há vários picaretas no Brasil divulgando e ministrando “cursos hacker”. Todos não passam de leitura de slides e apostilas copiadas de páginas de manuais e tutoriais em sites na Internet. Na sala de “aula” o aluno vê e faz mágica, mas no cenário real a grama muda de cor. 🐴 No entanto, não fique triste, ainda dá tempo de aprender segurança de verdade.
      Minha internet é de 10 megabaites!
      O mercado (sempre ele) cria estas babaquices pra vender. A unidade de medida aqui é o Mb (megabit) e não MB (megabyte). Pois é, muda tudo. Se a sua internet é de 10 “megas”, ou seja, 10 Mbps (megabit por segundo) você baixaria aproximadamente 1,25 MB em um segundo, não 10. O macete é dividir por 8 já que 8 bits formam um byte. O mesmo se aplica às placas de rede de 100 Mbps, 1 Gbps, ou as sem fio de 54 Mbps, 108 Mbps, 3G de 1 Mbps etc: é tudo bit, não byte.
×
×
  • Criar Novo...