<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2026-09-05T16:10:33+00:00</updated><id>/feed.xml</id><title type="html">Your awesome title</title><subtitle>Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description.</subtitle><entry><title type="html">Welcome to Jekyll!</title><link href="/jekyll/update/2026/09/05/welcome-to-jekyll.html" rel="alternate" type="text/html" title="Welcome to Jekyll!" /><published>2026-09-05T12:52:43+00:00</published><updated>2026-09-05T12:52:43+00:00</updated><id>/jekyll/update/2026/09/05/welcome-to-jekyll</id><content type="html" xml:base="/jekyll/update/2026/09/05/welcome-to-jekyll.html"><![CDATA[<p>You’ll find this post in your <code class="language-plaintext highlighter-rouge">_posts</code> directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run <code class="language-plaintext highlighter-rouge">jekyll serve</code>, which launches a web server and auto-regenerates your site when a file is updated.</p>

<p>Jekyll requires blog post files to be named according to the following format:</p>

<p><code class="language-plaintext highlighter-rouge">YEAR-MONTH-DAY-title.MARKUP</code></p>

<p>Where <code class="language-plaintext highlighter-rouge">YEAR</code> is a four-digit number, <code class="language-plaintext highlighter-rouge">MONTH</code> and <code class="language-plaintext highlighter-rouge">DAY</code> are both two-digit numbers, and <code class="language-plaintext highlighter-rouge">MARKUP</code> is the file extension representing the format used in the file. After that, include the necessary front matter. Take a look at the source for this post to get an idea about how it works.</p>

<p>Jekyll also offers powerful support for code snippets:</p>

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">def</span> <span class="nf">print_hi</span><span class="p">(</span><span class="nb">name</span><span class="p">)</span>
  <span class="nb">puts</span> <span class="s2">"Hi, </span><span class="si">#{</span><span class="nb">name</span><span class="si">}</span><span class="s2">"</span>
<span class="k">end</span>
<span class="n">print_hi</span><span class="p">(</span><span class="s1">'Tom'</span><span class="p">)</span>
<span class="c1">#=&gt; prints 'Hi, Tom' to STDOUT.</span></code></pre></figure>

<p>Check out the <a href="https://jekyllrb.com/docs/home">Jekyll docs</a> for more info on how to get the most out of Jekyll. File all bugs/feature requests at <a href="https://github.com/jekyll/jekyll">Jekyll’s GitHub repo</a>. If you have questions, you can ask them on <a href="https://talk.jekyllrb.com/">Jekyll Talk</a>.</p>]]></content><author><name></name></author><category term="jekyll" /><category term="update" /><summary type="html"><![CDATA[You’ll find this post in your _posts directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run jekyll serve, which launches a web server and auto-regenerates your site when a file is updated.]]></summary></entry><entry><title type="html">Blog</title><link href="/2026/09/05/blog.html" rel="alternate" type="text/html" title="Blog" /><published>2026-09-05T00:00:00+00:00</published><updated>2026-09-05T00:00:00+00:00</updated><id>/2026/09/05/blog</id><content type="html" xml:base="/2026/09/05/blog.html"><![CDATA[<h1 id="blog">Blog</h1>

<p>This blog is based on <a href="https://pages.github.com/">Github page</a> and <a href="https://jekyllrb.com/">jekyll</a>.</p>

<h2 id="installation">Installation</h2>

<p>It requires Ruby, RubyGems, and bundler.</p>

<p>The following command can install the prerequisites</p>

<p><code class="language-plaintext highlighter-rouge">sudo apt install ruby-full build-essential zlib1g-dev</code></p>

<p>Sometimes gem is hard to access in some regions.
It is recommended to change the source link.
As an example,</p>

<p><code class="language-plaintext highlighter-rouge">sudo gem source --add &lt;https://mirror.com&gt; --remove https://rubygems.org/</code></p>

<p>where <code class="language-plaintext highlighter-rouge">&lt;https://mirror.com&gt;</code> is the host of a mirror.
The follow installs jekyll and bundler</p>

<p><code class="language-plaintext highlighter-rouge">sudo gem install jekyll bundler</code></p>

<h2 id="jekyll-themes">Jekyll Themes</h2>

<p>The blog is based on <a href="https://jekyllthemes.io/theme/mediator">mediator</a> theme.
Download the theme and copy it into my own git directory by</p>

<p><code class="language-plaintext highlighter-rouge">git clone https://github.com/dirkfabisch/mediator</code></p>

<h2 id="usage">Usage</h2>

<p>The blog can be used from source with <code class="language-plaintext highlighter-rouge">bundle</code></p>

<p><code class="language-plaintext highlighter-rouge">bundle exec jekyll server</code></p>

<h2 id="upgrade">Upgrade</h2>

<p>Bundler and Jekyll requires the correct version of Ruby.
If Ruby is updated within the system upgrade, bundler and Jekyll both need to reinstall from gem.
For example, when Ubuntu 22.04 is upgraded from Ubuntu 20.04, Ruby 3.0 would be installed, but bundler and Jekyll both requires Ruby 2.7.
So the two programs would not processing correctly anymore.</p>

<p>To fix this problem, the direct approach is to reinstall bundle with gem.</p>

<p><code class="language-plaintext highlighter-rouge">sudo gem install bundler</code></p>

<p>Then, bundle can install all required packages by <code class="language-plaintext highlighter-rouge">bundle install</code> except <em>webrick</em> because webrick is no longer in the standard library of bundle.
However, I have a network issue when run <code class="language-plaintext highlighter-rouge">bundle add webrick</code>.
It shows “Could not reach host index.rubygems.org. Check your network connection and try again.”
The straightforward method is to set a mirror by</p>

<p><code class="language-plaintext highlighter-rouge">bundle config mirror.https://rubygems.org &lt;https://mirror.com&gt;</code></p>

<p>where <code class="language-plaintext highlighter-rouge">&lt;https://mirror.com&gt;</code> is the host of a mirror.
However, it still does not work for me, while the mirror still can be reached by ping, curl, and the browser with ipv4.
So the problem is strange, but I fix it with root command.</p>

<p><code class="language-plaintext highlighter-rouge">sudo bundle config mirror.https://rubygems.org &lt;https://mirror.com&gt;</code>
<code class="language-plaintext highlighter-rouge">sudo bundle install</code>
<code class="language-plaintext highlighter-rouge">sudo bundle add webrick</code></p>

<p>The ipv6 is also cloased because it seems that bundle only supports ipv4, but it is not sure if this process works.</p>

<h1 id="jekyll-syntax">Jekyll Syntax</h1>

<p>This page introduces Markdown syntax used in Jekyll websites. 
These syntax examples are based on common usage in the Just the Docs theme.</p>

<h2 id="1-front-matter-yaml-header">1. Front Matter (YAML Header)</h2>

<p>Front Matter is a YAML-formatted configuration block at the top of Jekyll pages, used to set page properties.</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">---</span>
<span class="na">title</span><span class="pi">:</span> <span class="s">Page Title</span>
<span class="na">layout</span><span class="pi">:</span> <span class="s">Layout Name</span>
<span class="na">nav_order</span><span class="pi">:</span> <span class="s">Navigation Order</span>
<span class="na">description</span><span class="pi">:</span> <span class="s2">"</span><span class="s">Page</span><span class="nv"> </span><span class="s">Description"</span>
<span class="na">permalink</span><span class="pi">:</span> <span class="s">/custom-url-path</span>
<span class="nn">---</span>
</code></pre></div></div>

<p><strong>Parameter Explanation:</strong></p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">title</code>: Page title</li>
  <li><code class="language-plaintext highlighter-rouge">layout</code>: Layout template to use (e.g., home, default, page, etc.)</li>
  <li><code class="language-plaintext highlighter-rouge">nav_order</code>: Display order in navigation menu (lower numbers appear first)</li>
  <li><code class="language-plaintext highlighter-rouge">description</code>: Page description, used for SEO and page summaries</li>
  <li><code class="language-plaintext highlighter-rouge">permalink</code>: Custom URL path, overrides default filename-based path</li>
</ul>

<h2 id="2-headings">2. Headings</h2>

<p>Markdown uses <code class="language-plaintext highlighter-rouge">#</code> symbols to indicate heading levels, from <code class="language-plaintext highlighter-rouge">#</code> (level 1) to <code class="language-plaintext highlighter-rouge">######</code> (level 6).</p>

<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gh"># Level 1 Heading</span>
{: .fs-9 }

<span class="gu">## Level 2 Heading</span>
{: .fs-8 }

<span class="gu">### Level 3 Heading</span>
{: .fs-7 }
</code></pre></div></div>

<p><strong>Note:</strong> The Just the Docs theme supports adding attribute blocks after headings to set CSS classes, such as <code class="language-plaintext highlighter-rouge">{: .fs-9 }</code> for setting font size.</p>

<h2 id="3-attribute-blocks">3. Attribute Blocks</h2>

<p>Attribute blocks are used to add CSS classes or other attributes to the preceding element.</p>

<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code>This is a text paragraph.
{: .fs-6 .fw-300 .text-red }

This is a paragraph.
{: .note }
</code></pre></div></div>

<p><strong>Common CSS Classes:</strong></p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">.fs-9</code>, <code class="language-plaintext highlighter-rouge">.fs-8</code>, <code class="language-plaintext highlighter-rouge">.fs-7</code>, <code class="language-plaintext highlighter-rouge">.fs-6</code>: Font sizes</li>
  <li><code class="language-plaintext highlighter-rouge">.fw-300</code>, <code class="language-plaintext highlighter-rouge">.fw-400</code>, <code class="language-plaintext highlighter-rouge">.fw-700</code>: Font weights</li>
  <li><code class="language-plaintext highlighter-rouge">.text-red</code>, <code class="language-plaintext highlighter-rouge">.text-blue</code>: Text colors</li>
  <li><code class="language-plaintext highlighter-rouge">.note</code>, <code class="language-plaintext highlighter-rouge">.warning</code>: Callout styles</li>
</ul>

<h2 id="4-horizontal-rules">4. Horizontal Rules</h2>

<p>Create horizontal rules using three or more hyphens, asterisks, or underscores.</p>

<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">---

***
</span>
<span class="ge">__</span>_
</code></pre></div></div>

<h2 id="5-blockquotes">5. Blockquotes</h2>

<p>Use <code class="language-plaintext highlighter-rouge">&gt;</code> symbol to create blockquotes.</p>

<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gt">&gt; This is a blockquote.</span>
<span class="gt">&gt; It can span multiple lines.</span>
<span class="gt">&gt;</span>
<span class="gt">&gt; Empty lines separate quote paragraphs.</span>
</code></pre></div></div>

<h2 id="6-links">6. Links</h2>

<h3 id="basic-links">Basic Links</h3>
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="nv">Link Text</span><span class="p">](</span><span class="sx">https://example.com</span><span class="p">)</span>
</code></pre></div></div>

<h3 id="links-with-titles">Links with Titles</h3>
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="nv">Link Text</span><span class="p">](</span><span class="sx">https://example.com</span> <span class="nn">"Link Title"</span><span class="p">)</span>
</code></pre></div></div>

<h3 id="reference-style-links">Reference-style Links</h3>
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code>This is a reference-style <span class="p">[</span><span class="nv">example link</span><span class="p">][</span><span class="ss">1</span><span class="p">]</span>.

<span class="p">[</span><span class="ss">1</span><span class="p">]:</span> <span class="sx">https://example.com</span> <span class="nn">"Example Website"</span>
</code></pre></div></div>

<h2 id="7-emphasis">7. Emphasis</h2>

<h3 id="italic">Italic</h3>
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="ge">*Italic Text*</span>
<span class="ge">_Italic Text_</span>
</code></pre></div></div>

<h3 id="bold">Bold</h3>
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gs">**Bold Text**</span>
<span class="gs">__Bold Text__</span>
</code></pre></div></div>

<h3 id="bold-and-italic">Bold and Italic</h3>
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gs">***Bold and Italic Text**</span><span class="err">*</span>
<span class="gs">___Bold and Italic Text__</span>_
</code></pre></div></div>

<h2 id="8-footnotes">8. Footnotes</h2>

<p>Footnotes are used to add notes at the bottom of the page.</p>

<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code>This is text containing a footnote[^1].

<span class="p">[</span><span class="ss">^1</span><span class="p">]:</span> <span class="sx">This</span> is the footnote content, displayed at the bottom of the page.
</code></pre></div></div>

<h2 id="9-code">9. Code</h2>

<h3 id="inline-code">Inline Code</h3>
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Use <span class="sb">`code`</span> to mark inline code.
</code></pre></div></div>

<h3 id="code-blocks">Code Blocks</h3>
<p>Use three backticks to create code blocks, optionally specifying a language for syntax highlighting.</p>

<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">```</span><span class="nl">python
</span><span class="k">def</span> <span class="nf">hello_world</span><span class="p">():</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"Hello, World!"</span><span class="p">)</span>
<span class="p">```</span>
</code></pre></div></div>

<h2 id="10-lists">10. Lists</h2>

<h3 id="unordered-lists">Unordered Lists</h3>
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">-</span> Item One
<span class="p">-</span> Item Two
<span class="p">  -</span> Subitem One
<span class="p">  -</span> Subitem Two
<span class="p">-</span> Item Three
</code></pre></div></div>

<h3 id="ordered-lists">Ordered Lists</h3>
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">1.</span> First Item
<span class="p">2.</span> Second Item
<span class="p">   1.</span> Subitem One
<span class="p">   2.</span> Subitem Two
<span class="p">3.</span> Third Item
</code></pre></div></div>

<h2 id="11-liquid-template-syntax">11. Liquid Template Syntax</h2>

<p>Jekyll supports the Liquid templating language, which can be used within Markdown.</p>

<div class="language-liquid highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Current Year: 2026

Site Title: Your awesome title

Page URL: /2026/09/05/blog.html
</code></pre></div></div>

<p><strong>Common Liquid Filters:</strong></p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">| date: "%Y"</code>: Format date</li>
  <li><code class="language-plaintext highlighter-rouge">| downcase</code>: Convert to lowercase</li>
  <li><code class="language-plaintext highlighter-rouge">| upcase</code>: Convert to uppercase</li>
  <li><code class="language-plaintext highlighter-rouge">| strip_html</code>: Remove HTML tags</li>
  <li><code class="language-plaintext highlighter-rouge">| markdownify</code>: Convert Markdown to HTML</li>
</ul>

<h2 id="12-callouts">12. Callouts</h2>

<p>The Just the Docs theme provides special callout syntax.</p>

<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code>{: .note }
This is a note callout.

{: .warning }
<span class="gt">&gt; This is a warning callout, often combined with blockquotes.</span>
</code></pre></div></div>

<p><strong>Available Callout Types:</strong></p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">.note</code>: Regular note</li>
  <li><code class="language-plaintext highlighter-rouge">.warning</code>: Warning</li>
  <li><code class="language-plaintext highlighter-rouge">.important</code>: Important note</li>
  <li><code class="language-plaintext highlighter-rouge">.new</code>: New content note</li>
</ul>

<h2 id="13-tables">13. Tables</h2>

<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code>| Header 1 | Header 2 | Header 3 |
|----------|----------|----------|
| Cell 1   | Cell 2   | Cell 3   |
| Cell 4   | Cell 5   | Cell 6   |
</code></pre></div></div>

<h2 id="14-task-lists">14. Task Lists</h2>

<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">-</span> [x] Completed Task
<span class="p">-</span> [ ] Incomplete Task
<span class="p">-</span> [ ] Another Incomplete Task
</code></pre></div></div>

<h2 id="15-definition-lists">15. Definition Lists</h2>

<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Term One
: Definition One

Term Two
: Definition Two
: Second Definition
</code></pre></div></div>

<h2 id="best-practices">Best Practices</h2>

<ol>
  <li><strong>Maintain Consistency</strong>: Use the same Markdown style throughout the website</li>
  <li><strong>Use Front Matter Appropriately</strong>: Set appropriate title, description, and navigation order for each page</li>
  <li><strong>Use Attribute Blocks Reasonably</strong>: Utilize CSS classes provided by the theme to enhance visual effects</li>
  <li><strong>Semantic Markup</strong>: Use correct heading levels (don’t skip levels)</li>
  <li><strong>Accessibility</strong>: Add alt text for images, provide meaningful text for links</li>
</ol>

<h2 id="references">References</h2>

<ul>
  <li><a href="https://daringfireball.net/projects/markdown/">Markdown Official Documentation</a></li>
  <li><a href="https://jekyllrb.com/docs/">Jekyll Documentation</a></li>
  <li><a href="https://just-the-docs.com/">Just the Docs Theme Documentation</a></li>
  <li><a href="https://shopify.github.io/liquid/">Liquid Template Language</a></li>
</ul>]]></content><author><name></name></author><summary type="html"><![CDATA[Blog]]></summary></entry><entry><title type="html">Clash</title><link href="/2026/09/05/clash.html" rel="alternate" type="text/html" title="Clash" /><published>2026-09-05T00:00:00+00:00</published><updated>2026-09-05T00:00:00+00:00</updated><id>/2026/09/05/clash</id><content type="html" xml:base="/2026/09/05/clash.html"><![CDATA[<h1 id="clash">Clash</h1>

<h2 id="introduction">Introduction</h2>

<p>clash is a tunnel in Go.</p>

<h2 id="installation">Installation</h2>

<p>openSUSE contains clash in its repository, so it can be downloaded directly</p>

<p><code class="language-plaintext highlighter-rouge">sudo zypper in clash</code></p>

<p>Debian repository does not contain clash, so it can be downloaded from <a href="https://github.com/Dreamacro/clash/releases">Github release</a>.
It also can be downloaded in command.
As an example</p>

<p><code class="language-plaintext highlighter-rouge">wget https://github.com/Dreamacro/clash/releases/download/v1.18.0/clash-linux-amd64-v1.18.0.gz</code>
<code class="language-plaintext highlighter-rouge">mv clash-linux-amd64-v1.18.0.gz clash</code></p>

<h2 id="basic-usage">Basic Usage</h2>

<p>If clash is run in the user space, copy the <code class="language-plaintext highlighter-rouge">config.yaml</code> file to <code class="language-plaintext highlighter-rouge">~/.config/clash/</code> directory and run</p>

<p><code class="language-plaintext highlighter-rouge">clash</code></p>

<p>Clash will download the <code class="language-plaintext highlighter-rouge">Country.mmdb</code> file by itselef and load the configuration in <code class="language-plaintext highlighter-rouge">~/.config/clash/</code>.</p>

<h2 id="autostart">Autostart</h2>

<p>Clash support auto-start after opening the system.
In openSUSE, the download version of clash has a systemd service with <code class="language-plaintext highlighter-rouge">/lib/system/system/clash.service</code> to support the auto-start process.
This service is based on systemd, so it works for openSUSE and other distributions that uses systemd as the init process.
Different from manually run clash, the systemd will load the configuration in the directory <code class="language-plaintext highlighter-rouge">/etc/clash/</code> by default.
So move the configuration file and mmdb file in the above directory by</p>

<p><code class="language-plaintext highlighter-rouge">sudo mv /path/to/config/file /etc/clash/</code>
<code class="language-plaintext highlighter-rouge">sudo mv /path/to/Country.mmdb /etc/clash</code></p>

<p>Then, enable and start clash service</p>

<p><code class="language-plaintext highlighter-rouge">systemclt enable clash</code>
<code class="language-plaintext highlighter-rouge">systemclt start clash</code></p>

<p>The final process is to config the system-level network setting or program-level network setting to use the clash service.</p>

<h2 id="clash-for-lan">Clash for LAN</h2>

<p>Clash can support connection from devices in the local area network (LAN).
To enable it, just edit the config.yaml file and set the <code class="language-plaintext highlighter-rouge">allow-lan</code> to <code class="language-plaintext highlighter-rouge">true</code>.
Then open clash with manual</p>

<p><code class="language-plaintext highlighter-rouge">clash -d ~/.config/clash/</code></p>]]></content><author><name></name></author><summary type="html"><![CDATA[Clash]]></summary></entry><entry><title type="html">Desktop Environment</title><link href="/2026/09/05/desktop.html" rel="alternate" type="text/html" title="Desktop Environment" /><published>2026-09-05T00:00:00+00:00</published><updated>2026-09-05T00:00:00+00:00</updated><id>/2026/09/05/desktop</id><content type="html" xml:base="/2026/09/05/desktop.html"><![CDATA[<h1 id="desktop-environment">Desktop Environment</h1>

<p>A Linux distribution usually has two types of interfaces.
One of them is virtual console (CLI) and the other is GUI.
Virtual console is the default interface from Linux kernel and does not support Unicode.
For example, in Debian/Ubuntu, type <code class="language-plaintext highlighter-rouge">&lt;ctrl&gt;+&lt;alt&gt;+F@{1-6@</code>} can change between virtual console and GUI.
Specifically, <code class="language-plaintext highlighter-rouge">&lt;ctrl&gt;+&lt;alt&gt;+F2</code> can change to the GUI, and <code class="language-plaintext highlighter-rouge">&lt;ctrl&gt;+&lt;alt&gt;+F@{3,4,5,6@</code>} are different virtual consoles.
Desktop environment is a collection of GUI programs that replaces CLI and is one of the most complicated subsystem in Linux.
It breaks up the limitation of shell and provides a more flexiable interface for users.
By default, the startup program, i.e., systemd, will initialize the GUI desktop.
The desktop also can be opened manually. 
For example, <code class="language-plaintext highlighter-rouge">sudo startx</code> is the command to start an x11 service.
x11 and Wayland are two communication protocol that relates a display server and the client.
Most of the desktop and libraries are based on them.</p>

<p>Graphicless compares the follow open-source desktop environments.</p>

<p>@multitable @columnfractions .2 .2 .2 .2 .2
@headitem              @tab        KDE         @tab       GNOME       @tab         xfce         @tab    LXQT    <br />
@item      Toolkit     @tab         QT         @tab        GTK        @tab         GTK          @tab      QT    <br />
@item  Display manager @tab        SDDM        @tab        gdm        @tab       LightDM        @tab     SDDM   <br />
@item  Session manager @tab      ksmserver     @tab   gnome-session   @tab    xfce4-session     @tab lxqt-session 
@item  Windows manager @tab        KWin        @tab    gnome-shell    @tab        xfwm4         @tab    Openbox <br />
@item  Desktop manager @tab          -         @tab         -         @tab      xfdesktop       @tab       -    <br />
@item   File manager   @tab       Dolphin      @tab     Nautilus      @tab        Thunar        @tab  PcManFm-qt<br />
@item     Launcher     @tab       Kickoff      @tab         -         @tab      xfce-panel      @tab  lxqt-runner 
@item      Editor      @tab        Kate        @tab gnome-text-editor @tab       Mousepad       @tab       -    <br />
@item     Terminal     @tab       Konsole      @tab   gnome-terminal  @tab    xfce4-terminal    @tab   QTerminal<br />
@item      Network     @tab   Network Manager  @tab  Network Manager  @tab          -           @tab       -    <br />
@item     Capturer     @tab      Spectacle     @tab  GNOME Screenshot @tab xfce4-screenshooter  @tab  Screengrab<br />
@item  Document viewer @tab       Okular       @tab       Evince      @tab          -           @tab       -    <br />
@item   Image viewer   @tab      Gwenview      @tab       Loupe       @tab      Ristretto       @tab  Lximage-qt<br />
@item   Input method   @tab          -         @tab         -         @tab          -           @tab       -    <br />
@item Advanced setting @tab          -         @tab    gnome-tweaks   @tab          -           @tab       -    <br />
@item    Development   @tab      KDevelop      @tab   GNOME Builder   @tab          -           @tab       -    <br />
@end multitable</p>

<h2 id="gnome">GNOME</h2>

<h3 id="advanced-setting">Advanced Setting</h3>

<p>gnome-tweaks gives advanced settings for gnome.
It support swap of Caplock and Ctrl.
Download it in Debian with</p>

<p><code class="language-plaintext highlighter-rouge">sudo apt install gnome-tweaks</code></p>

<p>This swap is only useful in gnome-based GUI.
Windows has a similar tool that named as <a href="https://github.com/microsoft/PowerToys">PowerToys</a>.</p>

<h2 id="xfce4">xfce4</h2>

<p>Graphicless tests xfce4 in Debian 12.
It uses xfce4-terminal and firefox as the default applications for terminal and web browser, respectively.</p>

<h2 id="window-manager">Window Manager</h2>

<p>@multitable @columnfractions .2 .2 .2 .2 .2
@headitem @tab Openbox @tab i3 @tab xmonad @tab sway
@item Protocol @tab x11 @tab x11 @tab Wayland @tab Wayland
@end multitable</p>

<h3 id="openbox">Openbox</h3>

<p>Install Openbox with apt</p>

<p><code class="language-plaintext highlighter-rouge">sudo apt install openbox</code></p>

<p>By default, openbox has a refresh issue in Ubuntu.
The applications will not automatic refresh after opening them.
To fix this, change the configuration file</p>

<p><code class="language-plaintext highlighter-rouge">sudo vim /usr/lib/x86_64-linux-gnu/openbox-autostart</code></p>

<p>Uncommand the line 
<code class="language-plaintext highlighter-rouge">test -z $BG || $BG -solid "#303030"</code></p>

<h2 id="tmux">tmux</h2>

<p>Tmux is a famous terminal multiplexer.
It works like a window manager in terminal.
This is only part of the common keys and commands for tmux.
To read the full list, use <code class="language-plaintext highlighter-rouge">man tmux</code> or type <code class="language-plaintext highlighter-rouge">&lt;C-b&gt; + ?</code>.
The keybindings are in the “DEFAULT KEY BINDINGS” section.</p>

<p><code class="language-plaintext highlighter-rouge">&lt;C-b&gt;</code> is the default prefix key of tmux.
The follow shortcuts omit the prefix key.</p>

<h3 id="normal-mode">Normal mode</h3>

<p>@example
    # Session
    d       # Detach the window from the session
    s       # Select a new session
    (/)     # Move to the previous/next session</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>tmux ls/list                            # List sessions
tmux attach/detach                      # Attach/Detach the window to the session
tmux kill-session -t &lt;session-name&gt;     # Close (Kill) the session

# Window
c       # Create new window
l       # Toggle last active window
n/p     # Next/Previous window
w       # List windows

tmux new -s &lt;session-name&gt;              # Create a new window for the session

# Pane
o             # Go to next pane
q &lt;num&gt;       # Switch to the pane
x             # Close the pane
z             # Toggle pane zoom
@{ or @}      # Move the pane to left/right
% or "        # Split pane with vertical/horizontal
&lt;Up&gt;/&lt;Down&gt;/&lt;Left&gt;/&lt;right&gt;          # Go to the up/down/left/right pane
</code></pre></div></div>

<p>@end example</p>

<h3 id="copy-mode">Copy mode</h3>

<p>In copy mode, user can view the contents in tmux pane.
The user also can use vim-like commands to view and copy the content.
@example
    [       # Enter copy mode.
@end example</p>

<h3 id="command-line-mode">Command line mode</h3>

<p>The follow key does not need prefix key.</p>

<p>@example
    :       # Enter command-line mode
@end example</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Desktop Environment]]></summary></entry><entry><title type="html">Distribution</title><link href="/2026/09/05/distribution.html" rel="alternate" type="text/html" title="Distribution" /><published>2026-09-05T00:00:00+00:00</published><updated>2026-09-05T00:00:00+00:00</updated><id>/2026/09/05/distribution</id><content type="html" xml:base="/2026/09/05/distribution.html"><![CDATA[<h1 id="distribution">Distribution</h1>

<p>Linux contains lots of well-known distributions.
A Linux distribtuion comprises multiple drivers to support different hardware architectures and a collections of softwares in the user sapce.
The follow tables summarize the main different between these awesome distributions and the programs.</p>

<p>@multitable @columnfractions .18 .16 .16 .16 .16 .16
@headitem             @tab    Arch   @tab      Debian      @tab   Fedora  @tab   NixOS   @tab    Void <br />
@item   Init system   @tab  systemd  @tab      systemd     @tab  systemd  @tab  systemd  @tab   runit <br />
@item Package manager @tab   pacman  @tab        apt       @tab    dnf    @tab    Nix    @tab    xbps <br />
@item    C library    @tab   glibc   @tab       glibc      @tab   glibc   @tab   glibc   @tab    musl <br />
@item     Utility     @tab coreutils @tab     coreutils    @tab coreutils @tab coreutils @tab coreutils 
@item    Installer    @tab    CLI    @tab Debian-Installer @tab  Anaconda @tab Calamares @tab    CLI  <br />
@end multitable</p>

<p>The distributions for embeded devices</p>

<p>@multitable @columnfractions .2 .2 .2 .2 .2
@headitem             @tab Openwrt @tab  Alpine   <br />
@item   Init system   @tab   init  @tab  OpenRC
@item Package manager @tab   opkg  @tab   apk     <br />
@item     Utility     @tab Busybox @tab Busybox   <br />
@end multitable</p>

<h2 id="package-manager">Package Manager</h2>

<p>The follow lists common package managers that in different distributions.
@itemize @bullet
@item apt
@item dnf
@item pacman
@item zypper
@item Flatpak
@item AppImage
@end itemize</p>

<h3 id="dnf">dnf</h3>

<p>dnf or Dandified YUM is the next-generation of the Fedora package manger yum.
It manages rpm packages.</p>

<p><a href="https://copr.fedorainfracloud.org">COPR</a> is an extra repository for Fedora.
NeuroFedora team move the softwares to official Fedora repositories.
Add this repo into the dnf repo list by running
<code class="language-plaintext highlighter-rouge">sudo dnf copr enable @@neurofedora/neurofedora-extra</code></p>

<p>The source files of an rpm package are in the *.src.rpm.</p>

<p>@example</p>
<h1 id="download-the-srcrpm">Download the src.rpm</h1>
<p>dnf download –source <package name=""></package></p>
<h1 id="list-the-infomation-in-the-srcrpm">List the infomation in the *src.rpm</h1>
<p>rpm -ql *.src.rpm</p>
<h1 id="extract-the-srcrpm">Extract the *src.rpm</h1>
<p>rpm2cpio *.src.rpm | cpio -idv</p>
<h1 id="install-source-code-from-srcrpm-to-home-directory">Install source code from *src.rpm to home directory</h1>
<p>rpm -i *src.rpm</p>
<h1 id="rebuild-the-source-package-if-it-is-patched">Rebuild the source package if it is patched</h1>
<p>rpmbuild -bb /spec/directory/package.spec
@end example</p>

<p>The default directory for the rpm macros is under<code class="language-plaintext highlighter-rouge">/usr/lib/rpm/macros</code>.</p>

<h3 id="zypper">zypper</h3>

<p>openSUSE uses <code class="language-plaintext highlighter-rouge">zypper</code> as the default package manager.
It is based on RPM, which is similar to Fedora.
zypper uses repository for packages.
<code class="language-plaintext highlighter-rouge">zypper repos</code> lists repositories.
Search all installed packages in a target repo, use <code class="language-plaintext highlighter-rouge">zypper search -i -r &lt;repo&gt;</code>.</p>

<p>Besides installation of the built programs, zypper also provides an official repository for the source code.
As an example, the download and build process for the <code class="language-plaintext highlighter-rouge">hostapd</code> is</p>

<p>@example
sudo zypper source-install hostapd  # or <code class="language-plaintext highlighter-rouge">sudo zypper si hostapd</code>
cd /usr/src/packages/       # cd to the default directory for source code
ls SOURCES
ls SPECS
sudo zypper in rpmbuild     # The build tool of the download source code
sudo rpmbuild -ba SPECS/hostapd.spec  # -ba means to perform a full build.
ls RPMS/x86_64              # The built program in the x86 architecture
sudo rpmbuild -ba –noclean SPECS/hostapd.spec    # It does not remove the extracted source code
ls BUILD                    # The extracted source code
@end example</p>

<p>openSUSE also provides a command-line tool for package download, building and packaging.
The name of the tool is osc, which means openSUSE commander.
To use it, run</p>

<p><code class="language-plaintext highlighter-rouge">sudo zypper install osc</code></p>

<h3 id="flatpak">Flatpak</h3>

<p>Flatpak is a cross-platform package manager that run applications in a sandbox.
It can download apps from FlatHub, which is the official repository of Flatpak.</p>

<p><code class="language-plaintext highlighter-rouge">flatpak install &lt;package name/ID&gt;</code></p>

<p>Different from apt/zypper/dnf/pacman, you cannot run the applications from flatpak directly.</p>

<p><code class="language-plaintext highlighter-rouge">flatpak run &lt;package name/ID&gt;</code></p>

<h2 id="init-process">Init Process</h2>

<p>In Linux, the first process is usually <em>init</em> or <em>systemd</em>.
They both work to manage the initialization of the system before the login shell.
The PID of them is 1, which means the first process after the kernel.</p>

<h3 id="system-v-and-init">System V and init</h3>

<p>init is the initial script in System V project.
In a early version of a Linux distribution, it usually uses init as the initalization system.
It finds the configuration file in <code class="language-plaintext highlighter-rouge">/etc/inittab</code> and runs the scripts in <code class="language-plaintext highlighter-rouge">/etc/rc</code> according to the runlevel.
Different runlevels means different modes of init.
It will run the corresponding runlevel scripts in <code class="language-plaintext highlighter-rouge">/etc/rcN.d/</code>, where N means the runlevel.
The value of N is from 0 to 6.
All scripts under these directories are a symbolic link to a file in <code class="language-plaintext highlighter-rouge">etc/init.d/</code>.
The file started with “S” means “start it”, while “K” means “kill it”.
The feature of init is run all script in a fixed order one-by-one, so it is easy to find the error, while costs lots of time.</p>

<h3 id="systemd">systemd</h3>

<p>In contrast, systemd concurrently runs all scripts.</p>

<p>In a system that initialized with systemd, the init file, which is <code class="language-plaintext highlighter-rouge">/usr/sbin/init</code> will be a symbolic to the <code class="language-plaintext highlighter-rouge">/lib/systemd/systemd</code>.
The default configuration file of systemd is <code class="language-plaintext highlighter-rouge">/usr/lib/systemd/system/default.target</code>, which is also a symbolic link to <code class="language-plaintext highlighter-rouge">/usr/lib/systemd/system/graphical.target</code>.
You can find the default target with</p>

<p><code class="language-plaintext highlighter-rouge">systemctl get-default</code></p>

<h2 id="live-cd">Live CD</h2>

<p>This section discribes how to create a custom Live CD in Fedora with <code class="language-plaintext highlighter-rouge">livemedia-creator</code>.</p>

<p>@example</p>
<h1 id="install-mock-which-provides-an-independent-compose-environment">Install mock, which provides an independent compose environment.</h1>
<p>sudo dnf install mock</p>
<h1 id="init-mock">Init mock</h1>
<p>mock -r <live_cd_name> --init</live_cd_name></p>
<h1 id="install-packages-into-the-composed-environment">Install packages into the composed environment</h1>
<p>mock -r <live_cd_name> --install lorax-lmc-novirt vim-minimal pykickstart livecd-tools</live_cd_name></p>
<h1 id="chroot-into-the-environment">chroot into the environment</h1>
<p>mock -r &lt;live_cd_name –shell –enable-network –isolation=simple
@end example</p>

<p>After that, the user has been changed into the compose environment, and the packages for composion have been installed.
The next step is get the configuration files for the target ISO.
These files are named as kickstart files, and <code class="language-plaintext highlighter-rouge">.ks</code> is the file extension.
The kickstart files are in the <a href="https://pagure.io/fedora-kickstarts.git">fedora kickstarts project</a>.
Download the files and move it into the mock environment.</p>

<p>The home directory of <live_cd_name> is under the `/var/lib/mock/<live_cd_name>/root/builddir`.
The project can be directly copied into the builddir of the compose environment.
Another method is to copy the project with the command</live_cd_name></live_cd_name></p>

<p><code class="language-plaintext highlighter-rouge">mock -r &lt;live_cd_name&gt; --copyin &lt;project name&gt; /builddir</code></p>

<p>The kickstart files in the project are templates, it should be resolved by flattening in the compose environment.</p>

<p><code class="language-plaintext highlighter-rouge">ksflatten --config &lt;template.ks&gt; -o flat-&lt;template.ks&gt;</code></p>

<p>In X64 system, compose the Fedora 42 system lacks <code class="language-plaintext highlighter-rouge">shim-ia32</code> package.
It should be installed manually.
To do that, add the package name, i.e. <code class="language-plaintext highlighter-rouge">shim-ia32</code> after the <code class="language-plaintext highlighter-rouge">%packages</code> in the flatten kickstart file.</p>

<p>Finally, run the livemedia-creator</p>

<p><code class="language-plaintext highlighter-rouge">livemedia-creator --ks flat-&lt;template&gt;.ks --no-virt --resultdir /var/lmc --project &lt;project_name&gt; --make-iso --volid &lt;volume ID&gt; --iso-only --iso-name &lt;live_cd&gt;.iso --releasever &lt;version&gt; --macboot</code></p>

<p>The target ISO is under the <code class="language-plaintext highlighter-rouge">var/lmc</code>.</p>

<p>The official page is <a href="https://fedoraproject.org/wiki/Livemedia-creator-_How_to_create_and_use_a_Live_CD">How to create and use a Live CD</a>.</p>

<h2 id="linux-to-go">Linux To Go</h2>

<p>Linux To Go (LTG) is a method to install Linux in external USB disk.
The main advantage of LTG is to boot your owe system in multiple computers that have same architecture (for example, x86 system).</p>

<p>The LTG is based on Fedora since it has stable version, so it does not need to be updated frequently.
The boot method is UEFI, so allocate a partition with 1 GiB to support UEFI.
In addition, install the bootloader to the USB disk.
After that, the installation process is the same as a normal installation in any disk.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Distribution]]></summary></entry><entry><title type="html">Editor</title><link href="/2026/09/05/editor.html" rel="alternate" type="text/html" title="Editor" /><published>2026-09-05T00:00:00+00:00</published><updated>2026-09-05T00:00:00+00:00</updated><id>/2026/09/05/editor</id><content type="html" xml:base="/2026/09/05/editor.html"><![CDATA[<h1 id="editor">Editor</h1>

<h2 id="vim">Vim</h2>

<p>Vim has six modes: normal, insert, operator-pending, visual, select, and command-line modes.
All the keys in the keyboard have been used as a command in these mode.</p>

<h3 id="normalvisual-mode">Normal/Visual Mode</h3>

<p>Most keymappings both can work in normal and visual mode with slightly difference.</p>

<p>@subsubsection Movement</p>

<p>@example
h/j/k/l     Character-level movement: left/down/up/right
F/f<char>   Character-level movement: Find the <char> on left/right
T/t<char>   Character-level movement: Till (Find) before/after <char> on left/right
;           Repeat: F/f/T/t
,           Repeat: F/f/T/t in opposite direction
w/W         Word-level movement: forward to the begin of the word/WORD 
e/E         Word-level movement: forward to the end of the word/WORD 
b/B         Word-level movement: backward to the begin of the word/WORD 
0/$         Line-level movement: Begin/End of the line
^           Line-level movement: The first non-blank character of the line</char></char></char></char></p>
<count>|    Line-level movement: The <count> column in this line
+/-         Line-level movement: Downward/Upward
<count>_    Line-level movement: Downward <count>-1 lines, on the first non-blank character
H/M/L       Window-level movement: Top/Middle/Bottom of the window
G           Document-level movement: End of the document
'           Document-level movement: Jump to the line of the mark
`           Document-level movement: Jump to the mark
K           Run an external predefined program with word (i.e., !<Program> <word>)
@end example

@subsubsection Mark

@example
m<A-Z>              Set global marks
m<a-z>              Set local marks
'<A-Za-z0-9>        Document-level movement: Jump to the mark
`<A-Za-z0-9>        Document-level movement: Jump to the mark
:mark <A-Za-z>      Set global/local marks
:marks              List all marks
:delmarks <A-Za-z>  Delete mark
:delmarks!          Delete all marks
@end example

@subsubsection Edit and Register

Replace, delete, and yank commands in normal mode save the characters in to registers.

@example
r/R         Character-level edit: Replace/Enter replace mode
X/x         Character-level edit: Delete at previous/current cursor
s           Character-level edit: Delete and enter the insert mode
~           Character-level edit: Swap case
D           Line-level edit: Delete (cut) from the cursor to the end
S           Line-level edit: Delete (cut) the line and enter the insert mode
C           Line-level edit: Delete from the cursor to the end and enter the insert mode
Y           Line-level edit: Yank the line
J           Line-level edit: Join the forward line to the current one
P/p         Document-level edit: Put (Paste) the text before/after the cursor
u/U         Document-level edit: Undo the last change / Undo all changes in the line
.           Repeat: The last edit command
"<reg>      Use <reg> for d/y/p
&lt;C-a/x&gt;     Character-level edit: The first number after the cursor plus/minus 1
@end example

Recording-related command

@example
q<reg>      Recording: Record operations into <reg> until "q" is typed in normal mode
@@<reg>      Recording: Run the operations in <reg>
@@@@          Repeat: The last @@<reg>
@end example

In normal mode, "d/c/y/&lt;/&gt;" are operators.
If an operator is typed, it will wait for a motion, like "h/j/k/l/w/W/e/E/b/B".
Type an operator twice indicates line-level edit.

@example
d/y         Delete (Cut) / Yank (Copy)
C           Delete (Cut/Change) to the end of the line and enter the insert mode
&lt;           Shift left
&gt;           Shift right
dd/yy       Line-level edit: Delete (Cut) / Yank
cc          Line-level edit: Delete and enter the insert mode
&lt;&lt;          Line-level edit: Shift left
&gt;&gt;          Line-level edit: Shift right
@end example

Register-related Command-line mode command 

@example
:reg            Show the registers
:messages       Show messages and errors
@end example

@subsubsection Text Object

@example
[a/i][w/W]          # a/inner word/WORD. Select a word/WORD with/without the space behind
[a/i][s/p/t]        # a/inner setence/paragraph/tag block
a[/@{/(/&lt;/"/'/`      # a [\@{\( block with [\@{\(
i[/@{/(/&lt;/"/'/`      # inner [\@{\( block without [\@{\(
@end example

@subsubsection Keymapings start with 'Z' and 'z'

This is not full list. Use `help z` in vim to find all the keymappings.

Quit vim
@example
ZQ          Close and quit vim without saving
ZZ          Save and close the current window
@end example

Folding

@example
za/A                Toggle a fold/folds recursively
zc/C                Close a fold/folds recursively
zd/D                Delete a fold/ folds recursively
zf<motion>/F        Create folds
zj                  Move to the start of the next fold
zo/O                Open a fold/folds recursively
@end example

Redraw the window

@example
zb/t/z      Redraw the cursor to the bottom/top/middle of the window

z.          Give spell suggestion 
@end example

@subsubsection Keymappings start with 'g'

Part of the commands have been listed.

@example
gd/gD       Document-level movement: Go to local/global decleration
ge/gE       Word-level movement: Backward to the end of the word/WORD
gg/G        Document-level movement: The first/last line
<count>g_   Line-level movement: Downward <count>-1 lines, on the last non-blank character
@end example

@subsubsection Window 

@example
<C-w>s/v        Horizontal/Vertical split
<C-w>w          Switch
<C-w>h/j/k/l    Move left/down/up/right
<C-w>q          Quit
@end example

@subsubsection Filter

Filter can lint to other formatters.

@example
!/=             Filter text through an external program 
@end example

### Insert Mode

@example
A/a             Enter insert mode and append at the end of the line/cursor
I/i             Enter insert mode and insert at the beginning of the line/cursor
O/o             Enter insert mode and insert a new line above/below the current line
@end example

Most commands in insert mode uses CTRL at first.

### Command-Line Mode

Command-line mode can be entered from normal mode by typing ':', '/', '?', '!'.
The above commands are related to command-line mode, while part of them works in normal mode.

@example
:<command />      Run <command /> (Enter command-line mode)
Q               Enter Ex mode
@end example

@subsubsection Search

@example
%               Line-level search: Forward to the `@{[(` and jump to its match
/<pattern>      Document-level search: Forward for <pattern>
?<pattern>      Document-level search: Backward for <pattern>
n/N             Repeat: '/' or '?' in the same/opposite direction
*/#             Document-level search: Forward/Backward for the next word under the cursor
@end example

@subsubsection Substitute
The substitute command is 
@example
:[range]s[ubstitute]/<pattern>/<string>/[flags] [count]
@end example

It has one repeat single-character command in normal mode.
@example
&amp;               Repeat: The last substitute
@end example

@subsubsection vimgrep

vimgrep is the built-in search command in vim.
The results can be listed in quickfix window.

@example
:vimgrep /<PATTERN>/<FLAGS> <FILES>
:vimgrep /foo/g <DIR>/**        Search all foo patterns recursively in <DIR>
:cnext                          Search the next position
:cprevious                      Search the previous position
:clist                          List all matched patterns
:cwindow                        Open the quickfix window
@end example

### Test Vim Script

Vim is an awesome editor with powerful plugin ecosystems.
Most of the time, the plugin can be directly used by downloading them into the directory.
The plugin manager, which is also a plugin, can add the other plugins in to the runtime directory of vim.

This subsection is not about how to install and use plugins, but is related to how to write a plugin.
The goal of this post is to give a brief introduction on test Vim plugins like test a command line.
Specifically, test is the basic function if someone wants to write their custom plugin.
Test the source code of a well-known plugin is also a good way to learn the idea of other developers' plugins.

The plugin language of writing plugins is Vimscript.
There are at least two vim processes, one for edit, and the other for running test.
Although vim is an editor, it provides a non-interactive mode to run Vim scripts without open the window.
Redirect the output of vim to other command with pipeline in shell like this

`vim -u NONE --not-a-term -c "echoconsole \"hello world \"  | q" &gt;&gt; vim2stdout.txt`

where `-u`, `-c`, `--not-a-term` are vim options.
The detail can be found in `vim --help`.
`echoconsole` is a vim command can be used to output a message, which is "hello world" in this case, to the terminal.
The output is redirect to a file vim2stdout.txt and the string "hello world" can be found in the file, with some other strings.

In addition, a recommand method for unit test is to write a script with a test case, and redirect the output to the awk tool, such as

    vim -u -NOME --not-a-term -S <run_test_file> <test_case> | awk <pattern>

Note that there must be `echoconsole` and `quit` in the <run_test_file>.

Debug the unit test of vim plugin can be implemented by the `clientserver` feature of Vim.
There is a good plugin [breakpts](https://github.com/vim-scripts/BreakPts).

### Vim Distribution

Vim is one of the most famous editors in the world with powerful scalability.
However, Vim is extremely unfriendly for newbies, especially for those who uses graphical user interfaces (GUI).
NeoVim is a new version of Vim.
It is community-driven and deprecates lots of old-fashions in Vim.

Due to the extensibility of Vim and Neovim, lots of developers contribute thousands of plugins for them.
So many plugins give both Vim and Neovim unlimited possibilities, but they also dazzle newbies who want to try these famous editors and don't know how to select a suitable configuration that meet their requirements.

To solve this problem, recently, multiple developers and open source projects provide community-driven out-of-box configurations for Vim.
The relationship between these projects and Vim (or Neovim) is like the relationship between a Linux distribution and the kernel.
Therefore, I call these projects as "Vim distributions", which means they use Vim (or Neovim) as the "editor kernel".
The development of Vim distribution is more easier then before, thanks to the language server protocol (LSP).
The follows are some Vim distributions.

@subsubsection SpaceVim

[SpaceVim](https://spacevim.org) is inspired by spacemacs.
It is community-driven and provides layers to encapsulated the low-level configuration of Vim/Neovim.
Each layer in SpaceVim indicates a collection of plugins that provides a similar function.
Users can choose different plugins for the layer.
However, although SpaceVim change the <leader> to <Space>, it lacks a local easy-to-use document about all the keybindings (like vim).
SpaceVim provides a new configuration interface that uses `.toml` in the directory `~/.Spacevim.d/`.
SpaceVim is only distribution that can support both Vim and NeoVim.

@subsubsection LunarVim

[LunarVim](https://www.lunarvim.org/), or lvim in short, is another distribution that only supports Neovim.
It needs npm, node, and cargo as the prerequisites.
LunarVim is also community-driven and provides good support for multiple languages.
It provides a shortcut named as lvim in `.local/bin/`.

@subsubsection NvChad

[NvChad](https://nvchad.com/) is a pure lua distribution with a customized colorscheme.
The aim of NvChad is to be a "basic configuration", so the configuration logic of NvChad is pretty simple.
It is quitely easy to extend.

@subsubsection Doom-nvim

[Doom-nvim](https://github.com/doom-neovim/doom-nvim) is also inspired by an emacs-based project.
It also proposes modules that includes plugins and keybindings.
The prerequisites includes npm and tree-sitter, which are both based on javascript.
If the Linux does not contains the prerequisites, the installation would have some problem.

## Micro Editor

Micro is a easily used terminal editor with intuitive key bindings as well as modern build-in features, including command line, auto-pair and linter.

Install it in Debian (Test on Debian 12)

`sudo apt install micro`

A universal installation method for most Linux distributions

`mkdir ~/bin`
`cd ~/bin`
`curl https://getmic.ro | bash`

The configuration files are in `~/.config/micro/*`

The recommended plugins are follows
@itemize @bullet
@item linter (default installation)
@item filemanager
@item wc
@item quickfix
@end itemize

The linter requires out-of-box support for each language (see, `help linter` in the command line mode).
Enter the command line mode by typing `<C-e>`, run

	`plugin install filemanager wc quickfix`

### Configuration

Micro uses `json` as the configuration file.
The follows are the default keymappings for it.

@example
@{
  // The keymappings both can be used in normal pane and command pane.
    "Ctrl-a":          "SelectAll",
    "Ctrl-b":          "ShellMode",
    "Ctrl-c":          "CopyLine|Copy",
    "Ctrl-d":          "DuplicateLine",
    "Ctrl-e":          "CommandMode",
    "Ctrl-f":          "Find",
    "Ctrl-g":          "ToggleHelp",
    "Ctrl-h":          "Backspace",
    "Ctrl-j":          "PlayMacro",
    "Ctrl-k":          "CutLine",
    "Ctrl-l":          "command-edit:goto ",
    "Ctrl-n":          "FindNext",
    "Ctrl-o":          "OpenFile",
    "Ctrl-p":          "FindPrevious",
    "Ctrl-q":          "Quit",
    "Ctrl-r":          "ToggleRuler",
    "Ctrl-s":          "Save",
    "Ctrl-t":          "AddTab",
    "Ctrl-u":          "ToggleMacro",
    "Ctrl-v":          "Paste",
    "Ctrl-w":          "NextSplit",
    "Ctrl-x":          "Cut",
    "Ctrl-y":          "Redo",
    "Ctrl-z":          "Undo",

    "Alt-F":          "FindLiteral",
    "Alt-a":          "StartOfLine",
    "Alt-b":          "WordLeft",
    "Alt-c":          "RemoveAllMultiCursors",
    "Alt-e":          "EndOfLine",
    "Alt-f":          "WordRight",
    "Alt-g":          "ToggleKeyMenu",
    "Alt-m":          "SpawnMultiCursorSelect",
    "Alt-n":          "SpawnMultiCursor",
    "Alt-p":          "RemoveMultiCursor",
    "Alt-x":          "SkipMultiCursor",
    "Alt-@{":          "ParagraphPrevious",
    "Alt-@}":          "ParagraphNext",
    "Alt-,":          "PreviousTab",
    "Alt-.":          "NextTab",

    "CtrlUp":         "CursorStart",
    "CtrlDown":       "CursorEnd",

    "AltUp":          "MoveLinesUp",
    "AltDown":        "MoveLinesDown",

    "Alt-CtrlH":      "DeleteWordLeft",

    "CtrlShiftUp":    "SelectToStart",
    "CtrlShiftDown":  "SelectToEnd",
    "CtrlShiftRight": "SelectWordRight",
    "CtrlShiftLeft":  "SelectWordLeft",

    "AltShiftUp":     "SpawnMultiCursorUp",
    "AltShiftDown":   "SpawnMultiCursorDown",
    "AltShiftLeft":   "SelectToStartOfTextToggle",
    "AltShiftRight":  "SelectToEndOfLine",

    // Keymapping for terminal mode
   "terminal": @{
          "<Ctrl-q><Ctrl-q>": "Exit",
          "<Ctrl-e><Ctrl-e>": "CommandMode",
          "<Ctrl-w><Ctrl-w>": "NextSplit"
      @},
@}
@end example
</Ctrl-w></Ctrl-w></Ctrl-e></Ctrl-e></Ctrl-q></Ctrl-q></C-e></Space></leader></run_test_file></pattern></test_case></run_test_file></DIR></DIR></FILES></FLAGS></PATTERN></string></pattern></pattern></pattern></pattern></pattern></C-w></C-w></C-w></C-w></count></count></motion></reg></reg></reg></reg></reg></reg></reg></A-Za-z></A-Za-z></A-Za-z0-9></A-Za-z0-9></a-z></A-Z></word></Program></count></count></count></count>]]></content><author><name></name></author><summary type="html"><![CDATA[Editor]]></summary></entry><entry><title type="html">Input Method</title><link href="/2026/09/05/input-method.html" rel="alternate" type="text/html" title="Input Method" /><published>2026-09-05T00:00:00+00:00</published><updated>2026-09-05T00:00:00+00:00</updated><id>/2026/09/05/input-method</id><content type="html" xml:base="/2026/09/05/input-method.html"><![CDATA[<h1 id="input-method">Input Method</h1>

<p>This chapter is related to the chinese input method.
In openSUSE, the fcitx5 framework can be installed from the repository with command</p>

<p><code class="language-plaintext highlighter-rouge">sudo zypper in fcitx5</code></p>

<p>This command will install a GUI configuration tool <code class="language-plaintext highlighter-rouge">fcitx5-configtool</code>.
The chinese input method can be chosen from it.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Input Method]]></summary></entry><entry><title type="html">Kernel</title><link href="/2026/09/05/kernel.html" rel="alternate" type="text/html" title="Kernel" /><published>2026-09-05T00:00:00+00:00</published><updated>2026-09-05T00:00:00+00:00</updated><id>/2026/09/05/kernel</id><content type="html" xml:base="/2026/09/05/kernel.html"><![CDATA[<h1 id="kernel">Kernel</h1>

<h2 id="building-the-kernel">Building the Kernel</h2>

<p>This is a brief introduction about build a customized linux kernel.
The compiling process has been successfully run on the distribution of Ubuntu 20.04 (Focal Fossa), and the release of the kernel is “linux-5.8.7”.</p>

<p>The Linux kernel can be download from the <a href="https://www.kernel.org/">website</a>.
The downloaded files are under the “linux-5.8.7” directory.</p>

<h3 id="prerequisites">Prerequisites</h3>

<p>There are some packets that are necessary to compile the kernel. 
It is hard to obtain all the packets manually.
Fortunately, we can get the information from both the <a href="https://www.kernel.org/doc/html/latest/kbuild/kbuild.html">Linux kernel documentations</a> and the Ubuntu <a href="https://wiki.ubuntu.com/Kernel/BuildYourOwnKernel">BuildYourOwnKernel Wiki</a>.
Run the following command</p>

<p>@example
sudo apt-get build-dep linux linux-image-$(uname -r)</p>

<p>sudo apt-get install libncurses-dev flex bison openssl libssl-dev <br />
dkms libelf-dev libudev-dev libpci-dev libiberty-dev autoconf
@end example</p>

<p>It is worth to note that directly following <a href="https://wiki.ubuntu.com/Kernel/BuildYourOwnKernel">BuildYourOwnKernel Wiki</a> has some problems.
When run the command</p>

<p>@example
sudo apt-get build-dep linux linux-image-$(uname -r)
sudo apt-get build-dep linux linux-image-$(uname -r)
@end example</p>

<p>it reports an error as follows</p>

<p>@example
E: You must put some ‘deb-src’ URIs in your sources.list
@end example</p>

<p>Please add the contents</p>

<p>@example
deb-src http://cn.archive.ubuntu.com/ubuntu/ focal-updates main restricted
deb-src http://cn.archive.ubuntu.com/ubuntu/ focal-updates main restricted
@end example</p>

<p>Then uncomment all commands with “deb-src” in the <code class="language-plaintext highlighter-rouge">/etc/apt/sources.list</code> file, and run <code class="language-plaintext highlighter-rouge">sudo apt update</code>. 
The error is fixed.</p>

<h3 id="build-and-install-the-linux-kernel">Build and install the linux kernel</h3>

<p>After installing the prerequisites, the building process is simple enough.
The linux kernel has built-in Makefiles.
In specific, the first process is to config some modules of the kernel. 
Since Linux kernel supports hundreds of modules, it is hard to config them one-by-one.
In stead,  run <code class="language-plaintext highlighter-rouge">make oldconfig</code> to config our the kernel.
This command tell the compiler that use the configuration for the new kernel the same as the configuration for the current kernel.
All the new features of the new kernel will be set as the default value, so type “enter” for all these options is enough.</p>

<p>Note: 
The new kernel has been successfully compiled by following these steps. 
The installed kernel has shown in the grub. However, the OS cannot load by the grub. 
It blocked and shows “loading initial ramdisk”. 
The OS cannot load with the newest kernel, while it can load with an older version. 
This problem may be caused by a kernel bug for Intel devices.
The details can be found in <a href="https://askubuntu.com/questions/1374282/stuck-on-loading-initial-ramdisk-after-kernel-upgrade">this page</a>.
Otherwise, building the kernel in the <a href="https://wiki.ubuntu.com/Kernel/BuildYourOwnKernel">Ubuntu way</a> can fix this problem.</p>

<p>However, during the building process, if the error occurs with <code class="language-plaintext highlighter-rouge">llvm-strip:not found</code>.
This message is due to the command <code class="language-plaintext highlighter-rouge">llvm-strip</code> does not exist in <code class="language-plaintext highlighter-rouge">/usr/bin/</code> directory.
On the other hand, in the directory we can find a command named as <code class="language-plaintext highlighter-rouge">llvm-strip-10</code>.
To fix this, we can create a symbolic link (i.e., soft link) with</p>

<p><code class="language-plaintext highlighter-rouge">sudo ln -s /usr/bin/llvm-strip-10 /usr/bin/llvm-strip</code></p>

<p>The command will build the kernel with all the chosen modules, so it will take some hours to complete the compiling.</p>

<p>After the compile complete, the following command will install the kernel</p>

<p>@example
sudo make install
sudo make modules_install
@end example</p>

<p>The final step is to update grub, so the new kernel can be found when reboot the system.
@example
sudo update-grub
sudo grub-install
@end example</p>

<h3 id="remove-kernel">Remove Kernel</h3>

<p>The built kernel contains the following files:</p>

<p>@example
/boot/vmlinuz<em>KERNEL-VERSION</em>
/boot/initrd<em>KERNEL-VERSION</em>
/boot/System-map<em>KERNEL-VERSION</em>
/boot/config-<em>KERNEL-VERSION</em>
/lib/modules/<em>KERNEL-VERSION</em>/
/var/lib/initramfs-tools/<em>KERNEL-VERSION</em>/
@end example</p>

<p>It can be manually removed by <code class="language-plaintext highlighter-rouge">sudo rm -rf &lt;kernel_files&gt;</code> command.</p>

<h2 id="kernel-modules">Kernel Modules</h2>

<p>Linux kernel composes of hundreds of modules.
The user can compile and load modules according to the requirement.
Additionally, independently compiling the module will save lots of time because compile the whole kernel usually needs three or four hours.</p>

<h3 id="prerequisites-1">Prerequisites</h3>

<p>There are some packets that are necessary to compile the kernel. 
All these packets can be get from apt. 
Please follow the <a href="https://wiki.ubuntu.com/Kernel/BuildYourOwnKernel">Ubuntu wiki</a> (if use Ubuntu), and run the commands.</p>

<p>Specifically, first open the “/etc/apt/source.list” with <code class="language-plaintext highlighter-rouge">sudo</code> and uncomment commands with “deb-src” in this file.
After saving the file, run <code class="language-plaintext highlighter-rouge">sudo apt update</code> to update the packet list.
Then, run the following command to install all the dependents.</p>

<p>@example
sudo apt-get build-dep linux linux-image-$(uname -r)</p>

<p>sudo apt-get install libncurses-dev flex bison openssl libssl-dev <br />
dkms libelf-dev libudev-dev libpci-dev libiberty-dev autoconf
@end example</p>

<p>The next step is to download the kernel source code. 
One can download the newest kernel from <a href="https://www.kernel.org/">the official website</a>.
However, in this website is difficult to download the old version.</p>

<p>Instead, the aternative method is to download the source code by using “apt”.</p>

<p><code class="language-plaintext highlighter-rouge">sudo apt install linux-source-5.4.0</code></p>

<p>Then the corresponding version of the source code can be downloaded. 
The kernel version of Ubuntu 20.04 is 5.4.0.
The  of this source code can be found in “/usr/src/linux-source-5.4.0”.
The source code is a compressed file, and run <code class="language-plaintext highlighter-rouge">sudo tar jvxf linux-source-5.4.0.tar.bz2</code> to uncompress it.</p>

<h3 id="build-the-modules">Build the Modules</h3>

<p>Build a module or modules is very simple.
Linux kernel uses “Kbuild” to compile the kernel. 
“Kbuild” is at the root directory of the source code (i.e., at ./linux-source-5.4.0/ in my case).
Build the module needs to at the ./linux-source-5.4.0/ directory.</p>

<p>As an example, we use the compilinig process of “iwlwifi” module, which is the wireless Linux driver of Intel wireless network card.</p>

<p>The source code of this module is at <code class="language-plaintext highlighter-rouge">/usr/src/linux-source-5.4.0/linux-source-5.4.0/drivers/net/wireless/intel/iwlwifi/</code> in this case.</p>

<p>@example
make oldconfig &amp;&amp; make prepare
make # This command is to compile the kernel
     # which is the prerequisit of the module compilation
sudo make M=./drivers/net/wireless/intel/iwlwifi modules
@end example</p>

<p>After the compiling process is complete, a file named as “iwlwifi.ko” at he iwlwifi directory can be found.</p>

<p>To install it, use the following command</p>

<p>@example
cd ./drivers/net/wireless/intel/iwlwifi
insmod iwlwifi.ko
@end example</p>

<p><code class="language-plaintext highlighter-rouge">insmod</code> means “insert module”.
This is a command to install Linux kernel module.</p>

<p>If the iwlwifi module has been installed in the kernel, the old modules can be removed from the kernel with <code class="language-plaintext highlighter-rouge">sudo modprobe -r iwlwifi</code>.
Then, run the <code class="language-plaintext highlighter-rouge">insmod</code> command to install the compiled module.</p>

<h3 id="command-about-module">Command about Module</h3>

<p>All the usage are an example of the <em>iwlwifi</em> module.</p>

<p>@subsubsection lsmod</p>

<p><code class="language-plaintext highlighter-rouge">lsmod</code> is a command to list all installed module in the kernel.
It contains some information such as name, dependencies, etc.</p>

<p>Usage: <code class="language-plaintext highlighter-rouge">lsmod</code></p>

<p>@subsubsection modinfo</p>

<p><code class="language-plaintext highlighter-rouge">modinfo</code> can display details about a specific module.
It can display the information of either a installed module or a compiled module.</p>

<p>Usage: <code class="language-plaintext highlighter-rouge">modinfo iwlwifi</code></p>

<p>This command display the information of the installed module “iwlwifi”, not the compiled module.</p>

<p>Usage: <code class="language-plaintext highlighter-rouge">modinfo iwlwifi.ko</code></p>

<p>This command display the information of the compiled module.</p>

<p>@subsubsection modprobe</p>

<p><code class="language-plaintext highlighter-rouge">modprobe</code> is usually used to install or remove a module.</p>

<p>Usage: <code class="language-plaintext highlighter-rouge">sudo modprobe -r iwlwifi</code></p>

<p>Remove the iwlwifi module.</p>

<p>Usage: <code class="language-plaintext highlighter-rouge">sudo modprobe iwlwifi</code></p>

<p>Install the iwlwifi module.</p>

<p>@subsubsection insmod</p>

<p><code class="language-plaintext highlighter-rouge">insmod</code> can install a customized module.
If the module with the same name has been installed, <code class="language-plaintext highlighter-rouge">sudo modprobe -r iwlwifi</code> is needed to remove the pre-installed module.</p>

<p>Usage: <code class="language-plaintext highlighter-rouge">insmod iwlwifi.ko</code></p>

<h2 id="mac80211">mac80211</h2>

<h3 id="rate-control">Rate Control</h3>

<p>Rate control (or rate adaptation) is an important algorithm for wireless devices to select the optimal bit rate under different wireless channel conditions.
In mac80211 subsystem in Linux kernel, rate control is part of the subsystem, and it can be self-designed by each wireless driver.
For example, ath9k driver uses the default rate control (i.e., <code class="language-plaintext highlighter-rouge">https://wireless.wiki.kernel.org/en/developers/documentation/mac80211/ratecontrol/minstrel, minstrel</code>), while iwlwifi uses a custom rate control named <code class="language-plaintext highlighter-rouge">https://wiki.gentoo.org/wiki/Iwlwifi, "iwl-agn-rs"</code>.</p>

<p>mac80211 provides a struct <code class="language-plaintext highlighter-rouge">https://docs.huihoo.com/doxygen/linux/kernel/3.7/structrate__control__ops.html, "rate_control_ops"</code> with multiple callbacks.
To implement a new rate control algorithm, someone must define these callbacks in <code class="language-plaintext highlighter-rouge">rate_control_ops</code>.
For example, minstrel includes two types of algorithm, one is in the file <code class="language-plaintext highlighter-rouge">rc80211_minstrel.c</code> (mac80211_minstrel) and the other is in the file <code class="language-plaintext highlighter-rouge">rc80211_minstrel_ht.c</code> (mac80211_minstrel_ht).</p>

<p>For iwlwifi driver, <code class="language-plaintext highlighter-rouge">rate_control_ops</code> is defined in <code class="language-plaintext highlighter-rouge">dvm/mac80211.c</code> (rs_ops) and <code class="language-plaintext highlighter-rouge">mvm.mac80211.c</code> (rs_mvm_ops_drv), depend on different types of drivers.</p>

<p><code class="language-plaintext highlighter-rouge">rate.c</code> defines all rate control functions for different drivers.
Ideally, the developer does not need to change the function in <code class="language-plaintext highlighter-rouge">rate.c</code>.</p>

<p>Two basic functions in this file is <code class="language-plaintext highlighter-rouge">ieee80211_rate_control_register</code> and <code class="language-plaintext highlighter-rouge">ieee80211_rate_control_unregister</code>.
The driver loads different rate control algorithms by calling the two functions.</p>

<h2 id="ath9k_htc-driver">ath9k_htc driver</h2>

<p><a href="https://wireless.wiki.kernel.org/en/users/drivers/ath9k_htcl">ath9k_htc</a> driver is a wireless driver for IEEE 802.11n devices with USB port.
It can support AR9271 USB devices.
Atheros provides an open source version of the firmware, i.e., <a href="https://github.com/qca/open-ath9k-htc-firmware">open-ath9k-htc-firmware</a>.</p>

<p>This document is a simple analysis about the RX pipeline of ath9k_htc.</p>

<p>ath9k_htc is based on other ath drivers, you can find the drivers and all relations with</p>

<p>@example 
    $lsmod | grep ath
    ath9k_htc              77824  0
    ath9k_common           36864  1 ath9k_htc
    ath9k_hw              483328  2 ath9k_htc,ath9k_common
    ath                    36864  3 ath9k_htc,ath9k_common,ath9k_hw
    mac80211             1024000  2 ath9k_htc,iwlmvm
    cfg80211              888832  6 ath9k_htc,ath9k_common,iwlmvm,ath,iwlwifi,mac80211
@end example</p>

<p>The description of all drivers can found in <a href="http://linuxwireless.sipsolutions.net/en/users/Drivers/Atheros/__v22.html">Atheros Linux wireless drivers</a>.</p>

<p>In Ubuntu, “apt” can be used to download the Linux kernel source code with the current kernel version  by using</p>

<p><code class="language-plaintext highlighter-rouge">apt source linux-image-unsigned-$(uname -r)</code></p>

<p>After changing into the kernel file, the source code of ath9k_htc is in</p>

<p><code class="language-plaintext highlighter-rouge">/driver/net/wireless/ath/ath9k/</code></p>

<p>If the downloaded driver is mismatched with the Linux kernel version, the “insmod” command will report an error with invalid module format.</p>

<p>All htc related codes are listed in the following files.</p>

<p>@example
    htc_drv_init.c
    htc_drv_main.c
    htc_drv_txrx.c
    htc_drv_beacon.c<br />
    htc_drv_gpio.c  <br />
    htc_hst.c
    hif_usb.c
    htc_drv_debug.c
@end example</p>

<p>In particular, “htc_drv_main.c” is the entry point of HTC driver with “module_init” and “module_exit”.
Other files related to receive data is “htc_drv_txrx.c”, “htc_hst.c”, and “hif_usb.c”</p>

<p>AR9271 chips connect to the device with USB port, so it uses USB subsystem in Linux kernel to transmit and receive data.
As a USB device, it uses USB Request Block (URB) to receive data.</p>

<p>All functions about URB reception are in “hif_usb.c” file.
In specific, the following functions is the main process for the data reception.</p>

<p>@example
    hif_usb.c
        |
        |—ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
            |
            |—usb_fill_bulk_urb(urb, hif_dev-&gt;udev,
            |             usb_rcvbulkpipe(hif_dev-&gt;udev,
            |                     USB_WLAN_RX_PIPE),
            |             skb-&gt;data, MAX_RX_BUF_SIZE,
            |             ath9k_hif_usb_rx_cb, rx_buf);
            |
            |—usb_anchor_urb(urb, &amp;hif_dev-&gt;rx_submitted);
            |
            |—ret = usb_submit_urb(urb, GFP_KERNEL);
            |
        |—ath9k_hif_usb_rx_cb(struct urb *urb)
        |—ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, struct sk_buff *skb)</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>htc_hst.c
    |
    |---ath9k_htc_rx_msg(struct htc_target *htc_handle, 
    |                       struct sk_buff *skb, 
    |                       u32 len, u8 pipe_id)

htc_drv_txrx.c
    |
    |---ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb, htc_endpoint_id ep_id)
        |
        |---tasklet_schedule(&amp;priv-&gt;rx_tasklet)
        |---ath9k_rx_tasklet(struct tasklet_struct *t) @end example
</code></pre></div></div>

<p>In <code class="language-plaintext highlighter-rouge">ath9k_hif_usb_alloc_rx_urbs</code>, it allocates a usb bulk URB for signal reception, the callback function is <code class="language-plaintext highlighter-rouge">ath9k_hif_usb_rx_cb</code>. 
It will submit the URB to the USB core and call the callback function.
If you are new to Linux USB, for a detailed description about <a href="https://manpages.debian.org/testing/linux-manual-4.8/usb_fill_bulk_urb.9.en.html">usb_fill_bulk_urb</a> and <a href="https://manpages.debian.org/testing/linux-manual-4.9/usb_submit_urb.9">usb_submit_urb</a>, please refer to <a href="https://www.kernel.org/doc/html/v4.15/driver-api/usb/index.html">Linux USB API</a>.</p>

<p>In <code class="language-plaintext highlighter-rouge">ath9k_hif_usb_rx_cb</code>, it will process skb, if it has new data, the data will pass to <code class="language-plaintext highlighter-rouge">ath9k_hif_usb_rx_stream</code>.
After that, it will call itself by resubmitting the URB. 
The resubmit ensure that USB core will repeatedly poll the buffer to receive data.</p>

<p>In <code class="language-plaintext highlighter-rouge">ath9k_hif_usb_rx_stream</code>, it will packetize the data in buffer. Each packet will push into <code class="language-plaintext highlighter-rouge">ath9k_htc_rx_msg</code> in <code class="language-plaintext highlighter-rouge">htc_hst.c</code> file.</p>

<p><code class="language-plaintext highlighter-rouge">ath9k_htc_rx_msg</code> will handle different types of packets.
For a data packet, it will call <code class="language-plaintext highlighter-rouge">endpoint-&gt;ep_callbacks.rx</code>, which is also a callback function. 
The callback handler is defined in <code class="language-plaintext highlighter-rouge">htc_drv_txrx.c</code>, which is named as <code class="language-plaintext highlighter-rouge">ath9k_htc_rxep</code>.</p>

<p>Finally, <code class="language-plaintext highlighter-rouge">ath9k_htc_rxep</code> will check that whether the buffer is valid, and call <code class="language-plaintext highlighter-rouge">tasklet_schedule</code>.
<a href="http://books.gigatux.nl/mirror/kerneldevelopment/0672327201/ch07lev1sec3.html">Tasklet</a> is an interrupt in Linux Kernel.
In this tasklet, ath9k_htc defines a callback for reception named as <code class="language-plaintext highlighter-rouge">ath9k_rx_tasklet</code>, which is the final process of signal reception. 
The data will pass to mac80211 subsystem by calling <a href="https://elixir.bootlin.com/linux/latest/ident/ieee80211_rx">ieee80211_rx</a>.</p>

<h3 id="customized-ath9k">Customized ath9k</h3>

<p>ath9k is a kernel driver that works as a kernel module for Atheros wireless IEEE802.11n NICs.
Compilation of the kernel module is the prerequisite to investigate the rate adaptation algorithm.
However, the driver (and the kernel module) highly depends on the version of the kernel, so it is difficult to compile and install even a simple driver.</p>

<p>This subsection introduces a basic and simple method to build it on the newest Ubuntu 22.04.</p>

<p>First, change to the directory of ath driver, which is in the <code class="language-plaintext highlighter-rouge">./drivers/net/wireless/ath/</code> if the working directory is the root of the kernel source code.
Note that ath9k driver is based on the ath module, so we better compile is at the same time.</p>

<p>In the directory, build the driver for the current kernel with</p>

<p><code class="language-plaintext highlighter-rouge">make -C /lib/modules/</code>uname -r<code class="language-plaintext highlighter-rouge">/build M=$PWD</code></p>

<p>where <code class="language-plaintext highlighter-rouge">$PWD</code> means print work directory.</p>

<p>Now, the compilation is complete, we can load the modules with</p>

<p>@example
    insmod ath.ko
    insmod ./ath9k_common.ko
    insmod ./ath9k_hw.ko
    insmod ./ath9k.ko
@end example</p>

<p>Use <code class="language-plaintext highlighter-rouge">sudo modprobe -r &lt;MODULE_NAME&gt;</code> to remove the old versions of them.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Kernel]]></summary></entry><entry><title type="html">Multi-OS</title><link href="/2026/09/05/multiple-os-installation.html" rel="alternate" type="text/html" title="Multi-OS" /><published>2026-09-05T00:00:00+00:00</published><updated>2026-09-05T00:00:00+00:00</updated><id>/2026/09/05/multiple-os-installation</id><content type="html" xml:base="/2026/09/05/multiple-os-installation.html"><![CDATA[<h1 id="multi-os">Multi-OS</h1>

<p>Install multiple OSs is simple since lots-of OSs have a GUI installer.
In most time, someone does not need to install the OS in the hardware, if he only want to try it at first.
This section summarizes the content about Live USB and Disk layout.</p>

<h2 id="live-usb">Live USB</h2>

<p>The first thing of installation OSs is having a Live USB that contains multiple ISOs.
<a href="https://www.ventoy.net/en/index.html">Vectoy</a> is an open-source tool that can load multiple Live USBs
The USB with Ventoy also can be used for backup files.</p>

<p>The only drawback of ventoy is the grub may have a incorrect boot configuration.
This makes the installed OS can be boot with recovery mode but cannot boot with the normal mode.
To avoid this, just edit the grub (type <code class="language-plaintext highlighter-rouge">e</code> when boot) and delete the command <code class="language-plaintext highlighter-rouge">rdinit=/vtoy/vtoy</code>.</p>

<h2 id="disk-partition">Disk Partition</h2>

<p>Most Linux distributions provides a GUI installer, so the installation is quite easy.
The only thing worth noting is carefully about the disk partition without formating the partition and lossing data.
Usually, all the home directories of all OSs can be listed in the same partition with different folders.
An example partition can be as follows</p>

<p>@itemize @bullet
@item nvme0n1
    @itemize @minus
    @item nvme0n1p1 (512 MB)
        @itemize @minus
        @item /boot/efi
        @end itemize
    @item nvme0n1p2 (16 GB)
        @itemize @minus
        @item /swap
        @end itemize
    @item nvme0n1p3 (500 GB)
        @itemize @minus
        @item /home
            @itemize @minus
            @item /home/user_ubuntu
            @item /home/user_suse
            @item /home/user_arch
            @item …
            @end itemize
        @end itemize
    @item nvme0n1p4 (100 GB)
        @itemize @minus
        @item /       # root for Ubuntu
        @end itemize
    @item nvme0n1p5 (100 GB)
        @itemize @minus
        @item /       # root for OpenSUSE
        @end itemize
    @item …
    @end itemize
@end itemize</p>

<p>The most important thing is: DON’T FORMAT the home directory in nvme0n1p3 and the /boot/efi directory in nvme0n1p1 when install a new OS.
This partition can provide the capability to reinstall all OSs without affecting the user data.</p>

<h2 id="update-grub">Update grub</h2>

<p>After a new installation, it is better to update the grub at any OSs.
The follow command can be used only once at one of the OSs.
In Debian, use</p>

<p><code class="language-plaintext highlighter-rouge">sudo grub-mkconfig -o /boot/grub/grub.cfg</code>
<code class="language-plaintext highlighter-rouge">sudo grub-install /nvme0n1</code></p>

<p>In OpenSUSE, use</p>

<p><code class="language-plaintext highlighter-rouge">sudo grub2-mkconfig -o /boot/grub/grub.cfg</code>
<code class="language-plaintext highlighter-rouge">sudo grub2-install /nvme0n1</code></p>

<h2 id="reinstallation">Reinstallation</h2>

<p>Most time there is no need to reinstall my OSs, but sometimes the OS cannot be boot due to strange issues.
In this time, the OS can be reinstalled with the same partition and user name as the old version.
For example, the root of the new ubuntu will be listed in nvme0n1p4, and the /home will be listed in nvme01n1p3.
The user name is ‘user_ubuntu’, so the configuration of the old OS can be reused for the new OS.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Multi-OS]]></summary></entry><entry><title type="html">Network</title><link href="/2026/09/05/network.html" rel="alternate" type="text/html" title="Network" /><published>2026-09-05T00:00:00+00:00</published><updated>2026-09-05T00:00:00+00:00</updated><id>/2026/09/05/network</id><content type="html" xml:base="/2026/09/05/network.html"><![CDATA[<h1 id="network">Network</h1>

<h2 id="iw">iw</h2>

<p>iw is a configuration tool for mac80211 in Linux kernel with netlink
The code tree of <code class="language-plaintext highlighter-rouge">iw.c</code> in iw is</p>

<p>@itemize @bullet
@item main
    @itemize @minus
    @item version
    @item nl80211_init
        @itemize @minus 
        @item nl_socket_alloc
        @item nl_socket_free
        @item nl_socket_set_buffer_size
        @end itemize
    @item usage
        @itemize @minus 
        @item __usage_cmd
        @item usage_options
        @end itemize
    @item __handle_cmd
        @itemize @minus 
        @item error_handler
        @item finish_handler
        @item ack_handler
        @item register_handler
        @item valid_handler
        @item phy_lookup
        @end itemize
    @item phy_lookup
    @item nl80211_cleanup
    @end itemize
@item TOPLEVEL
    @itemize @minus 
    @item print_help
    @end itemize
@item handle_cmd
    @itemize @minus 
    @item __handle_cmd
    @end itemize
@item usage_cmd
    @itemize @minus 
    @item __usage_cmd
    @end itemize
@end itemize</p>

<h2 id="proxy">proxy</h2>

<p>Auto detect proxy with <code class="language-plaintext highlighter-rouge">nc</code> and connect to it</p>

<p>@example
if nc -z $<srv_ip> $<proxy_port>; then
    git config --global http.proxy "http://$<srv_ip>:$<proxy_port>"
    git config --global https.proxy "https://$<srv_ip>:$<proxy_port>"</proxy_port></srv_ip></proxy_port></srv_ip></proxy_port></srv_ip></p>

<p>elif nc -z $<local_ip> $<proxy_port>; then
    git config --global http.proxy "http://$<local_ip>:$<proxy_port>"
    git config --global https.proxy "https://$<local_ip>:$<proxy_port>"</proxy_port></local_ip></proxy_port></local_ip></proxy_port></local_ip></p>

<p>else
    git config –global –unset http.proxy 
    git config –global –unset https.proxy
fi
@end example</p>

<h2 id="snapdropnet">snapdrop.net</h2>

<p><a href="https://snapdrop.net">snapdrop</a> is an easily-used point-to-point file transfer in the web browser.
Open the link of snapdrop in the same network.
The website can identify all devices in the same network. 
Just drop the file to the target.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Network]]></summary></entry></feed>