<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>MacOS | FoxTechWorld</title><link>https://foxtechworld.github.io/tags/macos/</link><description>Conteúdo recente em MacOS no FoxTechWorld.</description><language>pt-BR</language><copyright>KitsuneSemCalda (CC BY 4.0)</copyright><lastBuildDate>Sat, 15 Aug 2026 00:00:00 -0300</lastBuildDate><generator>Hugo</generator><atom:link href="https://foxtechworld.github.io/tags/macos/" rel="self" type="application/rss+xml"/><item><title>OSDev: até onde dá para usar C++?</title><link>https://foxtechworld.github.io/osdev-ate-onde-da-para-usar-c/</link><guid isPermaLink="true">https://foxtechworld.github.io/osdev-ate-onde-da-para-usar-c/</guid><pubDate>Mon, 22 Sep 2025 15:33:40 -0300</pubDate><description>Veja quais recursos de C++ podem ser usados no desenvolvimento de um kernel e quais partes da runtime precisam ser implementadas pelo sistema operacional.</description><category>Programação</category><category>OSDev</category><category>OSDev</category><category>C++</category><category>Cpp</category><category>Kernel</category><category>Linux</category><category>Windows</category><category>MacOS</category><content:encoded><![CDATA[<p>Estou desenvolvendo um <a href="https://pt.wikipedia.org/wiki/N%C3%BAcleo_(sistema_operacional)">kernel</a> chamado <a href="https://github.com/KitsuneBSD/FKernel">FKernel</a>.</p>
<p>Para uso desktop em código x86_64.</p>
<p>E lendo sobre algumas linguagens como <strong><em>Rust</em></strong>, <strong><em>C</em></strong>, <strong><em>C++</em></strong>, <strong><em>Zig</em></strong> &hellip;</p>
<p>Decidi fazer uma combinação de:</p>
<ul>
<li>Linguagens de Programação:
<ul>
<li>C</li>
<li>C++</li>
</ul>
</li>
<li>Linguagem de montagem:
<ul>
<li>Nasm</li>
</ul>
</li>
</ul>
<p>Obviamente alguns podem estranhar já que eu propositalmente ignorei Rust, e aquelas que são considerados &ldquo;memory-safe&rdquo;.</p>
<h2 id="por-que-não-usar-linguagens-memory-safe">Por que não usar linguagens <em>memory-safe</em>?</h2>
<p>Pro Tip: Não existe linguagem memory-safe em baixo nível. Para programar um kernel ou similar, você vai depender do unsafe então nem tenta.</p>
<p>Se for para ter que lidar com sintaxes estranhas para programar um kernel, eu prefiro seguir no bom e velho C/C++.</p>
<p>Também não quero fazer um overflow de logs de um compilador super-nanny para chegar a um subset daquilo que eu queria no meu código.</p>
<h2 id="e-por-que-c">E por que C++?</h2>
<p>Muito tempo atrás Linus Torvalds havia tentado escrever um kernel com a versão de sua época.</p>
<blockquote>
<p>C++ leads to really, really bad design choices. You invariably start using the STL, boost, and other total and utter crap…</p>
</blockquote>
<p>Ok, podemos concordar em algumas partes mas, isso não seria inevitavelmente ruim.</p>
<p>Sim, C++ tem um monte de coisa, mas fugiria do ponto principal que é C++ dá contratos que structs sozinhas dificilmente conseguem.</p>
<p>Pegue um exemplo do <code>SerenityOS</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c++" data-lang="c++"><span class="line"><span class="cl"><span class="k">static</span> <span class="n">ErrorOr</span><span class="o">&lt;</span><span class="n">NonnullOwnPtr</span><span class="o">&lt;</span><span class="n">KBuffer</span><span class="o">&gt;&gt;</span> <span class="n">try_create_with_size</span><span class="p">(</span><span class="n">StringView</span> <span class="n">name</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="n">size_t</span> <span class="n">size</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="n">Memory</span><span class="o">::</span><span class="n">Region</span><span class="o">::</span><span class="n">Access</span> <span class="n">access</span> <span class="o">=</span> <span class="n">Memory</span><span class="o">::</span><span class="n">Region</span><span class="o">::</span><span class="n">Access</span><span class="o">::</span><span class="n">ReadWrite</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="n">AllocationStrategy</span> <span class="n">strategy</span> <span class="o">=</span> <span class="n">AllocationStrategy</span><span class="o">::</span><span class="n">Reserve</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">  <span class="k">auto</span> <span class="n">rounded_size</span> <span class="o">=</span> <span class="n">TRY</span><span class="p">(</span><span class="n">Memory</span><span class="o">::</span><span class="n">page_round_up</span><span class="p">(</span><span class="n">size</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">  <span class="k">auto</span> <span class="n">region</span> <span class="o">=</span> <span class="n">TRY</span><span class="p">(</span><span class="n">MM</span><span class="p">.</span><span class="n">allocate_kernel_region</span><span class="p">(</span><span class="n">rounded_size</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">access</span><span class="p">,</span> <span class="n">strategy</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="nf">TRY</span><span class="p">(</span><span class="n">adopt_nonnull_own_or_enomem</span><span class="p">(</span><span class="k">new</span> <span class="p">(</span><span class="n">nothrow</span><span class="p">)</span> <span class="n">KBuffer</span> <span class="p">{</span> <span class="n">size</span><span class="p">,</span> <span class="n">move</span><span class="p">(</span><span class="n">region</span><span class="p">)</span> <span class="p">}));</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Consegue entender o que esse código faz? Todo esse contrato engloba em poucas linhas</p>
<blockquote>
<p>Essa função try_create_with_size serve para criar um buffer de memória no kernel de um tamanho específico e lidar com possíveis erros de forma segura.</p>
</blockquote>
<p>Para termos o equivalente exato em C garantindo a mesma segurança seria necessária escrever dessa forma.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-C" data-lang="C"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">try_create_with_size</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">name</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                         <span class="kt">size_t</span> <span class="n">size</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                         <span class="n">MemoryAccess</span> <span class="n">access</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                         <span class="n">AllocationStrategy</span> <span class="n">strategy</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                         <span class="n">KBuffer</span><span class="o">**</span> <span class="n">out_buffer</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">out_buffer</span><span class="p">)</span> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kt">size_t</span> <span class="n">rounded_size</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">rc</span> <span class="o">=</span> <span class="nf">page_round_up</span><span class="p">(</span><span class="n">size</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">rounded_size</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">rc</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span> <span class="n">rc</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">MemoryRegion</span><span class="o">*</span> <span class="n">region</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">rc</span> <span class="o">=</span> <span class="nf">allocate_kernel_region</span><span class="p">(</span><span class="n">rounded_size</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">access</span><span class="p">,</span> <span class="n">strategy</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">region</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">rc</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span> <span class="n">rc</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">KBuffer</span><span class="o">*</span> <span class="n">buffer</span> <span class="o">=</span> <span class="nf">malloc</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="n">KBuffer</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">buffer</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">free</span><span class="p">(</span><span class="n">region</span><span class="o">-&gt;</span><span class="n">addr</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="nf">free</span><span class="p">(</span><span class="n">region</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="o">-</span><span class="n">ENOMEM</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">buffer</span><span class="o">-&gt;</span><span class="n">size</span> <span class="o">=</span> <span class="n">size</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">buffer</span><span class="o">-&gt;</span><span class="n">region</span> <span class="o">=</span> <span class="n">region</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="o">*</span><span class="n">out_buffer</span> <span class="o">=</span> <span class="n">buffer</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// sucesso
</span></span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Ok, tivemos uma disparidade no tamanho, mas isso não significa nada no geral.</p>
<p>Meu ponto defendido é que precisamos fazer muito mais código, que vai ser muito mais performático mas que vai resultar em um resultado muito menos seguro, e muito menos reusável no geral.</p>
<p>Não ironicamente, muitos empresas incluindo a própria Apple usam o C++ em seus kernels.</p>
<p>Mas não precisa ser o c++ inteiro e sim um subset chamado <a href="https://en.wikipedia.org/wiki/Embedded_C%2B%2B"><strong><em>embedded c++</em></strong></a>.</p>
<h3 id="implementação-do-iokit">Implementação do IOKit</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c++" data-lang="c++"><span class="line"><span class="cl"><span class="cm">/*
</span></span></span><span class="line"><span class="cl"><span class="cm"> * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
</span></span></span><span class="line"><span class="cl"><span class="cm"> *
</span></span></span><span class="line"><span class="cl"><span class="cm"> * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
</span></span></span><span class="line"><span class="cl"><span class="cm"> *
</span></span></span><span class="line"><span class="cl"><span class="cm"> * This file contains Original Code and/or Modifications of Original Code
</span></span></span><span class="line"><span class="cl"><span class="cm"> * as defined in and that are subject to the Apple Public Source License
</span></span></span><span class="line"><span class="cl"><span class="cm"> * Version 2.0 (the &#39;License&#39;). You may not use this file except in
</span></span></span><span class="line"><span class="cl"><span class="cm"> * compliance with the License. The rights granted to you under the License
</span></span></span><span class="line"><span class="cl"><span class="cm"> * may not be used to create, or enable the creation or redistribution of,
</span></span></span><span class="line"><span class="cl"><span class="cm"> * unlawful or unlicensed copies of an Apple operating system, or to
</span></span></span><span class="line"><span class="cl"><span class="cm"> * circumvent, violate, or enable the circumvention or violation of, any
</span></span></span><span class="line"><span class="cl"><span class="cm"> * terms of an Apple operating system software license agreement.
</span></span></span><span class="line"><span class="cl"><span class="cm"> *
</span></span></span><span class="line"><span class="cl"><span class="cm"> * Please obtain a copy of the License at
</span></span></span><span class="line"><span class="cl"><span class="cm"> * http://www.opensource.apple.com/apsl/ and read it before using this file.
</span></span></span><span class="line"><span class="cl"><span class="cm"> *
</span></span></span><span class="line"><span class="cl"><span class="cm"> * The Original Code and all software distributed under the License are
</span></span></span><span class="line"><span class="cl"><span class="cm"> * distributed on an &#39;AS IS&#39; basis, WITHOUT WARRANTY OF ANY KIND, EITHER
</span></span></span><span class="line"><span class="cl"><span class="cm"> * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
</span></span></span><span class="line"><span class="cl"><span class="cm"> * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
</span></span></span><span class="line"><span class="cl"><span class="cm"> * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
</span></span></span><span class="line"><span class="cl"><span class="cm"> * Please see the License for the specific language governing rights and
</span></span></span><span class="line"><span class="cl"><span class="cm"> * limitations under the License.
</span></span></span><span class="line"><span class="cl"><span class="cm"> *
</span></span></span><span class="line"><span class="cl"><span class="cm"> * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cp">#ifndef _IOKIT_IONVRAMCONTROLLER_H
</span></span></span><span class="line"><span class="cl"><span class="cp">#define _IOKIT_IONVRAMCONTROLLER_H
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;IOKit/IOService.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">IONVRAMController</span> <span class="o">:</span> <span class="k">public</span> <span class="n">IOService</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="n">OSDeclareAbstractStructors</span><span class="p">(</span><span class="n">IONVRAMController</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">	<span class="k">virtual</span> <span class="kt">void</span> <span class="n">registerService</span><span class="p">(</span><span class="n">IOOptionBits</span> <span class="n">options</span> <span class="o">=</span> <span class="mi">0</span><span class="p">)</span> <span class="n">APPLE_KEXT_OVERRIDE</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="k">virtual</span> <span class="kt">void</span> <span class="nf">sync</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="k">virtual</span> <span class="n">IOReturn</span> <span class="nf">select</span><span class="p">(</span><span class="kt">uint32_t</span> <span class="n">bank</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="k">virtual</span> <span class="n">IOReturn</span> <span class="nf">eraseBank</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="k">virtual</span> <span class="n">IOReturn</span> <span class="nf">read</span><span class="p">(</span><span class="n">IOByteCount</span> <span class="n">offset</span><span class="p">,</span> <span class="n">UInt8</span> <span class="o">*</span><span class="n">buffer</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">	    <span class="n">IOByteCount</span> <span class="n">length</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">	<span class="k">virtual</span> <span class="n">IOReturn</span> <span class="nf">write</span><span class="p">(</span><span class="n">IOByteCount</span> <span class="n">offset</span><span class="p">,</span> <span class="n">UInt8</span> <span class="o">*</span><span class="n">buffer</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">	    <span class="n">IOByteCount</span> <span class="n">length</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cp">#endif </span><span class="cm">/* !_IOKIT_IONVRAMCONTROLLER_H */</span><span class="cp">
</span></span></span></code></pre></div><p>Quem diria.</p>
<p>Se fossemos falar do C++ antes da versão 17, eu até concordaria mas após a versão 17 muita coisa mudou.</p>
<p>E veja que o IOKit é implementado na forma Embedded C++.</p>
<p>Mas, e como em tudo há um mas, há em real,o ponto da STL que invariavelmente você vai acabar usando ou não.</p>
<h3 id="realmente-preciso-do-stl">Realmente preciso do STL?</h3>
<p>No fringir dos ovos há um outro superset de C++ chamado <a href="https://terminalroot.com.br/2023/07/conheca-o-cpp-ortodoxo.html"><strong><em>c++ ortodoxo</em></strong></a> jamais o use, sério.</p>
<p>Uma das soluções que o FKernel e o SerenityOS fazem é criar sua própria STL.</p>
<p>O SerenityOS com sua <strong>Abstraction Kit</strong>.
E o FKernel com seu <strong>LibFK</strong>.</p>
<p>Usar uma STL não é de todo mal, há diversos efeitos, como otimização em cascata.</p>
<p>Genericos e todo resto.</p>
<h2 id="e-no-fim">E no fim?</h2>
<p>No fim, depende de você.</p>
<p>Se você está desenvolvendo um app para desktop.</p>
<p>Eu sugeriria:</p>
<ul>
<li><a href="https://pt.wikipedia.org/wiki/D_(linguagem_de_programa%C3%A7%C3%A3o)">D</a></li>
<li><a href="https://pt.wikipedia.org/wiki/Go_(linguagem_de_programa%C3%A7%C3%A3o)">Go</a></li>
<li><a href="https://pt.wikipedia.org/wiki/Zig_(linguagem_de_programa%C3%A7%C3%A3o)">Zig</a></li>
<li><a href="https://pt.wikipedia.org/wiki/Rust_(linguagem_de_programa%C3%A7%C3%A3o)">Rust</a></li>
</ul>
<p>Para baixo nível certamente eu sugeriria:</p>
<ul>
<li><a href="https://pt.wikipedia.org/wiki/B_(linguagem_de_programa%C3%A7%C3%A3o)">B</a></li>
<li><a href="https://pt.wikipedia.org/wiki/C_(linguagem_de_programa%C3%A7%C3%A3o)">C</a>,</li>
<li><a href="https://pt.wikipedia.org/wiki/C%2B%2B">C++</a></li>
<li><a href="https://pt.wikipedia.org/wiki/D_(linguagem_de_programa%C3%A7%C3%A3o)">D</a></li>
<li><a href="https://pt.wikipedia.org/wiki/Rust_(linguagem_de_programa%C3%A7%C3%A3o)">Rust</a></li>
<li><a href="https://pt.wikipedia.org/wiki/Zig_(linguagem_de_programa%C3%A7%C3%A3o)">Zig</a></li>
</ul>
<p>Mas em kernel estou muito mais satisfeito com minha escolha do que usar C puro.</p>
<p>Não que eu não use C obviamente, por baixo dos panos da LibFK eu implementei uma LibC bem simples com funções que eu teria que usar dentro do FKernel para algumas funções da LibFK.</p>
<p>Mas enfim, se uma linguagem que você prefere usar por algum motivo de design ou simplesmente por ser a que você sabe, simplesmente use.</p>
<p>Desde que não seja usar algo interpretado para fazer baixo nível, tá valendo tudo.</p>
]]></content:encoded></item></channel></rss>