<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Wu Yuwei</title>
    <link rel="self" type="application/atom+xml" href="https://wusyong.github.io/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://wusyong.github.io"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2025-07-09T16:55:00+08:00</updated>
    <id>https://wusyong.github.io/atom.xml</id>
    <entry xml:lang="en">
        <title>Can we use Wasmtime to build web script engine?</title>
        <published>2025-07-09T16:55:00+08:00</published>
        <updated>2025-07-09T16:55:00+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/posts/wasmtime-script-engine/"/>
        <id>https://wusyong.github.io/posts/wasmtime-script-engine/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/posts/wasmtime-script-engine/">&lt;p&gt;A few years ago, there was a discussion around Servo community about using alternative Javascript engine instead of
SpiderMonkey. While Servo has a solid bindings to SpiderMonkey, we have to deal with several issues along with it.
Servo creates its own fork called &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/mozjs&quot;&gt;mozjs&lt;/a&gt; with patches it needs. At that time, people
were wondering if there could be a better option. Or, even better, to see if Servo can make script engine pluggable and
switch to others like V8. But in the end, we stick to existing choice and keep maintaining mozjs.&lt;/p&gt;
&lt;p&gt;For me, I had a wilder idea in my mind back then: What if we could use a Webassembly runtime directly to build a script
engine? I know mojarity of browsers can load Webassembly modules already. However, they can&#39;t access to most DOM
objects and WebAPIs directly. You will need to add bindings to Webassembly modules to actually obtain those features.
What if there&#39;s a script engine built on top of Webassembly directly? This way, all languages could be the first
class citizen when using Web browsers!&lt;/p&gt;
&lt;p&gt;Unfortunately, at that time, I found out Webassembly hasn&#39;t completed the spec of &lt;a rel=&quot;external&quot; href=&quot;https://github.com/WebAssembly/gc&quot;&gt;GC&lt;/a&gt; yet. It is
necessary for building DOM node tree due to its design nature. DOM objects can reference each other pretty
easily. It&#39;s pretty common to see a node link to its child, while its child link to its parent. So we must have a
garbage collector that can trace these objects. So eventually, I kept the idea for future me to worry.&lt;/p&gt;
&lt;p&gt;And a couple of weeks ago, I found that Wasmtime has completed the &lt;a rel=&quot;external&quot; href=&quot;https://bytecodealliance.org/articles/wasmtime-27.0&quot;&gt;Wasm GC support&lt;/a&gt;
already! So I believe it&#39;s time to explore this idea again. In this post, I&#39;ll share my current progress, explain
possible design, and what&#39;s next for future roadmap.&lt;/p&gt;
&lt;h2 id=&quot;dom-objects-in-wasm-gc&quot;&gt;DOM &lt;code&gt;Object&lt;/code&gt;s in Wasm GC&lt;/h2&gt;
&lt;p&gt;If you want to understand Wasmtime&#39;s GC types in details, Their &lt;a rel=&quot;external&quot; href=&quot;https://github.com/bytecodealliance/rfcs/blob/main/accepted/wasm-gc.md&quot;&gt;RFC repository&lt;/a&gt;
has a whole page to explain them exhaustively. What we want to know here is what will the definition of DOM object look
like when using these GC types. And the choice is its reference types, more precisely, &lt;a rel=&quot;external&quot; href=&quot;https://docs.rs/wasmtime/latest/wasmtime/struct.ExternRef.html&quot;&gt;ExternRef&lt;/a&gt; type.
The usage of &lt;code&gt;ExternRef&lt;/code&gt; is pretty straight forward. We call the &lt;code&gt;new&lt;/code&gt; method with provided value and we will get
&lt;code&gt;Rooted&amp;lt;ExternRef&amp;gt;&lt;/code&gt;. The only problem is the type annotation will be eliminated upon &lt;code&gt;ExternRef&lt;/code&gt; creation. You can see
this type doesn&#39;t hold any generic. So in my attempt, I create a new type for it to contain the type information along
with several utility methods:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5E81AC;&quot;&gt;#[derive(&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Copy&lt;/span&gt;&lt;span style=&quot;color: #5E81AC;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Debug&lt;/span&gt;&lt;span style=&quot;color: #5E81AC;&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;pub struct&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Object&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Any&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Send&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Sync&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    object&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Rooted&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;ExternRef&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    _phantom&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; PhantomData&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that we can still access &lt;code&gt;Rooted&amp;lt;ExternRef&amp;gt;&lt;/code&gt; through dereference. But this type helps us understand underlying
implementation when defining new DOM objects. We will see more examples with it in later section of the post.&lt;/p&gt;
&lt;h2 id=&quot;reflector-in-wasm-component&quot;&gt;Reflector in Wasm Component&lt;/h2&gt;
&lt;p&gt;Before we can dive deeper into DOM object implementation details, we need to determine how reflector in Wasm works. When
a browser creates a DOM object, it needs a reflector object that can be used in script side. For Servo, you can read its
&lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/blob/main/components/script/docs/JS-Servos-only-GC.md&quot;&gt;script crate&#39;s documentation&lt;/a&gt; to
understand how Servo uses SpiderMonkey&#39;s types to achieve it. For Wasm, each language usually provide codegen or binding
libraries to help us instantiate the Wasm module. Take Rust&#39;s &lt;code&gt;wasm-bindgen&lt;/code&gt; as an example. When we build a wasm module
through &lt;code&gt;wasm-bindgen&lt;/code&gt;, it will also generate Javascript/Typescript bindings script to instantiage the module. But
there&#39;s a major issue, these binding codes can vary between different libraries. And this kind of defeat the purpose to
make every language as first class citizen of the script engine. We can&#39;t just choose certain framework to define the
reflector bindings.&lt;/p&gt;
&lt;p&gt;Fortunately, this seems to be what WebAssembly community faces as well, and they propose another concept called
&lt;a rel=&quot;external&quot; href=&quot;https://component-model.bytecodealliance.org/design/why-component-model.html&quot;&gt;Wasm Component Model&lt;/a&gt;. You can think it&#39;s
like another kind of Wasm module, but it has a pre-defined set called &lt;a rel=&quot;external&quot; href=&quot;https://component-model.bytecodealliance.org/design/wit.html&quot;&gt;WIT(Wasm Interface Type)&lt;/a&gt;.
Let&#39;s say we want to define &lt;a rel=&quot;external&quot; href=&quot;https://dom.spec.whatwg.org/#document&quot;&gt;Document&lt;/a&gt; WebIDL interface. We can define it through
&lt;code&gt;resource&lt;/code&gt; type. This is a type that only exposes behaviour through methods. We can think it as a object that implement
an interface. To define &lt;code&gt;Document&lt;/code&gt; in &lt;code&gt;resource&lt;/code&gt; type, it can be listed as following:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;wit&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;interface&lt;/span&gt;&lt;span&gt; node&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    resource&lt;/span&gt;&lt;span&gt; node&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;        append-child&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: func&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;child&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span&gt; node&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span&gt; node;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    resource&lt;/span&gt;&lt;span&gt; document&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;        constructor&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;()&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;        url&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: func&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span&gt; string;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;        document-element&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: func&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span&gt; option&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;element&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    resource&lt;/span&gt;&lt;span&gt; element&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;        has-attributes&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: func&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span&gt; bool;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since this is for demo purpose, I won&#39;t explain all concepts of WIT and every steps on how to use it. Instead,
I&#39;ll only list out the necessary methods that could explain our proof of concept. In this
example, we define resources &lt;code&gt;node&lt;/code&gt;, &lt;code&gt;document&lt;/code&gt; and &lt;code&gt;element&lt;/code&gt;. They are corresponding to &lt;code&gt;Node&lt;/code&gt;, &lt;code&gt;Document&lt;/code&gt; and &lt;code&gt;Element&lt;/code&gt; as
DOM objects. I would like to showcase that once we get a &lt;code&gt;document&lt;/code&gt;, we can use it to call several methods, including
methods that can get another DOM objects linked to it. The &lt;code&gt;document-element&lt;/code&gt; will return &lt;code&gt;option&amp;lt;element&amp;gt;&lt;/code&gt; which &lt;code&gt;element&lt;/code&gt;
is another &lt;code&gt;resource&lt;/code&gt; represent as another DOM object. Next, we will demonstrate how to
implement the detail in &lt;strong&gt;Host side&lt;/strong&gt;, and then use it in the script side. Or in Wasm&#39;s term, script side is usually called
&lt;strong&gt;Guest side&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;implement-resources-in-host-side&quot;&gt;Implement Resources in Host Side&lt;/h2&gt;
&lt;p&gt;To get the bindings from the host side, Wasmtime provides &lt;code&gt;bindgen!&lt;/code&gt; macro to generate the code based on provided WIT
files. What we care the most is what are the exact type of each &lt;code&gt;resource&lt;/code&gt; we will define. Let&#39;s we already have a few
types called &lt;code&gt;Node&lt;/code&gt;, &lt;code&gt;Document&lt;/code&gt;, &lt;code&gt;Element&lt;/code&gt; (We will further explain their details later). They can be specified in the
macro as following:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;wasmtime&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;component&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt;bindgen!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    path&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;wit&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    with&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;        &amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;ohim:dom/node/node&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Node&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;        &amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;ohim:dom/node/document&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Document&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;        &amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;ohim:dom/node/element&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Element&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    trappable_imports&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: true&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;&quot;ohim:dom/node/node&quot;&lt;/code&gt; is the full path to &lt;code&gt;node&lt;/code&gt; resource we defined in WIT file. In the bindgen macro, we
specify the exact implementation type of &lt;code&gt;document&lt;/code&gt; is &lt;code&gt;Document&lt;/code&gt;. And then the macro will generate a &lt;code&gt;HostDocument&lt;/code&gt;
trait with all related method defined. Our job is to fulfill all these resource traits. Now, it&#39;s time to see what&#39;s
inside of the DOM objects and how do we implement to those resource traits.&lt;/p&gt;
&lt;h3 id=&quot;node-and-nodeimpl&quot;&gt;&lt;code&gt;Node&lt;/code&gt; and &lt;code&gt;NodeImpl&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;As we mentioned above, we intend to use &lt;code&gt;Object&amp;lt;T&amp;gt;&lt;/code&gt; to define DOM Object. For &lt;code&gt;Node&lt;/code&gt; type, it will basically be a new
type of &lt;code&gt;Object&amp;lt;T&amp;gt;&lt;/code&gt; with &lt;code&gt;NodeImpl&lt;/code&gt; as the actual data:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;pub struct&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Node&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Object&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;NodeImpl&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;pub struct&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; NodeImpl&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    event_target&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; EventTarget&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    parent_node&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Option&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Node&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    first_child&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Option&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Node&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    last_child&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Option&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Node&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    next_sibling&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Option&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Node&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    pub&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;crate&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span&gt; data&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; NodeTypeData&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let&#39;s focus on fields related to &lt;code&gt;Node&lt;/code&gt; and itself first. &lt;code&gt;Node&lt;/code&gt; is a GC object which can be created by &lt;code&gt;Object::new&lt;/code&gt;.
And this method is essentially a &lt;code&gt;ExterRef::new&lt;/code&gt;. All the implement details are in &lt;code&gt;NodeImpl&lt;/code&gt;. &lt;code&gt;Node&lt;/code&gt; will
become an opaque GC rooted reference to the public, so users can have confident to link it to anywhere without worrying
circular reference. You can see &lt;code&gt;NodeImpl&lt;/code&gt;&#39;s node fields like &lt;code&gt;parent_node&lt;/code&gt; would take a &lt;code&gt;Option&amp;lt;Node&amp;gt;&lt;/code&gt;. When we
implement the methods, we just need to get the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/wusyong/ohim/blob/9540476082be776eb4804cf77788a7fcfda9e66c/src/node.rs#L66&quot;&gt;&lt;code&gt;NodeImpl&lt;/code&gt; data&lt;/a&gt;
from one &lt;code&gt;Node&lt;/code&gt; and link the other one to it.&lt;/p&gt;
&lt;h3 id=&quot;inherent-node&quot;&gt;Inherent &lt;code&gt;Node&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Next, let&#39;s talk about inherence. We know &lt;code&gt;Document&lt;/code&gt; and &lt;code&gt;Element&lt;/code&gt; need to inherent &lt;code&gt;Node&lt;/code&gt;, but neither Rust nor Wasm
component have builtin support to it. I&#39;ve thought about similar casting mechanism like Servo did based on SpiderMonkey.
However, it resolves with tons of unsafe usage and it still bothers us when we need to implement some complicated types
in script crate. Wasmtime already provide pretty safe and ergonomic APIs to use. I feel like we should chase for same
direction as well. So I decided to make types who inherent ancestor type as a sum type which is the &lt;code&gt;NodeTypeData&lt;/code&gt;
listed in &lt;code&gt;NodeImpl&lt;/code&gt;&#39;s definition:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;pub enum&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; NodeTypeData&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;    /// `ELEMENT_NODE`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;    Element&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;ElementImpl&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;    /// `DOCUMENT_NODE`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;    Document&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;DocumentImpl&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;    /// Similar to `Option::None`.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;    None&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With &lt;code&gt;From&lt;/code&gt; trait implements to related DOM Object new types and methods that are exclusive to these
types to get the deeper Impl types, it should be possible for a DOM Object casts to correct type and use the right
implementation data.&lt;/p&gt;
&lt;h3 id=&quot;implement-resource-traits&quot;&gt;Implement resource traits&lt;/h3&gt;
&lt;p&gt;Now we have explained the definition of DOM Objects and their implementation details. It&#39;s time to implement to resource
traits generated from &lt;code&gt;bindgen!&lt;/code&gt;, so the Guest script side can actually use these types. Let&#39;s use &lt;code&gt;HostDocument&lt;/code&gt; to
demonstrate because it can showcase how to implement the constructor and also showcase how to link an object to the other:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;/// `Store` states to use when `[Exposed=Window]`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;pub struct&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; WindowStates&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    table&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; ResourceTable&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ctx&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; WasiCtx&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    store&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Store&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;()&amp;gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;impl&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; HostDocument&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; for&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; WindowStates&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;amp;mut self&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Result&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Resource&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Document&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;        // This is only for demo purpose&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;        let&lt;/span&gt;&lt;span&gt; element&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Element&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;amp;mut self.&lt;/span&gt;&lt;span&gt;store&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;        let&lt;/span&gt;&lt;span&gt; document&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Document&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;amp;mut self.&lt;/span&gt;&lt;span&gt;store&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        document&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;            .&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;data_mut&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;amp;mut self.&lt;/span&gt;&lt;span&gt;store&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;            .&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;as_document_mut&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;            .&lt;/span&gt;&lt;span&gt;document_element &lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Some&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;element&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;        Ok&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;self.&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;document&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; drop&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;amp;mut self&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; rep&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Resource&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Document&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Result&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;()&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;        self.&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;delete&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;rep&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;        Ok&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;    // ...other methods&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To implement traits, we need to define a state data that can put into Wasmtime&#39;s &lt;a rel=&quot;external&quot; href=&quot;https://docs.rs/wasmtime/latest/wasmtime/struct.Store.html&quot;&gt;Store&lt;/a&gt;.
I found this is perfect match to WebIDL&#39;s extend attribute &lt;code&gt;Exposed&lt;/code&gt; as we can decide which WebIDL interfaces can
expose to certain target. In this example, we want to expose to &lt;code&gt;Window&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you look at the signature of &lt;code&gt;new&lt;/code&gt; and &lt;code&gt;drop&lt;/code&gt;, you can see what Wasm component provides to guest side isn&#39;t the
actual object. Instead, it returns a &lt;code&gt;Resource&amp;lt;T&amp;gt;&lt;/code&gt;. You can think this type as a handle. We will put the actual data
that say &lt;code&gt;Document&lt;/code&gt; into &lt;code&gt;ResourceTable&lt;/code&gt;, and it will return &lt;code&gt;Resource&amp;lt;Document&amp;gt;&lt;/code&gt;. And the guest will use it to call
all methods related to this resource. For example, if the guest want to call &lt;code&gt;document-element&lt;/code&gt;, it will use this
handle to call the method. What we need to do is implement the trait method to get the actual object from the table,
get the &lt;code&gt;Element&lt;/code&gt; object it wants, and then return the &lt;code&gt;Resource&amp;lt;Element&amp;gt;&lt;/code&gt; handle it needs:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; document_element&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;amp;mut self&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; self_&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Resource&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Document&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Result&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Option&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Resource&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Element&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;&amp;gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    let&lt;/span&gt;&lt;span&gt; self_&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; = self.&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;self_&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    match&lt;/span&gt;&lt;span&gt; self_&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;document_element&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;amp;self.&lt;/span&gt;&lt;span&gt;store&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;        Some&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Ok&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Some&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;self.&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;        None&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Ok&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;None&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With all necessary resource traits implemented, it&#39;s now possible to create a wasm component and use these host
resources! There&#39;s &lt;a rel=&quot;external&quot; href=&quot;https://github.com/bytecodealliance/cargo-component&quot;&gt;cargo-component&lt;/a&gt; tool that can compile your
crate into a Wasm component. In the code, we just need to use &lt;code&gt;wit_bindgen&lt;/code&gt; to get all the WIT bindings we need:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;// cargo component build&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;wit_bindgen&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt;generate!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    path&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;../wit/&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    world&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;imports&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;struct&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; GuestComponent&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt;export!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;GuestComponent&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;impl&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Guest&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; for&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; GuestComponent&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; test&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; String&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;        let&lt;/span&gt;&lt;span&gt; document&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span&gt; dom&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;node&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Document&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;        let&lt;/span&gt;&lt;span&gt; element&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span&gt; document&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;document_element&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt;        format!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;            &amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;Document has url: &lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt;{}&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; with element has attributes: &lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt;{}&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            document&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;url&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            element&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;unwrap&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;has_attributes&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;        )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;eventtarget-as-a-field&quot;&gt;&lt;code&gt;EventTarget&lt;/code&gt; As a field&lt;/h3&gt;
&lt;p&gt;Last, we need to talk about &lt;code&gt;EventTarget&lt;/code&gt;. If you look at the definition of &lt;code&gt;NodeImpl&lt;/code&gt; mentioned above. you can see I
treat &lt;code&gt;EventTarget&lt;/code&gt; as a field instead of making all other &lt;code&gt;Impl&lt;/code&gt; types into a sum type of &lt;code&gt;EventTarget&lt;/code&gt;. The reason of
this choice is because there are &lt;a rel=&quot;external&quot; href=&quot;https://dontcallmedom.github.io/webidlpedia/names/EventTarget.html&quot;&gt;hundreds of WebIDL interfaces&lt;/a&gt;
inherent &lt;code&gt;EventTarget&lt;/code&gt;. The main reason they need &lt;code&gt;EventTarget&lt;/code&gt; is because they can be added to &lt;code&gt;EventListner&lt;/code&gt;.
Otherwise, they don&#39;t share any similarity with each other. So I decided to make it as a field instead to prevent endless
casting starting from it. &lt;code&gt;Node&lt;/code&gt;, on the other hand, has more frequent requirement to update its &lt;code&gt;Node&lt;/code&gt; tree. Many
interfaces who inherent it will usually edit its node pretty oftehn. So I think defining sum type for it is more justified.
&lt;code&gt;EventTarget&lt;/code&gt; will probably be the only special case here.&lt;/p&gt;
&lt;p&gt;There&#39;s also another issue that WIT spec currently hasn&#39;t support &lt;a rel=&quot;external&quot; href=&quot;https://github.com/WebAssembly/component-model/issues/223&quot;&gt;function callback&lt;/a&gt; yet.
The closest thing is scoped callbacks mentioned from the link, but it&#39;s still far away. So right now, I define &lt;code&gt;EventListner&lt;/code&gt;
as good old &lt;code&gt;FnMut&lt;/code&gt; that can import/export to Wasm module. Hopefully, WIT reference can be expanded in the near future.
Or perhaps Wasm component can get some features from Wasm module that can pass &lt;code&gt;func&lt;/code&gt; directly.&lt;/p&gt;
&lt;h2 id=&quot;next-steps&quot;&gt;Next steps&lt;/h2&gt;
&lt;p&gt;So that&#39;s all the code I&#39;d like to explain. Full example can be viewed in &lt;a rel=&quot;external&quot; href=&quot;https://github.com/wusyong/ohim&quot;&gt;Ohim&lt;/a&gt; repository.
For the next steps, I wish to collect feedback and starting to evolve current example into full &lt;a rel=&quot;external&quot; href=&quot;https://dom.spec.whatwg.org/#concept-node-tree&quot;&gt;Node tree&lt;/a&gt;.
Either it can be an alternative script backend or not, I plan to reuse as many Servo components as possible. Once we
have minimum functioning script engine, I would try to pass the tree to Servo&#39;s &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/tree/main/components/layout&quot;&gt;layout&lt;/a&gt;.
And hopefully, it can generate the display list and ask Servo&#39;s &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/webrender&quot;&gt;webrender&lt;/a&gt; to render the webpage!
The road is still far far away. But it seems to be the time to kick-start the journey!&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Behind the Scenes of Verso Browser Development</title>
        <published>2025-05-13T12:17:07+08:00</published>
        <updated>2025-05-13T12:17:07+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/posts/verso-ui/"/>
        <id>https://wusyong.github.io/posts/verso-ui/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/posts/verso-ui/">&lt;p&gt;In the past few months, we are trying to evaluate Servo web engine and see if we could build a proper web browser application. In this post, I’d like to share some insights into the challenges we’re tackling, and where we are in the journey to transform Servo from a web engine into a fully functional, user-friendly browser.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;why-build-verso-from-servo-minibrowser-to-a-stable-application&quot;&gt;Why Build Verso? From Servo Minibrowser to a Stable Application&lt;/h2&gt;
&lt;p&gt;Servo itself is a powerful and modern web engine, but it has traditionally not been treated as a fully functioning browser. Instead, the Servo project provides a minimum working example called &lt;strong&gt;servoshell&lt;/strong&gt;, often described as a mini-browser, mainly serving as a testing ground for the engine’s capabilities.&lt;/p&gt;
&lt;p&gt;Our vision with &lt;strong&gt;Verso&lt;/strong&gt; is to take this starting point and gradually expand it into a formal, stable, and feature-rich browser — something that ordinary users would comfortably use as their daily web browser. The goal is to build an application on top of Servo that delivers a native, complete browsing experience.&lt;/p&gt;
&lt;p&gt;By attempting to implement a fully functional browser with Verso, we also identify gaps and missing features in Servo itself. This creates a &lt;strong&gt;win-win situation&lt;/strong&gt;: as we build out needed capabilities in Verso, we contribute improved implementations and bug fixes back upstream to Servo, strengthening the engine for the entire community.&lt;/p&gt;
&lt;p&gt;This long-term ambition is why you’re seeing the broad scope of features we’ve implemented recently—from window management and menus to prompt dialogs and notifications.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;the-big-picture-engine-versus-browser-responsibilities&quot;&gt;The Big Picture: Engine Versus Browser Responsibilities&lt;/h2&gt;
&lt;p&gt;One key motivation behind building Verso as its own separate repository is to &lt;strong&gt;cleanly separate concerns&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Servo&lt;/strong&gt; should stay focused primarily on what it does best—the web engine itself. This includes implementing web standards, improving style, layout, and web APIs.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Everything else that builds a full browser experience — windowing, UI, user interactions, menus, file dialogs, bookmarks, history, notifications, and more — should left for embedders to decide.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This approach not only prevents Servo from being bogged down with application-level chores but also helps distribute resources and responsibilities clearly across projects and teams.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;recent-development-highlights-from-our-perspective&quot;&gt;Recent Development Highlights from Our Perspective&lt;/h2&gt;
&lt;p&gt;Working on Verso, I’ve had the opportunity to collaborate closely with Jason, TeKai, and others. Here are some key features and improvements we’ve tackled recently, reflecting our progress toward a full-fledged browser.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3 id=&quot;borderless-window-dragging&quot;&gt;Borderless Window Dragging&lt;/h3&gt;
&lt;p&gt;A simple but critical UX feature was missing from the minibrowser — the ability to drag and maximize a borderless window smoothly across platforms.&lt;/p&gt;
&lt;p&gt;The tricky part is that borderless windows lose native dragging features on &lt;strong&gt;Linux and Windows&lt;/strong&gt;, and on &lt;strong&gt;macOS&lt;/strong&gt;, the draggable area was limited and inconsistent.&lt;/p&gt;
&lt;p&gt;We had to &lt;strong&gt;reimplement dragging from scratch&lt;/strong&gt;, carefully ensuring the drag functionality wouldn’t interfere with dynamic UI elements like panels. On macOS, we tracked down subtle bugs to provide a reliable, uniform dragging experience (issue &lt;a rel=&quot;external&quot; href=&quot;https://github.com/versotile-org/verso/issues/192&quot;&gt;#192&lt;/a&gt;).&lt;/p&gt;
&lt;hr /&gt;
&lt;h3 id=&quot;context-menus&quot;&gt;Context Menus&lt;/h3&gt;
&lt;p&gt;Context menus are a cornerstone of desktop usability. But context menu support across OSes is fragmented:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Windows/macOS offer native context menu, for which we leveraged the &lt;strong&gt;muda crate&lt;/strong&gt; — originally developed for Tauri — adapting and improving it to fit Verso’s context menu needs (PR &lt;a rel=&quot;external&quot; href=&quot;https://github.com/versotile-org/verso/pull/226&quot;&gt;#226&lt;/a&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;On Linux, especially with Wayland, native context menus are not available. We opted to draw menus inside Servo itself using an embedded webview (PR &lt;a rel=&quot;external&quot; href=&quot;https://github.com/versotile-org/verso/pull/237&quot;&gt;#237&lt;/a&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This hybrid approach took around three weeks of work and allows us to provide native-like context menus on all platforms.&lt;/p&gt;
&lt;p&gt;In the meantime, Working closely with the Servo upstream, we also marked the first pointer event API implementation inside Servo itself.&lt;/p&gt;
&lt;p&gt;This was a multi-month effort involving the team, laying a foundation for many UI features, including the later improved context menu (Servo PRs &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/pull/34437&quot;&gt;#34437&lt;/a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/pull/35364&quot;&gt;#35364&lt;/a&gt;).&lt;/p&gt;
&lt;hr /&gt;
&lt;h3 id=&quot;prompt-dialog-support&quot;&gt;Prompt Dialog Support&lt;/h3&gt;
&lt;p&gt;From simple confirm dialogue to authentications prompt dialogue is used everywhere, which makes it a fundamental API that users expect to work flawlessly.&lt;/p&gt;
&lt;p&gt;Jason took the lead on implementing these dialogs across platforms (PR &lt;a rel=&quot;external&quot; href=&quot;https://github.com/versotile-org/verso/pull/250&quot;&gt;#250&lt;/a&gt;).&lt;/p&gt;
&lt;hr /&gt;
&lt;h3 id=&quot;tabs-for-multi-page-browsing&quot;&gt;Tabs for Multi-Page Browsing&lt;/h3&gt;
&lt;p&gt;Tabs are a defining feature of any modern browser. Jason dived straight into adding tabs for Verso, building both the core logic and the panel UI (PR &lt;a rel=&quot;external&quot; href=&quot;https://github.com/versotile-org/verso/pull/260&quot;&gt;#260&lt;/a&gt;, panel PR &lt;a rel=&quot;external&quot; href=&quot;https://github.com/versotile-org/verso-panel/pull/10&quot;&gt;#10&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;With this we have tabs work smoothly on all desktop platforms, including creation via keyboard shortcuts.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3 id=&quot;ime-input-events&quot;&gt;IME Input Events&lt;/h3&gt;
&lt;p&gt;Input Method Editor (IME) support is crucial for many users worldwide. Languages like Japanese and Chinese relied heavily on IME support.&lt;/p&gt;
&lt;p&gt;We contributed multiple PRs to Servo and Verso that handle pre-edit text, caret positioning, and related operations, ensuring IME input flows correctly and synchronizes with the UI (Servo PRs &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/pull/35535&quot;&gt;#35535&lt;/a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/pull/35623&quot;&gt;#35623&lt;/a&gt; and Verso PR &lt;a rel=&quot;external&quot; href=&quot;https://github.com/versotile-org/verso/pull/282&quot;&gt;#282&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3 id=&quot;file-input-dialog-support&quot;&gt;File Input Dialog Support&lt;/h3&gt;
&lt;p&gt;File inputs require integration with native file pickers.&lt;/p&gt;
&lt;p&gt;We enhanced Servo’s FileSelection embedder message to properly display file counts and names, sorted out related testing issues, then integrated native file dialogs in Verso (Servo PR &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/pull/35789&quot;&gt;#35789&lt;/a&gt;, Verso PR &lt;a rel=&quot;external&quot; href=&quot;https://github.com/versotile-org/verso/pull/282&quot;&gt;#286&lt;/a&gt;).&lt;/p&gt;
&lt;hr /&gt;
&lt;h3 id=&quot;notifications-with-webapi-support&quot;&gt;Notifications with WebAPI Support&lt;/h3&gt;
&lt;p&gt;Notifications are an important part of modern web applications.&lt;/p&gt;
&lt;p&gt;We added basic Notification and NotificationEvent WebAPI support to Servo, including image caching for notification icons (Servo PRs &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/pull/34842&quot;&gt;#34842&lt;/a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/pull/35878&quot;&gt;#35878&lt;/a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/pull/36055&quot;&gt;#36055&lt;/a&gt;). On Verso, we integrated a third-party library to render platform-native notifications across Linux, Windows, and macOS (Merge Request &lt;a rel=&quot;external&quot; href=&quot;https://gitlab.com/verso-browser/verso/-/merge_requests/308&quot;&gt;#308&lt;/a&gt;).&lt;/p&gt;
&lt;hr /&gt;
&lt;h3 id=&quot;caret-and-text-selection-display-in-text-input&quot;&gt;Caret and Text Selection display in Text Input&lt;/h3&gt;
&lt;p&gt;We contributed to Servo’s text input and textarea elements to ensure caret and selection display matches the layout, (Servo PR &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/pull/35830&quot;&gt;#35830&lt;/a&gt;).&lt;/p&gt;
&lt;hr /&gt;
&lt;h3 id=&quot;browsing-history-and-bookmarks-in-profile-config&quot;&gt;Browsing History and Bookmarks in Profile Config&lt;/h3&gt;
&lt;p&gt;We started to build out essential browser infrastructure:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Adding a &lt;strong&gt;history menu&lt;/strong&gt; accessible by long-pressing navigation buttons, rendered on top of Servo webviews for cross-platform consistency (Panel PR &lt;a rel=&quot;external&quot; href=&quot;https://github.com/versotile-org/verso-panel/pull/11&quot;&gt;#11&lt;/a&gt;, Verso MR &lt;a rel=&quot;external&quot; href=&quot;https://gitlab.com/verso-browser/verso/-/merge_requests/322&quot;&gt;#322&lt;/a&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Implementing &lt;strong&gt;bookmark management&lt;/strong&gt; through panel UI and backend interaction, allowing users quick access to favorite sites (Panel PR &lt;a rel=&quot;external&quot; href=&quot;https://github.com/versotile-org/verso-panel/pull/13&quot;&gt;#13&lt;/a&gt;, Verso MR &lt;a rel=&quot;external&quot; href=&quot;https://gitlab.com/verso-browser/verso/-/merge_requests/327&quot;&gt;#327&lt;/a&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;what-s-next&quot;&gt;What&#39;s next?&lt;/h2&gt;
&lt;p&gt;Our work on Verso seeks for modularity of Servo and hope to improve its ecosystem. One of the major milestones we wish to achieve is to make more Servo components modular and able to be used in other projects. This is also why we have some &lt;a rel=&quot;external&quot; href=&quot;https://v2.tauri.app/blog/tauri-verso-integration/&quot;&gt;good news&lt;/a&gt; from Tauri community on Verso integration.&lt;/p&gt;
&lt;p&gt;Sine we&#39;ve added multiple application features mentioned above, we are confident it&#39;s possible to evolve Verso into a mature application one day. But before that, I think it&#39;s also a good time to look back into windowing and rendering management again as we encountered some blockage from time to time.&lt;/p&gt;
&lt;p&gt;What&#39;s worrying me is Servo&#39;s webrender is still using OpenGL, while many other projects have moved to wgpu. I hope we could also get a solid wgpu backend one day, so Servo can collaborate with more projects. In the next few month, I&#39;ll share more info on my progress and see what we could do.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Should we add wgpu support to webrender?</title>
        <published>2025-04-21T12:17:07+08:00</published>
        <updated>2025-04-21T12:17:07+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/posts/webrender-wgpu/"/>
        <id>https://wusyong.github.io/posts/webrender-wgpu/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/posts/webrender-wgpu/">&lt;p&gt;I&#39;ve been thinking about adding &lt;a rel=&quot;external&quot; href=&quot;https://wgpu.rs/&quot;&gt;wgpu&lt;/a&gt; support whenever I need to mess around with rendering context and compositor of Servo. The core component of these parts is &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/webrender&quot;&gt;webrender&lt;/a&gt; and it uses OpenGL for graphics. While it works most of the time, it has many workarounds on different platforms. On Windows, it needs ANGLE to guarantee the GL version. On macOS, it stucks on version 4.1 forever since Metal has been the latest official support. It is also worrying that OpenGL hasn&#39;t been updated ever since because Khronos decideds to move on to Vulkan. Whenever I look into webrender, I also fear it will become the part that might be unable to maintain in one day. There are some solutions in my mind that we could take depending on the situations and the resources we could use.&lt;/p&gt;
&lt;h2 id=&quot;build-on-top-of-angle&quot;&gt;Build on top of ANGLE&lt;/h2&gt;
&lt;p&gt;The easiest and minimum effort we could take is, of course, extending the support of &lt;a rel=&quot;external&quot; href=&quot;https://github.com/google/angle&quot;&gt;ANGLE&lt;/a&gt;. Servo already uses it on Windows and has a fork called &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/mozangle&quot;&gt;mozangle&lt;/a&gt;. It shouldn&#39;t be a problem to extend the support to other platforms. This should resolve the worry if macOS doesn&#39;t want to support CGL(legacy openGL) anymore.&lt;/p&gt;
&lt;p&gt;However, there are some disadvantages that will restrict Servo&#39;s development. First is the binary size. Building the shared libraries of ANGLE are around 20MB of DLLs on Windows. If we extend to all platforms, Servo will increase this amount of size. And Servo already needs to include GStreamer and SpiderMonkey already. Another issue is moudlarity, keep using OpenGL means anyone who wish to adopt Servo need to use this graphic library. If you browse through Rust&#39;s GUI ecosystem, you can see many frameworks are migrating to wgpu. Some even don&#39;t have OpenGL support anymore. It will be a growing problem for people who wish to integrate Servo and many other crates.&lt;/p&gt;
&lt;h2 id=&quot;implement-compositor-trait&quot;&gt;Implement Compositor trait&lt;/h2&gt;
&lt;p&gt;If we are able to spare some resources to look into, I think the experiment we could do is implementing the &lt;a rel=&quot;external&quot; href=&quot;https://doc.servo.org/webrender/composite/trait.Compositor.html&quot;&gt;Compositor&lt;/a&gt; trait. This is the trait for webrender managing surfaces and framebuffers. It can be &lt;code&gt;None&lt;/code&gt; which is what Servo does, and it will let external usage to decide how to bind the buffers and surfaces. For Firefox, it does &lt;a rel=&quot;external&quot; href=&quot;https://github.com/mozilla-firefox/firefox/blob/acb55c58a88788dd71a1652d597cc5b73a1d78de/gfx/webrender_bindings/src/bindings.rs#L1351&quot;&gt;implement&lt;/a&gt; this trait instead.&lt;/p&gt;
&lt;p&gt;The only issue I found is webrender still use &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/webrender/blob/c4bd5b47d8f5cd684334b445e67a1f945d106848/webrender/src/device/gl.rs#L1064&quot;&gt;OpenGL APIs&lt;/a&gt; internally. I&#39;m not sure if wgpu has any interoperability to OpenGL. Perhaps it needs to lock into OpenGL backends as well. But this will circle back to the need of ANGLE or similar tools again.&lt;/p&gt;
&lt;h2 id=&quot;add-wgpu-version-of-renderer&quot;&gt;Add wgpu version of Renderer&lt;/h2&gt;
&lt;p&gt;The one true solution in my opinion is adding a wgpu version of Renderer to webrender if we have enough resource. While it sounds crazy because webrender is a huge project which is over 200k LOC, the GL usage is limited to &lt;a rel=&quot;external&quot; href=&quot;https://doc.servo.org/webrender/struct.Device.html&quot;&gt;Device&lt;/a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https://doc.servo.org/webrender/struct.Renderer.html&quot;&gt;Renderer&lt;/a&gt;. Although they are still pretty large, I believe with someone who understand WebGPU, it can build the minimum support in reasonable amount of time. The only worrying is probably shader support. However, there&#39;re only a few shader in Servo. I also believe we are able to translate them.&lt;/p&gt;
&lt;p&gt;If we can get the wgpu support, I believe it can bring lots of benefits to Servo ecosystem. For maintainers, it&#39;s already fewer workarounds need to worry about. This also means we can obtain better WebGPU support, because the current one needs to copy the buffer to openGL which is not ideal in terms of performance. And for the cummunity, it will be easier for people to integrate into other projects.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Why I voted for Servo&#39;s AI policy change despite I don&#39;t use those tools</title>
        <published>2025-04-08T12:17:07+08:00</published>
        <updated>2025-04-08T12:17:07+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/posts/servo-ai-policy/"/>
        <id>https://wusyong.github.io/posts/servo-ai-policy/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/posts/servo-ai-policy/">&lt;p&gt;Before we start, I want to claim &lt;strong&gt;this post is written without any usage of AI tools&lt;/strong&gt;, even without &lt;a rel=&quot;external&quot; href=&quot;https://app.grammarly.com/&quot;&gt;Grammarly&lt;/a&gt; which I&#39;ve added the plugin into Firefox way before AI mania and usually use it to fix my grammar. With Servo&#39;s recent controversial &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/discussions/36379&quot;&gt;AI policy update&lt;/a&gt;, I would like to share my two cents on it. However, it&#39;s not going to be all about this policy only and will be a bit off topic, so I suppose it&#39;s better to publish on my own blog.&lt;/p&gt;
&lt;p&gt;I am one of the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/project/blob/main/governance/README.md&quot;&gt;Servo TSC&lt;/a&gt; members. Before this, I tried to casually contribute to various browsers and projects related to browser ecosystems. Servo became the browser engine I would like to push the most, and it came a long way for me to be able to steadily contribute to it. To this day, the commits I pushed never use any AI tools. I don&#39;t even use &lt;a rel=&quot;external&quot; href=&quot;https://github.com/features/copilot&quot;&gt;Github Copilot&lt;/a&gt; which is a very popular one and can be integrated to your IDE pretty easily. Most of my work is dealing with embedding or rendering side of Servo engine. My experience when testing with Copilot was terrible. All code suggestions to platform stuff like Objc runtime, COM, and even just some unix sockects are either plain wrong, or seem to work but have deep flaws that require deep know-how to identify.&lt;/p&gt;
&lt;p&gt;It came to my conclusion that LSP is still the best assist tools to help me code. Servo book has &lt;a rel=&quot;external&quot; href=&quot;https://book.servo.org/contributing/editor-setup.html&quot;&gt;&quot;Editor Support&quot;&lt;/a&gt; page to help you add rust-analyser support when you develop Servo. I know it&#39;s still not perfect, and my friend also &lt;a rel=&quot;external&quot; href=&quot;https://servo.zulipchat.com/#narrow/channel/263398-general/topic/rust-analyzer.20failed.20to.20include.20codes.20in.20script_bindings&quot;&gt;encountered&lt;/a&gt; some pitfall. But we are adding the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/pull/36384&quot;&gt;support&lt;/a&gt; as much as we can.&lt;/p&gt;
&lt;p&gt;However, I still voted for the change. The closest statement to describe my stand point is &lt;a rel=&quot;external&quot; href=&quot;https://github.com/LadybirdBrowser/ladybird/blob/948349974c37d991837fa041c9e834e1b56429b5/CONTRIBUTING.md#on-usage-of-ai-and-llms&quot;&gt;Ladybird&#39;s contributing guide&lt;/a&gt;. I won&#39;t allow gibberish if I need to deal with the issue or feature. But if it could help you and you can take the responsibility to meet the standard we set, I&#39;m happy whatever tools that assist you. In Servo&#39;s script component, the common standard is to keep the &lt;a rel=&quot;external&quot; href=&quot;https://servo.org/wpt/&quot;&gt;WPT coverage&lt;/a&gt; and pass more scores. And this is what policy update &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/discussions/36379#discussion-8173909&quot;&gt;mentioned&lt;/a&gt;: someone experimented with &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/pull/34844&quot;&gt;WritableStream&lt;/a&gt; and their experience is positive. However, we already set the &lt;a rel=&quot;external&quot; href=&quot;https://book.servo.org/contributing/getting-started.html#ai-contributions&quot;&gt;restriction&lt;/a&gt; that any AI tools are not allowed. And this was how the debate among TSC members began and the proposal Servo published this week.&lt;/p&gt;
&lt;p&gt;I think the biggest mistake and lesson we should learn from is this kind of topic should open to public in the first place. We didn&#39;t gather the opinion from community to discuss the solution. I believe some members who vote for the change is also similar to my stand. But the proposal appeals to no one despite it&#39;s a compromise already. &lt;strong&gt;Servo is a very unique browser engine shared by the community.&lt;/strong&gt; It&#39;s not dictated by any corporation or BDFL. This is why Servo is the project I wish to push the most and hope it could be the real open-sourced browser that offers freedom. I&#39;m confident this topic will be resolved by the community in the end, whether we keep the restriction or not.&lt;/p&gt;
&lt;p&gt;With the topic we have recently, I would like to take this chance to discuss the code contributors ourselves. I believe one of the huge factors that lead to this topic today is because of how we contribute. Like I mentioned before, Servo isn&#39;t controlled by a single person or corporation. This means contributors are responsible for their own finance. Servo&#39;s donations are primarily used for operation costs. While some people are hired by certain companies to contribute, others need to find their way to sustain.&lt;/p&gt;
&lt;p&gt;Around a year ago, I tried to put my &lt;a rel=&quot;external&quot; href=&quot;https://github.com/versotile-org/verso&quot;&gt;best effort&lt;/a&gt; together with the help of several people from Servo and Tauri to see if we can make practical usage for Servo and get the stable funding options. &lt;a rel=&quot;external&quot; href=&quot;https://commonsconservancy.org/dracc/0044/&quot;&gt;Versotile&lt;/a&gt; is the organization we formed under &lt;a rel=&quot;external&quot; href=&quot;https://commonsconservancy.org/&quot;&gt;Commons Conservancy&lt;/a&gt;. For now, we only applied &lt;a rel=&quot;external&quot; href=&quot;https://www.ngi.eu&quot;&gt;NGI grants&lt;/a&gt; because we believe this aligns with our vision the most. However, we also need to make sure the task is delivered the actually get the grants with a given deadline.&lt;/p&gt;
&lt;p&gt;One of the blockers from the tasks we want to do is to remove the patch of &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/mozjs/pull/540&quot;&gt;jsstreams&lt;/a&gt; feature. The reason of the patch is because upstream has removed whole implementation completely, this led to worry about annual updating of spidermonkey ESR version and we expected it to be more and more difficult to update each year. So I tried to find the people can help me rewrite &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/issues/32898&quot;&gt;ReadableStream&lt;/a&gt; in Servo. The scope of &lt;a rel=&quot;external&quot; href=&quot;https://streams.spec.whatwg.org/#rs&quot;&gt;stream spec&lt;/a&gt; is enormous, even ReadableStream itself only is huge. Fortunately, we managed to find the people and resolved the issue. And then there&#39;s the follow-up issue to WritableStream which resulted into the controversy policy change I saw.&lt;/p&gt;
&lt;p&gt;What worries me the most is the potential of losing major contributors. If you contributed to Servo before, you should understand how difficult it is to land the features you wish to happen. Especially when there are components like script and layout requiring deep know-how to understand how it actually works. There are PRs with lots of comment back and forth and still got stuck for months because no one entirely sure how &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/pull/35830#discussion_r2025921533&quot;&gt;certain types work&lt;/a&gt;. This is why I voted for the policy change despite I&#39;m not fond of AI tools either. In fact, I stated it clearly Versotile has nothing to do with AI when we were applying for grants. But I also hope to see other contributors can receive the help they need when contributing to the project.&lt;/p&gt;
&lt;p&gt;Sorry if this sounds like a rant on latter half of the article. I&#39;m confident the feedback from the community will take a huge role on the policy change. But in the meantime, I want to let people understand the difficulty of smaller contributors that wish to devote to the project in the long run. No matter what the change will be, I wish the follow-up can focus on helping contributors next. I hope people can keep &lt;a rel=&quot;external&quot; href=&quot;https://servo.org/sponsorship/&quot;&gt;sponsoring Servo&lt;/a&gt; , and if possible, also &lt;a rel=&quot;external&quot; href=&quot;https://opencollective.com/verso&quot;&gt;sponsoring us&lt;/a&gt;. If we have more stable funding option, I believe we can deliver more features to Servo that can meet community&#39;s needs and expectations. Welcome to send me a mail, if you wish to discuss in details.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Verso: initial multi-window support</title>
        <published>2024-08-10T12:17:07+08:00</published>
        <updated>2024-08-10T12:17:07+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/posts/verso-compositor-part3/"/>
        <id>https://wusyong.github.io/posts/verso-compositor-part3/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/posts/verso-compositor-part3/">&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https://github.com/versotile-org/verso/pull/109#event-13818698306&quot;&gt;multi-window&lt;/a&gt; has landed! We are fortunate that refactoring worked as planned. Although it opened some &lt;a rel=&quot;external&quot; href=&quot;https://github.com/versotile-org/verso/pull/109#issuecomment-2277526692&quot;&gt;follow-up&lt;/a&gt;
issues to triage, I&#39;m glad we got the initial support to open more windows instead of just only one in the very beginning.
This is one of the most difficult challenge when it comes to develop GUI tools and frameworks. This opens more
opportunities to implement further features such as prompt dialog and directory selector, etc. This post is actually the
third part of previous series, but I think it worths an unique title for it. In this post, I&#39;ll explain
what are the key changes to enable multiple windows.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/multiwindow.webp&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;h2 id=&quot;multiple-surfaces&quot;&gt;Multiple surfaces&lt;/h2&gt;
&lt;p&gt;To achieve multi-window, we need, of course, multiple windows (Duh). Winit can already open and manage more than one window.
What we need to do next is create individual surfaces for each window. A &lt;a rel=&quot;external&quot; href=&quot;https://docs.rs/surfman/0.9.5/surfman/platform/unix/wayland/surface/struct.Surface.html&quot;&gt;surface&lt;/a&gt; is a collection of pixel buffers that
are rendered via GPU and displayed in the final target. The target could be either a window or a texture that can be
saved in the file or offscreen. In our case, we only need the window surface for now. We will explore offscreen rendering
in the future. We extended the capability of &lt;code&gt;RenderingContext&lt;/code&gt; to be able to create and destroy additional surfaces in
&lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/pull/32933&quot;&gt;Servo#32933&lt;/a&gt;. And then we try to &lt;a rel=&quot;external&quot; href=&quot;https://github.com/versotile-org/verso/blob/07a88a86347c67639f2262fb94acce713d989d5a/src/compositor.rs#L1292&quot;&gt;swap the surface&lt;/a&gt; whenever we need the Compositor to deal with different windows.&lt;/p&gt;
&lt;p&gt;This change is easier said then done. Although it essentially just needs to add the method of swapping surfaces to the
Compositor, updating the window fields to a hashmap of windows requires a lot of fields to be updated as well.
I&#39;m also surprised that many changes in the PR are actually updating the parts related to windows instead of dealing with surface.&lt;/p&gt;
&lt;h2 id=&quot;multiple-display-lists&quot;&gt;Multiple display lists&lt;/h2&gt;
&lt;p&gt;Let the Compositor manage multiple surfaces is the first half. The other half is telling &lt;a rel=&quot;external&quot; href=&quot;https://docs.rs/webrender/latest/webrender/&quot;&gt;WebRender&lt;/a&gt; to render the correct
display list. A &lt;a rel=&quot;external&quot; href=&quot;https://docs.rs/webrender_api/0.61.0/webrender_api/struct.Transaction.html#method.set_display_list&quot;&gt;display list&lt;/a&gt; is used to supply a new frame to the WebRender. When &lt;a rel=&quot;external&quot; href=&quot;https://docs.rs/webrender_api/0.61.0/webrender_api/struct.DisplayListBuilder.html&quot;&gt;building&lt;/a&gt; the display list, we could
decide which webviews are in such window and &lt;a rel=&quot;external&quot; href=&quot;https://docs.rs/webrender_api/0.61.0/webrender_api/struct.DisplayListBuilder.html#method.push_iframe&quot;&gt;push&lt;/a&gt; to the list. Finally, we will see the Compositor displays the different
surface when we swap the window. It will call the method that can &lt;a rel=&quot;external&quot; href=&quot;https://github.com/versotile-org/verso/blob/07a88a86347c67639f2262fb94acce713d989d5a/src/compositor.rs#L1047&quot;&gt;update the display list&lt;/a&gt; when the surface is changed.&lt;/p&gt;
&lt;p&gt;And that&#39;s how Verso gets its initial support of multi-window. There are some follow-up issues we need to triage further. For
example, it seems to have some trouble when we try to close the window on macOS and X11. On Wayland, it still displays in the
same window. We will have to spend some more time to fix these issues and polish the multi-window feature.
Nevertheless, I&#39;m still happy with what Verso achieved. Because even Firefox is still creating &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/webrender/blob/9c4012b33b7b2ab316867865b47c694a7e1d4303/webrender/src/renderer/mod.rs#L1237&quot;&gt;multiple contexts&lt;/a&gt; to
deal with multi-window. We managed to do it with a single context with multiple surfaces.&lt;/p&gt;
&lt;h2 id=&quot;what-s-next&quot;&gt;What&#39;s next?&lt;/h2&gt;
&lt;p&gt;After we polish the multi-window feature. We will explore the multi-process mode, which is already a configuration option in
Servo, but it only supports Linux and macOS for now. I want to even improve it via sandboxing on all platforms. Then, we
plan to figure out the set-up of Gstreamer with the best DX experience and enable the media feature back.
We should also revision the IPC mechanism again since we can communicate with the Constellation directly now. If I still have
some free time, I would like to implement &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/issues/32898&quot;&gt;ReadableStream&lt;/a&gt; in the script crate again. So we can remove the heavy patch from mozjs.&lt;/p&gt;
&lt;p&gt;There are many challenging tasks ahead, but I&#39;m excited to see what Verso will become. I&#39;m also looking for new sponsors since
this work is probably the final grant from NLNet. If you are also interested in supporting Verso, a new web browser written in
Rust, please don&#39;t hesitate to &lt;a rel=&quot;external&quot; href=&quot;https://opencollective.com/verso&quot;&gt;donate&lt;/a&gt; or &lt;a href=&quot;mailto:yuweiwu@pm.me&quot;&gt;contact me&lt;/a&gt;.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Verso: Writing its own compositor part 2</title>
        <published>2024-07-30T12:17:07+08:00</published>
        <updated>2024-07-30T12:17:07+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/posts/verso-compositor-part2/"/>
        <id>https://wusyong.github.io/posts/verso-compositor-part2/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/posts/verso-compositor-part2/">&lt;p&gt;In the previous post, we extended the embedder to handle more jobs like thread and channel creations. We also tried to communicate with Constellation directly to reduce the overhead. In this post, I&#39;ll demonstrate how we implemented our own compositor that fits our needs. This part may seem like just writing the same module, but I believe it did more than that and established a solid foundation to support multi-surface in rendering context.&lt;/p&gt;
&lt;h2 id=&quot;clarify-which-component-should-own-which-states&quot;&gt;Clarify which component should own which states&lt;/h2&gt;
&lt;p&gt;One of the major goals of the custom Compositor is to figure out which state should stay in which type. Because we are going to use the same rendering context with multiple surfaces to achieve multi-window support, this means the rendering context should, of course, belong to the Compositor. This also means all the types around webrender will stay in the Compositor. However, other fields that are not GL-related should be removed from the Compositor, and it should only get access to them when it&#39;s necessary. So here are some major fields that got removed, and I&#39;ll explain the reasons.&lt;/p&gt;
&lt;h3 id=&quot;window&quot;&gt;Window&lt;/h3&gt;
&lt;p&gt;This field is very obvious because we want to support multiple windows in the future, so the Compositor shouldn&#39;t own only one window in its field. In Servo&#39;s compositor, it uses &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/blob/29a4cca42d01ab7acf6610362cd1165d2c2e85f7/components/compositing/windowing.rs#L202&quot;&gt;WindowMethods&lt;/a&gt; to get the generic of the Window. Its trait methods cause a little overhead because they are not granular enough. For example, when it wants to get the viewport size, it always needs to get the whole &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/blob/29a4cca42d01ab7acf6610362cd1165d2c2e85f7/components/compositing/windowing.rs#L228&quot;&gt;EmbedderCoordinates&lt;/a&gt;. And the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/blob/29a4cca42d01ab7acf6610362cd1165d2c2e85f7/components/compositing/windowing.rs#L211&quot;&gt;rendering_context&lt;/a&gt; forces the window to hold a copy of the rendering context as well. The Compositor should only get access to a window in methods when it really wants to get the states of the window. After removing, it also helps the window type remove some redundant types.&lt;/p&gt;
&lt;h3 id=&quot;webview&quot;&gt;Webview&lt;/h3&gt;
&lt;p&gt;A webview is essentially an alias of a top-level browsing context. Previously, the Compositor had a &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/blob/29a4cca42d01ab7acf6610362cd1165d2c2e85f7/components/compositing/webview.rs#L17&quot;&gt;WebViewManager&lt;/a&gt; to handle them, but now it&#39;s removed. This sounds a bit weird but let me explain. In the multi-window environment, I would prefer a window that contains and manages the web views instead of the compositor. If the Compositor wants to know the painting order of webviews for the current frame, it can ask for &lt;a rel=&quot;external&quot; href=&quot;https://github.com/versotile-org/verso/blob/4b0ae59997819ffd56958cdd98057cf95bac01ec/src/window.rs#L333&quot;&gt;Window::painting_order&lt;/a&gt; to get the order the window wishes to composite. It will be the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/versotile-org/verso/blob/4b0ae59997819ffd56958cdd98057cf95bac01ec/src/window.rs#L38&quot;&gt;Window&lt;/a&gt; to actually own its &lt;a rel=&quot;external&quot; href=&quot;https://github.com/versotile-org/verso/blob/4b0ae59997819ffd56958cdd98057cf95bac01ec/src/webview.rs#L17&quot;&gt;WebView&lt;/a&gt;. This will also be the same when we introduce more window types like headless windows in the future.&lt;/p&gt;
&lt;h3 id=&quot;compositetarget&quot;&gt;CompositeTarget&lt;/h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/blob/29a4cca42d01ab7acf6610362cd1165d2c2e85f7/components/compositing/compositor.rs#L337&quot;&gt;CompositeTarget&lt;/a&gt; was used for checking what&#39;s the target that the Compositor should display. So it can render to offscreen framebuffers or create images in shared memory instead. However, this creates additional texture and framebuffer objects that are not owned by the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/blob/29a4cca42d01ab7acf6610362cd1165d2c2e85f7/components/shared/webrender/rendering_context.rs#L22&quot;&gt;RenderingContext&lt;/a&gt;. This makes it difficult to figure out what are all these GL objects that the compositor is handling. It should be the job of rendering context to tell the compositor which exact surface it should use. So, right now, they are all removed, and there&#39;s only one single surface in the rendering context that needs to be handled. We will extend the functionality of rendering context to support multiple surfaces in the next part.&lt;/p&gt;
&lt;h2 id=&quot;the-next-step&quot;&gt;The next step&lt;/h2&gt;
&lt;p&gt;With the custom compositor added, the current Verso instance workflow remains the same. For each &lt;a rel=&quot;external&quot; href=&quot;https://github.com/versotile-org/verso/blob/4b0ae59997819ffd56958cdd98057cf95bac01ec/src/verso.rs#L379&quot;&gt;run&lt;/a&gt; iteration, it will handle the winit event first and then handle servo messages from the Constellation. But this time, it&#39;s the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/versotile-org/verso/blob/4b0ae59997819ffd56958cdd98057cf95bac01ec/src/window.rs#L38&quot;&gt;Window&lt;/a&gt; and the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/versotile-org/verso/blob/4b0ae59997819ffd56958cdd98057cf95bac01ec/src/compositor.rs#L103&quot;&gt;IOCompositor&lt;/a&gt; working with each other to handle all the messages from the Constellation. The next step will be the most significant step: We will extend the rendering context to support multi-surface. And if it works perfectly, it should enable us to implement multiple windows with a single context. We are close to complete the journey, stay tune for the next and hopefully the final part!&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Verso: Writing its own compositor part 1</title>
        <published>2024-07-20T12:17:07+08:00</published>
        <updated>2024-07-20T12:17:07+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/posts/verso-compositor-part1/"/>
        <id>https://wusyong.github.io/posts/verso-compositor-part1/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/posts/verso-compositor-part1/">&lt;p&gt;In previous post, I mentioned we probably should research our own compositor to get multi-windows support. The compositor is a component in Servo that composites graphical contexts and decides which browsing contexts should be displayed on the surface of the window. Servo&#39;s compositor isn&#39;t exposed to users directly, despite its being in the same thread as the embedder and being a public module. This makes it difficult to get &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/issues/32485&quot;&gt;the work&lt;/a&gt; we want the compositor to do. And because we use the channel to send &lt;code&gt;EmbedderEvent&lt;/code&gt; for compositor to handle, there&#39;s always a delay for compositor handling its messages, which makes it difficult to predict when the frames will be rendered. In the hope of understanding more about how to &lt;strong&gt;enable multiple rendering contexts to compositor&lt;/strong&gt;, I decided I should write at least one for an experiment. &lt;a rel=&quot;external&quot; href=&quot;https://github.com/versotile-org/verso/pull/86&quot;&gt;Verso#86&lt;/a&gt; is the first step to this exploration.&lt;/p&gt;
&lt;h2 id=&quot;what-has-changed&quot;&gt;What has changed&lt;/h2&gt;
&lt;p&gt;However, this PR hasn&#39;t actually written the compositor yet. It just extends embedder&#39;s work to what &lt;a rel=&quot;external&quot; href=&quot;https://doc.servo.org/servo/struct.Servo.html&quot;&gt;&lt;code&gt;Servo&lt;/code&gt; instance&lt;/a&gt; does. So now Verso itself will handle all channel and thread creations, and it can call the compositor methods directly. I have to say this is not my first choice, to be honest. I actually prefer using channels to send &lt;code&gt;EmbedderEvent&lt;/code&gt; and receive &lt;code&gt;EmbedderMsg&lt;/code&gt; to communicate. They are very clean enumerations that help users understand what kind of task the embedder should handle. But like I said I wish to get more control to understand the whole behavior of compositor. So Verso now calls the compositor directly and sends &lt;code&gt;ConstellationMsg&lt;/code&gt; itself to the constellation thread. Surprisingly, I think it didn&#39;t change a lot. We are still using channels, but we can communicate directly with Constellation and Compositor at this time.&lt;/p&gt;
&lt;h3 id=&quot;thread-creation&quot;&gt;Thread creation&lt;/h3&gt;
&lt;p&gt;The most obvious benefit is that I have a clear overview of what threads require Embedder to create now. The constellation thread requires several channel senders of these threads when creating. We can potentially spawn the thread lazily or even disable them based on preference. This could reduce huge amount of memory usage at the beginning. Here are threads that Embedder is responsible for spawning and the improvement we can achieve in the future:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Constellation: This is the main station of all Servo components.&lt;/li&gt;
&lt;li&gt;Memory and Time Profiler: There&#39;s no preference option to toggle. But since there&#39;s a constellation message to disable profiler, maybe it can be disabled by default.&lt;/li&gt;
&lt;li&gt;DevTools: This can be toggled by &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/blob/a29e5c8115bc9b2a07467a44518a0a617e056208/components/config/opts.rs#L78&quot;&gt;Opts::devtools_server_enabled&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Webrender: This is Servo&#39;s renderer and has its own thread pool. Perhaps we can set the size of thread pool.&lt;/li&gt;
&lt;li&gt;WebGL: It must be created for now because WebXR needs to use it to create a registry. Perhaps there&#39;s a way to disable them by default and only spawn it lazily.&lt;/li&gt;
&lt;li&gt;Bluetooth: It doesn&#39;t have preference option either. We should look for a way to spawn it lazily.&lt;/li&gt;
&lt;li&gt;Resource threads: This is a thread pool with the size based on CPU core. This is the one that really needs to be improved in the &lt;code&gt;net&lt;/code&gt; crate because it can be spawned multiple times. There&#39;s also a Tokio runtime in &lt;code&gt;net&lt;/code&gt; that will spawn its thread pool. I think this is the main reason we saw hundreds of MB memory usage upon creating the browser. If you have 32 cores, that means &lt;a rel=&quot;external&quot; href=&quot;https://servo.zulipchat.com/#narrow/stream/416779-Performance/topic/Too.20many.20threads/near/441625582&quot;&gt;64 threads&lt;/a&gt; will be created already!&lt;/li&gt;
&lt;li&gt;Font Cache&lt;/li&gt;
&lt;li&gt;Canvas: It should be spawned lazily as well.&lt;/li&gt;
&lt;li&gt;Web Driver: This can be toggled by &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/blob/a29e5c8115bc9b2a07467a44518a0a617e056208/components/config/opts.rs#L82&quot;&gt;Opts::webdriver_port&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;JS engine: Spidermonkey also has its own thread pool.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As you can see, that&#39;s quite a few threads and will already use some MB of memory. One of the improvements we should constantly push is trying to spawn only necessary threads at the beginning.&lt;/p&gt;
&lt;h3 id=&quot;constellation-messages&quot;&gt;Constellation messages&lt;/h3&gt;
&lt;p&gt;Another benefit we got is we can focus on handling constellation messages only. But I would say this is a subtle benefit. We change from &lt;code&gt;EmbedderEvent&lt;/code&gt; to &lt;code&gt;ConstellationMsg&lt;/code&gt;. The improvement we got I think is more about finding some redundant parts that can be eliminated. For example, I found &lt;a rel=&quot;external&quot; href=&quot;https://docs.rs/gleam/latest/gleam/gl/struct.GlFns.html#method.load_with&quot;&gt;GlFns::load_with&lt;/a&gt; is called multiple time during thread creation and event handling, even Verso itself will load again when creating a window. And that&#39;s &lt;a rel=&quot;external&quot; href=&quot;https://servo.zulipchat.com/#narrow/stream/263398-general/topic/Binary.20size/near/450657083&quot;&gt;60 KB&lt;/a&gt; each time will be included in the binary. We can manage it to call only once. I also found we can send the web driver message directly to the Constellation without starting a server. Of course, we can also extend &lt;code&gt;EmbedderEvent&lt;/code&gt; to do so. But I guess I will never find out if I can reach deeper. This can benefit us by sending some light weight messages without spawning a web driver thread for the more trivial use cases.&lt;/p&gt;
&lt;h2 id=&quot;the-next-step&quot;&gt;The next step&lt;/h2&gt;
&lt;p&gt;So right now, it&#39;s more like a preparation before writing our own compositor. The next step is trying to replicate the existing compsitor in Verso, so we can make sure it can work at least. Then, I want to understand which parts belong to which component, primarily the parts from Webrender. Should they all belong to the compositor? Or should they be kept in the window? Can we also just create one compositor and give it different contexts to handle? The whole compositor is around 4000 LOC. So I think it will take a while. But I&#39;m confident we can clear this out one by one. I&#39;ll also upload more posts about this series in the near future.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Verso: A new browser based on Servo</title>
        <published>2024-07-13T12:17:07+08:00</published>
        <updated>2024-07-13T12:17:07+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/posts/verso-0-1/"/>
        <id>https://wusyong.github.io/posts/verso-0-1/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/posts/verso-0-1/">&lt;p&gt;&lt;img src=&quot;/images/lookinside.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Yep, I&#39;m building a new web browser called &lt;a rel=&quot;external&quot; href=&quot;https://github.com/versotile-org/verso&quot;&gt;Verso&lt;/a&gt; based on &lt;a rel=&quot;external&quot; href=&quot;https://servo.org/&quot;&gt;Servo&lt;/a&gt;. If you don&#39;t know what is Servo yet, it&#39;s a web engine written in Rust from the ground up. I think it would be cool to see a browser that&#39;s built on top of it instead of creating yet another chromium fork. I also have personal milestones want to achieve. One of them is building the UI from Servo itself. Right now I can already render two views: One for the webpage, the other for the navbar UI. The image below is the Verso window navigating the demo page:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/versodemo.webp&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I know it&#39;s still a bit rough but what I want to showcase is that the navbar can already perform some basic actions. There are still a few blockers I prefer to resolve first before improving the UI. Like I said I would like to dog food eating which should look inside both Verso/Servo and improve them. Here are some list served as my remainder and hopefully attract some contributors to help as well.&lt;/p&gt;
&lt;h2 id=&quot;multi-windows&quot;&gt;Multi-Windows&lt;/h2&gt;
&lt;p&gt;Last year, I spent a lot of time to look into multi-views support. And thanks to Delan from Igalia, it&#39;s added in Servo &lt;a rel=&quot;external&quot; href=&quot;https://servo.org/blog/2024/01/19/embedding-update/&quot;&gt;this Januaray&lt;/a&gt;. So the next milestone would be adding multi-windows support. I have some idea but not sure how to execute yet. Servo&#39;s compositor only accept one rendering context at the moment. With multiple windows, I believe there will be multiple contexts need to handle. Another restrcition is the embedder couldn&#39;t access to the compositor directly despite they are in the same thread. They use channels to communicate with each other. I&#39;m thinking maybe I should implement another compositor as experiment to see how it goes.&lt;/p&gt;
&lt;h2 id=&quot;better-ipc&quot;&gt;Better IPC&lt;/h2&gt;
&lt;p&gt;The navbar UI I showcase in the image above is essentially a web page as well. The embedder sends events and receives messages with existing channels. For example, the UI may send the message by prompting a dialog. But instead of actually showing the dialogs, the embedder will process the message and perform actions like navigating the URL and minimize/maximize the window. But there are some advanced features that current event variants couldn&#39;t satisfy them, such as changing the history session and reflect to the input bar. We could try to add more variants but some may contain security violation concerns. Perhaps Servo can public the &lt;a rel=&quot;external&quot; href=&quot;https://doc.servo.org/script/dom/index.html&quot;&gt;DOM module&lt;/a&gt; in script crate. And we add a custom DOM API similar to &lt;code&gt;postMessage&lt;/code&gt; that only accepts special origin like &lt;code&gt;about:&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;multiprocess&quot;&gt;Multiprocess&lt;/h2&gt;
&lt;p&gt;Servo actually has multiprocess mode but it only supports Linux and macOS. I feel like multiprocess is a must have feature after &lt;a rel=&quot;external&quot; href=&quot;https://en.wikipedia.org/wiki/Spectre_(security_vulnerability)&quot;&gt;Spectre&lt;/a&gt;. At least we should provide some basic &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/issues/20567&quot;&gt;site isolation&lt;/a&gt;. It would be great that Windows can get the benefits too. To achieve this, we will need to fix this issue: &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/ipc-channel/issues/310&quot;&gt;ipc-channel#310&lt;/a&gt; which is caused by &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/ipc-channel/blob/7f432aab1eb77bb2c860881153799087918558e9/src/platform/windows/mod.rs#L163&quot;&gt;this panic&lt;/a&gt;. Another good to have is sandboxing but &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/gaol&quot;&gt;gaol&lt;/a&gt; hasn&#39;t supported Windows yet either. We should either add the support or see if there are other crates already add the implementation like &lt;a rel=&quot;external&quot; href=&quot;https://learn.microsoft.com/en-us/windows/win32/secauthz/appcontainer-isolation&quot;&gt;AppContainer&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;flatpack-support&quot;&gt;Flatpack Support&lt;/h2&gt;
&lt;p&gt;Linux remains as the most difficult target when it comes to packaging. There are so many distributions and package formats. We also have to worry about both X11 and Wayland at the same time. Althouh Servo has a &lt;a rel=&quot;external&quot; href=&quot;https://book.servo.org/building/building.html&quot;&gt;book&lt;/a&gt; to get started with the setup, it still lists lots of dependencies compared to other platforms. I think we should figure this out in the first place, writing &lt;a rel=&quot;external&quot; href=&quot;https://docs.flatpak.org/en/latest/manifests.html&quot;&gt;Flatpak manifests&lt;/a&gt; to clarify the dependencies, and make the final packaging easier to distribute.&lt;/p&gt;
&lt;h2 id=&quot;looking-toward-the-future&quot;&gt;Looking toward the future&lt;/h2&gt;
&lt;p&gt;There are more items in the roadmap but I guess these milestones will take quite some time already. I have to say I&#39;m more and more excited to the Verso project as I engage into the Servo community deeper. Nico from Taffy is also trying to add &lt;a rel=&quot;external&quot; href=&quot;https://servo.zulipchat.com/#narrow/stream/263398-general/topic/Layout.20library.20without.20the.20rest.20of.20Servo/near/450618586&quot;&gt;flexbox support&lt;/a&gt; to Servo and it looks pretty promisng! I believe we can see a web browser that&#39;s made in Rust in the foreseeable future!&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Install Windows 11 the hard way</title>
        <published>2023-03-14T12:01:00+08:00</published>
        <updated>2023-03-14T12:01:00+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/posts/install-windows/"/>
        <id>https://wusyong.github.io/posts/install-windows/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/posts/install-windows/">&lt;p&gt;Recently, I got my hands on a Framework Laptop DIY Edition. I wanted to set up a dual boot system, but I didn&#39;t want to install Windows 11 on my primary SSD due to some bad experiences in the past.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/L0hdijs.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I planned to install Windows 11 on an storage expansion card. While this is possible theoretically, Microsoft&#39;s boot driver may not work with its default interface for various reasons. We will have to create the required partitions manually. In this article, I will share my experience for installing Windows on an external drive and provide some tips during the process.&lt;/p&gt;
&lt;h2 id=&quot;create-a-usb-installer&quot;&gt;Create a USB Installer&lt;/h2&gt;
&lt;p&gt;First of all, we need to create a USB installer for Windows 11. If you have a device with any Windows OS, you can download the &lt;a rel=&quot;external&quot; href=&quot;https://www.microsoft.com/software-download/windows11&quot;&gt;installation media&lt;/a&gt; from the official page. Download it, plug in a USB drive, and follow the instructions. You should complete it in no time.&lt;/p&gt;
&lt;h2 id=&quot;boot-into-installer&quot;&gt;Boot into Installer&lt;/h2&gt;
&lt;p&gt;Once you boot the laptop, repeatedly press F12 to enter the boot selection screen, and then select your USB device. When the installer appears, proceed through each step until you accept the license agreement. After this point, we won&#39;t be able to use the installer any longer. We&#39;ll need to create the partitions ourselves.&lt;/p&gt;
&lt;h2 id=&quot;create-partitions-manually&quot;&gt;Create Partitions Manually&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Proceed with caution during this step&lt;/strong&gt;, as you will need to create several partitions, and selecting the wrong disk may potentially overwrite the internal disk.&lt;/p&gt;
&lt;p&gt;Essentially, Windows requires the following partitions to be created:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Windows RE Tools partition&lt;/li&gt;
&lt;li&gt;System partition&lt;/li&gt;
&lt;li&gt;MSR partition&lt;/li&gt;
&lt;li&gt;Windows partition&lt;/li&gt;
&lt;li&gt;Recovery image partition&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now let&#39;s use &lt;code&gt;diskpart&lt;/code&gt; to open the built-in partition tool. And then select the disk x where &lt;strong&gt;x is the number of you expansion card&lt;/strong&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;diskpart&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;list disk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;select disk x&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, we need to format the disk to GPT format. Please double-check that you have selected the right disk before proceeding!&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;clean&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;convert gpt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;windows-re-tools-partition&quot;&gt;Windows RE Tools partition&lt;/h3&gt;
&lt;p&gt;Let&#39;s start with RE Tools partition. Note that I increase the size slightly since the size of Windows build has grown too. Some following partitions will also apply to this tip. There&#39;s lots of 0 when assigning gpt attributes. Just remember there are &lt;strong&gt;14 zeros&lt;/strong&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;create partition primary size=670&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;format quick fs=ntfs label=&amp;quot;Windows RE Tools&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;assign letter=&amp;quot;T&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;set id=&amp;quot;de94bba4-06d1-4d40-a16a-bfd50179d6ac&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;gpt attributes=0x8000000000000001&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;system-msr-partition&quot;&gt;System &amp;amp; MSR Partition&lt;/h3&gt;
&lt;p&gt;Next is system partition and MSR partition:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;create partition efi size=100&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;format quick fs=fat32 label=&amp;quot;System&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;assign letter=&amp;quot;S&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;create partition msr size=128&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;windows-partition&quot;&gt;Windows Partition&lt;/h3&gt;
&lt;p&gt;Now here the important part: you should choose proper size for Windows partition depending on the size of your expansion card. If you use 250GB drive, then set the size to 23000. If you use 1TB drive, then set the size to 949044.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;create partition primary size=230000&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;format quick fs=ntfs label=&amp;quot;Windows&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;assign letter=&amp;quot;W&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;recovery-image-partition&quot;&gt;Recovery Image Partition&lt;/h3&gt;
&lt;p&gt;The last is recovery image:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;create partition primary size=5120&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;format quick fs=ntfs label=&amp;quot;Recovery Image&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;assign letter=&amp;quot;R&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;set id=&amp;quot;de94bba4-06d1-4d40-a16a-bfd50179d6ac&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;gpt attributes=0x8000000000000001&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;View the disk volume to confirm that the partitions were created successfully. Take note of the drive letter assigned to your USB drive containing the Windows installer. In my case, it&#39;s &lt;code&gt;E&lt;/code&gt;. If everything goes well, you can exit the &lt;code&gt;diskpart&lt;/code&gt; tool.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;list volume&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;exit&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;copy-windows-data-to-partitions&quot;&gt;Copy Windows Data to Partitions&lt;/h2&gt;
&lt;p&gt;Now we install the Windows 11 by copy data to partition manually. When you see &lt;code&gt;E:\&lt;/code&gt; in following instructions, you should replace it to the letter you have. And when you see &lt;code&gt;index&lt;/code&gt;, you should enter the Windows 11 version you want to install. Here&#39;s overall list, but you probably just need to enter 1 or 6:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Windows 11 Home&lt;/li&gt;
&lt;li&gt;Windows 11 Home N&lt;/li&gt;
&lt;li&gt;Windows 11 Home Single Language&lt;/li&gt;
&lt;li&gt;Windows 11 Education&lt;/li&gt;
&lt;li&gt;Windows 11 Education N&lt;/li&gt;
&lt;li&gt;Windows 11 Pro&lt;/li&gt;
&lt;li&gt;Windows 11 Pro N&lt;/li&gt;
&lt;li&gt;Windows 11 Pro Education&lt;/li&gt;
&lt;li&gt;Windows 11 Pro Education N&lt;/li&gt;
&lt;li&gt;Windows 11 Pro for Workstations&lt;/li&gt;
&lt;li&gt;Windows 11 Pro N for Workstations&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;One last thing to note is that the extension of some files may differ depending on the installer you use. If you can&#39;t find &lt;code&gt;install.esd&lt;/code&gt;, for example, try looking for &lt;code&gt;install.wim&lt;/code&gt;, and vice versa.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;md R:\RecoveryImage&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;copy E:\sources\install.esd R:\RecoveryImage\install.esd&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;E:\Windows\System32&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;dism /Apply-Image /ImageFile:R:\RecoveryImage\install.esd /Index:1 /ApplyDir:W:\&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;md T:\Recovery\WindowsRE&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;copy W:\Windows\System32\Recovery\winre.wim T:\Recovery\WindowsRE\winre.wim&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;bcdboot W:\Windows /s S: /f UEFI&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;W:\Windows\System32\reagentc /setosimage /path R:\RecoveryImage /target W:\Windows /index 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;W:\Windows\System32\reagentc /setreimage /path T:\Recovery\WindowsRE /target W:\Windows&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;restart-and-boot-into-windows&quot;&gt;Restart and Boot into Windows&lt;/h2&gt;
&lt;p&gt;If everything goes well, we can exit the installer! Remove the USB drive, restart the machine, and keep pressing F12 again to choose the drive containing Windows 11 to boot. If you want to default to boot Windows, you can press F2 instead to change the boot order. It&#39;s in &lt;code&gt;Boot &amp;gt; EFI Boot Order&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;install-driver-bundle&quot;&gt;Install Driver Bundle&lt;/h2&gt;
&lt;p&gt;Once you boot into Windows, you will be prompted to complete the setup process. Just proceed as usual. If you finally reach the desktop, you should have a functional Windows installation! However, we&#39;re not done yet. We have to install Framework&#39;s &lt;a rel=&quot;external&quot; href=&quot;https://knowledgebase.frame.work/en_us/framework-laptop-bios-and-driver-releases-12th-gen-intel-core-Bkx2kosqq&quot;&gt;Driver Bundle&lt;/a&gt;.You can install the bundle and just copy to the USB drive you use for installer. And then plug into the laptop to install it.&lt;/p&gt;
&lt;p&gt;Restart and congratulation! You have a Windows installed in an external disk!&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Environment Setup for Building Webkit on Linux</title>
        <published>2023-03-04T12:01:00+08:00</published>
        <updated>2023-03-04T12:01:00+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/posts/building-webkit/"/>
        <id>https://wusyong.github.io/posts/building-webkit/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/posts/building-webkit/">&lt;p&gt;Although I&#39;ve always wanted to contribute to Webkit, I&#39;ve often found the issues to be too difficult or too time-consuming to tackle amidst my regular workload. However, I recently found myself with enough free time after Rust Nation, and decided to take on an issue that seemed straightforward enough to contribute to. Indeed the &lt;a rel=&quot;external&quot; href=&quot;https://trac.webkit.org/wiki&quot;&gt;Webkit wiki&lt;/a&gt; provides comprehensive information for contributors, I wanted to share my own steps and tips for setting up the environment in the hopes of helping future developers get started on Webkit more quickly and painlessly.&lt;/p&gt;
&lt;h2 id=&quot;choose-git-repo-as-source&quot;&gt;Choose git repo as Source&lt;/h2&gt;
&lt;p&gt;Back in the days, I used to download release tarballs to test and debug, only to discover that they could conflict with builds installed by package managers in my distribution. Even worse, their build scripts didn&#39;t provide an uninstall option, so once you run &lt;code&gt;ninja install&lt;/code&gt;, there&#39;s no turning back. Because of this, I recommend building from the git repository, even though it takes longer to build from scratch. This way, you can avoid conflicts with other builds and easily uninstall if necessary.&lt;/p&gt;
&lt;p&gt;Since Webkit has migrated to git, it&#39;s really easy to access it. Their main upstream is now on &lt;a rel=&quot;external&quot; href=&quot;https://github.com/WebKit/WebKit&quot;&gt;Github&lt;/a&gt;!&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;git clone https://github.com/WebKit/WebKit.git WebKit&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;installing-dependencies&quot;&gt;Installing Dependencies&lt;/h2&gt;
&lt;p&gt;Before starting to build the project, it&#39;s important to make sure that all dependencies are up-to-date. Luckily, Webkit provides a flatpak runtime and SDK to simplify this process. However, these files can be quite large and need to be re-downloaded each time a new version is released. The worst part is that download speeds can sometimes be painfully slow. I&#39;ve tried changing DNS or using a VPN, but none of them helped. If you find that the download speed is unreasonably low, try rerunning the following command. Whole flatpak dependency could be 5+ GB and take hours to download.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Tools/Scripts/update-webkitgtk-libs&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;building-and-running&quot;&gt;Building and Running&lt;/h2&gt;
&lt;p&gt;The steps to build and run Webkit are quite straightforward; you can follow the instructions provided on the project&#39;s wiki, specifically the &lt;a rel=&quot;external&quot; href=&quot;https://trac.webkit.org/wiki/BuildingGtk&quot;&gt;build page&lt;/a&gt;). However, it&#39;s important to note that building the project can take several hours to complete. If you want to perform debug builds, simply pass &lt;code&gt;--debug&lt;/code&gt; to each command. But the debug build will run pretty slow:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Tools/Scripts/build-webkit --gtk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Tools/Scripts/run-minibrowser --gtk&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The source code of mini browser demo can be found in &lt;code&gt;Tools/MiniBrowser/gtk/main.c&lt;/code&gt;. It has a custom url scheme &lt;code&gt;minibrowser-about&lt;/code&gt;. But if you type &lt;code&gt;about:&lt;/code&gt; it will also redirect to this scheme.&lt;/p&gt;
&lt;p&gt;Webit can also perform incremental compilation. So if you just edit some GTK related files under &lt;code&gt;Source/&lt;/code&gt;, it should take a few minutes to compile again. But if you have to edit the interface of WebCore, it will need to relink the libraries and hence take several hours to compile again. Try some advice from &lt;a rel=&quot;external&quot; href=&quot;https://trac.webkit.org/wiki/WebKitGTK/SpeedUpBuild&quot;&gt;this page&lt;/a&gt;, if you want to speed up the build time.&lt;/p&gt;
&lt;h2 id=&quot;debugging-and-testing&quot;&gt;Debugging and Testing&lt;/h2&gt;
&lt;p&gt;When you start fixing some issues or adding some features, you might want to search the codebase. Since the codebase of Webkit is huge, I suggest just browse the code through https://searchfox.org/wubkat/source. Even using ripgrep can take minutes to do the job.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://trac.webkit.org/wiki/WebKitGTK/Debugging&quot;&gt;Debugging page&lt;/a&gt; on wiki has pretty good advice about how to debug Webkit. There are two test suites that might relate to you when you need to perform some testing. And if you want specific test, simply add the path of the test to them:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Tools/Scripts/run-webkit-tests --gtk  http/tests/media/video-play-stall.html&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Tools/Scripts/run-gtk-tests WebKitBuild/GTK/Release/bin/TestWebKitAPI/WebKitGTK/TestWebKitWebContext&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;contributing&quot;&gt;Contributing&lt;/h2&gt;
&lt;p&gt;Again, &lt;a rel=&quot;external&quot; href=&quot;https://www.webkit.org/contributing-code/&quot;&gt;contributing page&lt;/a&gt; has detailed walkthrough about it. Basically, yo need to make sure the tests you would like to run have to pass at least. And then check your code obeys the code style guideline:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Tools/Scripts/check-webkit-style&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you haven&#39;t made any commit yet, be sure to run the checkout setup script:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Tools/Scripts/git-webkit setup&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will give you a commit template when you are adding commit. You&#39;ll just need to fill out the required information. The last thing to note is webkit only allow one commit per PR. So remember to squash or amend the commit when updating PRs.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>GAT 懶人包</title>
        <published>2022-11-08T12:04:23+08:00</published>
        <updated>2022-11-08T12:04:23+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/posts/gat/"/>
        <id>https://wusyong.github.io/posts/gat/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/posts/gat/">&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://blog.rust-lang.org/2022/11/03/Rust-1.65.0.html&quot;&gt;Rust 1.65&lt;/a&gt; 提供了大家期待已久的功能「Generic Associated Types」，這是在 Functional Programming 中 Higher-Kind Types 的其中一種實現。對於已經有這樣需求的人來說，這些概念應該並不陌生，或是早已知道如何善用它們了。但對於從未接觸過的人來說，我想應該就會遇到一些困難。通常看到新出的 Rust 進階功能，我們都會推薦大家去看 RFC，而我近日也將 GAT 的 &lt;a rel=&quot;external&quot; href=&quot;https://rust-lang.tw/rfcs-tw/1598-generic_associated_types.html&quot;&gt;RFC 翻譯&lt;/a&gt;完畢。但我並沒有相當的把握確保新手能了解文中舉的例子「StreamingIterator」，因為它的泛型用到了生命週期，尤其是後面又繼續提到了各種進階的用法，像是怎麼與 Higher-Rank Trait Bounds 一起使用等等。我有點擔心新手一開始接觸時就會看的眼花撩亂。這次我們不妨把所有概念都拋諸腦後，看看在寫程式的過程中，到底為何會遇上這樣的需求。&lt;/p&gt;
&lt;p&gt;讓我們用各型別都有的方法 &lt;code&gt;map&lt;/code&gt; 來作為例子，這在 &lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/std/option/enum.Option.html#method.map&quot;&gt;&lt;code&gt;Option&lt;/code&gt;&lt;/a&gt; 和 &lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/std/result/enum.Result.html#method.map&quot;&gt;&lt;code&gt;Result&lt;/code&gt;&lt;/a&gt; 都有。如果今天我們想定義一個 Trait 將該方法抽象化成泛型（generic）型別的話，我們會發現這是做不到的！其中一個得回傳 &lt;code&gt;Option&amp;lt;T&amp;gt;&lt;/code&gt; 而另一個得回傳 &lt;code&gt;Result&amp;lt;T&amp;gt;&lt;/code&gt;。這時你可能就會想將 &lt;code&gt;Option&lt;/code&gt; 或 &lt;code&gt;Result&lt;/code&gt; 作為泛型的引數（argument），但是這也是做不到的！泛型型別的名稱在 Rust 不是一個基礎的型別！&lt;/p&gt;
&lt;p&gt;而 GAT 能夠允許你達成這樣的事，這也是為何 RFC 一開始得先介紹 Kind 以及 Type Constructor 等概念，我非常推薦有時間可以&lt;a rel=&quot;external&quot; href=&quot;https://rust-lang.tw/rfcs-tw/1598-generic_associated_types.html#%E8%83%8C%E6%99%AF%E4%BB%80%E9%BA%BC%E6%98%AF%E7%A8%AE%E9%A1%9Ekind&quot;&gt;讀一讀這段&lt;/a&gt;。不過畢竟這篇是懶人包，怕太難懂我們可以直接先來看看真正的例子會怎麼寫。我們可以宣告一個這樣的 trait：&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;trait&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;font-weight: bold;&quot;&gt; Mappable&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    type&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Item&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    type&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Target&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;U&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; map&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;U&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; F&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; FnMut&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;Self::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Item&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; U&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; f&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; F&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt; Self::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Target&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;U&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然後針對 &lt;code&gt;Option&lt;/code&gt; 和 &lt;code&gt;Result&lt;/code&gt; 實作它們：&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;impl&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Mappable&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; for&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Option&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    type&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Item&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; T&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    type&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Target&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;U&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Option&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;U&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; map&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;U&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; F&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; FnMut&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;Self::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Item&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; U&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; f&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; F&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Option&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;U&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;        self.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;map&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;impl&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; E&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Mappable&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; for&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Result&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; E&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    type&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Item&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; T&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    type&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Target&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;U&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Result&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;U&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; E&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; map&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;U&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; F&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; FnMut&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;Self::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Item&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; U&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; f&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; F&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Result&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;U&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; E&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;        self.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;map&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;這樣一來你就能使用「泛型的泛型」來寫出這樣的函數：&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; absolute&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;M&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Mappable&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Item&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; i32&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;&amp;gt;(&lt;/span&gt;&lt;span&gt;m&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; M&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;M&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; as&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Mappable&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Target&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;u32&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    m&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;map&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;|&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;|&lt;/span&gt;&lt;span&gt; x&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;abs&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; as&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; u32&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;這還能用在 &lt;code&gt;Vec&lt;/code&gt; 上，完整的範例可以參考 &lt;a rel=&quot;external&quot; href=&quot;https://play.rust-lang.org/?version=stable&amp;amp;mode=debug&amp;amp;edition=2021&amp;amp;gist=396cbd95b63807d63c96cca42cdf09ac&quot;&gt;Rust Playground 的連結&lt;/a&gt;。在 RFC 中稱這樣的模式為「Family」模式，同樣的作法也能套用在指標的泛型上，像是 &lt;code&gt;Arc&lt;/code&gt; 與 &lt;code&gt;Rc&lt;/code&gt;。當然 GAT 也可以用在生命週期上，就如同 RFC 上的 StreamingIterator，而這種 trait 的用途就是希望能只可變借用到特定片段的切片，而非平常 &lt;code&gt;IterMut&lt;/code&gt; 得借用一整個集合。而在往下還有更多複雜的用法，不過希望看完這篇懶人包你能對 GAT 有初步的了解，在閱讀 RFC 時就不會那麼令人望之卻步了。&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>After half a year, what now?</title>
        <published>2022-09-09T11:04:23+08:00</published>
        <updated>2022-09-09T11:04:23+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/posts/the-next-step/"/>
        <id>https://wusyong.github.io/posts/the-next-step/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/posts/the-next-step/">&lt;p&gt;At the beginning of this year, I was planning to contribute to Servo and wish to restore its glory. But after diving into the code base and understanding its landscape, I accepted the cruel reality that it&#39;s impossible unless Servo can be adequately funded again, just as previous Servo members advised. So I will not continue the series of Servo posts. However, I hope I can demonstrate the situation it faces well in this post, grasp the remaining we have, and look for where we can explore further.&lt;/p&gt;
&lt;h2 id=&quot;what-happened-after-mozilla-layoff&quot;&gt;What happened after Mozilla layoff?&lt;/h2&gt;
&lt;p&gt;After &lt;a rel=&quot;external&quot; href=&quot;https://www.theverge.com/2020/8/11/21363424/mozilla-layoffs-quarter-staff-250-people-new-revenue-focus&quot;&gt;Mozilla layoff&lt;/a&gt; in 2020, most members from Servo are fired AFAIK. Despite being moved under &lt;a rel=&quot;external&quot; href=&quot;https://blog.servo.org/2020/11/17/servo-home/&quot;&gt;Linux Foundation&lt;/a&gt;, the foundation would only cover its cost of CI/CD. So technically speaking, the project was already in maintenance mode at that time. But several parts in Servo are already integrated into Firefox, and some people in Mozilla still maintain them to date. I was hoping if we can fill the missing puzzle in Servo, we can get a minimum viable browser or a webview library. However, it didn&#39;t go as easy as I thought would be. There are some blockers just too difficult for normal contributors to refactor.&lt;/p&gt;
&lt;h3 id=&quot;unable-to-upgrade-spoodermonke&quot;&gt;Unable to upgrade SpooderMonke&lt;/h3&gt;
&lt;p&gt;Servo, as a project under Mozilla, uses SpiderMonkey as its JavaScript engine. &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/rust-mozjs&quot;&gt;Mozjs&lt;/a&gt; and rust-mozjs are its wrappers on top of SpiderMonkey. In the last two years, contributors are trying to upgrade it to the latest version but they &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/mozjs/pull/284&quot;&gt;all&lt;/a&gt; &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/mozjs/pull/295&quot;&gt;failed&lt;/a&gt;. Servo still uses version 88 nowadays, while SpiderMonkey has already published 108 at the time of this post. And the engine itself is also the problem IMHO. Its types, GC, and design affect not only the script layer, but also the rest of Servo. Although Rust doesn&#39;t require any garbage collection, JavaScript in script layer needs it. In order to use the GC from SpiderMonky, Servo has to create &lt;a rel=&quot;external&quot; href=&quot;https://manishearth.github.io/blog/2021/04/05/a-tour-of-safe-tracing-gc-designs-in-rust/#servos-dom-integration&quot;&gt;crazy amount of types and lints&lt;/a&gt; to control it. This makes handling DOM types extremely verbose, and hence also affects whole style crate and layout crate since they all have to deal with these types. I once considered perhaps we could switch to v8 instead which have a well-maintained crate from deno. But after giving a try of its API for dealing with GC and creating JavaScript types, I got a conclusion that it will fall into same scenario like Mozjs already has. Unless Rust has a decent crate for GC, I don&#39;t believe we can work with a GC language seamlessly. &lt;a rel=&quot;external&quot; href=&quot;https://github.com/withoutboats/shifgrethor&quot;&gt;Shifgrethor&lt;/a&gt; is the closest we could get, and I also forked it into &lt;a rel=&quot;external&quot; href=&quot;https://github.com/wusyong/elise&quot;&gt;elise&lt;/a&gt; for testing multi-thread situations. But it relies on several nightly features.&lt;/p&gt;
&lt;h3 id=&quot;spaghetti-inside-script-style-layout&quot;&gt;Spaghetti inside script/style/layout&lt;/h3&gt;
&lt;p&gt;One of the main goals of Servo is to extract each feature from a browser into individual crates. This has been succeed in some features like HTML parsing, selecting CSS, and rendering etc. But there are some crates still tangle around and unable to do so which are &lt;code&gt;script&lt;/code&gt;, &lt;code&gt;style&lt;/code&gt;, and &lt;code&gt;layout&lt;/code&gt; crates. We already see types from GC affect all these crates. It&#39;s also difficult to distinguish which document traversals should belong to whom. The worst part is the old layout is sort of incorrect. Back in the day, they want to make the layout to be parallel as possible. But this didn&#39;t work well in some attributes like flex and absolute. When they tried to rewrite a new one, the layoff happened. So now we have two layout crates: &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/tree/master/components/layout&quot;&gt;the old one&lt;/a&gt; is more complete but would be wrong in specific properties; &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/tree/a1135f92fdb2eed8cc77c480311cd3901d3a2818/components/layout_2020&quot;&gt;the new one&lt;/a&gt; has almost nothing but should be correct if only it could be complete. If you try to fix some layout issues, you will have to jump around different crates again and again. And the amount of issue is massive already!&lt;/p&gt;
&lt;h2 id=&quot;crates-that-still-work-well&quot;&gt;Crates that still work well&lt;/h2&gt;
&lt;p&gt;With huge blockers like those mentioned above, I tend to agree it will require proper funding to be able to start developing again. In the near future, I feel like we should focus on those crates which are already mature and explore further on top of them. Take crates like &lt;code&gt;html5ever&lt;/code&gt;, &lt;code&gt;cssparser&lt;/code&gt; for example, they become the bedrock of every modern web framework. There are also crates like kuchiki and scraper which build on top to make users easier to use. And I hope perhaps same thing can happen to webrender.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/webrender&quot;&gt;Webrender&lt;/a&gt; is one of a few crates still maintained by Mozilla and is being used by Firefox directly! There was a GUI crate called &lt;a rel=&quot;external&quot; href=&quot;https://github.com/fschutt/azul&quot;&gt;Azul&lt;/a&gt; that once used Webrender to build the layout system. Although Azul is also no longer maintained due to &lt;a rel=&quot;external&quot; href=&quot;https://www.reddit.com/r/rust/comments/c24b57/azul_the_gui_framework_will_be_unmaintained_from/&quot;&gt;personal reasons&lt;/a&gt;, I feel like we could give it another shot and see if an HTML/CSS layout system can work again. I understand it will be very limited without any scripting functionality. But I hope we can try something other than DOM layer built by JavaScript engine. Maybe an API for document tree could work, or just doing regular XML parsing as other GUI frameworks do is enough. I don&#39;t have any conclusion yet, but I haven&#39;t come this far just to end the journey here either!&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Rust Kernel Module: Pinning</title>
        <published>2022-06-04T12:04:23+08:00</published>
        <updated>2022-06-04T12:04:23+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/posts/rust-kernel-module-03/"/>
        <id>https://wusyong.github.io/posts/rust-kernel-module-03/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/posts/rust-kernel-module-03/">&lt;p&gt;Let&#39;s talk about pinning! This is a concept we usually don&#39;t encounter often. It&#39;s introduced in the update of Rust 1.36 which brings async syntax and many other related types to build the async executor. And &lt;code&gt;Pin&lt;/code&gt; is one of them. If you want to understand it comprehensively, documentation of &lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/std/pin/index.html&quot;&gt;&lt;code&gt;std::pin&lt;/code&gt;&lt;/a&gt; has excellent explanation of why we need to pin the data. But in short, it&#39;s basically a type to pin data to its location in memory.&lt;/p&gt;
&lt;p&gt;This is in fact rarely seen in the world of C/C++ which doesn&#39;t construct movable objects frequently. Even when we work with &lt;code&gt;std::move&lt;/code&gt; in C++, we will make sure move constructor is equal to delete. However, cases like moving data are the default behavior in Rust. Its cloning requires explicit semantics.&lt;/p&gt;
&lt;h2 id=&quot;the-problem-requires-pinning&quot;&gt;The problem requires pinning&lt;/h2&gt;
&lt;p&gt;When everything is under the context of Rust, it&#39;s of course not a problem. Ownership model can take care of it. But this is not the case in our kernel module. Instead of rewriting everything in Rust, it&#39;s still more reasonable to build on top of something that already exists. This is how &lt;code&gt;kernel&lt;/code&gt; crate wraps around the existing kernel interface. And that&#39;s why you see we reuse the &lt;code&gt;refcount_t&lt;/code&gt; wrapped by &lt;code&gt;Ref&lt;/code&gt; type instead of using &lt;code&gt;Arc&lt;/code&gt; like normal rust program.&lt;/p&gt;
&lt;p&gt;This is the point that pinning matters to us. Because many kernel data structures are actually self-referential. Either it is a list self-reference itself directly, or it points to other structure which points back to it eventually.&lt;/p&gt;
&lt;p&gt;Let&#39;s look at the definition from kernel&#39;s mutex which we will discuss how to use it soon in the future post. It has a &lt;code&gt;wait_list&lt;/code&gt; which is an intrusive, circular, double-linked list.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;struct&lt;/span&gt;&lt;span&gt; mutex &lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;	atomic_long_t&lt;/span&gt;&lt;span&gt;		owner&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;	raw_spinlock_t&lt;/span&gt;&lt;span&gt;		wait_lock&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5E81AC;font-weight: bold;&quot;&gt;#ifdef&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; CONFIG_MUTEX_SPIN_ON_OWNER&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;	struct&lt;/span&gt;&lt;span&gt; optimistic_spin_queue osq&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5E81AC;font-weight: bold;&quot;&gt;#endif&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;	struct&lt;/span&gt;&lt;span&gt; list_head	wait_list&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color: #616E88;&quot;&gt; // &amp;lt;==================&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5E81AC;font-weight: bold;&quot;&gt;#ifdef&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; CONFIG_DEBUG_MUTEXES&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;	void			*&lt;/span&gt;&lt;span&gt;magic&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5E81AC;font-weight: bold;&quot;&gt;#endif&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5E81AC;font-weight: bold;&quot;&gt;#ifdef&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; CONFIG_DEBUG_LOCK_ALLOC&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;	struct&lt;/span&gt;&lt;span&gt; lockdep_map	dep_map&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5E81AC;font-weight: bold;&quot;&gt;#endif&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/Q3NJqn1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;If we represent it visually, you can tell it&#39;s self-referenced as soon as you see it. When we define the abstraction in Rust, we of course include this binding and the data we want to protect. So this list is included in the type of &lt;code&gt;Mutex&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;pub struct&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Mutex&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: ?&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Sized&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    mutex&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Opaque&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;bindings&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;mutex&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    _pin&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; PhantomPinned&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    data&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; UnsafeCell&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And because we already know Rust is move by default. When type like this is contained in the field of other struct, it&#39;s very trivial to move it in basic operations. For example if we declare a struct contains a mutex and we want to make it a reference count object, we will see the problem as shown in below:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Ref&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;AStruct&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;    //...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    innner&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span&gt; Mutex&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Inner&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color: #616E88;&quot;&gt; /* ... */&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;})&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/NkYoZXv.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;We have an original list in inner field, and when we called &lt;code&gt;Ref::new&lt;/code&gt;, we need to move that structure to the &lt;code&gt;Ref&lt;/code&gt; type we are going to create. This means create and copy the object bit by bit from the original. And because we copy the data the pointer points to instead of pointing to the newly created one, this causes the new list points to the old one.&lt;/p&gt;
&lt;h3 id=&quot;miscdev-initialization&quot;&gt;Miscdev initialization&lt;/h3&gt;
&lt;p&gt;This also happens to misc device we just learned. Its definition also has an intrusive, circular, double-linked list. That&#39;s why methods signature of &lt;code&gt;miscdev::Registration&lt;/code&gt; always requires &lt;code&gt;Pin&lt;/code&gt; upon registration:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;struct&lt;/span&gt;&lt;span&gt; miscdevice  &lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;	int&lt;/span&gt;&lt;span&gt; minor&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;	const char *&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;	const struct&lt;/span&gt;&lt;span&gt; file_operations &lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;*&lt;/span&gt;&lt;span&gt;fops&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;	struct&lt;/span&gt;&lt;span&gt; list_head list&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color: #616E88;&quot;&gt; // &amp;lt;==================&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;	struct&lt;/span&gt;&lt;span&gt; device &lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;*&lt;/span&gt;&lt;span&gt;parent&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;	struct&lt;/span&gt;&lt;span&gt; device &lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;*&lt;/span&gt;&lt;span&gt;this_device&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;	const struct&lt;/span&gt;&lt;span&gt; attribute_group &lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;**&lt;/span&gt;&lt;span&gt;groups&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;	const char *&lt;/span&gt;&lt;span&gt;nodename&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;	umode_t&lt;/span&gt;&lt;span&gt; mode&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;pub fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; new_pinned&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span&gt; fmt&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Arguments&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;,&lt;/span&gt;&lt;span&gt; open_data&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span&gt; T&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;OpenData&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Result&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Pin&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Box&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;Self&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;&amp;gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;    Options&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;register_new&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; open_data&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;pub fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; register&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    self:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Pin&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;amp;mut Self&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    name&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span&gt; fmt&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Arguments&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    open_data&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span&gt; T&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;OpenData&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Result&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;    Options&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;register&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; open_data&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can call &lt;code&gt;new&lt;/code&gt; and pin it manually before &lt;code&gt;register&lt;/code&gt;, or just call &lt;code&gt;new_pinned&lt;/code&gt; to do both thing at the same time. The interface enforces you to pin the date before registration.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;And that&#39;s the reason we use &lt;code&gt;new_pinned&lt;/code&gt; to create the misc device in previous post. The question we haven&#39;t solved is how do we also pin the mutex we just mentioned. This will leave to the next post to answer and I think it will also be the good timing to introduce what built-in concurrent primitives we can use in kernel.&lt;/p&gt;
&lt;h2 id=&quot;reference&quot;&gt;Reference&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://youtu.be/fVEeqo40IyQ&quot;&gt;Rust for Linux by Miguel Ojeda and Wedson Almeida Filho&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Rust Kernel Module: Character Device Driver</title>
        <published>2022-05-25T12:04:23+08:00</published>
        <updated>2022-05-25T12:04:23+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/posts/rust-kernel-module-02/"/>
        <id>https://wusyong.github.io/posts/rust-kernel-module-02/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/posts/rust-kernel-module-02/">&lt;p&gt;There&#39;s one kind of module called device driver which provides functionality for hardware like a serial port. On Unix, each piece of hardware is represented by a file located in &lt;code&gt;/dev&lt;/code&gt; named a device file (or sometimes called device node) which provides the means to communicate with the hardware. Devices are divided into two types: character devices and block devices. Block devices are usually used for storage hardwares since have buffers to handle requests with different scenario. Character device, on the other hand, can accept any length of bytes as they like.&lt;/p&gt;
&lt;h2 id=&quot;device-file-and-device-driver&quot;&gt;Device File and Device Driver&lt;/h2&gt;
&lt;p&gt;In our simple initramfs, we can see our console device file is controlled by a character device:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;# Add this line in the init script `qemu-init.sh` then run.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; busybox ls -l /dev/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;crw-------&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 1 0 0&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;   5,&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; May&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 21&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; 12:43 console&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If it starts with &lt;code&gt;c&lt;/code&gt; then it means character device. And if it&#39;s &lt;code&gt;b&lt;/code&gt;, it would be block device. Notice there are two numbers separated by a comma. These are driver&#39;s major number and minor number. The major number is a unique number tells you which driver is used to access the hardware. If you see multiple device file with same major number, they are controlled by the same device driver. The minor number is used by the driver to distinguish between the various hardware it controls. Imagine there&#39;s a storage hardware might contain multiple partitions, so there might be multiple device files in &lt;code&gt;/dev&lt;/code&gt; with same major number. The device driver will use minor number to distinguish different partitions.&lt;/p&gt;
&lt;p&gt;To create a device file, we can use &lt;code&gt;mknod&lt;/code&gt; command to create the node. For example, &lt;code&gt;mknod /dev/covfefe c 12 2&lt;/code&gt; will create your device file &lt;code&gt;dev/covfefe&lt;/code&gt; as character device with major number 12 and minor number 2. And since we use &lt;code&gt;usr/gen_init_cpio&lt;/code&gt; to generate our initramfs, it also supports creating nodes with &lt;code&gt;nod &amp;lt;name&amp;gt; &amp;lt;mode&amp;gt; &amp;lt;uid&amp;gt; &amp;lt;gid&amp;gt; &amp;lt;dev_type&amp;gt; &amp;lt;maj&amp;gt; &amp;lt;min&amp;gt;&lt;/code&gt;. So if you want to create &lt;code&gt;console&lt;/code&gt; statically, you can add the line like &lt;code&gt;nod /dev/console 0600 0 0 c 5 1&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;While we can create device files from this for sure, this isn&#39;t the best way to do it because we might create files with conflicted major number accidentally. Kernel can create and generate major number dynamically nowadays. We could choose this approach instead. There are also another kind of module even suit for us. I will demonstrate it pretty soon along the way.&lt;/p&gt;
&lt;h3 id=&quot;more-file-system-support&quot;&gt;More File System Support&lt;/h3&gt;
&lt;p&gt;Before we proceed, I would like to introduce a few more file systems for us to mount. So we can interact to our character devices and get some more information about them. Let&#39;s add following configurations:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Run &lt;code&gt;make menuconfig&lt;/code&gt; and check these options:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ Device Drivers -&amp;gt; Generic Driver Options -&amp;gt; Maintain a devtmpfs filesystem to mount at /dev&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ File Systems -&amp;gt; Pseudo filesystems -&amp;gt; /proc file system support&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ File Systems -&amp;gt; Pseudo filesystems -&amp;gt; /sysfs file system support&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;In &lt;code&gt;qemu-initramfs.desc&lt;/code&gt;, it should have these at least:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;dir     /bin                                          0755 0 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;dir     /sys                                          0755 0 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;dir     /dev                                          0755 0 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;dir     /proc                                         0755 0 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;file    /bin/busybox  busybox                         0755 0 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;slink   /bin/sh       /bin/busybox                    0755 0 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;file    /init         .github/workflows/qemu-init.sh  0755 0 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;file    /rust_chrdev.ko  samples/rust/rust_chrdev.ko  0755 0 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;file    /rust_miscdev.ko samples/rust/rust_miscdev.ko 0755 0 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# Other kernel modules...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Update our &lt;code&gt;qemu-init.sh&lt;/code&gt;. You can add whatever commands you want to add. Just don&#39;t &lt;code&gt;rmmod&lt;/code&gt; modules we just list. To interact with our character devices, we need a shell with job control enabled. The last line in init script is usually used for &lt;a rel=&quot;external&quot; href=&quot;https://wiki.gentoo.org/wiki/Custom_Initramfs#Rescue_shell&quot;&gt;rescue shell&lt;/a&gt;, but it also works perfectly in our case.  You can also unmount at the end of the script. But since we are not going to do anything afterwards, it&#39;s not really necessary.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;#!/bin/sh&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;busybox&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; mount -t devtmpfs none /dev&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;busybox&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; mount -t proc none /proc&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;busybox&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; mount -t sysfs none /sys&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;busybox&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; insmod rust_chrdev.ko&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;busybox&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; insmod rust_miscdev.ko&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;busybox&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; insmod rust_semaphore.ko&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;busybox&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; setsid sh -c&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;exec sh -l &amp;lt;/dev/ttyS0 &amp;gt;/dev/ttyS0 2&amp;gt;&amp;amp;1&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Okay let&#39;s build the kernel and image again, run via qemu, and you should get the shell prompt. This time you should see devices created by &lt;code&gt;devtmpfs&lt;/code&gt;, and it should also contain some we just installed:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; busybox ls -l /dev&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;crw-------&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt;    1 0 0&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;   10,&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 126&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; May&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 21&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; 15:59 rust_miscdev&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;crw-------&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt;    1 0 0&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;   10,&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 125&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; May&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 21&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; 15:59 rust_semaphore&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;device-registration-and-file-operations&quot;&gt;Device Registration and file::Operations&lt;/h2&gt;
&lt;p&gt;Alright! Let&#39;s see how does the code work, starting with &lt;code&gt;rust_chrdev.rs&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;struct&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; RustChrdev&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    _dev&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Pin&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Box&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;chrdev&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Registration&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;&amp;gt;&amp;gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;impl&lt;/span&gt;&lt;span&gt; kernel&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Module&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; for&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; RustChrdev&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; init&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;static CStr&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; module&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;static ThisModule&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Result&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;Self&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt;        pr_info!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;Rust character device sample (init)&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;        let mut&lt;/span&gt;&lt;span&gt; chrdev_reg&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span&gt; chrdev&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Registration&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;new_pinned&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; module&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;        // Register the same kind of device twice, we&amp;#39;re just demonstrating&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;        // that you can use multiple minors. There are two minors in this case&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;        // because its type is `chrdev::Registration&amp;lt;2&amp;gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        chrdev_reg&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;as_mut&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;register&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;RustFile&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;()&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        chrdev_reg&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;as_mut&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;register&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;RustFile&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;()&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;        Ok&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;RustChrdev&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;span&gt; _dev&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span&gt; chrdev_reg&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;First we can notice the module declares a new field with type of pinned &lt;code&gt;chrdev::Registration&lt;/code&gt;. We create the instance via &lt;code&gt;new_pinned&lt;/code&gt; with arguments &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;module&lt;/code&gt;, and a number &lt;code&gt;0&lt;/code&gt; indicate the starting minor number. Don&#39;t worry about what&#39;s &lt;code&gt;Pin&lt;/code&gt; for now. We will discuss it in the future post. To register a character device, we call &lt;code&gt;register&lt;/code&gt; method. It accept any generic has the trait &lt;code&gt;file::Operations&lt;/code&gt; which we will explain later. In this case, we define a &lt;code&gt;RustFile&lt;/code&gt; for it. Notice we can register the same kind of device twice because our type uses const generic and its type is &lt;code&gt;chrdev::Registration&amp;lt;2&amp;gt;&lt;/code&gt;. This matches what we just said above: a device driver can control multiple minors. Next, let&#39;s shift our focus to &lt;code&gt;RustFile&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;struct&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; RustFile&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;impl&lt;/span&gt;&lt;span&gt; file&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Operations&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; for&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; RustFile&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    kernel&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt;declare_file_operations!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; open&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;_shared&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(),&lt;/span&gt;&lt;span&gt; _file&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span&gt;file&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;File&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Result&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;        Ok&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see it doesn&#39;t contain many things yet. But the &lt;code&gt;file::Operations&lt;/code&gt; trait actually has more methods can implement, we just define an pretty empty one first. The whole trait definition looks like this:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;pub trait&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;font-weight: bold;&quot;&gt; Operations&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    type&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Data&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; PointerWrapper&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Send&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Sync&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; ();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    type&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; OpenData&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Sync&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; ();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    const&lt;/span&gt;&lt;span&gt; TO_USE&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; ToUse&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; open&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: &amp;amp;Self::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;OpenData&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; file&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;File&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Result&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;Self::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Data&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; read&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        _data&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;Self::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Data&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; as&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; PointerWrapper&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Borrowed&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        _file&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;File&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        _writer&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: &amp;amp;mut impl&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; IoBufferWriter&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        _offset&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; u64&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    )&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Result&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt; {&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; ...&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; write&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        _data&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;Self::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Data&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; as&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; PointerWrapper&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Borrowed&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        _file&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;File&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        _reader&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: &amp;amp;mut impl&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; IoBufferReader&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        _offset&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; u64&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    )&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Result&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt; {&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; ...&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;    //...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All methods except &lt;code&gt;open&lt;/code&gt; have default implementation which just returns &lt;code&gt;EINVAL&lt;/code&gt; invalid argument signal. So types implement &lt;code&gt;file::Operations&lt;/code&gt; trait must define &lt;code&gt;open&lt;/code&gt; at least. The trait has two associated types &lt;code&gt;OpenData&lt;/code&gt; and &lt;code&gt;Data&lt;/code&gt;. &lt;code&gt;OpenData&lt;/code&gt; is used for &lt;code&gt;open&lt;/code&gt; method, it&#39;s passed as an argument when we call &lt;code&gt;register&lt;/code&gt;. And &lt;code&gt;Data&lt;/code&gt; is returned by &lt;code&gt;open&lt;/code&gt; method and made available to other methods. Since we haven&#39;t done anything yet, they are both &lt;code&gt;()&lt;/code&gt; for now and Rust can derive them automatically so we don&#39;t need to specify them explicitly.&lt;/p&gt;
&lt;p&gt;Last, we have macro &lt;code&gt;kernel::declare_file_operations!()&lt;/code&gt; to help generating &lt;code&gt;TO_USE&lt;/code&gt; constant. It&#39;s a list of bool to decide which methods will be used as callbacks in the end. In our example, we do nothing for now, so all methods except &lt;code&gt;open&lt;/code&gt; will be None (and hence be NULL in &lt;code&gt;files_operation&lt;/code&gt; bindings.)&lt;/p&gt;
&lt;h3 id=&quot;miscellaneous-device-driver&quot;&gt;Miscellaneous Device Driver&lt;/h3&gt;
&lt;p&gt;We discussed that it&#39;s not safe to assign a major number to create device file manually. And when we called &lt;code&gt;register method&lt;/code&gt;, it pass &lt;code&gt;0&lt;/code&gt; under the hood which will let kernel dynamically allocate the major number. The newly registered device will have an entry in &lt;code&gt;/proc/devices&lt;/code&gt;. We can see the major number by command &lt;code&gt;busybox more /proc/devices&lt;/code&gt;. To make the device file, we can either call &lt;code&gt;mknod&lt;/code&gt; command or use &lt;code&gt;device_create&lt;/code&gt; function in C FFI manner. But we also have another choice which can create the device node when we just call &lt;code&gt;register&lt;/code&gt;. It is called Miscellaneous Character Drivers.&lt;/p&gt;
&lt;p&gt;Miscellaneous character drivers (short for &lt;code&gt;miscdev&lt;/code&gt;) is a subset of character drivers which different drivers will all share the same major number and make minor numbers as their identifier. This is pretty useful when your driver only controls one device, because it will save all the unnecessary minor space. Running &lt;code&gt;busybox more /proc/misc&lt;/code&gt; will show all miscdev&#39;s minor numbers. What&#39;s really convenient is when a miscdev is registered, kernel will create a device node under &lt;code&gt;/dev&lt;/code&gt; right away. This suits us pretty well for our upcoming examples. So let&#39;s update our chrdev sample to become a miscdev and find how to interact with it! We&#39;ll create a module that can show some strings when it&#39;s being opened and read, such as &lt;code&gt;cat /dev/rust_chrdev&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;// Update your imports to these&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;use&lt;/span&gt;&lt;span&gt; core&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;sync&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;atomic&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;AtomicBool&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; AtomicU64&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Ordering&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;use&lt;/span&gt;&lt;span&gt; kernel&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;io_buffer&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::*&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;use&lt;/span&gt;&lt;span&gt; kernel&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;prelude&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::*&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;use&lt;/span&gt;&lt;span&gt; kernel&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;str&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;CString&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;use&lt;/span&gt;&lt;span&gt; kernel&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;sync&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Ref&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; RefBorrow&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;use&lt;/span&gt;&lt;span&gt; kernel&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;{&lt;/span&gt;&lt;span&gt;file&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; miscdev&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;struct&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; SharedState&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    already_opened&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; AtomicBool&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    count&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; AtomicU64&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;struct&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; RustChrdev&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    _dev&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Pin&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Box&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;miscdev&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Registration&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;RustFile&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;&amp;gt;&amp;gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;impl&lt;/span&gt;&lt;span&gt; kernel&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Module&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; for&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; RustChrdev&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; init&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;static CStr&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; _module&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;static ThisModule&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Result&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;Self&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt;        pr_info!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;Rust character device sample (init)&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;        let&lt;/span&gt;&lt;span&gt; state&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Ref&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;try_new&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;SharedState&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            already_opened&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span&gt; AtomicBool&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            count&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span&gt; AtomicU64&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;        })&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;        let&lt;/span&gt;&lt;span&gt; miscdev_reg&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span&gt; miscdev&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Registration&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;new_pinned&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt;fmt!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;),&lt;/span&gt;&lt;span&gt; state&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;        Ok&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;RustChrdev&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;span&gt; _dev&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span&gt; miscdev_reg&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You will notice a few signatures have been changed but their types should still be similar. We now declare the module with &lt;code&gt;miscdev::Registration&lt;/code&gt; and it accepts just a generic that has &lt;code&gt;file::Operations&lt;/code&gt; trait instead. Parameters of &lt;code&gt;new_pinned&lt;/code&gt; is also a little bit different because &lt;code&gt;miscdev&lt;/code&gt; can take an argument for &lt;code&gt;OpenData&lt;/code&gt;. This time we actually want to pass some thing for our driver. So we declare a new type &lt;code&gt;SharedState&lt;/code&gt; which contains a few atomic types. Notice we also create the instance with &lt;code&gt;Ref&lt;/code&gt; type. This is the reference counted pointer &lt;code&gt;refcount_t&lt;/code&gt; in kernel which serve the same purpose as &lt;code&gt;Arc&lt;/code&gt; in rust &lt;code&gt;std&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In the multiple-threaded environment, without any protection, concurrent access to the same memory may lead to the race condition, and will not preserve the performance. In the kernel module, this problem may happen due to multiple instances accessing the shared resources. Fortunately, &lt;code&gt;OpenData&lt;/code&gt; and &lt;code&gt;Data&lt;/code&gt; in &lt;code&gt;file::Operations&lt;/code&gt; are passed as immutable reference. You can&#39;t modify it unless you define with types that promise synchronization. We will introduce other concurrency primitives in later posts. For now, let&#39;s just use reference count with atomic combination to let processor handle for you. Now let&#39;s update our &lt;code&gt;RustFile&lt;/code&gt; as well to see how it utilize &lt;code&gt;SharedState&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;struct&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; RustFile&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;impl&lt;/span&gt;&lt;span&gt; file&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Operations&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; for&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; RustFile&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    type&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; OpenData&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Ref&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;SharedState&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    type&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Data&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Ref&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;SharedState&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    kernel&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt;declare_file_operations!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;read&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; write&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;    /// Called when a process tries to open the device file, such as `cat /dev/rust_chrdev`.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; open&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;shared&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Ref&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;SharedState&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;,&lt;/span&gt;&lt;span&gt; _&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span&gt;file&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;File&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Result&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Ref&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;SharedState&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;        if&lt;/span&gt;&lt;span&gt; shared&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;            .&lt;/span&gt;&lt;span&gt;already_opened&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;            .&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;compare_exchange&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; true&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; Ordering&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Acquire&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; Ordering&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Relaxed&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;            .&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;is_ok&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            shared&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span&gt;count&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;fetch_add&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; Ordering&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;AcqRel&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;            Ok&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;shared&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;clone&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;        }&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; else&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;            Err&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;EBUSY&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;    /// Called when a process closes the device file.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; release&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;shared&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Ref&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;SharedState&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;,&lt;/span&gt;&lt;span&gt; _&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span&gt;file&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;File&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        shared&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span&gt;already_opened&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;store&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; Ordering&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Release&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;    /// Called when a process, which already opened the dev file, attempts to read from it.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; read&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        shared&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; RefBorrow&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; SharedState&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        _&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span&gt;file&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;File&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        data&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: &amp;amp;mut impl&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; IoBufferWriter&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        offset&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; u64&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    )&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Result&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;        // Succeed if the caller doesn&amp;#39;t provide a buffer or if not at the start.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;        if&lt;/span&gt;&lt;span&gt; data&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;is_empty&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; ||&lt;/span&gt;&lt;span&gt; offset&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; !=&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;            return&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Ok&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;        let&lt;/span&gt;&lt;span&gt; msg&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; CString&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;try_from_fmt&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt;fmt!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;            &amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;This is my &lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt;{}&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; times saying Hello World!&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            shared&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span&gt;count&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;load&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;Ordering&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Acquire&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;        ))&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;        // Put the message to the buffer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        data&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;write_slice&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;msg&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;as_bytes&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;())&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;        // Most read functions return the number of bytes put into the buffer.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;        Ok&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;msg&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;len&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;    /// Called when a process writes to dev file, such as `echo &amp;quot;hi&amp;quot; &amp;gt; /dev/hello`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; write&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        _&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; RefBorrow&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; SharedState&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        _&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span&gt;file&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;File&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        _&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: &amp;amp;mut impl&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; IoBufferReader&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        _&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; u64&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    )&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Result&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt;        pr_alert!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;Sorry, this operation is not supported.&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;        Err&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;EINVAL&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We need to declare the type of &lt;code&gt;Data&lt;/code&gt; and &lt;code&gt;OpenData&lt;/code&gt; since we now want to share some states. They can be different types, but it doesn&#39;t need to in this case. In this example we use &lt;code&gt;already_opened&lt;/code&gt; field which is a &lt;code&gt;AtomicBool&lt;/code&gt; to determine whether the file is currently opened by someone or not and then add the counter.&lt;/p&gt;
&lt;p&gt;This time we also have more operation methods, so we need to add them into &lt;code&gt;declare_file_operations!&lt;/code&gt; macro. Usually the only required methods are &lt;code&gt;open&lt;/code&gt; and &lt;code&gt;release&lt;/code&gt;, so what we only need to list in the macro would be &lt;code&gt;read&lt;/code&gt; and &lt;code&gt;write&lt;/code&gt;. In &lt;code&gt;read&lt;/code&gt; method, you can see how to create a message and put into buffer. While we don&#39;t do anything in &lt;code&gt;write&lt;/code&gt; method, we still add this to demonstrate how to catch these attempts and tell the user that the operation is not supported.&lt;/p&gt;
&lt;p&gt;Build and run the kernel again and you should find there&#39;s a device file &lt;code&gt;rust_chardev&lt;/code&gt; under &lt;code&gt;/dev&lt;/code&gt; and see how many times &quot;Hello World&quot; are being called via &lt;code&gt;busybox cat /dev/rust_chrdev&lt;/code&gt;. Running command &lt;code&gt;busybox more /proc/misc&lt;/code&gt; will show that is now a miscdev and you can get its minor number.&lt;/p&gt;
&lt;h3 id=&quot;device-unregistration&quot;&gt;Device Unregistration&lt;/h3&gt;
&lt;p&gt;Last we need to talk about unregistration. We can not allow &lt;code&gt;rmmod&lt;/code&gt; to remove the kernel module that is being used. When you call &lt;code&gt;cat /proc/modules&lt;/code&gt; or &lt;code&gt;lsmod&lt;/code&gt;, the third field is the counter of how many processes are using that module. It&#39;s increase when &lt;code&gt;open&lt;/code&gt; is called and decrease when &lt;code&gt;release&lt;/code&gt;. The check is performed by system call &lt;code&gt;sys_delete_module&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Congratulations! Your kernel module start doing something. While it&#39;s not pretty meaningful, it will get more and more powerful as we add more types and functions into our tool belt. Next will be concurrency primitives like Mutex lock. But before we explore them, we will have to figure out why some types must be pinned.&lt;/p&gt;
&lt;h2 id=&quot;reference&quot;&gt;Reference&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://sysprog21.github.io/lkmpg/#character-device-drivers&quot;&gt;The Linux Kernel Module Programming Guide: Character Device drivers&lt;/a&gt;&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Rust Kernel Module: Hello World</title>
        <published>2022-05-18T12:04:23+08:00</published>
        <updated>2022-05-18T12:04:23+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/posts/rust-kernel-module-01/"/>
        <id>https://wusyong.github.io/posts/rust-kernel-module-01/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/posts/rust-kernel-module-01/">&lt;p&gt;In &lt;a href=&quot;/posts/rust-kernel-module-00&quot;&gt;previous post&lt;/a&gt;, we set up our environment to develop Linux kernel module in Rust. Now we can kick start our journey. Like every programming tutorial, we must start with a &quot;Hello World&quot; example. It is the law!&lt;/p&gt;
&lt;p&gt;While there are already many samples under &lt;code&gt;samples/rust&lt;/code&gt; directory, I&#39;ll still write a simple example to showcase how to add a module to our compiled kernel. Once you learn how to do it, you can add as many as you want.&lt;/p&gt;
&lt;h2 id=&quot;the-simplest-module&quot;&gt;The Simplest Module&lt;/h2&gt;
&lt;p&gt;To add a kernel module, there are a few files need to configure since we choose to compile Linux kernel on our own. But this is safer approach IMHO. This doesn&#39;t need to be the final workflow for you, but you should follow the safety measurement it obeys. First of all, let&#39;s add additional option to build a new kernel module called &lt;code&gt;rust_hello&lt;/code&gt;. Try to add following configurations and files under other modules:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;In &lt;code&gt;samples/rust/Kconfig&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;config&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; SAMPLE_RUST_HELLO&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;	tristate&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;Hello&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;	help&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;	  This&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; option builds the Rust hello module sample.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;	  To&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; compile this as a module, choose M here:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;	  the&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; module will be called rust_hello.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;	  If&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; unsure, say N.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;In &lt;code&gt;samples/rust/Makefile&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;make&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;obj-&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;$(&lt;/span&gt;&lt;span&gt;CONFIG_SAMPLE_RUST_HELLO&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;	+=&lt;/span&gt;&lt;span&gt; rust_hello.o&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Add a new rust file &lt;code&gt;samples/rust/rust_hello.rs&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;// SPDX-License-Identifier: GPL-2.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;//! Rust hello sample.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;use&lt;/span&gt;&lt;span&gt; kernel&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;prelude&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::*&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt;module!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    type:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; RustHello&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    name&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;rust_hello&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    author&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;Rust for Linux Contributors&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    description&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;Rust hello sample&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    license&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;GPL v2&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;struct&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; RustHello&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    message&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; String&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;impl&lt;/span&gt;&lt;span&gt; kernel&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Module&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; for&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; RustHello&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; init&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;_name&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;static CStr&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; _module&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;static ThisModule&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Result&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;Self&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt;        pr_info!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;Rust hello sample (init)&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt;        pr_info!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;Am I built-in? &lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt;{}\n&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;,&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; !&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt;cfg!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;MODULE&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;        Ok&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;RustHello&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            message&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;on the heap!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;try_to_owned&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;        })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;impl&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Drop&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; for&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; RustHello&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; drop&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;amp;mut self&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt;        pr_info!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;My message is &lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt;{}\n&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;,&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; self.&lt;/span&gt;&lt;span&gt;message&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt;        pr_info!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;Rust hello sample (exit)&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;build-and-run-the-kernel-again&quot;&gt;Build and Run the Kernel again&lt;/h3&gt;
&lt;p&gt;This is in fact just &lt;code&gt;rust_minimal&lt;/code&gt; example with renaming. It&#39;s okay to skip adding this if you just want to learn how to do it instead of practicing yourself. To enable the module, run &lt;code&gt;make menuconfig&lt;/code&gt; and toggle it to &lt;code&gt;M&lt;/code&gt; in &lt;code&gt;Kernel hacking --&amp;gt; Sample kernel code --&amp;gt; Rust samples --&amp;gt; Hello&lt;/code&gt;. Next, we have to build it and include it into our file system:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Build Linux kernel again. But this time, it should just build the kernel module we added:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;make&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; LLVM=&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; -j&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;$(&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;nproc&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Build new image to include our kernel module. In &lt;code&gt;.github/workflows/qemu-initramfs.desc&lt;/code&gt;, add another line under other modules and then build it again:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;file /rust_hello.ko samples/rust/rust_hello.ko 0755 0 0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;usr/gen_init_cpio&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; .github/workflows/qemu-initramfs.desc&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; &amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; qemu-initramfs.img&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Also add another command under other modules in &lt;code&gt;.github/workflows/qemu-init.sh&lt;/code&gt;. This script is what we tell busybox to do upon initialization:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;busybox&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; modinfo rust_hello.ko&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;busybox&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; insmod rust_hello.ko&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;busybox&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; lsmod&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;busybox&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; rmmod rust_hello.ko&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Run the kernel via qemu again. This time you should see the log from the kernel we just built.&lt;/p&gt;
&lt;h3 id=&quot;command-helpers-and-tools&quot;&gt;Command Helpers and Tools&lt;/h3&gt;
&lt;p&gt;We&#39;ll introduce a few commands relate to kernel module. &lt;code&gt;modinfo&lt;/code&gt; will show the info of our kernel module. &lt;code&gt;lsmod&lt;/code&gt; will show what modules are already loaded within your current kernel. Modules are stored within &lt;code&gt;/proc/modules&lt;/code&gt;, so you can also see them with &lt;code&gt;cat /proc/modules&lt;/code&gt;. &lt;code&gt;inmosd&lt;/code&gt; will load the module you provide, and &lt;code&gt;rmmod&lt;/code&gt; will remove it. If you follow this guide from the start, you should see the logs about kernel module when running qemu. But if you run the kernel natively, you can run &lt;code&gt;journalctl&lt;/code&gt; to get the logs. Or if you are debugging with GDB like we mentioned before, run &lt;code&gt;lx-dmesg&lt;/code&gt; in debugger to see them.&lt;/p&gt;
&lt;p&gt;Now we know how to create, compile, and install the new kernel module. Let&#39;s see how the kernel module actually works. Before we deep dive into the code, please allow me to introduce a few tools and commands that will benefit us significantly. The first is documentation, Linux can build and read &lt;code&gt;rustdoc&lt;/code&gt; for its &lt;code&gt;kernel&lt;/code&gt; crate with this command:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;make&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; LLVM=&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; rustdoc&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;xdg-open&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; rust/doc/kernel/index.html&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The documentation is pretty comprehensive, I believe many people can even read it themselves and learn even more beyond our guides could teach. Next is formatting and lints. Linux also supports &lt;code&gt;rustfmt&lt;/code&gt; and &lt;code&gt;clippy&lt;/code&gt;, so you shouldn&#39;t be afraid of inconsistent code style. Rust will guide you how to comply:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;make&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; LLVM=&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; rustfmt&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;make&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; LLVM=&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; CLIPPY=&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, we have language server protocol support. Yes! Linux supports &lt;code&gt;rust_analyzer&lt;/code&gt; too! Run the following command to create &lt;code&gt;rust-project.json&lt;/code&gt; configuration and you will gain full LSP support on whatever IDE you uses:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;make&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; LLVM=&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; rust-analyzer&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/uIEG241.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;h2 id=&quot;macros-and-types-from-kernel-crate&quot;&gt;Macros and Types from &lt;code&gt;kernel&lt;/code&gt; Crate&lt;/h2&gt;
&lt;p&gt;Alright! Everything is set! Let&#39;s see how does the code work. Unlike normal Rust program, we can&#39;t simply use standard library &lt;code&gt;std&lt;/code&gt;. But we can still import &lt;code&gt;core&lt;/code&gt; and &lt;code&gt;alloc&lt;/code&gt; crates, types require heap allocation like &lt;code&gt;String&lt;/code&gt; is still possible to use. And the most important crate is probably the &lt;code&gt;kernel&lt;/code&gt; crate. It contains kernel APIs that have been ported or wrapped for usage by Rust code in the kernel and is shared by all of them. Like most rust crates, it provides a prelude module for us to import some common items.&lt;/p&gt;
&lt;p&gt;The first one we must add is &lt;code&gt;module!&lt;/code&gt; macro. This is the macro to declare a kernel module. You can see its description from documentation or even just hover it via rust-analyzer. You&#39;ll learn its usage, example, and all supported argument and parameter types. There are three argument types you must add to complete the macro:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;type&lt;/code&gt;: The type we are going to implement the &lt;code&gt;Module&lt;/code&gt; trait which we will demonstrate soon.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;name&lt;/code&gt;: Your kernel module name.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;license&lt;/code&gt;: Your kernel module license. Some examples include &quot;GPL&quot;, &quot;GPL v2&quot;, &quot;GPL and additional rights&quot;, &quot;Dual BSD/GPL&quot;, &quot;Dual MIT/GPL&quot;, &quot;Dual MPL/GPL&quot; and &quot;Proprietary&quot;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To add logics for the kernel module, we can define any type as long as it implements &lt;code&gt;Module&lt;/code&gt; trait. The trait&#39;s signature looks like this:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;pub trait&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;font-weight: bold;&quot;&gt; Module&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Sized&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Sync&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; init&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;static CStr&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; module&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;static ThisModule&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Result&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;Self&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The method &lt;code&gt;init&lt;/code&gt; is equivalent to the &lt;code&gt;module_init&lt;/code&gt; macro in the C API. We create the instance via this method. Since Rust ownership can manage our memory properly, it&#39;s not necessary to implement &lt;code&gt;Drop&lt;/code&gt; trait which is equivalent to the &lt;code&gt;module_exit&lt;/code&gt; macro in the C API. In our hello world example, we still do this to show when will the module exit.&lt;/p&gt;
&lt;p&gt;Notice we use &lt;code&gt;pr_info&lt;/code&gt; macro instead of &lt;code&gt;println&lt;/code&gt;, but the usage is pretty similar. This maps to kernel&#39;s print macros. It follows most log level for different conditions. There are also other print macros like &lt;code&gt;pr_err&lt;/code&gt;, &lt;code&gt;pr_alert&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;passing-command-line-arguments-to-a-module&quot;&gt;Passing Command Line Arguments to a Module&lt;/h2&gt;
&lt;p&gt;Modules can take command line arguments too, but not from &lt;code&gt;env::args()&lt;/code&gt; you might used to. To allow arguments to be passed to your module, declare the parameter types in &lt;code&gt;modules!&lt;/code&gt; macro. Let&#39;s see the example from &lt;code&gt;samples/rust/rust_module_parameters.rs&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;// SPDX-License-Identifier: GPL-2.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;//! Rust module parameters sample.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;use&lt;/span&gt;&lt;span&gt; kernel&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;prelude&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::*&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt;module!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    type:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; RustModuleParameters&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    name&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;rust_module_parameters&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    author&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;Rust for Linux Contributors&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    description&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;Rust module parameters sample&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    license&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;GPL v2&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    params&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        my_bool&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; bool&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            default&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: true&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            permissions&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            description&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;Example of bool&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;        },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        my_i32&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; i32&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            default&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 42&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            permissions&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 0o644&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            description&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;Example of i32&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;        },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        my_str&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; str&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            default&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;default str val&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            permissions&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 0o644&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            description&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;Example of a string param&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;        },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        my_usize&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; usize&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            default&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 42&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            permissions&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 0o644&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            description&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;Example of usize&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;        },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        my_array&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; ArrayParam&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;i32&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; 3&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            default&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            permissions&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            description&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;Example of array&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;        },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;struct&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; RustModuleParameters&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;impl&lt;/span&gt;&lt;span&gt; kernel&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Module&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; for&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; RustModuleParameters&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; init&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;_name&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;static CStr&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; module&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;static ThisModule&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Result&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;Self&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt;        pr_info!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;Rust module parameters sample (init)&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;            let&lt;/span&gt;&lt;span&gt; lock&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span&gt; module&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;kernel_param_lock&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt;            pr_info!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;Parameters:&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt;            pr_info!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;  my_bool:    &lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt;{}\n&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;,&lt;/span&gt;&lt;span&gt; my_bool&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;read&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt;            pr_info!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;  my_i32:     &lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt;{}\n&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;,&lt;/span&gt;&lt;span&gt; my_i32&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;read&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;lock&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt;            pr_info!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;                &amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;  my_str:     &lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt;{}\n&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                core&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;str&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;from_utf8&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;my_str&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;read&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;lock&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;))&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;?&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;            );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt;            pr_info!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;  my_usize:   &lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt;{}\n&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;,&lt;/span&gt;&lt;span&gt; my_usize&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;read&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;lock&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt;            pr_info!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;  my_array:   &lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;:?&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt;}\n&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;,&lt;/span&gt;&lt;span&gt; my_array&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;read&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;        Ok&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;RustModuleParameters&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;impl&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Drop&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; for&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; RustModuleParameters&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; drop&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;amp;mut self&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt;        pr_info!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;Rust module parameters sample (exit)&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To add a parameter, we declare its type, default value, permission, and description. As we already saw the documentation of &lt;code&gt;module!&lt;/code&gt; macro, it supports most primitive types. It can also support arrays via const generic &lt;code&gt;ArrayParam&amp;lt;T, N&amp;gt;&lt;/code&gt;. At the time of this post, const generic only support numeric types, but this should cover most of our use cases.&lt;/p&gt;
&lt;p&gt;In the init script &lt;code&gt;.github/workflows/qemu-init.sh&lt;/code&gt;, &lt;code&gt;insmod&lt;/code&gt; will fill the variables with any command line arguments that are given. The parameter that doesn&#39;t get the value from here will set to default value. We can pass the argument like this:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;busybox&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; insmod rust_module_parameters.ko&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;    my_bool=n&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;    my_i32=&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt;345543&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;    my_str=🦀mod&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;    my_usize=&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt;84&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;    my_array=1,2,3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;busybox&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;  rmmod rust_module_parameters.ko&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To read the values, some types require scoped lock, we can get it from &lt;code&gt;module.kernel_param_lock()&lt;/code&gt;. Then you&#39;ll retrieve values from &lt;code&gt;read()&lt;/code&gt; method. The lock will be dropped once it&#39;s out of the scope. Kernel parameters are usually used to have the module variable’s default values set, like a port or IO address. If the variables contain the default values, then perform auto-detection (explained elsewhere). Otherwise, keep the current value. This will be made clear later on.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;And that&#39;s it! Now you should have the basic idea about how to write and build the kernel module. Feel free to play around with config files, scripts, and kernel modules either it&#39;s existing one or the one you create. The documentation is also comprehensive enough, I&#39;m confident many people can even learn it themselves starting from here. But don&#39;t worry if you don&#39;t know how to proceed. I&#39;ll publish more posts in the future. Next time we will try to write another simple kernel module: Character Device drivers.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Rust Kernel Module: Getting Started</title>
        <published>2022-05-04T12:04:23+08:00</published>
        <updated>2022-05-04T12:04:23+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/posts/rust-kernel-module-00/"/>
        <id>https://wusyong.github.io/posts/rust-kernel-module-00/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/posts/rust-kernel-module-00/">&lt;p&gt;Linux-next has &lt;a rel=&quot;external&quot; href=&quot;https://lwn.net/Articles/849849/&quot;&gt;Rust support&lt;/a&gt; for a while. While it&#39;s still not really in the mainline yet, the whole Rust stack in Linux is pretty solid already. From compiling to debugging, I can confirm the development workflow for Rust kernel modules is surprisingly seamless. In this post, I&#39;m going to introduce you how to setup the development environment for Linux Kernel. So you can build the modules and test it.&lt;/p&gt;
&lt;p&gt;I know setup whole kernel is incredibly cumbersome, and theoretically we can just build the modules from linux headers. In fact, the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/fishinabarrel/linux-kernel-module-rust&quot;&gt;old project&lt;/a&gt; for Rust kernel module actually did this approach already. But testing programs without any kind of sandbox is dangerous and error prone. We should build common sense that sandbox is crucial for any project IMHO. Just bear with me throughout these steps. It&#39;s going to be easier and more fun after all of these.&lt;/p&gt;
&lt;h2 id=&quot;getting-started&quot;&gt;Getting Started&lt;/h2&gt;
&lt;p&gt;To get the source code, we can clone the Linux repository from Rust-for-Linux organization:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; git clone https://github.com/Rust-for-Linux/linux.git&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;dependencies&quot;&gt;Dependencies&lt;/h3&gt;
&lt;p&gt;Next we need to prepare all dependencies required. Quick start guide from &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Rust-for-Linux/linux/blob/rust/Documentation/rust/quick-start.rst&quot;&gt;&lt;code&gt;Documentation/rust&lt;/code&gt;&lt;/a&gt; also lists all the requirements already. Feel free to follow it instead for this step.&lt;/p&gt;
&lt;h4 id=&quot;system-requirements&quot;&gt;System Requirements&lt;/h4&gt;
&lt;p&gt;The first one is of course all dependencies for compiling the kernel. For some distributions, they might already ship some of the packages. I&#39;ll only provide commands for debian-related distributions. But others should follow the same:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; sudo apt install libncurses-dev flex bison openssl libssl-dev&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;    dkms libelf-dev libudev-dev libpci-dev libiberty-dev autoconf&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&quot;qemu-gdb&quot;&gt;QEMU &amp;amp; GDB&lt;/h4&gt;
&lt;p&gt;And then is tools for testing and debugging, this includes all dependencies required from QEMU and GDB. In later post, we&#39;ll show how to run and debug kernel via attaching QEMU to GDB.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; sudo apt install qemu qemu-system qemu-kvm libvirt-daemon-system&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;    libvirt-clients bridge-utils&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; sudo apt install gdb&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;llvm-or-libclang&quot;&gt;LLVM (or libclang)&lt;/h3&gt;
&lt;p&gt;For simplicity, we will compile the kernel with LLVM. This is because we will use &lt;code&gt;bindgen&lt;/code&gt; to help Rust connect to the C code which requires &lt;code&gt;libclang&lt;/code&gt;. We will compile the kernel with &lt;code&gt;LLVM=1&lt;/code&gt;, or if your distribution doesn&#39;t support full toolchain, use with &lt;code&gt;CC=clang&lt;/code&gt;. Again, most distributions should ship with LLVM already. But if you are afraid of missing anything, run the following command:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; sudo apt install llvm lld libclang-dev&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;rust&quot;&gt;Rust&lt;/h3&gt;
&lt;p&gt;For your sanity, I really recommend &lt;a rel=&quot;external&quot; href=&quot;https://www.rust-lang.org/tools/install&quot;&gt;download and install Rust&lt;/a&gt; from the official site and remove other versions installed from other package managers. But if you insist, &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Rust-for-Linux/linux/blob/rust/Documentation/rust/quick-start.rst&quot;&gt;&lt;code&gt;Documentation/rust&lt;/code&gt;&lt;/a&gt; should also cover that. For the time of this post, Linux is still stick to a certain Rust version instead of stable. To get the toolchain of that version, run the following commands:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; rustup override set&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; $(&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;scripts/min-tool-version.sh&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; rustc&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; rustup component add rust-src&lt;/span&gt;&lt;span style=&quot;color: #616E88;&quot;&gt; # Rust standard library source&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And we also need to install &lt;code&gt;bindgen&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; cargo install --locked --version&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; $(&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;scripts/min-tool-version.sh&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; bindgen&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; bindgen&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;compiling-kernel&quot;&gt;Compiling Kernel&lt;/h2&gt;
&lt;p&gt;Alright, this is where the fun begins! We are ready to compile the Linux kernel. Before we start, let&#39;s check again and make sure the toolchain is correct:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; make LLVM=&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; rustavailable&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will use the same logic by Kconfig to determine if &lt;code&gt;RUST_IS_AVAILABLE&lt;/code&gt; should be enable. When you get a fresh kernel, it usually starts with &lt;code&gt;make menuconfig&lt;/code&gt; to create the &lt;code&gt;.config&lt;/code&gt; file. While we can use it to toggle the Rust support and all modules we want to build, we can also copy existing one from its CI workflow. We could get the most similar configurations from the upstream. In this post, I will assume you are under &lt;code&gt;x86_64&lt;/code&gt; architecture. If it&#39;s not, please take a look of its &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Rust-for-Linux/linux/blob/rust/.github/workflows/ci.yaml&quot;&gt;&lt;code&gt;ci.yaml&lt;/code&gt;&lt;/a&gt; and choose the closest possible config for you.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; cp .github/workflows/kernel-x86_64-debug.config .config&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;AAAAAAAAAAAAAAAAAAAAAND COMPILE!&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;make&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; LLVM=&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; -j&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;$(&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;nproc&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Take a coffee or go for a walk. It will take some time to complete. Once the compilation is done, you should found the kernel binary image under &lt;code&gt;arch/x86/boot/bzImage&lt;/code&gt; in Linux source directory.&lt;/p&gt;
&lt;h3 id=&quot;build-initramfs&quot;&gt;Build initramfs&lt;/h3&gt;
&lt;p&gt;Now we have the kernel, we could run with QMEU right? Well not quite, we still need a root filesystem for the kernel. Starting from here, there could be multiple approaches. Depends on your need, it could be totally different. I would say there&#39;s no one true ring to rule all of them. For example, You can use &lt;a rel=&quot;external&quot; href=&quot;https://buildroot.org/&quot;&gt;&lt;code&gt;Buildroot&lt;/code&gt;&lt;/a&gt; to setup as your drive. For us, we can just follow how CI does: Building initramfs. If you don&#39;t know what is initramfs, here&#39;s the quote from &lt;a rel=&quot;external&quot; href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/Documentation/filesystems/ramfs-rootfs-initramfs.txt?h=v4.9.30&quot;&gt;Linux kernel documentation&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;All 2.6 Linux kernels contain a gzipped &quot;cpio&quot; format archive, which is
extracted into rootfs when the kernel boots up. After extracting, the
kernel checks to see if rootfs contains a file &quot;init&quot;, and if so it executes
it as PID 1. If found, this init process is responsible for bringing the
system the rest of the way up, including locating and mounting the real root
device (if any). If rootfs does not contain an init program after the
embedded cpio archive is extracted into it, the kernel will fall through to
the older code to locate and mount a root partition, then exec some variant
of /sbin/init out of that.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I hope you got it, because I&#39;m going to introduce another tool we need: &lt;a rel=&quot;external&quot; href=&quot;https://www.busybox.net/downloads/binaries/&quot;&gt;&lt;code&gt;busybox&lt;/code&gt;&lt;/a&gt;. And I&#39;ll also drop another quote for you to understand:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;BusyBox combines tiny versions of many common UNIX utilities into a single small executable. It provides replacements for most of the utilities you usually find in GNU fileutils, shellutils, etc. The utilities in BusyBox generally have fewer options than their full-featured GNU cousins; however, the options that are included provide the expected functionality and behave very much like their GNU counterparts. BusyBox provides a fairly complete environment for any small or embedded system.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Whew that&#39;s quite a read. Don&#39;t worry about not fully understanding what they do. Because we only care about the setup and how to create the image for now. We&#39;ll come back to this if we really need some advanced configurations. The project itself already offer a script for us to create image:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; wget https://www.busybox.net/downloads/binaries/1.35.0-x86_64-linux-musl/busybox&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; usr/gen_init_cpio .github/workflows/qemu-initramfs.desc&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; &amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; qemu-initramfs.img&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;qemu-initramfs.desc&lt;/code&gt; might contain modules we didn&#39;t build. Just remove those lines if you get the errors.&lt;/p&gt;
&lt;h2 id=&quot;running-on-qemu&quot;&gt;Running on QEMU&lt;/h2&gt;
&lt;p&gt;Alright! This time is real. We are going to start QEMU on the compiled kernel:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In case you don&#39;t know how to exit &lt;del&gt;vim&lt;/del&gt; qemu: Ctrl+A then X&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; sudo qemu-system-x86_64&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;    -kernel arch/x86/boot/bzImage&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;    -initrd qemu-initramfs.img&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;    -M pc&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;    -m 4G&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;    -cpu Cascadelake-Server&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;    -smp&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; $(&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;nproc&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;    -nographic&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;    -vga none&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;    -no-reboot&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;    -append&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;console=ttyS0&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;See QEMU&#39;s &lt;a rel=&quot;external&quot; href=&quot;https://www.qemu.org/docs/master/system/invocation.html&quot;&gt;Invocation&lt;/a&gt; if you want to understand what each parameter does. If everything runs smoothly, it should look like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/5foNAMl.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Hooray! You just built a Linux kernel with Rust kernel modules loaded!&lt;/p&gt;
&lt;h2 id=&quot;debugging-with-gdb&quot;&gt;Debugging with GDB&lt;/h2&gt;
&lt;p&gt;Before we end the post, there&#39;s one more thing we haven&#39;t done yet. Running the kernel is one thing, how to debug it is another. While it&#39;s definitely a huge topic, I would like to give an entry point to let everyone know how to start the first step at least.&lt;/p&gt;
&lt;p&gt;To enable debugging, we need to make sure option &lt;code&gt;CONFIG_GDB_SCRIPTS&lt;/code&gt; is on and &lt;code&gt;CONFIG_DEBUG_INFO_REDUCED&lt;/code&gt; is off when building kernel. If you configure with &lt;code&gt;make menucofig&lt;/code&gt;, you can use &lt;code&gt;/&lt;/code&gt; to search these options and find their path to toggle. Build the kernel with &lt;code&gt;make LLVM=1 -j$(nproc)&lt;/code&gt; will create the kernel with symbols we need. With incremental compilations, it should take way lesser time to complete. This is also true when we focus on kernel modules later. We just need to compile the modules afterwards.&lt;/p&gt;
&lt;p&gt;Once it&#39;s finish again, you should see &lt;code&gt;vmlinux&lt;/code&gt; and &lt;code&gt;vmlinux-gdb.py&lt;/code&gt; in the root of project. &lt;code&gt;vmlinux&lt;/code&gt; is the target for GDB and &lt;code&gt;vmlinux-gdb.py&lt;/code&gt; is pre-defined GDB helpers. To get the commands (&lt;code&gt;lx-*&lt;/code&gt;) defined in &lt;code&gt;vmlinux-gdb.py&lt;/code&gt;, we add the script file to GDB’s auto load path. Some usages of the commands can be found in &lt;a rel=&quot;external&quot; href=&quot;https://docs.kernel.org/process/debugging/gdb-kernel-debugging.html&quot;&gt;GDB Kernel Debugging Page&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; echo&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;add-auto-load-safe-path path/to/vmlinux-gdb.py&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; &amp;gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; ~/.gdbinit&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let&#39;s run the kernel on QMEU again, but this time with a few more parameters added:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; sudo qemu-system-x86_64&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;    -kernel arch/x86/boot/bzImage&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;    -initrd qemu-initramfs.img&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;    -M pc&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;    -m 4G&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;    -cpu Cascadelake-Server&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;    -smp&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; $(&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;nproc&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;    -nographic&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;    -vga none&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;    -no-reboot&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;    -append&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;console=ttyS0 nokaslr&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;    -s -S&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We add &lt;code&gt;nokaslr&lt;/code&gt; boot parameter because GDB doesn&#39;t work well with KASLR on. We also use &lt;code&gt;-s -S&lt;/code&gt; combination to hold QEMU from booting the kernel until a GDB instance is attached. Now let&#39;s create another shell window to start GDB and attach then to QEMU. Starting from here we can now set breakpoints and debugging the kernel.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; gdb vmlinux&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(gdb) target remote :1234   # Attach to QEMU&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(gdb) hbreak start_kernel&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(gdb) c&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(gdb) b mm_alloc&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(gdb) c&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(gdb) lx-dmesg  # Display kernel dmesg log in GDB shell&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(gdb) ...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Okay we are finally done with building our first kernel. While this is just the first step, I believe this is the most difficult one and it will be more and more interesting from now on. In the next post, we&#39;ll start exploring the joy of writing kernel modules!&lt;/p&gt;
&lt;h2 id=&quot;reference&quot;&gt;Reference&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;https://mirrors.edge.kernel.org/pub/linux/kernel&lt;/li&gt;
&lt;li&gt;https://wiki.gentoo.org/wiki/Custom_Initramfs&lt;/li&gt;
&lt;li&gt;https://busybox.net/FAQ.html&lt;/li&gt;
&lt;li&gt;https://www.qemu.org/docs/master/system/index.html&lt;/li&gt;
&lt;li&gt;https://github.com/d0u9/Linux-Device-Driver/blob/draft/02_getting_start_with_driver_development/03_build_initramfs.md&lt;/li&gt;
&lt;li&gt;https://www.josehu.com/memo/2021/01/02/linux-kernel-build-debug.html#fn:2&lt;/li&gt;
&lt;/ol&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Overview of Servo</title>
        <published>2022-04-21T12:04:23+08:00</published>
        <updated>2022-04-21T12:04:23+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/posts/servo-01/"/>
        <id>https://wusyong.github.io/posts/servo-01/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/posts/servo-01/">&lt;p&gt;Before we deep dive into the code base of servo, I guess it&#39;s better to have a high level overview of it. Servo is a huge project and it contains over million lines of code. Sometimes it might be diificult to graspe where are you looking at or how each component interact with others. Getting a high level overview could help you building your own mental model. So let&#39;s get started:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/hb2SRa6.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;And that&#39;s it! Don&#39;t worry about what is each component and how do they do. We&#39;ll talk about them along the way. And of course it still simplifies and ignore many parts. These include &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/webrender&quot;&gt;Webrender&lt;/a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/surfman&quot;&gt;Surfman&lt;/a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/rust-mozjs&quot;&gt;Mozjs&lt;/a&gt;, and many other web features like &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/webxr&quot;&gt;WebXR&lt;/a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/media&quot;&gt;media&lt;/a&gt;, and WebGPU etc.&lt;/p&gt;
&lt;p&gt;What this overview trying to represent is how the main trunk of Servo looks like and where is the part handles web pages mostly. There are other processes and threads, but they will behave similar to how pipelines do.&lt;/p&gt;
&lt;h2 id=&quot;constellation&quot;&gt;Constellation&lt;/h2&gt;
&lt;p&gt;Let&#39;s start with the main process. There isn&#39;t actually a module called main process. But this helps us to understand who takes the big part in the center of Servo. &lt;strong&gt;Every rectangles it contains is a thread.&lt;/strong&gt; Threads with plural name mean they could be multi-threads.&lt;/p&gt;
&lt;p&gt;The most important thread we want to focus on is the &quot;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/blob/master/components/constellation/constellation.rs&quot;&gt;Constellation&lt;/a&gt;&quot;. &lt;strong&gt;It is the centeral station of the engine.&lt;/strong&gt; It stores core states of the engine like &quot;User Agent&quot; and also handles any workflow involving several components. The constellation the unique thread in Servo and there&#39;s no the other one. This means it couldn&#39;t get the deadlock and is also responsible for crash reporting.&lt;/p&gt;
&lt;p&gt;Interestingly, the constellatiion doesn&#39;t receive all messages from other processes directly. Main process has a IPC Router and receiving messages is its job instead. &lt;strong&gt;Every arrow you see is a &lt;a rel=&quot;external&quot; href=&quot;https://docs.rs/crossbeam-channel/latest/crossbeam_channel/&quot;&gt;Channel&lt;/a&gt;.&lt;/strong&gt; This allows the router thread to use &lt;code&gt;select!&lt;/code&gt; macro to re-route all IPC messages. The router also allows other threads in other processes to register callbacks to do some operations.&lt;/p&gt;
&lt;h3 id=&quot;embedder&quot;&gt;Embedder&lt;/h3&gt;
&lt;p&gt;Embedder itself in servo is actually just a few traits. It&#39;s a interface requires code who uses servo to implements. Thinking it&#39;s like several methods servo need users to define. So the implementation would be able to receive message from servo and handle its own event loop. For servo&#39;s demo, it uses winit&#39;s event loop and implements those traits for it.&lt;/p&gt;
&lt;h3 id=&quot;compositor&quot;&gt;Compositor&lt;/h3&gt;
&lt;p&gt;Graphic compositor is a thread renders the necessary pieces of the web pages. This includes iframe, animation and scroll bars etc. You can think it as a layer design to show what parts should be painted on the screen eventually.&lt;/p&gt;
&lt;h3 id=&quot;resource-thread&quot;&gt;Resource Thread&lt;/h3&gt;
&lt;p&gt;Resource thread&#39;s purpose is just like the name itself. Getting the resources from I/O, either from network or file system. It&#39;s a bit weird to include this thread into the main process instead of pipeline. But it will be created soon after constellation, because it will have to load some initial assets real soon. It&#39;s the few thread that doesn&#39;t communicate via IPC router. Script threads in pipeline are able to talk to it directly.&lt;/p&gt;
&lt;h2 id=&quot;pipeline-s&quot;&gt;Pipeline(s)&lt;/h2&gt;
&lt;p&gt;A &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/blob/master/components/constellation/pipeline.rs&quot;&gt;pipeline&lt;/a&gt; is a process for servo to load your page and maintain it. It&#39;s servo&#39;s view of a &quot;web page&quot; or a &quot;iframe&quot;, or we could just call it a &quot;Window&quot;. When the constellation want to load an url, it will get or create a &quot;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/blob/master/components/constellation/browsingcontext.rs&quot;&gt;BrowsingContext&lt;/a&gt;&quot;. It&#39;s servo&#39;s view of &quot;WindowProxy&quot; and it contains several states related to the page like session history. The constellation will spawn a pipeline and pair with it. You can treat them like a key value pair of a &lt;code&gt;HashMap&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;And yes, you can see there&#39;s a IPC router again. This is just like how main process routing incoming messages.&lt;/p&gt;
&lt;h3 id=&quot;script-threads&quot;&gt;Script Threads&lt;/h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/blob/f5a3d282fbc47177285d7635284d9bd1c00dc04a/components/script/script_thread.rs&quot;&gt;Script thread&lt;/a&gt; is the &quot;main thread&quot; of a pipeline. It runs the &lt;a rel=&quot;external&quot; href=&quot;https://html.spec.whatwg.org/multipage/webappapis.html#window-event-loop&quot;&gt;window event loop&lt;/a&gt; of a web page that belongs to the same &lt;code&gt;BrowsingContext&lt;/code&gt; and Origin. A pipeline could possibly share the same script thread because thread itself could potentially process multiple iframe with same origin.&lt;/p&gt;
&lt;p&gt;Script threads also connect the javasvript engine: Spider Monkey. In Rust, it&#39;s a wrapper crate called mozjs. Script itself defines the webIDL interface to communicate with it.&lt;/p&gt;
&lt;h3 id=&quot;layout-threads&quot;&gt;Layout Threads&lt;/h3&gt;
&lt;p&gt;For each pipeline, it will spawn a &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/blob/f5a3d282fbc47177285d7635284d9bd1c00dc04a/components/layout_thread/lib.rs&quot;&gt;layout thread&lt;/a&gt; and it doesn&#39;t share between pipeline. It process DOM tree and stylist created from CSS selector to produce the display lists. These lists are used for final graphic rendering. For example there might be a list to tell we need to render a rectangle and a triangle.&lt;/p&gt;
&lt;h3 id=&quot;web-workers&quot;&gt;Web workers&lt;/h3&gt;
&lt;p&gt;And of course there will be &lt;a rel=&quot;external&quot; href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers&quot;&gt;web workers&lt;/a&gt; running scripts in the background. But the web workers shown in the picture is more like dedicated workers belong to script thread. There could be another process that has standalone web workers running other web features.&lt;/p&gt;
&lt;h2 id=&quot;what-s-next&quot;&gt;What&#39;s next&lt;/h2&gt;
&lt;p&gt;There you have it! This is basically how the overview of Servo could look like. There are indeed many more processes and threads. But you should already get the insight and idea how will they interact and communicate. In the next post, we&#39;ll see how an url being loaded and its journey to finally being rendered.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Getting Started with Servo</title>
        <published>2022-04-03T12:04:23+08:00</published>
        <updated>2022-04-03T12:04:23+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/posts/servo-00/"/>
        <id>https://wusyong.github.io/posts/servo-00/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/posts/servo-00/">&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://servo.org/&quot;&gt;Servo&lt;/a&gt; is a browser engine developed by Mozilla and now running individually. It shared many philosophies from &lt;a rel=&quot;external&quot; href=&quot;https://wiki.mozilla.org/Gecko:Overview&quot;&gt;gecko&lt;/a&gt; and one of its original goals is to make more components in a browser more modular. Despite it&#39;s not pretty active after the &lt;a rel=&quot;external&quot; href=&quot;https://www.theverge.com/2020/8/11/21363424/mozilla-layoffs-quarter-staff-250-people-new-revenue-focus&quot;&gt;layoff&lt;/a&gt; of Mozilla, there are many crates still being maintained pretty well. Crates like url, html5ever, selector are widely used by many organizations like Deno, Vercel, and Rome. There are also non-web related crates that are actually came from Servo too, such as bindgen, core-foundation, brotli. Servo itself shaped the foundation of many rust ecosystems and is still worth exploring it IMHO. It still has the potential to become a competent engine for general usage. I would like to encourage people to participate Servo again and getting familiar with it. And perhaps in the future, we can push its boundary further. In this post, I want you to let you know how to run a minimum demo to play around with it.&lt;/p&gt;
&lt;h2 id=&quot;setting-up-environment&quot;&gt;Setting up environment&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Aka the most difficult part.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Setting environment is usually the least interesting part, but bare with me, it will become better after this step. Basically you should just need to follow these &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/blob/79444349a6506947e08e35fbeeb36e8a21d94c93/README.md#setting-up-your-environment&quot;&gt;instructions&lt;/a&gt; from Servo&#39;s README and it will be good to go.&lt;/p&gt;
&lt;h2 id=&quot;building&quot;&gt;Building&lt;/h2&gt;
&lt;p&gt;Mozilla has a passion that really really likes to utilize python scripts for building projects. So in Servo, it uses &lt;code&gt;./mach&lt;/code&gt; build scripts to do most jobs. Servo comes with two build mode: &lt;code&gt;dev&lt;/code&gt; and &lt;code&gt;release&lt;/code&gt;. One for developing and debugging purpose, the other for optimized build. To build the project, run one of the following commands:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;./mach&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; build --dev&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;./mach&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; build --release&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will build library crates under &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/tree/master/components&quot;&gt;components&lt;/a&gt; directory and build &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/tree/79444349a6506947e08e35fbeeb36e8a21d94c93/ports/winit&quot;&gt;winit port&lt;/a&gt; binary. There are other ports can be built, but winit one is the most common option when developing it.&lt;/p&gt;
&lt;p&gt;Since this is a fairly large project, it usually takes several minutes to complete the build. If you are developing it and just want to check build errors, you can run this command:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;./mach&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; check&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;running&quot;&gt;Running&lt;/h2&gt;
&lt;p&gt;To run the winit port binary, we could run one of the following commands with file path or url as argument:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;./mach&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; run --dev&lt;/span&gt;&lt;span&gt; [url/path]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;# For example&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;./mach&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; run --release https://www.google.com&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Unlike &lt;code&gt;cargo run&lt;/code&gt;, this will not run the build command again. It executes the built binary directly and open a window as a web page. There are more arguments and shortcut listed in Servo&#39;s &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/blob/79444349a6506947e08e35fbeeb36e8a21d94c93/README.md#commandline-arguments&quot;&gt;README&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;testing&quot;&gt;Testing&lt;/h2&gt;
&lt;p&gt;There are several test suite with commands to run them. But what we care about the most right now is the compatibility of &lt;a rel=&quot;external&quot; href=&quot;https://wpt.fyi/results/?label=master&amp;amp;product=servo&amp;amp;aligned&quot;&gt;wpt.fyi&lt;/a&gt;. It&#39;s a test suite to check how complete a web engine is. Wpt runs daily pipeline for Servo, and Servo also include these tests too. To run a wpt test, we can choose one test under &lt;code&gt;tests/wpt&lt;/code&gt; directory and run following command:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;./mach&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; test-wpt tests/wpt/mozilla/tests/mozilla/input_value.html&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can also just run the directory, it will run all tests under that directory. As the time of this post written, the main focus is full coverage of CSS 2 which tests can be found at &lt;code&gt;tests/wpt/web-platform-tests/css/CSS2&lt;/code&gt;. We will talk about wpt testing and how to debug them in the future posts.&lt;/p&gt;
&lt;h2 id=&quot;documentation&quot;&gt;Documentation&lt;/h2&gt;
&lt;p&gt;The generated documentation can be found on &lt;a rel=&quot;external&quot; href=&quot;https://doc.servo.org/servo/index.html&quot;&gt;official website&lt;/a&gt;. But of course this means only default features. If you want to see the documentation from different features, you can go with &lt;code&gt;./mach doc&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;
&lt;p&gt;That&#39;s pretty much it! There are definitely more commands and tools you can use. You can run &lt;code&gt;./mach --help&lt;/code&gt; or browse Servo&#39;s &lt;a rel=&quot;external&quot; href=&quot;https://github.com/servo/servo/wiki&quot;&gt;wiki&lt;/a&gt; search them. In the next post, I would like to talk about the overview structure of Servo. So people can get the idea how it looks like and could dive into the part they are interested the most.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Mutex 的大小</title>
        <published>2022-03-24T12:04:23+08:00</published>
        <updated>2022-03-24T12:04:23+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/posts/mutex/"/>
        <id>https://wusyong.github.io/posts/mutex/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/posts/mutex/">&lt;blockquote&gt;
&lt;p&gt;以下討論的鎖全以 x86_64-linux-gnu 目標為準&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;一個簡單的 &lt;code&gt;futex&lt;/code&gt; 在 Linux 上是 &lt;strong&gt;4 bytes&lt;/strong&gt; 而已，不過 &lt;code&gt;pthread_mutex_t&lt;/code&gt; 為了支援一些額外的功能，所以最後是 &lt;strong&gt;40 bytes&lt;/strong&gt;。這些功能包含像是 reentrance 和 &lt;a rel=&quot;external&quot; href=&quot;https://man7.org/linux/man-pages/man3/pthread_mutexattr_setrobust.3.html&quot;&gt;robust&lt;/a&gt; 等等。一個 robust mutex 會在擁有該鎖的執行緒死亡時自動釋放，讓其他執行緒在必要時能清理殘骸。不過這些 flag 預設都是關閉的。&lt;/p&gt;
&lt;p&gt;同樣地，在 glibc 中 &lt;code&gt;pthread_cond_t&lt;/code&gt; 是 &lt;strong&gt;48 bytes&lt;/strong&gt;，也提供了不少額外功能像是防止錯誤的喚醒、儲存 flag 紀錄哪些核心在用且是否有被共享。但是在 Boost 的 &lt;code&gt;condition_variable&lt;/code&gt; 又多存了一個 mutex，所以加總其來是 &lt;strong&gt;88 bytes&lt;/strong&gt;，這個額外的 mutex 是用來支援執行緒的取消與中斷。因為 &lt;code&gt;pthread_cond_wait&lt;/code&gt; 會在回傳前重新鎖住 mutex，這樣在 mutex 是鎖住時是無法中斷的，所以 Boost 改在每個條件變數(condvar) 都加一個 mutex 來等待。&lt;/p&gt;
&lt;p&gt;而不像 &lt;code&gt;pthread_rwlock_t&lt;/code&gt;，Boost 的 &lt;code&gt;shared_mutex&lt;/code&gt; 能夠將 reader 升級成 writer。該實作是用一個 40 bytes 的 mutex 保護一個 4 bytes 的狀態，並用到了三個 88 bytes 的條件變數：一個給 reader、一個給 writer、一個給升級用。最後加上 padding 就是 &lt;strong&gt;312 bytes&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;最後 Rust 的 &lt;code&gt;Mutex&lt;/code&gt; 本質上就只是 &lt;code&gt;Box&amp;lt;pthread_mutex_t&amp;gt;&lt;/code&gt;，一樣是 40 bytes，不過會被分配到 heap 上。&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>你想要多安全的記憶體安全？</title>
        <published>2022-02-13T12:04:23+08:00</published>
        <updated>2022-02-13T12:04:23+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/posts/memory-safety/"/>
        <id>https://wusyong.github.io/posts/memory-safety/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/posts/memory-safety/">&lt;p&gt;&lt;strong&gt;記憶體安全&lt;/strong&gt;通常是指針對軟體在處理記憶體存取時的措施手段，像是防止 Buffer Overflow 或 Dangling Pointer 等等。大多數擁有 Garbage Collection 的語言會在 Runtime 自動幫忙管理記憶體，而且不會暴露出太危險的抽象化型別給使用者直接使用。但在 C 和 C艹 則允許在沒有任何防護或檢查下，直接使用指標直接操控記憶體位置，我們通常就會稱這些語言是&lt;strong&gt;記憶體不安全的語言&lt;/strong&gt;。&lt;/p&gt;
&lt;h2 id=&quot;wei-he-wo-men-xu-yao-tao-lun-ji-yi-ti-an-quan&quot;&gt;為何我們需要討論記憶體安全?&lt;/h2&gt;
&lt;p&gt;我們之所以一而再再而三地討論並思考記憶體安全性的問題，無非是因為仍有非常多的軟體程式仍然是用記憶體不安全的語言寫出來的，且很多仍得繼續使用而造成維護的困難。這些很多是效能敏感的程式，無法負擔 Garbage Collector 在 Runtime 上產生的開銷。抑或是歷史的包袱，複雜的架構已經無法再改用其他語言重寫或維護。&lt;/p&gt;
&lt;p&gt;當我們仔細分析像是 &lt;a rel=&quot;external&quot; href=&quot;https://langui.sh/2019/07/23/apple-memory-safety/&quot;&gt;iOS/macOS&lt;/a&gt;、&lt;a rel=&quot;external&quot; href=&quot;https://security.googleblog.com/2019/05/queue-hardening-enhancements.html&quot;&gt;Android&lt;/a&gt;、&lt;a rel=&quot;external&quot; href=&quot;https://msrc-blog.microsoft.com/2019/07/18/we-need-a-safer-systems-programming-language/&quot;&gt;Windows&lt;/a&gt;、&lt;a rel=&quot;external&quot; href=&quot;https://daniel.haxx.se/blog/2021/03/09/half-of-curls-vulnerabilities-are-c-mistakes/&quot;&gt;cURL&lt;/a&gt; 這些重要的專案，我們可以發現所有專案的 CVE 有 60 ~ 90% 全都是來自記憶體安全相關的錯誤。用比較負面的觀點來說的話，也就是會有這些記憶體安全的錯誤全都只是因為用了 C 和 C艹 來寫。&lt;/p&gt;
&lt;p&gt;不過當然隨著時代在進步，C 和 C艹 的生態系也出現不少檢查工具鏈來改善，除了 Valgrind 能用來檢查記憶體洩漏，其他還有像是 AddressSanitizor、ThreadSanitizor 能來分別檢查記憶體位址與執行緒的安全。上面分析 iOS/macOS 的文章就可以看到，記憶體安全的錯誤比例有逐年遞減到約略 60% 左右。&lt;/p&gt;
&lt;p&gt;但能視為通用程式語言並用在系統開發上的語言當然不是只有 C 和 C艹 而已。早在 1980 年就已經有 Ada 語言存在，並廣泛運用在美軍的系統程式上。而甚至有人開發過 Lisp 機器嘗試將 Lisp 作為該電腦的主要開發語言。&lt;/p&gt;
&lt;p&gt;而近年來還有許多新興的程式語言能選擇，有些承襲了些傳統語言預設會去做的檢查並在編譯時就做好優化，有些甚至帶來了有趣的概念像是 Rust 的&lt;strong&gt;所有權與 Borrow Checker&lt;/strong&gt; 來治本解決根本性的問題。許多諸如 &lt;a rel=&quot;external&quot; href=&quot;https://docs.kernel.org/rust/index.html&quot;&gt;Linux&lt;/a&gt; 的 Kernel Module、Amazon 的虛擬化技術 &lt;a rel=&quot;external&quot; href=&quot;https://firecracker-microvm.github.io/&quot;&gt;Firecracker&lt;/a&gt;、Google 的 &lt;a rel=&quot;external&quot; href=&quot;https://security.googleblog.com/2021/04/rust-in-android-platform.html&quot;&gt;Android&lt;/a&gt; 與 &lt;a rel=&quot;external&quot; href=&quot;https://security.googleblog.com/2021/09/an-update-on-memory-safety-in-chrome.html&quot;&gt;Chrome&lt;/a&gt; 甚至是 &lt;a rel=&quot;external&quot; href=&quot;https://fuchsia.dev/fuchsia-src/development/languages/rust&quot;&gt;Fuchsia&lt;/a&gt; 以及 &lt;a rel=&quot;external&quot; href=&quot;https://github.com/microsoft/windows-rs&quot;&gt;Windows&lt;/a&gt;，這些大型企業以及開源的專案都開始嘗試使用 Rust 來寫。&lt;/p&gt;
&lt;h2 id=&quot;na-gai-xuan-ze-na-xie-ji-yi-ti-an-quan-yu-yan&quot;&gt;那該選擇哪些記憶體安全語言?&lt;/h2&gt;
&lt;p&gt;所有具有 Garbage Collection 的語言都算是記憶體安全的語言，盡管在執行時會有一定程度的開銷，但是它們可沒有想像中的那麼笨重緩慢不堪。JVM 和 .NET 都有十分強而有力的 Garbage Collector 實作，如果無法完全理解記憶體與抽象指標的概念，或是手動的記憶體管理反而是負擔的話，仍然非常推薦有 Garbage Collection 的語言像是 Elixir、F# 和 Racket 等等。&lt;/p&gt;
&lt;p&gt;但很多時候不如在一開始就搞定問題，Garbage Collector 產生問題時要解決的時間與人力成本也不亞於非記憶體安全的語言，最常見就像 Java 的記憶體卡在老生代釋放不掉造成 Out of Memory，且並行程式下也可能防止不了 Data Race。在 Oracle 和 Line 等企業中都得培養整個部門團隊去維護優化它們的 JVM。&lt;/p&gt;
&lt;p&gt;回到不用 Garbage Collection 的語言，像是 C 和 C艹 也不是都沒在做檢查，除了上述提到的檢查工具，也有許多標準規範像是 MISRA C 來限制。不過這些畢竟不全是預設行為，對自己的要求標準高，其他的開發者或團隊可能並沒有跟你站在同個標準上。所以使用 Ada 和 Zig 這些預設在編譯時就會做諸多記憶體安全檢查的語言會是我推薦的選項。在先不討論 Allocator 的情況下，要在 Zig 做記憶體不安全的行為是要明確指定的，從 Build Mode 就可以略知該程式提供的保障到哪。&lt;/p&gt;
&lt;p&gt;接下來我們還有 Rust，所有權和 Borrow Checker 能在編譯時釐清記憶體的歸屬問題，任何人都能夠寫出既迅速又安全的程式碼，讓魚與熊掌可以兼得。而所有權當然其實和 C艹 的 RAII 類似，且 Borrow Checker 在做的也是我們平時在寫程式時腦海裡就會勾勒出的藍圖。然而讓編譯器也一同檢查比你自己一個人檢查更清楚多了，有許多專案重寫後還發現原來沒找出的 bug。&lt;/p&gt;
&lt;h2 id=&quot;zhe-xie-yu-yan-you-duo-an-quan&quot;&gt;這些語言有多安全?&lt;/h2&gt;
&lt;p&gt;最後我想我們可以來看看上述的語言相比到底多安全。確實使用 C 夠謹慎的話，的確能一掃所有記憶體安全問題。寫 Rust 使用 &lt;code&gt;unsafe&lt;/code&gt; 也能把 Undefined Behaviour 玩得天花亂墜。但我們想知道在預設行為下，這些語言到底提供了怎麼樣的保障。Garbage Collection 的語言不用說，本文提到的多數問題應該都不必煩惱。至於 C、Zig 與 Rust 相比的話，我們有以下 &lt;a rel=&quot;external&quot; href=&quot;https://www.scattered-thoughts.net/writing/how-safe-is-zig/&quot;&gt;Jamie Brandon&lt;/a&gt; 整理的列表:&lt;/p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;問題&lt;/th&gt;&lt;th&gt;C&lt;/th&gt;&lt;th&gt;Zig&lt;/th&gt;&lt;th&gt;Rust&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Out-of-Bounds Heap Read/Write&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;td&gt;⭕️&lt;/td&gt;&lt;td&gt;⭕️&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Null Pointer Dereference&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;td&gt;⭕️¹&lt;/td&gt;&lt;td&gt;⭕️¹&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Type Confusion&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;td&gt;⭕️²&lt;/td&gt;&lt;td&gt;⭕️&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Integer Overflow&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;td&gt;⭕️&lt;/td&gt;&lt;td&gt;❌³&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Use After Free&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;td&gt;❌⁴&lt;/td&gt;&lt;td&gt;⭕️&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Double Free&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;td&gt;❌⁴&lt;/td&gt;&lt;td&gt;⭕️&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Invalid Stack Read/Write&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;td&gt;⭕️&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Uninitialized Memory&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;td&gt;❌⁵&lt;/td&gt;&lt;td&gt;⭕️&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Data Race&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;td&gt;⭕️⁶&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;上面的列表我有更改一些，以確定真的都是預設的行為。在 Zig 我們討論的是 &lt;code&gt;Debug&lt;/code&gt; / &lt;code&gt;ReleaseSafe&lt;/code&gt; Mode，而 Rust 則是 &lt;code&gt;Debug&lt;/code&gt; / &lt;code&gt;Release&lt;/code&gt; Profile。而有附上數字的欄位就是接下來需要近一步解釋，或是某方面其實還是能視為安全的地方：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;其實就是提供 &lt;code&gt;Option&lt;/code&gt; 型別作為第一公民。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;只有 Union 會造成&lt;a rel=&quot;external&quot; href=&quot;https://cwe.mitre.org/data/definitions/843.html&quot;&gt;型別混淆&lt;/a&gt;，雖然 Zig 可以用 &lt;code&gt;enum&lt;/code&gt; 組合成 Tagged Union，但這必免不了持有指標數值的同時更改 Tag。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;在 &lt;code&gt;Debug&lt;/code&gt; 時 Overflow 會 Panic，在 &lt;code&gt;Release&lt;/code&gt; 則是會 Wrap。實際在做數值運算時通常都是使用型別提供的方法像是 &lt;code&gt;wrapping_add&lt;/code&gt; 或 &lt;code&gt;overflow_add&lt;/code&gt; 來確定想要的行為。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Zig 的作者 &lt;a rel=&quot;external&quot; href=&quot;https://lobste.rs/s/v5y4jb/how_safe_is_zig#c_vddk9j&quot;&gt;Andrew Kelley&lt;/a&gt; 有解釋其標準函式庫提供的 Allocator 會防止這些常見的記憶體分配錯誤。C 也有像是 &lt;a rel=&quot;external&quot; href=&quot;https://github.com/GrapheneOS/hardened_malloc&quot;&gt;hardened_malloc&lt;/a&gt; 的概念，不過並沒有什麼標準函式庫，預設就能拿來使用。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Zig 的安全檢查會檢測未初始化的記憶體，且使用的關鍵字是 &lt;code&gt;undefined&lt;/code&gt;。在 &lt;code&gt;Debug&lt;/code&gt; 時寫入的值是 0xaa 以方便做檢查。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;所有權和 Borrow Checker 能完全杜絕 Data Race，我發現這是很少被提到的，在有些 Garbage Collection 的語言甚至沒有辦法完全防範。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;最後有一些問題並沒有列上去，因為這在所有語言都存在，而且有時候是刻意為之的：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Race Condition：因為整個系統本質上就在互相爭奪資源的寫入與讀取，當程式需要依賴這些系統進行操作的話，難免會在非常極端的狀況出現微妙的問題，而且有時是非常難以重現的，這個我覺得值得獨立一個話題討論。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Memory Leak：記憶體洩漏不像其他行為會觸發到 Undefined Behaviour 進而造成程式錯誤，而且有時候是刻意洩漏的。在 Valgrind 的檢查中洩漏就被分成好幾種類別，有些其實使用者自己知道且仍在掌控中。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>fn 與 Fn</title>
        <published>2021-01-01T12:04:23+08:00</published>
        <updated>2021-01-01T12:04:23+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/posts/fn/"/>
        <id>https://wusyong.github.io/posts/fn/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/posts/fn/">&lt;p&gt;大家在其他語言中大部分的時候可能可以將 &lt;code&gt;fn&lt;/code&gt; 與 &lt;code&gt;Fn&lt;/code&gt; 視為同樣的語意來處理，可是這在 Rust 中會需要多一些操作，比方說以下的做法就是不可行的：&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; foo&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;A&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; B&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span&gt;f1&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; Fn&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;A&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; B&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; f2&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; Fn&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;B&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; A&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt;    todo!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;因為 &lt;code&gt;fn&lt;/code&gt; 才是函式（更確切地說是函式指標），而 &lt;code&gt;Fn&lt;/code&gt; 是 trait，我們得改成用 &lt;code&gt;fn&lt;/code&gt; 或是真的要用 &lt;code&gt;Fn&lt;/code&gt; 的話則是採用泛型 &lt;code&gt;impl trait&lt;/code&gt; 甚至是 Trait Object &lt;code&gt;&amp;amp;dyn trait&lt;/code&gt; 等等。選擇 &lt;code&gt;impl trait&lt;/code&gt; 的話會寫成像這樣：&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; foo&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;A&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; B&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span&gt;f1&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: impl&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; Fn&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;A&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; B&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; f2&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: impl&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; Fn&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;B&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; A&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt;    todo!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;會有這樣的差別的原因是，除了普通的函式以外，閉包也擁有 &lt;code&gt;Fn&lt;/code&gt; trait，閉包通常會再有個 context struct 來保存狀態，在大多數的語言中會選擇 Box 起來變成同樣的指標，讓型別之間的區別抹去。在 Rust 預設則不是如此，型別之間的區別是存在的，所以真的想在執行時視為同樣的型別處理，我們就會用 Trait Object &lt;code&gt;Box&amp;lt;dyn trait&amp;gt;&lt;/code&gt;，但這樣就是動態調度（Dynamic Dispatch），和其他語言一樣會有額外的開銷。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Fn&lt;/code&gt; 預設的行為則不然，它是 trait，用在泛型上會是靜態調度（Static Dispatch），在執行時是沒有任何額外的開銷（不過因為是靜態的，你的程式碼大小的確會增加）。有趣的是 &lt;code&gt;fn&lt;/code&gt; 因為是指標，所以拿來當作參數使用的話其實是動態調度的，和使用 &lt;code&gt;Fn&lt;/code&gt; 的泛型靜態調度有一點不一樣。詳細的區別可以看看以下例子：&lt;a rel=&quot;external&quot; href=&quot;https://godbolt.org/z/bexE6v&quot;&gt;https://godbolt.org/z/bexE6v&lt;/a&gt;&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5E81AC;&quot;&gt;#![feature(test)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5E81AC;&quot;&gt;#[inline(never)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; foo&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    std&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;hint&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;black_box&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5E81AC;&quot;&gt;#[inline(never)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; bar&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    std&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;hint&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;black_box&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    std&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;hint&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;black_box&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;pub fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; run1&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5E81AC;&quot;&gt;    #[inline(never)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; run&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: fn&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;()) {&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; f&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;() }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;    run&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;foo&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;    run&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;bar&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;pub fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; run2&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5E81AC;&quot;&gt;    #[inline(never)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; run&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: impl&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; Fn&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;()) {&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; f&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;() }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;    run&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;foo&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;    run&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;bar&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;而產生的組合語言則是如此：&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;example::foo:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        push    rax&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        mov     rax, rsp&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        pop     rax&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ret&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;example::bar:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        push    rax&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        mov     rax, rsp&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        pop     rax&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ret&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;example::run1:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        push    rax&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        lea     rdi, [rip + example::foo]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        call    example::run1::run&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        lea     rdi, [rip + example::bar]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        pop     rax&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        jmp     example::run1::run&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;example::run1::run:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        jmp     rdi&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;example::run2:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        push    rax&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        call    example::run2::run&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        pop     rax&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        jmp     example::run2::run&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;example::run2::run:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        jmp     example::foo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;example::run2::run:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        jmp     example::bar&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;run1&lt;/code&gt; 會接受的參數是個指標，而 &lt;code&gt;run2&lt;/code&gt; 才會確切呼叫實際個別函式。&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>在 Rust 中讓型別能夠跨執行緒的方法</title>
        <published>2020-12-30T12:04:23+08:00</published>
        <updated>2020-12-30T12:04:23+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/posts/arc-mutex/"/>
        <id>https://wusyong.github.io/posts/arc-mutex/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/posts/arc-mutex/">&lt;p&gt;最近我需要用到 Cache 的功能，但在 crates.io 找了一遍後並沒有滿意的 crates，大部分都包含了 unsafe 與裸指標的引用。我自己並不排斥 unsafe 的使用，只要有詳細的註解能讓我理解使用的必要原因就好。不過這些都沒有跑過 &lt;a rel=&quot;external&quot; href=&quot;https://github.com/rust-lang/miri&quot;&gt;miri&lt;/a&gt;，而與其要解決出錯的未定義行為，我覺得不如自己寫一個最適用於自己使用情境的一個還比較實際。所以寫了一個之後，我在 benchmark 的同時剛好需要讓該型別能跨執行緒使用，加了一些簡單的修改後我發現這個或許能幫助到剛好正在學習怎麼寫 concurrency 的人，所以我把修改時的思路與過程記錄下來。&lt;/p&gt;
&lt;p&gt;當然在現在的程式設計中也有許多其他技巧可以使用，像是 channel、atomics 或者 lock-free 等等。但在這邊只是要用最簡單的方式而已：開多條 thread 並使用互斥鎖。這樣的方式雖然簡單，但沒有處理好的話卻也常常造成許多錯誤。不過在安全的 Rust 中就提供了許多保障，讓你在使用它們的同時就免除了許多不必要的危害。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;雖然 Rust 能幫你預防 data race 甚至所有記憶體不安全的問題，但 race condition 仍然是會發生的，因為整個系統環境本來就是在互相競爭的，使用者還是有可能寫出死鎖。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;首先 Rust 大部分的基礎型別都有 &lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/std/marker/trait.Sync.html&quot;&gt;&lt;code&gt;Sync&lt;/code&gt;&lt;/a&gt; 和 &lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/std/marker/trait.Send.html&quot;&gt;&lt;code&gt;Send&lt;/code&gt;&lt;/a&gt; traits，以這些定義的型別也會擁有這些 traits，這用來表明該型別是可以安全在執行緒間同步與傳遞的。不過因為所有權的關係一個數值就算有這些 traits 也只能被一個 thread 所擁有，要讓多條 thread 可以擁有同個實例的話，通常我們就會使用 &lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/std/sync/struct.Arc.html&quot;&gt;&lt;code&gt;Arc&lt;/code&gt;&lt;/a&gt; 型別，此型別在 &lt;code&gt;clone&lt;/code&gt; 時不會複製數值，而是仍引用原本的實例然後增加原子引用計數。&lt;code&gt;Arc&lt;/code&gt; 型別擁有 &lt;code&gt;Deref&lt;/code&gt; trait 讓使用者可以拿到原本的引用。不過此引用是不可變的引用，想要拿到可變得用的話，我們就會再繼續加上 &lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/std/sync/struct.Mutex.html&quot;&gt;&lt;code&gt;Mutex&lt;/code&gt;&lt;/a&gt; 來繼續取得可變引用。&lt;strong&gt;所以通常要讓一個型別可以跨執行緒並可變的話，我們會很直覺地使用 &lt;code&gt;Arc&amp;lt;Mutex&amp;lt;T&amp;gt;&amp;gt;&lt;/code&gt;。&lt;/strong&gt; 而且這些型別的 API 仍然遵守著 Rust 的所有權與生命週期規則，這直接讓 Data Race 的產生成為不可能。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/slap.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;不過我所實作的 Cache 內部還分成了數個 shard，所以與其將整個型別用 &lt;code&gt;Arc&amp;lt;Mutex&amp;lt;T&amp;gt;&amp;gt;&lt;/code&gt; 包起來，我採用了別種選擇：讓 Mutex 鎖的是各個 shard。這樣當某個 shard 被鎖起來時，其他 shard 在別條 thread 仍能使用。而在此 &lt;a rel=&quot;external&quot; href=&quot;https://github.com/wusyong/sosi/commit/24de852ad155e9078c99423dbda668cc41848ef5&quot;&gt;commit&lt;/a&gt; 短短幾行修改中，產生了一些有趣的變化，在之後的 benchmark 時我發現變的更好使用了！&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/W7lTPbE.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;首先，我對每個 thread 加上了 &lt;code&gt;Mutex&lt;/code&gt;，而要取得每個 shard 的話就是呼叫 &lt;code&gt;lock().unwrap()&lt;/code&gt;。取鎖得到的回傳值是一種 &lt;code&gt;Result&lt;/code&gt; 型別的原因是因為要是該鎖在其他 thread panic 的話就會被污染。被污染的鎖就會回傳 &lt;code&gt;Err&lt;/code&gt;。不過要是確定 thread 不會 panic 的話，直接 unwrap 是不會有問題的，以我自己的經驗要是真的在除錯時也比較容易。這邊最有趣的地方在於原本需要 &lt;code&gt;&amp;amp;mut self&lt;/code&gt; 的方法可以改成 &lt;code&gt;&amp;amp;self&lt;/code&gt; 就好了，因為 Mutex 提供的是內部可變性，&lt;code&gt;lock()&lt;/code&gt; 的需求也只要 &lt;code&gt;&amp;amp;self&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;這邊沒有加上 &lt;code&gt;Arc&lt;/code&gt; 的原因是因為是使用者才要決定要不要傳給其他 thread，所以使用者不需要的話他們本來就能直接使用，而需要跨執行緒的話，他們就會本能地使用 &lt;code&gt;Arc&lt;/code&gt; 包裝起來，而且因為所有方法都只需要不可變引用，所以他們不必再定義 Mutex(要真的定義也不是不行，只是最後會發現完全不需要鎖)。這樣一來就完成能夠跨平台的型別，確保外部不變的同時，提供內部可變性。&lt;/p&gt;
&lt;p&gt;以上是快樂的部分，而在剛剛的 commit 中有再定義另一個型別，這則是比較惱人的部分。或者說「遇過太多次這樣的錯誤，所以下意識就會寫的部分」，在剛剛的 commit 中有再定義另一個型別：&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;pub struct&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; LookupRef&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; T&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;MutexGuard&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; LRUCache&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;&amp;gt;,&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; usize&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;impl&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; T&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; LookupRef&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; T&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;    /// Get the value of the lookup reference and actually update the entry to the head of its&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;    /// cache shard.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    pub fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; value&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;amp;mut self&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Option&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;amp;mut&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; T&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;        self.&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;lookup&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;self.&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;這是因為 &lt;code&gt;lock()&lt;/code&gt; 的回傳值 &lt;code&gt;MutexGuard&lt;/code&gt; 是個引用型別，其產生的引用的生命週期當然不能超過它，不然就無效而無法擁有鎖提供的保障了。在 Cache 的 lookup 會希望取得該值的引用，所以常見的做法是把 &lt;code&gt;MutexGuard&lt;/code&gt; 延長給使用者，在那裏使用完後才釋放鎖。&lt;/p&gt;
&lt;p&gt;以上就是要讓型別跨執行緒時常見的思路，除了 &lt;code&gt;Mutex&lt;/code&gt; 以外，&lt;code&gt;RwLock&lt;/code&gt; 與 Atomic 型別也都適用這樣的思維。在一開始使用這些型別時，的確可能會覺得卡卡的。但習慣後會發現實際要寫的程式並不多，而且可以安全地定義並使用，享受 fealess concurrency 帶來的好處。&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Webassembly 與它們的產地</title>
        <published>2020-11-17T16:55:00+08:00</published>
        <updated>2020-11-17T16:55:00+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/posts/wasm/"/>
        <id>https://wusyong.github.io/posts/wasm/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/posts/wasm/">&lt;p&gt;最近看到大家又再討論 Webassembly，讓我想起以前就想寫篇總結了。這篇是我目前接觸 Webassembly 社群大致上的見解，希望可以讓大家能更清楚 Webassembly 的全貌並排除掉一些錯誤的見解。&lt;/p&gt;
&lt;h2 id=&quot;suo-yi-shen-mo-shi-webassembly&quot;&gt;所以什麼是 Webassembly？&lt;/h2&gt;
&lt;p&gt;Webassembly 簡稱 wasm 是個可攜式的位元組碼（bytecode），讓開發者可以用自己喜歡的程式語言編譯然後能在不同的系統或平台上快速且安全地執行，而且現在已經能用各大瀏覽器的虛擬機引擎執行。&lt;/p&gt;
&lt;p&gt;坦白說這當然不是什麼新點子，同樣的事情 JVM 與 .NET 都做過了，而且都已有一定的影響力並都在自己的市場站穩了腳步。那為何又要重造輪子一次呢？首先來看 JVM 的話，它已經有超過 20 年的歷史了，它原本是為了處理一個程式語言 Java 而設計的，而且是在網路的樣子成熟之前就出來的，當時有很多的設計思維與現在多少有些許的落差，當時甚至不確定 Garbage Collection 的設計對於現在高階且高效的程式會這麼有影響力。至於 .NET 我覺得就真的有點微妙，它在各方面的確做得很好，而且最近又出了 .NET 5 速度與效能又更好了。也許是因為它被微軟的開發生態綁死在一起了吧，就像 Apple 的 Swift 或 Cocoa 框架那樣。&lt;/p&gt;
&lt;p&gt;所以有不少原因與動力，況且也沒真的有人阻止大家再去定義出一個更通用、不被特定財閥綁架、且兼容於各個語言的 bytecode 系統與 JIT 編譯器。另外 Webassembly 也有不少優點，像是它不像前者一定需要 Garbage Collector，它沒有許多複雜的型別概念像是 generic 、 class 甚至是 structure，還有更簡單的命名空間（namespace）與連結/讀取模型。所以可以看到它比 JVM 或 .NET 還更像是機器語言。讓其他相對低階的語言像是 C/C++ 和 Rust 也能編譯成其目標（理論上）也不會有 overhead。&lt;/p&gt;
&lt;p&gt;經過社群多年的努力，現在所有瀏覽器都支援 Webassembly 了，我也看到不少專案甚至是企業將負擔較重的程式碼段落，像是運算或解析，轉成使用 wasm module 了。而且更棒的是 Webassembly 不只能用在瀏覽器上，別忘了 Webassembly 本來就是 bytecode。它當然可以 port 並跑在任何系統的沙盒上。能讓執行檔與函式庫以 bytecode 形式發布並在不同的平台本地端編譯可以說是最吸引我的賣點了。這對我來說這幾乎能直接取代發布特定系統執行檔這樣的方式。（當然沒人阻止你直接拿原始碼編譯，不過這是另一個話題了）隨著系統架構越來越多元，各領域的開發者們越來越需要考慮到不同平台的支援，這樣的點子我覺得會在近未來成為顯學。Docker 創辦人 Solomon Hykes 甚至&lt;a rel=&quot;external&quot; href=&quot;https://twitter.com/solomonstre/status/1111004913222324225&quot;&gt;發過推&lt;/a&gt;說如果 WASM/WASI 在 2008 年就問世的話，根本就不需要有 Ｄocker 了。&lt;/p&gt;
&lt;p&gt;不過當然 Webassembly 也不是沒有讓人困擾的地方，像是它是從 32 位元開始的，我有點不解為何不一開始就將 64 位元也考慮進去。許多基本的元件像是 interface type 也還在擬稿中。對於系統的介面支援 wasi 也還在進行中，所以只有 Webassembly 是無法呼叫執行緒或開啟檔案等等的。不過先撇除這些瑣碎的不便之處，Webassembly 真的已經開始在真實世界使用了！&lt;/p&gt;
&lt;h2 id=&quot;suo-yi-gai-zen-mo-xie-webassembly-bing-shi-yong-ni&quot;&gt;所以該怎麼寫 Webassembly 並使用呢？&lt;/h2&gt;
&lt;p&gt;我想到目前為止對 Webassembly 有興趣的大部分應該都是網路開發者，所以壞消息是你還是得寫 javascript XD，不過你可以直接匯入 Webassembly 來在程式碼內使用。至於要用什麼語言寫就見仁見智了，C/C++ 可以透過 emscripten，其他語言也應該都有對應的工具，但我覺得最簡單的方式還是用 Rust 了，它的社群提供了非常多超好用且簡單的工具可以讓你輕鬆就編譯出 Webassembly 並馬上使用。基本上你會用到的工具有：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;wasm_pack&lt;/code&gt; 是建立 Webassembly 專案最簡單的 CLI，使用起來也十分直觀，甚至還能將你的 wasm module 發布到 npm 等 registry。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;wasm-bindgen&lt;/code&gt; 是串接 rust 與 javascript 的函式庫，簡單來說你只要在所有的型別與函式上方加上 &lt;code&gt;#[wasm_bingen]&lt;/code&gt; 就完成了。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;web-sys&lt;/code&gt; 與 &lt;code&gt;js-sys&lt;/code&gt; 分別提供 Web 與 Js 相關的 API。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;要開始入門試試的話，我非常推薦 Rust 寫的 &lt;a rel=&quot;external&quot; href=&quot;https://rustwasm.github.io/docs/book/&quot;&gt;Webassembly 入門教學&lt;/a&gt;，一天內絕對看得完。想更快瞭解的話，&lt;a rel=&quot;external&quot; href=&quot;https://developer.mozilla.org/en-US/docs/WebAssembly/Rust_to_wasm&quot;&gt;MDN&lt;/a&gt; 也有提供更簡短的文章說明。&lt;/p&gt;
&lt;h2 id=&quot;wo-zhi-de-shi-zhen-de-webassembly&quot;&gt;我指的是「真的」Webassembly&lt;/h2&gt;
&lt;p&gt;上述的工具與建出來的 wasm module 是特別針對給前端來使用的，Webassembly 當然可以產生完整的應用程式並來執行。每個語言的社群應該都有開發出些編譯器來編譯，像剛剛講的 C/C++ 就是用 emscripton，C# 則有 Blazor 等等。Rust 的話交叉編譯（Cross Compilation）則原本就是第一公民，寫好程式後只要用 &lt;code&gt;cargo build --target wasm32-unkown-unknown&lt;/code&gt; 就能編譯出 Webassembly，甚至還提供了 &lt;code&gt;wasm32-unknown-emscripten&lt;/code&gt; 與 &lt;code&gt;wasm32-wasi&lt;/code&gt; 等目標讓開發者還可以使用這些標準提供的功能。&lt;/p&gt;
&lt;p&gt;Wasi 的全名是 WebAssembly System Interface 旨在讓 wasm 可以有個符合 POSIX 的系統介面來做系統呼叫，目前 Bytcode Alliance 還在開發 wasi 中，不過許多 wasm runtime 都已經有支援了。 &lt;a rel=&quot;external&quot; href=&quot;https://bytecodealliance.org/&quot;&gt;Bytcode Alliance&lt;/a&gt; 是由 Mozilla、Fastly、Intel 與 Red Hat 聯合起來的組織，目標就是要讓 WebAssembly 及其生態圈能成熟穩定下來。&lt;/p&gt;
&lt;p&gt;既然我們能編譯出 wasm bytecode 了，總要有方式能執行起來，至於要怎麼執行也是見仁見智了，目前最官方的實作大概就是 Bytcode Alliance 的 wasmtime 了。&lt;a rel=&quot;external&quot; href=&quot;https://wasmtime.dev/&quot;&gt;Wasmtime&lt;/a&gt; 是原本由 Mozilla 主導，現在由 Fastly 接手開發的 JIT Interpreter，不同的語言如 C 或 GO 也都有使用其函式庫的方法。如果你想用其他 runtime 的話，&lt;a rel=&quot;external&quot; href=&quot;https://github.com/appcypher/awesome-wasm-runtimes&quot;&gt;Awesome WebAssembly Runtimes&lt;/a&gt; 也有列出非常多的不同實作。而許多大型&lt;a rel=&quot;external&quot; href=&quot;https://v8.dev/features&quot;&gt;專案&lt;/a&gt;或&lt;a rel=&quot;external&quot; href=&quot;https://docs.microsoft.com/en-us/dotnet/architecture/blazor-for-web-forms-developers/hosting-models&quot;&gt;框架&lt;/a&gt;也有針對不同領域用途的不同實作。&lt;/p&gt;
&lt;p&gt;所以的確 Webassembly 要當作完整獨自的生態體系的話還有一小段路要走，不過作為 web 的支援我覺得算是蠻成熟可以實際使用了。另外每個語言都可以一起協助拓展 Webassembly 的生態圈，期望 wasm 在未來可以持續有不錯的進展。&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Environment Setup for ESP Development in Rust</title>
        <published>2020-08-24T12:01:00+08:00</published>
        <updated>2020-08-24T12:01:00+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/posts/rust-esp/"/>
        <id>https://wusyong.github.io/posts/rust-esp/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/posts/rust-esp/">&lt;p&gt;ESP series are the targets I always want to explore in Rust. Because they have many convenient built-in features like integrated Wi-Fi and dual mode Bluetooth. Unfortunately, both rustc and llvm don’t provide the build target for xtensa by default which means usually we must build the xtensa version for both. Furthermore, it’s not just about the compiler. There’s the whole toolchain from original ecosystem needs to be setup too. In our case, this means installing &lt;a rel=&quot;external&quot; href=&quot;https://docs.espressif.com/projects/esp-idf/en/release-v3.0/get-started/linux-setup.html&quot;&gt;xtensa-esp32-elf toolchain&lt;/a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https://github.com/espressif/esptool&quot;&gt;esptool&lt;/a&gt;, and maybe &lt;a rel=&quot;external&quot; href=&quot;https://github.com/espressif/esp-idf&quot;&gt;esp-idf&lt;/a&gt; properly. This post is going to provide a guide to setup the development environment with esp32 as an example.&lt;/p&gt;
&lt;h2 id=&quot;docker-image-for-xtensa&quot;&gt;Docker image for xtensa&lt;/h2&gt;
&lt;p&gt;In order to make cross compilation easier, the rust embedded community proposes a crate called &lt;a rel=&quot;external&quot; href=&quot;https://github.com/rust-embedded/cross&quot;&gt;&lt;code&gt;cross&lt;/code&gt;&lt;/a&gt; which can build the docker image to setup required components for your targets and then build/flash your project from it. While original &lt;code&gt;cross&lt;/code&gt; doesn’t have the Dockerfile for xtensa targets, there’s a fork for it thanks to &lt;a rel=&quot;external&quot; href=&quot;https://github.com/reitermarkus&quot;&gt;@reitermarkus&lt;/a&gt;. Before building the docker image, I highly recommend adding your user to docker group to prevent any environment variable issue. &lt;strong&gt;Also make sure you already have &lt;a rel=&quot;external&quot; href=&quot;https://docs.docker.com/get-docker/&quot;&gt;Docker&lt;/a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https://stedolan.github.io/jq/&quot;&gt;&lt;code&gt;jq&lt;/code&gt;&lt;/a&gt; installed.&lt;/strong&gt; If you already have them, just follow instructions below to install the custom cross and required image:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; clone -b xtensa https://github.com/reitermarkus/cross&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;cd&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; cross&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;cargo&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; install --path . --force&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;./build-docker-image.sh&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; xtensa-esp32-none-elf&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;project-template&quot;&gt;Project Template&lt;/h3&gt;
&lt;p&gt;Next, we want to setup the project template that can build and flash our binary to the chip on the fly. Before we start, &lt;strong&gt;make sure you have &lt;a rel=&quot;external&quot; href=&quot;https://github.com/espressif/esptool&quot;&gt;&lt;code&gt;esptool.py&lt;/code&gt;&lt;/a&gt; installed&lt;/strong&gt;, this is how we going to flash the binary. Once you have it installed, we can clone the template and start building:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; clone https://github.com/wusyong/esp32-hello.git&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; submodule update --init --recursive&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This template also provides the ffi of &lt;code&gt;esp-idf&lt;/code&gt; and wraps some basic functions to the &lt;code&gt;esp-idf-hal&lt;/code&gt;. The main application is right under the &lt;code&gt;app/&lt;/code&gt; directory, there are more examples in the &lt;code&gt;app/examples&lt;/code&gt;. To build and flash the application, we could just use the build script:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;./build.sh&lt;/span&gt;&lt;span&gt; [--chip&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;chi&lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; (default:&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; esp32&lt;/span&gt;&lt;span&gt;)] &lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;[&lt;/span&gt;&lt;span&gt;--release&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;] [&lt;/span&gt;&lt;span&gt;--package &lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;package&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; (&lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span&gt; app&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)] [&lt;/span&gt;&lt;span&gt;--example &lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;example&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;] [&lt;/span&gt;&lt;span&gt;--flash-baudrate &lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;baud&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; (&lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 460800&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)] [&lt;/span&gt;&lt;span&gt;--erase-flash&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see it&#39;s basically calling &lt;code&gt;cross&lt;/code&gt; to build and &lt;code&gt;esptool&lt;/code&gt; to flash. If you are also using esp32, you probably don&#39;t need to edit environment variables in the script. &lt;strong&gt;But make sure the &lt;code&gt;SERIAL_PORT&lt;/code&gt; is correct&lt;/strong&gt; just in case (it&#39;s &lt;code&gt;/dev/ttyUSB0&lt;/code&gt; for my device), or it&#39;s not going to flash successfully. To build the application in release, simply call:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;./build.sh&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And if you want to build any example:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;./build.sh&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; --release --example thread_local&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;state-of-the-esp-ecosystem-in-rust&quot;&gt;State of the ESP ecosystem in Rust&lt;/h3&gt;
&lt;p&gt;In this section, I would like to talk about the ecosystem of it and evaluate is it worth it for ESP development using Rust. You don&#39;t need to proceed if you just want to setup the environment. It is basically complete.&lt;/p&gt;
&lt;p&gt;I do consider ESP series are not the first-class citizen among the rust embedded community. You can’t simply cross compile it like other targets (stm, nrf for instance). And despite there’s an &lt;a rel=&quot;external&quot; href=&quot;https://github.com/esp-rs&quot;&gt;&lt;code&gt;esp-rs&lt;/code&gt;&lt;/a&gt; organization which provides many helpful crates and even a quick start repository, there are still some obstacles and missing parts I can image many people would just give up if they cannot resolve. Building the compiler for xtensa is not trivial already, it is also very time consuming. It took me an hour or two to build the llvm and rustc.  And toolchains can be outdated too! A while ago I have a dockerfile for me to build the imagine. But many tools have changed, and some are not compatible anymore. Even llvm asked me to use new variable &lt;code&gt;LLVM_EXPERIMENTAL_TARGETS_TO_BUILD&lt;/code&gt; which is ** undocumented**! Furthermore, many crates are so difficult to seek and acquire.  You think something so straight forward like &lt;code&gt;esp32-hal&lt;/code&gt; should already on crates.io but it’s actually not. Other crates often scatter across the community, and you have to do the search yourself. But on the other hand, I feel like this is inevitable nature in FOSS. The community is moving for sure, just slowly. We saw that AVR target was merged into Rust recently. It definitely could also happen to ESP in the future.&lt;/p&gt;
&lt;p&gt;The reason for me to keep going is probably the potential to develop in Rust. Here’s the example for Wi-Fi scanning in the esp-hello template. You can see how elegant and ergonomic it is. It’s even possible to use async programming to achieve the goal! Indeed, it still depends on &lt;code&gt;esp-idf&lt;/code&gt; and FreeRTOS. But it is totally possible to just build an async runtime for it. I know some developers are already exploring this. I am exciting to see more powerful crates and tools for embedded in the future.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://pbs.twimg.com/media/EgGxlsOU8AAk0FW?format=jpg&amp;amp;name=large&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Option 的大小</title>
        <published>2020-07-27T17:35:00+08:00</published>
        <updated>2020-07-27T17:35:00+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/posts/option/"/>
        <id>https://wusyong.github.io/posts/option/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/posts/option/">&lt;p&gt;在 Rust 中預設是不能使用 &lt;code&gt;Null&lt;/code&gt; 指標/引用的，而當時的設計者 Tony Hoare 也說了這是造成&lt;a rel=&quot;external&quot; href=&quot;https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare/&quot;&gt;數十億損失的錯誤設計&lt;/a&gt;。所以通常我們會使用 &lt;code&gt;Option&lt;/code&gt; 型態來表示可能會有 &lt;code&gt;Null&lt;/code&gt; 值的型態。這麼做帶來很多好處，所有型態預設都是沒有 &lt;code&gt;Null&lt;/code&gt; 的，而 &lt;code&gt;Option&amp;lt;T&amp;gt;&lt;/code&gt; 剛好也形成一種 monadic structure。你可以在不和原生型態衝突的狀況下，自己定義他的運算行爲。&lt;/p&gt;
&lt;p&gt;但是對於資源吃緊的裝置來說，我們就會在意型態的大小了。我們很清楚的知道 &lt;code&gt;u64&lt;/code&gt; 就是有 64 bits 所以會佔 8 bytes，但是 &lt;code&gt;Option&amp;lt;u64&amp;gt;&lt;/code&gt; 的話就需要多一個 bit 來儲存 &lt;code&gt;None&lt;/code&gt;，所以一開始想的話我們應該會覺得它應該會佔 9 bytes，但結果卻是 16 bytes。&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://play.rust-lang.org/?version=stable&amp;amp;mode=debug&amp;amp;edition=2018&amp;amp;gist=636100b0d6ec110d614828933b70124d&quot;&gt;playground&lt;/a&gt;&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt;assert_eq!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt;9&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; std&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;mem&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;size_of&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Option&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;&amp;gt;());&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;thread&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;main&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; panicked at&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;assertion failed: `(left == right)`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;  left: `9`,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; right: `16`&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;, src/main.rs:2:5&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;這是因爲像是在 64-bit 的平台上的 CPU 都是 word-oriented，所有的形態預設都需要 align 爲 8 bytes 的界限。這樣就造成了一些效能的損失，當然這些在平常的應用開發不太重要，編譯器甚至能優化掉，但如果是要寫非常注重空間或記憶體消耗的話（像是寫 file system, kernel module 或 嵌入式系統），可能就需要一些考慮了。爲此 &lt;code&gt;std::num&lt;/code&gt; 提供了沒有零的原生型態像是 &lt;code&gt;NonZeroU8&lt;/code&gt;, &lt;code&gt;NonZeroUsize&lt;/code&gt; 等等。因爲他們的 0 是用不到的，所以作爲 &lt;code&gt;Option&lt;/code&gt; 型態的話，就可以剛好給 &lt;code&gt;None&lt;/code&gt; 使用。這樣一來大小絕對就和原本的型態一樣了。&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://play.rust-lang.org/?version=stable&amp;amp;mode=debug&amp;amp;edition=2018&amp;amp;gist=241f3744d24b83f655fe2f99385b72bf&quot;&gt;playground&lt;/a&gt;&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt;assert_eq!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; std&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;mem&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;size_of&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Option&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;num&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;NonZeroU64&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;&amp;gt;());&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Environment Setup for STM Development in Rust</title>
        <published>2020-06-30T17:01:00+08:00</published>
        <updated>2020-06-30T17:01:00+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/posts/rust-mbed/"/>
        <id>https://wusyong.github.io/posts/rust-mbed/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/posts/rust-mbed/">&lt;p&gt;STM32 is the recommended choice to start with Embedded System Programming in Rust consider there are many supported libraries for Cortex-m series and STM targets and hals among the ecosystem. If you are already familiar with programming with them, all you have to do is add a few config files in your cargo projects and it&#39;s done. If not, fear not then. This post will list all the tools and environment you have to setup. I&#39;m going to use STM32F3DISCOVERY as an example but other STM series should follow similar steps.&lt;/p&gt;
&lt;h2 id=&quot;tooling&quot;&gt;Tooling&lt;/h2&gt;
&lt;p&gt;First of all, we need to install some tools if you didn&#39;t have any embedded setup on your computer before. The common choice for our debuggers are usually GDB with OpenOCD. &lt;code&gt;minicom&lt;/code&gt; may be helpful if you want to also try out some serail module. The GDB you have to install may be different depends on your distribution. On Ubuntu/Debian, it will be &lt;code&gt;gdb-multiarch&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; sudo apt-get install&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;  gdb-multiarch&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;  minicom&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;  openocd&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While others like arch linux will use &lt;code&gt;arm-none-eabi-gdb&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; sudo pacman -S&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;  arm-none-eabi-gdb&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;  minicom&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;  openocd&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you want to communicate with bluetooth, there are some more packages recommended to install: &lt;code&gt;bluez&lt;/code&gt;, &lt;code&gt;bluez-utils&lt;/code&gt;, &lt;code&gt;rfkill&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;udev-rules&quot;&gt;udev rules&lt;/h3&gt;
&lt;p&gt;Next, we want to set some rules to let us use those devices directly without root privilege &lt;code&gt;sudo&lt;/code&gt;. Here&#39;s the example for STM32F3:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; cat /etc/udev/rules.d/99-ftdi.rules:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;# FT232 - USB &amp;lt;-&amp;gt; Serial Converter&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;ATTRS&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;{idVendor}==&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;&amp;quot;0403&amp;quot;,&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; ATTRS{idProduct}==&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;6001&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;, MODE:=&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;0666&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; cat /etc/udev/rules.d/99-openocd.rules&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;# STM32F3DISCOVERY rev A/B - ST-LINK/V2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;ATTRS&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;{idVendor}==&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;&amp;quot;0483&amp;quot;,&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; ATTRS{idProduct}==&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;3748&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;, MODE:=&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;0666&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;# STM32F3DISCOVERY rev C+ - ST-LINK/V2-1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;ATTRS&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;{idVendor}==&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;&amp;quot;0483&amp;quot;,&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; ATTRS{idProduct}==&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;374b&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;, MODE:=&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;0666&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then reload the rules:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; sudo udevadm control --reload-rules&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, let&#39;s plug the device and verify the permissions:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; lsusb&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; grep&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; -i stm&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;Bus&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 001&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; Device 006: ID 0483:374b STMicroelectronics ST-LINK/V2.1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This means my device is connected to Bus 001 and enumerated as Device 006. Let&#39;s check the permissions according to the number we have:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;ls&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; -l /dev/bus/usb/001/006&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;crw-rw-rw-+&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; root root 189,&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 5&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; Jun&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 30&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; 17:31 /dev/bus/usb/001/006&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We should see that current user does have read/write permissions as &lt;code&gt;crw-rw-rw-&lt;/code&gt; shows.&lt;/p&gt;
&lt;h3 id=&quot;openocd-connection&quot;&gt;OpenOCD connection&lt;/h3&gt;
&lt;p&gt;Once we install the packages, we could start to connect to our device using OpenOCD. The cfg file might be different depends on your device. But if everything works as planned, you should see something like following:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; openocd -f interface/stlink-v2-1.cfg -f target/stm32f3x.cfg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;Open&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; On-Chip Debugger&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 0.10.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;Licensed&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; under GNU GPL v2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;For&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; bug reports, read&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;        http://openocd.org/doc/doxygen/bugs.html&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;Info&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; : auto-selecting first available session transport&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;hla_swd&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;. To override use&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;transport select &amp;lt;transport&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;adapter&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; speed:&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 1000&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; kHz&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;adapter_nsrst_delay:&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 100&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;Info&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;none&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; separate&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;Info&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; : Unable to match requested speed&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 1000&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; kHz, using&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 950&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; kHz&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;Info&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; : Unable to match requested speed&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 1000&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; kHz, using&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 950&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; kHz&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;Info&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; : clock speed&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 950&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; kHz&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;Info&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; : STLINK v2 JTAG v27 API v2 SWIM v15 VID&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 0x0483&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; PID&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 0x374B&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;Info&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; : using stlink api v2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;Info&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; : Target voltage:&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 2.910427&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;Info&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; : stm32f3x.cpu: hardware has&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 6&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; breakpoints,&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 4&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; watchpoints&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You should see it says how many breakpoints and watchpoints are there.&lt;/p&gt;
&lt;h3 id=&quot;itm&quot;&gt;ITM&lt;/h3&gt;
&lt;p&gt;For ITM protocol, there&#39;s &lt;code&gt;itmdump&lt;/code&gt; we could install from cargo directly:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; cargo install itm&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And then make sure you start the tool in the same directory of where you start OpenOCD:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; touch itm.txt&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; &amp;amp;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; itmdump&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; -F -f itm.txt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;other-llvm-tools&quot;&gt;Other LLVM tools&lt;/h3&gt;
&lt;p&gt;If you also want to use some LLVM tools like &lt;code&gt;objdump&lt;/code&gt;, &lt;code&gt;size&lt;/code&gt; and more. There&#39;s also a cargo subcommand already:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; cargo install cargo-binutils&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; rustup component add llvm-tools-preview&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then you could use those tools like this:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; cargo objdump --target thumbv7em-none-eabihf --bin app --release -- -disassemble -no-show-raw-insn&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; cargo size --target thumbv7em-none-eabihf --bin app --release -- -A -x&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;rust-toolchains-configurations&quot;&gt;Rust Toolchains &amp;amp; Configurations&lt;/h2&gt;
&lt;p&gt;After installing packages that we needs for general embedded development, we can now start tweaking our rust related
stuffs. Like other projects we do in Rust, we usually create a cargo project since it can integrate several important
build tools especially toolchains when we want to do cross compilation. For STM boards, or Arm Cortex-m architectures
more precisely, here are the targets we could choose:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cortex-M0, M0+, and M1 (ARMv6-M architecture): &lt;code&gt;thumbv6m-none-eabi&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Cortex-M3 (ARMv7-M architecture): &lt;code&gt;thumbv7m-none-eabi&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Cortex-M4 and M7 without hardware floating point (ARMv7E-M architecture): &lt;code&gt;thumbv7em-none-eabi&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Cortex-M4F and M7F with hardware floating point (ARMv7E-M architecture): &lt;code&gt;thumbv7em-none-eabihf&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To install the toolchain, simply run:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; rustup target add thumbv7em-none-eabihf&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;config-files&quot;&gt;Config files&lt;/h3&gt;
&lt;p&gt;Once toolchain is installed, we can cross compile the project to specific target using &lt;code&gt;cargo build --target&lt;/code&gt;. But this
will become tedious and there are more steps need to do when you entering gdb. So instead of typing these command
manually each time, we could setup config files in the cargo project like this.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.cargo/config&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;[&lt;/span&gt;&lt;span&gt;target.thumbv7em-none-eabihf&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;runner&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;arm-none-eabi-gdb -q -x openocd.gdb&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;rustflags&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; =&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;  &amp;quot;-C&amp;quot;,&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;link-arg=-Tlink.x&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;[&lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;target&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;thumbv7em-none-eabihf&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;openocd.gdb&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;target remote :3333&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;set print asm-demangle on&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;set print pretty on&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;monitor tpiu config internal itm.txt uart off 8000000&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;monitor itm port 0 on&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;load&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;break main&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;continue&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This means we will build the project to specific target &lt;code&gt;thumbv7em-none-eabihf&lt;/code&gt; and then run with &lt;code&gt;arm-none-eabi-gdb&lt;/code&gt;
with gdb config file &lt;code&gt;openocd.gdb&lt;/code&gt;. Then we will just need to use &lt;code&gt;cargo run&lt;/code&gt; to enter the gdb and see how it goes!&lt;/p&gt;
&lt;h2 id=&quot;more-references&quot;&gt;More References&lt;/h2&gt;
&lt;p&gt;One of great reasons to develop embedded system in Rust is always its community. There are plenty of resources you can
find in the ecosystem. Here are some I think are useful and might help you too.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/rust-embedded/awesome-embedded-rust&quot;&gt;awesome-embedded-rust&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/rust-embedded/cortex-m-quickstart&quot;&gt;cortex-m-quickstart&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/rtic-rs/cortex-m-rtic&quot;&gt;Real-Time Interrupt-driven Concurrency&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>原子類型（Atomics）</title>
        <published>2020-06-08T12:17:07+08:00</published>
        <updated>2020-06-08T12:17:07+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/posts/atomic/"/>
        <id>https://wusyong.github.io/posts/atomic/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/posts/atomic/">&lt;p&gt;瞭解原子類型（Atomics）與記憶體順序（Memory Ordering）可以幫助我們更瞭解多執行緒程式設計，但實際上要理解的話可能就會和筆者一樣在網路上找隨機的文章或是官方文件來啃，可能就找個當下適合的選項來用，不再繼續往下理解，直到下一次又遇到更深入的問題。這篇文章算是一個總結，希望從最頭到尾說清楚，並且瞭解 Rust 的很多類型爲何那樣設計，以至於能讓所有人都能寫出安全又高效的多執行緒/並行程式。&lt;/p&gt;
&lt;p&gt;以下會先介紹多處理器程式設計，再來才會說明各個記憶體順序的意義，最後講解原子類型怎麼使用這些順序的，結束之前會再補充其他具有內部可變性的 Rust 類型爲什麼也是合理的。&lt;/p&gt;
&lt;h2 id=&quot;duo-chu-li-qi-cheng-shi-she-ji&quot;&gt;多處理器程式設計&lt;/h2&gt;
&lt;p&gt;當今幾乎所有程式都已經是跑在多核心 CPU 的機器上了，而這也產生了不少奇妙的問題讓我們得常常處理。在只有一個執行緒的程式是沒有什麼好擔心的，但如果是多核心的話很多麻煩就跟着來了，我們知道編譯器在編譯時會幫忙重新排列你的程式來做最佳化，事實上連 CPU 也會做這樣的事。對於編譯器的重新排列，我們可以檢查產生出來的組合語言知道，但如果是多核心的 CPU 的話我們就沒辦法這樣做了。&lt;/p&gt;
&lt;p&gt;當執行緒跑在不同的 CPU，CPU 會去重新排列指令，而這樣的行爲是很難去 debug 的，我們往往只能觀察它們的行爲、執行結果、pipeline 和 cache 等等才能知道。而這就是原子類型（Atomics）想要解決的，這些類型會確保在共用記憶體時它們的指令不會被重新排列。&lt;/p&gt;
&lt;h3 id=&quot;qiang-ji-yi-ti-pai-lie-yu-ruo-ji-yi-ti-pai-lie&quot;&gt;強記憶體排列與弱記憶體排列&lt;/h3&gt;
&lt;p&gt;接下來會有很多關於 CPU 的引用都會參考這份文件：&lt;a rel=&quot;external&quot; href=&quot;https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-vol-3a-part-1-manual.pdf&quot;&gt;Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 3A&lt;/a&gt;。但實際上不同的 CPU 對於記憶體會提供不同的保障，我們通常可以區分爲強記憶體排列（Strong Memory Ordering）和弱記憶體排列（Weak Memory Ordering），但這也只是簡單區隔而已，很多甚至是介於這兩者之間。爲了歸納這些不同，C++ 有一套 &lt;a rel=&quot;external&quot; href=&quot;http://www.stroustrup.com/abstraction-and-machine.pdf&quot;&gt;Abstraction Machine&lt;/a&gt;，而 Rust 也是借鑑於此。這套模型便是希望讓我們有辦法寫出能跑在任何機器上的程式，無論是強記憶體排列或是弱記憶體排列。你會看到 &lt;a rel=&quot;external&quot; href=&quot;https://people.mpi-sws.org/~viktor/papers/cpp2015-invited.pdf&quot;&gt;C++ 的 abstraction model&lt;/a&gt; 指定了很多存取記憶體的方式，而這幾乎也是必須的，考量到我們得用相同的語法跑在強與弱記憶體排列的處理器上。&lt;/p&gt;
&lt;p&gt;強記憶體排列的 CPU 可以給與我們一些非常重要的保障，這些保障可以讓我們的指令縮減到 no-op。No-op 是指 CPU 可以讓整個語義不發生，不會有任何花費與成本的損失。他做的事情其實也沒啥酷炫的。他就只是提醒編譯器，我們寫的程式哪些的地方是不可以讓記憶體重新排列的；而弱記憶體排列的 CPU 就沒那麼好了，我們得親自設置記憶體柵欄（Memory Fence）以及寫些特殊的指令來防止同步問題。當然要完全明白最好的方式就是親自在弱記憶體排列的 CPU 試試看，不過現在的人所使用的 CPU 幾乎都是強記憶體排列了，所以寫的時候可能就觀察不到差別了，下面在解釋時會特別說明兩者之間分別發生了什麼事情。&lt;/p&gt;
&lt;p&gt;上面說到現在所有的 CPU 幾乎都是強模型了，無論 AMD 或 Intel 都是，它們能夠對特定的指令給與不重新排列的保障，這些保障我們可以在 &lt;a rel=&quot;external&quot; href=&quot;https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-vol-3a-part-1-manual.pdf&quot;&gt;Intel 開發者手冊&lt;/a&gt;的第 8.2.2 章看到：&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;讀取不會和其他的讀取重新排列&lt;/li&gt;
&lt;li&gt;寫入不會和之前的讀取重新排列&lt;/li&gt;
&lt;li&gt;寫入不會和其他的寫入重新排列（有其他例外）&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;還有最重要的這一條，特別指明不提供保障：&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;讀取可能會和之前其他位置的寫入重新分配，但不會和之前相同位置的寫入重新分配&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;這一條要特別注意的原因是因爲和後面的排列選項 &lt;code&gt;SeqCst&lt;/code&gt; 有關。先在此注意到就好。接下來的章節會以弱模型爲基準，再補充強模型的說明。&lt;/p&gt;
&lt;h3 id=&quot;kuai-qu-ji-yi-ti&quot;&gt;快取記憶體&lt;/h3&gt;
&lt;p&gt;通常 CPU 有三層快取記憶體：L1、L2 和 L3。L2 和 L3 會在 CPU之間共享。而每個核心會有自己的 L1 快取記憶體，我們所有要解決的問題就是從這裏開始。L1 快取記憶體用的是 &lt;a rel=&quot;external&quot; href=&quot;https://zh.wikipedia.org/zh-tw/MESI%E5%8D%8F%E8%AE%AE&quot;&gt;MESI 協議&lt;/a&gt;，聽起來好像很複雜，其實就只是字面上的意思。他是指快取可以有四種狀態的縮寫（&lt;a rel=&quot;external&quot; href=&quot;https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-vol-3a-part-1-manual.pdf&quot;&gt;Intel 開發者手冊&lt;/a&gt;第 11.4 章有做更詳細的介紹）：&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;已修改 Modified (M) - 快取行是髒的（dirty），要寫回主記憶體&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;獨占 Exclusive (E) - 快取行只在當前快取中，但是乾淨的（clean）&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;共享 Shared (S) - 快取行也存在於其它快取中且是乾淨的，快取行可以在任意時刻拋棄&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;無效 Invalid (I) - 快取行是無效的，其他快取修改過了&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;chu-li-qi-zhi-jian-de-tong-xun&quot;&gt;處理器之間的通訊&lt;/h3&gt;
&lt;p&gt;既然我們真的得存取並修改 &lt;code&gt;Shared&lt;/code&gt; 記憶體，那麼其他核心是怎麼知道它們的 L1 已經無效了。一個快取行被視爲無效的規則就是有其他核心的 L1 修改過了，這時雖然自己的 L1 還是在 &lt;code&gt;Shared&lt;/code&gt; 的狀態，但在那邊的卻已經是 &lt;code&gt;Modified&lt;/code&gt; 了。所以記憶體之間得有個通訊的方法來通知大家，我們就暫且想像每個核心都有個&lt;em&gt;&lt;strong&gt;信箱&lt;/strong&gt;&lt;/em&gt;吧。&lt;/p&gt;
&lt;p&gt;每個信箱都可以存一些訊息，以避免 CPU 一直被傳過來的訊息給中斷，到某個時間點 CPU 會檢查信箱然後依據收到的訊息來更新快取。所以舉個例子的話就是，有個 CPU 修改了某個快取行，傳送了訊息給其他核心。核心檢查信箱收到訊息後，更新他們的快取行。最後 L1 從 主記憶體（或 L2、L3）取得正確的值，讓狀態再次回到 &lt;code&gt;Shared&lt;/code&gt;。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;在強模型的 CPU 則會有點不同。如果有個 CPU 要修改 &lt;code&gt;Shared&lt;/code&gt; 的快取行，它得先通知所有的核心讓該行失效，才能真的進行修改。這類的 CPU 通常會有&lt;a rel=&quot;external&quot; href=&quot;https://zh.wikipedia.org/zh-tw/%E5%BF%AB%E5%8F%96%E4%B8%80%E8%87%B4%E6%80%A7&quot;&gt;快取一致性&lt;/a&gt;來修改個核心的快取。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;ji-yi-ti-shun-xu-memory-ordering&quot;&gt;記憶體順序（Memory Ordering）&lt;/h2&gt;
&lt;p&gt;現在我們終於對 CPU 的設計以及它們怎麼溝通開始有點概念了。那麼也是時候來看看這些記憶體順序還有它們代表什麼意思了。無論是 C++ 的 &lt;a rel=&quot;external&quot; href=&quot;https://en.cppreference.com/w/cpp/atomic/memory_order&quot;&gt;std::memory_order&lt;/a&gt; 或是 Rust 的 &lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/std/sync/atomic/enum.Ordering.html&quot;&gt;std::sync::atomic::Ordering&lt;/a&gt;，都有五個值。接下來在講解時，我們很難真的用程式範例來說明發生什麼事情，不過我們可以想像一個觀察者的 CPU 在一旁觀看發生什麼事情。&lt;/p&gt;
&lt;h3 id=&quot;relaxed&quot;&gt;Relaxed&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;在目前的 CPU：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Relaxed 的記憶體順序會防止編譯器重新排列這些指令，但在弱模型的 CPU，它可能還是會重新排列其他所有的記憶體存取。所以如果只是要作爲計數器的話不會有啥問題，但如果是一個要實作在 lock 裡的 flag 的話可能就會出問題了。因爲這樣會無法確保其他一般的記憶體存取有沒有在 flag 之前或之後遭到重新排列。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;在觀察者的 CPU：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;編譯器和 CPU 可以任意重新排列記憶體順序，但是不能夠變更 &lt;code&gt;Relaxed&lt;/code&gt; 讀寫之間的順序。也就是說觀察者的 CPU 可能會看到與我們寫出來的程式順序不同，但是它們永遠會看到 &lt;code&gt;Relaxed&lt;/code&gt; 操作 A 一定會發生在 &lt;code&gt;Relaxed&lt;/code&gt; 操作 B 之前。所以說 &lt;code&gt;Relaxed&lt;/code&gt; 是最弱的記憶體順序，它不會爲其他 CPU 做同步的事情。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;在強模型的話，所有的記憶體操作預設都是 &lt;code&gt;Acquire&lt;/code&gt;/&lt;code&gt;Release&lt;/code&gt; 語義的。因此 &lt;code&gt;Relaxed&lt;/code&gt; 只會是用來告訴編譯器這些指令不能被重新排列的。在強模型用這個順序的原因有助於編譯器去重新排列其他記憶體存取。這也是爲啥你用 Relaxed 的效果會和 &lt;code&gt;Acquire&lt;/code&gt;/&lt;code&gt;Release&lt;/code&gt; 一樣，不過要注意這當然指存在強模型系統下，面對不同的 CPU 平時還是依照歸納模型說明的爲準，不然程式是會在不同 CPU 下出錯的。可以參考&lt;a rel=&quot;external&quot; href=&quot;https://preshing.com/20121019/this-is-why-they-call-it-a-weakly-ordered-cpu/&quot;&gt;這篇文章&lt;/a&gt;看看爲何同個程式碼跑在強記憶體排列與弱記憶體排列會不一樣。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;acquire&quot;&gt;Acquire&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;在目前的 CPU：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;任何在 &lt;code&gt;Acquire&lt;/code&gt; 存取之後的記憶體操作都會維持在它之後，它是與 &lt;code&gt;Release&lt;/code&gt; 順序一對的，組織成一個「記憶體三明治」。所有在它們之間的記憶體存取會與其他 CPU 進行同步。在弱模型的系統下，這代表在 Acquire 操作之前會需要用到一些特殊的 CPU 指令，強迫目前的核心消化完信箱內的所有訊息，很多 CPU 都有這種序列化和記憶體排序的指令。在 &lt;code&gt;Acquire&lt;/code&gt; 讀取之前可能還會在加個記憶體柵欄來防止 CPU 重新排列記憶體存取。這樣 &lt;code&gt;Acquire&lt;/code&gt; 的操作就會與其他 CPU 確保修改記憶體是同步的。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;記憶體柵欄簡單來說就是個硬體的概念，它會強迫 CPU 在柵欄前完成所有的記憶體讀寫，以防止指令重新排列。這樣一來就能確保沒有任何在柵欄前的操作會與柵欄後的操作重新排列。爲了區分不同操作像是讀寫或者全都有，它們都會有不同的名字。全部讀寫都擋的就叫做 full fence。&lt;/p&gt;
&lt;p&gt;你可以在[Intel 開發者手冊]的第 8.2,8.3,8.5 章看到它們的介紹，像是 MFENCE 就是會序列化所有讀寫的柵欄。不過在強模型系統中我們通常看不太到，因爲它們沒有需求。在弱模型的化就不一樣了，它們是實作 &lt;code&gt;Acquire&lt;/code&gt;/&lt;code&gt;Release&lt;/code&gt; 幾乎必備的指令。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;在觀察者的 CPU：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;因爲 &lt;code&gt;Acquire&lt;/code&gt; 是個讀取操作，不會修改記憶體，所以沒有觀察的必要。不過有點要注意的是如果觀察者核心做了 &lt;code&gt;Acquire&lt;/code&gt; 的讀取操作時，它就能夠看到所以從 &lt;code&gt;Acquire&lt;/code&gt; 發生的記憶體操作，一直到 &lt;code&gt;Release&lt;/code&gt; 儲存。這代表有個全域的同步事件正在發生，我們會在後面的 &lt;code&gt;Release&lt;/code&gt; 繼續說明。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Acquire&lt;/code&gt; 通常用來寫鎖的行爲，讓一些操作可以維持在成功取得鎖之後。所以說 &lt;code&gt;Acquire&lt;/code&gt; 只會用在讀取的操作上。在 Rust 的話許多儲存的原子操作要是你用 &lt;code&gt;Acquire&lt;/code&gt; 的話會直接 panic。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;在強模型系統的話，這個會是 no-op 也就是不會有任何花費，也不會有效能的損失。不過它還會防止編譯器去重新排列那些在 &lt;code&gt;Acquire&lt;/code&gt; 之後的記憶體操作被排列到 &lt;code&gt;Acquire&lt;/code&gt; 之前。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;release&quot;&gt;Release&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;在目前的 CPU：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;相對應於 &lt;code&gt;Acquire&lt;/code&gt;，任何在 &lt;code&gt;Release&lt;/code&gt; 記憶體順序之前的記憶體操作都會在它之前。它是與 Acquire 順序一對的。在弱模型系統中，編譯器可能會再加個記憶體柵欄來確保 CPU 沒有重新排列 &lt;code&gt;Release&lt;/code&gt; 之前的記憶體操作到它之後。這邊還有一項保障是所有其他核心做到 &lt;code&gt;Acquire&lt;/code&gt; 時一定要看到所有在 &lt;code&gt;Acquire&lt;/code&gt; 與 &lt;code&gt;Release&lt;/code&gt; 之間的記憶體操作。所以不光是所有操作必須在本地端排序正確，還要確保在此時所有的更動都是可以被其他觀察核心看到的。這就代表在 &lt;code&gt;Acquire&lt;/code&gt; 開始之前以及 &lt;code&gt;Release&lt;/code&gt; 之後都要進行某種全域同步操作。所以我們有兩種選項：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;Acquire&lt;/code&gt; 讀取必須要消化所有的訊息，如果有任何其他核心讓任和我們要讀得記憶失效的話，它必須要讀到正確的值才行。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Release&lt;/code&gt; 儲存必須是原子的並且讓它曾修改的值在其他所有快取都被失效。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;只進行其中一個操作就足夠了，所以這比後面要講的 &lt;code&gt;SeqCst&lt;/code&gt; 弱一些，但是也比較有效率。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;在觀察者的 CPU：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;觀察者的 CPU 可能不會看到任何特定順序的變更，除非他有用到 &lt;code&gt;Acquire&lt;/code&gt; 讀取記憶。如果有的話，它將會看到 &lt;code&gt;Acquire&lt;/code&gt; 與 &lt;code&gt;Release&lt;/code&gt; 的所有記憶體，包含 &lt;code&gt;Release&lt;/code&gt; 本身。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Release&lt;/code&gt; 通常會和 &lt;code&gt;Acquire&lt;/code&gt; 一起用於鎖的實作。對於一個鎖的函式，有些操作通常需要維持在成功獲得鎖之後，一直到鎖被釋放爲止。所以說與 &lt;code&gt;Acquire&lt;/code&gt; 相反，在 Rust 許多讀取的原子操作要是用 &lt;code&gt;Release&lt;/code&gt; 的話會直接 panic。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;在強模型的 CPU，所有的 Shared 值一旦被修改的話，在所有的 L1 快取都會失效。這代表 &lt;code&gt;Acquire&lt;/code&gt; 讀取時就會取得更新過的相關記憶體資訊，而 &lt;code&gt;Release&lt;/code&gt; 會立即讓在其他核心擁有該資訊的快取行失效。這就是爲何這些語義在這類的系統不會有任何效能花費。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;acqrel&quot;&gt;AcqRel&lt;/h3&gt;
&lt;p&gt;這是用在需要同時讀取並儲存值的操作，像是 &lt;code&gt;AtomicBool::compare_and_swap&lt;/code&gt; 就是這種。因爲這樣的操作需要同時讀取並儲存，這在弱模型系統下就會有影響，僅使用 Relaxed 的話是不夠的。我們也可以把這個操作想成是某種柵欄，在它之前的記憶體操作不會被重新排列到這之後，而在之後的操作也不會被排列到之前。剩下做的事情就和上面的 &lt;code&gt;Acquire&lt;/code&gt;/&lt;code&gt;Release&lt;/code&gt; 一樣了。&lt;/p&gt;
&lt;h3 id=&quot;seqcst&quot;&gt;SeqCst&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;在目前的 CPU：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;到這邊強與弱模型的行爲就一樣了，&lt;code&gt;SeqCst&lt;/code&gt; 的意思是 Sequential Consistency，我想就翻作順序一致性吧。它和 &lt;code&gt;Acquire&lt;/code&gt;/&lt;code&gt;Release&lt;/code&gt; 擁有同樣地保障，但還保證能建立「唯一的總修改順序」。&lt;/p&gt;
&lt;p&gt;雖然被視爲最強保障，但其實 &lt;code&gt;SeqCst&lt;/code&gt; 還是有被&lt;a rel=&quot;external&quot; href=&quot;https://github.com/rust-lang/nomicon/issues/166&quot;&gt;質疑&lt;/a&gt;是不是該作爲最推薦的順序，也有些人&lt;a rel=&quot;external&quot; href=&quot;https://github.com/crossbeam-rs/crossbeam/issues/317&quot;&gt;反對&lt;/a&gt;使用它。
很多時候似乎還是很難有個很好的理由說一定得用 &lt;code&gt;SeqCst&lt;/code&gt;，甚至有些&lt;a rel=&quot;external&quot; href=&quot;https://plv.mpi-sws.org/scfix/paper.pdf&quot;&gt;論文&lt;/a&gt;有指出它可能是有瑕疵的。總之，這邊只是提一下不是所有人的看法都相同，很多時候說不定 &lt;code&gt;Acquire`/`Release&lt;/code&gt; 就能涵蓋所有問題了。&lt;/p&gt;
&lt;p&gt;無論如何，讓我們繼續介紹 &lt;code&gt;SeqCst&lt;/code&gt; 吧！我們會需要看個範例和產生的組合語言，以下是 playground 連結： https://godbolt.org/z/EFK-qU&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;use&lt;/span&gt;&lt;span&gt; std&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;sync&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;atomic&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;AtomicBool&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Ordering&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; X&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; AtomicBool&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; AtomicBool&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Y&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; AtomicBool&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; AtomicBool&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;pub fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; example&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;val&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; bool&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; bool&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    let&lt;/span&gt;&lt;span&gt; x&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; X&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;load&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;Ordering&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Acquire&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;    X&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;store&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;val&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; |&lt;/span&gt;&lt;span&gt; x&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; Ordering&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Release&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    let&lt;/span&gt;&lt;span&gt; y&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Y&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;load&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;Ordering&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Acquire&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    x&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; ||&lt;/span&gt;&lt;span&gt; y&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;movb&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;    example::X.0.0&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;%rip&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;, %al&lt;/span&gt;&lt;span style=&quot;color: #616E88;&quot;&gt; # load(Acquire)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;testb&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;   %al, %al&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;setne&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;   %al&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;orb&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;     %dil, %al&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;movb&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;    %al, example::X.0.0&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;%rip&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #616E88;&quot;&gt; # store(Release)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;movb&lt;/span&gt;&lt;span&gt;    $1&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;, %al&lt;/span&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;                   # load(Acquire)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;retq&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;不同CPU可能產生的指令會有點不同，但結果都是一樣的。&lt;code&gt;store&lt;/code&gt; 會用到 &lt;code&gt;Release&lt;/code&gt; 記憶體順序也就是 &lt;code&gt;movb %al, example::X.0.0(%rip)&lt;/code&gt;。我們知道這樣就能確保有該值得快取行會立即失效。&lt;/p&gt;
&lt;p&gt;那問題在哪呢？是時候提起之前其中一項不保證的事情了，&lt;a rel=&quot;external&quot; href=&quot;https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-vol-3a-part-1-manual.pdf&quot;&gt;Intel 開發者手冊&lt;/a&gt;的第 8.2.3.4 章有在更加詳述：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;8.2.3.4 讀取可能會和更早之前不同位置的寫入重新排列
The Intel-64 記憶體排序模型允許讀取能和之前不同位置的寫入重新排列。但是讀取不會和相同位置的寫入重新排列。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;所以也就是說剛剛的範例可能會被改成：&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;let&lt;/span&gt;&lt;span&gt; x&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; X&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;load&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;Ordering&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Acquire&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;X&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;store&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;val&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; |&lt;/span&gt;&lt;span&gt; x&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; Ordering&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Release&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;span&gt; # 之前不同位置的寫入&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;let&lt;/span&gt;&lt;span&gt; y&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Y&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;load&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;Ordering&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Acquire&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;span&gt;   # 讀取&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;// 可能會被 CPU 變更成&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;let&lt;/span&gt;&lt;span&gt; x&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; X&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;load&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;Ordering&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Acquire&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;let&lt;/span&gt;&lt;span&gt; y&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Y&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;load&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;Ordering&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Acquire&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;X&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;store&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;val&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; |&lt;/span&gt;&lt;span&gt; x&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; Ordering&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Release&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果我們現在改成 &lt;code&gt;SeqCst&lt;/code&gt; 的話就可以看到生成的組合語言變成：&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;use&lt;/span&gt;&lt;span&gt; std&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;sync&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;atomic&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;AtomicBool&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Ordering&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; X&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; AtomicBool&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; AtomicBool&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Y&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; AtomicBool&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; AtomicBool&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;pub fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; example&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;val&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; bool&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; bool&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    let&lt;/span&gt;&lt;span&gt; x&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; X&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;load&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;Ordering&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;SeqCst&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;    X&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;store&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;val&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; |&lt;/span&gt;&lt;span&gt; x&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; Ordering&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;SeqCst&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    let&lt;/span&gt;&lt;span&gt; y&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Y&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;load&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;Ordering&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;SeqCst&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    x&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; ||&lt;/span&gt;&lt;span&gt; y&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;movb&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;    example::X.0.0&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;%rip&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;, %al&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;testb&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;   %al, %al&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;setne&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;   %al&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;orb&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;     %dil, %al&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;xchgb&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;   %al, example::X.0.0&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;%rip&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;movb&lt;/span&gt;&lt;span&gt;    $1&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;, %al&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;retq&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我們可以看到讀取的指令變成了 &lt;code&gt;xchgb %al, example::X.0.0(%rip)&lt;/code&gt;，這是一個原子的操作，[&lt;code&gt;xchgb&lt;/code&gt; 有個 &lt;code&gt;lock&lt;/code&gt; 的前綴]，&lt;code&gt;lock&lt;/code&gt; 相關的指令會確保其他所有核心的快取行存取到的記憶體在獲取時會鎖住，然後在修改時變成無效。除此之外它還可以作爲 full fence，&lt;a rel=&quot;external&quot; href=&quot;https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-vol-3a-part-1-manual.pdf&quot;&gt;Intel 開發者手冊&lt;/a&gt;的第 8.2.3.9 章就如此說道：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;8.2.3.9 Lock 指令的讀取和寫入不會被重新排列
記憶體排序模型會阻止 lock 指令的讀取和寫入無論是之前或之後都不會被重新排列。此區塊的範例僅展示 lock 指令在讀取或寫入之前的狀況。讀者請注意到 lock 指令後的讀取或寫入是不會被重新排列的。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;在觀察者的 CPU：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;對於觀察者來說，這項變更非常地顯著。首先就是順序一致性，如果我們要求一個讀取一定得在某個 flag 釋放之後，理論上我們是可以觀察到 Acquire/Release 語義下，它卻在 Release 操作之前就讀取了。使用 lock 可以防止這樣的情況，所以除了擁有 Acquire/Release 的保證以外，它還確保覺不會有其他記憶體的操作會在之間發生，無論是&lt;strong&gt;讀取&lt;/strong&gt;還是寫入。&lt;/p&gt;
&lt;p&gt;再來就是唯一的總修改順序，&lt;code&gt;SeqCst&lt;/code&gt; 在弱模型的 CPU 可以提供一些我們在強模型 CPU 就有的保障，最重要的就是這個唯一總修改順序。如果我們有兩個觀察者核心，他們將會在 &lt;code&gt;SeqCst&lt;/code&gt; 操作下看到相同的順序，Acquire/Release 則沒辦法提供這項保證。一號觀察者可能會看到兩個變動但順序和二號觀察者不同。假如有個一號核心用 &lt;code&gt;Acquire&lt;/code&gt; 拿到了 flag X ，而二號核心也一樣以此方式拿到了 Y。兩者再做相同的操作最後使用 &lt;code&gt;Release&lt;/code&gt; 將 flag 改回去。這樣不會阻止一號觀察者先看到 flag X 變回去再來看到 Y 變回去，但二號觀察者卻看到相反地順序。&lt;code&gt;SeqCst&lt;/code&gt; 可以防止這發生。在強模型下，甚至連儲存都會馬上被其他核心看到，所以修改的順序在這不會是問題。&lt;/p&gt;
&lt;p&gt;**所以說 &lt;code&gt;SeqCst&lt;/code&gt; 是最強的記憶體順序，但同時花費也比其他順序高一些。**你可以看到上面的每個原子指令都會有些開銷，因爲這會用到 CPU 的快取一致機制以及鎖定其他快取的記憶體位置等等。&lt;/p&gt;
&lt;h2 id=&quot;yuan-zi-cao-zuo-atomic-operation&quot;&gt;原子操作（Atomic Operation）&lt;/h2&gt;
&lt;p&gt;除了上述講到的記憶體柵欄，使用 &lt;code&gt;std::sync::atomic&lt;/code&gt; 提供的原子類型還可以使用到一些 CPU 重要的指令，這些是我們平常在 Rust 看不到得：&lt;/p&gt;
&lt;p&gt;在 [Implementing Scalable Atomic Locks for Multi-Core Intel® EM64T and IA32 Architectures] 一文中有提到:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;User level locks involve utilizing the atomic instructions of processor to atomically update a memory space. The atomic instructions involve utilizing a lock prefix on the instruction and having the destination operand assigned to a memory address. The following instructions can run atomically with a lock prefix on current Intel processors: ADD, ADC, AND, BTC, BTR, BTS, CMPXCHG, CMPXCH8B, DEC, INC, NEG, NOT, OR, SBB, SUB, XOR, XADD, and XCHG...&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;也就是說當我們使用原子類型的方法，像是 &lt;code&gt;AtomicUsize&lt;/code&gt; 的 &lt;code&gt;fetch_add&lt;/code&gt; 的話，編譯器實際上會變更原本指令的行爲，在 CPU 除了加兩個數字以外還會做其他事。用組合語言來看的話就會像是 &lt;code&gt;lock addq ...&lt;/code&gt; 而不僅僅是我們平常預期的 &lt;code&gt;addq ...&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;一個原子操作其實是一系列的執行操作組合成一個不可分割的操作單位。任何觀察者是沒辦法看到底下的細部操作或者嘗試在操作執行時獲得相同的資料的。任何在其他核心且會造成的的 B 操作都得等擁有相同資料的操作 A 先完成才行。我們用計數器來舉個例子，總共有三個步驟：讀取資料、修改資料、儲存資料。每一步之間，其他核心都可以跟着採取想要的操作進行讀寫。通常我們希望可以在我們讀取資料一直到儲存回去時，不被其他人干擾到，確定操作正確無誤，這就是原子操作想要解決的。&lt;/p&gt;
&lt;p&gt;原子類型常見的用途之一就是 spinlock，而最簡單的範例大概長得像這樣：https://godbolt.org/z/GxS_bp&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;static&lt;/span&gt;&lt;span&gt; LOCKED&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; AtomicBool&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; AtomicBool&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;static mut&lt;/span&gt;&lt;span&gt; COUNTER&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; usize&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;pub fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; spinlock&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;inc&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; usize&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    while&lt;/span&gt;&lt;span&gt; LOCKED&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;compare_and_swap&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; true&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; Ordering&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Acquire&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;) {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    unsafe&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;span&gt; COUNTER&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; +=&lt;/span&gt;&lt;span&gt; inc&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    LOCKED&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;store&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; Ordering&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Release&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;xorl&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;    %eax, %eax&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;lock&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;    cmpxchgb %cl, example::LOCKED&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;%rip&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;jne&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;     .LBB0_1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;movb&lt;/span&gt;&lt;span&gt;    $0&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;, example::LOCKED&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;%rip&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;retq&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;lock cmpxchgb %cl, example::LOCKED(%rip)&lt;/code&gt; 就是我們的 &lt;code&gt;compare_and_swap&lt;/code&gt;，&lt;code&gt;lock cmpxchgb&lt;/code&gt; 就是我們的 lock 操作，它會讀取 flag 的值然後如果條件符合的話就變更它。我們可以看到&lt;a rel=&quot;external&quot; href=&quot;https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-vol-3a-part-1-manual.pdf&quot;&gt;Intel 開發者手冊&lt;/a&gt;的第 8.2.5 章的說明：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;多處理器的同步機制可能會需要依賴強記憶體排列的模型。在這裏一個程式可以用 lock 指令像是 &lt;code&gt;XCHG&lt;/code&gt; 指令或是 &lt;code&gt;LOCK&lt;/code&gt; 前綴來確保記憶體的讀取、修改、寫入都是原子的。Lock 指令通常就像 I/O 操作一樣，它們等待之前所有的指令完成以及所有緩充區的寫入都寫進記憶體了。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;接下來要釐清的就是 lock 指令前綴是在做什麼了。用最簡短的方式說明的話就是當有記憶體讀取時，它就馬上將該快取行設置爲已修改（Modified）。這樣一來從記憶一被讀取到核心的 L1 快取開始就是 Modified 的了。接着就算每個核心都還沒開始處理他們信箱的訊息，處理器就會用[快取一致性機制]讓所有其他核心的狀態都直接變爲無效（Invalid）了。&lt;/p&gt;
&lt;p&gt;如果說訊息傳遞是一般的同步方式的話，那 lock 操作以及其他記憶體順序或序列化操作則是包含更昂貴但強大的機制可以繞過訊息傳遞，直接鎖定其他核心的快取行，讓任何讀寫都沒辦法在這過程中實現，然後將它們設爲無效（Invalid），進而引導快取去索取更新的值。&lt;/p&gt;
&lt;p&gt;快取行通常在 64 位元的系統都是 64 bytes，不同 CPU 可能還是會有差。不過會特別提起的原因是如果鎖定機制在鎖定時會橫跨兩行快取行的話，花費會變得更昂貴，因爲這會需要再用到一些硬體的技術像是 bus locking 以及更多等等。而且對於會橫跨快取行的原子操作在不同架構擁有支援也大相徑庭。&lt;/p&gt;
&lt;h2 id=&quot;rust-de-yin-yong-xing-tai&quot;&gt;Rust 的引用型態&lt;/h2&gt;
&lt;p&gt;到這邊就算是講完整個原子類型了，希望這些說明能幫到想瞭解的人，至少能夠深入去理解整個原子操作的心智模型我覺得非常有利於往後實際的使用。而在 Rust 也是如此，所以差不多也是時候來深入理解一下 Rust 的引用形態了。我想熟悉 Rust 的人讀完上面應該就會發現這和 Rust 的引用 &lt;code&gt;&amp;amp;&lt;/code&gt; 和 &lt;code&gt;&amp;amp;mut&lt;/code&gt; 有點像，尤其是整個 MESI 協議定義的狀態。當然我們在學的時候，大家是稱 &lt;code&gt;&amp;amp;&lt;/code&gt; 爲 不可變引用（Immutable Reference）；稱 &lt;code&gt;&amp;amp;mut&lt;/code&gt; 爲 不可變引用（Mutable Reference）。書上會說對於那些可以違反 Rust 的型態模型的型態，像是我們本文的重點 Atomics 以及其他諸如 Rc/RefCell 等等，是因爲它們有內部可變性（interior mutability），才能在不可變引用做改變。現在你可以換個角度來看了，&lt;strong&gt;&lt;code&gt;&amp;amp;&lt;/code&gt; 就是共享引用（Shared Reference），而 &lt;code&gt;&amp;amp;mut&lt;/code&gt; 則是獨佔引用（Exclusive Reference）&lt;/strong&gt;。這剛剛好可以對應到 MESI 的 E 和 S，擁有這樣的模型可以作出其他語言做不到的優化。在 Rust 裡，也確實只有被視爲 &lt;code&gt;Exclusive&lt;/code&gt; 記憶體能夠被修改。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;這代表只要我們不違反修改 &lt;code&gt;Shared&lt;/code&gt; 記憶體的規則的話，所有的 Rust 程式可以將所有核心上的 L1 快取視爲是有更新到最新，而且無需進行同步的。&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;當然我們是需要在不同核心間共享記憶體的，但是顯式地表達出來，並特別注意的話是可以寫出品質更好地程式碼的。&lt;/p&gt;
&lt;h3 id=&quot;nei-bu-ke-bian-xing&quot;&gt;內部可變性&lt;/h3&gt;
&lt;p&gt;既然我們可以更改我們觀看得角度，那麼我們也可以一一來解釋哪些具有內部可變性的型態是說的通的了。標準函式庫裡的 &lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/std/cell/struct.UnsafeCell.html&quot;&gt;&lt;code&gt;UnsafeCell&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/a&gt; &lt;em&gt;唯一&lt;/em&gt; 可以擁有可變資料的共享引用，這是一個底層的 unsafe 元件平時這個型態我們是不會直接使用的。其他所有具有內部可變性的型態都是以此打造出安全的界面和不同的功能需求，畢竟 Rust 的初衷就一款能寫出安全程式的語言，這些型態本來必須達到這樣的條件。所以除了原子類型以外，標準函式庫內中含有內部可變性的類型有：&lt;/p&gt;
&lt;h4 id=&quot;cell-t&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/std/cell/struct.Cell.html&quot;&gt;&lt;code&gt;Cell&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;我們可以改變 &lt;code&gt;Cell&amp;lt;T&amp;gt;&lt;/code&gt; 的值，就算有其他的引用存在。但這是安全的因爲它的 API 有保障：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不同的執行緒絕對不可能引用同個 &lt;code&gt;Cell&amp;lt;T&amp;gt;&lt;/code&gt;，這是因爲 &lt;code&gt;Cell&amp;lt;T&amp;gt;&lt;/code&gt; 本來就沒有 &lt;code&gt;Sync&lt;/code&gt; trait，也就是說 &lt;code&gt;Cell&amp;lt;T&amp;gt;&lt;/code&gt; 只能存在單一執行緒。&lt;/li&gt;
&lt;li&gt;沒有辦法取得 &lt;code&gt;Cell&amp;lt;T&amp;gt;&lt;/code&gt; 裏面內容的引用，因爲要是能這樣拿到引用的話，就有可能去改變內部的值違反規則了。它所有的存取動作都是將 &lt;code&gt;Cell&amp;lt;T&amp;gt;&lt;/code&gt; 裡的資料複製出去。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;refcell-t&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/std/cell/struct.RefCell.html&quot;&gt;&lt;code&gt;RefCell&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;我們可以改變 &lt;code&gt;RefCell&amp;lt;T&amp;gt;&lt;/code&gt; 的值，就算有其他的引用存在。但這是安全的因爲它的 API 有保障：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;RefCell&amp;lt;T&amp;gt;&lt;/code&gt; 一樣也只能存在單一執行緒，它和 &lt;code&gt;Cell&amp;lt;T&amp;gt;&lt;/code&gt; 一樣都不能在多執行緒間引用。&lt;/li&gt;
&lt;li&gt;而在單一執行緒時，動態借用檢查規則會去檢測並防止取得 &lt;code&gt;RefCell&amp;lt;T&amp;gt;&lt;/code&gt; 引用並拿到內部資料的人改變其值。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;mutex-t&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/std/sync/struct.Mutex.html&quot;&gt;&lt;code&gt;Mutex&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;我們可以改變 &lt;code&gt;Mutex&amp;lt;T&amp;gt;&lt;/code&gt; 的值，就算有其他的引用存在。但這是安全的因爲它的 API 有保障：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;只有一個引用可以對內部的 &lt;code&gt;T&lt;/code&gt; 進行操作，無論是讀取或寫入。其他的存取都會被擋住直到當前的人將鎖釋放。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;rwlock-t&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/std/sync/struct.RwLock.html&quot;&gt;&lt;code&gt;RwLock&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;我們可以改變 &lt;code&gt;RwLock&amp;lt;T&amp;gt;&lt;/code&gt; 的值，就算有其他的引用存在。但這是安全的因爲它的 API 有保障：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;只有一個引用可以對內部的 &lt;code&gt;T&lt;/code&gt; 改變其值，而且必須在沒有任何引用用來讀取的情況下。要是這條件成立的話，其他的存取都會被擋住。也就是同時只能有一個寫入，或者多個讀取。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;zong-jie&quot;&gt;總結&lt;/h2&gt;
&lt;p&gt;這篇原本是想寫個簡單概述，不過看着像是 &lt;a rel=&quot;external&quot; href=&quot;https://docs.rs/dtolnay/0.0.9/dtolnay/macro._02__reference_types.html&quot;&gt;dtolnay&lt;/a&gt; 和  &lt;a rel=&quot;external&quot; href=&quot;https://cfsamsonbooks.gitbook.io/explaining-atomics-in-rust/&quot;&gt;cfsamson&lt;/a&gt; 的文章，覺得還是都寫下來好了，以上的資訊大部分都來自於此。回過頭來看，我也一樣不覺得一開始在學習時用可變與不可變是錯的，畢竟 Rust 的學習曲線在一開始就算蠻斗的了。不過要是能夠轉換觀看這些類型的心智模型的話，我自己覺得很多事反而更說的通了，不必特地去煩惱哪些型態有內部可變性而哪些沒有，又或者得想很久爲什麼這些 API 得這樣設計。這篇文章的確主軸仍然是原子類型，但我想順便偷渡一下這些觀點，可以發現 Rust 的整個設計模型的確可以直接的對應到底曾的記憶體管理設計。在寫程式時，變能夠特地注意到這些特點，進而寫出品質非常好的程式出來。&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Peh-oe-ji Lite</title>
        <published>2020-06-03T21:11:42+08:00</published>
        <updated>2020-06-03T21:11:42+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/posts/poj-lite/"/>
        <id>https://wusyong.github.io/posts/poj-lite/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/posts/poj-lite/">&lt;p&gt;&lt;strong&gt;Peh-oe-ji Lite (POJL)&lt;/strong&gt; is a dialect of &lt;a rel=&quot;external&quot; href=&quot;https://en.wikipedia.org/wiki/Pe%CC%8Dh-%C5%8De-j%C4%AB&quot;&gt;Pe̍h-ōe-jī&lt;/a&gt;, one of the first orthography in Taiwan and is still widely in use nowadays. It&#39;s literally the same BUT:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;No need for tone marking anymore. You can type &lt;strong&gt;Goa&lt;/strong&gt; (我) instead of Goá.&lt;/li&gt;
&lt;li&gt;Special letters, &lt;code&gt;ⁿ&lt;/code&gt; and &lt;code&gt;o͘&lt;/code&gt;, are simplified to &lt;code&gt;n&lt;/code&gt; and &lt;code&gt;o&lt;/code&gt;. Mo͘ can now be &lt;strong&gt;Mo&lt;/strong&gt; (毛), and Saⁿ can just be &lt;strong&gt;San&lt;/strong&gt; (衫). Here&#39;s the compaison of all letters between original and lite: &lt;code&gt;TODO&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;(Optional) Hyphens &lt;code&gt;-&lt;/code&gt; can be removed or become a space instead. &lt;strong&gt;Peh-oe-ji&lt;/strong&gt;, &lt;strong&gt;peh oe ji&lt;/strong&gt;, and &lt;strong&gt;pehoeji&lt;/strong&gt; are all valid in POJ lite. Just choose the one you think is the most readable.&lt;/li&gt;
&lt;li&gt;(Optional) Same with double hyphen &lt;code&gt;--&lt;/code&gt;. &lt;code&gt;chiah-pa--be&lt;/code&gt; (食飽袂), &lt;code&gt;chiah-pa-be&lt;/code&gt;, &lt;code&gt;chiah pa be&lt;/code&gt;, and &lt;code&gt;chiahpabe&lt;/code&gt; are all valid.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id=&quot;the-reason-that-hyphen-elision-is-optional-is-because-there-are-more-scenarios-need-to-be-considered-actually-we-will-figure-this-out-once-the-proposal-is-finalized&quot;&gt;The reason that hyphen elision is optional is because there are more scenarios need to be considered actually. We will figure this out once the proposal is finalized.&lt;/h5&gt;
&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;
&lt;p&gt;Pe̍h-ōe-jī and Tâi-uân Lô-má-jī are two mainstream romanization systems in Taiwan that are easy to read and write until they meet modern computation systems. Despite there are so many input methods to support on different platforms. It&#39;s still a huge gap to actually type these words. IMHO, we should be able to just use simple alphabet characters to express our sentences. Furthermore, it also increases the readability a lot once tone marks are removed. After all, we usually read &lt;strong&gt;texts&lt;/strong&gt; in any language instead of &lt;strong&gt;pronunciation&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;To be clear again, POJL is just a dialect and is not trying to replace any existing format. It aims to help people type Taiwanese easier, and potentially flatten the learning curve for beginner. Eventually, we expect POJL can be commonly used in casual situations.&lt;/p&gt;
&lt;h2 id=&quot;sample&quot;&gt;Sample&lt;/h2&gt;
&lt;p&gt;Here&#39;s what it looks like if we type in POJL:&lt;/p&gt;
&lt;p&gt;Peh-oe-ji (POJ) si 1 khoan iong Latin (Lo-ma) pheng-im he-thong lai sia Tai-oan e gi-gian e su-bin bun-ji. In-ui tong-chho si thoan-kau-su in--jip-lai e, so-i iah-u-lang ka POJ kio-cho kau-hoe Lo-ma-ji, hek-chia si kan-chheng kau-lo. Put-ji-ko hian-tai e su-iong-chia be-chio m-si kau-to, kau-to ma chin che be-hiau POJ.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>100% 確定清空並釋放記憶體</title>
        <published>2020-05-21T17:35:00+08:00</published>
        <updated>2020-05-21T17:35:00+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/posts/zeroize/"/>
        <id>https://wusyong.github.io/posts/zeroize/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/posts/zeroize/">&lt;p&gt;要&lt;a rel=&quot;external&quot; href=&quot;http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html&quot;&gt;安全地清空記憶體&lt;/a&gt;通常不是我們會在意的事情，在 Rust 因為所有物件都有其生命週期並會在 scope 結束時就被釋放掉，但如果今天的對象是敏感的資訊像是 secret 的話我們就得另當別論了。編譯器一直以來都會自動幫我們最佳化，所以他們很可能會把一些他們認為不必要的呼叫給優化掉，另外如果是在 stack 上的變數則是直到下一次存取才會覆蓋掉。而且當你想交叉編譯的話情況會變得更複雜，當然如果你願意的話可以在 regression 特地編出所有目標然後用 valgrind 之類的檢查有沒有記憶體洩漏，但這似乎太大費周章了。通常這樣的情形我們可以簡單有幾行程式顯式地確定有被清空釋放掉。&lt;/p&gt;
&lt;p&gt;首先我們知道有 &lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/std/ops/trait.Drop.html&quot;&gt;&lt;code&gt;Drop&lt;/code&gt;&lt;/a&gt; trait 讓物件在 drop 時可以多作一些事，可以把這個想成相當於 Destructor 的概念。再來 Rust 雖然還沒有 volatile 的語法，但是在標準函式庫中的 &lt;code&gt;ptr&lt;/code&gt; 模組就已經有 volatile 的方法可以使用，而我們可以在釋放前用 &lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/core/ptr/fn.write_volatile.html&quot;&gt;&lt;code&gt;ptr::write_volatile&lt;/code&gt;&lt;/a&gt; 清掉我們的敏感資訊，而且確定不會被編譯器重新排列或者優化掉。最後我們加上 &lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/stable/core/sync/atomic/fn.compiler_fence.html&quot;&gt;&lt;code&gt;atomic::compiler_fence&lt;/code&gt;&lt;/a&gt; 來確保所有的存取在這時看到的 secret 已經是被清掉的訊息了。這樣一來就能 100% 確定我們想釋放的記憶體是真的會被 drop 掉。&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://play.rust-lang.org/?version=stable&amp;amp;mode=debug&amp;amp;edition=2018&amp;amp;gist=5017c1b927f2441554a23e629aa83091&quot;&gt;Playground link&lt;/a&gt;&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;use&lt;/span&gt;&lt;span&gt; std&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;sync&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;atomic&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;compiler_fence&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;use&lt;/span&gt;&lt;span&gt; std&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;sync&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;atomic&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Ordering&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;use&lt;/span&gt;&lt;span&gt; std&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;ptr&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;write_volatile&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;use&lt;/span&gt;&lt;span&gt; std&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;ops&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Drop&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5E81AC;&quot;&gt;#[derive(&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Default&lt;/span&gt;&lt;span style=&quot;color: #5E81AC;&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;struct&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Secret&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;impl&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Drop&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; for&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Secret&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; drop&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;amp;mut self&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;        unsafe&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; write_volatile&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; Default&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;default&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;()); }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;        compiler_fence&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;Ordering&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;SeqCst&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt;        println!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;Secret is dropped for sure!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    let&lt;/span&gt;&lt;span&gt; _secret&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; Secret&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;Sensitive info&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
        
    </entry>
    <entry xml:lang="en">
        <title>用 grcov 收集整合 code coverage</title>
        <published>2020-04-30T06:37:23+08:00</published>
        <updated>2020-04-30T06:37:23+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/posts/grcov/"/>
        <id>https://wusyong.github.io/posts/grcov/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/posts/grcov/">&lt;p&gt;在 Rust cargo 專案中進行 code coverage 比想像中輕鬆許多。透過 &lt;a rel=&quot;external&quot; href=&quot;https://github.com/mozilla/grcov&quot;&gt;grcov&lt;/a&gt; 兩三行指令就能產生出報告來了。首先要先下載 &lt;a rel=&quot;external&quot; href=&quot;https://github.com/mozilla/grcov/releases&quot;&gt;release&lt;/a&gt;，不過既然有 cargo 我們只要 &lt;code&gt;cargo install grcov&lt;/code&gt; 就好了。&lt;/p&gt;
&lt;p&gt;再來設置一下環境變數，以下能夠防止 dead code 簡化才不會影響 coverage&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;export CARGO_INCREMENTAL=0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;export RUSTFLAGS=&amp;quot;-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;export RUSTDOCFLAGS=&amp;quot;-Cpanic=abort&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然後就像平時一樣測試就好了&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cargo build&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cargo test&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;這樣就能在 &lt;code&gt;target/debug/deps/&lt;/code&gt; 看到產生的檔案 &lt;code&gt;.gcdo&lt;/code&gt; &lt;code&gt;.gcda&lt;/code&gt;。如果要在產生 html coverage report 的話像這樣作就好&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;grcov ./target/debug/ -s . -t html --llvm --branch --ignore-not-existing -o ./target/debug/coverage/&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;最後報告的位置就在 &lt;code&gt;target/debug/coverage/index.html&lt;/code&gt;，整個過稱輕鬆寫意大概花不到五分鐘就完成了。&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Arch Linux 與 Windows 雙系統安裝方法</title>
        <published>2020-03-16T18:00:00+08:00</published>
        <updated>2020-03-16T18:00:00+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/posts/arch-dual-boot/"/>
        <id>https://wusyong.github.io/posts/arch-dual-boot/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/posts/arch-dual-boot/">&lt;p&gt;Arch 其實我已經用好一陣子了，當時在安裝前就有想過裝好後就要寫個文章還願一下，畢竟在這過程中也受益於不少社群的幫助，但是安裝時忘了一一截圖所以後來就懶了。現在想起來覺得還是該寫一下算是有個交待。首先，如果你的電腦沒有啥特別的需求像是一定得玩遊戲之類的，我是覺得可以直接裝任一 Linux 發行版了，畢竟現在是個什麼都是 Web app 或 Electron 的時代，你常用的各式程式像是 Spotify 或 Discord 等在 Linux 上都絕對都能安裝，你會用到的 IDE 通常在 Linux 上的支援都會更完備，想省麻煩的話就直上 Linux 吧！不過說到底有時還是會有些不得不保留 Windows 的需求在，如果你想體驗看看輕量化且十分彈性的 Arch 並參與它熱絡的社群的話，希望這篇能幫助到大家。&lt;/p&gt;
&lt;h2 id=&quot;shi-qian-zhun-bei&quot;&gt;事前準備&lt;/h2&gt;
&lt;p&gt;在開始之前，我誠心建議還是看一下 Arch 維基 &lt;a rel=&quot;external&quot; href=&quot;https://wiki.archlinux.org/title/Dual_boot_with_Windows&quot;&gt;Dual boot with Windows&lt;/a&gt; 的說明，下面等會會一一說明叫大家注意的，其實在這篇都有列舉出來。再來是兩個系統安裝的順序，我也是建議先安裝 Windows 在裝 Arch，而且在安裝 Windows 時最好將 &lt;strong&gt;boot partition 設為 512 MB&lt;/strong&gt; 以上（預設好像會是 100 MB）。然後如果你是 Windows 8 以上應該都是用 UEFI，所以請記得&lt;strong&gt;關掉 Secure Boot&lt;/strong&gt;，每家韌體的停用方法都會有點不一樣所以可能得自行搜尋一下。最後是到 Windows 控制台的的電源選項&lt;strong&gt;停用 Fast Startup 和 hibernation&lt;/strong&gt;，這兩個預設應該都是開啟的。&lt;/p&gt;
&lt;h2 id=&quot;zhi-zuo-arch-linux-an-zhuang-usb&quot;&gt;製作 Arch Linux 安裝 USB&lt;/h2&gt;
&lt;p&gt;在這邊我預設大家是用 Windows 來製作，先到 &lt;a rel=&quot;external&quot; href=&quot;https://www.archlinux.org/download/&quot;&gt;Arch 官網下載&lt;/a&gt;，然後用 &lt;a rel=&quot;external&quot; href=&quot;https://rufus.ie/&quot;&gt;Rufus&lt;/a&gt; 製作安裝碟。如果你是 Linux 的話可以直接用 &lt;code&gt;dd&lt;/code&gt; 。&lt;/p&gt;
&lt;p&gt;如果你的電腦是 UEFI 在燒錄時就選擇「GPT Partition」（大多數 Windows 7  以上 應該都是這個），如果還是不是的話就選「MBR partition」。如果你完全不清楚的話可以按下「開始鍵 + R」，然後輸入 &lt;code&gt;msinfo32&lt;/code&gt;，按下去之後應該會看到你的 BIOS 模式，如果顯示 UEFI 就選「UEFI-GPT mode」，如果是 Legacy 就選「BIOS-MBR mode」。&lt;/p&gt;
&lt;p&gt;製作完後，就重開機然後開 BIOS 調整開機順序用讓 USB 先執行吧。一樣每個人開 BIOS 的按鍵通常也不一樣，就 del, F12, ESC 都按按看吧。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/del.webp&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;h2 id=&quot;fen-ge-ci-qu&quot;&gt;分割磁區&lt;/h2&gt;
&lt;p&gt;通常我們會開出三個 partition 給 Linux：&lt;code&gt;/&lt;/code&gt;(root), &lt;code&gt;[swap]&lt;/code&gt;, &lt;code&gt;/home&lt;/code&gt;，&lt;code&gt;/boot&lt;/code&gt; 在前面已經提過了而我建議是 512 MB 以上。這邊算是比較頭痛的地方，因為要開多少見仁見智。Arch 維基也有一篇在介紹該如何分割 &lt;a rel=&quot;external&quot; href=&quot;https://wiki.archlinux.org/title/Partitioning&quot;&gt;Partitioning&lt;/a&gt;，不太確定該怎麽開的話可以參考看看。基本上來說會建議 root 開至少 20 GB 以上，swap 開跟你的 RAM 一樣的大小，剩下的全給 home。在開始分割之前先用  &lt;code&gt;lsblk&lt;/code&gt; 確定你的硬碟：&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; lsblk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;sda&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;      8:0&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt;    0&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; 465.8G&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt;  0&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; disk&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;-sda1&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;   8:1&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt;    0&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;   512M&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt;  0&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; part /boot&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;-sda2&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;   8:2&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt;    0&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;    16M&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt;  0&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; part&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;-sda3&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;   8:3&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt;    0&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;   464G&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt;  0&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; part &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然後用 &lt;code&gt;cfdisk&lt;/code&gt; 開始設置，以下是我設好後的樣子：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/cfdisk.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;所以這些是我會用到的磁區，以下請依照你分割對應的磁區來輸入指令&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;/dev/sda4 : root&lt;/li&gt;
&lt;li&gt;/dev/sda5 : swap&lt;/li&gt;
&lt;li&gt;/dev/sda6 : home&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;ge-shi-hua-linux-ci-qu&quot;&gt;格式化 Linux 磁區&lt;/h3&gt;
&lt;p&gt;分割好後再來就是格式化我們的 root 和 home 磁區，我這邊會繼續用 ext4，如果你想要的話也可以試試潮潮的 &lt;a rel=&quot;external&quot; href=&quot;https://wiki.archlinux.org/title/Btrfs&quot;&gt;Btrfs&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; mkfs.ext4 /dev/sda4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; mkfs.ext4 /dev/sda6&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;jian-li-swap&quot;&gt;建立 swap&lt;/h3&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; mkswap /dev/sda5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; swapon /dev/sda5&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;gua-zai-ci-qu&quot;&gt;掛載磁區&lt;/h3&gt;
&lt;p&gt;所有磁區都設好後就可以掛仔他們了。&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; mount /dev/sda4 /mnt&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; mkdir /mnt/home&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; mount /dev/sda6 /mnt/home&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; mkdir /mnt/boot&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; mount /dev/sda1 /mnt/boot&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;kai-shi-an-zhuang&quot;&gt;開始安裝&lt;/h2&gt;
&lt;p&gt;萬事就緒！開始來安裝 Arch Linux 吧！&lt;/p&gt;
&lt;h3 id=&quot;wang-lu-lian-xian&quot;&gt;網路連線&lt;/h3&gt;
&lt;p&gt;如果你要用 wifi 的話，先用 &lt;code&gt;wifi-menu&lt;/code&gt; 來選擇連線，不然直接 &lt;code&gt;ping&lt;/code&gt; 即可測試：&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; wifi-menu&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; ping  -c&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 3&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; www.google.com&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;yan-zheng-yu-geng-xin&quot;&gt;驗證與更新&lt;/h3&gt;
&lt;p&gt;這邊更新 gpg key 好讓 pacman (Arch 的套件管理工具) 可以驗證安裝套件：&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; pacman-key --refresh-keys&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;順便更新一下系統時間&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; timedatectl set-ntp&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; true&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;kai-shi-an-zhuang-1&quot;&gt;開始安裝&lt;/h3&gt;
&lt;p&gt;接著就可以一路按 Enter 或 Y 直到安裝進行。你也可以再多裝 &lt;code&gt;base-devel&lt;/code&gt; 不過我打算需要的工具再裝就好：&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; pacstrap /mnt base linux linux-firmware&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;chan-sheng-gua-zai-she-ding-dang&quot;&gt;產生掛載設定檔&lt;/h3&gt;
&lt;p&gt;Linux 需要除存掛載以便之後自動掛載：&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; genfstab -U /mnt&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; &amp;gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; /mnt/etc/fstab&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;boot-loader-she-ding&quot;&gt;Boot Loader 設定&lt;/h2&gt;
&lt;p&gt;接下來的步驟我們都可以切到我們的系統上進行了：&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; arch-chroot /mnt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我一開始是用 systemd-boot，但為了省掉一些麻煩我們還是用大家耳熟能詳的 GRUB 吧。我們會需要 &lt;a rel=&quot;external&quot; href=&quot;https://www.archlinux.org/packages/?name=grub&quot;&gt;grub&lt;/a&gt; 和 &lt;a rel=&quot;external&quot; href=&quot;https://www.archlinux.org/packages/?name=efibootmgr&quot;&gt;efibootmgr&lt;/a&gt;。&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; pacman -S grub efibootmgr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;安裝 GRUB:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;安裝 os-prober 讓 Windows 可以出現在 GRUB 的選單中：&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; pacman -S os-prober&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;掛載 Windows 的磁區，像我的是 /dev/sda3：&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; mkdir /mnt/windows10&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; mount /dev/sda2 /mnt/windows10&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;產生 grub 設定檔：&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; grub-mkconfig -o /boot/grub/grub.cfg&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;wang-lu-she-ding&quot;&gt;網路設定&lt;/h2&gt;
&lt;p&gt;我們希望開機後能夠自動連上網路：&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; pacman -S netctl wpa_supplicant dialog&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果你是用 wifi 的話，跟之前一樣：&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; wifi-menu&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果是用 LAN 的話：&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; systemctl enable dhcpcd@enp0s31f6.service&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;dhcpcd@&lt;/code&gt; 後面要輸入的是你的 interface name，你可以用 &lt;code&gt;ip link&lt;/code&gt; 或 &lt;code&gt;ls /sys/class/net&lt;/code&gt; 查到：&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; ip link&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;1:&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; lo:&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;LOOPBACK,UP,LOWER_U&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; mtu&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 65536&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; qdisc noqueue state UNKNOWN mode DEFAULT group def&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;    link/loopback&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; 00:00:00:00:00:00 brd 00:00:00:00:00:00&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;2:&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; enp0s31f6:&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;BROADCAST,MULTICAST,UP,LOWER_U&lt;/span&gt;&lt;span&gt;P&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; mtu&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 1500&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; qdisc fq_codel state UP mode DEFAult qlen&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 1000&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;    link/ether&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; 4c:cc:6a:ba:86:bb brd ff:ff:ff:ff:ff:ff&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;xi-tong-she-ding&quot;&gt;系統設定&lt;/h2&gt;
&lt;p&gt;在設定其他東西之前，推薦裝一下自動補完，方便你輸入指令&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; pacman -S bash-completion&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;root-yu-shi-yong-zhe-mi-ma&quot;&gt;root 與使用者密碼&lt;/h3&gt;
&lt;p&gt;先設定 root 的密碼&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; passwd&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;到這邊為止你已經可以直接重開機了，不過想將設定一次到位的話，我們可以繼續下去&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; reboot&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;再來建立一個新的使用者並加入相對應的 group，這個會是你平時用來登入的使用者&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; useradd -m -g users -G wheel,storage,power -s /bin/bash yourusername&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; passwd yourusername&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;接著我們要讓 wheel group 的使用者可以用 sudo 執行管理員相關的任務，如果你不熟悉 vim 的話也可以用 nano 就好&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; EDITOR=vim visudo&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;找到這行並解除留言（去掉 # 符號）&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;%wheel ALL=(ALL) ALL&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;she-ding-shi-jian-yu-yu-xi&quot;&gt;設定時間與語系&lt;/h3&gt;
&lt;p&gt;編輯語系檔案(一樣選你熟悉的編輯器)然後解除留言&lt;code&gt;en_US.UTF-8 UTF-8&lt;/code&gt;，你也可以再選擇其他語系，以台灣來說的話就是找到 &lt;code&gt;zh_TW.UTF-8 UTF-8&lt;/code&gt; 解除這行的留言：&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ vim /etc/locale.gen&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;接著用此檔案產生語系&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; locale-gen&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; echo LANG=en_US.UTF-8&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; &amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; /etc/locale.conf&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; export LANG=en_US.UTF-8&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&quot;shi-qu&quot;&gt;時區&lt;/h4&gt;
&lt;p&gt;你可以用這個指令搜尋時區&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; ls /usr/share/zoneinfo/&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;當然你要是就在台北時區這樣設定就好了&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; ln -s /usr/share/zoneinfo/Asia/Taipei /etc/localtime&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&quot;ying-ti-shi-zhong&quot;&gt;硬體時鐘&lt;/h4&gt;
&lt;p&gt;讓硬體時鐘在作業系統之間一致，以防它去複寫改變了顯示的時間&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; hwclock --systohc&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;hostname&quot;&gt;Hostname&lt;/h3&gt;
&lt;p&gt;命名你的主機名稱，這邊我就只叫做 arch 就好：&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; echo arch&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; &amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; /etc/hostname&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;diao-zheng-mirror-list&quot;&gt;調整 mirror list&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;pacman-contrib&lt;/code&gt; 這個套件有個腳本 &lt;code&gt;/usr/bin/rankmirrors&lt;/code&gt; 可以幫你排出最快的 mirror，不過要是嫌太麻煩的話就用 &lt;a rel=&quot;external&quot; href=&quot;https://www.archlinux.org/mirrorlist/&quot;&gt;Pacman Mirrorlist Generator&lt;/a&gt; 吧！然後寫進這邊：&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; vim /etc/pacman.d/mirrorlist&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;Server&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; = http://archlinux.cs.nctu.edu.tw/&lt;/span&gt;&lt;span&gt;$repo&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;/os/&lt;/span&gt;&lt;span&gt;$arch&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;zhuo-mian-huan-jing&quot;&gt;桌面環境&lt;/h2&gt;
&lt;p&gt;桌面環境想用那家一樣見仁見智，如果這些你打算自己摸索的話，那麽到這邊我們就算是告一段落了，已經可以開始你的 arch 探索之旅！不然這邊我們將還是先裝最大宗的 gnome，想找更多可以參考 &lt;a rel=&quot;external&quot; href=&quot;https://wiki.archlinux.org/title/Desktop_environment&quot;&gt;Desktop environment&lt;/a&gt;，裡面也有台灣之光號稱最輕量的 LXDE/LXQT。&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; pacman -S gnome gnome-extra&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; systemctl enable gdm.service&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; systemctl start gdm.service&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;大功告成！恭喜！&lt;/p&gt;
&lt;h4 id=&quot;references&quot;&gt;References&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;https://wiki.archlinux.org/title/Dual_boot_with_Windows&lt;/li&gt;
&lt;li&gt;https://gist.github.com/xtrymind/b895c640231adde21598d5188c75d4b5&lt;/li&gt;
&lt;li&gt;http://lampjs.com/easy-installing-arch-linux-dual-boot-with-windows-uefi-for-beginners/&lt;/li&gt;
&lt;/ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Waker Practice: Attempt to Unwrap a Future</title>
        <published>2020-03-15T16:13:00+08:00</published>
        <updated>2020-03-15T16:13:00+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/posts/future-unwrap/"/>
        <id>https://wusyong.github.io/posts/future-unwrap/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/posts/future-unwrap/">&lt;p&gt;Many enum types like &lt;code&gt;Option&lt;/code&gt; and &lt;code&gt;Result&lt;/code&gt; provide method like &lt;code&gt;unwrap&lt;/code&gt; to retrieve the field immediately. It panics if it can not get the value we want. This gives me an idea to do a silly exercise. What if we can also unwrap a future? &quot;But why?&quot; you said. Because why not. Consider when we use &lt;code&gt;.await&lt;/code&gt; syntax on futures from &lt;code&gt;async&lt;/code&gt; blocks or functions, it will poll the future and see if it is ready. The compiler transforms the whole block into some sort of state machine, and each &lt;code&gt;.await&lt;/code&gt; represents a potential state transition. And now I would like to make this exit to be &lt;code&gt;unwrap&lt;/code&gt; which attempts to resolve a future immediately.&lt;/p&gt;
&lt;h2 id=&quot;wake-up-mr-freeman&quot;&gt;Wake up Mr. Freeman&lt;/h2&gt;
&lt;p&gt;The entire method is quite easy actually, we just need to match the poll and then return the value. But the missing puzzle is the waker. In real executor system, it will provide all required contexts for us. But we are going to poll it manually ourselves, we need to define our waker function. Fortunately, the standard library already provide all the components we want. We just have to assemble them, so let&#39;s wake up and smell the ashes!&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;pub fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; waker&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;F&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; Fn&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Send&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Sync&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; F&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Waker&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    let&lt;/span&gt;&lt;span&gt; raw&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Arc&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;into_raw&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;Arc&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;))&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; as *const&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; ();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    let&lt;/span&gt;&lt;span&gt; vtable&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; = &amp;amp;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;RawWakerHelper&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;F&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;VTABLE&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    unsafe&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Waker&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;from_raw&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;RawWaker&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;raw&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; vtable&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)) }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We create a waker function which outputs, well, a &lt;code&gt;Waker&lt;/code&gt;. This type is a wrapper of inner instance &lt;code&gt;RawWaker&lt;/code&gt; which provides customized wakeup behavior. It consists of a pointer to data and vtable to customize the behavior we mentioned before. Since there&#39;s a method in vtable for cloning and we want the waker and future we are dealing with are still the same one, we wrap up with &lt;code&gt;Arc&lt;/code&gt; and turn it back to raw pointer. I will show you what&#39;s going to be next.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;struct&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; RawWakerHelper&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;F&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;F&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;impl&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;F&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; Fn&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Send&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Sync&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; RawWakerHelper&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;F&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    const&lt;/span&gt;&lt;span&gt; VTABLE&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; RawWakerVTable&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; RawWakerVTable&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;        Self::&lt;/span&gt;&lt;span&gt;clone_waker&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;        Self::&lt;/span&gt;&lt;span&gt;wake&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;        Self::&lt;/span&gt;&lt;span&gt;wake_by_ref&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;        Self::&lt;/span&gt;&lt;span&gt;drop_waker&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    unsafe fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; clone_waker&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;ptr&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: *const&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; ())&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; RawWaker&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;        let&lt;/span&gt;&lt;span&gt; arc&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; ManuallyDrop&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;Arc&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;from_raw&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;ptr&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; as *const&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; F&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        mem&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;forget&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;arc&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;clone&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;        RawWaker&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;ptr&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; &amp;amp;Self::&lt;/span&gt;&lt;span&gt;VTABLE&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    unsafe fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; wake&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;ptr&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: *const&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; ()) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;        let&lt;/span&gt;&lt;span&gt; arc&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Arc&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;from_raw&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;ptr&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; as *const&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; F&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;        (&lt;/span&gt;&lt;span&gt;arc&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    unsafe fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; wake_by_ref&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;ptr&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: *const&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; ()) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;        let&lt;/span&gt;&lt;span&gt; arc&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; ManuallyDrop&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;Arc&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;from_raw&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;ptr&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; as *const&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; F&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;        (&lt;/span&gt;&lt;span&gt;arc&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    unsafe fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; drop_waker&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;ptr&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: *const&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; ()) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;        drop&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;Arc&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;from_raw&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;ptr&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; as *const&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; F&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see the rest parameters that &lt;code&gt;RawWakerVTable&lt;/code&gt; requires are here. Since it demands raw pointers which already touch the unsafe field. We are able to play around out &lt;code&gt;Arc&lt;/code&gt; pointer in several way and still be sound. Take a look a little bit more if needed, all methods and modules used are documented in standard library.&lt;/p&gt;
&lt;h2 id=&quot;time-to-uwrap&quot;&gt;Time to &lt;code&gt;uwrap&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Once our waker is done, the last thing left to do is to write out one and only function &lt;code&gt;unwrap&lt;/code&gt;. And it&#39;s way simpler than you thought:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;pub fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; unwrap&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;F&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Future&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; F&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span&gt; F&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Output&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    let&lt;/span&gt;&lt;span&gt; waker&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; waker&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; ());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    let mut&lt;/span&gt;&lt;span&gt; f&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Box&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;pin&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    match&lt;/span&gt;&lt;span&gt; f&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;as_mut&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;poll&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;amp;mut&lt;/span&gt;&lt;span&gt; Context&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;from_waker&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;waker&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;        Poll&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;Ready&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;output&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span&gt; output&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;        Poll&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Pending&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;       =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt; panic!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;future not ready&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&#39;s it! Although this is probably very useless unless you are prototyping some executor or reactor systems. Still a good practice imho. Here&#39;s the &lt;a rel=&quot;external&quot; href=&quot;https://play.rust-lang.org/?version=stable&amp;amp;mode=debug&amp;amp;edition=2018&amp;amp;gist=7bad9f4c80261dc1f46b76abd251dba9&quot;&gt;link to the playground&lt;/a&gt;. Hope you can get more familiar with modules beneath the future system.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>DST 和 ZST 兩種願望一次滿足</title>
        <published>2020-01-25T18:40:07+08:00</published>
        <updated>2020-01-25T18:40:07+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/posts/dst-zst/"/>
        <id>https://wusyong.github.io/posts/dst-zst/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/posts/dst-zst/">&lt;p&gt;我們知道 Rust 大部分情況下要求要知道型態的 size 與 alignment，不過同時也支援一些特殊的型態可以忽視這些條件。首先我們最常遇見的就是 Dynamically Sized Types (DSTs) 它們就不會靜態地知道 size 與 alignment，所以它們得透過指標 (pointer) 指向它們才得以存在，這樣的指標是一個寬指標包含一個指針以及一些額外資訊來滿足 Rust 的要求。而這樣的型態也許沒察覺到但其實我們已經遇到而且也用到非常多次，其中最主要的兩大型態就是 trait object 和 slice，更多詳情可以參考 &lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/nomicon/exotic-sizes.html&quot;&gt;Rustonomicon&lt;/a&gt; 的解釋。在平時使用泛型時我們可以用 &lt;code&gt;?Sized&lt;/code&gt; 來指定 DST，以下是將 trait 的 associate type 指定為 DST 的範例：&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;trait&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;font-weight: bold;&quot;&gt; EncodedBuf&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;  type&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Slice&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: ?&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Sized&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;  fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt; Self where Self:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Sized&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;  /// View the bytes in this buffer as a slice&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;  fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; as_slice&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;amp;self&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt; &amp;amp;Self::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Slice&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;  //...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;當然 DST 實際上在很多函式庫中的使用都是很受限的，大部分當然對型態的要求都是 &lt;code&gt;Sized&lt;/code&gt;。在標準函式庫中我們也不乏看到諸多類似的設計像是 &lt;code&gt;&amp;amp;str&lt;/code&gt; 之於 &lt;code&gt;String&lt;/code&gt;、 &lt;code&gt;&amp;amp;[]&lt;/code&gt; 之於 &lt;code&gt;Vec&lt;/code&gt; 、 &lt;code&gt;Path&lt;/code&gt; 之於 &lt;code&gt;PathBuf&lt;/code&gt; 等等。前者均為 DST 都是設計成不擁有其數據的引用 (reference) 型態，需要用後者才能獲得所有權並作為可變 ( mutable) 數據來使用。&lt;/p&gt;
&lt;p&gt;而另一方面 Rust 也還支援 Zero Sized Types (ZSTs) 顧名思義就是沒有大小的型態，當然一開始想到的話的確沒有任何意義。當然對於編譯也是如此，所以 Rust 在編譯時可以將一些型態轉為 ZST 並讓它們的動作最終變成只有 &lt;code&gt;nop&lt;/code&gt;。原因很簡單，一來是它沒有大小，開空間給它們來儲存沒有任何意義，二來它們也只會有一種值甚至可以憑空產生，所以直接轉為 &lt;code&gt;nop&lt;/code&gt; 的確很合適。我們最常用到的 ZST 大概就非 empty tuple &lt;code&gt;()&lt;/code&gt; 莫屬，常常用在 Enum 像是 &lt;code&gt;Result&lt;/code&gt; 的 match 配對等等。&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; return_ok&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Result&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;(),&lt;/span&gt;&lt;span&gt; io&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Error&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;  Ok&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;既然知道有這兩種型態後，現在就讓我們用上面的 &lt;code&gt;EncodedBuf&lt;/code&gt; trait 嘗試一些有趣的東西，當然還有很多方法和 trait 沒寫上去，不過實作均類似所以不贅述：&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;pub struct&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; NewByte&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;([()]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;impl&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; NewByte&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    unsafe fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; make&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;ptr&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: *const&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; u8&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; offset&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; usize&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; len&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; usize&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt; *const Self&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        std&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;mem&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;transmute&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;((&lt;/span&gt;&lt;span&gt;ptr&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;offset&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;offset&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; as&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; isize&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;),&lt;/span&gt;&lt;span&gt; len&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    unsafe fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; ptr&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;amp;self&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; index&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; usize&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt; *const&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; u8&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;        (&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;self.&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;as_ptr&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; as *const&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; u8&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;offset&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;index&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; as&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; isize&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    pub fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; slice&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;amp;self&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; range&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Range&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt; &amp;amp;Self&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt;        assert!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;range&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span&gt;end &lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;gt;=&lt;/span&gt;&lt;span&gt; range&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span&gt;start &lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span&gt; range&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span&gt;end &lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;lt;= self.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;len&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;        unsafe&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; &amp;amp;*Self::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;make&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;self.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;ptr&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;),&lt;/span&gt;&lt;span&gt; range&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span&gt;start&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span&gt; range&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span&gt;end &lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;-&lt;/span&gt;&lt;span&gt; range&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span&gt;start&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;) }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;    //...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;pub struct&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; NewByteBuf&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Vec&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;u8&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;impl&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; EncodedBuf&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; for&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; NewByteBuf&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    type&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Slice&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; NewByte&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt; Self&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;        Self&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Vec&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    pub fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; as_slice&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;amp;self&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt; &amp;amp;Self::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Slice&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;        unsafe&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; &amp;amp;*Self::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Slice&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;make&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;self.&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;as_ptr&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; as&lt;/span&gt;&lt;span&gt; _&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; self.&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;len&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;()) }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #616E88;&quot;&gt;    //...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;簡單來說，我們嘗試定義兩種新的型態而他們的關係就類似 &lt;code&gt;Path&lt;/code&gt;/&lt;code&gt;PathBuf&lt;/code&gt;，它們的長度可能就不是一般的 byte，也許是 3 bits 就一個 byte，不過為了方變我們還是先用 8 bits = 1 byte 作為範例。接著有趣的地方是 &lt;code&gt;NewByte&lt;/code&gt;，這是一個 DST 包住了 &lt;code&gt;[()]&lt;/code&gt;：一個只包含 zero-sized item 的陣列而且沒有定義長度。由於對 DST 的引用是個胖指針 (我們可以下 &lt;code&gt;assert_eq!(16, std::mem::size_of::&amp;lt;&amp;amp;[u8]&amp;gt;());&lt;/code&gt; 來確認這點)，也就是 8 bytes 的指標加上 8 bytes 的長度，我們可以利用這點來儲存 bit offset。我們拿了一個 zero-sized 的 slice 型態，Rust 不必知道 slice 的長度，因為對 ZST 而言永遠會是 0 且 constant，所以長度這欄位變成沒有使用到，我們便能用此來位我們的型態來定義自己想要的長度了。所以神奇的事情發生了 &lt;code&gt;NewByte&lt;/code&gt; 同時是 dynamically-sized 以及 zero-sized！&lt;/p&gt;
&lt;p&gt;DST 與 ZST 個別都會帶來一些有趣的特性，舉例來說有 DST 的性質的話，因為本身是指標這樣一來 &lt;code&gt;NewTypeBuf&lt;/code&gt; 想要 deref 的話就可能變成 &lt;code&gt;NewType&lt;/code&gt;，標準函式庫中的 &lt;code&gt;PathBuf&lt;/code&gt; 與 &lt;code&gt;Path&lt;/code&gt; 就是這種關係。而如果 ZST 的話，由於很多動作最終能夠成為 &lt;code&gt;nop&lt;/code&gt;，這讓我們能更直接地存取到我們想使用的位置。當然這在一般狀況下的確不須用，而且用到這樣子的黑魔法的確需要處理並確保能解決 unsound 的問題，像是使用 &lt;a rel=&quot;external&quot; href=&quot;https://github.com/rust-lang/miri&quot;&gt;miri&lt;/a&gt; 反覆確認。不過當我們要處理的資料屬於非常低階，當占用到一點空間都成為關鍵性的考量時，這的確是非常有趣的使用方法之一。我們可以在像是 &lt;a rel=&quot;external&quot; href=&quot;https://crates.io/crates/bitvec&quot;&gt;&lt;code&gt;bitvec&lt;/code&gt;&lt;/a&gt; 或 &lt;a rel=&quot;external&quot; href=&quot;https://crates.io/crates/dashmap&quot;&gt;&lt;code&gt;dashmap&lt;/code&gt;&lt;/a&gt; 等這類的 crate 看到這樣子類似的實作應用。&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Rust 錯誤處理函式庫推薦：Anyhow + thiserror</title>
        <published>2019-11-22T12:04:23+08:00</published>
        <updated>2019-11-22T12:04:23+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/posts/error-handling-study/"/>
        <id>https://wusyong.github.io/posts/error-handling-study/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/posts/error-handling-study/">&lt;p&gt;在開始講解前我想開門見山講結論，Rust 在針對錯誤處理已經有 &lt;code&gt;Result&amp;lt;T&amp;gt;&lt;/code&gt; 這個非常好用的型態，而且在 &lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html&quot;&gt;TRPL 中也有一章&lt;/a&gt;在專門講解了。如果只是要寫個簡單的測試你可以只定義一個基本的 &lt;code&gt;enum&lt;/code&gt;，而如果是正式的專案也更推薦定義好屬於自己的錯誤型態，依賴第三方的函式庫總是會發生不可預期的狀況出現。但有時候在錯誤處理方面的確會遇到一些障礙是我們得花時間特別去解決的，如果這是一個普遍的問題通常大家便會用些方便的依賴來解決。在過去一兩年我想最常用的就是 &lt;a rel=&quot;external&quot; href=&quot;https://crates.io/crates/failure&quot;&gt;&lt;code&gt;failure&lt;/code&gt;&lt;/a&gt; 了，而過去幾年這類型的 crate 更是如雨後春筍般冒出來，再過不久大概就能像 go 和 npm 有上百萬種錯誤處理的函示庫了(笑)。總之目前更好更方便的選擇就是這次要講的 &lt;code&gt;anyhow&lt;/code&gt; + &lt;code&gt;thierror&lt;/code&gt;。&lt;/p&gt;
&lt;h2 id=&quot;anyhow&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https://crates.io/crates/anyhow&quot;&gt;anyhow&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;anyhow&lt;/code&gt; 首次公開於 2019 年十月，它主要是一個能夠讓我們方便傳遞錯誤的函示庫，就像 &lt;code&gt;failure&lt;/code&gt; 的訴求之一一樣。不同於 &lt;code&gt;failure&lt;/code&gt; 用了自己定義的 trait &lt;code&gt;Fail&lt;/code&gt;，&lt;code&gt;anyhow&lt;/code&gt; 定義的形態和 trait 都是基於標準函式庫的 &lt;code&gt;std::error::Error&lt;/code&gt;，除此之外無其他依賴，所以他也同時號稱是更好的 &lt;code&gt;Box&amp;lt;dyn Error&amp;gt;&lt;/code&gt;。不過也因如此 &lt;code&gt;anyhow&lt;/code&gt; 用到了 &lt;a rel=&quot;external&quot; href=&quot;https://github.com/rust-lang/rfcs/blob/master/text/2504-fix-error.md&quot;&gt;RFC 2504&lt;/a&gt; 的一些改進，所以會需要 Rust 1.34+ 以上&amp;gt;。&lt;/p&gt;
&lt;p&gt;首先最重要的當然就是更方便的錯誤型態 &lt;a rel=&quot;external&quot; href=&quot;https://docs.rs/anyhow/1.0.21/anyhow/struct.Error.html&quot;&gt;&lt;code&gt;Result&amp;lt;T, anyhow::Error&amp;gt;&lt;/code&gt;&lt;/a&gt; 或者也等同於 &lt;a rel=&quot;external&quot; href=&quot;https://docs.rs/anyhow/1.0.21/anyhow/type.Result.html&quot;&gt;&lt;code&gt;anyhow::Result&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/a&gt;，只要在函式內有實作 &lt;code&gt;std::error::Error&lt;/code&gt; trait 的型態，都能夠只使用 &lt;code&gt;?&lt;/code&gt; 來回傳：&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;use&lt;/span&gt;&lt;span&gt; anyhow&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Result&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; get_cluster_info&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Result&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;ClusterMap&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    let&lt;/span&gt;&lt;span&gt; config&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span&gt; std&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;fs&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;read_to_string&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;cluster.json&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    let&lt;/span&gt;&lt;span&gt; map&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; ClusterMap&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span&gt; serde_json&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;from_str&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;config&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;    Ok&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;map&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;再來 &lt;code&gt;anyhow&lt;/code&gt; 也提供了擴展 &lt;code&gt;Result&lt;/code&gt; 增加更多 &lt;a rel=&quot;external&quot; href=&quot;https://docs.rs/anyhow/1.0.23/anyhow/trait.Context.html&quot;&gt;&lt;code&gt;Context&lt;/code&gt;&lt;/a&gt;(上下文) 的功能。要是遇到錯誤時我們只能看到 &quot;No such file or directory&quot; 的話還是很難知道錯在哪。&lt;code&gt;Context&lt;/code&gt; 能提供更高階的錯誤形式來幫助 debug。&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;use&lt;/span&gt;&lt;span&gt; anyhow&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Context&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Result&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Result&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;()&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    it&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;detach&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;context&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;Failed to detach the important thing&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    let&lt;/span&gt;&lt;span&gt; content&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span&gt; std&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span&gt;fs&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;read&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;        .&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;with_context&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt; format!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;Failed to read instrs from &lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt;{}&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;,&lt;/span&gt;&lt;span&gt; path&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;))&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;Error:&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; Failed to read instrs from ./path/to/instrs.json&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;Caused&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; by:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;    No&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; such file or directory&lt;/span&gt;&lt;span&gt; (os&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt; error&lt;/span&gt;&lt;span style=&quot;color: #B48EAD;&quot;&gt; 2&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;anyhow&lt;/code&gt; 也有 Downcasting 能夠用 call by value, shared reference, mutable reference 等方式取得。除此之外還有 &lt;a rel=&quot;external&quot; href=&quot;https://docs.rs/anyhow/1.0.23/anyhow/struct.Chain.html&quot;&gt;&lt;code&gt;Chain&lt;/code&gt;&lt;/a&gt; 能夠方便迭代出結果&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;pub fn&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt; underlying_io_error_kind&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Error&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Option&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;io&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;ErrorKind&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;    for&lt;/span&gt;&lt;span&gt; cause&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; in&lt;/span&gt;&lt;span&gt; error&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;chain&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;        if let&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Some&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;io_error&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt; =&lt;/span&gt;&lt;span&gt; cause&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;downcast_ref&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;io&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Error&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;            return&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Some&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span&gt;io_error&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;kind&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;    None&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;最後我們常見的各式錯誤處理 macro 也都有提供，像是 &lt;a rel=&quot;external&quot; href=&quot;https://docs.rs/anyhow/1.0.23/anyhow/macro.bail.html&quot;&gt;&lt;code&gt;bail!&lt;/code&gt;&lt;/a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https://docs.rs/anyhow/1.0.23/anyhow/macro.ensure.html&quot;&gt;&lt;code&gt;ensure!&lt;/code&gt;&lt;/a&gt; 以及將字串轉換成錯誤的 &lt;a rel=&quot;external&quot; href=&quot;https://docs.rs/anyhow/1.0.21/anyhow/macro.anyhow.html&quot;&gt;&lt;code&gt;anyhow!&lt;/code&gt;&lt;/a&gt;(相當於 &lt;code&gt;format_err!&lt;/code&gt;)：&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Err&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #88C0D0;font-weight: bold;&quot;&gt;anyhow!&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;Missing attribute: &lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt;{}&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;&amp;quot;,&lt;/span&gt;&lt;span&gt; missing&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;));&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;thiserror&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https://docs.rs/thiserror/1.0.6/thiserror/&quot;&gt;thiserror&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;不過這樣只涵蓋到了動態錯誤處理的部份，如果你想要用外部依賴來定義出架構完善的錯誤的話，那麼就是使用 &lt;code&gt;thiserror&lt;/code&gt; 的時候了。它和 &lt;code&gt;anyhow&lt;/code&gt; 都是由 &lt;a rel=&quot;external&quot; href=&quot;https://github.com/dtolnay/&quot;&gt;dtolnay&lt;/a&gt; 在同時間釋出的，某方面來說可以把它們想成是原本 &lt;code&gt;failure&lt;/code&gt; 拆開來後並改善後的版本。&lt;code&gt;thiserror&lt;/code&gt; 最主要的功能就是透過 &lt;code&gt;#[derive(Error)]&lt;/code&gt; 來幫你的型態實作 &lt;code&gt;std::error::Error&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;use&lt;/span&gt;&lt;span&gt; thiserror&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Error&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5E81AC;&quot;&gt;#[derive(&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Error&lt;/span&gt;&lt;span style=&quot;color: #5E81AC;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; Debug&lt;/span&gt;&lt;span style=&quot;color: #5E81AC;&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;pub enum&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; DataStoreError&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5E81AC;&quot;&gt;    #[error(&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;data store disconnected&lt;/span&gt;&lt;span style=&quot;color: #5E81AC;&quot;&gt;&amp;quot;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;    Disconnect&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #5E81AC;&quot;&gt;#[from]&lt;/span&gt;&lt;span&gt; io&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;Error&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5E81AC;&quot;&gt;    #[error(&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;the data for key `&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;` is not available&lt;/span&gt;&lt;span style=&quot;color: #5E81AC;&quot;&gt;&amp;quot;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88C0D0;&quot;&gt;    Redaction&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5E81AC;&quot;&gt;    #[error(&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;invalid header (expected &lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;expected:?&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;, found &lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;found:?&lt;/span&gt;&lt;span style=&quot;color: #EBCB8B;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #5E81AC;&quot;&gt;&amp;quot;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;    InvalidHeader&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        expected&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; String&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        found&lt;/span&gt;&lt;span style=&quot;color: #81A1C1;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt; String&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #5E81AC;&quot;&gt;    #[error(&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #A3BE8C;&quot;&gt;unknown data store error&lt;/span&gt;&lt;span style=&quot;color: #5E81AC;&quot;&gt;&amp;quot;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8FBCBB;&quot;&gt;    Unknown&lt;/span&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ECEFF4;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;std-error-error&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/std/error/trait.Error.html&quot;&gt;std::error::Error&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;最後的最後筆者覺得還是講一下標準函示庫裡最基本的 &lt;code&gt;Error&lt;/code&gt; 比較好，在一開始學習實在完全不清楚的情況下，的確都過第三方依賴能夠輕鬆解決錯誤處理，而這也是大多數社群會推薦的。但隨著經驗累積後不免會發現一些負擔，如果時間充裕當然推薦親自實作在標準函式庫內的錯誤型態。而 &lt;code&gt;Error&lt;/code&gt; trait 隨著這幾年也有一些轉變，以下是值得注意的改變：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Error::description&lt;/code&gt; 已經被半棄用中，因為直接 &lt;code&gt;impl Display&lt;/code&gt; 會更好&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Error::cause&lt;/code&gt; 已被棄用，因為有了 &lt;code&gt;Error::source&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Error::iter_chain&lt;/code&gt; 和 &lt;code&gt;Error::iter_sources&lt;/code&gt; 可在 nightly 上使用了&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Error::backtrace&lt;/code&gt; 以及 &lt;code&gt;module&lt;/code&gt; 模組也能在 nightly 上使用了&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;除了 &lt;code&gt;Error&lt;/code&gt; 外再加上原本的 &lt;code&gt;Result&lt;/code&gt;、&lt;code&gt;?&lt;/code&gt; 到詳盡的錯誤代碼。這是筆者覺得 Rust 在錯誤處理做得十分不錯的地方，雖然對於一個通用的錯誤處理函示庫該有什麼樣的功能，社群仍在摸索當中。但底層的基本架構的確是非常的穩固完善。&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Slides</title>
        <published>2019-08-04T19:55:46+08:00</published>
        <updated>2019-08-04T19:55:46+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/slides/"/>
        <id>https://wusyong.github.io/slides/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/slides/">&lt;ul&gt;
&lt;li&gt;你的不可變引用不是你的不可變引用 @ rust.tw meetup 2020/08&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://www.slideshare.net/YuWeiWu13/smol-talk-on-async&quot;&gt;Smol Talk on async/.await&lt;/a&gt; @ COSCUP 2020 2020/08&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://hackmd.io/@mRP87MlTRvOLHDMXBXHf0Q/ryCMwXvYH#/&quot;&gt;FFI&lt;/a&gt; @ rust.tw meetup 2019/10&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://www.slideshare.net/YuWeiWu13/async-in-rust&quot;&gt;Async&lt;/a&gt; @ rust.tw meetup 2020/02&lt;/li&gt;
&lt;/ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Rust Webinar</title>
        <published>2018-03-15T19:00:00+08:00</published>
        <updated>2018-03-15T19:00:00+08:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://wusyong.github.io/resources/rust/rust/"/>
        <id>https://wusyong.github.io/resources/rust/rust/</id>
        
        <content type="html" xml:base="https://wusyong.github.io/resources/rust/rust/">&lt;h2 id=&quot;the-book-is-all-you-need&quot;&gt;&quot;&lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/book/&quot;&gt;The Book&lt;/a&gt;&quot; is all you need&lt;/h2&gt;
&lt;p&gt;Optional:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://play.rust-lang.org/&quot;&gt;Rust playground&lt;/a&gt;: Write and test your simple code&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/rust-lang/rustlings/&quot;&gt;Rustling&lt;/a&gt;: Super easy exercises&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/stable/rust-by-example/&quot;&gt;Rust by example&lt;/a&gt;: Examples for each subjects&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;getting-started&quot;&gt;Getting Started&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Linux/MacOS:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D8DEE9; background-color: #2E3440;&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;curl https://sh.rustup.rs -sSf | sh&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Windows: https://www.rust-lang.org/tools/install&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;what-you-installed&quot;&gt;What you installed:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;rustc&lt;/strong&gt;: compiler
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;rustc --verision&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;just like &lt;code&gt;gcc&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;rustup&lt;/strong&gt;: toolchain manager
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;rustup update&lt;/code&gt; to update Rust&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;cargo&lt;/strong&gt;: build system &amp;amp; package manager
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;cargo new hello-world&lt;/code&gt; to create a project&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cargo build&lt;/code&gt; to build the project&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cargo run&lt;/code&gt; to run the project binary&lt;/li&gt;
&lt;li&gt;&lt;code&gt;carrgo test&lt;/code&gt; to run test case&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;slides&quot;&gt;Slides&lt;/h2&gt;
&lt;p&gt;Chapters without slides:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ch1. is just installation&lt;/li&gt;
&lt;li&gt;Ch2. is a simple exmaple&lt;/li&gt;
&lt;li&gt;Ch12. is a summary example of previous chapters&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;TODO:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ch19: advanced usage&lt;/li&gt;
&lt;li&gt;Appendex(?)&lt;/li&gt;
&lt;/ul&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Chapter&lt;/th&gt;&lt;th&gt;Slides&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/book/ch03-00-common-programming-concepts.html&quot;&gt;3&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://hackmd.io/@mRP87MlTRvOLHDMXBXHf0Q/HyV_egflr#/&quot;&gt;Common Concepts&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/book/ch04-00-understanding-ownership.html&quot;&gt;4&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://hackmd.io/@mRP87MlTRvOLHDMXBXHf0Q/B1m2SXMlS&quot;&gt;Ownership&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/book/ch05-00-structs.html&quot;&gt;5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://hackmd.io/@mRP87MlTRvOLHDMXBXHf0Q/S1klhE7eS#/&quot;&gt;Structs&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/book/ch06-00-enums.html&quot;&gt;6&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://hackmd.io/@mRP87MlTRvOLHDMXBXHf0Q/HkL92M9xB#/&quot;&gt;Enums&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/book/ch07-00-managing-growing-projects-with-packages-crates-and-modules.html&quot;&gt;7&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://hackmd.io/@mRP87MlTRvOLHDMXBXHf0Q/H1JKjn2lH#/&quot;&gt;Crates &amp;amp; Modules&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/book/ch08-00-common-collections.html&quot;&gt;8&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://hackmd.io/@mRP87MlTRvOLHDMXBXHf0Q/rkAkKtW-B&quot;&gt;Collections - Vector, String, HashMap&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/book/ch09-00-error-handling.html&quot;&gt;9&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://hackmd.io/@mRP87MlTRvOLHDMXBXHf0Q/BJqhOH_-H#/&quot;&gt;Error Handling&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/book/ch10-00-generics.html&quot;&gt;10&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://hackmd.io/@mRP87MlTRvOLHDMXBXHf0Q/rJk-EU_bB#/&quot;&gt;Generic, Traits, Lifetime&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/book/ch11-00-testing.html&quot;&gt;11&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://hackmd.io/@mRP87MlTRvOLHDMXBXHf0Q/rJwOMGPMH#/&quot;&gt;Testing&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/book/ch13-00-functional-features.html&quot;&gt;13&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://hackmd.io/@mRP87MlTRvOLHDMXBXHf0Q/SJ175fhGS#/&quot;&gt;Iterator &amp;amp; Closure&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/book/ch14-00-more-about-cargo.html&quot;&gt;14&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://hackmd.io/@mRP87MlTRvOLHDMXBXHf0Q/S1dbqQnMH#/&quot;&gt;Cargo &amp;amp; Crates.io&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/book/ch15-00-smart-pointers.html&quot;&gt;15&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://hackmd.io/@mRP87MlTRvOLHDMXBXHf0Q/rkaIziuWr#/&quot;&gt;Smart Pointers&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/book/ch16-00-concurrency.html&quot;&gt;16&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://hackmd.io/@mRP87MlTRvOLHDMXBXHf0Q/Hko0zC9mr#/&quot;&gt;Fearles Concurrency&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/book/ch17-00-oop.html&quot;&gt;17&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://hackmd.io/@mRP87MlTRvOLHDMXBXHf0Q/BkyrO-gES#/&quot;&gt;Trait Object&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://doc.rust-lang.org/book/ch18-00-patterns.html&quot;&gt;18&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;external&quot; href=&quot;https://hackmd.io/@mRP87MlTRvOLHDMXBXHf0Q/HkBtzNg4r#/&quot;&gt;Pattern Matching&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
</content>
        
    </entry>
</feed>
