Patricio Domingues

Patrício Domingues é doutorado em Engenharia Informática e professor do Departamento de Engª Informática na Escola Superior de Tecnologia e Gestão (ESTG) do Instituto Politécnico de Leiria (IPLeiria). Tem lecionado, entre outras, a disciplina de Programação Avançada da Licenciatura em Engenharia Informática. É ainda responsável pelo GPU Education Center (antigo NVIDIA CUDA Teaching ) da ESTG/IPLeiria.

Tipos de dados int e variantes na linguagem C

Introdução

Este artigo foca os tipos de dados int e variantes disponíveis na linguagem de programação C. Na parte inicial, o artigo apresenta os tipos de dados inteiros ditos tradicionais. Seguidamente, o artigo introduz os tipos inteiros orientados para a portabilidade, tais como o int8_t, uint_fast64_t e similares. Os principais conceitos são ilustrados com exemplos, executados, sempre que conveniente, em duas plataformas Linux: uma plataforma de 32 bits Lubuntu 16.04 com a versão 5.3.1 do compilador gcc 5.3.1, e uma plataforma de 64 bits Lubuntu 17.04 com o gcc 6.3.0. A primeira é designada por L32, a segunda por L64. Note-se que ambos as versões do compilador usam nativamente a norma C11 (2011) da linguagem C.

Tipos de dados int

Como em muitas outras linguagens de programação, a linguagem C define um conjunto de tipos de dados inteiros. São exemplos os tipos de dados signed char, signed short, signed int e signed long e as variantes sem sinal, unsigned char, unsigned short, unsigned int e unsigned long. Na revisão à linguagem designada por norma C99 foi acrescentado o tipo inteiro long long, nas variantes com (signed) e sem (unsigned) sinal.

Continuar a ler

Programação de aplicações cliente/servidor assentes no protocolo de transporte UDP

A pilha protocolar TCP/IP

A pilha protocolar TCP/IP é considerada o standard de facto na área das comunicações informáticas, sendo praticamente obrigatório o seu uso em aplicações distribuídas. A referida pilha tem mecanismos próprios que possibilitam o envio, encaminhamento e receção de dados entre duas ou mais entidades comunicantes. Um dos elementos chaves da pilha TCP/ IP é o endereço IP que identifica um sistema computacional. Atualmente, existem dois tipos de endereços IP: IPv4 e IPv6. O IPv4 assenta em endereços de 32 bits (4 octetos), sendo comum a sua representação através de 4 números inteiros separados por ponto. Por exemplo, 192.168.120.12 é um endereço IPv4. O crescimento exponencial da internet tornou necessária a criação de um espaço de endereçamento alternativo, com capacidade para um maior número de endereços IP: o IPv6. Neste protocolo, cada endereço IP é composto por 128 bits (16 octetos). Exemplos de endereço IPv6 são 2001:0db8:85a3:0000:0000:8a2e:0370:7334 e ::1, este último representando o endereço local.

Continuar a ler

Programação (in)Segura – Transbordo de Memória

Introdução

O software assume cada vez mais uma importância primordial no nosso dia-a-dia. De facto, é crescente o número de dispositivos com o qual interagimos quotidianamente e cujo funcionamento está dependente de software. Exemplos incluem, obviamente, computadores e tablets, bem como dispositivos ditos inteligentes, como telemóveis, relógios e televisões. Outros exemplos abarcam sistemas de transportes como automóveis, aeronaves e barcos, e sistemas de domótica, para citar apenas alguns dos mais conhecidos. Dado a complexidade associada não só à criação e manutenção de programas informáticos como ainda dos sistemas que pretendem controlar, o software está sujeito a ocorrência de erros. Alguns desses erros podem ser aproveitados por indivíduos ou entidades com intenções maliciosas para subverter os dispositivos controlados, comprometendo deste modo, parcial ou totalmente, a segurança dos sistemas.

Este artigo analisa os erros do tipo transbordo de memória, em particular os que poderão ocorrer no segmento de pilha. O artigo foca alguns dos problemas de segurança que estão associados a situações de transbordo de memória afeta ao segmento de pilha. Os exemplos de código apresentados foram testados num sistema Linux – Lubuntu 14.04 / 32 bits, com kernel versão 3.13.04. Os exemplos foram compilados com a versão 4.8.2 do compilador de linguagem C GNU Collection Compiler (GCC).

Continuar a ler

Travessia de uma árvore de diretórios usando recursividade

Introdução

O diretório é um elemento familiar nos sistemas de ficheiros, sendo empregue para organizar o armazenamento de dados em suporte persistente como, por exemplo, discos rígidos. Uma operação relativamente comum num sistema de ficheiros é a travessia da árvore de diretórios, através da qual são visitados todos os subdiretórios e ficheiros. Este artigo foca o uso de recursividade e das funções stat e readdir para a travessia de uma árvore de diretório recorrendo à metodologia denominada de busca em profundidade (depth-first search na designação anglo-saxónica) (Knuth, 1968) (Wikipedia, 2015). Embora o artigo assente no ambiente Linux e na linguagem C, a metodologia utilizada pode ser empregue, com algumas adaptações, noutras plataformas e com outras linguagens de programação.

Continuar a ler

Manipulação ao nível do bit na Linguagem C

É sabido que um computador trabalha em modo binário, armazenando e manipulando bits, isto é, zeros e uns. Este artigo procura resumir as metodologias mais comuns para uso e manipulação de bits através da linguagem C.

Base binária, octal e hexadecimal

A designação bit identifica um valor da base binária. Como o nome sugere, a base binária é composta por dois valores distintos, representados por zero e um, daí também se designar por base dois. Assim, um bit pode assumir um desses dois valores, sendo muitas vezes empregue para representar um estado ativo (bit com o valor a 1) ou inativo (bit com valor a 0).

Continuar a ler

A ferramenta gengetopt

Os parâmetros de linha de comando constituem um poderoso mecanismo de interação, especialmente nas aplicações de modo consola/terminal que funcionam em modo de texto. De facto, através dos parâmetros da linha de comando, torna-se possível especificar múltiplos comportamentos e funcionalidades para uma mesma aplicação de modo consola/terminal, estando cada comportamento associado a um dado conjunto de parâmetros passado pela linha de comando. Por exemplo, o bem conhecido comando ls, cuja função primária no UNIX é a listar nomes de ficheiros e diretórios, disponibiliza na versão GNU mais de 50 parâmetros da linha de comando, desde o -a (mostra todos os ficheiros) ao -x (mostra a listagem por linhas). Curiosamente, existe ainda a opção -X (maiúscula) que lista os ficheiros por ordem alfabética das respetivas extensões.

Este artigo mostra como se usa e quais as mais-valias da ferramenta gengetopt para o tratamento semi-automatizado das opções passadas pela linha de comando em programas escritos em linguagem C que se destinam a ambientes Linux.

Programação em OpenCL

A norma OpenCL (Open Computing Language) foi impulsionada pela empresa Apple com o intuito de uniformizar a programação para dispositivos de processamento de alto desempenho que suportem execução paralela. Assim, o OpenCL tem por alvo dispositivos de processamento, sejam eles processadores multicores, placas gráficas com capacidade de processamento paralelo (GPU – Graphical Processing Unit), ou outros dispositivos de co-processamento como processadores de sinais (vulgarmente designados por DSP – Digital Signal Processors). Presentemente, a norma OpenCL está sob o controlo do Khronos Group (http:// www.khronos.org/), um consórcio que coordena normas abertas tais como a bem conhecida OpenGL (norma de programação gráfica), a variante OpenGL/ES (OpenGL para sistemas embarcados) e ainda a norma OpenAS/ES (aceleração de áudio para sistemas embarcados).

A norma OpenCL foi adotada por um vasto conjunto de grandes empresas da área da informática (AMD/ATI, NVIDIA, Intel, IBM, Samsung, Google, entre outras). Deste modo, ao contrário da plataforma CUDA (ver Introdução à Programação em CUDA, revista Programar nº 38, Dezembro 2012) que é uma plataforma proprietária que está apenas disponível para GPUs da NVIDIA, a norma OpenCL é suportada numa vasta gama de dispositivos desde as GPUs da AMD/ ATI e da NVIDIA, ao processador Cell e ainda nas mais recentes placas gráficas do tipo HD e CPUs multicore da Intel. Contudo, o suporte varia, sendo ainda poucos os dispositivos que disponibilizam a versão 1.2 da norma OpenCL publicada em Novembro de 2011 (Khronos Group OpenCL Working Group, 2012). Neste artigo introduzem-se os conceitos básicos de programação paralela na norma OpenCL, focando somente o OpenCL na perspetiva de dispositivos GPUs, dado ser esse o cenário mais comum.

O objetivo do OpenCL é o de permitir explorar as capacidades de execução em paralelo dos dispositivos de processamento. Para tal, a norma OpenCL define uma API (Application Programming Interface) para a linguagem C complementada com extensões para paralelismo. Para além do suporte direto para a linguagem C, existe ainda suporte para OpenCL noutras linguagens de programação como o C++, o Python (PyOpenCL) e o Java (Jocl.org), entre outras.

Introdução à Programação em CUDA

Nos últimos anos, as placas gráficas (GPU – Graphical Processing Unit) ganharam relevância no âmbito da computação paralela. De facto, os mais recentes modelos da NVidia e da AMD/ATI – dois dos maiores construtores de placas gráficas – têm na ordem do milhar de núcleos de processamento, “core” na designação anglo-saxónica. Exemplo disso é a GPU NVidia GTX 680 que tem 1536 núcleos, estando creditada com um desempenho máximo (teórico) de 3.1 TFLOPS em cálculo de vírgula flutuante com precisão simples, sendo que um TFLOPS corresponde a 1012 operações de vírgula flutuante por segundo.

Contudo, do ponto de vista de computação paralela, de pouco serve a existência de milhares de cores se o seu uso estiver limitado somente à produção e tratamento de gráficos. Foi pois a pensar na comunidade de computação paralela e no potencial mercado que essa representa, que a NVidia lançou em Novembro de 2006, a versão 1.0 da plataforma Compute Unified Device Architecture (CUDA). Embora limitado às GPU da NVidia, as sucessivas versões de CUDA tornaram possível o uso de GPU para o desenvolvimento e execução de computação paralela de larga escala. Em alguns cenários de computação – tratamento de imagens e video, processamento de dados, aplicações bioinformáticas, etc. – as GPU proporcionam velocidades de execução muito mais rápidas do que as alcançadas pelos processadores (CPU). Neste artigo introduzem-se os conceitos básicos de programação paralela para a plataforma CUDA.