ioctl()

Posted Maio 7, 2007 by samuca
Categories: C/C++, Linux

Estou aprendendo a usar esta system call para fazer controle de dispositivos. Hoje é o primeiro dia, então fiz um exemplo simples que faz os leds dos teclado piscarem.

piscaleds.cpp

#include <sys/ioctl.h>
#include <linux/kd.h>
#include <fcntl.h>
#include <iostream>

int main(int argc, char **argv){
/*
* Abrir o dispositivo teclado para leitura
*/
int teclado = open(“/dev/tty0″, O_RDONLY);

/*
* Inicializando o contador para variar os leds
*/
int leds = 0;

while(1) {

/*
* So para imprimir algo na tela…
*/
std::cout << “Piscando…\n” << std::endl;

/*
* Chamada a system call que manipula os leds
*/
ioctl(teclado, KDSETLED, leds);

/*
* Para variar os leds que acendem
*/
leds++;

/*
* Zerar quando chega no ultimo estado possivel
*/

if( leds == 8 ) leds = 0;

sleep(1);
}
}

Para compilar:

g++ piscaleds.cpp -o piscaleds

Para executar:

./piscaleds

Para finalizar:

Ctrl + C

Ps: Deve ser executado como root, para ter permissão de acesso ao teclado.

Ps2: Quando eu aprender algo mais poderoso, posto novamente sobre isso.

enscript.sh

Posted Maio 4, 2007 by samuca
Categories: Dicas, Linux

Como eu nunca lembro os parâmetros para usar o enscript, para fazer meus códigos fontes ficarem coloridos para eu colocar aqui no blog, e toda vez que eu preciso fazer isso tenho que entrar no blog do Ricardo, fiz um script que corta a maioria das opções do enscript, mas para o que eu preciso tá bom e eu não esqueço dos parâmetros…

#! /bin/bash

language=$1;
output=$2;
arq=$3;

if [ "$3" = "" ]; then
echo “Use: ./enscript.sh <linguagem> <nome_arq_saida> <nome_arq_entrada>”;
else
enscript –color –language=html -E$language –output $output.htm $arq
fi

Perl + Python + Fifos

Posted Maio 4, 2007 by samuca
Categories: Linux, Perl, Python

Hoje vou postar um código de teste de uso de pipes nomeados com perl e python. Como já havia postado, pipes nomeados são usados para comunicação entre processos.

Neste caso, em um exemplo simples, mostra-se um programa em perl que escreve em um pipe nomeado e um programa em python que lê os dados.

fifo.pl

#! /usr/bin/perl

$fifo = "saida";

if ( ! -e $fifo ) {			#verifica se não existe
	system ( "mkfifo saida" );	#criando o fifo de saida
	print "Criando fifo de saida...n";
}else {
	print "Fifo de saida ja existe...n";
}

unless(open($input, "> $fifo")){	#a menos que abra o fifo de saida
	system('dialog --clear --backtitle "Erro" --title "Erro" --msgbox "nErro na abertura do FIFO para gravacao" 19 75');	#usando dialog para ecoar msg de erro
	exit;
}

for ($i=0; $i<10; $i++){
	print $input "Gravei Linha ".$i."n";
}

1;

fifo.py

#! /usr/bin/python

arq = open("saida", "r")

for linha in arq.readlines():
	print linha
arq.close()

Note que, será criado um arquivo (pipe nomeado) que será o canal de transferência de dados entre os programas.

Sockets em Perl

Posted Maio 3, 2007 by samuca
Categories: Perl

 

Manipular sockets em perl é muito simples com o uso da biblioteca IO::Socket::INET. Perl proporciona outras maneiras de implementar sockets, com o uso das system calls, porém esta biblioteca encapsula as funcionalidades básicas do socket.
Abaixo segue um exemplo de um server e de um client escrito em perl.

Objetivo do Server: Receber dados de um socket cliente.


 #! /usr/bin/perl			#Usado para chamar o interpretador do perl
 
 # server.pl
 use IO::Socket::INET;			#biblioteca que encapsula as funcionalidades do socket
 print "Servidor Socket TCP em Perln";# Criando o socket
 $server = IO::Socket::INET->new(
 		LocalAddr=>"localhost",	# host
 		LocalPort=>7000,	# porta que vai ficar em listening
 		Proto=>'tcp',		# protocolo
 		Listen=>10		# numero maximo de clientes conectados
 		);

$sock_client = $server->accept();	# aceitando o socket cliente
 
 while( 1 )
 {
 	$sock_client->recv($data,1024);	# recebendo os dados do cliente
 	if($data)
 	{
 		print "nRecebido: ", $data,"n";
 	}
 }

Objetivo do Client: Enviar dados a um socket servidor.


 #! /usr/bin/perl
 
 # client.pl
 use IO::Socket::INET;
 print "Cliente Socket TCP em Perl";# Criando o socket cliente
 $client = IO::Socket::INET->new(
 			PeerAddr=>"localhost",		# host do server
                                     PeerPort  => "7000",# porta em que o server está listening
                                     Timeout   => 60 );	# timeout de conexao
 
 while(1)
 {
     $msg = "Mensagem de teste!";
     print "nEnviando: ",$msg, " ";

    if($client->send($msg))				#enviando a mensagem
     {
             print "-> Enviado com sucesso","n";
 	sleep(5);
     }
 }

Agora é só mudar as permissões dos arquivos server.pl e client.pl para torná-los executáveis.

chmod +x server.pl client.pl

Após isso é só iniciar o server em um terminal e em outro iniciar o client e ver o resultado.

Pipes e Pipes Nomeados ou Fifos

Posted Maio 2, 2007 by samuca
Categories: Linux

PIPE

É o redirecionamento da saída padrão de um programa para a entrada padrão de outro. Permite apenas comunicação unidirecional. Se um processo está tentando passar os dados, e o leitor ainda não está pronto, o pipe bloqueia o processo até que o mesmo esteja disponível. Sendo assim, o próprio pipe provê a sincronização dos processos. Os pipes só podem se comunicar entre processos “parent – child”, por exemplo, comandos executados em um mesmo terminal.

cat /etc/passwd | more

PIPE NOMEADO ou FIFO

Um pipe nomeado é uma extensão do pipe convencional. A diferença é que um pipe termina juntamente com o fim da execução do programa, e um pipe nomeado deve ser criado e destruido explicitamente.

Para criar um pipe nomeado pode-se usar o comando mknod ou mkfifo.

Pode-se usar pipes nomeados em programas para prover meios de comunicação inter processos.

Exemplo:

mkfifo teste
cat < teste # o pipe fica esperando até obter algum dado

Em outro terminal execute:

ls > teste # a saída do comando ls será redirecionada para o pipe nomeado “teste”

Desta forma, a saída do comando ls será ecoada no primeiro terminal, o qual aguardava recebimento de dados no pipe.

Signals Unix

Posted Abril 30, 2007 by samuca
Categories: Linux

Signals são interrupções de software, são mecanismos para comunicação e manipulação de processos UNIX. Um signal é uma mensagem especial enviada à um processo à qual permite a manipulação de eventos assincronos.

Quando um processo recebe um signal, este o processa imediatamente, pausando a sua execução. Após processar o signal o programa retorna a sua execução.

No linux a definição dos signals se encontra em “/usr/include/bits/signum.h“.

Para incluir nos programas em C ou C++ use “<signum.h>“.
O linux envia signals a processos em resposta a condições específicas.

Alguns Signals:

  • SIGABRT: é gerado pela chamada da função abort. O programa termina anormalmente.
  • SIGALRM: acontece quando um tempo que foi setado com a função alarm termina.
  • SIGBUS: isto indica uma implementação de uma falha de hardware.
  • SIGCHLD: sempre que um processo termina ou para, o sinal SIGCHLD é enviado ao processo pai.
  • SGIKILL: usado para matar processos.
  • SIGBUS (error bus), SIGSEGV (segmentation violation), SIGFPE (float point exception) são enviados a processos para avisar sobre uma operação ilegal.

Exemplo de uso no terminal:

kill -9 <nome_processo>

typeid

Posted Abril 27, 2007 by samuca
Categories: C/C++

Como eu havia postado sobre casts em C++, vou postar também sobre esta função do C++ que ajuda na programação.

Typeid pode ser usado para checar o tipo de uma expressão.

Typeid (expressao)

O operador retorna uma referência para um objeto do tipo type_info, que é definido com o arquivo header <typeinfo>.

O valor de retorno pode ser usado com os operadores “==” e “!=” para fazer uma comparação entre tipos.

Também pode-se usar o método name() do objeto, que mostrará o tipo de dado.

Exemplo:

#include <iostream>

#include <typeinfo>

int main(){

int a;

int *b;

if(typeid(a) != typeid(b)){

cout << “a eh diferente de b” << endl;

cout << “a eh: “ << typeid(a).name << endl;

cout << “b eh: “ << typeid(b).name << endl;

}else cout << “a e b sao iguais” << endl;

return 0;

}

 

O type_id também pode ser aplicado em classes. Retornando a classe a qual o objeto foi criado.

Exemplo:

#include <iostream>

#include <typeinfo>

 

class Base {};

class Derivada : public Base {};

 

int main(){

 

Base *a = new Base;

Base *b = new Derivada;

cout << “a eh: “ << typeid(a).name() << endl; //Retorno “a eh: class Base *”

cout << “b eh: “ << typeid(b).name() << endl; //Retorno “b eh: class Base *”

 

cout << “*a eh: << typeid(*a).name() << endl; //Retorno “*a eh: class Base”

cout << “*b eh: << typeid(*b).name() << endl; //Retorno “*b eh: class Derivada”

}

Quando o typeid é aplicado sobre o valor, retorna a classe a qual o objeto foi definido. Quando o typeid é aplicado sobre o ponteiro, retorna a classe a qual o objeto foi instanciado.

Ferramenta Dialog

Posted Abril 23, 2007 by samuca
Categories: Linux

Continuo fuçando com a ferramenta Dialog do linux, e é uma boa idéia para construir instaladores ou outros utilitários de terminal. Usando com o bash, é possível fazer aplicações completas.

No meu primeiro post, coloquei apenas a construção de uma caixa de mensagem, porém também é possível a criação de forms, checklists, menus etc.

Abaixo vou colocar um exemplo simples, que fará o desligamento ou não da máquina conforme escolhido.

 

Código:

#!/bin/bash

/usr/bin/dialog \

–clear \

–backtitle “Sistema Teste.” \

–title “Atencao” \

–yesno “\nDeseja desligar o sistema?” 7 65

ESCOLHA=$?

if [ $ESCOLHA = "0" ]; then #Caso seja sim a escolha

/usr/bin/dialog \

–clear –backtitle “Sistema Teste” –title “Confirmacao” \

–msgbox “Seu sistema sera desligado em 1 minuto!” 0 0

/sbin/shutdown -h +1 #Comando para desligar

else /usr/bin/dialog \

–clear –backtitle “Sistema Teste” –title “Abortado” \

–msgbox “Sistema abortado!” 0 0

fi

 

 

Quando eu aprender a fazer coisas mais interessantes usando esta ferramenta, volto a postar aqui.

Criando arquivos specs para a geração de RPMs

Posted Abril 19, 2007 by samuca
Categories: Dicas

Um arquivo RPM é um pacote contendo algum tipo de dado ou programa. É bastante utilizado para a padronização de instalações em ambientes que utilizam pacotes RPM.

Para a geração dos RPMs pode-se criar arquivos .spec que possuem informações sobre o que se quer empacotar, onde estão os arquivos e onde ficarão após ser feita a instalação/descompactamento.

 

Arquivos .spec

Um arquivo spec é usado para construir pacotes com maior facilidade.

É dividido em partes:

Cabeçalhos com informações básicas

Summary: Programa para fazer alguma coisa

Name: programa_teste

Version: 1

Release: 0

Vendor: Empresa X

Group: XXX

License: Gnu

ExcludeArch: x86-64

BuildRoot: /var/tmp/install -> diretório padrão

Requires: glibc-base, libxml2 >= 2.6.9, libstdc++5.0 -> bibliotecas necessárias

Descrição do pacote (%description)

%description

Pode ser uma descricao qualquer do programa

Preparação para a compilação (%prep)

%prep

%setup -q

A compilação do código fonte em si (%build)

%build

gcc <programa_fonte> -o <programa_binario>

Você pode compilar o código usando o código acima ou pode compilar o código separadamente e apenas empacotá-lo.

A instalação do resultado da compitalação (%install)

Para copiar os arquivos para o BuildRoot para empacotamento.

%install

mkdir -p %{buildroot}/<caminho_a_ser_gerado> #cria os diretórios dentro do buildroot

install -m644 <arquivo_1> <arquivo_2> %{buildroot}/<caminho> #copia os arquivos para dentro do buildroot

Executa comandos, fazendo o que for solicitado. No caso acima, cria os diretórios dentro do buildroot e copia os arquivos para ele.

 

Limpeza dos arquivos depois da compilação (%clean)

Para apagar algum arquivo temporário usado.

%clean

rm -rf <caminho>

 

Scripts para antes e depois da instalação/desinstalação (%pre, %post, %preun, %postun)

Pode ser usado para executar qualquer comando no processo de criação.

%post

ln -sf <path_origem> <path_destino>

Ou qualquer outro comando que for necessário.

Lista de arquivos de pacote (%files)

Os arquivos que serão empacotados.

%files

/<caminho_gerado_anteriormente>/<arquivo_1>

/<caminho_gerado_anteriormente>/<arquivo_2>

Gerando o RPM

Depois do spec pronto, é só executar o comando:

rpm -ba <arquivo_spec>

Se tudo ocorreu certo, o seu arquivo RPM estará gerado. E o seu caminho estará escrito na saída do comando acima.

Nem todos os comandos mostrados precisam ser usados. Abaixo segue um exemplo de um arquivo spec para ilustração.

 

Summary: Programa para ilustrar uso de arquivos specs

Name: programa1

Version: 1.2

Release: 1

Vendor: Empresa X

Group: Empresa X

License: Copyright(c) by Empresa X

ExcludeArch: x86-64

BuildRoot: /var/tmp/install/

Requires: glibc-base, libstdc++5.0, openssl0.9.7, bash, libgcc >= 3.3.3, readline >= 4.3

 

%description

Programa para ilustrar uso de arquivos specs

%install

mkdir -p %{buildroot}/teste/bin

install -m644 programa1 %{buildroot}/teste/bin

 

%files

/teste/bin/programa1

 

%post

echo “Criacao efetuada”

 

Lembrando que deve-se respeitar os caminhos de onde se encontram os programas a serem empacotados.

Lembrando também, que estes arquivos .specs estão sendo usados para a geração de RPMs.

Casts C++

Posted Abril 18, 2007 by samuca
Categories: C/C++

A conversão de um tipo de dado em outro tipo é conhecido como type casting.

 

Conversão Implícita

 

Conversão implicita não requer qualquer operador. Ela é executada automaticamente quando se atribui valores de tipos compatíveis.

 

Exemplo:

short a = 200;

int b;

b = a;

 

Conversão explícita

Conversão explícita requer que o programador indique a que tipo de dado outro deve ser convertido. Geralmente é necessária quando existem diferentes interpretações do valor de um dado para outro.

dynamic_cast

Para converter ponteiros da classe base em um ponteiro de uma classe derivada. Funciona se as classes forem derivadas direta ou indiretamente entre elas. Somente pode ser usado com ponteiros e referências a objetos.

 

Exemplo:

class Tmatriz{};

class Timagem:public Tmatriz{};

Tmatriz *pm;

pm = new Timagem();

Timagem *im = dynamic_cast<TImagem*>(pm);

 

Isto funciona porque o objeto criado e apontado por pm é um objeto do tipo Timagem. Quando o dynamic_cast não consegue fazer a conversão de um tipo a outro, ele seta o retorno para null indicando a falha.

 

 

static_cast

O static_cast é usado para conversões de tipos em tempo de compilação. Se a conversão for ilegal o compilador acusa o erro. Converte tipos de dados relacionados. Pode executar conversões entre ponteiros de classes relacionadas, não somente da classe derivada para a classe base, mas também da classe base para a derivada. Isto pode causar erros em tempo de execução, pois a checagem do cast é feita somente em tempo de compilação.

 

Exemplo:

class CBase {};

class CDerived: public CBase {};

CBase * a = new CBase;

CDerived * b = static_cast<CDerived*>(a);

 

Pode ser utilizado também para qualquer tipo de conversão de dados não ponteiros.

Exemplo:

float fpi = 3.141516;

double dpi = static_cast<double> (fpi);

reinterpret_cast

Este tipo de cast permite converter qualquer tipo de ponteiro para qualquer outro tipo de ponteiro, mesmo de classe sem relação. O resultado da operação é uma cópia do valor binário de um ponteiro para outro. Toda a conversão usando o reinterpret_cast é permitida, e os dados convertidos não são checados. Na maioria dos casos seu uso indica problemas na modelagem e seu uso é perigoso. Geralmente o código é não portável.

Exemplo:

#include <iostream>

int main(){

int a = 3;

int *pa = &a;

cout << “pa=” << pa << endl;

cout << reinterpret_cast <char*> (pa) << endl;

}

 

const_cast

O const_cast manipula as constantes de um objeto. Por exemplo, para passar um argumento const para uma função que não define um parâmetro como const.

Exemplo:

#include <iostream>

void mostra(char *data){

cout << data << endl;

}

int main(){

const char *c = “Teste”;

mostra(const_cast<char *> (c));

return 0;

}