<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="/mac5856/feed.xml" rel="self" type="application/atom+xml" /><link href="/mac5856/" rel="alternate" type="text/html" /><updated>2026-04-05T03:38:33+00:00</updated><id>/mac5856/feed.xml</id><title type="html">MAC5856 - POSCOMP 1º Sem. 2026</title><subtitle>Diário de bordo da matéria de Desenvolvimento de Software Livre do programa de Mestrado em Ciência da Computação do IME - USP</subtitle><entry><title type="html">Relato Tutoriais 7 e 8</title><link href="/mac5856/jekyll/update/2026/04/04/tutorial-7-8.html" rel="alternate" type="text/html" title="Relato Tutoriais 7 e 8" /><published>2026-04-04T22:00:00+00:00</published><updated>2026-04-04T22:00:00+00:00</updated><id>/mac5856/jekyll/update/2026/04/04/tutorial-7-8</id><content type="html" xml:base="/mac5856/jekyll/update/2026/04/04/tutorial-7-8.html"><![CDATA[<p>Link para o Tutorial 7: <a href="https://flusp.ime.usp.br/iio/iio-dummy-anatomy/">The iio_simple_dummy Anatomy</a></p>

<p>Link para o Tutorial 8: <a href="https://flusp.ime.usp.br/iio/experiment-one-iio-dummy/">IIO Dummy module Experiment One: Play with iio_dummy</a></p>

<p>A realização dos tutoriais 7 e 8 foi um bom modo de encerrar essa etapa do curso, a final, pude colocar em prática vários dos conceitos aprendidos desde o primeiro tutorial.</p>

<p>Depois de habilitar o módulo <code class="language-plaintext highlighter-rouge">iio_dummy</code> via <code class="language-plaintext highlighter-rouge">make menuconfig</code>, realizar o build e boot da vm não consegui fazer o comando <code class="language-plaintext highlighter-rouge">sudo make modules_install</code> funcionar de jeito nenhum dentro da vm, por isso voltei para o <a href="/mac5856/jekyll/update/2026/03/12/tutorial-3.html">Tutorial 3</a> para rever alguns conceitos e comando úteis sobre módulos, e finalmente consegui carregar o módulo dessa maneira:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>@HOST
kw ssh <span class="nt">--send</span> drivers/iio/dummy/iio_dummy.ko
kw ssh <span class="nt">--send</span> drivers/iio/dummy/iio_dummy_evgen.ko

@VM
<span class="nb">cp</span> ~/iio_dummy.ko /lib/modules/<span class="sb">`</span><span class="nb">uname</span> <span class="nt">-r</span><span class="sb">`</span>/kernel/drivers/iio/dummy
<span class="nb">cp</span> ~/iio_dummy_evgen.ko /lib/modules/<span class="sb">`</span><span class="nb">uname</span> <span class="nt">-r</span><span class="sb">`</span>/kernel/drivers/iio/dummy
</code></pre></div></div>

<p>Depois disso a utilização do módulo começou tranquila:</p>

<p><img src="/mac5856/assets/images/t7_8_modinfo_iio_dummy.png" alt="modinfo result for iio_dumy module" /></p>

<p>Até o momento de montar o configfs filesystem:</p>

<p><img src="/mac5856/assets/images/t7_8_mount_warning.png" alt="mount warning" /></p>

<p>Como o tutorial não comentou nada sobre esse warning e após uma breve pesquisa não pareceu ser nada que fosse quebrar os próximos passos apenas ignorei e segui em frente.</p>

<p>Seguindo para o problema que demorei mais tempo para resolver… Após executar o mount tentei verificar se estava tudo certo através do comando <code class="language-plaintext highlighter-rouge">ls /mnt/iio_experiments/iio/devices/</code>, como o tutorial indica, e foi ai que as coisas desandaram. O comando apenas retornava o erro <code class="language-plaintext highlighter-rouge">No such file or directory</code>, logo achei que havia algo de errado com o meu módulo. De primeiro momento sai da vm, compilei e carreguei tudo novamente e… o mesmo erro.</p>

<p>Meu segundo pensamento foi achar que o problema estava na vm, a final, já havia feito varios testes nela e algo poderia ter quebrado no meio do caminho, como não tinha certeza do que poderia ser esse algo resolvi “formatar” a vm. Para isso apaguei o disco <code class="language-plaintext highlighter-rouge">${VM_DIR}/arm64_img.qcow2</code> e retornei ao passo 2.2 do <a href="/mac5856/jekyll/update/2026/03/05/tutorial-1.html">Tutorial 1</a> para criá-lo novamente - dessa vez aproveitei para salvar um backup do disco “limpo” - e mesmo após tudo isso continuei tomando o erro <code class="language-plaintext highlighter-rouge">No such file or directory</code>.</p>

<p>Dai fui tomar um café e deixei o problema de lado por um tempinho. Foi quando e me veio na cabeça “Será que o módulo tem que estar carregado?”, fui testar e… <em>Voilà</em>, funcionou!</p>

<p><img src="/mac5856/assets/images/t7_8_module_running.png" alt="module runing" /></p>

<p>Dai para frente implementai as mudanças sugeridas no tutorial e tudo correu bem:</p>

<p>Descrição do módulo modificado:</p>

<p><img src="/mac5856/assets/images/t7_8_dummy_modified.png" alt="Descrição do módulo modificado" /></p>

<p>Conteúdo do diretório <code class="language-plaintext highlighter-rouge">/sys/bus/iio/devices/iio:device0</code>:</p>

<p><img src="/mac5856/assets/images/t7_8_iio:device.png" alt="/sys/bus/iio/devices/iio:device0/" /></p>

<p>Leitura dos canais:</p>

<p><img src="/mac5856/assets/images/t7_8_chanels.png" alt="canais" /></p>

<h4 id="considerações-finais"><strong>Considerações finais</strong></h4>

<p>Apesar de os tutoriais 7 e 8 serem bem explicativos algumas informações podem ser atualizadas, como por exeplo os snipets da função iio_dummy_read_raw no tutorial 7. Também acharia interessante integrar o kw em alguns passos do tutorial 8, além de adicionar o diff das mudanças feitas no módulo, para que fique mais claro o que deve ser feito.</p>]]></content><author><name></name></author><category term="jekyll" /><category term="update" /><summary type="html"><![CDATA[Link para o Tutorial 7: The iio_simple_dummy Anatomy]]></summary></entry><entry><title type="html">Relato Tutoriais 5 e 6</title><link href="/mac5856/jekyll/update/2026/03/29/tutorial-5-6.html" rel="alternate" type="text/html" title="Relato Tutoriais 5 e 6" /><published>2026-03-29T22:00:00+00:00</published><updated>2026-03-29T22:00:00+00:00</updated><id>/mac5856/jekyll/update/2026/03/29/tutorial-5-6</id><content type="html" xml:base="/mac5856/jekyll/update/2026/03/29/tutorial-5-6.html"><![CDATA[<p>Link para o Tutorial 5: <a href="https://flusp.ime.usp.br/git/sending-patches-by-email-with-git/">Sending patches by email with git</a></p>

<p>Link para o Tutorial 6: <a href="https://flusp.ime.usp.br/git/sending-patches-with-git-and-a-usp-email/">Sending patches with git and a USP email</a></p>

<p>Nesses tutoriais vimos que o fluxo de desenvolvimento do kernel é centralizado no uso de e-mails para envio de patches, e em como podemos enviar esses patches de forma eficiente utilizando ferramentas como o <code class="language-plaintext highlighter-rouge">git</code> ou o <code class="language-plaintext highlighter-rouge">kw</code>. Aprendemos também a importância das mensagens de commits e como elas podem ser decisivas para a aceitação ou rejeição de um patch.</p>

<p>Para esse tutorial, por conveniência, resolvi utilizar o kw para o envio dos patches. Como o kw encapsula o <code class="language-plaintext highlighter-rouge">git send-email</code> os comandos de configuração acabam sendo bem parecidos, e o processo foi relativamente simples:</p>

<p><img src="/mac5856/assets/images/t5_6_email_config.png" alt="kw email config" /></p>

<p>Por conta de limitações no e-mail USP não é possivel criar um <a href="https://support.google.com/mail/answer/185833">App Password</a> para o envio de emails. Então o tutorial fernece uma maneira de contornar isso utilizando um e-mail proxy executado via docker + docker-compose para autenticação via OAuth 2.0.</p>

<p>Após clonar o repositório do tutorial e configurar o arquivo <code class="language-plaintext highlighter-rouge">emailproxy.config</code> com as credenciais do e-mail USP, bastou executar o comando <code class="language-plaintext highlighter-rouge">docker compose up --build</code> para subir o container e, em outro terminal, o comando <code class="language-plaintext highlighter-rouge">docker exec -it emailproxy-coNntainer-server-1 /bin/bash</code> para entrar no container. Já dentro do container executei o comando <code class="language-plaintext highlighter-rouge">emailproxy --no-gui --external-auth --config-file /app/emailproxy.config</code> para iniciar o serviço de proxy de e-mail:</p>

<p><img src="/mac5856/assets/images/t5_6_proxy_running.png" alt="email proxy" /></p>

<p>Após isso rodei o comando <code class="language-plaintext highlighter-rouge">kw send-patch --send --private --to='felipe.souza1506@outlook.com'</code> e confirmei o conteúdo do patch pelo editor nano:</p>

<p><img src="/mac5856/assets/images/t5_6_patch_content.png" alt="patch content" /></p>

<p>E então… tive um problema com a autenticação do e-mail USP:</p>

<p><img src="/mac5856/assets/images/t5_6_erro_autenticacao.png" alt="patch content" /></p>

<p>Que foi resolvido rapidamente pelo monitor da diciplina, aparentemente era uma questão de cadastro relacionado ao meu e-mail USP. Então tentando novamente tive a confirmação de sucesso no log do servidor proxy:</p>

<p><img src="/mac5856/assets/images/t5_6_autenticado_proxy.png" alt="log do servidor proxy" /></p>

<p>E a confirmação do kw informando que o e-mail foi enviado:</p>

<p><img src="/mac5856/assets/images/t5_6_email_enviado.png" alt="patch content" /></p>

<p>Então fui verificar a caixa de entrada do e-mail e o patch estava lá!</p>

<p><img src="/mac5856/assets/images/t5_6_email_recebido.png" alt="patch content" /></p>

<h4 id="extra"><strong>Extra!</strong></h4>

<p>Os comandos utilizados pelo tutorial para subir o servidor proxy necessitam de dois terminais abertos ao mesmo tempo, o que pode ser um pouco incoveniente para quem está realizando o tutorial. Por isso tomei a liberdade para editar um pouco as configurações do compose para que esse segundo terminal pudesse ser extinto.</p>

<h4 id="isso-é-possivel-de-duas-maneiras"><strong>Isso é possivel de duas maneiras:</strong></h4>

<h4 id="1º"><strong>1º:</strong></h4>

<p>Adicionando o comando a ser excutado diretamente no <code class="language-plaintext highlighter-rouge">docker-compose.yaml</code></p>

<div class="language-diff highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">services:
</span>  server:
<span class="gi">+   command: ["emailproxy", "--no-gui", "--external-auth", "--config-file", "/app/emailproxy.config"]
</span>    build: .
    ports:
      - "2587:2587"
    stdin_open: true
    tty: true
    volumes:
      - ./emailproxy.config:/app/emailproxy.config
</code></pre></div></div>

<p>E então subir o container utilizando o seguinte comando:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker compose run <span class="nt">--service-ports</span> <span class="nt">--build</span> server 
</code></pre></div></div>

<h4 id="2º">2º:</h4>

<p>Caso a edição do arquivo não seja desejada, é possível fazer a mesma coisa atráves do comando:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker compose run <span class="nt">--service-ports</span> <span class="nt">--build</span> server emailproxy <span class="nt">--no-gui</span> <span class="nt">--external-auth</span> <span class="nt">--config-file</span> /app/emailproxy.config
</code></pre></div></div>

<h4 id="explicação"><strong>Explicação:</strong></h4>

<p>O comando original <a href="https://docs.docker.com/reference/cli/docker/compose/up/">docker compose up</a> sobe todos services configurados e agrega o output de cada container em um único terminal, ignorando os inputs.</p>

<p>Já o comando <a href="https://docs.docker.com/reference/cli/docker/compose/run/">docker compose run</a> sobe apenas um único service, passado por parametro para o comando, e por isso é possível utilizar o stdin para interagir com o container. O parâmetro –service-ports serve para criar e mapear as portas declaradas.</p>

<h4 id="fim"><strong>Fim</strong></h4>

<p>Esses foram os valiosos aprendizados desta semana, até a próxima pessoal :)</p>]]></content><author><name></name></author><category term="jekyll" /><category term="update" /><summary type="html"><![CDATA[Link para o Tutorial 5: Sending patches by email with git]]></summary></entry><entry><title type="html">Relato Tutorial 4</title><link href="/mac5856/jekyll/update/2026/03/20/tutorial-4.html" rel="alternate" type="text/html" title="Relato Tutorial 4" /><published>2026-03-20T22:00:00+00:00</published><updated>2026-03-20T22:00:00+00:00</updated><id>/mac5856/jekyll/update/2026/03/20/tutorial-4</id><content type="html" xml:base="/mac5856/jekyll/update/2026/03/20/tutorial-4.html"><![CDATA[<p>Link para o Tutorial 4: <a href="https://flusp.ime.usp.br/kernel/char-drivers-intro/">Introduction to Linux kernel Character Device Drivers</a></p>

<p>Depois desse tutorial entendemos um pouco mais a frase “Tudo no Linux é um arquivo”, a final é nesse tutorial que aprendemos sobre os chamados <code class="language-plaintext highlighter-rouge">Linux character devices</code>, que são arquivos especiais utilizados para fazer a comunicação entre o espaço do usuário e o kernel. Também desenvolvemos o nosso primeiro <code class="language-plaintext highlighter-rouge">driver</code> para interagir com um desses “arquivos”.</p>

<p>Como nesse tutorial não tive nenhum problema para seguir os passos vou registar aqui tudo funcionando localmente.</p>

<p>O driver desenvolvido, <code class="language-plaintext highlighter-rouge">simple_char</code>, não faz muito mais do que tranferir informações de texto entre o espaço do usuário e um buffer no espaço do sistema, através de um character device. Podemos testar isso com auxilio dos scripts fornecidos pelo tutorial <code class="language-plaintext highlighter-rouge">read_prog</code> e <code class="language-plaintext highlighter-rouge">write_prog</code>:</p>

<p><img src="/mac5856/assets/images/t4_initial_driver_working.png" alt="simple_char working" /></p>

<h4 id="proposed-exercices"><strong>Proposed Exercices</strong></h4>

<ol>
  <li>
    <p>Printing device numbers: Modify the simple_char driver to make it print major and minor device numbers on device open.</p>

    <p>After a little bit of research I found that the device numbers are stored in the inode structure, so I modified the <code class="language-plaintext highlighter-rouge">simple_char_open</code> function to print the major and minor numbers from inode pointer using the functions MAJOR and MINOR. Here is the modified code:</p>

    <div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="p">...</span>
 <span class="k">static</span> <span class="kt">int</span> <span class="nf">simple_char_open</span><span class="p">(</span><span class="k">struct</span> <span class="n">inode</span> <span class="o">*</span><span class="n">inode</span><span class="p">,</span> <span class="k">struct</span> <span class="n">file</span> <span class="o">*</span><span class="n">file</span><span class="p">)</span>
 <span class="p">{</span>
     <span class="kt">int</span> <span class="n">major_num</span> <span class="o">=</span> <span class="n">MAJOR</span><span class="p">(</span><span class="n">inode</span><span class="o">-&gt;</span><span class="n">i_rdev</span><span class="p">);</span>
     <span class="kt">int</span> <span class="n">minor_num</span> <span class="o">=</span> <span class="n">MINOR</span><span class="p">(</span><span class="n">inode</span><span class="o">-&gt;</span><span class="n">i_rdev</span><span class="p">);</span>
     <span class="n">pr_info</span><span class="p">(</span><span class="s">"%s: MAJOR: %d MINOR: %d %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">KBUILD_MODNAME</span><span class="p">,</span> <span class="n">major_num</span><span class="p">,</span> <span class="n">minor_num</span><span class="p">,</span> <span class="n">__func__</span><span class="p">);</span>
     <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
 <span class="p">}</span>
 <span class="p">...</span>
</code></pre></div>    </div>

    <p>After recompiling and installing the module, I ran the test scripts again and got the following output in the kernel log:</p>

    <p><img src="/mac5856/assets/images/t4_major_minor_on_log.png" alt="major and minor numbers on dmesg log" /></p>
  </li>
  <li>
    <p>Device private data: Modify the simple_char driver to register more than one minor device number and make it keep separate buffers for each of them. Check the device minor number on device open and allocate a buffer for it if it doesn’t have one. Also, make the read/write operations run over the buffer for the particular major/minor device number pair. Access <code class="language-plaintext highlighter-rouge">f_inode</code> field of <code class="language-plaintext highlighter-rouge">struct file</code> to get a pointer to the device inode then access <code class="language-plaintext highlighter-rouge">i_rdev</code> field of <code class="language-plaintext highlighter-rouge">struct inode</code> to get the device ID (<code class="language-plaintext highlighter-rouge">dev_t</code>) from which you can extract the device minor number. On module unload, free all allocated buffers. With that, we can think of each pair of major/minor numbers as a different character device and each of them will have their own data. Finally, create device nodes with different minor numbers to test you implementation.</p>

    <p>This one was a little bit more tricky, but i managed to implement it by creating a array of buffers, one for each minor number. After modifing all the functions except simple_char_release, the code looks like this:</p>

    <div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="cp">#include</span> <span class="cpf">&lt;linux/init.h&gt;</span><span class="cp">
</span> <span class="cp">#include</span> <span class="cpf">&lt;linux/module.h&gt;</span><span class="cp">
</span>
 <span class="cp">#include</span> <span class="cpf">&lt;linux/kdev_t.h&gt;</span><span class="c1"> /* for MAJOR */</span><span class="cp">
</span> <span class="cp">#include</span> <span class="cpf">&lt;linux/cdev.h&gt;</span><span class="c1"> /* for cdev */</span><span class="cp">
</span> <span class="cp">#include</span> <span class="cpf">&lt;linux/fs.h&gt;</span><span class="c1"> /* for chrdev functions */</span><span class="cp">
</span> <span class="cp">#include</span> <span class="cpf">&lt;linux/slab.h&gt;</span><span class="c1"> /* for malloc */</span><span class="cp">
</span> <span class="cp">#include</span> <span class="cpf">&lt;linux/string.h&gt;</span><span class="c1"> /* for strlen() */</span><span class="cp">
</span> <span class="cp">#include</span> <span class="cpf">&lt;linux/uaccess.h&gt;</span><span class="c1"> /* copy_to_user() */</span><span class="cp">
</span>
 <span class="k">struct</span> <span class="n">cdev</span> <span class="o">*</span><span class="n">s_cdev</span><span class="p">;</span>
 <span class="k">static</span> <span class="n">dev_t</span> <span class="n">dev_id</span><span class="p">;</span>

 <span class="cp">#define S_BUFF_SIZE 4096
</span>
 <span class="cp">#define MINOR_NUMS 2
</span>
 <span class="k">static</span> <span class="kt">char</span> <span class="o">*</span><span class="n">s_bufs</span><span class="p">[</span><span class="n">MINOR_NUMS</span><span class="p">];</span>

 <span class="k">static</span> <span class="kt">int</span> <span class="nf">simple_char_open</span><span class="p">(</span><span class="k">struct</span> <span class="n">inode</span> <span class="o">*</span><span class="n">inode</span><span class="p">,</span> <span class="k">struct</span> <span class="n">file</span> <span class="o">*</span><span class="n">file</span><span class="p">)</span>
 <span class="p">{</span>
     <span class="kt">int</span> <span class="n">major_num</span> <span class="o">=</span> <span class="n">MAJOR</span><span class="p">(</span><span class="n">inode</span><span class="o">-&gt;</span><span class="n">i_rdev</span><span class="p">);</span>
     <span class="kt">int</span> <span class="n">minor_num</span> <span class="o">=</span> <span class="n">MINOR</span><span class="p">(</span><span class="n">inode</span><span class="o">-&gt;</span><span class="n">i_rdev</span><span class="p">);</span>
     <span class="n">pr_info</span><span class="p">(</span><span class="s">"%s: MAJOR: %d MINOR: %d %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">KBUILD_MODNAME</span><span class="p">,</span> <span class="n">major_num</span><span class="p">,</span> <span class="n">minor_num</span><span class="p">,</span> <span class="n">__func__</span><span class="p">);</span>
     <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">s_bufs</span><span class="p">[</span><span class="n">minor_num</span><span class="p">])</span> <span class="p">{</span>
         <span class="n">s_bufs</span><span class="p">[</span><span class="n">minor_num</span><span class="p">]</span> <span class="o">=</span> <span class="n">kmalloc</span><span class="p">(</span><span class="n">S_BUFF_SIZE</span><span class="p">,</span> <span class="n">GFP_KERNEL</span><span class="p">);</span>
         <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">s_bufs</span><span class="p">[</span><span class="n">minor_num</span><span class="p">])</span>
             <span class="k">return</span> <span class="o">-</span><span class="n">ENOMEM</span><span class="p">;</span>

         <span class="n">snprintf</span><span class="p">(</span><span class="n">s_bufs</span><span class="p">[</span><span class="n">minor_num</span><span class="p">],</span> <span class="n">S_BUFF_SIZE</span><span class="p">,</span> <span class="s">"This is data from simple_char buffer. MAJOR: %d MINOR: %d"</span><span class="p">,</span> <span class="n">major_num</span><span class="p">,</span> <span class="n">minor_num</span><span class="p">);</span>
         <span class="n">pr_info</span><span class="p">(</span><span class="s">"%s: MAJOR: %d MINOR: %d %s Allocated new buffer for minor %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">KBUILD_MODNAME</span><span class="p">,</span> <span class="n">major_num</span><span class="p">,</span> <span class="n">minor_num</span><span class="p">,</span> <span class="n">__func__</span><span class="p">,</span> <span class="n">minor_num</span><span class="p">);</span>
     <span class="p">}</span>
     <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
 <span class="p">}</span>

 <span class="k">static</span> <span class="kt">ssize_t</span> <span class="nf">simple_char_read</span><span class="p">(</span><span class="k">struct</span> <span class="n">file</span> <span class="o">*</span><span class="n">file</span><span class="p">,</span> <span class="kt">char</span> <span class="n">__user</span> <span class="o">*</span><span class="n">buffer</span><span class="p">,</span>
                 <span class="kt">size_t</span> <span class="n">count</span><span class="p">,</span> <span class="n">loff_t</span> <span class="o">*</span><span class="n">ppos</span><span class="p">)</span>
 <span class="p">{</span>
     <span class="kt">int</span> <span class="n">minor_num</span> <span class="o">=</span> <span class="n">MINOR</span><span class="p">(</span><span class="n">file</span><span class="o">-&gt;</span><span class="n">f_inode</span><span class="o">-&gt;</span><span class="n">i_rdev</span><span class="p">);</span>
     <span class="kt">int</span> <span class="n">n_bytes</span><span class="p">;</span>
     <span class="n">pr_info</span><span class="p">(</span><span class="s">"%s: %s about to read %ld bytes from buffer position %lld</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span>
         <span class="n">KBUILD_MODNAME</span><span class="p">,</span> <span class="n">__func__</span><span class="p">,</span> <span class="n">count</span><span class="p">,</span> <span class="o">*</span><span class="n">ppos</span><span class="p">);</span>
     <span class="n">n_bytes</span> <span class="o">=</span> <span class="n">count</span> <span class="o">-</span> <span class="n">copy_to_user</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="n">s_bufs</span><span class="p">[</span><span class="n">minor_num</span><span class="p">]</span> <span class="o">+</span> <span class="o">*</span><span class="n">ppos</span><span class="p">,</span> <span class="n">count</span><span class="p">);</span>
     <span class="o">*</span><span class="n">ppos</span> <span class="o">+=</span> <span class="n">n_bytes</span><span class="p">;</span>
     <span class="k">return</span> <span class="n">n_bytes</span><span class="p">;</span>
 <span class="p">}</span>

 <span class="k">static</span> <span class="kt">ssize_t</span> <span class="nf">simple_char_write</span><span class="p">(</span><span class="k">struct</span> <span class="n">file</span> <span class="o">*</span><span class="n">file</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="n">__user</span> <span class="o">*</span><span class="n">buffer</span><span class="p">,</span>
                 <span class="kt">size_t</span> <span class="n">count</span><span class="p">,</span> <span class="n">loff_t</span> <span class="o">*</span><span class="n">ppos</span><span class="p">)</span>
 <span class="p">{</span>
     <span class="kt">int</span> <span class="n">minor_num</span> <span class="o">=</span> <span class="n">MINOR</span><span class="p">(</span><span class="n">file</span><span class="o">-&gt;</span><span class="n">f_inode</span><span class="o">-&gt;</span><span class="n">i_rdev</span><span class="p">);</span>
     <span class="kt">int</span> <span class="n">n_bytes</span><span class="p">;</span>
     <span class="n">pr_info</span><span class="p">(</span><span class="s">"%s: %s about to write %ld bytes to buffer position %lld</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span>
         <span class="n">KBUILD_MODNAME</span><span class="p">,</span> <span class="n">__func__</span><span class="p">,</span> <span class="n">count</span><span class="p">,</span> <span class="o">*</span><span class="n">ppos</span><span class="p">);</span>
     <span class="n">n_bytes</span> <span class="o">=</span> <span class="n">count</span> <span class="o">-</span> <span class="n">copy_from_user</span><span class="p">(</span><span class="n">s_bufs</span><span class="p">[</span><span class="n">minor_num</span><span class="p">]</span> <span class="o">+</span> <span class="o">*</span><span class="n">ppos</span><span class="p">,</span> <span class="n">buffer</span><span class="p">,</span> <span class="n">count</span><span class="p">);</span>
     <span class="k">return</span> <span class="n">n_bytes</span><span class="p">;</span>
 <span class="p">}</span>

 <span class="k">static</span> <span class="kt">int</span> <span class="nf">simple_char_release</span><span class="p">(</span><span class="k">struct</span> <span class="n">inode</span> <span class="o">*</span><span class="n">inode</span><span class="p">,</span> <span class="k">struct</span> <span class="n">file</span> <span class="o">*</span><span class="n">file</span><span class="p">)</span>
 <span class="p">{</span>
     <span class="n">pr_info</span><span class="p">(</span><span class="s">"%s: %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">KBUILD_MODNAME</span><span class="p">,</span> <span class="n">__func__</span><span class="p">);</span>
     <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
 <span class="p">}</span>

 <span class="k">static</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">file_operations</span> <span class="n">simple_char_fops</span> <span class="o">=</span> <span class="p">{</span>
     <span class="p">.</span><span class="n">owner</span> <span class="o">=</span> <span class="n">THIS_MODULE</span><span class="p">,</span>
     <span class="p">.</span><span class="n">open</span> <span class="o">=</span> <span class="n">simple_char_open</span><span class="p">,</span>
     <span class="p">.</span><span class="n">release</span> <span class="o">=</span> <span class="n">simple_char_release</span><span class="p">,</span>
     <span class="p">.</span><span class="n">read</span> <span class="o">=</span> <span class="n">simple_char_read</span><span class="p">,</span>
     <span class="p">.</span><span class="n">write</span> <span class="o">=</span> <span class="n">simple_char_write</span><span class="p">,</span>
 <span class="p">};</span>

 <span class="k">static</span> <span class="kt">int</span> <span class="n">__init</span> <span class="nf">simple_char_init</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
 <span class="p">{</span>
     <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span>

     <span class="n">pr_info</span><span class="p">(</span><span class="s">"Initialize %s module.</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">KBUILD_MODNAME</span><span class="p">);</span>

     <span class="cm">/* Dynamically allocate character device device numbers. */</span>
     <span class="cm">/* The name passed here will appear in /proc/devices. */</span>
     <span class="n">ret</span> <span class="o">=</span> <span class="n">alloc_chrdev_region</span><span class="p">(</span><span class="o">&amp;</span><span class="n">dev_id</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">MINOR_NUMS</span><span class="p">,</span> <span class="s">"simple_char"</span><span class="p">);</span>
     <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span>
         <span class="k">return</span> <span class="n">ret</span><span class="p">;</span>

     <span class="cm">/* Allocate and initialize the character device cdev structure */</span>
     <span class="n">s_cdev</span> <span class="o">=</span> <span class="n">cdev_alloc</span><span class="p">();</span>
     <span class="n">s_cdev</span><span class="o">-&gt;</span><span class="n">ops</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">simple_char_fops</span><span class="p">;</span>
     <span class="n">s_cdev</span><span class="o">-&gt;</span><span class="n">owner</span> <span class="o">=</span> <span class="n">simple_char_fops</span><span class="p">.</span><span class="n">owner</span><span class="p">;</span>

     <span class="cm">/* Adds a mapping for the device ID into the system. */</span>
     <span class="k">return</span> <span class="n">cdev_add</span><span class="p">(</span><span class="n">s_cdev</span><span class="p">,</span> <span class="n">dev_id</span><span class="p">,</span> <span class="n">MINOR_NUMS</span><span class="p">);</span>
 <span class="p">}</span>

 <span class="k">static</span> <span class="kt">void</span> <span class="n">__exit</span> <span class="nf">simple_char_exit</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
 <span class="p">{</span>
     <span class="cm">/*
     * Undoes the device ID mapping and frees cdev struct, removing the
     * character device from the system.
     */</span>
     <span class="n">cdev_del</span><span class="p">(</span><span class="n">s_cdev</span><span class="p">);</span>
     <span class="cm">/* Unregisters (disassociate) the device numbers allocated. */</span>
     <span class="n">unregister_chrdev_region</span><span class="p">(</span><span class="n">dev_id</span><span class="p">,</span> <span class="n">MINOR_NUMS</span><span class="p">);</span>

     <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">MINOR_NUMS</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
         <span class="k">if</span> <span class="p">(</span><span class="n">s_bufs</span><span class="p">[</span><span class="n">i</span><span class="p">])</span> <span class="p">{</span>
             <span class="n">kfree</span><span class="p">(</span><span class="n">s_bufs</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
             <span class="n">pr_info</span><span class="p">(</span><span class="s">"%s: The buffer for minor %d is free</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">KBUILD_MODNAME</span><span class="p">,</span> <span class="n">i</span><span class="p">);</span>
         <span class="p">}</span>
     <span class="p">}</span>
     <span class="n">pr_info</span><span class="p">(</span><span class="s">"%s exiting.</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">KBUILD_MODNAME</span><span class="p">);</span>
 <span class="p">}</span>

 <span class="n">module_init</span><span class="p">(</span><span class="n">simple_char_init</span><span class="p">);</span>
 <span class="n">module_exit</span><span class="p">(</span><span class="n">simple_char_exit</span><span class="p">);</span>

 <span class="n">MODULE_AUTHOR</span><span class="p">(</span><span class="s">"felipers@ime.usp.br"</span><span class="p">);</span>
 <span class="n">MODULE_DESCRIPTION</span><span class="p">(</span><span class="s">"A simple character device driver example."</span><span class="p">);</span>
 <span class="n">MODULE_LICENSE</span><span class="p">(</span><span class="s">"GPL"</span><span class="p">);</span>
</code></pre></div>    </div>

    <p>Despite the new stuff, I also had to change <code class="language-plaintext highlighter-rouge">strcpy</code> to <code class="language-plaintext highlighter-rouge">snprintf</code> in simple_char_open function, beacuse I wanted to print major and minor numbers on the buffer and strcpy doesn’t format the string:</p>

    <p><img src="/mac5856/assets/images/t4_erro_strcpy.png" alt="strcpy error" /></p>

    <p>After recompiling and installing the module, I created two device nodes with different minor numbers to test the implementation:</p>

    <p><img src="/mac5856/assets/images/t4_multiple_minors.png" alt="driver running using multiple minors" /></p>
  </li>
</ol>]]></content><author><name></name></author><category term="jekyll" /><category term="update" /><summary type="html"><![CDATA[Link para o Tutorial 4: Introduction to Linux kernel Character Device Drivers]]></summary></entry><entry><title type="html">Relato Tutorial 3</title><link href="/mac5856/jekyll/update/2026/03/12/tutorial-3.html" rel="alternate" type="text/html" title="Relato Tutorial 3" /><published>2026-03-12T22:00:00+00:00</published><updated>2026-03-12T22:00:00+00:00</updated><id>/mac5856/jekyll/update/2026/03/12/tutorial-3</id><content type="html" xml:base="/mac5856/jekyll/update/2026/03/12/tutorial-3.html"><![CDATA[<p>Link para o Tutorial 3: <a href="https://flusp.ime.usp.br/kernel/modules-intro/">Introduction to Linux kernel build configuration and modules</a></p>

<p>No tutorial 3 aprendemos a criar módulos que podem ser “acoplados” no kernel linux.</p>

<p>Seguindo o conceito do blog vou discorrer apenas sobre os pontos do tutorial em que tive algum tipo de problema.</p>

<h4 id="passo-2"><strong>Passo 2:</strong></h4>

<p>Esse não é bem um problema em si, mas o tutorial informa que os registros nos arquivos Kconfig e Makefile devem estar em ordem alfabética, porém os arquivos originais já estavam fora de ordem, então apenas inseri as novas configurações no inicio de cada um.</p>

<h4 id="passo-3"><strong>Passo 3:</strong></h4>

<p>Ao Executar <code class="language-plaintext highlighter-rouge">make -C "$IIO_TREE" menuconfig</code> reparei que a opção apresentada no tutorial <code class="language-plaintext highlighter-rouge">Simple Test Module</code> não estava disponível então selecionei a opção <code class="language-plaintext highlighter-rouge">Simple exemple Linux Kernel module (NEW)</code>:
<img src="/mac5856/assets/images/t3_simple_exemple_module.png" alt="Opção Simple exemple Linux Kernel module (NEW)" />
Então segui o tutorial até o momento de instalar os novos módulos, mas quando executei o seguinte comando:</p>

<figure class="highlight"><pre><code class="language-shell" data-lang="shell"><span class="nb">sudo </span>guestmount <span class="nt">--rw</span> <span class="nt">--add</span> <span class="s2">"</span><span class="k">${</span><span class="nv">VM_DIR</span><span class="k">}</span><span class="s2">/arm64_img.qcow2"</span> <span class="nt">--mount</span> /dev/&lt;rootfs&gt; <span class="s2">"</span><span class="k">${</span><span class="nv">VM_DIR</span><span class="k">}</span><span class="s2">/arm64_rootfs"</span></code></pre></figure>

<p>Fui agraciado com o seguinte erro:
<img src="/mac5856/assets/images/t3_erro_guestmount.png" alt="erro no comando guestmount" />
Tentei exportar as variáveis de debug mas o erro continou o mesmo, ai notei que a minha VM estava rodando, então desliguei ela e tentei rodar novamente, funcionou!</p>

<p>Seguindo os comandos bloco…Tive um problema no unmount <code class="language-plaintext highlighter-rouge">sudo guestunmount "$VM_MOUNT_POINT"</code>:
<img src="/mac5856/assets/images/t3_erro_guestunmount.png" alt="erro no comando guestunmount" /></p>

<p>Já que a variável VM_MOUNT_POINT não existe, o comando correto é o:</p>

<figure class="highlight"><pre><code class="language-shell" data-lang="shell"><span class="nb">sudo </span>guestunmount <span class="s2">"</span><span class="k">${</span><span class="nv">VM_DIR</span><span class="k">}</span><span class="s2">/arm64_rootfs"</span> </code></pre></figure>

<h4 id="passo-4"><strong>Passo 4:</strong></h4>

<p>Todos os comandos rodaram sem problemas, vou deixar aqui um print do módulo funcionando:
<img src="/mac5856/assets/images/t3_modulo.png" alt="log do modulo simple_mod" /></p>

<h4 id="passo-5"><strong>Passo 5:</strong></h4>

<p>Ao executar o comando <code class="language-plaintext highlighter-rouge">make -C "$IIO_TREE" menuconfig</code> para configurar o simple_mod_part, selecionei a opção:
<img src="/mac5856/assets/images/t3_menuconfig_simple_mod_part.png" alt="erro no comando guestunmount" />
Dai para frente não tive mais problemas para seguir o tutorial e consegui executar o simple_mod_part com sucesso dentro da VM.
<img src="/mac5856/assets/images/t3_modpart.png" alt="log do modulo simple_mod_part" /></p>

<h4 id="proposed-exercices"><strong>Proposed Exercices</strong></h4>

<ol>
  <li>
    <p>The .config file that comes with the arm64 VM is bloated with features built together with the kernel image (y config value) which is why even after <code class="language-plaintext highlighter-rouge">make localmodconfig</code> the .config file did not reduce significantly and the build took a lot of time. Run <code class="language-plaintext highlighter-rouge">make allmodconfig</code> to turn builtin configuration values into module values when possible. After that, boot the VM, regenerate the list of needed modules as described in Part 1, run <code class="language-plaintext highlighter-rouge">make localmodconfig</code> with new list of modules. Did it reduce .config size further? How much? Does the whole kernel build take less time with the new .config? Does the resulting kernel still boot?</p>

    <p>.config size before the exercise: 179Kb <br />
 .config size after <code class="language-plaintext highlighter-rouge">make allmodconfig</code>: 419K <br />
 .config size after <code class="language-plaintext highlighter-rouge">make localmodconfig</code> with new list of modules: 204K <br />
 If we compare the final size with the initial size it actualy got bigger, but if we compare with the size of .config with all the modules enabled it got ~51% smaller. <br />
 Build time before the exercise: ~6:30 <br />
 Final build time: ~8:40 <br />
 Yes, the result kernel still boots, but I cant connect to it neither using <code class="language-plaintext highlighter-rouge">sudo virsh connect arm64</code> nor <code class="language-plaintext highlighter-rouge">kw ssh</code>.
 <img src="/mac5856/assets/images/t3_new_vm.png" alt="cant connect to new vm" /></p>
  </li>
  <li>
    <p>Sometimes developers lose track of what .config was used to generate a running kernel after messing arround for enough time. The in kernel configuration config (IKCONFIG) exports (imports?) the .config file used to build the kernel into the kernel image and make it later availabe as /proc/config.gz file. Enable IKCONFIG, rebuild the kernel and read your .config from /proc/config.gz within the VM.</p>

    <p>In my case IKCONFIG was already enabled, so i just needed to read the file inside the VM:
 <img src="/mac5856/assets/images/t3_vm_dotconfig.png" alt="vm .config" /></p>
  </li>
  <li>
    <p>Customize the log messages for simple_mod and simple_mod_part. Add <code class="language-plaintext highlighter-rouge">#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt</code> at the top of the module source files. KBUILD_MODNAME will expand to the module source file name resulting in every message logged through <code class="language-plaintext highlighter-rouge">pr_info()</code> (and friends) being prepended by the module name. See include/linux/printk.h for documentation. Tip, add the above define before header inclusions to avoid build warnings.</p>

    <p>No problems with these, here is the logs:
 <img src="/mac5856/assets/images/t3_module_name.png" alt="modules names" /></p>
  </li>
</ol>

<h3 id="considerações-finais"><strong>Considerações finais</strong></h3>
<p>Achei interessante a maneira que o kernel lida com novos módulos e como podemos ver eles sendo executados.</p>]]></content><author><name></name></author><category term="jekyll" /><category term="update" /><summary type="html"><![CDATA[Link para o Tutorial 3: Introduction to Linux kernel build configuration and modules]]></summary></entry><entry><title type="html">Relato Tutorial 2</title><link href="/mac5856/jekyll/update/2026/03/09/tutorial-2.html" rel="alternate" type="text/html" title="Relato Tutorial 2" /><published>2026-03-09T22:00:00+00:00</published><updated>2026-03-09T22:00:00+00:00</updated><id>/mac5856/jekyll/update/2026/03/09/tutorial-2</id><content type="html" xml:base="/mac5856/jekyll/update/2026/03/09/tutorial-2.html"><![CDATA[<p>Link para o Tutorial 2: <a href="https://flusp.ime.usp.br/kernel/build-linux-for-arm-kw/">Building and booting a custom Linux kernel for ARM using kw</a></p>

<p>Nesse tutorial aprendemos a compilar o kernel linux e depois realizar um boot em um máquina virtual utilizando esse kernel.</p>

<p>Seguindo o conceito do blog vou discorrer apenas sobre os pontos do tutorial em que tive algum tipo de problema.</p>

<h4 id="passo-3"><strong>Passo 3:</strong></h4>

<p>Na primeira vez que segui o tutorial defini o IP da VM para o IP obtido através do comando:</p>

<figure class="highlight"><pre><code class="language-shell" data-lang="shell"><span class="nb">sudo </span>virsh net-dhcp-leases default</code></pre></figure>

<p>Que dentre as outras informações retornados, temos o IP 192.168.122.24/24, então rodei:</p>

<figure class="highlight"><pre><code class="language-shell" data-lang="shell">kw remote <span class="nt">--add</span> arm64 root@192.168.122.24 <span class="nt">--set-default</span></code></pre></figure>

<p>Segui o tutorial até o passo 5 mas precisei desligar a minha máquina para tratar de outro assunto, quando retomei o tutorial notei que o comando <code class="language-plaintext highlighter-rouge">kw ssh</code> estava falhando pois o IP definido não estava correto, executei o comando <code class="language-plaintext highlighter-rouge">sudo virsh net-dhcp-leases default</code> novamente o obtive o IP 192.168.122.166. Então configurei o kw para utilizar o novo IP:</p>

<figure class="highlight"><pre><code class="language-shell" data-lang="shell">kw remote <span class="nt">--add</span> arm64 root@192.168.122.166 <span class="nt">--set-default</span></code></pre></figure>

<h4 id="passo-4"><strong>Passo 4:</strong></h4>

<p>Ao executar o comando <code class="language-plaintext highlighter-rouge">kw ssh --get '~/vm_mod_list'</code> me deparei com o seguinte erro:</p>

<figure class="highlight"><pre><code class="language-shell" data-lang="shell">bash: line 1: rsync: <span class="nb">command </span>not found
rsync: connection unexpectedly closed <span class="o">(</span>0 bytes received so far<span class="o">)</span> <span class="o">[</span>Receiver]
rsync error: error <span class="k">in </span>rsync protocol data stream <span class="o">(</span>code 12<span class="o">)</span> at io.c<span class="o">(</span>232<span class="o">)</span> <span class="o">[</span><span class="nv">Receiver</span><span class="o">=</span>3.2.7]
An error occurred <span class="k">while </span>uploading the file<span class="o">(</span>s<span class="o">)</span><span class="nb">.</span> rsync <span class="k">return </span>code: 12</code></pre></figure>

<p>Após uma breve pesquisa entendi que isso estava ocrrendo pela falta da ferramenta <code class="language-plaintext highlighter-rouge">rsync</code> na VM, o que foi rapidamente resolvido através da instalação da mesma:</p>

<figure class="highlight"><pre><code class="language-shell" data-lang="shell"><span class="nb">sudo </span>apt update
<span class="nb">sudo </span>apt <span class="nb">install </span>rsync</code></pre></figure>

<h4 id="passo-6"><strong>Passo 6:</strong></h4>

<p>Ao executar <code class="language-plaintext highlighter-rouge">kw deploy --modules</code> me deparei com alguns erros além dos erros apontados pelas ferramentas <code class="language-plaintext highlighter-rouge">strip</code> e <code class="language-plaintext highlighter-rouge">make</code>:</p>

<p><img src="/mac5856/assets/images/t2_kw_deploy_error.png" alt="log mostrando erro rodar kw deploy --modules" /></p>

<p>Mas o deploy finalizou com sucesso.</p>

<p>De inicio achei que o boot utilizando o novo kernel não tinha funcionado, pois fiz as alterações nos scripts <code class="language-plaintext highlighter-rouge">launch_vm_qemu</code> e <code class="language-plaintext highlighter-rouge">create_vm_virsh</code> e quando executei as funções não obtive nenhum log. O que me fez “criar” mais duas funções <code class="language-plaintext highlighter-rouge">launch_vm_qemu_original</code> e <code class="language-plaintext highlighter-rouge">create_vm_virsh_original</code> que utilizam o kernel obtido da imagem baixada no <a href="/mac5856/jekyll/update/2026/03/05/tutorial-1.html">Tutorial 1</a> e essas rodaram com sucesso. O que me fez pensar que o novo kernel poderia estar com problema, então refiz o tutorial para garantir que não pulei nenhuma etapa e mesmo assim o problema continou. A solução para esse caso é subir a VM e aguardar alguns momentos, já que não sabemos o que está acontecendo pela falta de logs, então entrar nela via ssh para verificar que novo kernel estava lá:</p>

<p><img src="/mac5856/assets/images/t2_vm_new_kernel.png" alt="evidência de filesystem compartilhado" /></p>

<h3 id="considerações-finais"><strong>Considerações finais</strong></h3>
<p>Achei o tutorial bem explicativo, no geral nenhum dos problemas encontrados foi complicado de resolver.</p>]]></content><author><name></name></author><category term="jekyll" /><category term="update" /><summary type="html"><![CDATA[Link para o Tutorial 2: Building and booting a custom Linux kernel for ARM using kw]]></summary></entry><entry><title type="html">Relato Tutorial 1</title><link href="/mac5856/jekyll/update/2026/03/05/tutorial-1.html" rel="alternate" type="text/html" title="Relato Tutorial 1" /><published>2026-03-05T22:00:00+00:00</published><updated>2026-03-05T22:00:00+00:00</updated><id>/mac5856/jekyll/update/2026/03/05/tutorial-1</id><content type="html" xml:base="/mac5856/jekyll/update/2026/03/05/tutorial-1.html"><![CDATA[<p>Link para o Tutorial 1: <a href="https://flusp.ime.usp.br/kernel/qemu-libvirt-setup/">Setting up a test environment for Linux Kernel Dev using QEMU and libvirt</a></p>

<p>Como o próprio nome já diz, o primeiro tutorial nos ensina a realizar o setup inical do QEMU e do libvirt para desenvolvimento do Kernel Linux.</p>
<ul>
  <li><a href="https://www.qemu.org/">QEMU</a>: Emulador utilizado para subir máquinas virtuais.</li>
  <li><a href="https://libvirt.org/">libvirt</a>: Gerenciador de máquinas virtuais.</li>
  <li><a href="https://github.com/torvalds/linux">Kernel Linux</a>: Núcleo utilizado por diversos sistemas operacionais.</li>
</ul>

<p>Já que a finalidade desse blog é contar como foi a minha experiência seguindo o tutorial, vamos lá…</p>

<h5 id="ps-vou-fazer-comentários-apenas-sobre-os-passos-em-que-tive-algum-tipo-de-problema"><strong>PS:</strong> Vou fazer comentários apenas sobre os passos em que tive algum tipo de problema.</h5>

<h4 id="passo-1"><strong>Passo 1:</strong></h4>

<p>Tive problemas para inserir o usuário no grupo libvirt-qemu. No tutorial é informado que basta fazer logout + login e seguir, mas precisei reiniciar minha máquina para que as configurações fossem persistidas.</p>

<h4 id="passo-2"><strong>Passo 2:</strong></h4>

<p><strong>Passo 2.1:</strong> O único problema que tive foi para baixar a imagem. A imagem informada no tutorial não está mais disponível, então baixei a <a href="http://cdimage.debian.org/cdimage/cloud/bookworm/daily/latest/debian-12-nocloud-arm64-daily.qcow2">http://cdimage.debian.org/cdimage/cloud/bookworm/daily/latest/debian-12-nocloud-arm64-daily.qcow2</a>.</p>

<p><strong>Passo 2.3:</strong> cometi um erro no script launch_vm_qemu, invés de vda2 coloquei &lt;vda2&gt; sem perceber, ai estava tomando o seguinte erro:</p>

<figure class="highlight"><pre><code class="language-shell" data-lang="shell">...
Begin: Running /scripts/local-block ... <span class="k">done</span><span class="nb">.</span>
Begin: Running /scripts/local-block ... <span class="k">done</span><span class="nb">.</span>
Begin: Running /scripts/local-block ... <span class="k">done</span><span class="nb">.</span>
Begin: Running /scripts/local-block ... <span class="k">done</span><span class="nb">.</span>
Begin: Running /scripts/local-block ... <span class="k">done</span><span class="nb">.</span>
Begin: Running /scripts/local-block ... <span class="k">done</span><span class="nb">.</span>
<span class="k">done</span><span class="nb">.</span>
Gave up waiting <span class="k">for </span>root file system device.  Common problems:
 - Boot args <span class="o">(</span><span class="nb">cat</span> /proc/cmdline<span class="o">)</span>
   - Check <span class="nv">rootdelay</span><span class="o">=</span> <span class="o">(</span>did the system <span class="nb">wait </span>long enough?<span class="o">)</span>
 - Missing modules <span class="o">(</span><span class="nb">cat</span> /proc/modules<span class="p">;</span> <span class="nb">ls</span> /dev<span class="o">)</span>
ALERT!  /dev/&lt;vda2&gt; does not exist.  Dropping to a shell!
<span class="o">(</span>initramfs<span class="o">)</span> ^[[Aqemu-system-aarch64: terminating on signal 15 from pid 9100 <span class="o">()</span></code></pre></figure>

<p>Acabei demorando um pouco para perceber que o erro era por conta dos sinais de maior que e menor que. Mas no final consegui subir a vm com sucesso:
<img src="/mac5856/assets/images/t1_vm.png" alt="vm rodando em um terminal" /></p>

<h4 id="passo-3"><strong>Passo 3:</strong></h4>
<p>Para que esse passo desse certo precisei instalar o openssh-server na vm e iniciar o serviço do ssh:</p>

<figure class="highlight"><pre><code class="language-shell" data-lang="shell"><span class="nb">sudo </span>apt-get update
<span class="nb">sudo </span>apt-get <span class="nb">install </span>openssh-server
<span class="nb">sudo </span>systemctl <span class="nb">enable </span>ssh</code></pre></figure>

<h4 id="passo-5"><strong>Passo 5:</strong></h4>
<p>Fiquei um pouco confuso sobre onde era para rodar o comando, já que no tutoral não existe indicação de @host nem de @VM no snippet:</p>

<figure class="highlight"><pre><code class="language-shell" data-lang="shell"><span class="nb">sudo </span><span class="nv">EDITOR</span><span class="o">=</span>vim<span class="p">;</span> <span class="nb">sudo </span>virsh edit iio-arm64</code></pre></figure>

<p>Porém fica evidente que deveria ser no host devido ao uso do comando virsh.</p>

<p>Além disso o nome <code class="language-plaintext highlighter-rouge">io-arm64</code> não segue o padrão <code class="language-plaintext highlighter-rouge">arm64</code> adotado no resto do tutorial, o que também deixa um pouco confuso.</p>

<p>Após rodar o comando e instalar o virtiofs no host tive que reiniciar a vm para que a configuração do filesystem compartilhado fosse persistida. O que funcionou perfeitamente:</p>

<p><img src="/mac5856/assets/images/t1_shared_fs.png" alt="evidência de filesystem compartilhado" /></p>

<h3 id="considerações-finais"><strong>Considerações finais</strong></h3>
<p>Achei o tutorial bem explicativo, no geral nenhum dos problemas encontrados foi complicado de resolver.</p>]]></content><author><name></name></author><category term="jekyll" /><category term="update" /><summary type="html"><![CDATA[Link para o Tutorial 1: Setting up a test environment for Linux Kernel Dev using QEMU and libvirt]]></summary></entry></feed>