<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Blog do Sergio Prado &#187; Linguagem C</title>
	<atom:link href="http://sergioprado.org/linguagem-c/feed/" rel="self" type="application/rss+xml" />
	<link>http://sergioprado.org</link>
	<description>Sistemas embarcados, Linux embarcado, RTOS e segurança</description>
	<lastBuildDate>Wed, 16 May 2012 00:49:49 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>Resultado do concurso do livro uC/OS-III The Real-Time Kernel</title>
		<link>http://sergioprado.org/resultado-do-concurso-do-livro-ucos-iii-the-real-time-kernel/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=resultado-do-concurso-do-livro-ucos-iii-the-real-time-kernel</link>
		<comments>http://sergioprado.org/resultado-do-concurso-do-livro-ucos-iii-the-real-time-kernel/#comments</comments>
		<pubDate>Wed, 25 Jan 2012 18:19:24 +0000</pubDate>
		<dc:creator>Sergio Prado</dc:creator>
				<category><![CDATA[Concurso]]></category>
		<category><![CDATA[Linguagem C]]></category>
		<category><![CDATA[RTOS]]></category>
		<category><![CDATA[ucosiii]]></category>

		<guid isPermaLink="false">http://sergioprado.org/?p=2395</guid>
		<description><![CDATA[<p>Resultado do concurso para ganhar o livro uC/OS-III The Real-Time Kernel.</p><p><p>Sergio Prado atua com desenvolvimento de software para sistemas embarcados há mais de 15 anos. É sócio-fundador da Embed­ded Lab­works, uma empresa focada em te aju­dar a desen­volver soft­ware de qual­i­dade para sis­temas embar­ca­dos. Se você pre­cisa de ajuda para desen­volver seu pro­duto, ou quer saber mais sobre o que a Embed­ded Lab­works pode fazer por você, acesse <a href=”http://e-labworks.com/servicos/”> http://e-labworks.com/servicos</a>.</p>
<p>Este post foi originalmente publicado em <a href="http://sergioprado.org/resultado-do-concurso-do-livro-ucos-iii-the-real-time-kernel/">Resultado do concurso do livro uC/OS-III The Real-Time Kernel</a>.</p></p>
Posts relacionados:<ol>
<li><a href='http://sergioprado.org/quer-ganhar-o-livro-ucos-iii-da-micrium/' rel='bookmark' title='Quer ganhar o livro uC/OS-III The Real-Time Kernel?'>Quer ganhar o livro uC/OS-III The Real-Time Kernel?</a></li>
<li><a href='http://sergioprado.org/resultado-do-concurso-para-ganhar-o-convite-vip/' rel='bookmark' title='Resultado do concurso para ganhar o convite VIP'>Resultado do concurso para ganhar o convite VIP</a></li>
<li><a href='http://sergioprado.org/sistemas-de-tempo-real-parte-2-3/' rel='bookmark' title='Sistemas de Tempo Real — Parte 2'>Sistemas de Tempo Real — Parte 2</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic -->
<p style="text-align: justify;"><span style="font-family: verdana, geneva; font-size: small;">Muito bem pessoal, chegou a hora de conhecer os 3 vencedores da <a href="http://sergioprado.org/2012/01/10/quer-ganhar-o-livro-ucos-iii-da-micrium/" target="_blank">promoção para ganhar o livro de RTOS da Micrium</a>!</span></p>
<p style="text-align: justify;"><span style="font-family: verdana, geneva; font-size: small;">Primeiramente, gostaria de agradecer à todos pela participação. Recebi 85 respostas, e deu um pouco de trabalho corrigir tudo! :)</span></p>
<p style="text-align: justify;"><span style="font-family: verdana, geneva; font-size: small;">A maioria acertou pelo menos 3 dos 4 desafios, e 38 acertaram tudo. Dentre estas 38 pessoas, fiz o sorteio lá no <a href="http://www.random.org/" target="_blank">http://www.random.org/</a>.</span></p>
<p style="text-align: justify;"><span style="font-family: verdana, geneva; font-size: small;">Mas antes de dizer quem são os 3 felizardos, que tal darmos uma olhada novamente nos desafios?</span></p>
<p><strong><span style="font-family: verdana, geneva; font-size: small;">DESAFIO 1</span></strong></p>
<p><span style="font-family: verdana, geneva; font-size: small;">O desafio 1 dizia o seguinte:</span></p>
<p><span style="font-family: verdana, geneva; font-size: small;">O código abaixo tem um erro. Qual é este erro?</span></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#include &lt;stdlib.h&gt;</span>
<span style="color: #339933;">#include &lt;stdio.h&gt;</span>
&nbsp;
<span style="color: #339933;">#define SIZE 15 </span>
&nbsp;
<span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> <span style="color: #339933;">*</span>a<span style="color: #339933;">,</span> i<span style="color: #339933;">;</span>
&nbsp;
    a <span style="color: #339933;">=</span> malloc<span style="color: #009900;">&#40;</span>SIZE<span style="color: #339933;">*</span><span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> SIZE<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span>
        <span style="color: #339933;">*</span><span style="color: #009900;">&#40;</span>a <span style="color: #339933;">+</span> i<span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> i <span style="color: #339933;">*</span> i<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> SIZE<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span>
        <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;%dn&quot;</span><span style="color: #339933;">,</span> <span style="color: #339933;">*</span>a<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    free<span style="color: #009900;">&#40;</span>a<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>



<p style="text-align: justify;"><span style="font-family: verdana, geneva; font-size: small;">A maioria acertou este desafio. Na linha 10 alocamos uma região de memória e armazenamos o endereço no ponteiro “a”. Na linha 16 este ponteiro é alterado, e quando tentamos desalocá-lo na linha 18 teremos problemas na certa, já que o ponteiro “a” não armazena mais o endereço inicial retornado por malloc(). A solução aqui seria não alterar este ponteiro. O código abaixo resolve o problema:</span></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#include &lt;stdlib.h&gt;</span>
<span style="color: #339933;">#include &lt;stdio.h&gt;</span>
&nbsp;
<span style="color: #339933;">#define SIZE 15 </span>
&nbsp;
<span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> <span style="color: #339933;">*</span>a<span style="color: #339933;">,</span> i<span style="color: #339933;">;</span>
&nbsp;
    a <span style="color: #339933;">=</span> malloc<span style="color: #009900;">&#40;</span>SIZE<span style="color: #339933;">*</span><span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> SIZE<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span>
        <span style="color: #339933;">*</span><span style="color: #009900;">&#40;</span>a <span style="color: #339933;">+</span> i<span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> i <span style="color: #339933;">*</span> i<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> SIZE<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span>
        <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;%dn&quot;</span><span style="color: #339933;">,</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#40;</span>a <span style="color: #339933;">+</span> i<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>  <span style="color: #666666; font-style: italic;">// CORREÇÃO</span>
&nbsp;
    free<span style="color: #009900;">&#40;</span>a<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>



<p style="text-align: justify;"><span style="font-family: verdana, geneva; font-size: small;">Algumas pessoas apontaram ainda que faltou checar o retorno da função malloc() e fazer o cast para (int *). É verdade! O cast é necessário principalmente se você tentar compilar em C++. Mas não considerei estes fatores para validar a resposta como certa.</span></p>
<p><strong><span style="font-family: verdana, geneva; font-size: small;">DESAFIO 2</span></strong></p>
<p><span style="font-family: verdana, geneva; font-size: small;">O desafio 2 dizia o seguinte:</span></p>
<p><span style="font-family: verdana, geneva; font-size: small;">O código abaixo tam­bém tem um erro. Qual?</span></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#include &lt;stdio.h&gt;</span>
&nbsp;
<span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span><span style="color: #339933;">*</span> ptr1<span style="color: #339933;">,</span> ptr2<span style="color: #339933;">;</span>
&nbsp;
    ptr1 <span style="color: #339933;">=</span> malloc<span style="color: #009900;">&#40;</span><span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    ptr2 <span style="color: #339933;">=</span> ptr1<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #339933;">*</span>ptr2 <span style="color: #339933;">=</span> <span style="color: #0000dd;">10</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>



<p style="text-align: justify;"><span style="font-family: verdana, geneva; font-size: small;">A maioria também acertou este exercício. Uma coisa que aprendi deste quando comecei a estudar C é que devemos colocar o “*” sempre do lado do nome do ponteiro, e não do lado do tipo. No código acima, ptr2 é um inteiro, e não um ponteiro para inteiro como pretendiamos, causando erro na linha 11. Para corrigir este código, basta declarar ptr2 como ponteiro:</span></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#include &lt;stdio.h&gt;</span>
&nbsp;
<span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> <span style="color: #339933;">*</span>ptr1<span style="color: #339933;">,</span> <span style="color: #339933;">*</span>ptr2<span style="color: #339933;">;</span>  <span style="color: #666666; font-style: italic;">// CORREÇÃO</span>
&nbsp;
    ptr1 <span style="color: #339933;">=</span> malloc<span style="color: #009900;">&#40;</span><span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    ptr2 <span style="color: #339933;">=</span> ptr1<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #339933;">*</span>ptr2 <span style="color: #339933;">=</span> <span style="color: #0000dd;">10</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>



<p style="text-align: justify;"><span style="font-family: verdana, geneva; font-size: small;">Assim como no primeiro exercício, algumas pessoas também apontaram a ausência da checagem do retorno da função malloc() e do cast para (int *). Mas também não considerei estes fatores para validar a resposta como certa.</span></p>
<p style="text-align: justify;"><span style="font-family: verdana, geneva; font-size: small;">Outros falaram da ausência do free(). Sim, é sempre uma boa prática usar o free(), mas sua ausência nem sempre significa erro. No nosso caso, como a aplicação aloca e depois encerra, não teremos problema com memory leak pela ausência do free().</span></p>
<p style="text-align: justify;"><strong><span style="font-family: verdana, geneva; font-size: small;">DESAFIO 3</span></strong></p>
<p style="text-align: justify;"><span style="font-family: verdana, geneva; font-size: small;">O desafio 3 dizia o seguinte:</span></p>
<p style="text-align: justify;"><span style="font-family: verdana, geneva; font-size: small;">A função abaixo recebe um vetor de números inteiros e tem o obje­tivo de retornar o menor número inteiro deste vetor. Imple­mente esta função sem usar nen­hum oper­ador de com­para­ção! Ou seja, você não pode usar nen­hum destes oper­adores: “==”, “!=”, “&gt;”, “&lt;”, “&gt;=”, “&lt;=”.</span></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">unsigned</span> <span style="color: #993333;">int</span> menor<span style="color: #009900;">&#40;</span><span style="color: #993333;">unsigned</span> <span style="color: #993333;">int</span> buf<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> size_t size<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>



<p style="text-align: justify;"><span style="font-family: verdana, geneva; font-size: small;">Aqui o bicho pegou! Este é o típico “exercício bombril”, que pode ser resolvido de 1001 maneiras. Recebi implementações de 5 linhas e outras de 50 linhas! :)</span></p>
<p style="text-align: justify;"><span style="font-family: verdana, geneva; font-size: small;">Esta é a minha sugestão de implementação:</span></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">unsigned</span> <span style="color: #993333;">int</span> menor<span style="color: #009900;">&#40;</span><span style="color: #993333;">unsigned</span> <span style="color: #993333;">int</span> buf<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> size_t size<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">unsigned</span> <span style="color: #993333;">int</span> m <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> i<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
        <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> size<span style="color: #339933;">;</span> i<span style="color: #339933;">;</span> i<span style="color: #339933;">--</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>buf<span style="color: #009900;">&#91;</span>i <span style="color: #339933;">-</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">return</span> m<span style="color: #339933;">;</span>
            buf<span style="color: #009900;">&#91;</span>i <span style="color: #339933;">-</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">--;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        m<span style="color: #339933;">++;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>



<p style="text-align: justify;"><span style="font-family: verdana, geneva; font-size: small;">Eu faço uma varredura do vetor em um loop e decremento, um a um, cada elemento deste vetor. A quantidade de decrementos realizados é armazenada na variável “m”. Quando um dos elementos do vetor atingir o valor 0, significa que descobri qual era o elemento de menor valor dentro do vetor, e retorno este valor, que é exatamente a quantidade de decrementos realizada, armazenada na variável “m”.</span></p>
<p style="text-align: justify;"><span style="font-family: verdana, geneva; font-size: small;">Recebi algumas implementações que usavam esta lógica, mas também recebi outras implementações bem interessantes.</span></p>
<p style="text-align: justify;"><span style="font-family: verdana, geneva; font-size: small;">Achei bem legal esta implementação do Paulo Daniel:</span></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">unsigned</span> <span style="color: #993333;">int</span> menor<span style="color: #009900;">&#40;</span><span style="color: #993333;">unsigned</span> <span style="color: #993333;">int</span> buf<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> size_t size<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
   <span style="color: #993333;">unsigned</span> <span style="color: #993333;">int</span> min <span style="color: #339933;">=</span> UINT_MAX<span style="color: #339933;">;</span>
   <span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span>size<span style="color: #009900;">&#41;</span> 
      <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #009900;">&#40;</span>buf<span style="color: #009900;">&#91;</span><span style="color: #339933;">--</span>size<span style="color: #009900;">&#93;</span><span style="color: #339933;">/</span>min<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
         min <span style="color: #339933;">=</span> buf<span style="color: #009900;">&#91;</span>size<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
   <span style="color: #b1b100;">return</span> min<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>



<p style="text-align: justify;"><span style="font-family: verdana, geneva; font-size: small;">Ele conseguiu resolver em 5 linhas, usando apenas uma operação de divisão de inteiros!</span></p>
<p style="text-align: justify;"><span style="font-family: verdana, geneva; font-size: small;"><strong>Atualização:</strong> Como bem observado pelos leitores Fernando Barboza e Уθя¡ςκ, esta implementação tem uma falha, já que existe o risco de divisão por 0 na linha 5. Mas a forma como o problema foi resolvido não deixa de ser bem interessante.</span></p>
<p style="text-align: justify;"><span style="font-family: verdana, geneva; font-size: small;">Já o Douglas Drumond preferiu escovar alguns bits e trabalhar com complemento de 2:</span></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">unsigned</span> <span style="color: #993333;">int</span> menor<span style="color: #009900;">&#40;</span><span style="color: #993333;">unsigned</span> <span style="color: #993333;">int</span> buf<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> size_t size<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">unsigned</span> <span style="color: #993333;">int</span> shamt <span style="color: #339933;">=</span>  <span style="color: #009900;">&#40;</span><span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">unsigned</span> <span style="color: #993333;">int</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">*</span> <span style="color: #0000dd;">8</span> <span style="color: #339933;">-</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">unsigned</span> <span style="color: #993333;">int</span> mask <span style="color: #339933;">=</span> <span style="color: #208080;">0x01</span><span style="color: #339933;">;</span>
&nbsp;
    size_t i <span style="color: #339933;">=</span> size <span style="color: #339933;">-</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #993333;">unsigned</span> <span style="color: #993333;">int</span> menor_item <span style="color: #339933;">=</span> buf<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span>i<span style="color: #339933;">--</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>buf<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span> <span style="color: #339933;">-</span> menor_item<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;&gt;</span> shamt<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> mask<span style="color: #009900;">&#41;</span> menor_item <span style="color: #339933;">=</span> buf<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> menor_item<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>



<p style="text-align: justify;"><strong><span style="font-family: verdana, geneva; font-size: small;">DESAFIO 4</span></strong></p>
<p style="text-align: justify;"><span style="font-family: verdana, geneva; font-size: small;">Este desafio dizia o seguinte:</span></p>
<p style="text-align: justify;"><span style="font-family: verdana, geneva; font-size: small;">Escreva um pro­grama em C que imprima “Quero o meu livro!”, mas sem usar nen­hum ponto-e-vírgula no arquivo “.c”! Obs: o pro­grama deve com­pi­lar e fun­cionar nor­mal­mente.</span></p>
<p style="text-align: justify;"><span style="font-family: verdana, geneva; font-size: small;">A solução é bem simples:</span></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#include &lt;stdio.h&gt;</span>
&nbsp;
<span style="color: #993333;">void</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Quero o livro!n&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>



<p style="text-align: justify;"><span style="font-family: verdana, geneva; font-size: small;">Você pode trocar o “if” pelo “while” também.</span></p>
<p style="text-align: justify;"><span style="font-family: verdana, geneva; font-size: small;">Teve gente que queria tanto o livro que colocou em um loop infinito! :)</span></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">void</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span><span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Quero o meu livro!n&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>



<p style="text-align: justify;"><span style="font-family: verdana, geneva; font-size: small;">Mas aqui o pessoal resolveu usar a criatividade. Como falei apenas que não podia usar “;” no arquivo “.c”, e não mencionei nada sobre o uso de arquivo “.h”, recebi respostas do tipo:</span></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// Author: Celso</span>
<span style="color: #666666; font-style: italic;">// imprime.c</span>
<span style="color: #339933;">#include &lt;stdio.h&gt;</span>
<span style="color: #339933;">#include &lt;stdlib.h&gt;</span>
&nbsp;
<span style="color: #339933;">#include &quot;imprime.h&quot;</span>
<span style="color: #993333;">void</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  IMPRIME
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// imprime.h</span>
<span style="color: #339933;">#define IMPRIME   printf(&quot;Quero o meu livro!n&quot;);</span></pre></td></tr></table></div>



<p style="text-align: justify;"><span style="font-family: verdana, geneva; font-size: small;">Ou então trocando o “;” por um define passado pelo compilador:</span></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">/* Author: Fernando Martines
 *
 * Compilacao: gcc -DSPECIAL=&quot;;&quot; desafio4.c -o desafio4
 */</span>
<span style="color: #339933;">#include &lt;stdio.h&gt;</span>
&nbsp;
<span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Quero o meu livro!n&quot;</span><span style="color: #009900;">&#41;</span> SPECIAL
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span> SPECIAL
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>



<p style="text-align: justify;"><span style="font-family: verdana, geneva; font-size: small;">Bom, gostei muito do resultado destes desafios. Aprendi bastante e espero que vocês tenham aprendido também. Afinal, o que importa é participar. Ganhar é só um detalhe, não é verdade? O quê? Não!? :)</span></p>
<p style="text-align: justify;"><span style="font-family: verdana, geneva; font-size: small;">OK, chega de enrolação, estes são os três participantes que acertaram os 4 desafios e foram sorteados para receber o livro:</span></p>
<ul>
	<li><span style="font-family: verdana, geneva; font-size: small;">Rodrigo (a.k.a. Skhaz)</span></li>
	<li><span style="font-family: verdana, geneva; font-size: small;">Eduardo Vieira</span></li>
	<li><span style="font-family: verdana, geneva; font-size: small;">Rodolfo Pereira Araujo</span></li>
</ul>
<p style="text-align: justify;"><span style="font-family: verdana, geneva; font-size: small;">Para aqueles que não ganharam, não desanimem! </span><span style="font-family: verdana, geneva; font-size: small;">Vocês podem baixar gratuitamente o PDF do livro no site da Micrium <a href="http://micrium.com/page/downloads/os-iii_projects" target="_blank">aqui</a>.</span></p>
<p style="text-align: justify;"><span style="font-family: verdana, geneva; font-size: small;">Ou então vocês podem esperar o próximo concurso. Eu havia falado que tinha 3 livros, não é verdade? Então… eu estava escondendo o jogo! :)</span></p>
<p style="text-align: justify;"><span style="font-family: verdana, geneva; font-size: small;">Na verdade, alem destes 3, tenho mais 1! E logo mais teremos um novo desafio por aqui. Mas desta vez não será tão fácil assim! :)</span></p>
<p style="text-align: justify;"><span style="font-family: verdana, geneva; font-size: small;">Um abraço!</span></p>
<p style="text-align: justify;"><span style="font-family: verdana, geneva; font-size: small;">Sergio Prado</span></p>
<div id="-chrome-auto-translate-plugin-dialog" style="opacity: 1 !important; background-image: initial !important; background-attachment: initial !important; background-origin: initial !important; background-clip: initial !important; background-color: transparent !important; position: absolute !important; top: 0px; left: 0px; overflow-x: visible !important; overflow-y: visible !important; z-index: 999999 !important; text-align: left !important; display: none; padding: 0px !important; margin: 0px !important;">
<div style="max-width: 300px !important; color: #fafafa !important; opacity: 0.8 !important; border-color: #000000 !important; border-width: 0px !important; -webkit-border-radius: 10px !important; background-color: #363636 !important; font-size: 16px !important; padding: 8px !important; overflow: visible !important; background-image: -webkit-gradient(linear, left top, right bottom, color-stop(0%, #000), color-stop(50%, #363636), color-stop(100%, #000)); z-index: 999999 !important; text-align: left  !important;"></div>
<p><img style="position: absolute !important; z-index: -1 !important; right: 1px !important; top: -20px !important; cursor: pointer !important; -webkit-border-radius: 20px; background-color: rgba(200, 200, 200, 0.3) !important; padding: 3px 5px 0 !important; margin: 0 !important;" onclick="document.location.href='http://translate.google.com/';" src="http://www.google.com/uds/css/small-logo.png" alt="small logo Resultado do concurso do livro uC/OS III The Real Time Kernel"  title="Resultado do concurso do livro uC/OS III The Real Time Kernel" /></p>
</div>
<div class="shr-publisher-2395"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic --><p>Posts relacionados:</p><ol>
<li><a href='http://sergioprado.org/quer-ganhar-o-livro-ucos-iii-da-micrium/' rel='bookmark' title='Quer ganhar o livro uC/OS-III The Real-Time Kernel?'>Quer ganhar o livro uC/OS-III The Real-Time Kernel?</a></li>
<li><a href='http://sergioprado.org/resultado-do-concurso-para-ganhar-o-convite-vip/' rel='bookmark' title='Resultado do concurso para ganhar o convite VIP'>Resultado do concurso para ganhar o convite VIP</a></li>
<li><a href='http://sergioprado.org/sistemas-de-tempo-real-parte-2-3/' rel='bookmark' title='Sistemas de Tempo Real — Parte 2'>Sistemas de Tempo Real — Parte 2</a></li>
</ol><p><p>Sergio Prado atua com desenvolvimento de software para sistemas embarcados há mais de 15 anos. É sócio-fundador da Embed­ded Lab­works, uma empresa focada em te aju­dar a desen­volver soft­ware de qual­i­dade para sis­temas embar­ca­dos. Se você pre­cisa de ajuda para desen­volver seu pro­duto, ou quer saber mais sobre o que a Embed­ded Lab­works pode fazer por você, acesse <a href=”http://e-labworks.com/servicos/”> http://e-labworks.com/servicos</a>.</p>
<p>Este post foi originalmente publicado em <a href="http://sergioprado.org/resultado-do-concurso-do-livro-ucos-iii-the-real-time-kernel/">Resultado do concurso do livro uC/OS-III The Real-Time Kernel</a>.</p></p>]]></content:encoded>
			<wfw:commentRss>http://sergioprado.org/resultado-do-concurso-do-livro-ucos-iii-the-real-time-kernel/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Implementando um teclado virtual no Linux</title>
		<link>http://sergioprado.org/implementando-um-teclado-virtual-no-linux/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=implementando-um-teclado-virtual-no-linux</link>
		<comments>http://sergioprado.org/implementando-um-teclado-virtual-no-linux/#comments</comments>
		<pubDate>Tue, 13 Dec 2011 00:01:34 +0000</pubDate>
		<dc:creator>Sergio Prado</dc:creator>
				<category><![CDATA[Linguagem C]]></category>
		<category><![CDATA[Linux embarcado]]></category>
		<category><![CDATA[device driver]]></category>
		<category><![CDATA[Kernel]]></category>
		<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://www.sergioprado.org/?p=2150</guid>
		<description><![CDATA[<p>Neste artigo veremos como desenvolver um modulo do kernel para emular um teclado virtual.</p><p><p>Sergio Prado atua com desenvolvimento de software para sistemas embarcados há mais de 15 anos. É sócio-fundador da Embed­ded Lab­works, uma empresa focada em te aju­dar a desen­volver soft­ware de qual­i­dade para sis­temas embar­ca­dos. Se você pre­cisa de ajuda para desen­volver seu pro­duto, ou quer saber mais sobre o que a Embed­ded Lab­works pode fazer por você, acesse <a href=”http://e-labworks.com/servicos/”> http://e-labworks.com/servicos</a>.</p>
<p>Este post foi originalmente publicado em <a href="http://sergioprado.org/implementando-um-teclado-virtual-no-linux/">Implementando um teclado virtual no Linux</a>.</p></p>
Posts relacionados:<ol>
<li><a href='http://sergioprado.org/linux-device-drivers-parte-1/' rel='bookmark' title='Linux Device Drivers — Parte 1'>Linux Device Drivers — Parte 1</a></li>
<li><a href='http://sergioprado.org/linux-device-drivers-parte-2/' rel='bookmark' title='Linux Device Drivers — Parte 2'>Linux Device Drivers — Parte 2</a></li>
<li><a href='http://sergioprado.org/por-dentro-da-console-em-sistemas-linux/' rel='bookmark' title='Por dentro da console em sistemas Linux'>Por dentro da console em sistemas Linux</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">A idéia de escrever este artigo surgiu da necessidade de um projeto que trabalhei algumas semanas atrás.</span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">O objetivo era implementar um teclado virtual, de forma que um processo ou aplicação pudesse simular o pressionamento de uma tecla, sem que esta tecla tivesse sido realmente pressionada em um teclado físico.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Até aí tudo bem, qualquer biblioteca ou toolkit gráfico decente (X11, DirectFB, Qt, etc) possui algum mecanismo para emular entrada de teclado. Mas o objetivo era ser independente de biblioteca gráfica, e funcionar também em ambiente somente texto. Ou seja, precisavamos de algo implementado dentro do kernel.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Mas não vamos “colocar a carroça na frente dos bois”! Antes de pensar na solução, vamos pensar no problema…<br />
	</span></span></p>
<p style="text-align: justify; "><strong><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">PURA MÁGICA?<br />
	</span></span></strong></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Não, não é mágica. Mas uma tecla pressionada dentro do kernel do Linux passa por algumas camadas até você vê-la ecoando na tela do seu monitor.<br />
	</span></span></p>
<p style="text-align: justify; "><strong><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">CAMADA 0: HARDWARE<br />
	</span></span></strong></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Tudo começa no hardware, claro. A controladora do teclado conectado ao seu PC varre e decodifica a matriz de teclas e cuida de detalhes como o controle de debouncing.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Quando você pressiona uma tecla, essa tecla é transformada em um código chamado de scancode. Cada tecla possui um scancode quando é pressionada e outro quando é liberada (o bit mais significativo é setado). Por exemplo, a letra ‘x’ emite o scancode 0x2d quando é pressionada e 0xad quando é liberada (no meu teclado USB).<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Se você quiser, pode usar a ferramenta “<em>showkey</em>” para fazer o dump e exibir o scancode das teclas pressionadas no seu PC:<br />
	</span></span></p>


<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">$ sudo showkey -s
press any key (program terminates 10s after last keypress)...
0x2d 0xad</pre></div></div>



<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Portanto, para cada tecla pressionada, uma interrupção é gerada para a CPU, e os scancodes são enviados via barramento de comunicação, dependendo do hardware do seu teclado (PS2, USB, etc).</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Logo após, a rotina de tratamento de interrupção do teclado é acionada, sendo responsável por receber e tratar estes scancodes, conforme veremos a seguir.<br />
	</span></span></p>
<p style="text-align: justify; "><strong><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">CAMADA 1: DEVICE DRIVER<br />
	</span></span></strong></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Aqui já estamos no kernel do Linux. Um device driver vai conversar com o hardware do seu teclado, receber e tratar os scancodes.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">E dependendo do hardware que você esta usando (teclado USB, PS2, etc), um diferente device driver será o responsável por ler estes scancodes. Por exemplo, a implementação do teclado PS2 padrão encontra-se nos fontes do kernel em <a href="http://lxr.free-electrons.com/source/drivers/input/keyboard/atkbd.c?v=3.0" target="_blank"><em>drivers/input/keyboard/atkbd.c</em></a>. Vai lá dar uma olhada, eu espero!<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Após ler os scancodes, o device driver irá convertê-los em um outro código chamado keycodes. Cuidado para não confundir! Scancode é um código dependente do hardware do teclado e tratado pelo device driver. Keycode é um código que representa uma tecla dentro de um sistema Linux.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Você já viu que cada tecla pressionada gera dois scancodes (pressionada e liberada). Mas ela possui um único keycode. Por exemplo, no meu PC, quando pressiono a tecla ‘x’, é gerado o keycode 45:<br />
	</span></span></p>


<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">$ sudo showkey -k
press any key (program terminates 10s after last keypress)...
keycode  45 press
keycode  45 release</pre></div></div>



<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Mas como então o kernel diferencia teclas pressionadas e liberadas se o keycode é o mesmo? Fácil. O device driver gera dois eventos para o kernel. Um para teclas pressionadas e outro para teclas liberadas. E estes eventos são enviados para camada input do kernel.<br />
	</span></span></p>
<p style="text-align: justify; "><strong><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">CAMADA 2: INPUT SUBSYSTEM<br />
	</span></span></strong></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">É nesta camada que percebemos toda a capacidade de modularização do kernel do Linux. <br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">A camada input foi criada para abstrair a captura de eventos de dispositivos de entrada como mouse, teclado, joysticks, touch screens, etc. Enquanto que cada um destes dispositivos possui seu respectivo device driver, cada device driver exporta os eventos para a camada input. Por sua vez, a camada input trata e exporta estes eventos em um formato padrão para arquivos de dispositivo em /dev/input/:<br />
	</span></span></p>


<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">$ ls /dev/input
event0  event1  event2  event3  event4  event5  mice  mouse0</pre></div></div>



<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Cada um destes arquivos de dispositivo representam um dispositivo de entrada.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Você pode usar a ferramenta “evtest” para verificar qual o dispositivo relacionado à determinado arquivo:<br />
	</span></span></p>


<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">$ sudo evtest /dev/input/event4
Input driver version is 1.0.1
Input device ID: bus 0x3 vendor 0x1c4f product 0x2 version 0x110
Input device name: &quot;USB USB Keykoard&quot;
...</pre></div></div>



<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Veja que, na minha máquina, /dev/input/event4 é o arquivo de dispositivo que gera os eventos do teclado USB.</span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">A ferramenta “evtest” também é capaz de monitorar os eventos de dispositivos de entrada. Execute novamente o comando acima, pressione uma tecla e veja os eventos que foram exportados para userspace através deste arquivo de dispositivo:<br />
	</span></span></p>


<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">...
Event: time 1323720735.849223, type 1 (Key), code 45 (X), value 1
Event: time 1323720735.849225, -------------- Report Sync ------------
Event: time 1323720735.905222, type 1 (Key), code 45 (X), value 0
Event: time 1323720776.880210, -------------- Report Sync ------------
...</pre></div></div>



<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Perceba o keycode 45 para a tecla ‘x’ e os valores 1 para tecla pressionada e 0 para tecla liberada.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Por fim, as bibliotecas gráficas monitoram os eventos nestes arquivos de dispositivos e exportam estes eventos para as aplicações. E assim você vê uma tecla ecoando em seu terminal!<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Linux é ou não é um dos SOMLTT — sistemas operacionais mais legais de todos os tempos? :-)<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Apenas um detalhe aqui: no caso do teclado, além de exportar os eventos para “/dev/input/”, a camada input também exporta os eventos de teclas pressionadas para a camada TTY ativa no momento. Desta forma, se você estiver em um terminal conectado à /dev/tty2, por exemplo, irá receber este evento. Se quiser saber mais sobre a camada TTY, leia o artigo “<a href="http://www.sergioprado.org/2011/04/25/por-dentro-da-console-em-sistemas-linux/" target="_blank">Por dentro da console em sistemas Linux</a>”.<br />
	</span></span></p>
<p style="text-align: justify; "><strong><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">VOLTANDO AO NOSSO PROBLEMA…<br />
	</span></span></strong></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Depois de todas estas explicações, espero que você não tenha se esquecido do nosso problema original: emular um teclado virtual independente de biblioteca gráfica, e que funcione em modo texto.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Agora ficou mais fácil pensar numa solução, não é verdade? </span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Reveja as camadas. A camada 0 é hardware, e não temos hardware no nosso caso. A camada 2 é genérica, e não é uma boa prática mexer nela. Potanto, é na camada 1 que trabalharemos.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Vamos desenvolver um device driver (no nosso caso, um módulo do kernel, já que não falaremos com nenhum hardware) que irá gerar eventos de teclado para a camada input. Simples assim!<br />
	</span></span></p>
<p style="text-align: justify; "><strong><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">A SOLUÇÃO<br />
	</span></span></strong></p>
<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Para não complicar muito, vamos escrever um modulo simples que irá emular a digitação de uma frase a cada 10 segundos. Assim que carregado, uma frase será “digitada” pelo módulo a cada 10 segundos. E para deixar o trabalho mais divertido, a frase será “segmentation fault”!</span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Sem mais enrolação, este é o código completo do nosso módulo do kernel:<br />
	</span></span></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#include &quot;linux/fs.h&quot;</span>
<span style="color: #339933;">#include &quot;linux/cdev.h&quot;</span>
<span style="color: #339933;">#include &quot;linux/module.h&quot;</span>
<span style="color: #339933;">#include &quot;linux/kernel.h&quot;</span>
<span style="color: #339933;">#include &quot;linux/delay.h&quot;</span>
<span style="color: #339933;">#include &quot;linux/kthread.h&quot;</span>
<span style="color: #339933;">#include &quot;linux/device.h&quot;</span>
<span style="color: #339933;">#include &quot;linux/slab.h&quot;</span>
<span style="color: #339933;">#include &quot;linux/tty.h&quot;</span>
<span style="color: #339933;">#include &quot;linux/tty_flip.h&quot;</span>
<span style="color: #339933;">#include &quot;linux/kbd_kern.h&quot;</span>
<span style="color: #339933;">#include &quot;linux/input.h&quot;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* vtkbd kernel thread struct */</span>
<span style="color: #993333;">static</span> <span style="color: #993333;">struct</span> task_struct <span style="color: #339933;">*</span>vtkbd_thread_task<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* vtkbd input device structure */</span>
<span style="color: #993333;">static</span> <span style="color: #993333;">struct</span> input_dev <span style="color: #339933;">*</span>vtkbd_input_dev<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #993333;">const</span> <span style="color: #993333;">char</span> str_keys<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span> KEY_S<span style="color: #339933;">,</span> KEY_E<span style="color: #339933;">,</span> KEY_G<span style="color: #339933;">,</span> KEY_M<span style="color: #339933;">,</span> KEY_E<span style="color: #339933;">,</span> KEY_N<span style="color: #339933;">,</span>
                          KEY_T<span style="color: #339933;">,</span> KEY_A<span style="color: #339933;">,</span> KEY_T<span style="color: #339933;">,</span> KEY_I<span style="color: #339933;">,</span> KEY_O<span style="color: #339933;">,</span> KEY_N<span style="color: #339933;">,</span>
                          KEY_SPACE<span style="color: #339933;">,</span> KEY_F<span style="color: #339933;">,</span> KEY_A<span style="color: #339933;">,</span> KEY_U<span style="color: #339933;">,</span> KEY_L<span style="color: #339933;">,</span>
                          KEY_T<span style="color: #339933;">,</span> KEY_ENTER <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* kernel thread */</span>
<span style="color: #993333;">static</span> <span style="color: #993333;">int</span> vtkbd_thread<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span> <span style="color: #339933;">*</span>unused<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> i<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>kthread_should_stop<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
        <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>str_keys<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
            input_report_key<span style="color: #009900;">&#40;</span>vtkbd_input_dev<span style="color: #339933;">,</span> str_keys<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            input_report_key<span style="color: #009900;">&#40;</span>vtkbd_input_dev<span style="color: #339933;">,</span> str_keys<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            input_sync<span style="color: #009900;">&#40;</span>vtkbd_input_dev<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;">/* wait 10 seconds */</span>
        msleep<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">10000</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">return</span><span style="color: #009900;">&#40;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* driver initialization */</span>
<span style="color: #993333;">static</span> <span style="color: #993333;">int</span> __init vtkbd_init<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">static</span> <span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>name <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;Virtual Keyboard&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> i<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/* allocate input device */</span>
    vtkbd_input_dev <span style="color: #339933;">=</span> input_allocate_device<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>vtkbd_input_dev<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        printk<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;vtkbd_init: Error on input_allocate_device!<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #339933;">-</span>ENOMEM<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/* set input device name */</span>
    vtkbd_input_dev<span style="color: #339933;">-&gt;</span>name <span style="color: #339933;">=</span> name<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/* enable key events */</span>
    set_bit<span style="color: #009900;">&#40;</span>EV_KEY<span style="color: #339933;">,</span> vtkbd_input_dev<span style="color: #339933;">-&gt;</span>evbit<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">256</span><span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span>
        set_bit<span style="color: #009900;">&#40;</span>i<span style="color: #339933;">,</span> vtkbd_input_dev<span style="color: #339933;">-&gt;</span>keybit<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/* register input device */</span>
    input_register_device<span style="color: #009900;">&#40;</span>vtkbd_input_dev<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/* start thread */</span>
    vtkbd_thread_task <span style="color: #339933;">=</span> kthread_run<span style="color: #009900;">&#40;</span>vtkbd_thread<span style="color: #339933;">,</span> NULL<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;%s&quot;</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;vtkbd_thread&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    printk<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Virtual Keyboard driver initialized.<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* driver exit */</span>
<span style="color: #993333;">void</span> __exit vtkbd_exit<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #808080; font-style: italic;">/* stop thread */</span>
    kthread_stop<span style="color: #009900;">&#40;</span>vtkbd_thread_task<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/* unregister input device */</span>
    input_unregister_device<span style="color: #009900;">&#40;</span>vtkbd_input_dev<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    printk<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Virtual Keyboard driver.<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
module_init<span style="color: #009900;">&#40;</span>vtkbd_init<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
module_exit<span style="color: #009900;">&#40;</span>vtkbd_exit<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
MODULE_LICENSE<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;GPL&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
MODULE_AUTHOR<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Sergio Prado sergio.prado@embeddedlabworks.com&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
MODULE_DESCRIPTION<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Virtual Keyboard driver&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>



<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">O módulo tem basicamente 3 funções: <em>vtkbd_init()</em> para inicializar o módulo, <em>vtkbd_exit()</em> para fazer a limpeza ao descarregar o módulo e <em>vtkbd_thread()</em> que faz a mágica de digitar a frase periodicamente.</span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Na função de inicialização, o primeiro passo é alocar um dispositivo de input com a função <em>input_allocate_device()</em> na linha 54. Essa função vai devolver uma estrutura que vai nos possibilitar conversar com a camada input e gerar os eventos de teclado. Nas linhas 64 a 66 habilitamos a geração de eventos em todas as teclas (veja o loop) e na linha 69 registramos o dispositivo de input com a função <em>input_register_device()</em>. Por último, criamos e iniciamos a thread do kernel que irá fazer o “trabalho sujo”. Se você quiser ler mais sobre Kernel Threads, leia o artigo “<a href="http://www.sergioprado.org/2011/04/18/linux-device-drivers-trabalhando-com-kernel-threads/" target="_blank">Linux Device Drivers — Trabalhando com Kernel Threads</a>”</span></span></p>
<p style="text-align: justify; "><font class="Apple-style-span" face="verdana, geneva, sans-serif"><span class="Apple-style-span" style="font-size: 14px;">Na função de limpeza, paramos a thread e removemos o dispositivo de input que registramos na inicialização.</span></font></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">A thread <em>vtkbd_thread()</em> é bem simples e faz toda a mágica. Ela é basicamente um loop infinito que, a cada 10 segundos, gera os eventos para emular a digitação. O vetor <em>str_keys[]</em> contém os keycodes para a frase “<em>segmentation fault</em>”. Esses keycodes estão definidos em <a href="http://lxr.free-electrons.com/source/include/linux/input.h?v=3.0" target="_blank">include/linux/input.h</a>. Para cada keycode, geramos dois eventos com a função <em>input_report_key()</em>, simulando a tecla pressionada na linha 34 e a tecla liberada na linha 35 (veja os parâmetros 1 e 0, respectivamente). Por último, executamos a função <em>input_sync()</em>, notificando a camada input da existência de novos eventos a serem tratados.</span></span></p>
<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Simples, não?</span></p>
<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Para compilar, crie um Makefile com o conteúdo abaixo:</span></p>


<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">KVER := $(shell uname -r)
KDIR := /usr/src/linux-headers-$(KVER)
PWD  := $(shell pwd)
&nbsp;
obj-m += vtkbd.o
&nbsp;
default:
        $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
&nbsp;
clean:
        @rm -Rf *.o *.ko *.mod.c modules.order Module.symvers Module.markers</pre></div></div>



<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">E compile:</span></p>


<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">$ make</pre></div></div>



<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Para carregar o módulo:</span></p>


<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">$ sudo insmod vtkbd.ko</pre></div></div>



<p style="text-align: justify; "><font class="Apple-style-span" face="verdana, geneva, sans-serif"><span class="Apple-style-span" style="font-size: 14px;">E para remover o módulo:</span></font></p>


<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">$ sudo rmmod vtkbd</pre></div></div>



<p style="text-align: justify; "><font class="Apple-style-span" face="verdana, geneva, sans-serif"><span class="Apple-style-span" style="font-size: 14px;">Como o módulo ficará digitando “segmentation fault” a cada 10 segundos, este é o tempo que você terá para digitar o comando de remoção do módulo antes dele bagunçar seu shell!</span></font></p>
<p style="text-align: justify; "><font class="Apple-style-span" face="verdana, geneva, sans-serif"><span class="Apple-style-span" style="font-size: 14px;">E lembre-se de que você esta trabalhando em kernel space, com acesso total e irrestrito à memória e I/Os. Portanto, o ideal aqui é trabalhar em uma máquina virtual. É mais seguro e pode evitar muitos acidentes, principalmente para aqueles que estão começando os estudos do Kernel do Linux.</span></font></p>
<p style="text-align: justify; "><strong><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">PEGADINHA DO MALANDRO</span></span></strong></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Agora pegue este módulo, e quando seu amigo deixar a seção aberta para tomar um café, instale e cronometre o tempo que ele vai levar para encontrar a causa do “segmentation fault”! Isso se ele encontrar… :)<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Um abraço,<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Sergio Prado</span></span></p><div class="shr-publisher-2150"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic --><p>Posts relacionados:</p><ol>
<li><a href='http://sergioprado.org/linux-device-drivers-parte-1/' rel='bookmark' title='Linux Device Drivers — Parte 1'>Linux Device Drivers — Parte 1</a></li>
<li><a href='http://sergioprado.org/linux-device-drivers-parte-2/' rel='bookmark' title='Linux Device Drivers — Parte 2'>Linux Device Drivers — Parte 2</a></li>
<li><a href='http://sergioprado.org/por-dentro-da-console-em-sistemas-linux/' rel='bookmark' title='Por dentro da console em sistemas Linux'>Por dentro da console em sistemas Linux</a></li>
</ol><p><p>Sergio Prado atua com desenvolvimento de software para sistemas embarcados há mais de 15 anos. É sócio-fundador da Embed­ded Lab­works, uma empresa focada em te aju­dar a desen­volver soft­ware de qual­i­dade para sis­temas embar­ca­dos. Se você pre­cisa de ajuda para desen­volver seu pro­duto, ou quer saber mais sobre o que a Embed­ded Lab­works pode fazer por você, acesse <a href=”http://e-labworks.com/servicos/”> http://e-labworks.com/servicos</a>.</p>
<p>Este post foi originalmente publicado em <a href="http://sergioprado.org/implementando-um-teclado-virtual-no-linux/">Implementando um teclado virtual no Linux</a>.</p></p>]]></content:encoded>
			<wfw:commentRss>http://sergioprado.org/implementando-um-teclado-virtual-no-linux/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Linux Device Drivers — Trabalhando com Kernel Threads</title>
		<link>http://sergioprado.org/linux-device-drivers-trabalhando-com-kernel-threads/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=linux-device-drivers-trabalhando-com-kernel-threads</link>
		<comments>http://sergioprado.org/linux-device-drivers-trabalhando-com-kernel-threads/#comments</comments>
		<pubDate>Mon, 18 Apr 2011 22:59:39 +0000</pubDate>
		<dc:creator>Sergio Prado</dc:creator>
				<category><![CDATA[Linguagem C]]></category>
		<category><![CDATA[Linux embarcado]]></category>
		<category><![CDATA[device drivers]]></category>
		<category><![CDATA[Mini2440]]></category>

		<guid isPermaLink="false">http://www.sergioprado.org/?p=1566</guid>
		<description><![CDATA[<p>Neste artigo vamos aprender sobre kernel threads, e para exemplificar os conceitos iremos desenvolver um device driver para piscar os leds do kit FriendlyARM mini2440.</p><p><p>Sergio Prado atua com desenvolvimento de software para sistemas embarcados há mais de 15 anos. É sócio-fundador da Embed­ded Lab­works, uma empresa focada em te aju­dar a desen­volver soft­ware de qual­i­dade para sis­temas embar­ca­dos. Se você pre­cisa de ajuda para desen­volver seu pro­duto, ou quer saber mais sobre o que a Embed­ded Lab­works pode fazer por você, acesse <a href=”http://e-labworks.com/servicos/”> http://e-labworks.com/servicos</a>.</p>
<p>Este post foi originalmente publicado em <a href="http://sergioprado.org/linux-device-drivers-trabalhando-com-kernel-threads/">Linux Device Drivers — Trabalhando com Kernel Threads</a>.</p></p>
Posts relacionados:<ol>
<li><a href='http://sergioprado.org/linux-device-drivers-parte-1/' rel='bookmark' title='Linux Device Drivers — Parte 1'>Linux Device Drivers — Parte 1</a></li>
<li><a href='http://sergioprado.org/linux-device-drivers-parte-2/' rel='bookmark' title='Linux Device Drivers — Parte 2'>Linux Device Drivers — Parte 2</a></li>
<li><a href='http://sergioprado.org/device-drivers-e-gerenciamento-dinamico-de-dispositivos/' rel='bookmark' title='Device Drivers e gerenciamento dinâmico de dispositivos'>Device Drivers e gerenciamento dinâmico de dispositivos</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Já faz um tempo que não escrevo sobre desenvolvimento de device drivers em Linux. Na <a href="http://www.sergioprado.org/2011/01/07/linux-device-drivers-parte-2/" target="_blank">parte 2</a> desta série desenvolvemos um device driver completo para acessar os leds do kit FriendlyARM mini2440. Que tal estudar um pouco mais sobre a API do kernel do Linux? </span></p>
<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Neste artigo vamos aprender a trabalhar com threads em kernel space, e para exemplificar os conceitos, vamos fazer os leds do kit mini2440 piscarem.</span></p>
<p style="text-align: justify; "><strong><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">THREADS?<br />
	</span></span></strong></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Você já sabe que o Linux é um sistema operacional multi-tarefa, e que ele consegue executar mais de uma tarefa ao mesmo tempo. É claro que em sistemas com apenas 1 núcleo, apenas uma tarefa tem a atenção da CPU em determinado momento, mas temos a impressão de que várias coisas estão acontecendo simultaneamente. Isso ocorre devido ao fato do Linux ser um sistema operacional preemptivo. O escalonador aloca uma fatia do tempo disponível para cada tarefa em execução.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Se você trabalha a um tempo desenvolvendo aplicações para Linux, sabe que é possível ter mais de uma linha de execução em um processo. É o que chamamos de threads. E o conceito é simples: “dividir para conquistar”. Cada thread tem uma responsabilidade específica, e você acaba otimizando o uso dos recursos da máquina, além de estruturar melhor o código e facilitar a manutenção.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">O que você talvez não saiba é que em kernel space também podemos ter mais de uma thread de execução.<br />
	</span></span></p>
<p style="text-align: justify; "><strong><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">KERNEL THREADS?<br />
	</span></span></strong></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Kernel threads são threads dentro do kernel. Você pode por exemplo ter tarefas executando em background em um device driver, esperando por eventos assíncronos ou executando determinada atividade de tempos em tempos.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">É fácil identificar as threads do kernel rodando no seu sistema. Ao listar os processos em execução com o comando “ps”, os nomes entre “[]” são kernel threads. Veja um trecho da saída deste comando na minha máquina de desenvolvimento:<br />
	</span></span></p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">ps</span> auxf
PID   USER     COMMAND
    <span style="color: #000000;">1</span> root     init
    <span style="color: #000000;">2</span> root     <span style="color: #7a0874; font-weight: bold;">&#91;</span>kthreadd<span style="color: #7a0874; font-weight: bold;">&#93;</span>
    <span style="color: #000000;">3</span> root     <span style="color: #7a0874; font-weight: bold;">&#91;</span>ksoftirqd<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">0</span><span style="color: #7a0874; font-weight: bold;">&#93;</span>
    <span style="color: #000000;">4</span> root     <span style="color: #7a0874; font-weight: bold;">&#91;</span>events<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">0</span><span style="color: #7a0874; font-weight: bold;">&#93;</span>
    <span style="color: #000000;">5</span> root     <span style="color: #7a0874; font-weight: bold;">&#91;</span>khelper<span style="color: #7a0874; font-weight: bold;">&#93;</span>
   <span style="color: #000000;">81</span> root     <span style="color: #7a0874; font-weight: bold;">&#91;</span>kblockd<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">0</span><span style="color: #7a0874; font-weight: bold;">&#93;</span>
   <span style="color: #000000;">92</span> root     <span style="color: #7a0874; font-weight: bold;">&#91;</span>khubd<span style="color: #7a0874; font-weight: bold;">&#93;</span>
...</pre></div></div>



<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Da listagem acima, com exceção do processo “init”, o restante dos processos são kernel threads.</span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Mas quando você vai precisar de kernel threads? Em algumas situações, na verdade. Se você precisa esperar por eventos assíncronos, é bem provável que a solução seja criar uma thread no kernel para aguardar por este eventos. Se você tem uma tarefa dentro de um device driver que leva bastante tempo para ser executada, você pode delegá-la para uma kernel thread. Se você precisa executar determinada tarefa periodicamente, pode também usar uma thread no kernel para fazer isso.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Mas como isso funciona na prática? É o que veremos agora!<br />
	</span></span></p>
<p style="text-align: justify; "><strong><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">NOSSO EXEMPLO<br />
	</span></span></strong></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Mais uma vez, nosso exemplo será executado no kit mini2440. <a href="http://www.sergioprado.org/2011/01/07/linux-device-drivers-parte-2/" target="_blank">Neste </a><a href="http://www.sergioprado.org/2011/01/07/linux-device-drivers-parte-2/" target="_blank">artigo aqui</a> desenvolvemos um device driver para acender e apagar os leds deste kit. Agora iremos extender as funcionalidades deste device driver para fazer os leds piscarem. </span></span><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Da mesma forma que “0” apaga e “1” acende, enviar “2” ao led irá colocá-lo em um estado de “<em>blink</em>”, fazendo-o piscar com uma frequência de 1 segundo.</span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Existem duas formas de trabalhar com threads no kernel: a antiga e ultrapassada <em>kernel_thread() </em>e a atual e melhor estruturada <em>kthread</em>. Vamos ver exemplos com as duas. </span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Iremos criar uma thread que a cada 1 segundo irá verificar se algum dos leds esta configurado para piscar, e então inverteremos seu estado. Simples, não? Então mãos à obra!<br />
	</span></span></p>
<p style="text-align: justify; "><strong><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">A ANTIGA INTERFACE KERNEL_THREADS<br />
	</span></span></strong></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Este é o código responsável pelo gerenciamento da thread usando a antiga interface <em>kernel_thread()</em>:<br />
	</span></span></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#define BLINK_TIME  1000</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* flag to enable thread */</span>
<span style="color: #993333;">unsigned</span> <span style="color: #993333;">int</span> thread_enabled <span style="color: #339933;">=</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
<span style="color: #993333;">struct</span> completion leds_blink_exit<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* kernel thread to blink the leds */</span>
<span style="color: #993333;">static</span> <span style="color: #993333;">int</span> leds_blink<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span> <span style="color: #339933;">*</span>unused<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> i<span style="color: #339933;">;</span>
&nbsp;
    daemonize<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;leds_blink&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span>thread_enabled<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
        <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> NUM_LEDS<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>leds_dev<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">status</span> <span style="color: #339933;">==</span> LED_BLINK<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                changeLedStatus<span style="color: #009900;">&#40;</span>leds_dev<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">number</span><span style="color: #339933;">,</span> LED_BLINK<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        msleep<span style="color: #009900;">&#40;</span>BLINK_TIME<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    complete_and_exit<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>leds_blink_exit<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* driver initialization */</span>
<span style="color: #993333;">int</span> __init leds_init<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    ...
&nbsp;
    <span style="color: #808080; font-style: italic;">/* init completion struct */</span>
    init_completion<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>leds_blink_exit<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/* initialize leds_blink therad */</span>
    kernel_thread<span style="color: #009900;">&#40;</span>leds_blink<span style="color: #339933;">,</span> NULL<span style="color: #339933;">,</span> CLONE_FS <span style="color: #339933;">|</span> CLONE_FILES <span style="color: #339933;">|</span>
                  CLONE_SIGHAND <span style="color: #339933;">|</span> SIGCHLD<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    ....
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* driver exit */</span>
<span style="color: #993333;">void</span> __exit leds_exit<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    ...
&nbsp;
    <span style="color: #808080; font-style: italic;">/* stop thread */</span>
    thread_enabled <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
    wait_for_completion<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>leds_blink_exit<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    ...
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>



<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">A thread é criada na linha 37 com a função <em>kernel_thread()</em>. Esta função recebe basicamente um ponteiro para a função da thread e alguns parâmetros que indicam quais recursos serão compartilhados com o processo pai.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">A função da thread <em>leds_blink()</em> na linha 8 é bem simples. Ela é basicamente um loop infinito que periodicamente faz piscar os leds com o estado configurado como LED_BLINK.</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">A complexidade aqui esta no controle de finalização da thread. Se removermos o módulo do device driver sem aguardar a finalização da thread, esta ficará no sistema com o status de zombie. Precisamos controlar manualmente este processo, e fazemos isso através da flag <em>thread_enabled</em>. Ao finalizar a execução do módulo, setamos esta flag na linha 49 e aguardamos a finalização da execução da thread na linha 50.</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Para testar, basta enviar “2” ao arquivo de dispositivo do led que se deseja piscar. Por exemplo, para piscar o led 3:<br />
	</span></span></p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #000000;">2</span> <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>leds3</pre></div></div>



<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">O código completo deste device driver pode ser baixado <a href="http://www.sergioprado.org/wp-content/plugins/download-monitor/download.php?id=10" target="_blank">aqui</a>.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">A interface <em>kernel_thread</em> é antiga, propensa a bugs, e não deve ser usada em novos projetos. A frase abaixo é da própria documentação do kernel, disponível em “<em>documentation/feature-removal-schedule.txt</em>”:<br />
	</span></span></p>
<blockquote>
	<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">“kernel_thread is a low-level implementation detail. Drivers should use the &lt;linux/kthread.h&gt; API instead which shields them from implementation details and provides a higherlevel interface that prevents bugs and code duplication”.<br />
		</span></span></p></blockquote>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">É por isso que você deve esquecer tudo que leu acima… brincadeira! É bem capaz que você encontre um ou outro device driver usando esta API, por isso é bom conhecê-la. Mas você verá que com a interface <em>kthread</em> as coisas são muito mais fáceis.<br />
	</span></span></p>
<p style="text-align: justify; "><strong><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">A INTERFACE KTHREAD<br />
	</span></span></strong></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Os conceitos são os mesmos. A interface <em>kthread</em> na verdade utiliza a função <em>kernel_thread</em> internamente, mas abstraindo alguns conceitos, e tornando-a mais simples e segura de usar:</span></span></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#define BLINK_TIME  1000</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* kernel thread to blink the leds */</span>
<span style="color: #993333;">static</span> <span style="color: #993333;">int</span> leds_blink<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span> <span style="color: #339933;">*</span>unused<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> i<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>kthread_should_stop<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
        <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> NUM_LEDS<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>leds_dev<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">status</span> <span style="color: #339933;">==</span> LED_BLINK<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                changeLedStatus<span style="color: #009900;">&#40;</span>leds_dev<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">number</span><span style="color: #339933;">,</span> LED_BLINK<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        msleep<span style="color: #009900;">&#40;</span>BLINK_TIME<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">return</span><span style="color: #009900;">&#40;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* driver initialization */</span>
<span style="color: #993333;">int</span> __init leds_init<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    ...
&nbsp;
    <span style="color: #808080; font-style: italic;">/* initialize leds_blink therad */</span>
    leds_blink_task <span style="color: #339933;">=</span> kthread_run<span style="color: #009900;">&#40;</span>leds_blink<span style="color: #339933;">,</span> NULL<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;%s&quot;</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;leds_blink&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    ....
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* driver exit */</span>
<span style="color: #993333;">void</span> __exit leds_exit<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    ...
&nbsp;
    <span style="color: #808080; font-style: italic;">/* stop thread */</span>
    kthread_stop<span style="color: #009900;">&#40;</span>leds_blink_task<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    ...
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>



<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Veja como ficou simples. Usamos apenas 3 funções: <em>kthread_run()</em> para iniciar a thread (linha 28), <em>kthread_should_stop()</em> para que a thread saiba quando deve finalizar sua execução (linha 8) e <em>kthread_stop()</em> para finalizar a thread (linha 39). </span></span></p>
<p><meta content="text/html; charset=utf-8" http-equiv="content-type" /></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">O código completo deste device driver pode ser baixado <a href="http://www.sergioprado.org/wp-content/plugins/download-monitor/download.php?id=11" target="_blank">aqui</a>.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Vocês viram como é fácil usar threads no kernel do Linux. Mas devemos ter sempre muito cuidado com o que fazemos em kernel space. Dentro do kernel, temos acesso completo a todos os recursos da máquina. E com o poder vem a responsabilidade. Portanto, use este recurso com sabedoria.</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Um abraço,<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Sergio Prado</span></span></p><div class="shr-publisher-1566"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic --><p>Posts relacionados:</p><ol>
<li><a href='http://sergioprado.org/linux-device-drivers-parte-1/' rel='bookmark' title='Linux Device Drivers — Parte 1'>Linux Device Drivers — Parte 1</a></li>
<li><a href='http://sergioprado.org/linux-device-drivers-parte-2/' rel='bookmark' title='Linux Device Drivers — Parte 2'>Linux Device Drivers — Parte 2</a></li>
<li><a href='http://sergioprado.org/device-drivers-e-gerenciamento-dinamico-de-dispositivos/' rel='bookmark' title='Device Drivers e gerenciamento dinâmico de dispositivos'>Device Drivers e gerenciamento dinâmico de dispositivos</a></li>
</ol><p><p>Sergio Prado atua com desenvolvimento de software para sistemas embarcados há mais de 15 anos. É sócio-fundador da Embed­ded Lab­works, uma empresa focada em te aju­dar a desen­volver soft­ware de qual­i­dade para sis­temas embar­ca­dos. Se você pre­cisa de ajuda para desen­volver seu pro­duto, ou quer saber mais sobre o que a Embed­ded Lab­works pode fazer por você, acesse <a href=”http://e-labworks.com/servicos/”> http://e-labworks.com/servicos</a>.</p>
<p>Este post foi originalmente publicado em <a href="http://sergioprado.org/linux-device-drivers-trabalhando-com-kernel-threads/">Linux Device Drivers — Trabalhando com Kernel Threads</a>.</p></p>]]></content:encoded>
			<wfw:commentRss>http://sergioprado.org/linux-device-drivers-trabalhando-com-kernel-threads/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Netrino’s Embedded C Coding Standard</title>
		<link>http://sergioprado.org/netrinos-embedded-c-coding-standard/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=netrinos-embedded-c-coding-standard</link>
		<comments>http://sergioprado.org/netrinos-embedded-c-coding-standard/#comments</comments>
		<pubDate>Tue, 08 Mar 2011 23:01:53 +0000</pubDate>
		<dc:creator>Sergio Prado</dc:creator>
				<category><![CDATA[Linguagem C]]></category>
		<category><![CDATA[Netrino]]></category>
		<category><![CDATA[padrão]]></category>

		<guid isPermaLink="false">http://www.sergioprado.org/?p=1474</guid>
		<description><![CDATA[<p>Minhas impressões sobre o padrão de desenvolvimento de software embarcado em C da Netrino.</p><p><p>Sergio Prado atua com desenvolvimento de software para sistemas embarcados há mais de 15 anos. É sócio-fundador da Embed­ded Lab­works, uma empresa focada em te aju­dar a desen­volver soft­ware de qual­i­dade para sis­temas embar­ca­dos. Se você pre­cisa de ajuda para desen­volver seu pro­duto, ou quer saber mais sobre o que a Embed­ded Lab­works pode fazer por você, acesse <a href=”http://e-labworks.com/servicos/”> http://e-labworks.com/servicos</a>.</p>
<p>Este post foi originalmente publicado em <a href="http://sergioprado.org/netrinos-embedded-c-coding-standard/">Netrino’s Embedded C Coding Standard</a>.</p></p>
Sem posts relacionados.]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Em uma “promoção relâmpago” da <a href="http://www.netrino.com/" target="_blank">Netrino</a>, tive a oportunidade de comprar seu padrão para desenvolvimento de software embarcado em C por míseros $9.</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Assim como todo bom padrão de codificação, seu objetivo é diminuir a quantidade de bugs, melhorar a legibilidade, a manutenibilidade e a portabilidade de seus códigos em C.</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Quem acompanha meu blog sabe da importância que dou para este tipo de assunto, vide meus artigos sobre <a href="http://www.sergioprado.org/2011/01/14/linguagem-c-historia-e-padroes/" target="_blank">a história e os padrões da linguagem C</a>, e o <a href="http://www.sergioprado.org/2010/05/27/misra-c-padrao-para-software-em-c/" target="_blank">padrão MISRA-C</a>.</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Mas este documento da Netrino define algumas normas que se aproximam bastante da nossa realidade como desenvolvedor de software embarcado em C, já que não é tão aberto à interpretações como o padrão C99, nem tão restritivo quanto o MISRA-C.</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Michael Barr, autor do documento, e que já foi entrevistado por mim <a href="http://www.sergioprado.org/2010/12/14/entrevista-com-michael-barr/" target="_blank">aqui</a>, é uma personalidade conhecida no mercado mundial de embarcados, e teve a ajuda de outras personalidades como Nigel Jones, Jack Ganssle e Jean Labrosse na elaboração do padrão.</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">A principal premissa seguida pelo documento é a de que existe um trabalho contínuo em um produto com software embarcado. Apesar de alguns desenvolvedores pensarem o contrário, o código que você esta desenvolvendo não é seu, e sim da empresa em que atua! A não ser que esta empresa seja sua mesmo…:)</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">E um dia você, ou outra pessoa, precisará dar manutenção no código. Ou então o código é complexo o bastante para envolver uma equipe de vários desenvolvedores, cada um trabalhando em um módulo do software. Como coordenar este trabalho conjunto? Como garantir que todos “falarão a mesma língua”? Sem um padrão, fica realmente muito difícil.</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">E tem muita coisa boa nesse documento, incluindo regras como:</span></span></p>
<ul>
	<li style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Todo bloco deve explicitamente abrir e fechar chaves.</span></span></li>
	<li style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Ser explícito no uso de parênteses.</span></span></li>
	<li style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Usar <em>#if 0</em> para comentar código.</span></span></li>
	<li style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Escrever comentários antes de começar a codificar, mesmo porque você deve saber explicar o algoritmo antes de escrever uma linha de código.</span></li>
	<li style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Usar o <a href="http://www.stack.nl/~dimitri/doxygen/" target="_blank">Doxygen</a> para gerar documentação do código.</span></span></li>
	<li style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Usar uma ferramenta de Lint para análise estática de código (escrevi um artigo sobre análise estática de código <a href="http://www.sergioprado.org/2010/01/28/analise-estatica-codigo/" target="_blank">aqui</a>).</span></span></li>
	<li style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Usar um <em>Code Beautifier</em> para formatar o código (eu uso o <a href="http://astyle.sourceforge.net/" target="_blank">astyle</a>).</span></span></li>
	<li style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Definir uma variável apenas quando precisar dela, o que facilita a leitura do código e está dentro do padrão C99.</span></span></li></ul>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Confesso que não concordei 100% com o documento, como por exemplo as regras abaixo:</span></span></p>
<ul>
	<li style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Manter o código-fonte limitado a 80 colunas. Isso fazia sentido quando desenvolvíamos em monitores monocromáticos e imprimíamos o código em impressoras matriciais. Hoje, na minha opinião, já não é tão importante assim.</span></span></li>
	<li style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Não usar <em>goto</em>, <em>continue</em> e <em>break</em>. Ainda acho que estas palavras-chave possuem alguma utilidade bem específica. Este meu <a href="http://www.sergioprado.org/2011/02/15/voce-usa-goto-nos-seus-codigos-em-c/" target="_blank">post sobre goto</a> pode explicar.</span></span></li>
	<li style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Não usar <em>short</em> ou <em>long</em>. Por quê? Desde que protegidas com <em>typedef</em>, não vejo motivo em não utilizá-las.</span></span></li>
	<li style="text-align: justify; "><span style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Não usar vírgula na declaração de variáveis. Esta regra visa resolver problemas do tipo <em>“char * x, y;”</em>, quando queremos declarar ambas variáveis como ponteiro. Neste caso, o correto seria <em>“char *x, *y;”</em>. Mas discordo que, por causa deste tipo de problema, precisamos necessariamente declarar cada variável em uma linha. Uma função com 5 variáveis do tipo <em>char</em> precisaria de 5 linhas para declará-las. Acho isso desnecessário, e pode até piorar a legibilidade do código. Acredito que devemos tratar o caso da declaração de ponteiros como exceção, e não como regra</span>.</li></ul>
<p><meta content="text/html; charset=utf-8" http-equiv="content-type" /></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Ao todo, são 105 páginas com boas práticas de desenvolvimento em C para sistemas embarcados. No final do documento o autor disponibiliza modelos de arquivo fonte (.c) e header (.h).</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Se você tiver a oportunidade, vale a pena <a href="http://www.netrino.com/Coding-Standard" target="_blank">comprar o documento</a>. A propósito, não estou ganhando um centavo com isso, e até acho seu valor demasiado caro.</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Mas pensando bem, aquela “uma horinha” que você ou sua equipe perderam procurando um bug no software que poderia ter sido evitado seguindo algumas boas práticas, teriam pago o investimento, e com sobras!</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Um abraço,</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Sergio Prado</span></span></p><div class="shr-publisher-1474"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic --><p>Sem posts relacionados.</p><p><p>Sergio Prado atua com desenvolvimento de software para sistemas embarcados há mais de 15 anos. É sócio-fundador da Embed­ded Lab­works, uma empresa focada em te aju­dar a desen­volver soft­ware de qual­i­dade para sis­temas embar­ca­dos. Se você pre­cisa de ajuda para desen­volver seu pro­duto, ou quer saber mais sobre o que a Embed­ded Lab­works pode fazer por você, acesse <a href=”http://e-labworks.com/servicos/”> http://e-labworks.com/servicos</a>.</p>
<p>Este post foi originalmente publicado em <a href="http://sergioprado.org/netrinos-embedded-c-coding-standard/">Netrino’s Embedded C Coding Standard</a>.</p></p>]]></content:encoded>
			<wfw:commentRss>http://sergioprado.org/netrinos-embedded-c-coding-standard/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Você usa goto nos seus códigos em C?</title>
		<link>http://sergioprado.org/voce-usa-goto-nos-seus-codigos-em-c/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=voce-usa-goto-nos-seus-codigos-em-c</link>
		<comments>http://sergioprado.org/voce-usa-goto-nos-seus-codigos-em-c/#comments</comments>
		<pubDate>Wed, 16 Feb 2011 00:59:12 +0000</pubDate>
		<dc:creator>Sergio Prado</dc:creator>
				<category><![CDATA[Linguagem C]]></category>
		<category><![CDATA[assembly]]></category>
		<category><![CDATA[goto]]></category>

		<guid isPermaLink="false">http://www.sergioprado.org/?p=1417</guid>
		<description><![CDATA[<p>Neste post vamos analisar o uso da palavra-chave goto em Linguagem C.</p><p><p>Sergio Prado atua com desenvolvimento de software para sistemas embarcados há mais de 15 anos. É sócio-fundador da Embed­ded Lab­works, uma empresa focada em te aju­dar a desen­volver soft­ware de qual­i­dade para sis­temas embar­ca­dos. Se você pre­cisa de ajuda para desen­volver seu pro­duto, ou quer saber mais sobre o que a Embed­ded Lab­works pode fazer por você, acesse <a href=”http://e-labworks.com/servicos/”> http://e-labworks.com/servicos</a>.</p>
<p>Este post foi originalmente publicado em <a href="http://sergioprado.org/voce-usa-goto-nos-seus-codigos-em-c/">Você usa goto nos seus códigos em C?</a>.</p></p>
Posts relacionados:<ol>
<li><a href='http://sergioprado.org/tratamento-de-erros-em-linguagem-c/' rel='bookmark' title='Tratamento de erros em Linguagem C'>Tratamento de erros em Linguagem C</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Esses dias estava trabalhando em um device driver para Linux de um display LCD de 3.5″, e me deparei com o código abaixo, responsável pela inicialização do display:</span></span></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">static</span> <span style="color: #993333;">int</span> __init s3c24xxfb_probe<span style="color: #009900;">&#40;</span><span style="color: #993333;">struct</span> platform_device <span style="color: #339933;">*</span>pdev<span style="color: #339933;">,</span>
                                  <span style="color: #000000; font-weight: bold;">enum</span> s3c_drv_type drv_type<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">struct</span> s3c2410fb_info <span style="color: #339933;">*</span>info<span style="color: #339933;">;</span>
    <span style="color: #993333;">struct</span> s3c2410fb_display <span style="color: #339933;">*</span>display<span style="color: #339933;">;</span>
    <span style="color: #993333;">struct</span> fb_info <span style="color: #339933;">*</span>fbinfo<span style="color: #339933;">;</span>
    <span style="color: #993333;">struct</span> s3c2410fb_mach_info <span style="color: #339933;">*</span>mach_info<span style="color: #339933;">;</span>
    <span style="color: #993333;">struct</span> resource <span style="color: #339933;">*</span>res<span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> ret<span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> irq<span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> i<span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> size<span style="color: #339933;">;</span>
    u32 lcdcon1<span style="color: #339933;">;</span>
&nbsp;
    mach_info <span style="color: #339933;">=</span> pdev<span style="color: #339933;">-&gt;</span>dev.<span style="color: #202020;">platform_data</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>mach_info <span style="color: #339933;">==</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        dev_err<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>pdev<span style="color: #339933;">-&gt;</span>dev<span style="color: #339933;">,</span>
                <span style="color: #ff0000;">&quot;no platform data for lcd, cannot attach<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #339933;">-</span>EINVAL<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>mach_info<span style="color: #339933;">-&gt;</span>default_display <span style="color: #339933;">&gt;=</span> mach_info<span style="color: #339933;">-&gt;</span>num_displays<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        dev_err<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>pdev<span style="color: #339933;">-&gt;</span>dev<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;default is %d but only %d displays<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span>
                mach_info<span style="color: #339933;">-&gt;</span>default_display<span style="color: #339933;">,</span> mach_info<span style="color: #339933;">-&gt;</span>num_displays<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #339933;">-</span>EINVAL<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    display <span style="color: #339933;">=</span> mach_info<span style="color: #339933;">-&gt;</span>displays <span style="color: #339933;">+</span> mach_info<span style="color: #339933;">-&gt;</span>default_display<span style="color: #339933;">;</span>
&nbsp;
    irq <span style="color: #339933;">=</span> platform_get_irq<span style="color: #009900;">&#40;</span>pdev<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>irq <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        dev_err<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>pdev<span style="color: #339933;">-&gt;</span>dev<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;no irq for device<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #339933;">-</span>ENOENT<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    fbinfo <span style="color: #339933;">=</span> framebuffer_alloc<span style="color: #009900;">&#40;</span><span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">struct</span> s3c2410fb_info<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>pdev<span style="color: #339933;">-&gt;</span>dev<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>fbinfo<span style="color: #009900;">&#41;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #339933;">-</span>ENOMEM<span style="color: #339933;">;</span>
&nbsp;
    platform_set_drvdata<span style="color: #009900;">&#40;</span>pdev<span style="color: #339933;">,</span> fbinfo<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    info <span style="color: #339933;">=</span> fbinfo<span style="color: #339933;">-&gt;</span>par<span style="color: #339933;">;</span>
    info<span style="color: #339933;">-&gt;</span>dev <span style="color: #339933;">=</span> <span style="color: #339933;">&amp;</span>pdev<span style="color: #339933;">-&gt;</span>dev<span style="color: #339933;">;</span>
    info<span style="color: #339933;">-&gt;</span>drv_type <span style="color: #339933;">=</span> drv_type<span style="color: #339933;">;</span>
&nbsp;
    res <span style="color: #339933;">=</span> platform_get_resource<span style="color: #009900;">&#40;</span>pdev<span style="color: #339933;">,</span> IORESOURCE_MEM<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>res <span style="color: #339933;">==</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        dev_err<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>pdev<span style="color: #339933;">-&gt;</span>dev<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;failed to get memory registers<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        ret <span style="color: #339933;">=</span> <span style="color: #339933;">-</span>ENXIO<span style="color: #339933;">;</span>
        <span style="color: #b1b100;">goto</span> dealloc_fb<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    size <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>res<span style="color: #339933;">-&gt;</span>end <span style="color: #339933;">-</span> res<span style="color: #339933;">-&gt;</span>start<span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
    info<span style="color: #339933;">-&gt;</span>mem <span style="color: #339933;">=</span> request_mem_region<span style="color: #009900;">&#40;</span>res<span style="color: #339933;">-&gt;</span>start<span style="color: #339933;">,</span> size<span style="color: #339933;">,</span> pdev<span style="color: #339933;">-&gt;</span>name<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>info<span style="color: #339933;">-&gt;</span>mem <span style="color: #339933;">==</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        dev_err<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>pdev<span style="color: #339933;">-&gt;</span>dev<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;failed to get memory region<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        ret <span style="color: #339933;">=</span> <span style="color: #339933;">-</span>ENOENT<span style="color: #339933;">;</span>
        <span style="color: #b1b100;">goto</span> dealloc_fb<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    info<span style="color: #339933;">-&gt;</span>io <span style="color: #339933;">=</span> ioremap<span style="color: #009900;">&#40;</span>res<span style="color: #339933;">-&gt;</span>start<span style="color: #339933;">,</span> size<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>info<span style="color: #339933;">-&gt;</span>io <span style="color: #339933;">==</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        dev_err<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>pdev<span style="color: #339933;">-&gt;</span>dev<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;ioremap() of registers failed<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        ret <span style="color: #339933;">=</span> <span style="color: #339933;">-</span>ENXIO<span style="color: #339933;">;</span>
        <span style="color: #b1b100;">goto</span> release_mem<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    info<span style="color: #339933;">-&gt;</span>irq_base <span style="color: #339933;">=</span> info<span style="color: #339933;">-&gt;</span>io <span style="color: #339933;">+</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>drv_type <span style="color: #339933;">==</span> DRV_S3C2412<span style="color: #009900;">&#41;</span> <span style="color: #339933;">?</span> S3C2412_LCDINTBASE <span style="color: #339933;">:</span> S3C2410_LCDINTBASE<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    dprintk<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;devinit<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    strcpy<span style="color: #009900;">&#40;</span>fbinfo<span style="color: #339933;">-&gt;</span>fix.<span style="color: #202020;">id</span><span style="color: #339933;">,</span> driver_name<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/* Stop the video */</span>
    lcdcon1 <span style="color: #339933;">=</span> readl<span style="color: #009900;">&#40;</span>info<span style="color: #339933;">-&gt;</span>io <span style="color: #339933;">+</span> S3C2410_LCDCON1<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    writel<span style="color: #009900;">&#40;</span>lcdcon1 <span style="color: #339933;">&amp;</span> ~S3C2410_LCDCON1_ENVID<span style="color: #339933;">,</span> info<span style="color: #339933;">-&gt;</span>io <span style="color: #339933;">+</span> S3C2410_LCDCON1<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    fbinfo<span style="color: #339933;">-&gt;</span>fix.<span style="color: #202020;">type</span>      <span style="color: #339933;">=</span> FB_TYPE_PACKED_PIXELS<span style="color: #339933;">;</span>
    fbinfo<span style="color: #339933;">-&gt;</span>fix.<span style="color: #202020;">type_aux</span>  <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
    fbinfo<span style="color: #339933;">-&gt;</span>fix.<span style="color: #202020;">xpanstep</span>  <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
    fbinfo<span style="color: #339933;">-&gt;</span>fix.<span style="color: #202020;">ypanstep</span>  <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
    fbinfo<span style="color: #339933;">-&gt;</span>fix.<span style="color: #202020;">ywrapstep</span> <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
    fbinfo<span style="color: #339933;">-&gt;</span>fix.<span style="color: #202020;">accel</span>     <span style="color: #339933;">=</span> FB_ACCEL_NONE<span style="color: #339933;">;</span>
&nbsp;
    fbinfo<span style="color: #339933;">-&gt;</span>var.<span style="color: #202020;">nonstd</span>      <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
    fbinfo<span style="color: #339933;">-&gt;</span>var.<span style="color: #202020;">activate</span>    <span style="color: #339933;">=</span> FB_ACTIVATE_NOW<span style="color: #339933;">;</span>
    fbinfo<span style="color: #339933;">-&gt;</span>var.<span style="color: #202020;">accel_flags</span> <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
    fbinfo<span style="color: #339933;">-&gt;</span>var.<span style="color: #202020;">vmode</span>       <span style="color: #339933;">=</span> FB_VMODE_NONINTERLACED<span style="color: #339933;">;</span>
&nbsp;
    fbinfo<span style="color: #339933;">-&gt;</span>fbops           <span style="color: #339933;">=</span> <span style="color: #339933;">&amp;</span>s3c2410fb_ops<span style="color: #339933;">;</span>
    fbinfo<span style="color: #339933;">-&gt;</span>flags           <span style="color: #339933;">=</span> FBINFO_FLAG_DEFAULT<span style="color: #339933;">;</span>
    fbinfo<span style="color: #339933;">-&gt;</span>pseudo_palette  <span style="color: #339933;">=</span> <span style="color: #339933;">&amp;</span>info<span style="color: #339933;">-&gt;</span>pseudo_pal<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">256</span><span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span>
        info<span style="color: #339933;">-&gt;</span>palette_buffer<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> PALETTE_BUFF_CLEAR<span style="color: #339933;">;</span>
&nbsp;
    ret <span style="color: #339933;">=</span> request_irq<span style="color: #009900;">&#40;</span>irq<span style="color: #339933;">,</span> s3c2410fb_irq<span style="color: #339933;">,</span> IRQF_DISABLED<span style="color: #339933;">,</span> pdev<span style="color: #339933;">-&gt;</span>name<span style="color: #339933;">,</span> info<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>ret<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        dev_err<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>pdev<span style="color: #339933;">-&gt;</span>dev<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;cannot get irq %d - err %d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> irq<span style="color: #339933;">,</span> ret<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        ret <span style="color: #339933;">=</span> <span style="color: #339933;">-</span>EBUSY<span style="color: #339933;">;</span>
        <span style="color: #b1b100;">goto</span> release_regs<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    info<span style="color: #339933;">-&gt;</span>clk <span style="color: #339933;">=</span> clk_get<span style="color: #009900;">&#40;</span>NULL<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;lcd&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>info<span style="color: #339933;">-&gt;</span>clk <span style="color: #339933;">||</span> IS_ERR<span style="color: #009900;">&#40;</span>info<span style="color: #339933;">-&gt;</span>clk<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        printk<span style="color: #009900;">&#40;</span>KERN_ERR <span style="color: #ff0000;">&quot;failed to get lcd clock source<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        ret <span style="color: #339933;">=</span> <span style="color: #339933;">-</span>ENOENT<span style="color: #339933;">;</span>
        <span style="color: #b1b100;">goto</span> release_irq<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    clk_enable<span style="color: #009900;">&#40;</span>info<span style="color: #339933;">-&gt;</span>clk<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    dprintk<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;got and enabled clock<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    msleep<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    info<span style="color: #339933;">-&gt;</span>clk_rate <span style="color: #339933;">=</span> clk_get_rate<span style="color: #009900;">&#40;</span>info<span style="color: #339933;">-&gt;</span>clk<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/* find maximum required memory size for display */</span>
    <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> mach_info<span style="color: #339933;">-&gt;</span>num_displays<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #993333;">unsigned</span> <span style="color: #993333;">long</span> smem_len <span style="color: #339933;">=</span> mach_info<span style="color: #339933;">-&gt;</span>displays<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">xres</span><span style="color: #339933;">;</span>
&nbsp;
        smem_len <span style="color: #339933;">*=</span> mach_info<span style="color: #339933;">-&gt;</span>displays<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">yres</span><span style="color: #339933;">;</span>
        smem_len <span style="color: #339933;">*=</span> mach_info<span style="color: #339933;">-&gt;</span>displays<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">bpp</span><span style="color: #339933;">;</span>
        smem_len <span style="color: #339933;">&gt;&gt;=</span> <span style="color: #0000dd;">3</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>fbinfo<span style="color: #339933;">-&gt;</span>fix.<span style="color: #202020;">smem_len</span> <span style="color: #339933;">&lt;</span> smem_len<span style="color: #009900;">&#41;</span>
            fbinfo<span style="color: #339933;">-&gt;</span>fix.<span style="color: #202020;">smem_len</span> <span style="color: #339933;">=</span> smem_len<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/* Initialize video memory */</span>
    ret <span style="color: #339933;">=</span> s3c2410fb_map_video_memory<span style="color: #009900;">&#40;</span>fbinfo<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>ret<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        printk<span style="color: #009900;">&#40;</span>KERN_ERR <span style="color: #ff0000;">&quot;Failed to allocate video RAM: %d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> ret<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        ret <span style="color: #339933;">=</span> <span style="color: #339933;">-</span>ENOMEM<span style="color: #339933;">;</span>
        <span style="color: #b1b100;">goto</span> release_clock<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    dprintk<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;got video memory<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    fbinfo<span style="color: #339933;">-&gt;</span>var.<span style="color: #202020;">xres</span> <span style="color: #339933;">=</span> display<span style="color: #339933;">-&gt;</span>xres<span style="color: #339933;">;</span>
    fbinfo<span style="color: #339933;">-&gt;</span>var.<span style="color: #202020;">yres</span> <span style="color: #339933;">=</span> display<span style="color: #339933;">-&gt;</span>yres<span style="color: #339933;">;</span>
    fbinfo<span style="color: #339933;">-&gt;</span>var.<span style="color: #202020;">bits_per_pixel</span> <span style="color: #339933;">=</span> display<span style="color: #339933;">-&gt;</span>bpp<span style="color: #339933;">;</span>
&nbsp;
    s3c2410fb_init_registers<span style="color: #009900;">&#40;</span>fbinfo<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    s3c2410fb_check_var<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>fbinfo<span style="color: #339933;">-&gt;</span>var<span style="color: #339933;">,</span> fbinfo<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    ret <span style="color: #339933;">=</span> s3c2410fb_cpufreq_register<span style="color: #009900;">&#40;</span>info<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>ret <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        dev_err<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>pdev<span style="color: #339933;">-&gt;</span>dev<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;Failed to register cpufreq<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">goto</span> free_video_memory<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    ret <span style="color: #339933;">=</span> register_framebuffer<span style="color: #009900;">&#40;</span>fbinfo<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>ret <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        printk<span style="color: #009900;">&#40;</span>KERN_ERR <span style="color: #ff0000;">&quot;Failed to register framebuffer device: %d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span>
               ret<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">goto</span> free_cpufreq<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/* create device files */</span>
    ret <span style="color: #339933;">=</span> device_create_file<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>pdev<span style="color: #339933;">-&gt;</span>dev<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>dev_attr_debug<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>ret<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        printk<span style="color: #009900;">&#40;</span>KERN_ERR <span style="color: #ff0000;">&quot;failed to add debug attribute<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    printk<span style="color: #009900;">&#40;</span>KERN_INFO <span style="color: #ff0000;">&quot;fb%d: %s frame buffer device<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span>
           fbinfo<span style="color: #339933;">-&gt;</span>node<span style="color: #339933;">,</span> fbinfo<span style="color: #339933;">-&gt;</span>fix.<span style="color: #202020;">id</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
&nbsp;
free_cpufreq<span style="color: #339933;">:</span>
    s3c2410fb_cpufreq_deregister<span style="color: #009900;">&#40;</span>info<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
free_video_memory<span style="color: #339933;">:</span>
    s3c2410fb_unmap_video_memory<span style="color: #009900;">&#40;</span>fbinfo<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
release_clock<span style="color: #339933;">:</span>
    clk_disable<span style="color: #009900;">&#40;</span>info<span style="color: #339933;">-&gt;</span>clk<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    clk_put<span style="color: #009900;">&#40;</span>info<span style="color: #339933;">-&gt;</span>clk<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
release_irq<span style="color: #339933;">:</span>
    free_irq<span style="color: #009900;">&#40;</span>irq<span style="color: #339933;">,</span> info<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
release_regs<span style="color: #339933;">:</span>
    iounmap<span style="color: #009900;">&#40;</span>info<span style="color: #339933;">-&gt;</span>io<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
release_mem<span style="color: #339933;">:</span>
    release_resource<span style="color: #009900;">&#40;</span>info<span style="color: #339933;">-&gt;</span>mem<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    kfree<span style="color: #009900;">&#40;</span>info<span style="color: #339933;">-&gt;</span>mem<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
dealloc_fb<span style="color: #339933;">:</span>
    platform_set_drvdata<span style="color: #009900;">&#40;</span>pdev<span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    framebuffer_release<span style="color: #009900;">&#40;</span>fbinfo<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span> ret<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>



<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Esqueça um pouco o que a função faz, e perceba como ela implementa o tratamento de erros. Para cada erro identificado, ela usa chamadas a <em>goto</em> para tratar o erro e fazer uma limpeza antes de retornar da função (desalocar <em>buffers</em> previamente alocados, liberar recursos, configurar portas de I/O, etc). São ao todo oito chamadas a <em>goto</em> apenas nesta função!</span></span></p>
<p style="text-align: center; "><img alt="goto Você usa goto nos seus códigos em C?" height="149" src="http://www.sergioprado.org/wp-content/uploads/goto.png" width="550" title="Você usa goto nos seus códigos em C?" /></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Não aprendemos que usar <em>goto</em> é uma técnica ruim? Também não aprendemos que todo código bem estruturado em C não deve ter nenhuma chamada a <em>goto</em>? Então como é possível encontrar um código assim dentro do kernel do Linux?</span></span></p>
<p style="text-align: justify; "><strong><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">NÃO SE ASSUSTE</span></span></strong></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Usar <em>goto</em> em código C pode ser mais comum do que você imagina. Fiz um levantamento do uso da palavra-chave “<em>goto</em>” no kernel do <a href="http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.37.tar.bz2" target="_blank">Linux 2.6.37</a>, no <a href="http://www.busybox.net/" target="_blank">Busybox</a> e no <a href="http://www.denx.de/wiki/U-Boot" target="_blank">U-Boot</a>.</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Apenas o core do kernel (<em>/kernel</em>), possui 1.417 usos de <em>goto</em>. Quando incluimos os drivers de dispositivo (<em>/drivers</em>) e o código dependente de arquitetura (<em>/arch</em>) são 54.223 usos de <em>goto</em>. Fazendo a contagem completa, chegamos ao impressionante numero de 84.719 usos de <em>goto</em> no kernel do Linux!</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Mas não é só o kernel do Linux que abusa de <em>goto</em>. O pacote <em>Busybox</em>, comum em sistemas embarcados com Linux, usa o <em>goto</em> 1.782 vezes. E o famoso bootloader U-Boot utiliza em 1.662 oportunidades.</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Ok Sergio, então você esta me dizendo que estou livre para usar e abusar de goto no meu código?</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Calma aí, não é bem assim!</span></span></p>
<p style="text-align: justify; "><strong><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">BAIXANDO O NÍVEL</span></span></strong></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Veja o código que o compilador <em>gcc</em> gera em uma chamada a <em>goto</em>, comparando o fonte em <em>C</em> e o arquivo <em>assembly</em> gerado:</span></span></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> i <span style="color: #339933;">=</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>i<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Goto error!<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">goto</span> error<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;OK!<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
&nbsp;
error<span style="color: #339933;">:</span>
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>





<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
</pre></td><td class="code"><pre class="asm" style="font-family:monospace;">    <span style="color: #339933;">.</span>file   <span style="color: #7f007f;">&quot;goto.c&quot;</span>
    <span style="color: #339933;">.</span>section    <span style="color: #339933;">.</span>rodata
<span style="color: #339933;">.</span>LC0<span style="color: #339933;">:</span>
    <span style="color: #339933;">.</span>string <span style="color: #7f007f;">&quot;Goto error!&quot;</span>
<span style="color: #339933;">.</span>LC1<span style="color: #339933;">:</span>
    <span style="color: #339933;">.</span>string <span style="color: #7f007f;">&quot;OK!&quot;</span>
    <span style="color: #339933;">.</span>text
<span style="color: #339933;">.</span>globl main
    <span style="color: #339933;">.</span><span style="color: #000000; font-weight: bold;">type</span>   main<span style="color: #339933;">,</span> @function
main<span style="color: #339933;">:</span>
    pushl   <span style="color: #339933;">%</span><span style="color: #00007f;">ebp</span>
    movl    <span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">ebp</span>
    andl    $<span style="color: #339933;">-</span><span style="color: #0000ff;">16</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">esp</span>
    subl    $<span style="color: #0000ff;">32</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">esp</span>
    movl    $<span style="color: #0000ff;">1</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">28</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span>
    cmpl    $<span style="color: #0000ff;">0</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">28</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span>
    <span style="color: #00007f; font-weight: bold;">je</span>  <span style="color: #339933;">.</span>L2
    movl    $<span style="color: #339933;">.</span>LC0<span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span>
    <span style="color: #00007f; font-weight: bold;">call</span>    puts
    <span style="color: #00007f; font-weight: bold;">nop</span>
<span style="color: #339933;">.</span>L3<span style="color: #339933;">:</span>
    movl    $<span style="color: #0000ff;">1</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">eax</span>
    <span style="color: #00007f; font-weight: bold;">jmp</span> <span style="color: #339933;">.</span>L4
<span style="color: #339933;">.</span>L2<span style="color: #339933;">:</span>
    movl    $<span style="color: #339933;">.</span>LC1<span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span>
    <span style="color: #00007f; font-weight: bold;">call</span>    puts
    movl    $<span style="color: #0000ff;">0</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">eax</span>
<span style="color: #339933;">.</span>L4<span style="color: #339933;">:</span>
    <span style="color: #00007f; font-weight: bold;">leave</span>
    <span style="color: #00007f; font-weight: bold;">ret</span>
    <span style="color: #339933;">.</span><span style="color: #000000; font-weight: bold;">size</span>   main<span style="color: #339933;">,</span> <span style="color: #339933;">.-</span>main
    <span style="color: #339933;">.</span>ident  <span style="color: #7f007f;">&quot;GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3&quot;</span>
    <span style="color: #339933;">.</span>section    <span style="color: #339933;">.</span>note<span style="color: #339933;">.</span>GNU<span style="color: #339933;">-</span><span style="color: #000000; font-weight: bold;">stack</span><span style="color: #339933;">,</span><span style="color: #7f007f;">&quot;&quot;</span><span style="color: #339933;">,</span>@progbits</pre></td></tr></table></div>



<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Veja que o <em>if</em> na linha 5 do fonte <em>C</em> gera uma chamada a “<em>je .L2</em>″ (jump condicional) na linha 17 do código Assembly. E o <em>goto</em> na linha 7 do fonte <em>C</em> gera uma chamada a “<em>jmp .L4</em>″ (jump) na linha 23 do código assembly.</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Perceba que, na prática, tudo é tratado com uma instrução de salto no nível do <em>assembly</em>, não importa se você esta usando <em>goto</em>, <em>if/else</em>, <em>switch</em>, <em>do/while</em> ou <em>for</em>. Não existe nenhum impacto na performance ou no uso de memória da aplicação. Na verdade, em alguns casos, o uso de <em>goto</em> pode até melhorar a performance da aplicação. Mas normalmente seu uso é uma questão de legibilidade do código.</span></span></p>
<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Os mais puristas afirmam que não existe nada que se escreva usando <em>goto</em>, que não possa ser escrito usando as estruturas de controle disponíveis na linguagem C (<em>if/else</em>, <em>switch</em>, <em>do/while</em>, <em>for</em>), e durante um bom tempo também acreditei nisso. Mas na prática, às vezes, a teoria é diferente! E existem alguns casos onde o uso de <em>goto</em> pode ser a melhor solução.</span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Sergio, você já não falou que é contra o uso de <em>goto</em> em código C? Sim, mas isso não muda o fato de que pode existir uma forma de utilizar esta palavra-chave melhorando a estrutura e a legibilidade do seu programa.</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Mas você também não esta sempre defendendo qualidade de código, segurança, bla bla bla, e agora vem me falar que existe uma utilidade para o uso de “goto”? Sim, existe! É só olhar para os números (e para o código-fonte do kernel do Linux, e para outros tantos códigos open-source). Essa utilidade chama-se: Tratamento de Erros!</span></span></p>
<p style="text-align: justify; "><strong><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">O PROBLEMA EM QUESTÃO</span></span></strong></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Uma das deficiências da linguagem C é a ausência de um mecanismo simples e eficiente de tratamento de erros. Já escrevi sobre isso <a href="http://www.sergioprado.org/2010/06/12/tratamento-de-erros-em-linguagem-c/" target="_blank">neste post aqui</a>.</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">O problema fica mais transparente quando precisamos lidar com limpeza (desalocação) de recursos. Dê uma olhada no exemplo abaixo:</span></span></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">int</span> initRTC<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>buf1<span style="color: #339933;">,</span> <span style="color: #339933;">*</span>buf2<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>buf1 <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span>malloc<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">20</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> NULL<span style="color: #009900;">&#41;</span>
        <span style="color: #b1b100;">return</span> ERR_RTC_MALLOC<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>buf2 <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span>malloc<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">40</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        free<span style="color: #009900;">&#40;</span>buf1<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">return</span> ERR_RTC_MALLOC<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>openRTC<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        free<span style="color: #009900;">&#40;</span>buf2<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        free<span style="color: #009900;">&#40;</span>buf1<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">return</span> ERR_RTC_OPEN<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>cfgRTC<span style="color: #009900;">&#40;</span>buf1<span style="color: #339933;">,</span> <span style="color: #0000dd;">20</span><span style="color: #339933;">,</span> buf2<span style="color: #339933;">,</span> <span style="color: #0000dd;">40</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        closeRTC<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        free<span style="color: #009900;">&#40;</span>buf2<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        free<span style="color: #009900;">&#40;</span>buf1<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">return</span> ERR_RTC_CFG<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>txCmd<span style="color: #009900;">&#40;</span>buf1<span style="color: #339933;">,</span> <span style="color: #0000dd;">20</span><span style="color: #339933;">,</span> buf2<span style="color: #339933;">,</span> <span style="color: #0000dd;">40</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        closeRTC<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        free<span style="color: #009900;">&#40;</span>buf2<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        free<span style="color: #009900;">&#40;</span>buf1<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">return</span> ERR_RTC_TX<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    closeRTC<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    free<span style="color: #009900;">&#40;</span>buf2<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    free<span style="color: #009900;">&#40;</span>buf1<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> RTC_OK<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>



<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Esta função faz duas alocações de memória, abre a comunicação com o RTC, configura os buffers e transmite. Perceba que existe vários pontos de retorno. </span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Na linha 8, em caso de erro na chamada a <em>malloc()</em> para o <em>buf2</em>, é necessário liberar a memória alocada para <em>buf1</em> antes de retornar. Da mesma forma, se der erro ao abrir a comunicação com o RTC na linha 13, é necessário liberar a memória alocada em <em>buf1</em> e <em>buf2</em>. E por aí vai. </span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Para cada ponto de retorno adicional, precisamos lembrar de fazer a limpeza necessária antes de retornar. Veja que os trechos de código responsáveis pela limpeza são replicados nos vários pontos de retorno. Imagine o problema e os riscos envolvidos em dar manutenção num código desse tipo.</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Veja agora a mesma função reescrita usando <em>goto</em>:</span></span></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">int</span> initRTC<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>buf1<span style="color: #339933;">,</span> <span style="color: #339933;">*</span>buf2<span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> ret <span style="color: #339933;">=</span> RTC_OK<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>buf1 <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span>malloc<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">20</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        ret <span style="color: #339933;">=</span> ERR_RTC_MALLOC<span style="color: #339933;">;</span>
        <span style="color: #b1b100;">goto</span> fim0<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>buf2 <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span>malloc<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">40</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        ret <span style="color: #339933;">=</span> ERR_RTC_MALLOC<span style="color: #339933;">;</span>
        <span style="color: #b1b100;">goto</span> fim1<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>openRTC<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        ret <span style="color: #339933;">=</span> ERR_RTC_OPEN<span style="color: #339933;">;</span>
        <span style="color: #b1b100;">goto</span> fim2<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>cfgRTC<span style="color: #009900;">&#40;</span>buf1<span style="color: #339933;">,</span> <span style="color: #0000dd;">20</span><span style="color: #339933;">,</span> buf2<span style="color: #339933;">,</span> <span style="color: #0000dd;">40</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        ret <span style="color: #339933;">=</span> ERR_RTC_CFG<span style="color: #339933;">;</span>
        <span style="color: #b1b100;">goto</span> fim3<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>txCmd<span style="color: #009900;">&#40;</span>buf1<span style="color: #339933;">,</span> <span style="color: #0000dd;">20</span><span style="color: #339933;">,</span> buf2<span style="color: #339933;">,</span> <span style="color: #0000dd;">40</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        ret <span style="color: #339933;">=</span> ERR_RTC_TX<span style="color: #339933;">;</span>
        <span style="color: #b1b100;">goto</span> fim3<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
fim3<span style="color: #339933;">:</span>
    closeRTC<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
fim2<span style="color: #339933;">:</span>
    free<span style="color: #009900;">&#40;</span>buf2<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
fim1<span style="color: #339933;">:</span>
    free<span style="color: #009900;">&#40;</span>buf1<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
fim0<span style="color: #339933;">:</span>
    <span style="color: #b1b100;">return</span> ret<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>



<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Agora a função tem apenas um ponto de retorno e não existe mais código replicado para fazer a limpeza (desalocação de recursos) em caso de erro, o que facilita a leitura e futuras manutenções. Me parece uma solução interessante para um problema comum e sem solução fácil em <em>C</em>.</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">É claro que existem outros mecanismos para resolver este mesmo problema. Você pode criar uma máquina de estados, conforme o exemplo abaixo:</span></span></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">int</span> initRTC<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>buf1<span style="color: #339933;">,</span> <span style="color: #339933;">*</span>buf2<span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> ret <span style="color: #339933;">=</span> RTC_OK<span style="color: #339933;">,</span> state <span style="color: #339933;">=</span> ST_BUF1<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span>state <span style="color: #339933;">!=</span> ST_DONE<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
        <span style="color: #b1b100;">switch</span><span style="color: #009900;">&#40;</span>state<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
            <span style="color: #b1b100;">case</span> ST_BUF1<span style="color: #339933;">:</span>
                <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>buf1 <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span>malloc<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">20</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                    ret <span style="color: #339933;">=</span> ERR_RTC_MALLOC<span style="color: #339933;">;</span>
                    state <span style="color: #339933;">=</span> ST_DONE<span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
                <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
                    state <span style="color: #339933;">=</span> ST_BUF2<span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
                <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #b1b100;">case</span> ST_BUF2<span style="color: #339933;">:</span>
                <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>buf2 <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span>malloc<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">40</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                    ret <span style="color: #339933;">=</span> ERR_RTC_MALLOC<span style="color: #339933;">;</span>
                    state <span style="color: #339933;">=</span> ST_ERR_BUF2<span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
                <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
                    state <span style="color: #339933;">=</span> ST_OPEN_RTC<span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
                <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #b1b100;">case</span> ST_OPEN_RTC<span style="color: #339933;">:</span>
                <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>openRTC<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                    ret <span style="color: #339933;">=</span> ERR_RTC_OPEN<span style="color: #339933;">;</span>
                    state <span style="color: #339933;">=</span> ST_ERR_OPEN<span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
                <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
                    state <span style="color: #339933;">=</span> ST_CFG_RTC<span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
                <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #666666; font-style: italic;">// ....</span>
&nbsp;
            <span style="color: #b1b100;">case</span> ST_ERR_BUF2<span style="color: #339933;">:</span>
                free<span style="color: #009900;">&#40;</span>buf1<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                state <span style="color: #339933;">=</span> ST_DONE<span style="color: #339933;">;</span>
                <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #b1b100;">case</span> ST_ERR_OPEN<span style="color: #339933;">:</span>
                free<span style="color: #009900;">&#40;</span>buf2<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                state <span style="color: #339933;">=</span> ST_ERR_BUF2<span style="color: #339933;">;</span>
                <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #b1b100;">case</span> ST_ERR_TX<span style="color: #339933;">:</span>
                closeRTC<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                state <span style="color: #339933;">=</span> ST_ERR_OPEN<span style="color: #339933;">;</span>
                <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #666666; font-style: italic;">// ....</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> ret<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>



<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Não implementei todos os estados, mas dá para ter uma idéia do mecanismo utilizado. Perceba a complexidade deste código, comparado ao código com <em>goto</em>.</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Podemos também aninhar chamadas <em>if/else</em> e controlar a desalocação de recursos com alguns flags:</span></span></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">int</span> initRTC<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>buf1<span style="color: #339933;">,</span> <span style="color: #339933;">*</span>buf2<span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> ret <span style="color: #339933;">=</span> RTC_OK<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>buf1 <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span>malloc<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">20</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        ret <span style="color: #339933;">=</span> ERR_RTC_MALLOC1<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>buf2 <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span>malloc<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">40</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        ret <span style="color: #339933;">=</span> ERR_RTC_MALLOC2<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>openRTC<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        ret <span style="color: #339933;">=</span> ERR_RTC_OPEN<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>cfgRTC<span style="color: #009900;">&#40;</span>buf1<span style="color: #339933;">,</span> <span style="color: #0000dd;">20</span><span style="color: #339933;">,</span> buf2<span style="color: #339933;">,</span> <span style="color: #0000dd;">40</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        ret <span style="color: #339933;">=</span> ERR_RTC_CFG<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>txCmd<span style="color: #009900;">&#40;</span>buf1<span style="color: #339933;">,</span> <span style="color: #0000dd;">20</span><span style="color: #339933;">,</span> buf2<span style="color: #339933;">,</span> <span style="color: #0000dd;">40</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        ret <span style="color: #339933;">=</span> ERR_RTC_TX<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>ret <span style="color: #339933;">&gt;=</span> ERR_RTC_CFG<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        closeRTC<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>ret <span style="color: #339933;">&gt;=</span> ERR_RTC_OPEN<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        free<span style="color: #009900;">&#40;</span>buf2<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>ret <span style="color: #339933;">&gt;=</span> ERR_RTC_MALLOC2<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        free<span style="color: #009900;">&#40;</span>buf1<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> ret<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>



<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Neste exemplo estamos usando a própria variável de retorno como flag para desalocação de recursos. O problema deste tipo de código é que nem sempre temos a possibilidade de aninhar <em>if’s</em> e <em>else’s</em> desta forma. Esta técnica pode também deixar o código muito sujo, dependendo da sua complexidade. </span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Ainda neste exemplo, você poderia usar o próprio estado do recurso para verificar se deve realizar a desalocação, implementando no fim da função:</span></span></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="code"><pre class="c" style="font-family:monospace;">    <span style="color: #666666; font-style: italic;">//...</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>rtcOpenned<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        closeRTC<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>buf2 <span style="color: #339933;">!=</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        free<span style="color: #009900;">&#40;</span>buf2<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>buf1 <span style="color: #339933;">!=</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        free<span style="color: #009900;">&#40;</span>buf1<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">//...</span></pre></td></tr></table></div>



<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Mas nem sempre você tem o controle de quais recursos precisa desalocar. De qualquer forma, o código com <em>if/else</em> aninhados ainda continua mais complicado de ler, quando comparado à solução com <em>goto</em>.</span></span></p>
<p style="text-align: justify; "><strong><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">ONDE ESTA O PROBLEMA ENTÃO?</span></span></strong></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Se o código com <em>goto</em> neste caso é menos complicado de ler, e o binário gerado não sofre nenhum impacto na performance ou no uso de memória, porque não usá-lo?</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Assim como grande parte dos problemas da vida, o erro esta no excesso. É muito fácil abusar deste recurso, e deixar o código cheio de “idas” e “vindas” (o famoso código-espaguete!). </span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Foi o que aconteceu no passado, e isso ajudou a criar a má reputação do uso de <em>goto</em>. Pense sempre nos prós e contras, reflita sobre sua forma de pensar e use os recursos disponíveis na linguagem com muita sabedoria.</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Não foi meu objetivo neste artigo fazer qualquer tipo de apologia ao uso de “goto” em linguagem C, muito pelo contrário! Particularmente evito seu uso sempre que possível. Apenas acho válida uma análise mais profunda de nossos paradigmas de programação. Eu procuro sempre “guardar na manga” algumas técnicas para usar quando necessário.</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">E você? O que acha do uso de <em>goto</em> em linguagem <em>C</em>? Conhece alguma outra técnica para tratar o problema citado acima?</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Um abraço,</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Sergio Prado</span></span></p><div class="shr-publisher-1417"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic --><p>Posts relacionados:</p><ol>
<li><a href='http://sergioprado.org/tratamento-de-erros-em-linguagem-c/' rel='bookmark' title='Tratamento de erros em Linguagem C'>Tratamento de erros em Linguagem C</a></li>
</ol><p><p>Sergio Prado atua com desenvolvimento de software para sistemas embarcados há mais de 15 anos. É sócio-fundador da Embed­ded Lab­works, uma empresa focada em te aju­dar a desen­volver soft­ware de qual­i­dade para sis­temas embar­ca­dos. Se você pre­cisa de ajuda para desen­volver seu pro­duto, ou quer saber mais sobre o que a Embed­ded Lab­works pode fazer por você, acesse <a href=”http://e-labworks.com/servicos/”> http://e-labworks.com/servicos</a>.</p>
<p>Este post foi originalmente publicado em <a href="http://sergioprado.org/voce-usa-goto-nos-seus-codigos-em-c/">Você usa goto nos seus códigos em C?</a>.</p></p>]]></content:encoded>
			<wfw:commentRss>http://sergioprado.org/voce-usa-goto-nos-seus-codigos-em-c/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Device Drivers e gerenciamento dinâmico de dispositivos</title>
		<link>http://sergioprado.org/device-drivers-e-gerenciamento-dinamico-de-dispositivos/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=device-drivers-e-gerenciamento-dinamico-de-dispositivos</link>
		<comments>http://sergioprado.org/device-drivers-e-gerenciamento-dinamico-de-dispositivos/#comments</comments>
		<pubDate>Fri, 21 Jan 2011 23:52:07 +0000</pubDate>
		<dc:creator>Sergio Prado</dc:creator>
				<category><![CDATA[Linguagem C]]></category>
		<category><![CDATA[Linux embarcado]]></category>
		<category><![CDATA[Mini2440]]></category>
		<category><![CDATA[devfs]]></category>
		<category><![CDATA[device drivers]]></category>
		<category><![CDATA[mdev]]></category>
		<category><![CDATA[udev]]></category>

		<guid isPermaLink="false">http://www.sergioprado.org/?p=1327</guid>
		<description><![CDATA[<p>Neste post vamos aprender como o Linux gerencia dinamicamente os arquivos de dispositivo e implementar um device driver que envie notificações de eventos ao udev.</p><p><p>Sergio Prado atua com desenvolvimento de software para sistemas embarcados há mais de 15 anos. É sócio-fundador da Embed­ded Lab­works, uma empresa focada em te aju­dar a desen­volver soft­ware de qual­i­dade para sis­temas embar­ca­dos. Se você pre­cisa de ajuda para desen­volver seu pro­duto, ou quer saber mais sobre o que a Embed­ded Lab­works pode fazer por você, acesse <a href=”http://e-labworks.com/servicos/”> http://e-labworks.com/servicos</a>.</p>
<p>Este post foi originalmente publicado em <a href="http://sergioprado.org/device-drivers-e-gerenciamento-dinamico-de-dispositivos/">Device Drivers e gerenciamento dinâmico de dispositivos</a>.</p></p>
Posts relacionados:<ol>
<li><a href='http://sergioprado.org/linux-device-drivers-parte-1/' rel='bookmark' title='Linux Device Drivers — Parte 1'>Linux Device Drivers — Parte 1</a></li>
<li><a href='http://sergioprado.org/mini2440-compilando-aplicacoes-e-device-drivers/' rel='bookmark' title='Mini2440 — Compilando aplicações e device drivers'>Mini2440 — Compilando aplicações e device drivers</a></li>
<li><a href='http://sergioprado.org/linux-device-drivers-parte-2/' rel='bookmark' title='Linux Device Drivers — Parte 2'>Linux Device Drivers — Parte 2</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Conforme expliquei no meu <a href="http://www.sergioprado.org/2010/12/18/linux-device-drivers-parte-1/" target="_blank">primeiro artigo sobre device drivers</a>, tudo em Linux são arquivos. Expliquei também que todo acesso ao hardware é realizado através de arquivos no diretório <em>/dev</em>. Portanto, sempre que você precisar acessar determinado hardware, seu arquivo de dispositivo deve estar presente em <em>/dev</em>. Obs: em alguns casos bem específicos, o hardware pode ser acessado via <em>/proc</em> ou <em>/sys</em>.</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Nos primeiros anos de vida do Linux, a quantidade de dispositivos suportados era apenas uma pequena fração do que é hoje. Naquela época, para cada hardware suportado pelo sistema operacional, criava-se um arquivo estático em <em>/dev</em>.</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">À medida que o kernel foi evoluindo com a adição de novos drivers de dispositivo, a quantidade de arquivos criados em <em>/dev</em> começou a crescer exponencialmente, tornando difícil seu gerenciamento, e acabando aos poucos com a disponibilidade de <em>major e minor numbers</em> que podiam ser atribuídos à outros dispositivos. </span></span><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">No <em>RedHat 9</em>, por exemplo, existiam 19.000 arquivos de dispositivo em <em>/dev</em>!</span></p>
<p><meta content="text/html; charset=utf-8" http-equiv="content-type" /></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Além disso, sempre que você adicionasse um hardware não suportado nativamente pelo kernel, você precisaria adicionar um arquivo de dispositivo manualmente com o comando <em>mknod</em>. Foi o que fizemos no <a href="http://www.sergioprado.org/2011/01/07/linux-device-drivers-parte-2/" target="_blank">segundo artigo sobre device drivers</a>, para acessar os leds do kit FriendlyARM mini2440:</span></span></p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">mknod</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>led1 c <span style="color: #000000;">253</span> <span style="color: #000000;">0</span>
$ <span style="color: #c20cb9; font-weight: bold;">mknod</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>led2 c <span style="color: #000000;">253</span> <span style="color: #000000;">1</span>
$ <span style="color: #c20cb9; font-weight: bold;">mknod</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>led3 c <span style="color: #000000;">253</span> <span style="color: #000000;">2</span>
$ <span style="color: #c20cb9; font-weight: bold;">mknod</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>led4 c <span style="color: #000000;">253</span> <span style="color: #000000;">3</span></pre></div></div>



<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Em determinado momento, os desenvolvedores do kernel precisaram buscar uma solução que possibilitasse a criação dinâmica de arquivos de dispositivo. Então nasceu o <a href="http://en.wikipedia.org/wiki/Device_file#devfs" target="_blank"><em>devfs</em></a>.</span></span></p>
<p style="text-align: justify; "><strong><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">DEVFS</span></span></strong></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">O <em>devfs</em> é um sistema de arquivos virtual criado para representar dinamicamente todos os dispositivos conectados ao sistema. Isso significa que, no boot, bastaria você montar o <em>devfs</em> no <em>/dev</em>, conforme abaixo:</span></span></p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">mount</span> <span style="color: #660033;">-t</span> devfs none <span style="color: #000000; font-weight: bold;">/</span>dev</pre></div></div>



<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Para cada hardware adicionado ou removido, o kernel atualizaria este sistema de arquivos virtual, refletindo diretamente no diretório <em>/dev</em>. Pareceu uma solução boa, e resolveu o problema de ter uma lista enorme de arquivos criados em <em>/dev</em>. </span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Porém, toda sua implementação estava em <em>kernel space</em>. Isso significa que, se por exemplo inserirmos um dispositivo não suportado pelo kernel, ainda teríamos que usar o comando <em>mknod</em> para criá-lo manualmente. Além disso, o nome dos dispositivos eram estáticos e não poderiam ser mudados, além da implementação ter alguns bugs.</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Foi então que, para corrigir estas deficiências, criou-se a arquitetura de <em>hotplug</em> do kernel, e um tempo depois o <a href="http://en.wikipedia.org/wiki/Udev" target="_blank"><em>udev</em></a> foi implementado.</span></span></p>
<p style="text-align: justify; "><strong><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">HOTPLUG E UDEV</span></span></strong></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">A arquitetura de hotplug do kernel levou toda a implementação do <em>devfs</em> para userspace. A única responsabilidade do kernel nesta arquitetura é notificar o <em>userspace</em> quando um hardware é inserido, removido, etc. Esta implementação deu uma flexibilidade muito maior para o gerenciamento dos arquivos de dispositivo.</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Nesta arquitetura, o kernel pode trabalhar de duas formas:</span></span></p>
<ol>
	<li style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">O kernel notifica o <em>userspace</em> através da chamada à um processo definido em <em>/proc/sys/kernel/hotplug</em> (no começo usava-se o <em>/sbin/hotplug</em>).</span></span></li>
	<li style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">O kernel notifica o <em>userspace</em> através de um <a href="http://en.wikipedia.org/wiki/Netlink" target="_blank">socket do tipo netlink</a>. Qualquer processo que estiver “escutando” este socket irá receber as notificações (que também são chamadas de <em>uevents</em>).</span></span></li></ol>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Então surgiu a implementação do <em>udev</em> para se beneficiar destas facilidades do kernel. No começo, o udev usava o primeiro mecanismo, trocando o <em>/sbin/hotplug</em> pelo <em>/sbin/udevsend</em>. Depois, ele passou a usar o segundo mecanismo, através da implementação do processo <em>udevd</em> para escutar os eventos no <em>netlink socket</em>. Desde então, o uso do <em>udevd</em> é padrão na maioria das distribuições Linux atuais.</span></span></p>
<p style="text-align: center; "><img alt="udev3 Device Drivers e gerenciamento dinâmico de dispositivos" height="420" src="http://www.sergioprado.org/wp-content/uploads/udev3.png" width="550" title="Device Drivers e gerenciamento dinâmico de dispositivos" /></p>
<p style="text-align: center; "><span style="font-size:11px;"><span style="font-family:verdana,geneva,sans-serif;">fonte: </span><a href="http://free-electrons.com/" target="_blank">http://free-electrons.com/</a><br />
	</span></p>
<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">A notificação enviada em ambos os casos (processo ou socket) é idêntica. O evento gerado pelo kernel, ao invés de trazer todas as informações do dispositivo conectado, traz apenas um identificador do dispositivo. A partir deste identificador, o <em>udev</em> busca as informações necessárias no diretório <em>/sys</em>. Este diretório, que também é montado a partir de um sistema de arquivos virtual (<em>sysfs</em>), contém dados detalhados do hardware do sistema, e é de suma importância para a arquitetura de hotplug do kernel.</span></p>
<p><meta content="text/html; charset=utf-8" http-equiv="content-type" /></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Basicamente, o que acontece em um sistema com <em>udev</em> é o seguinte:</span></span></p>
<ol>
	<li style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">No boot, o kernel gera eventos para todos os dispositivos identificados no <em>/sys</em>, o <em>udevd</em> captura estes eventos e cria no <em>/dev</em> os arquivos de dispositivo para o hardware presente no sistema. Este procedimento é chamado de <em>coldplugging</em>.</span></span></li>
	<li style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Para cada novo evento, o kernel envia uma nova notificação, o <em>udev</em> captura esta notificação trata. Este procedimento é chamado de <em>hotplugging</em>.</span></span></li></ol>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Uma explicação mais detalhada sobre o mecanismo de hotplug pode ser encontrado <a href="http://www.kernel.org/doc/pending/hotplug.txt" target="_blank">aqui</a>.</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">O usuário poderá definir regras para o tratamento das notificações enviadas pelo kernel, e a grande vantagem desta arquitetura é a criação de regras persistentes. O udev resolve problemas do tipo: quando conectar este pendrive, quero que seja sempre atribuído a ele o arquivo de dispositivo <em>/dev/mypendrive</em>.</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Outro exemplo: imagine que você tenha duas impressoras, uma jato de tinta e outra à laser. A primeira impressora identificada pelo kernel será a <em>/dev/lp0</em>, e a segunda a <em>/dev/lp1</em>. Isso significa que o nome do arquivo associado à impressora vai depender da ordem de identificação do hardware pelo kernel. Isso pode causar um problema para as aplicações, já que não existe uma garantia de que a impressora à laser estará sempre em <em>/dev/lp0</em>, por exemplo. Mas podemos resolver este problema com a criação de uma regra no <em>udev</em>.</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">No udev, as regras são salvas em <em>/etc/udev/rules.d</em>, e para cada evento recebido, o <em>udev</em> procura uma regra que se encaixe. No exemplo abaixo, conseguimos garantir que a impressora à laser, que possui o número serial <em>“L72010011070626380”</em>, será sempre associada ao arquivo de dispositivo <em>/dev/printer/laser</em>:</span></span></p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #007800;">SUBSYSTEM</span>==<span style="color: #ff0000;">&quot;usb&quot;</span>, ATTRS<span style="color: #7a0874; font-weight: bold;">&#123;</span>serial<span style="color: #7a0874; font-weight: bold;">&#125;</span>==<span style="color: #ff0000;">&quot;L72010011070626380&quot;</span>, SYMLINK+=<span style="color: #ff0000;">&quot;printer/laser&quot;</span></pre></div></div>



<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Um artigo bem completo sobre como criar regras no udev pode ser <a href="http://www.linuxformat.co.uk/includes/download.php?PDF=LXF66.tut_udev.pdf" target="_blank">lido aqui</a>. Além da criação de arquivos de dispositivo, o <em>udev</em> também é capaz de carregar drivers ou baixar um firmware no hardware conectado.</span></span></p>
<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">A implementação do </span><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; "><em>udev</em></span><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; "> é bem compacta (no meu desktop com Ubuntu ela tem apenas 100K), mas para sistemas embarcados com recursos bem escassos, podemos recorrer implementações mais enxutas como o </span><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; "><em>mdev</em></span><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; "> do nosso bom e velho amigo </span><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; "><a href="http://www.busybox.net/" target="_blank"><em>Busybox</em></a></span><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">.</span></p>
<p style="text-align: justify; "><strong><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">MDEV</span></span></strong></p>
<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">O <em>mdev</em> é uma implementação do <em>udev</em> dentro do <em>Busybox</em>. </span></p>
<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Vamos ver então um exemplo prático de como usar o <em>mdev</em> para criar dinamicamente os arquivos de dispositivo do device driver que desenvolvemos para <a href="http://www.sergioprado.org/2011/01/07/linux-device-drivers-parte-2" target="_blank">controlar os leds do kit FriendlyARM mini2240</a>.</span></p>
<p><meta content="text/html; charset=utf-8" http-equiv="content-type" /></p>
<p style="text-align: justify; "><meta content="text/html; charset=utf-8" http-equiv="content-type" /></p>
<p style="text-align: justify; "><strong><font class="Apple-style-span" face="verdana, geneva, sans-serif"><span class="Apple-style-span" style="font-size: 14px;">PREPARADO O KERNEL</span></font></strong></p>
<p style="text-align: justify; "><meta content="text/html; charset=utf-8" http-equiv="content-type" /></p>
<p style="text-align: justify; "><span style="font-size: 14px; "><span style="font-family: verdana, geneva, sans-serif; ">O kernel precisa ser compilado com a opção <em>CONFIG_HOTPLUG</em> habilitada. Para verificar se seu kernel foi compilada com esta opção habilitada, veja se o arquivo <em>/proc/sys/kernel/hotplug</em> existe. Se não existir, você precisará habilitá-lo e recompilar o kernel.</span></span></p>
<p style="text-align: justify; "><strong><span style="font-size: 14px; "><span style="font-family: verdana, geneva, sans-serif; ">PREPARANDO O BUSYBOX</span></span><br />
	</strong></p>
<p style="text-align: justify; "><span style="font-size: 14px; "><span style="font-family: verdana, geneva, sans-serif; ">O <em>Busybox</em> precisa estar configurado para gerar o <em>mdev</em>. Esta opção vem habilitada no <em>config</em> padrão do Busybox, mas se não estiver, você precisará habilitá-la com as opções abaixo:</span></span></p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">Linux System Utilities
    <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000; font-weight: bold;">*</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> mdev
    <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000; font-weight: bold;">*</span><span style="color: #7a0874; font-weight: bold;">&#93;</span>   Support <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>mdev.conf</pre></div></div>



<p style="text-align: justify; "><strong><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">COMANDOS NO BOOT</span></strong></p>
<p style="text-align: justify; "><font class="Apple-style-span" face="verdana, geneva, sans-serif"><span class="Apple-style-span" style="font-size: 14px;">Altere uns dos scripts de inicialização e insira os dois comandos abaixo:</span></font></p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #000000; font-weight: bold;">/</span>sbin<span style="color: #000000; font-weight: bold;">/</span>mdev <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>proc<span style="color: #000000; font-weight: bold;">/</span>sys<span style="color: #000000; font-weight: bold;">/</span>kernel<span style="color: #000000; font-weight: bold;">/</span>hotplug
$ mdev <span style="color: #660033;">-s</span></pre></div></div>



<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">O primeiro comando serve para configurar o processo que irá receber os eventos do kernel. O segundo comando serve para inicializar o <em>/dev</em> no boot com os dispositivos listados no <em>/sys</em>.</span></p>
<p style="text-align: justify; "><span style="font-size: 14px; "><span style="font-family: verdana, geneva, sans-serif; ">Obs: Antes de executar estes comandos, certifique-se de que os diretórios <em>/proc</em>, <em>/sys</em> e <em>/dev</em> estejam montados e disponíveis.</span></span></p>
<p style="text-align: justify; "><meta content="text/html; charset=utf-8" http-equiv="content-type" /></p>
<p style="text-align: justify; "><strong><span style="font-size: 14px; "><span style="font-family: verdana, geneva, sans-serif; ">ALTERANDO O DEVICE DRIVER</span></span></strong></p>
<p style="text-align: justify; "><span style="font-size: 14px; "><span style="font-family: verdana, geneva, sans-serif; ">Para quem não acompanhou, desenvolvemos um device driver para controlar os leds do kit FriendlyARM mini2440 <a href="http://www.sergioprado.org/2011/01/07/linux-device-drivers-parte-2/" target="_blank">neste artigo aqui</a>. Agora, iremos alterá-lo para criar as entradas necessárias no <em>/sys</em> e enviar eventos ao <em>udev </em>(no nosso caso <em>mdev</em>), para que este gere automaticamente os arquivos de dispositivo em <em>/dev</em>.</span></span></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">/* class for the sysfs entry */</span>
<span style="color: #993333;">struct</span> class <span style="color: #339933;">*</span>leds_class<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* driver initialization */</span>
<span style="color: #993333;">int</span> __init leds_init<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> ret<span style="color: #339933;">,</span> i<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/* request device major number */</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>ret <span style="color: #339933;">=</span> alloc_chrdev_region<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>leds_dev_number<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">,</span> NUM_LEDS<span style="color: #339933;">,</span> DEVICE_NAME<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        printk<span style="color: #009900;">&#40;</span>KERN_DEBUG <span style="color: #ff0000;">&quot;Error registering device!<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">return</span> ret<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/* create /sys entry */</span>
    leds_class <span style="color: #339933;">=</span> class_create<span style="color: #009900;">&#40;</span>THIS_MODULE<span style="color: #339933;">,</span> DEVICE_NAME<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/* init leds GPIO port */</span>
    initLedPort<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/* init each led device */</span>
    <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> NUM_LEDS<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;">/* init led status */</span>
        leds_dev<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">number</span> <span style="color: #339933;">=</span> i <span style="color: #339933;">+</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
        leds_dev<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">status</span> <span style="color: #339933;">=</span> LED_OFF<span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;">/* connect file operations to this device */</span>
        cdev_init<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>leds_dev<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">cdev</span><span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>leds_fops<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        leds_dev<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">cdev</span>.<span style="color: #202020;">owner</span> <span style="color: #339933;">=</span> THIS_MODULE<span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;">/* connect major/minor numbers */</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>ret <span style="color: #339933;">=</span> cdev_add<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>leds_dev<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">cdev</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span>leds_dev_number <span style="color: #339933;">+</span> i<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            printk<span style="color: #009900;">&#40;</span>KERN_DEBUG <span style="color: #ff0000;">&quot;Error adding device!<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">return</span> ret<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;">/* init led status */</span>
        changeLedStatus<span style="color: #009900;">&#40;</span>leds_dev<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">number</span><span style="color: #339933;">,</span> LED_OFF<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;">/* send uevent to udev to create /dev node */</span>
        device_create<span style="color: #009900;">&#40;</span>leds_class<span style="color: #339933;">,</span> NULL<span style="color: #339933;">,</span> MKDEV<span style="color: #009900;">&#40;</span>MAJOR<span style="color: #009900;">&#40;</span>leds_dev_number<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> i<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> NULL<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;leds%d&quot;</span><span style="color: #339933;">,</span> i<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    printk<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Leds driver initialized.<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* driver exit */</span>
<span style="color: #993333;">void</span> __exit leds_exit<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> i<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/* release major number */</span>
    unregister_chrdev_region<span style="color: #009900;">&#40;</span>leds_dev_number<span style="color: #339933;">,</span> NUM_LEDS<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/* delete devices */</span>
    <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> NUM_LEDS<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        device_destroy<span style="color: #009900;">&#40;</span>leds_class<span style="color: #339933;">,</span> MKDEV<span style="color: #009900;">&#40;</span>MAJOR<span style="color: #009900;">&#40;</span>leds_dev_number<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> i<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        cdev_del<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>leds_dev<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">cdev</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/* destroy class */</span>
    class_destroy<span style="color: #009900;">&#40;</span>leds_class<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    printk<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Exiting leds driver.<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>



<p style="text-align: justify; "><span style="font-size: 14px; "><span style="font-family: verdana, geneva, sans-serif; ">Na linha 2 declaramos o ponteiro que irá armazenar a estrutura com as informações do dispositivo no <em>/sys</em>. Na linha 16, com a função <em>class_create()</em>, criamos esta estrutura. Esta chamada criará a entrada <em>/sys/class/leds</em>. </span></span></p>
<p style="text-align: justify; "><span style="font-size: 14px; "><span style="font-family: verdana, geneva, sans-serif; ">Na linha 42, a função <em>device_create()</em> é chamada para cada led. É na chamada desta função que o kernel irá enviar uma notificação de evento para o <em>mdev</em>. Ao receber este evento, o <em>mdev</em> irá automaticamente criar um arquivo de dispositivo no <em>/dev</em>.</span></span></p>
<p style="text-align: justify; "><meta content="text/html; charset=utf-8" http-equiv="content-type" /></p>
<p style="text-align: justify; "><span style="font-size: 14px; "><span style="font-family: verdana, geneva, sans-serif; ">Ao inserir o módulo, serão criadas automaticamente as seguintes entradas:</span></span></p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">ls</span> <span style="color: #660033;">-la</span> <span style="color: #000000; font-weight: bold;">/</span>sys<span style="color: #000000; font-weight: bold;">/</span>class<span style="color: #000000; font-weight: bold;">/</span>leds<span style="color: #000000; font-weight: bold;">/</span>
total <span style="color: #000000;">0</span>
drwxr-xr-x    <span style="color: #000000;">6</span> root     root             <span style="color: #000000;">0</span> Oct <span style="color: #000000;">29</span> <span style="color: #000000;">17</span>:<span style="color: #000000;">46</span> .
drwxr-xr-x   <span style="color: #000000;">29</span> root     root             <span style="color: #000000;">0</span> Oct <span style="color: #000000;">29</span> <span style="color: #000000;">17</span>:<span style="color: #000000;">46</span> ..
drwxr-xr-x    <span style="color: #000000;">2</span> root     root             <span style="color: #000000;">0</span> Oct <span style="color: #000000;">29</span> <span style="color: #000000;">17</span>:<span style="color: #000000;">46</span> leds0
drwxr-xr-x    <span style="color: #000000;">2</span> root     root             <span style="color: #000000;">0</span> Oct <span style="color: #000000;">29</span> <span style="color: #000000;">17</span>:<span style="color: #000000;">46</span> leds1
drwxr-xr-x    <span style="color: #000000;">2</span> root     root             <span style="color: #000000;">0</span> Oct <span style="color: #000000;">29</span> <span style="color: #000000;">17</span>:<span style="color: #000000;">46</span> leds2
drwxr-xr-x    <span style="color: #000000;">2</span> root     root             <span style="color: #000000;">0</span> Oct <span style="color: #000000;">29</span> <span style="color: #000000;">17</span>:<span style="color: #000000;">46</span> leds3
$ <span style="color: #c20cb9; font-weight: bold;">ls</span> <span style="color: #660033;">-la</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>leds<span style="color: #000000; font-weight: bold;">*</span>
crw-rw----    <span style="color: #000000;">1</span> root     root      <span style="color: #000000;">251</span>,   <span style="color: #000000;">0</span> Jan <span style="color: #000000;">21</span>  <span style="color: #000000;">2011</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>leds0
crw-rw----    <span style="color: #000000;">1</span> root     root      <span style="color: #000000;">251</span>,   <span style="color: #000000;">1</span> Jan <span style="color: #000000;">21</span>  <span style="color: #000000;">2011</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>leds1
crw-rw----    <span style="color: #000000;">1</span> root     root      <span style="color: #000000;">251</span>,   <span style="color: #000000;">2</span> Jan <span style="color: #000000;">21</span>  <span style="color: #000000;">2011</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>leds2
crw-rw----    <span style="color: #000000;">1</span> root     root      <span style="color: #000000;">251</span>,   <span style="color: #000000;">3</span> Jan <span style="color: #000000;">21</span>  <span style="color: #000000;">2011</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>leds3</pre></div></div>



<p style="text-align: justify; "><span style="font-size: 14px; "><span style="font-family: verdana, geneva, sans-serif; ">Da mesma forma, ao remover o modulo, a função <em>leds_exit()</em> será executada, e a chamada à <em>device_destroy()</em> na linha 60 fará com que o kernel envie uma mensagem para o <em>mdev</em> remover os arquivos de dispositivo previamente criados.</span></span></p>
<p style="text-align: justify; "><span style="font-size: 14px; "><span style="font-family: verdana, geneva, sans-serif; ">Vejam que, com poucas linhas de código, conseguimos tornar dinâmico o gerenciamento de arquivos de dispositivo do nosso device driver. O código-fonte completo do device driver pode ser <a href="http://www.sergioprado.org/wp-content/plugins/download-monitor/download.php?id=7" target="_blank">baixado aqui</a>. </span></span></p>
<p style="text-align: justify; "><span style="font-size: 14px; "><span style="font-family: verdana, geneva, sans-serif; ">No próximo artigo iremos aprender sobre mais algumas funções da API kernel, usar timers e transformar os leds em pisca-piscas. Até lá!</span></span></p>
<p style="text-align: justify; "><span style="font-size: 14px; "><span style="font-family: verdana, geneva, sans-serif; ">Um abraço,</span></span></p>
<p style="text-align: justify; "><span style="font-size: 14px; "><span style="font-family: verdana, geneva, sans-serif; ">Sergio Prado</span></span></p><div class="shr-publisher-1327"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic --><p>Posts relacionados:</p><ol>
<li><a href='http://sergioprado.org/linux-device-drivers-parte-1/' rel='bookmark' title='Linux Device Drivers — Parte 1'>Linux Device Drivers — Parte 1</a></li>
<li><a href='http://sergioprado.org/mini2440-compilando-aplicacoes-e-device-drivers/' rel='bookmark' title='Mini2440 — Compilando aplicações e device drivers'>Mini2440 — Compilando aplicações e device drivers</a></li>
<li><a href='http://sergioprado.org/linux-device-drivers-parte-2/' rel='bookmark' title='Linux Device Drivers — Parte 2'>Linux Device Drivers — Parte 2</a></li>
</ol><p><p>Sergio Prado atua com desenvolvimento de software para sistemas embarcados há mais de 15 anos. É sócio-fundador da Embed­ded Lab­works, uma empresa focada em te aju­dar a desen­volver soft­ware de qual­i­dade para sis­temas embar­ca­dos. Se você pre­cisa de ajuda para desen­volver seu pro­duto, ou quer saber mais sobre o que a Embed­ded Lab­works pode fazer por você, acesse <a href=”http://e-labworks.com/servicos/”> http://e-labworks.com/servicos</a>.</p>
<p>Este post foi originalmente publicado em <a href="http://sergioprado.org/device-drivers-e-gerenciamento-dinamico-de-dispositivos/">Device Drivers e gerenciamento dinâmico de dispositivos</a>.</p></p>]]></content:encoded>
			<wfw:commentRss>http://sergioprado.org/device-drivers-e-gerenciamento-dinamico-de-dispositivos/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Linguagem C: História e Padrões</title>
		<link>http://sergioprado.org/linguagem-c-historia-e-padroes/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=linguagem-c-historia-e-padroes</link>
		<comments>http://sergioprado.org/linguagem-c-historia-e-padroes/#comments</comments>
		<pubDate>Sat, 15 Jan 2011 00:09:07 +0000</pubDate>
		<dc:creator>Sergio Prado</dc:creator>
				<category><![CDATA[Linguagem C]]></category>
		<category><![CDATA[ANSI C]]></category>
		<category><![CDATA[C1X]]></category>
		<category><![CDATA[C89]]></category>
		<category><![CDATA[C99]]></category>

		<guid isPermaLink="false">http://www.sergioprado.org/?p=1312</guid>
		<description><![CDATA[<p>Um pouco da história da linguagem C e da evolução de seus padrões.</p><p><p>Sergio Prado atua com desenvolvimento de software para sistemas embarcados há mais de 15 anos. É sócio-fundador da Embed­ded Lab­works, uma empresa focada em te aju­dar a desen­volver soft­ware de qual­i­dade para sis­temas embar­ca­dos. Se você pre­cisa de ajuda para desen­volver seu pro­duto, ou quer saber mais sobre o que a Embed­ded Lab­works pode fazer por você, acesse <a href=”http://e-labworks.com/servicos/”> http://e-labworks.com/servicos</a>.</p>
<p>Este post foi originalmente publicado em <a href="http://sergioprado.org/linguagem-c-historia-e-padroes/">Linguagem C: História e Padrões</a>.</p></p>
Posts relacionados:<ol>
<li><a href='http://sergioprado.org/otimizacao-de-codigo-em-linguagem-c-parte-2/' rel='bookmark' title='Otimização de código em Linguagem C — Parte 2'>Otimização de código em Linguagem C — Parte 2</a></li>
<li><a href='http://sergioprado.org/memory-leak-em-linguagem-c/' rel='bookmark' title='Memory leak em linguagem C'>Memory leak em linguagem C</a></li>
<li><a href='http://sergioprado.org/tratamento-de-erros-em-linguagem-c/' rel='bookmark' title='Tratamento de erros em Linguagem C'>Tratamento de erros em Linguagem C</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Em qualquer livro de programação, normalmente as primeiras páginas são voltadas à história da linguagem (e são também as páginas que não lemos ou damos uma “passada bem rápida”). Mas conhecer a origem da linguagem pode nos ajudar a entender um pouco suas características.</span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">C é uma linguagem desenvolvida por engenheiros e para engenheiros. Foi criada em 1972 por <a href="http://en.wikipedia.org/wiki/Dennis_Ritchie" target="_blank">Dennis Ritchie</a> para ser usada no desenvolvimento sistema operacional <a href="http://en.wikipedia.org/wiki/Unix" target="_blank">Unix</a> no <a href="http://en.wikipedia.org/wiki/Bell_Telephone_Laboratories" target="_blank">Bell Labs</a>, que na época pertencia à AT&amp;T (hoje parte da Alcatel-Lucent). C foi derivada da linguagem B, desenvolvida por <a href="http://en.wikipedia.org/wiki/Ken_Thompson_(computer_programmer)" target="_blank">Ken Thompson</a>, que por sua vez se baseou-se na linguagem <a href="http://en.wikipedia.org/wiki/BCPL" target="_blank">BCPL</a>.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Ritchie e Thompson também participaram da equipe de desenvolvimento do UNIX, cujas primeiras versões foram totalmente desenvolvidas em Assembly. Em um certo momento, eles sentiram a necessidade de uma linguagem mais portável para implementar o Unix no <a href="http://en.wikipedia.org/wiki/PDP-11" target="_blank">PDP-11</a>.</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Esta linguagem precisava</span></span><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; "> prover acesso de baixo nível ao hardware (PCU, I/Os e periféricos) e se entender bem com o Assembly, precisava ser portável para que o SO pudesse rodar em diferentes plataformas de hardware, além de ter um bom desempenho e otimizar o uso de memória, principalmente numa época em que estavam começando a surgir as primeiras CPUs, e o preço por byte de memória era caríssimo. Foi portanto destas necessidades que surgiu a linguagem C.</span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Deste então, 99,99999% das arquiteturas de CPU possuem a implementação de um compilador C. De mainframes, supercomputadores e minicomputadores, a celulares, relógios e torradeiras. É difícil encontrar uma plataforma de hardware sem um compilador C compatível.<br />
	</span></span></p>
<p style="text-align: justify; "><strong><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">O PRIMEIRO PADRÃO<br />
	</span></span></strong></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">O livro “<a href="http://en.wikipedia.org/wiki/The_C_Programming_Language_(book)" target="_blank">The C Programming Language</a>”, publicado em 1978 por Brian Kernighan e Dennis Ritchie, foi considerado o padrão de facto da linguagem C durante muitos anos, até sair o padrão <em>ANSI C</em>. Este padrão informal também ficou conhecido como “<em>K&amp;R C</em>”.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">É provavelmente o livro de C que mais se vendeu até hoje, por vários motivos. Dentre eles, foi o primeiro livro de C disponível de forma mais abrangente, um dos autores do livro é o próprio criador da linguagem, é escrito de forma clara e possui poucas páginas, comparado à outras “bíblias” que vemos por aí. Todo desenvolvedor C deveria ter sua cópia.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">A <a href="http://www.amazon.com/gp/product/0131103628?ie=UTF8&amp;tag=blodoserpra-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0131103628" target="_blank">segunda edição do livro</a> foi lançada em 1988 e atualizada para ficar de acordo com o padrão ANSI C.<br />
	</span></span></p>
<p style="text-align: justify; "><strong><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">OS PADRÕES ANSI C E ISO C<br />
	</span></span></strong></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Durante a década de 80 “choveram” implementações de compiladores C, já que naquela época a semântica da linguagem estava aberta à interpretações. Surgiu então a necessidade de um padrão formal da linguagem.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Este padrão foi desenvolvido pelo <a href="http://en.wikipedia.org/wiki/American_National_Standards_Institute" target="_blank">ANSI (American National Standards Institute)</a>, que formou um comitê e ratificou o padrão em 1989 como ANSI X3.159‑1989 “Programming Language C”, também conhecido com <a href="http://en.wikipedia.org/wiki/ANSI_C" target="_blank"><em>ANSI C</em> ou <em>C89</em></a>.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Um ano depois o padrão foi adotado pela <a href="http://en.wikipedia.org/wiki/International_Organization_for_Standardization" target="_blank">ISO (International Organization for Standardization)</a> como ISO/IEC 9899:1990, também chamado de <em>C90</em>. Na prática, <em>C89</em> (<em>ANSI C</em>) e <em>C90</em> (<em>ISO C</em>) referem-se ao mesmo padrão.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">A partir de 1990, a ISO ficou responsável pela evolução do padrão. O endereço oficial do grupo é <a href="http://www.open-std.org/jtc1/sc22/wg14/" target="_blank">este aqui</a>, e um draft do padrão pode ser <a href="http://flash-gordon.me.uk/ansi.c.txt" target="_blank">visto aqui</a>.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">O que eles fizeram foi acrescentar algumas novas características ao padrão anterior <em>K&amp;R C</em>.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">As principais mudanças foram a inclusão de protótipos de função, a padronização das bibliotecas e a adição de algumas palavras-chave como <em>enum</em>, <em>const</em>, <em>volatile</em>, <em>signed</em>, <em>void</em> (isso mesmo, estas palavras-chave não existiam formalmente antes do padrão <em>ANSI C</em>).<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">A maioria do código compilado em <em>K&amp;R C</em>, compila em <em>ANSI C</em>, com algumas exceções. Para tratar estas exceções, foi criado o <em>#define __STDC__</em>, que deveria ser implementado por padrão em todos os compiladores <em>ANSI C</em>. Veja no exemplo abaixo o protótipo da função <em>soma()</em> nos padrões <em>ANSI C</em> e <em>K&amp;R C</em>.</span></span></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#if __STDC__</span>
<span style="color: #000000; font-weight: bold;">extern</span> <span style="color: #993333;">int</span> soma<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> a<span style="color: #339933;">,</span> <span style="color: #993333;">int</span> b<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #339933;">#else</span>
<span style="color: #000000; font-weight: bold;">extern</span> <span style="color: #993333;">int</span> soma<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #339933;">#endif</span></pre></td></tr></table></div>



<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Todos os compiladores modernos suportam <em>ANSI C.</em> E ter um programa compatível com <em>ANSI C</em> significa que este será provavelmente portável para qualquer arquitetura de hardware que possua um compilador <em>ANSI C</em> disponível.</span></p>
<p style="text-align: justify; "><strong><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">O PADRÃO C99<br />
	</span></span></strong></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Na década de 90 a ISO corrigiu alguns detalhes e publicou em 1999 o ISO/IEC 9899:1999, que ficou conhecido como <em>C99</em>. Um draft do padrão <a href="http://www.open-std.org/jtc1/sc22/wg14/www/docs/n869/n869.txt.gz" target="_blank">pode ser visto aqui</a>.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Dentre as alterações, podemos destacar a inclusão de funções <em>inline</em>, variáveis “<em>long long</em>”, suporte para comentários de uma linha, além de não assumir <em>int</em> quando não é especificado o retorno da função.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Por exemplo, o código abaixo esta de acordo com o padrão <em>C89</em>, mas não compila de acordo com o padrão <em>C99</em>:</span></span></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#include &quot;stdio.h&quot;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* Retorna indice do maior elemento do array */</span>
maior<span style="color: #009900;">&#40;</span><span style="color: #993333;">long</span> buf<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #993333;">int</span> qtd<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">long</span> m <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> i<span style="color: #339933;">,</span> ind <span style="color: #339933;">=</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> qtd<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>buf<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span> <span style="color: #339933;">&gt;</span> m<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            m <span style="color: #339933;">=</span> buf<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
            ind <span style="color: #339933;">=</span> i<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">return</span><span style="color: #009900;">&#40;</span>ind<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
main<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> m <span style="color: #339933;">=</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #993333;">long</span> buf<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span> <span style="color: #0000dd;">1234</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">3456</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">7345</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">5897</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>m <span style="color: #339933;">=</span> maior<span style="color: #009900;">&#40;</span>buf<span style="color: #339933;">,</span> <span style="color: #0000dd;">4</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;=</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>
        <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Maior elemento buf[%d]=%ld<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> m<span style="color: #339933;">,</span> buf<span style="color: #009900;">&#91;</span>m<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">else</span>
        <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Maior elemento nao encontrado<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> buf<span style="color: #009900;">&#91;</span>m<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>



<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Para compilar de acordo com o padrão <em>C99</em>, algumas linhas precisam ser alteradas:</span></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#include &quot;stdio.h&quot;</span>
&nbsp;
<span style="color: #993333;">int</span> maior<span style="color: #009900;">&#40;</span><span style="color: #993333;">long</span> <span style="color: #993333;">long</span> buf<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #993333;">int</span> qtd<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Retorna indice do maior elemento do array</span>
<span style="color: #000000; font-weight: bold;">inline</span> <span style="color: #993333;">int</span> maior<span style="color: #009900;">&#40;</span><span style="color: #993333;">long</span> <span style="color: #993333;">long</span> buf<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #993333;">int</span> qtd<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">long</span> <span style="color: #993333;">long</span> m <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> i<span style="color: #339933;">,</span> ind <span style="color: #339933;">=</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> qtd<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>buf<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span> <span style="color: #339933;">&gt;</span> m<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            m <span style="color: #339933;">=</span> buf<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
            ind <span style="color: #339933;">=</span> i<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">return</span><span style="color: #009900;">&#40;</span>ind<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> m <span style="color: #339933;">=</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #993333;">long</span> <span style="color: #993333;">long</span> buf<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span> <span style="color: #0000dd;">1234</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">3456</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">7345</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">5897</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>m <span style="color: #339933;">=</span> maior<span style="color: #009900;">&#40;</span>buf<span style="color: #339933;">,</span> <span style="color: #0000dd;">4</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;=</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>
        <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Maior elemento buf[%d]=%lld<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> m<span style="color: #339933;">,</span> buf<span style="color: #009900;">&#91;</span>m<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">else</span>
        <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Maior elemento nao encontrado<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> buf<span style="color: #009900;">&#91;</span>m<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>



<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Para compilar, foi necessário alterar os retornos de função, declarando explicitamente “<em>int</em>”. </span></p>
<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Além disso, fizemos algumas alterações permitidas no padrão <em>C99</em>. Alteramos todas as variáveis “<em>long</em>” para “<em>long long</em>”, usamos comentários de uma linha com “//” e declaramos a função <em>maior()</em> como “<em>inline</em>”. </span></p>
<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Com estas alterações o código ficou compatível com o padrão <em>C99</em>, mas perdeu a compatibilidade como padrão <em>ANSI C</em> (<em>C89</em>).</span></p>
<p style="text-align: justify; "><strong><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">O FUTURO PADRÃO C1X<br />
	</span></span></strong></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;"><em>C1X</em> é um nome não-oficial para um trabalho que começou em 2007, com o objetivo de revisar e definir um novo padrão para a linguagem C. Algumas das alterações propostas podem ser encontradas no <a href="http://en.wikipedia.org/wiki/C1X" target="_blank">site da Wikipedia</a>.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Algumas adições me pareceram bem interessantes: uso das palavras-chave _Generic para declarar uma função que pode receber diferentes tipos de dados e _Atomic para definir que o acesso à determinada variável deve ser atômico; a substituição da função gets() pela gets_s(), cuja implementação é bem mais segura; implementação de estruturas e unions anônimas; etc.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Claro que o padrão atual (<em>C99</em>) é bem maduro, e você deveria usá-lo em todos os seus projetos. O novo padrão pretende adicionar novas funcionalidades para melhorar a vida do desenvolvedor. Eu particularmente gostaria de ver um mecanismo de tratamento de erros ao estilo <em>try-catch-throw</em> do C++. De qualquer forma, deve levar ainda um tempo para o padrão sair, e mais um tempo para os compiladores implementarem.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Nenhum dos documentos oficiais dos padrões esta disponível gratuitamente na internet para download. Mas podemos baixar versões iniciais da especificação, ATAs de reunião e adendos. <a href="http://clc-wiki.net/wiki/The_C_Standard" target="_blank">Esta wiki</a> tem algumas informações interessantes com links para documentos relacionados aos padrões.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Um abraço,<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Sergio Prado</span></span></p><div class="shr-publisher-1312"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic --><p>Posts relacionados:</p><ol>
<li><a href='http://sergioprado.org/otimizacao-de-codigo-em-linguagem-c-parte-2/' rel='bookmark' title='Otimização de código em Linguagem C — Parte 2'>Otimização de código em Linguagem C — Parte 2</a></li>
<li><a href='http://sergioprado.org/memory-leak-em-linguagem-c/' rel='bookmark' title='Memory leak em linguagem C'>Memory leak em linguagem C</a></li>
<li><a href='http://sergioprado.org/tratamento-de-erros-em-linguagem-c/' rel='bookmark' title='Tratamento de erros em Linguagem C'>Tratamento de erros em Linguagem C</a></li>
</ol><p><p>Sergio Prado atua com desenvolvimento de software para sistemas embarcados há mais de 15 anos. É sócio-fundador da Embed­ded Lab­works, uma empresa focada em te aju­dar a desen­volver soft­ware de qual­i­dade para sis­temas embar­ca­dos. Se você pre­cisa de ajuda para desen­volver seu pro­duto, ou quer saber mais sobre o que a Embed­ded Lab­works pode fazer por você, acesse <a href=”http://e-labworks.com/servicos/”> http://e-labworks.com/servicos</a>.</p>
<p>Este post foi originalmente publicado em <a href="http://sergioprado.org/linguagem-c-historia-e-padroes/">Linguagem C: História e Padrões</a>.</p></p>]]></content:encoded>
			<wfw:commentRss>http://sergioprado.org/linguagem-c-historia-e-padroes/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Linux Device Drivers — Parte 2</title>
		<link>http://sergioprado.org/linux-device-drivers-parte-2/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=linux-device-drivers-parte-2</link>
		<comments>http://sergioprado.org/linux-device-drivers-parte-2/#comments</comments>
		<pubDate>Fri, 07 Jan 2011 22:00:44 +0000</pubDate>
		<dc:creator>Sergio Prado</dc:creator>
				<category><![CDATA[Linguagem C]]></category>
		<category><![CDATA[Linux embarcado]]></category>
		<category><![CDATA[Mini2440]]></category>
		<category><![CDATA[device driver]]></category>
		<category><![CDATA[embedded linux]]></category>

		<guid isPermaLink="false">http://www.sergioprado.org/?p=1259</guid>
		<description><![CDATA[<p>Neste artigo iremos desenvolver um driver de dispositivo em Linux para controlar o leds conectados à porta GPB do kit FriendlyARM mini2440.</p><p><p>Sergio Prado atua com desenvolvimento de software para sistemas embarcados há mais de 15 anos. É sócio-fundador da Embed­ded Lab­works, uma empresa focada em te aju­dar a desen­volver soft­ware de qual­i­dade para sis­temas embar­ca­dos. Se você pre­cisa de ajuda para desen­volver seu pro­duto, ou quer saber mais sobre o que a Embed­ded Lab­works pode fazer por você, acesse <a href=”http://e-labworks.com/servicos/”> http://e-labworks.com/servicos</a>.</p>
<p>Este post foi originalmente publicado em <a href="http://sergioprado.org/linux-device-drivers-parte-2/">Linux Device Drivers — Parte 2</a>.</p></p>
Posts relacionados:<ol>
<li><a href='http://sergioprado.org/mini2440-compilando-aplicacoes-e-device-drivers/' rel='bookmark' title='Mini2440 — Compilando aplicações e device drivers'>Mini2440 — Compilando aplicações e device drivers</a></li>
<li><a href='http://sergioprado.org/linux-device-drivers-parte-1/' rel='bookmark' title='Linux Device Drivers — Parte 1'>Linux Device Drivers — Parte 1</a></li>
<li><a href='http://sergioprado.org/mini2440-linux-com-u-boot-e-emdebian/' rel='bookmark' title='Mini2440 — Linux com U-Boot e Emdebian'>Mini2440 — Linux com U-Boot e Emdebian</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Na <a href="http://www.sergioprado.org/2010/12/18/linux-device-drivers-parte-1/" target="_blank">parte 1</a> desta série de artigos, dei uma introdução sobre o desenvolvimento de drivers de dispositivos em Linux. Vimos detalhes de um sistema com Linux embarcado, a arquitetura do kernel e como as aplicações se comunicam com o hardware.</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Neste artigo vamos finalmente colocar a mão na massa e codificar um driver de dispositivo de caractere (<em>char driver</em>). Desenvolveremos o “Hello world!” do software embarcado: acenderemos leds!</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Usaremos o <a href="http://www.sergioprado.org/2010/08/08/kit-de-desenvolvimento-friendlyarm-mini2440/" target="_blank">kit mini2440</a>, que possui 4 leds disponibilizados nas portas de I/O GPB5 à GPB8. Criaremos 4 arquivos de dispositivo (<em>/dev/led1</em>, <em>/dev/led2</em>, <em>/dev/led3</em>, <em>/dev/led4</em>) para gerenciar o status destes leds. Enviar “<em>1</em>″ para “<em>/dev/led1</em>″ irá acender o led 1, e enviar “<em>0</em>″ irá apagá-lo.</span></span></p>
<p style="text-align: justify; "><strong><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">ESQUELETO DE UM DEVICE DRIVER</span></span></strong></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Muito bem, chega de teorias e bla bla bla. Este é o esqueleto de um device driver:</span></span></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#include &quot;linux/fs.h&quot;</span>
<span style="color: #339933;">#include &quot;linux/cdev.h&quot;</span>
<span style="color: #339933;">#include &quot;linux/module.h&quot;</span>
<span style="color: #339933;">#include &quot;linux/kernel.h&quot;</span>
<span style="color: #339933;">#include &quot;linux/device.h&quot;</span>
<span style="color: #339933;">#include &quot;asm/uaccess.h&quot;</span>
<span style="color: #339933;">#include &quot;asm/io.h&quot;</span>
<span style="color: #339933;">#include &quot;linux/slab.h&quot;</span>
&nbsp;
<span style="color: #339933;">#define DEVICE_NAME     &quot;leds&quot;</span>
&nbsp;
<span style="color: #339933;">#define NUM_LEDS        4</span>
&nbsp;
<span style="color: #339933;">#define LED_ON          1</span>
<span style="color: #339933;">#define LED_OFF         0</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* per led structure */</span>
<span style="color: #993333;">struct</span> leds_device <span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> number<span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> status<span style="color: #339933;">;</span>
    <span style="color: #993333;">struct</span> cdev cdev<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span> leds_dev<span style="color: #009900;">&#91;</span>NUM_LEDS<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* file operations structure */</span>
<span style="color: #993333;">static</span> <span style="color: #993333;">struct</span> file_operations leds_fops <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
    .<span style="color: #202020;">owner</span>      <span style="color: #339933;">=</span> THIS_MODULE<span style="color: #339933;">,</span>
    .<span style="color: #202020;">open</span>       <span style="color: #339933;">=</span> leds_open<span style="color: #339933;">,</span>
    .<span style="color: #202020;">release</span>    <span style="color: #339933;">=</span> leds_release<span style="color: #339933;">,</span>
    .<span style="color: #202020;">read</span>       <span style="color: #339933;">=</span> leds_read<span style="color: #339933;">,</span>
    .<span style="color: #202020;">write</span>      <span style="color: #339933;">=</span> leds_write<span style="color: #339933;">,</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* leds driver major number */</span>
<span style="color: #993333;">static</span> dev_t leds_dev_number<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* driver initialization */</span>
<span style="color: #993333;">int</span> __init leds_init<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> ret<span style="color: #339933;">,</span> i<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/* request device major number */</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>ret <span style="color: #339933;">=</span> alloc_chrdev_region<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>leds_dev_number<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">,</span> NUM_LEDS<span style="color: #339933;">,</span> DEVICE_NAME<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        printk<span style="color: #009900;">&#40;</span>KERN_DEBUG <span style="color: #ff0000;">&quot;Error registering device!<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">return</span> ret<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/* init leds GPIO port */</span>
    initLedPort<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/* init each led device */</span>
    <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> NUM_LEDS<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;">/* init led status */</span>
        leds_dev<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">number</span> <span style="color: #339933;">=</span> i <span style="color: #339933;">+</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
        leds_dev<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">status</span> <span style="color: #339933;">=</span> LED_OFF<span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;">/* connect file operations to this device */</span>
        cdev_init<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>leds_dev<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">cdev</span><span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>leds_fops<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        leds_dev<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">cdev</span>.<span style="color: #202020;">owner</span> <span style="color: #339933;">=</span> THIS_MODULE<span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;">/* connect major/minor numbers */</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>ret <span style="color: #339933;">=</span> cdev_add<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>leds_dev<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">cdev</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span>leds_dev_number <span style="color: #339933;">+</span> i<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            printk<span style="color: #009900;">&#40;</span>KERN_DEBUG <span style="color: #ff0000;">&quot;Error adding device!<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">return</span> ret<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;">/* init led status */</span>
        changeLedStatus<span style="color: #009900;">&#40;</span>leds_dev<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">number</span><span style="color: #339933;">,</span> LED_OFF<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    printk<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Leds driver initialized.<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* driver exit */</span>
<span style="color: #993333;">void</span> __exit leds_exit<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #808080; font-style: italic;">/* release major number */</span>
    unregister_chrdev_region<span style="color: #009900;">&#40;</span>leds_dev_number<span style="color: #339933;">,</span> NUM_LEDS<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    printk<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Exiting leds driver.<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
module_init<span style="color: #009900;">&#40;</span>leds_init<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
module_exit<span style="color: #009900;">&#40;</span>leds_exit<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
MODULE_LICENSE<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;GPL&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>



<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Para começar, veja que existem duas funções definidas: <em>leds_init</em>(), que será chamada na inicialização do driver, ao ser carregado para a memória; e <em>leds_exit</em>(), que por sua vez será chamada ao remover o driver.</span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Existem também duas estruturas definidas: <em>leds_dev[]</em> armazena as informações de cada um dos 4 leds, e <em>leds_fops</em> armazena as operações que poderão ser realizadas com os leds (os nomes são auto-explicativos). Dentro de <em>leds_dev[]</em>, temos <em>cdev</em>, que é a estrutura que representa um char device.</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">A primeira tarefa que um driver deve executar é definir o “<em>major number</em>” que estará associado a ele. Ele pode requisitar um determinado número fixo com a função <em>register_chrdev_region()</em>, ou pedir para o kernel gerar um número dinamicamente com a função <em>alloc_chrdev_region()</em>. </span></span><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Requisitar um número fixo pode ser um risco pois não sabemos se ele já esta sendo usado, portanto a solução mais segura é requisitá-lo dinamicamente (é o que </span></span><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">fazemos na linha 42).</span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Na chamada a </span></span><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; "><em>alloc_chrdev_region()</em>, requisitamos ao kernel a alocação de 4 </span><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">“<em>minor numbers</em>” (parâmetro 3), começando por “<em>0</em>″ (parâmetro 2) e </span><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">armazenando o “<em>major </em></span><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; "><em>number</em>” em <em>leds_dev_number</em> (parâmetro 1). O quarto parâmetro diz ao kernel o nome associado ao driver, que você poderá ver quando listar o dispositivo em “<em>/proc/devices</em>”.</span></p>
<p><meta content="text/html; charset=utf-8" http-equiv="content-type" /><meta content="text/html; charset=utf-8" http-equiv="content-type" /></p>
<p style="text-align: justify; "><font class="Apple-style-span" face="verdana, geneva, sans-serif"><span class="Apple-style-span" style="font-size: 14px;">Na linha 51 temos um loop a ser executado para cada device (led) que criaremos. Na linha 58, a função <em>cdev_init()</em> associa a estrutura do led “<em>cdev”</em> (parâmetro 1) às funções de acesso ao arquivo de dispositivo (parâmetro 2).</span></font></p>
<p style="text-align: justify; "><font class="Apple-style-span" face="verdana, geneva, sans-serif"><span class="Apple-style-span" style="font-size: 14px;">Na linha 62 é que a mágica acontece. A função <em>cdev_add()</em> associa a estrutura do led <em>cdev</em> (parâmetro 1) ao seu “<em>major e minor number</em>” (parametro 2).</span></font></p>
<p><meta content="text/html; charset=utf-8" http-equiv="content-type" /></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Na prática: quando você realiza uma operação de escrita em <em>/dev/led1</em> (<em>major=253</em> e <em>minor=0</em>), o kernel procura a estrutura <em>cdev</em> associada a este device (mesmo <em>major/minor numbers</em>), que você definiu em <em>cdev_add()</em>, e então passa esta estrutura como parâmetro para a função <em>write()</em>, que você associou na chamada a <em>cdev_init()</em>. Simples, não?</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Mas como é então a implementação das funções de operação nos arquivos de dispositivo?</span></span></p>
<p style="text-align: justify; "><strong><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">ACESSANDO O HARDWARE PELO ARQUIVO DE DISPOSITIVO</span></strong></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Não tem segredo, o conceito é simples:</span></span></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">/* open led file */</span>
<span style="color: #993333;">int</span> leds_open<span style="color: #009900;">&#40;</span><span style="color: #993333;">struct</span> inode <span style="color: #339933;">*</span>inode<span style="color: #339933;">,</span> <span style="color: #993333;">struct</span> file <span style="color: #339933;">*</span>file<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">struct</span> leds_device <span style="color: #339933;">*</span>leds_devp<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/* get cdev struct */</span>
    leds_devp <span style="color: #339933;">=</span> container_of<span style="color: #009900;">&#40;</span>inode<span style="color: #339933;">-&gt;</span>i_cdev<span style="color: #339933;">,</span> <span style="color: #993333;">struct</span> leds_device<span style="color: #339933;">,</span> cdev<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/* save cdev pointer */</span>
    file<span style="color: #339933;">-&gt;</span>private_data <span style="color: #339933;">=</span> leds_devp<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/* return OK */</span>
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* close led file */</span>
<span style="color: #993333;">int</span> leds_release<span style="color: #009900;">&#40;</span><span style="color: #993333;">struct</span> inode <span style="color: #339933;">*</span>inode<span style="color: #339933;">,</span> <span style="color: #993333;">struct</span> file <span style="color: #339933;">*</span>file<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #808080; font-style: italic;">/* return OK */</span>
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* read led status */</span>
ssize_t leds_read<span style="color: #009900;">&#40;</span><span style="color: #993333;">struct</span> file <span style="color: #339933;">*</span>file<span style="color: #339933;">,</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>buf<span style="color: #339933;">,</span> size_t count<span style="color: #339933;">,</span> loff_t <span style="color: #339933;">*</span>ppos<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">struct</span> leds_device <span style="color: #339933;">*</span>leds_devp <span style="color: #339933;">=</span> file<span style="color: #339933;">-&gt;</span>private_data<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>leds_devp<span style="color: #339933;">-&gt;</span>status <span style="color: #339933;">==</span> LED_ON<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>copy_to_user<span style="color: #009900;">&#40;</span>buf<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;1&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
            <span style="color: #b1b100;">return</span> <span style="color: #339933;">-</span>EIO<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>copy_to_user<span style="color: #009900;">&#40;</span>buf<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;0&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
            <span style="color: #b1b100;">return</span> <span style="color: #339933;">-</span>EIO<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
ssize_t leds_write<span style="color: #009900;">&#40;</span><span style="color: #993333;">struct</span> file <span style="color: #339933;">*</span>file<span style="color: #339933;">,</span> <span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>buf<span style="color: #339933;">,</span> size_t count<span style="color: #339933;">,</span> loff_t <span style="color: #339933;">*</span>ppos<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">struct</span> leds_device <span style="color: #339933;">*</span>leds_devp <span style="color: #339933;">=</span> file<span style="color: #339933;">-&gt;</span>private_data<span style="color: #339933;">;</span>
    <span style="color: #993333;">char</span> kbuf <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>copy_from_user<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>kbuf<span style="color: #339933;">,</span> buf<span style="color: #339933;">,</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #339933;">-</span>EFAULT<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>kbuf <span style="color: #339933;">==</span> <span style="color: #339933;">&amp;</span><span style="color: #339933;">#39;1&amp;#39;) {</span>
        changeLedStatus<span style="color: #009900;">&#40;</span>leds_devp<span style="color: #339933;">-&gt;</span>number<span style="color: #339933;">,</span> LED_ON<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        leds_devp<span style="color: #339933;">-&gt;</span>status <span style="color: #339933;">=</span> LED_ON<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>kbuf <span style="color: #339933;">==</span> <span style="color: #339933;">&amp;</span><span style="color: #339933;">#39;0&amp;#39;) {</span>
        changeLedStatus<span style="color: #009900;">&#40;</span>leds_devp<span style="color: #339933;">-&gt;</span>number<span style="color: #339933;">,</span> LED_OFF<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        leds_devp<span style="color: #339933;">-&gt;</span>status <span style="color: #339933;">=</span> LED_OFF<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> count<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>



<p style="text-align: justify; "><font class="Apple-style-span" face="verdana, geneva, sans-serif"><span class="Apple-style-span" style="font-size: 14px;">A função <em>leds_open()</em> é chamada na abertura do arquivo. Sua única responsabilidade, no nosso caso, é salvar a estrutura <em>leds_dev</em> associada ao device (led), pois usaremos esta estrutura nas funções de leitura e escrita. Isso é feito através da função <em>container_of()</em> na linha 7. O ponteiro para <em>leds_dev</em> é salvo em <em>file-&gt;private_data</em> na linha 10.</span></font></p>
<p><meta content="text/html; charset=utf-8" http-equiv="content-type" /></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Na função de leitura <em>leds_read()</em>, recuperamos a estrutura do led <em>leds_dev</em> em </span></span><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; "><em>file-&gt;private_data</em> na linha 26, verificamos o staus do led e retornamos “<em>1</em>″ para aceso e “<em>0</em>″ para apagado. Veja que, para retornar dados para a aplicação, você precisa usar a função <em>copy_to_user()</em>. Esta é uma forma do kernel enviar dados para a aplicação, já que o kernel não “enxerga” a memória dos processos rodando em “<em>user mode</em>”, assim como a aplicações não enxergam a memória dos processos rodando em “<em>kernel mode</em>”.</span></p>
<p><meta content="text/html; charset=utf-8" http-equiv="content-type" /></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Na função de escrita leds_write(), também </span></span><span style="font-size: 14px; "><span style="font-family: verdana, geneva, sans-serif; ">recuperamos a estrutura do led <em>leds_dev</em> em </span></span><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; "><em>file-&gt;private_data</em> na linha 42. E usamos também a função <em>copy_from_user()</em> na linha 45 para ler os dados recebidos da aplicação. E então, dependendo dos dados recebidos (“<em>0</em>″ ou “<em>1</em>″), mudamos o estado dos leds.</span></p>
<p><meta content="text/html; charset=utf-8" http-equiv="content-type" /></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Bom, agora falta o principal: as rotinas de acesso às portas de I/O para gerenciar os leds da mini2440.</span></span></p>
<p style="text-align: justify; "><strong><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">ESCOVANDO UM POUCO DE BITS</span></strong></p>
<p style="text-align: justify; "><font class="Apple-style-span" face="verdana, geneva, sans-serif"><span class="Apple-style-span" style="font-size: 14px;">Iremos acessar os leds disponíveis na porta GPB da CPU, conforme configuração abaixo:</span></font></p>
<p style="text-align: center; "><img alt="leds pinout Linux Device Drivers   Parte 2" height="118" src="http://www.sergioprado.org/wp-content/uploads/leds_pinout.png" width="407" title="Linux Device Drivers   Parte 2" /></p>
<p><meta content="text/html; charset=utf-8" http-equiv="content-type" /></p>
<p style="text-align: justify; "><font class="Apple-style-span" face="verdana, geneva, sans-serif"><span class="Apple-style-span" style="font-size: 14px;">Precisamos configurar as portas como saída no registrador <em>GPBCON</em>, e ligar/desligar os leds no registrador <em>GPBDAT</em>. Os leds são acionados em nível baixo.</span></font></p>
<p style="text-align: justify; "><font class="Apple-style-span" face="verdana, geneva, sans-serif"><span class="Apple-style-span" style="font-size: 14px;">Esta CPU (<a href="http://elinux.org/S3C2440" target="_blank"><em>S3C2440</em></a>) mapeia o acesso ao GPB através do endereço de memória 0x56000010. Porém, este é um endereço real, e no kernel você trabalhará sempre com endereços virtuais. Olhando os fontes do kernel, verifiquei que o endereço virtual associado à este endereço real é o 0xFB000010. As definições estão no arquivo “<em>arch/arm/mach-s3c2410/include/mach/regs-gpio.h</em>”.</span></font></p>
<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Vamos então dar uma olhada no código:</span></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#define GPB_BASE    0xFB000010</span>
<span style="color: #339933;">#define GPBCON      GPB_BASE</span>
<span style="color: #339933;">#define GPBDAT      GPB_BASE + 4</span>
&nbsp;
<span style="color: #339933;">#define CLEAR_PORT_MASK     0xFFFC03FF</span>
<span style="color: #339933;">#define SET_WRITE_PORT_MASK 0x00015400</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* initialize led port - GPB */</span>
<span style="color: #993333;">void</span> initLedPort<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">void</span> __iomem <span style="color: #339933;">*</span>base <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span> __iomem <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span>GPBCON<span style="color: #339933;">;</span>
&nbsp;
    u32 port <span style="color: #339933;">=</span> __raw_readl<span style="color: #009900;">&#40;</span>base<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    port <span style="color: #339933;">&amp;=</span> CLEAR_PORT_MASK<span style="color: #339933;">;</span>
    port <span style="color: #339933;">|=</span> SET_WRITE_PORT_MASK<span style="color: #339933;">;</span>
&nbsp;
    __raw_writel<span style="color: #009900;">&#40;</span>port<span style="color: #339933;">,</span> base<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* change led status */</span>
<span style="color: #993333;">void</span> changeLedStatus<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> led_num<span style="color: #339933;">,</span> <span style="color: #993333;">int</span> status<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">void</span> __iomem <span style="color: #339933;">*</span>base <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span> __iomem <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span>GPBDAT<span style="color: #339933;">;</span>
    u32 mask<span style="color: #339933;">,</span> data<span style="color: #339933;">;</span>
&nbsp;
    data <span style="color: #339933;">=</span> __raw_readl<span style="color: #009900;">&#40;</span>base<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    mask <span style="color: #339933;">=</span> <span style="color: #208080;">0x01</span> <span style="color: #339933;">&lt;&lt;</span> <span style="color: #009900;">&#40;</span><span style="color: #0000dd;">4</span> <span style="color: #339933;">+</span> led_num<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">switch</span> <span style="color: #009900;">&#40;</span>status<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
        <span style="color: #b1b100;">case</span> LED_ON<span style="color: #339933;">:</span>
            mask <span style="color: #339933;">=</span> ~mask<span style="color: #339933;">;</span>
            data <span style="color: #339933;">&amp;=</span> mask<span style="color: #339933;">;</span>
            <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #b1b100;">case</span> LED_OFF<span style="color: #339933;">:</span>
            data <span style="color: #339933;">|=</span> mask<span style="color: #339933;">;</span>
            <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    __raw_writel<span style="color: #009900;">&#40;</span>data<span style="color: #339933;">,</span> base<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>



<p style="text-align: justify; "><font class="Apple-style-span" face="verdana, geneva, sans-serif"><span class="Apple-style-span" style="font-size: 14px;">A função <em>initLedPort()</em> é chamada na carga do driver e irá inicializar as portas dos leds (<em>GPB5-GPB8</em>) para trabalhar como saída através do registrado <em>GPBCON (bits 10..17)</em>. Na linha 15 zeramos a configuração e na linha 16 configuramos as portas como saída.</span></font></p>
<p style="text-align: justify; "><meta content="text/html; charset=utf-8" http-equiv="content-type" /><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Veja que estamos usando as macros <em>__raw_readl()</em> para ler um inteiro de 4 bytes da memória virtual e <em>__raw_writel() </em>para escrever um inteiro de 4 bytes na memória virtual. Esse mecanismo é mais seguro para acessar I/O mapeado em memória em Linux.</span></p>
<p style="text-align: justify; "><font class="Apple-style-span" face="verdana, geneva, sans-serif"><span class="Apple-style-span" style="font-size: 14px;">A função <em>changeLedStatus()</em> irá mudar o status do led para aceso ou apagado através do registrador </span></font><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; "><em>GPBDAT (bits 5..8)</em>.</span></p>
<p style="text-align: justify; "><strong><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">COMPILANDO E TESTANDO</span></span></strong></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">O código-fonte completo e o Makefile podem ser baixados <a href="http://www.sergioprado.org/wp-content/plugins/download-monitor/download.php?id=6" target="_blank">aqui</a>. Para compilar, basta seguir os procedimentos que descrevi <a href="http://www.sergioprado.org/2010/12/30/mini2440-compilando-aplicacoes-e-device-drivers/" target="_blank">neste artigo</a>.</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Para transferir para a mini2440, você pode colocar a placa em rede com seu PC, e usar alguma aplicação de transferência de arquivos como o scp ou o ftp. Você pode também configurar um sistema de arquivos com NFS, conforme descrevi <a href="http://www.sergioprado.org/2010/12/27/mini2440-montando-rootfs-no-linux-via-nfs/" target="_blank">aqui</a>.</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Alguns dos comandos que usaremos para testes assumem que o módulo compilado (<em>leds.ko</em>) foi copiado para a mini2440 no diretório abaixo</span></span><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">:</span></p>
<p><meta content="text/html; charset=utf-8" http-equiv="content-type" /></p>
<p style="text-align: center; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;"><em>/lib/modules/2.6.32.2-FriendlyARM/kernel/drivers/char/</em></span></span></p>
<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Portanto, adapte os comandos se necessário.</span></p>
<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">O primeiro passo é iniciar o driver. Uma mensagem será exibida indicando sucesso na inicialização e todos os leds serão apagados.</span></p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ insmod <span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>modules<span style="color: #000000; font-weight: bold;">/</span>2.6.32.2-FriendlyARM<span style="color: #000000; font-weight: bold;">/</span>kernel<span style="color: #000000; font-weight: bold;">/</span>drivers<span style="color: #000000; font-weight: bold;">/</span>char<span style="color: #000000; font-weight: bold;">/</span>leds.ko
Leds driver initialized.</pre></div></div>



<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Agora você precisa verificar o “<em>major number</em>” alocado pelo kernel para o device driver usando o comando abaixo (veja que, no meu caso, foi alocado o número 253):</span></p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">grep</span> leds <span style="color: #000000; font-weight: bold;">/</span>proc<span style="color: #000000; font-weight: bold;">/</span>devices
<span style="color: #000000;">253</span> leds</pre></div></div>



<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Com o “<em>major number</em>” em mãos, criaremos todos os arquivos de dispositivo com os comandos abaixo (mude o valor do <em>major number</em> se necessário):</span></p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">mknod</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>led1 c <span style="color: #000000;">253</span> <span style="color: #000000;">0</span>
$ <span style="color: #c20cb9; font-weight: bold;">mknod</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>led2 c <span style="color: #000000;">253</span> <span style="color: #000000;">1</span>
$ <span style="color: #c20cb9; font-weight: bold;">mknod</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>led3 c <span style="color: #000000;">253</span> <span style="color: #000000;">2</span>
$ <span style="color: #c20cb9; font-weight: bold;">mknod</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>led4 c <span style="color: #000000;">253</span> <span style="color: #000000;">3</span>
$ <span style="color: #c20cb9; font-weight: bold;">chmod</span> a+<span style="color: #c20cb9; font-weight: bold;">w</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>led<span style="color: #000000; font-weight: bold;">*</span></pre></div></div>



<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Obs: No próximo artigo veremos como usar um mecanismo de hotplug para criação dinâmica de arquivos de dispositivo. </span></p>
<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Agora é hora de testar. Para acender um led, basta enviar o caracter “1”. Os comandos abaixo acendem os leds 1 e 3:</span></p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;1&quot;</span> <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>led1
$ <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;1&quot;</span> <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>led3</pre></div></div>



<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">E para apagar um led, basta enviar “0”:</span></p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;0&quot;</span> <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>led3</pre></div></div>



<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Para verificar o estado de um led, não podemos apenas ler o arquivo com o comando “cat” por exemplo. Isso porque na rotina que trata a leitura do arquivo, perceba que nunca retornamos <em>EOF</em> (<em>end-of-file</em>). Isso significa que, se por exemplo o led estiver aceso, o comando “<em>cat /dev/led1</em>″ irá imprimir indefinidamente o número “<em>1</em>″. Então, para ler o estado do led, precisamos de um comando que leia apenas 1 byte. Podemos fazer isso com o comando “<em>dd</em>”, salvar o byte em um arquivo, e depois imprimir, conforme abaixo:</span></p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">dd</span> <span style="color: #007800;">if</span>=<span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>led1 <span style="color: #007800;">of</span>=<span style="color: #000000; font-weight: bold;">/</span>tmp<span style="color: #000000; font-weight: bold;">/</span>led <span style="color: #007800;">bs</span>=<span style="color: #000000;">1</span> <span style="color: #007800;">count</span>=<span style="color: #000000;">1</span>
$ <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;LED=<span style="color: #007800;">$(cat /tmp/led)</span>&quot;</span>
<span style="color: #007800;">LED</span>=<span style="color: #000000;">1</span></pre></div></div>



<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">E finalmente, para remover o driver:</span></p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ rmmod leds
Exiting leds driver.</pre></div></div>



<p style="text-align: justify; "><strong><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">PRÓXIMOS PASSOS</span></strong></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Muito bem, vocês viram que o assunto deste artigo foi bem denso. Se para você foi muita informação de uma só vez, pare, respire, pense. Estude o código com mais calma, e você verá que não existe nenhum segredo no desenvolvimento de device drivers para Linux. Basta conhecer a API do Linux e escovar um pouco de bits.</span></span></p>
<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">No próximo artigo vamos aprender alguns novos conceitos, como criação dinâmica de arquivos de dispositivo, gerenciamento do hardware através do diretório “/sys” e rotinas de timer do kernel (vamos adicionar uma funcionalidade de pisca-pisca ao nosso driver).</span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Um abraço!</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Sergio Prado</span></span></p>
<p><meta content="text/html; charset=utf-8" http-equiv="content-type" /></p><div class="shr-publisher-1259"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic --><p>Posts relacionados:</p><ol>
<li><a href='http://sergioprado.org/mini2440-compilando-aplicacoes-e-device-drivers/' rel='bookmark' title='Mini2440 — Compilando aplicações e device drivers'>Mini2440 — Compilando aplicações e device drivers</a></li>
<li><a href='http://sergioprado.org/linux-device-drivers-parte-1/' rel='bookmark' title='Linux Device Drivers — Parte 1'>Linux Device Drivers — Parte 1</a></li>
<li><a href='http://sergioprado.org/mini2440-linux-com-u-boot-e-emdebian/' rel='bookmark' title='Mini2440 — Linux com U-Boot e Emdebian'>Mini2440 — Linux com U-Boot e Emdebian</a></li>
</ol><p><p>Sergio Prado atua com desenvolvimento de software para sistemas embarcados há mais de 15 anos. É sócio-fundador da Embed­ded Lab­works, uma empresa focada em te aju­dar a desen­volver soft­ware de qual­i­dade para sis­temas embar­ca­dos. Se você pre­cisa de ajuda para desen­volver seu pro­duto, ou quer saber mais sobre o que a Embed­ded Lab­works pode fazer por você, acesse <a href=”http://e-labworks.com/servicos/”> http://e-labworks.com/servicos</a>.</p>
<p>Este post foi originalmente publicado em <a href="http://sergioprado.org/linux-device-drivers-parte-2/">Linux Device Drivers — Parte 2</a>.</p></p>]]></content:encoded>
			<wfw:commentRss>http://sergioprado.org/linux-device-drivers-parte-2/feed/</wfw:commentRss>
		<slash:comments>28</slash:comments>
		</item>
		<item>
		<title>Mini2440 — Compilando aplicações e device drivers</title>
		<link>http://sergioprado.org/mini2440-compilando-aplicacoes-e-device-drivers/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mini2440-compilando-aplicacoes-e-device-drivers</link>
		<comments>http://sergioprado.org/mini2440-compilando-aplicacoes-e-device-drivers/#comments</comments>
		<pubDate>Thu, 30 Dec 2010 18:00:02 +0000</pubDate>
		<dc:creator>Sergio Prado</dc:creator>
				<category><![CDATA[Linguagem C]]></category>
		<category><![CDATA[Linux embarcado]]></category>
		<category><![CDATA[Mini2440]]></category>
		<category><![CDATA[compilador]]></category>
		<category><![CDATA[device driver]]></category>
		<category><![CDATA[toolchain]]></category>

		<guid isPermaLink="false">http://www.sergioprado.org/?p=1243</guid>
		<description><![CDATA[<p>Neste artigo vamos aprender como cross-compilar aplicações e device drivers para o kit FriendlyARM mini2440.</p><p><p>Sergio Prado atua com desenvolvimento de software para sistemas embarcados há mais de 15 anos. É sócio-fundador da Embed­ded Lab­works, uma empresa focada em te aju­dar a desen­volver soft­ware de qual­i­dade para sis­temas embar­ca­dos. Se você pre­cisa de ajuda para desen­volver seu pro­duto, ou quer saber mais sobre o que a Embed­ded Lab­works pode fazer por você, acesse <a href=”http://e-labworks.com/servicos/”> http://e-labworks.com/servicos</a>.</p>
<p>Este post foi originalmente publicado em <a href="http://sergioprado.org/mini2440-compilando-aplicacoes-e-device-drivers/">Mini2440 — Compilando aplicações e device drivers</a>.</p></p>
Posts relacionados:<ol>
<li><a href='http://sergioprado.org/linux-device-drivers-parte-1/' rel='bookmark' title='Linux Device Drivers — Parte 1'>Linux Device Drivers — Parte 1</a></li>
<li><a href='http://sergioprado.org/mini2440-linux-from-scratch-com-buildroot/' rel='bookmark' title='Mini2440 — Linux from scratch com Buildroot'>Mini2440 — Linux from scratch com Buildroot</a></li>
<li><a href='http://sergioprado.org/mini2440-montando-rootfs-no-linux-via-nfs/' rel='bookmark' title='Mini2440 — Montando rootfs no Linux via NFS'>Mini2440 — Montando rootfs no Linux via NFS</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Vimos um tempo atrás como gerar um Linux embarcado do zero com o Buildroot <a href="http://www.sergioprado.org/2010/09/26/mini2440-linux-from-scratch-com-buildroot/" target="_blank">neste artigo aqui</a>. Geramos o toolchain, a imagem do kernel e o rootfs. Mas compilamos apenas com os pacotes disponíveis por padrão no Buildroot. E se agora você quiser compilar uma aplicação ou um device driver e integrar na sua solução. Como podemos usar a infraestrutura gerada pelo Buildroot e cross-compilar qualquer código para ser executado na mini2440. Isso é o que veremos neste artigo.</span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Obs: Os termos cross-compiling, cross-compilar, cross-compilação e compilação cruzada tem o mesmo significado: compilar uma aplicação em uma arquitetura e gerar código para uma outra arquitetura. No nosso caso iremos compilar em um x86 e gerar código para um ARM.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Como pré-requisito, é necessário que você tenha executado todos os passos do <a href="http://www.sergioprado.org/2010/09/26/mini2440-linux-from-scratch-com-buildroot/" target="_blank">artigo mencionado acima</a>. Para realizar os testes, você pode configurar um ambiente com NFS, conforme expliquei <a href="http://www.sergioprado.org/2010/12/27/mini2440-montando-rootfs-no-linux-via-nfs/" target="_blank">neste artigo aqui</a>.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Vamos utilizar o toolchain gerado pelo Buildroot. Você verá que o processo de compilação cruzada é bem simples, bastando apenas algumas alterações no Makefile do projeto.<br />
	</span></span></p>
<p style="text-align: justify; "><strong><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">COMPILANDO UMA APLICAÇÃO STANDALONE<br />
	</span></span></strong></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Este é o código que iremos compilar para testar na mini2440:</span></span></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">/* hello.c */</span>
&nbsp;
<span style="color: #339933;">#include &quot;stdio.h&quot;</span>
&nbsp;
<span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Hello mini2440!<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>



<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Se fossemos compilar normalmente em nossa máquina, este seria o Makefile que utilizaríamos:</span></p>


<div class="wp_syntax"><div class="code"><pre class="make" style="font-family:monospace;">all<span style="color: #004400;">:</span>
	<span style="color: #004400;">@</span>gcc hello<span style="color: #004400;">.</span>c <span style="color: #004400;">-</span>o hello
&nbsp;
clean<span style="color: #004400;">:</span>
	<span style="color: #004400;">@</span>rm <span style="color: #004400;">-</span>Rf <span style="color: #004400;">*.</span>o hello</pre></div></div>



<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Porém, iremos cross-compilar. Isso significa que iremos utilizar um compilador diferente, e o código compilado será linkado com uma biblioteca diferente. Este será o nosso Makefile para cross-compilar a aplicação:<br />
	</span></span></p>


<div class="wp_syntax"><div class="code"><pre class="make" style="font-family:monospace;">TOOLCHAIN<span style="color: #004400;">=/</span>opt<span style="color: #004400;">/</span>buildroot<span style="color: #004400;">/</span>buildroot<span style="color: #004400;">-</span><span style="color: #CC2200;">2010.08</span><span style="color: #004400;">/</span>output<span style="color: #004400;">/</span>staging<span style="color: #004400;">/</span>usr<span style="color: #004400;">/</span>bin<span style="color: #004400;">/</span>
CROSS_COMPILE<span style="color: #004400;">=</span>arm<span style="color: #004400;">-</span>linux<span style="color: #004400;">-</span>
&nbsp;
PATH <span style="color: #004400;">:=</span> <span style="color: #004400;">$</span><span style="color: #004400;">&#123;</span><span style="color: #000088;">TOOLCHAIN</span><span style="color: #004400;">&#125;</span><span style="color: #004400;">:$</span><span style="color: #004400;">&#123;</span><span style="color: #000088;">PATH</span><span style="color: #004400;">&#125;</span>
&nbsp;
all<span style="color: #004400;">:</span>
	<span style="color: #004400;">@$</span><span style="color: #004400;">&#123;</span><span style="color: #000088;">CROSS_COMPILE</span><span style="color: #004400;">&#125;</span>gcc hello<span style="color: #004400;">.</span>c <span style="color: #004400;">-</span>o hello
&nbsp;
clean<span style="color: #004400;">:</span>
	<span style="color: #004400;">@</span>rm <span style="color: #004400;">-</span>Rf <span style="color: #004400;">*.</span>o hello</pre></div></div>



<p><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">A variável <em>TOOLCHAIN</em> vai depender do local onde você instalou o Buildroot. No meu caso, instalei em “<em>/opt/buildroot/buildroot-2010.08</em>″. Ajuste de acordo com seu ambiente.</span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Veja que foram apenas 2 mudanças em relação ao Makefile anterior. Alteramos a variável de ambiente <em>PATH</em> para que o sistema encontre os binários do toolchain, e em vez de compilar com o “<em>gcc</em>”, estamos usando o “<em>arm-linux-gcc</em>”.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Os dois arquivos (<em>hello.c</em> e <em>Makefile</em>) devem estar no mesmo diretório. Para compilar, digite apenas “<em>make</em>”. Após a compilação, você pode conferir se o binário foi compilado para a arquitetura correta com o comando “<em>file</em>”:</span></span></p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">file</span> hello
hello: ELF <span style="color: #000000;">32</span>-bit LSB executable, ARM, version <span style="color: #000000;">1</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>SYSV<span style="color: #7a0874; font-weight: bold;">&#41;</span>, dynamically linked <span style="color: #7a0874; font-weight: bold;">&#40;</span>uses shared libs<span style="color: #7a0874; font-weight: bold;">&#41;</span>, not stripped</pre></div></div>



<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Para testar, copie o binário para o sistema de arquivos que você configurou com o NFS:</span></p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">cp</span> hello <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>mini2440<span style="color: #000000; font-weight: bold;">/</span>rootfs<span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span></pre></div></div>



<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Agora, entre na console da mini2440 e teste sua aplicação:</span></span></p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>hello
Hello mini2440<span style="color: #000000; font-weight: bold;">!</span></pre></div></div>



<p style="text-align: justify; "><strong><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">COMPILANDO UM DEVICE DRIVER<br />
	</span></span></strong></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Para compilar um device driver não é muito diferente ou mais complicado.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Este é um “esqueleto” de um driver simples que escrevi, apenas com as funções de inicialização e finalização, mas que serve para nosso propósito de compilar e testar na mini2440:<br />
	</span></span></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">/* file leds.c */</span>
&nbsp;
<span style="color: #339933;">#include &quot;linux/fs.h&quot;</span>
<span style="color: #339933;">#include &quot;linux/cdev.h&quot;</span>
<span style="color: #339933;">#include &quot;linux/module.h&quot;</span>
<span style="color: #339933;">#include &quot;linux/kernel.h&quot;</span>
<span style="color: #339933;">#include &quot;linux/device.h&quot;</span>
<span style="color: #339933;">#include &quot;asm/uaccess.h&quot;</span>
<span style="color: #339933;">#include &quot;linux/slab.h&quot;</span>
&nbsp;
<span style="color: #339933;">#define DEVICE_NAME     &quot;leds&quot;</span>
&nbsp;
<span style="color: #339933;">#define NUM_LEDS        1</span>
&nbsp;
<span style="color: #993333;">int</span> __init leds_init<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">void</span> __exit leds_exit<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* per led structure */</span>
<span style="color: #993333;">struct</span> leds_device <span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> status<span style="color: #339933;">;</span>
    <span style="color: #993333;">struct</span> cdev cdev<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span> leds_dev<span style="color: #009900;">&#91;</span>NUM_LEDS<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* file operations structure */</span>
<span style="color: #993333;">static</span> <span style="color: #993333;">struct</span> file_operations leds_fops <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
    .<span style="color: #202020;">owner</span>      <span style="color: #339933;">=</span> THIS_MODULE<span style="color: #339933;">,</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #993333;">static</span> dev_t leds_dev_number<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* driver initialization */</span>
<span style="color: #993333;">int</span> __init leds_init<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> ret<span style="color: #339933;">,</span> i<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/* request device major number */</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>ret <span style="color: #339933;">=</span> alloc_chrdev_region<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>leds_dev_number<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">,</span> NUM_LEDS<span style="color: #339933;">,</span> DEVICE_NAME<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        printk<span style="color: #009900;">&#40;</span>KERN_DEBUG <span style="color: #ff0000;">&quot;Error registering device!<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">return</span> ret<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/* init each led device */</span>
    <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> NUM_LEDS<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;">/* init led status */</span>
        leds_dev<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">status</span> <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;">/* connect file operations to this device */</span>
        cdev_init<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>leds_dev<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">cdev</span><span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>leds_fops<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        leds_dev<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">cdev</span>.<span style="color: #202020;">owner</span> <span style="color: #339933;">=</span> THIS_MODULE<span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;">/* connect major/minor numbers */</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>ret <span style="color: #339933;">=</span> cdev_add<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>leds_dev<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">cdev</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span>leds_dev_number <span style="color: #339933;">+</span> i<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            printk<span style="color: #009900;">&#40;</span>KERN_DEBUG <span style="color: #ff0000;">&quot;Error adding device!<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">return</span> ret<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009900;">&#125;</span>
&nbsp;
    printk<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Initializing leds driver.<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* driver exit */</span>
<span style="color: #993333;">void</span> __exit leds_exit<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #808080; font-style: italic;">/* release major number */</span>
    unregister_chrdev_region<span style="color: #009900;">&#40;</span>leds_dev_number<span style="color: #339933;">,</span> NUM_LEDS<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    printk<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Exiting leds driver.<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
module_init<span style="color: #009900;">&#40;</span>leds_init<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
module_exit<span style="color: #009900;">&#40;</span>leds_exit<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
MODULE_LICENSE<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;GPL&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>



<p><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Para compilar, este é o Makefile:</span></p>


<div class="wp_syntax"><div class="code"><pre class="make" style="font-family:monospace;">TOOLCHAIN <span style="color: #004400;">:=</span> <span style="color: #004400;">/</span>opt<span style="color: #004400;">/</span>buildroot<span style="color: #004400;">/</span>buildroot<span style="color: #004400;">-</span><span style="color: #CC2200;">2010.08</span><span style="color: #004400;">/</span>output<span style="color: #004400;">/</span>staging<span style="color: #004400;">/</span>usr<span style="color: #004400;">/</span>bin<span style="color: #004400;">/</span>
KDIR <span style="color: #004400;">:=</span> <span style="color: #004400;">/</span>opt<span style="color: #004400;">/</span>buildroot<span style="color: #004400;">/</span>buildroot<span style="color: #004400;">-</span><span style="color: #CC2200;">2010.08</span><span style="color: #004400;">/</span>output<span style="color: #004400;">/</span>build<span style="color: #004400;">/</span>linux<span style="color: #004400;">-</span><span style="color: #CC2200;">2.6</span><span style="color: #004400;">/</span>
PWD  <span style="color: #004400;">:=</span> <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #0000CC; font-weight: bold;">shell</span> pwd<span style="color: #004400;">&#41;</span>
PATH <span style="color: #004400;">:=</span> <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">TOOLCHAIN</span><span style="color: #004400;">&#41;</span><span style="color: #004400;">:$</span><span style="color: #004400;">&#123;</span><span style="color: #000088;">PATH</span><span style="color: #004400;">&#125;</span>
&nbsp;
obj<span style="color: #004400;">-</span>m <span style="color: #004400;">+=</span> leds<span style="color: #004400;">.</span>o
&nbsp;
default<span style="color: #004400;">:</span>
	<span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">MAKE</span><span style="color: #004400;">&#41;</span> <span style="color: #004400;">-</span>C <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">KDIR</span><span style="color: #004400;">&#41;</span> SUBDIRS<span style="color: #004400;">=$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">PWD</span><span style="color: #004400;">&#41;</span> modules
&nbsp;
clean<span style="color: #004400;">:</span>
	<span style="color: #004400;">@</span>rm <span style="color: #004400;">-</span>Rf <span style="color: #004400;">*.</span>o <span style="color: #004400;">*.</span>ko <span style="color: #004400;">*.</span>mod<span style="color: #004400;">.</span>c modules<span style="color: #004400;">.</span>order Module<span style="color: #004400;">.</span>symvers</pre></div></div>



<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">A variável <em>KDIR</em> deve apontar para o diretório do kernel que o Buildroot compilou para a mini2440. Ajuste-a de acordo com seu ambiente. O mesmo deve ser feito novamente com a variável <em>TOOLCHAIN</em>. Perceba que aqui não precisamos setar o compilador para “<em>arm-linux-gcc</em>”. Este Makefile é uma extensão do Makefile do kernel, e como o kernel já foi compilado para esta arquitetura, ele sabe qual toolchain (compilador) usar. </span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Novamente, os dois arquivos (leds<em>.c</em> e <em>Makefile</em>) devem estar no mesmo diretório, e para compilar, digite apenas “<em>make</em>”. O módulo gerado terá a extensão “<em>.ko</em>”. </span></span><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Você também pode conferir se o módulo foi compilado para a arquitetura correta com o comando “file”:</span></p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">file</span> leds.ko
leds.ko: ELF <span style="color: #000000;">32</span>-bit LSB relocatable, ARM, version <span style="color: #000000;">1</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>SYSV<span style="color: #7a0874; font-weight: bold;">&#41;</span>, not stripped</pre></div></div>



<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Agora, copie o binário para o sistema de arquivos que você configurou com o NFS:</span></p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">cp</span> leds.ko <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>mini2440<span style="color: #000000; font-weight: bold;">/</span>rootfs<span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span></pre></div></div>



<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">E teste inserindo e removendo o driver:</span></span></p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ insmod <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>leds.ko
Initializing leds driver.
&nbsp;
$ rmmod leds
Exiting leds driver.</pre></div></div>



<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Claro que estes exemplos são bem simples, e o Makefile pode ficar bem complicado em projetos maiores. Mas os conceitos utilizados serão sempre os mesmos.</span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Um abraço,<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Sergio Prado</span></span></p><div class="shr-publisher-1243"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic --><p>Posts relacionados:</p><ol>
<li><a href='http://sergioprado.org/linux-device-drivers-parte-1/' rel='bookmark' title='Linux Device Drivers — Parte 1'>Linux Device Drivers — Parte 1</a></li>
<li><a href='http://sergioprado.org/mini2440-linux-from-scratch-com-buildroot/' rel='bookmark' title='Mini2440 — Linux from scratch com Buildroot'>Mini2440 — Linux from scratch com Buildroot</a></li>
<li><a href='http://sergioprado.org/mini2440-montando-rootfs-no-linux-via-nfs/' rel='bookmark' title='Mini2440 — Montando rootfs no Linux via NFS'>Mini2440 — Montando rootfs no Linux via NFS</a></li>
</ol><p><p>Sergio Prado atua com desenvolvimento de software para sistemas embarcados há mais de 15 anos. É sócio-fundador da Embed­ded Lab­works, uma empresa focada em te aju­dar a desen­volver soft­ware de qual­i­dade para sis­temas embar­ca­dos. Se você pre­cisa de ajuda para desen­volver seu pro­duto, ou quer saber mais sobre o que a Embed­ded Lab­works pode fazer por você, acesse <a href=”http://e-labworks.com/servicos/”> http://e-labworks.com/servicos</a>.</p>
<p>Este post foi originalmente publicado em <a href="http://sergioprado.org/mini2440-compilando-aplicacoes-e-device-drivers/">Mini2440 — Compilando aplicações e device drivers</a>.</p></p>]]></content:encoded>
			<wfw:commentRss>http://sergioprado.org/mini2440-compilando-aplicacoes-e-device-drivers/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Trabalhando com o stack em linguagem C — Parte 2</title>
		<link>http://sergioprado.org/trabalhando-com-o-stack-em-linguagem-c-parte-2/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=trabalhando-com-o-stack-em-linguagem-c-parte-2</link>
		<comments>http://sergioprado.org/trabalhando-com-o-stack-em-linguagem-c-parte-2/#comments</comments>
		<pubDate>Wed, 22 Dec 2010 23:40:56 +0000</pubDate>
		<dc:creator>Sergio Prado</dc:creator>
				<category><![CDATA[Linguagem C]]></category>
		<category><![CDATA[compilador]]></category>
		<category><![CDATA[stack]]></category>
		<category><![CDATA[stack overflow]]></category>

		<guid isPermaLink="false">http://www.sergioprado.org/?p=1193</guid>
		<description><![CDATA[<p>Nesta segunda parte vamos estudar algumas metodologias para calcular o tamanho do stack necessário por determinada aplicação.</p><p><p>Sergio Prado atua com desenvolvimento de software para sistemas embarcados há mais de 15 anos. É sócio-fundador da Embed­ded Lab­works, uma empresa focada em te aju­dar a desen­volver soft­ware de qual­i­dade para sis­temas embar­ca­dos. Se você pre­cisa de ajuda para desen­volver seu pro­duto, ou quer saber mais sobre o que a Embed­ded Lab­works pode fazer por você, acesse <a href=”http://e-labworks.com/servicos/”> http://e-labworks.com/servicos</a>.</p>
<p>Este post foi originalmente publicado em <a href="http://sergioprado.org/trabalhando-com-o-stack-em-linguagem-c-parte-2/">Trabalhando com o stack em linguagem C — Parte 2</a>.</p></p>
Posts relacionados:<ol>
<li><a href='http://sergioprado.org/trabalhando-com-o-stack-em-linguagem-c-parte-1/' rel='bookmark' title='Trabalhando com o stack em linguagem C — Parte 1'>Trabalhando com o stack em linguagem C — Parte 1</a></li>
<li><a href='http://sergioprado.org/otimizacao-de-codigo-em-linguagem-c-parte-1/' rel='bookmark' title='Otimização de código em Linguagem C — Parte 1'>Otimização de código em Linguagem C — Parte 1</a></li>
<li><a href='http://sergioprado.org/otimizacao-de-codigo-em-linguagem-c-parte-2/' rel='bookmark' title='Otimização de código em Linguagem C — Parte 2'>Otimização de código em Linguagem C — Parte 2</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Na <a href="http://www.sergioprado.org/2010/12/15/trabalhando-com-o-stack-em-linguagem-c-parte-1/" target="_blank">primeira parte</a> deste artigo falei sobre os conceitos de pilha, como o compilador gera o código e usa o stack, e dei alguns exemplos de como minimizar seu uso em código desenvolvido em linguagem C.</span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Agora vamos estudar algumas metodologias para calcular o tamanho do stack necessário por determinada aplicação.<br />
	</span></span></p>
<p style="text-align: justify; "><strong><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">CALCULANDO O USO DO STACK<br />
	</span></span></strong></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Qual o tamanho do stack necessário para sua aplicação? Vamos desperdiçar muita memória alocando um espaço bem grande para o stack, ou iremos alocar um espaço mais reduzido, e correr o risco de um <a href="http://en.wikipedia.org/wiki/Stack_overflow" target="_blank">stack overflow</a>?<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Não é fácil responder à estas perguntas. Não existe receita de bolo, e muito menos um caminho das pedras.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">O tamanho do stack depende de muitas variáveis e eventos assíncronos, como chamadas aninhadas de funções, tamanho de variáveis automáticas, chamadas à funções do sistema operacional, bibliotecas e interrupções. E o problema vai ficando cada vez pior conforme aumentamos a complexidade e a quantidade de linhas de código.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Para analisar então o tamanho do stack necessário pela aplicação, também chamado de profundidade do stack, podemos usar dois tipos de técnicas: análise estática de código e análise dinâmica de código — cada uma com seus prós e contras. Vamos dar uma olhada melhor nestas técnicas.<br />
	</span></span></p>
<p style="text-align: justify; "><strong><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">ANÁLISE ESTÁTICA<br />
	</span></span></strong></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">O objetivo da análise estática é calcular a profundidade máxima alcançada pelo stack, varrendo o código-fonte (ou arquivo binário) da aplicação, passando por cada caminho dentro das chamadas de função e interrupção, contabilizando basicamente as instruções de PUSH e POP.<br />
	</span></span></p>
<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Usar os fontes da aplicação não é uma técnica muito recomendada por diversos fatores, dentre eles:</span></p>
<ol>
	<li style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">É muito mais complicado fazer a análise sintática e semântica do código-fonte do que interpretar e converter o arquivo binário em mnemônicos assembly. Quem já desenvolveu ou trabalhou com compiladores sabe como esta tarefa é complexa.</span></span></li>
	<li style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">A análise fica incompleta se o código-fonte do sistema operacional e de bibliotecas não estiverem disponíveis.</span></span></li>
	<li style="text-align: justify; "><font class="Apple-style-span" face="verdana, geneva, sans-serif"><span class="Apple-style-span" style="font-size: 14px;">É difícil prever o que o compilador fará com o código-fonte. Por exemplo, uma chamada de função, que poderia gerar algumas instruções de PUSH, pode ser otimizada pelo compilador para uma função inline, não gerando nenhuma instrução de PUSH.</span></font></li></ol>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">O ideal então é usar o binário final para fazer esta análise. Mas isso não deixa a solução mais fácil.</span></span></p>
<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">A ferramenta precisa lidar com problemas como ponteiros dinâmicos de função, funções recursivas, funções de callback, etc. As interrupções também são outro problema, já que são eventos assíncronos. Como prever quais interrupções irão acontecer, e quando? Quantas interrupções ao mesmo tempo? Elas são reentrantes?</span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Mesmo com todos esses desafios, existem ferramentas que tentam chegar num valor aproximado de utilização do stack.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">O <a href="http://www.cs.utah.edu/~regehr/stacktool/" target="_blank">Stacktool</a> foi desenvolvido pelo <a href="http://www.cs.utah.edu/~regehr/" target="_blank">John Regehr</a> para fins educacionais. Esta ferramenta é um script em Perl que analisa o binário de uma aplicação desenvolvida para microcontroladores AVR. A saída do programa parece interessante (clique na figura para vê-la em tamanho maior):<br />
	</span></span></p>
<p style="text-align: justify; "><a href="http://www.cs.utah.edu/~regehr/stacktool/all_bounds.jpg" target="_blank"><img alt="stack analysis1 Trabalhando com o stack em linguagem C   Parte 2" height="236" src="http://www.sergioprado.org/wp-content/uploads/stack_analysis1.jpg" width="580" title="Trabalhando com o stack em linguagem C   Parte 2" /></a></p>
<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Outra ferramenta interessante, o <a href="http://www.absint.com/stackanalyzer/" target="_blank">Stack Analyser</a> da <a href="http://www.absint.com/" target="_blank">AbsInt</a> também promete o mesmo resultado, com um ambiente gráfico e suporte à diversas arquiteturas como PowerPC, HC12/HCS12, ARM, M68k, TMS320C3x/Texas, etc.</span></p>
<p style="text-align: justify; "><img alt="stack analysis2 Trabalhando com o stack em linguagem C   Parte 2" height="513" src="http://www.sergioprado.org/wp-content/uploads/stack_analysis2.jpg" width="580" title="Trabalhando com o stack em linguagem C   Parte 2" /></p>
<p style="text-align: justify; "> </p>
<p style="text-align: justify; "><strong><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">ANÁLISE DINÂMICA</span></strong></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">O objetivo desta técnica é analisar o código dinamicamente em tempo de execução. Você pode adotar duas soluções:<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">1. Preencher o stack com uma “palavra mágica”.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Esta solução consiste em preencher e monitorar os valores do stack com uma ferramenta de debugger. No boot do seu código, antes da função main, desenvolva uma função que preencha todo o stack com um conjunto de caracteres, por exemplo “STACK123”. Um dump do stack no boot ficaria mais ou menos assim:</span></span></p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">00001000   <span style="color: #000000;">53</span> <span style="color: #000000;">54</span> <span style="color: #000000;">41</span> <span style="color: #000000;">43</span>  4B <span style="color: #000000;">31</span> <span style="color: #000000;">32</span> <span style="color: #000000;">33</span>  <span style="color: #000000;">53</span> <span style="color: #000000;">54</span> <span style="color: #000000;">41</span> <span style="color: #000000;">43</span>  4B <span style="color: #000000;">31</span> <span style="color: #000000;">32</span> <span style="color: #000000;">33</span>  STACK123STACK123
00001010   <span style="color: #000000;">53</span> <span style="color: #000000;">54</span> <span style="color: #000000;">41</span> <span style="color: #000000;">43</span>  4B <span style="color: #000000;">31</span> <span style="color: #000000;">32</span> <span style="color: #000000;">33</span>  <span style="color: #000000;">53</span> <span style="color: #000000;">54</span> <span style="color: #000000;">41</span> <span style="color: #000000;">43</span>  4B <span style="color: #000000;">31</span> <span style="color: #000000;">32</span> <span style="color: #000000;">33</span>  STACK123STACK123
00001020   <span style="color: #000000;">53</span> <span style="color: #000000;">54</span> <span style="color: #000000;">41</span> <span style="color: #000000;">43</span>  4B <span style="color: #000000;">31</span> <span style="color: #000000;">32</span> <span style="color: #000000;">33</span>  <span style="color: #000000;">53</span> <span style="color: #000000;">54</span> <span style="color: #000000;">41</span> <span style="color: #000000;">43</span>  4B <span style="color: #000000;">31</span> <span style="color: #000000;">32</span> <span style="color: #000000;">33</span>  STACK123STACK123
00001030   <span style="color: #000000;">53</span> <span style="color: #000000;">54</span> <span style="color: #000000;">41</span> <span style="color: #000000;">43</span>  4B <span style="color: #000000;">31</span> <span style="color: #000000;">32</span> <span style="color: #000000;">33</span>  <span style="color: #000000;">53</span> <span style="color: #000000;">54</span> <span style="color: #000000;">41</span> <span style="color: #000000;">43</span>  4B <span style="color: #000000;">31</span> <span style="color: #000000;">32</span> <span style="color: #000000;">33</span>  STACK123STACK123
00001040   <span style="color: #000000;">53</span> <span style="color: #000000;">54</span> <span style="color: #000000;">41</span> <span style="color: #000000;">43</span>  4B <span style="color: #000000;">31</span> <span style="color: #000000;">32</span> <span style="color: #000000;">33</span>  <span style="color: #000000;">53</span> <span style="color: #000000;">54</span> <span style="color: #000000;">41</span> <span style="color: #000000;">43</span>  4B <span style="color: #000000;">31</span> <span style="color: #000000;">32</span> <span style="color: #000000;">33</span>  STACK123STACK123
00001050   <span style="color: #000000;">53</span> <span style="color: #000000;">54</span> <span style="color: #000000;">41</span> <span style="color: #000000;">43</span>  4B <span style="color: #000000;">31</span> <span style="color: #000000;">32</span> <span style="color: #000000;">33</span>  <span style="color: #000000;">53</span> <span style="color: #000000;">54</span> <span style="color: #000000;">41</span> <span style="color: #000000;">43</span>  4B <span style="color: #000000;">31</span> <span style="color: #000000;">32</span> <span style="color: #000000;">33</span>  STACK123STACK123
00001060   <span style="color: #000000;">53</span> <span style="color: #000000;">54</span> <span style="color: #000000;">41</span> <span style="color: #000000;">43</span>  4B <span style="color: #000000;">31</span> <span style="color: #000000;">32</span> <span style="color: #000000;">33</span>  <span style="color: #000000;">53</span> <span style="color: #000000;">54</span> <span style="color: #000000;">41</span> <span style="color: #000000;">43</span>  4B <span style="color: #000000;">31</span> <span style="color: #000000;">32</span> <span style="color: #000000;">33</span>  STACK123STACK123
00001070   <span style="color: #000000;">53</span> <span style="color: #000000;">54</span> <span style="color: #000000;">41</span> <span style="color: #000000;">43</span>  4B <span style="color: #000000;">31</span> <span style="color: #000000;">32</span> <span style="color: #000000;">33</span>  <span style="color: #000000;">53</span> <span style="color: #000000;">54</span> <span style="color: #000000;">41</span> <span style="color: #000000;">43</span>  4B <span style="color: #000000;">31</span> <span style="color: #000000;">32</span> <span style="color: #000000;">33</span>  STACK123STACK123</pre></div></div>



<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Agora execute sua aplicação e realize testes completos, forçando </span><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">inclusive </span><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">a geração de eventos assíncronos como interrupções. Teste durante bastante tempo, simulando o comportamento real da aplicação. Finalizados os testes, tire outro dump do stack:</span></p>
<p><meta content="text/html; charset=utf-8" http-equiv="content-type" /></p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">00001000   FF 02 05 09  <span style="color: #000000;">12</span> 01 01 03  08 DE A7 C3  C9 F3 04 E9  ................
00001010   03 08 DE A7  C3 C9 F3 04  E9 09 <span style="color: #000000;">12</span> 01  01 03 C9 F3  ................
00001020   F3 04 E9 09  4B <span style="color: #000000;">31</span> <span style="color: #000000;">32</span> <span style="color: #000000;">33</span>  <span style="color: #000000;">53</span> <span style="color: #000000;">54</span> <span style="color: #000000;">41</span> <span style="color: #000000;">43</span>  4B <span style="color: #000000;">31</span> <span style="color: #000000;">32</span> <span style="color: #000000;">33</span>  ....K123STACK123
00001030   <span style="color: #000000;">53</span> <span style="color: #000000;">54</span> <span style="color: #000000;">41</span> <span style="color: #000000;">43</span>  4B <span style="color: #000000;">31</span> <span style="color: #000000;">32</span> <span style="color: #000000;">33</span>  <span style="color: #000000;">53</span> <span style="color: #000000;">54</span> <span style="color: #000000;">41</span> <span style="color: #000000;">43</span>  4B <span style="color: #000000;">31</span> <span style="color: #000000;">32</span> <span style="color: #000000;">33</span>  STACK123STACK123
00001040   <span style="color: #000000;">53</span> <span style="color: #000000;">54</span> <span style="color: #000000;">41</span> <span style="color: #000000;">43</span>  4B <span style="color: #000000;">31</span> <span style="color: #000000;">32</span> <span style="color: #000000;">33</span>  <span style="color: #000000;">53</span> <span style="color: #000000;">54</span> <span style="color: #000000;">41</span> <span style="color: #000000;">43</span>  4B <span style="color: #000000;">31</span> <span style="color: #000000;">32</span> <span style="color: #000000;">33</span>  STACK123STACK123
00001050   <span style="color: #000000;">53</span> <span style="color: #000000;">54</span> <span style="color: #000000;">41</span> <span style="color: #000000;">43</span>  4B <span style="color: #000000;">31</span> <span style="color: #000000;">32</span> <span style="color: #000000;">33</span>  <span style="color: #000000;">53</span> <span style="color: #000000;">54</span> <span style="color: #000000;">41</span> <span style="color: #000000;">43</span>  4B <span style="color: #000000;">31</span> <span style="color: #000000;">32</span> <span style="color: #000000;">33</span>  STACK123STACK123
00001060   <span style="color: #000000;">53</span> <span style="color: #000000;">54</span> <span style="color: #000000;">41</span> <span style="color: #000000;">43</span>  4B <span style="color: #000000;">31</span> <span style="color: #000000;">32</span> <span style="color: #000000;">33</span>  <span style="color: #000000;">53</span> <span style="color: #000000;">54</span> <span style="color: #000000;">41</span> <span style="color: #000000;">43</span>  4B <span style="color: #000000;">31</span> <span style="color: #000000;">32</span> <span style="color: #000000;">33</span>  STACK123STACK123
00001070   <span style="color: #000000;">53</span> <span style="color: #000000;">54</span> <span style="color: #000000;">41</span> <span style="color: #000000;">43</span>  4B <span style="color: #000000;">31</span> <span style="color: #000000;">32</span> <span style="color: #000000;">33</span>  <span style="color: #000000;">53</span> <span style="color: #000000;">54</span> <span style="color: #000000;">41</span> <span style="color: #000000;">43</span>  4B <span style="color: #000000;">31</span> <span style="color: #000000;">32</span> <span style="color: #000000;">33</span>  STACK123STACK123</pre></div></div>



<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Os bytes com os caracteres alterados indicam a região do stack usada pela aplicação. Veja que neste exemplo 36 bytes foram consumidos do stack.</span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">2. Monitorar o stack pointer<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Se você não tiver um debugger para tirar dumps do stack, você pode desenvolver uma função que monitore o conteúdo do Stack Pointer e armazene o maior valor. Exemplo:</span></span></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">volatile</span> <span style="color: #993333;">int</span> stackDepth <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #993333;">void</span> stackMonitor<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>stackDepth <span style="color: #339933;">&lt;</span> STACK_POINTER<span style="color: #009900;">&#41;</span>
        stackDepth <span style="color: #339933;">=</span> STACK_POINTER<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>



<p style="text-align: justify; "><span class="Apple-style-span" style="font-family: verdana, geneva, sans-serif; font-size: 14px; ">Coloque esta função para ser executada em um timer do sistema na menor resolução possível. E crie uma forma de visualizar este valor, através de um display, ou transmitindo por uma interface de comunicação.</span></p>
<p style="text-align: justify; "><strong><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">QUAL A MELHOR SOLUÇÃO?<br />
	</span></span></strong></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Depende! <br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Na análise estática, sempre será considerado o pior dos cenários. Se uma interrupção é reentrante, a análise pode chegar a conclusão de que o stack usado será infinito! Ou seja, prevendo os piores caminhos (dentre eles os improváveis e os impossíveis), esta técnica poderá sugerir um tamanho de stack maior do que o necessário, desperdiçando memória RAM. Por outro lado, este método é mais rápido e seguro.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Na análise dinâmica, o resultado poderá estar mais próximo do real. Porém, dependendo do tamanho do programa, você pode não conseguir simular todos os caminhos possíveis, e o stack pode não ser estimado corretamente. É mais dificil também prever eventos assíncronos como interrupções. Existe então um risco de subestimar o valor necessário para o stack, correndo o risco de Stack Overflow.</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Na prática, use os dois métodos. Considere um valor para o stack que esteja entre os valores encontrados na análise estática e na analise dinâmica. </span></span></p>
<p><meta content="text/html; charset=utf-8" http-equiv="content-type" /></p>
<p style="text-align: center; "><em><span style="font-size: 14px; "><span style="font-family: verdana, geneva, sans-serif; ">Análise estática &gt; Tamanho do Stack &gt; Análise Dinâmica</span></span></em></p>
<p style="text-align: justify; "><font class="Apple-style-span" face="verdana, geneva, sans-serif"><span class="Apple-style-span" style="font-size: 14px;">Dependendo do seu projeto, pode ser que não exista uma ferramenta de análise estática no mercado. E desenvolver uma também pode estar fora dos seus planos. Neste caso, quando temos apenas a análise dinâmica como parâmetro, adicione à sua medida uma margem de segurança de mais ou menos 30%. Por exemplo, se você mediu o uso de 100 bytes no stack, configure-o com 130 bytes.</span></font></p>
<p style="text-align: justify; "><font class="Apple-style-span" face="verdana, geneva, sans-serif"><span class="Apple-style-span" style="font-size: 14px;">É claro que não existe nada científico que comprove o uso desta margem de segurança de 30%. Poderia ser 20%, 40% ou mesmo 100%! Tudo vai depender do nível de confiança (e paranóia) que você tem nos testes que executou. A decisão da quantidade de bytes a serem alocados para o stack será sempre um trade-off entre a economia de memória RAM e o risco de acontecer um stack overflow.</span></font></p>
<p style="text-align: justify; "><strong><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">PROTEGENDO O STACK<br />
	</span></span></strong></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Se você tiver sorte, terá em mãos uma CPU com MMU (Memory Management Unit). Neste caso, configure na MMU uma região para o stack e proteja as áreas acima e abaixo desta região alocada para o stack. Qualquer acesso fora do stack causará uma exceção que poderá ser tratada por software. </span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Com um debugger conectado ao equipamento, você pode identificar em qual chamada o stack overflow aconteceu. Fica muito mais fácil de identificar, analisar e resolver o problema.<br />
	</span></span></p>
<p style="text-align: justify; "><strong><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">MAIS UMA VEZ, USE FERRAMENTAS<br />
	</span></span></strong></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Sempre ressalto aqui a importância de aproveitar as funcionalidades das ferramentas que usamos no dia-a-dia.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">O ambiente de desenvolvimento da IAR possui um plugin para analisar o stack que usa uma técnica parecida com a descrita na primeira solução de análise dinâmica, preenchendo o stack com 0xCD e monitorando-o durante a execução do programa. Se chegar a um limite pré-definido pelo usuário (90% por exemplo) irá avisar.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Já o <a href="http://www.keil.com/support/docs/192.htm" target="_blank">µVision Simulator</a> da Keil usa a técnica descrita na segunda solução da análise dinâmica, monitorando o valor máximo do stack pointer e armazenando em uma variável chamada sp_max. A responsabilidade de analisar esta variável e ajustar o stack é do desenvolvedor.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Você deve ter percebido que a análise do uso do stack é um problema sem uma solução simples. O ideal é unir um conjunto de técnicas, ferramentas e bom senso.<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Se você conhece mais alguma técnica ou ferramenta, deixe seus comentários!<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Um abraço,<br />
	</span></span></p>
<p style="text-align: justify; "><span style="font-size:14px;"><span style="font-family:verdana,geneva,sans-serif;">Sergio Prado.</span></span></p><div class="shr-publisher-1193"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic --><p>Posts relacionados:</p><ol>
<li><a href='http://sergioprado.org/trabalhando-com-o-stack-em-linguagem-c-parte-1/' rel='bookmark' title='Trabalhando com o stack em linguagem C — Parte 1'>Trabalhando com o stack em linguagem C — Parte 1</a></li>
<li><a href='http://sergioprado.org/otimizacao-de-codigo-em-linguagem-c-parte-1/' rel='bookmark' title='Otimização de código em Linguagem C — Parte 1'>Otimização de código em Linguagem C — Parte 1</a></li>
<li><a href='http://sergioprado.org/otimizacao-de-codigo-em-linguagem-c-parte-2/' rel='bookmark' title='Otimização de código em Linguagem C — Parte 2'>Otimização de código em Linguagem C — Parte 2</a></li>
</ol><p><p>Sergio Prado atua com desenvolvimento de software para sistemas embarcados há mais de 15 anos. É sócio-fundador da Embed­ded Lab­works, uma empresa focada em te aju­dar a desen­volver soft­ware de qual­i­dade para sis­temas embar­ca­dos. Se você pre­cisa de ajuda para desen­volver seu pro­duto, ou quer saber mais sobre o que a Embed­ded Lab­works pode fazer por você, acesse <a href=”http://e-labworks.com/servicos/”> http://e-labworks.com/servicos</a>.</p>
<p>Este post foi originalmente publicado em <a href="http://sergioprado.org/trabalhando-com-o-stack-em-linguagem-c-parte-2/">Trabalhando com o stack em linguagem C — Parte 2</a>.</p></p>]]></content:encoded>
			<wfw:commentRss>http://sergioprado.org/trabalhando-com-o-stack-em-linguagem-c-parte-2/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

