Contents

This is a personal blog website that named as Shell Cottage. The blog focuses on Linux platform and wireless network.


1 Distribution

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.

ArchDebianFedora
Default desktop-GNOMEGNOME
Init systemsystemdsystemdsystemd
Package managerpacmanaptdnf
C libraryglibcglibcglibc
Utilitycoreutilscoreutilscoreutils
InstallerCLIDebian-InstallerAnaconda
NixOSVoidDeepin
Default desktopGNOMExfceDDE
Init systemsystemdrunitsystemd
Package managerNixxbps-
C libraryglibcmuslglibc
Utilitycoreutilscoreutilscoreutils
InstallerCalamaresCLIdeepin-installer

The distributions for embeded devices

OpenwrtAlpine
Init systeminitOpenRC
Package manageropkgapk
UtilityBusyboxBusybox

1.1 Package Manager

The follow lists common package managers that in different distributions.

  • apt
  • dnf
  • pacman
  • zypper
  • Flatpak
  • AppImage

1.1.1 dnf

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

The source files of an rpm package are in the *.src.rpm.

# Download the src.rpm
dnf download --source <package name>
# List the infomation in the *src.rpm
rpm -ql *.src.rpm 
# Extract the *src.rpm
rpm2cpio *.src.rpm | cpio -idv
# Install source code from *src.rpm to home directory
rpm -i *src.rpm
# Rebuild the source package if it is patched
rpmbuild -bb /spec/director/package.spec

1.1.2 zypper

openSUSE uses zypper as the default package manager. It is based on RPM, which is similar to Fedora. zypper uses repository for packages. zypper repos lists repositories. Search all installed packages in a target repo, use zypper search -i -r <repo>.

Besides installation of the built programs, zypper also provides an offical repository for the source code. As an example, the download and build process for the hostapd is

sudo zypper source-install hostapd  # or `sudo zypper si hostapd`
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

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

sudo zypper install osc

1.1.3 Flatpak

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.

flatpak install <package name/ID>

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

flatpak run <package name/ID>

1.2 Init Process

In Linux, the first process is usually *init* or *systemd*. 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.

1.2.1 System V and init

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 /etc/inittab and runs the scripts in /etc/rc according to the runlevel. Different runlevels means different modes of init. It will run the corresponding runlevel scripts in /etc/rcN.d/, 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 etc/init.d/. 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.

1.2.2 systemd

In contrast, systemd concurrently runs all scripts. Ubuntu and OpenSUSE have been support systemd and their would have other distributions. In a system that initialized with systemd. The init file, which is /usr/sbin/init will be a symbolic to the /lib/systemd/systemd. The default configuration file of systemd is /usr/lib/systemd/system/default.target, which is also a symbolic link to /usr/lib/systemd/system/graphical.target. You can find the default target with

systemctl get-default

1.3 Linux To Go

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).

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.

1.4 Multi-OS Installation

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.

1.4.1 Live USB

The first thing of installation OSs is having a Live USB that contains multiple ISOs. Vectoy is an open-source tool that can load multiple Live USBs The USB with Ventoy also can be used for backup files.

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 ‘e‘ when boot) and delete the command ‘rdinit=/vtoy/vtoy‘.

1.4.2 Disk Partition

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

  • nvme0n1
    • nvme0n1p1 (512 MB)
      • /boot/efi
    • nvme0n1p2 (16 GB)
      • /swap
    • nvme0n1p3 (500 GB)
      • /home
        • /home/user_ubuntu
        • /home/user_suse
        • /home/user_arch
        • ...
    • nvme0n1p4 (100 GB)
      • / # root for Ubuntu
    • nvme0n1p5 (100 GB)
      • / # root for OpenSUSE
    • ...

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.

1.4.3 Update grub

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

sudo grub-mkconfig -o /boot/grub/grub.cfg sudo grub-install /nvme0n1

In OpenSUSE, use

sudo grub2-mkconfig -o /boot/grub/grub.cfg sudo grub2-install /nvme0n1

1.4.4 Reinstallation

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.


2 Desktop Environment

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 <ctrl>+<alt>+F{1-6} can change between virtual console and GUI. Specifically, <ctrl>+<alt>+F2 can change to the GUI, and <ctrl>+<alt>+F{3,4,5,6} 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, sudo startx 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.

Graphicless compares the follow open-source desktop environments.

KDEGNOMExfce
ToolkitQTGTKGTK
Display managerSDDMgdmLightDM
Session managerksmservergnome-sessionxfce4-session
Windows managerKWingnome-shellxfwm4
Desktop manager--xfdesktop
File managerDolphinNautilusThunar
LauncherKickoff-xfce-panel
EditorKategnome-text-editorMousepad
TerminalKonsolegnome-terminalxfce4-terminal
NetworkNetwork ManagerNetwork Manager-
CapturerSpectacleGNOME Screenshotxfce4-screenshooter
Document viewerOkularEvince-
Image viewerGwenviewLoupeRistretto
Input method---
Advanced setting-gnome-tweaks-
DevelopmentKDevelopGNOME Builder-
LXQTDDE
ToolkitQTQT
Display managerSDDMLightDM
Session managerlxqt-sessiondde-session
Windows managerOpenboxTreeland
Desktop manager--
File managerPcManFm-qtdde-file-manager
Launcherlxqt-runnerdde-launcher
Editor-deepin-editor
TerminalQTerminaldeepin-terminal
Network--
CapturerScreengrabdeepin-screenshot
Document viewer-deepin-reader
Image viewerLximage-qtdeepin-image-viewer
Input method-deepin-im
Advanced setting-deepin-tweak
Development-Deepin-IDE

2.1 GNOME

2.1.1 Advanced Setting

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

sudo apt install gnome-tweaks

This swap is only useful in gnome-based GUI. Windows has a similar tool that named as [PowerToys](https://github.com/microsoft/PowerToys).

2.2 xfce4

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

2.3 Window Manager

Openboxi3xmonadsway
Protocolx11x11WaylandWayland

2.3.1 Openbox

Install Openbox with apt

sudo apt install openbox

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

sudo vim /usr/lib/x86_64-linux-gnu/openbox-autostart

Uncommand the line test -z $BG || $BG -solid "#303030"

2.4 tmux

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 man tmux or type <C-b> + ?. The keybindings are in the "DEFAULT KEY BINDINGS" section.

<C-b> is the default prefix key of tmux. The follow shortcuts omit the prefix key.

2.4.1 Normal mode

    # Session
    d       # Detach the window from the session
    s       # Select a new session
    (/)     # Move to the previous/next session

    tmux ls/list                            # List sessions
    tmux attach/detach                      # Attach/Detach the window to the session
    tmux kill-session -t <session-name>     # 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 <session-name>              # Create a new window for the session

    # Pane
    o             # Go to next pane
    q <num>       # 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
    <Up>/<Down>/<Left>/<right>          # Go to the up/down/left/right pane

2.4.2 Copy mode

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.

    [       # Enter copy mode.

2.4.3 Command line mode

The follow key does not need prefix key.

    :       # Enter command-line mode

3 System Management

Tools to manage Linux.

3.1 smartctl

SMART is a tool to check the health of disk. "SMART" means Self-Monitoring, Analysis and Report Technology. The command is "smartctl". To run it, type the command with sudo privilege.

sudo smartctl -H /dev/nvme0n1 # Show device SMART health status

3.2 top

  • us uniced user process
  • sy system process
  • ni niced user process
  • id kernel idle handler
  • wa waiting for I/O completion
  • hi hardware interrupt
  • si software interrupt
  • st stolen by hypervisor
  • PID process ID
  • USER user name
  • PR priority
  • NI nice value
  • VIRT virtual memory size (KiB)
  • RES resident memory size (KiB)
  • SHR shared memory size (KiB)

4 Kernel

4.1 Building the Kernel

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".

The Linux kernel can be download from the website. The downloaded files are under the "linux-5.8.7" directory.

4.1.1 Prerequisites

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 Linux kernel documentations and the Ubuntu BuildYourOwnKernel Wiki. Run the following command

sudo apt-get build-dep linux linux-image-$(uname -r)

sudo apt-get install libncurses-dev flex bison openssl libssl-dev \
dkms libelf-dev libudev-dev libpci-dev libiberty-dev autoconf

It is worth to note that directly following BuildYourOwnKernel Wiki has some problems. When run the command

sudo apt-get build-dep linux linux-image-$(uname -r)
sudo apt-get build-dep linux linux-image-$(uname -r)

it reports an error as follows

E: You must put some 'deb-src' URIs in your sources.list

Please add the contents

deb-src http://cn.archive.ubuntu.com/ubuntu/ focal-updates main restricted
deb-src http://cn.archive.ubuntu.com/ubuntu/ focal-updates main restricted

Then uncomment all commands with "deb-src" in the /etc/apt/sources.list file, and run sudo apt update. The error is fixed.

4.1.2 Build and install the linux kernel

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 make oldconfig 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.

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 this page. Otherwise, building the kernel in the Ubuntu way can fix this problem.

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

sudo ln -s /usr/bin/llvm-strip-10 /usr/bin/llvm-strip

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

After the compile complete, the following command will install the kernel

sudo make install
sudo make modules_install

The final step is to update grub, so the new kernel can be found when reboot the system.

sudo update-grub
sudo grub-install

4.1.3 Remove Kernel

The built kernel contains the following files:

/boot/vmlinuz*KERNEL-VERSION*
/boot/initrd*KERNEL-VERSION*
/boot/System-map*KERNEL-VERSION*
/boot/config-*KERNEL-VERSION*
/lib/modules/*KERNEL-VERSION*/
/var/lib/initramfs-tools/*KERNEL-VERSION*/

It can be manually removed by sudo rm -rf <kernel_files> command.

4.2 Kernel Modules

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.

4.2.1 Prerequisites

There are some packets that are necessary to compile the kernel. All these packets can be get from apt. Please follow the Ubuntu wiki (if use Ubuntu), and run the commands.

Specifically, first open the "/etc/apt/source.list" with sudo and uncomment commands with "deb-src" in this file. After saving the file, run sudo apt update to update the packet list. Then, run the following command to install all the dependents.

sudo apt-get build-dep linux linux-image-$(uname -r)

sudo apt-get install libncurses-dev flex bison openssl libssl-dev \
dkms libelf-dev libudev-dev libpci-dev libiberty-dev autoconf

The next step is to download the kernel source code. One can download the newest kernel from the official website. However, in this website is difficult to download the old version.

Instead, the aternative method is to download the source code by using "apt".

sudo apt install linux-source-5.4.0

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 sudo tar jvxf linux-source-5.4.0.tar.bz2 to uncompress it.

4.2.2 Build the Modules

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.

As an example, we use the compilinig process of "iwlwifi" module, which is the wireless Linux driver of Intel wireless network card.

The source code of this module is at /usr/src/linux-source-5.4.0/linux-source-5.4.0/drivers/net/wireless/intel/iwlwifi/ in this case.

make oldconfig && 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

After the compiling process is complete, a file named as "iwlwifi.ko" at he iwlwifi directory can be found.

To install it, use the following command

cd ./drivers/net/wireless/intel/iwlwifi
insmod iwlwifi.ko

insmod means "insert module". This is a command to install Linux kernel module.

If the iwlwifi module has been installed in the kernel, the old modules can be removed from the kernel with sudo modprobe -r iwlwifi. Then, run the insmod command to install the compiled module.

4.2.3 Command about Module

All the usage are an example of the *iwlwifi* module.

4.2.3.1 lsmod

lsmod is a command to list all installed module in the kernel. It contains some information such as name, dependencies, etc.

Usage: lsmod

4.2.3.2 modinfo

modinfo can display details about a specific module. It can display the information of either a installed module or a compiled module.

Usage: modinfo iwlwifi

This command display the information of the installed module "iwlwifi", not the compiled module.

Usage: modinfo iwlwifi.ko

This command display the information of the compiled module.

4.2.3.3 modprobe

modprobe is usually used to install or remove a module.

Usage: sudo modprobe -r iwlwifi

Remove the iwlwifi module.

Usage: sudo modprobe iwlwifi

Install the iwlwifi module.

4.2.3.4 insmod

insmod can install a customized module. If the module with the same name has been installed, sudo modprobe -r iwlwifi is needed to remove the pre-installed module.

Usage: insmod iwlwifi.ko

4.3 mac80211

4.3.1 Rate Control

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., https://wireless.wiki.kernel.org/en/developers/documentation/mac80211/ratecontrol/minstrel, minstrel), while iwlwifi uses a custom rate control named https://wiki.gentoo.org/wiki/Iwlwifi, "iwl-agn-rs".

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

For iwlwifi driver, rate_control_ops is defined in dvm/mac80211.c (rs_ops) and mvm.mac80211.c (rs_mvm_ops_drv), depend on different types of drivers.

rate.c defines all rate control functions for different drivers. Ideally, the developer does not need to change the function in rate.c.

Two basic functions in this file is ieee80211_rate_control_register and ieee80211_rate_control_unregister. The driver loads different rate control algorithms by calling the two functions.

4.4 ath9k_htc driver

ath9k_htc 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., open-ath9k-htc-firmware.

This document is a simple analysis about the RX pipeline of ath9k_htc.

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

    $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

The description of all drivers can found in Atheros Linux wireless drivers.

In Ubuntu, "apt" can be used to download the Linux kernel source code with the current kernel version by using

apt source linux-image-unsigned-$(uname -r)

After changing into the kernel file, the source code of ath9k_htc is in

/driver/net/wireless/ath/ath9k/

If the downloaded driver is mismatched with the Linux kernel version, the "insmod" command will report an error with invalid module format.

All htc related codes are listed in the following files.

    htc_drv_init.c
    htc_drv_main.c
    htc_drv_txrx.c
    htc_drv_beacon.c  
    htc_drv_gpio.c    
    htc_hst.c
    hif_usb.c
    htc_drv_debug.c

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"

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.

All functions about URB reception are in "hif_usb.c" file. In specific, the following functions is the main process for the data reception.

    hif_usb.c
        |
        |---ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
            |
            |---usb_fill_bulk_urb(urb, hif_dev->udev,
            |             usb_rcvbulkpipe(hif_dev->udev,
            |                     USB_WLAN_RX_PIPE),
            |             skb->data, MAX_RX_BUF_SIZE,
            |             ath9k_hif_usb_rx_cb, rx_buf);
            |
            |---usb_anchor_urb(urb, &hif_dev->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)

    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(&priv->rx_tasklet)
            |---ath9k_rx_tasklet(struct tasklet_struct *t)

In ath9k_hif_usb_alloc_rx_urbs, it allocates a usb bulk URB for signal reception, the callback function is ath9k_hif_usb_rx_cb. 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 usb_fill_bulk_urb and usb_submit_urb, please refer to Linux USB API.

In ath9k_hif_usb_rx_cb, it will process skb, if it has new data, the data will pass to ath9k_hif_usb_rx_stream. After that, it will call itself by resubmitting the URB. The resubmit ensure that USB core will repeatedly poll the buffer to receive data.

In ath9k_hif_usb_rx_stream, it will packetize the data in buffer. Each packet will push into ath9k_htc_rx_msg in htc_hst.c file.

ath9k_htc_rx_msg will handle different types of packets. For a data packet, it will call endpoint->ep_callbacks.rx, which is also a callback function. The callback handler is defined in htc_drv_txrx.c, which is named as ath9k_htc_rxep.

Finally, ath9k_htc_rxep will check that whether the buffer is valid, and call tasklet_schedule. Tasklet is an interrupt in Linux Kernel. In this tasklet, ath9k_htc defines a callback for reception named as ath9k_rx_tasklet, which is the final process of signal reception. The data will pass to mac80211 subsystem by calling ieee80211_rx.

4.4.1 Customized ath9k

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.

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

First, change to the directory of ath driver, which is in the ./drivers/net/wireless/ath/ 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.

In the directory, build the driver for the current kernel with

make -C /lib/modules/`uname -r`/build M=$PWD

where $PWD means print work directory.

Now, the compilation is complete, we can load the modules with

    insmod ath.ko
    insmod ./ath9k_common.ko
    insmod ./ath9k_hw.ko
    insmod ./ath9k.ko

Use sudo modprobe -r <MODULE_NAME> to remove the old versions of them.


5 Blog

This blog is based on Github page and jekyll.

5.1 Installation

It requires Ruby, RubyGems, and bundler.

The following command can install the prerequisites

sudo apt install ruby-full build-essential zlib1g-dev

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

sudo gem source --add <https://mirror.com> --remove https://rubygems.org/

where <https://mirror.com> is the host of a mirror. The follow installs jekyll and bundler

sudo gem install jekyll bundler

5.2 Jekyll Themes

The blog is based on [mediator](https://jekyllthemes.io/theme/mediator) theme. Download the theme and copy it into my own git directory by

git clone https://github.com/dirkfabisch/mediator

5.3 Usage

The blog can be used from source with ‘bundle‘

bundle exec jekyll server

5.4 Upgrade

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.

To fix this problem, the direct approach is to reinstall bundle with gem.

sudo gem install bundler

Then, bundle can install all required packages by ‘bundle install‘ except *webrick* because webrick is no longer in the standard library of bundle. However, I have a network issue when run ‘bundle add webrick‘. 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

bundle config mirror.https://rubygems.org <https://mirror.com>

where <https://mirror.com> 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.

sudo bundle config mirror.https://rubygems.org <https://mirror.com> sudo bundle install sudo bundle add webrick

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


6 Shell

6.1 Terminal emulator

Terminal emulator is the prerequisite of shell. An open-source terminal emulator is terminator. Install it with

sudo apt install terminator

The terminal emulator provides color and font support for shell. For example, the agnoster theme of zsh requires the powerline font. To install it, run

sudo apt install fonts-powerline

and then set the fonts in the terminator.

6.2 Swap keys

Usually, if someone wants to swap Caplock and left Ctrl since the latter is more useful, some desktop provides an GUI tool such as gnome-tweak in GNOME or the setting in KDE that support this function. For the desktops that do not have an GUI tool, a shell method is to use xmodmap and the GUI helper xkeycaps. After change the keys in xkeycaps, write out the configuration file of xmodmap in the HOME diretory, and add the follows in the shell

xmodmap ~/.xmodmap-`uname -n`

xmodmap will trigger the key swap when open a terminal.

6.3 Bash

Bash has two style interface: emacs style and vi style. Emacs style is the default style. Vi style can type <Esc> to exit insert mode and use vim keybindings. The follows are the keymappings in for its emacs style.

    CTRL+a/e    # Move to begin/End of the line
    CTRL+b/f    # Backward/forward
    CTRL+c      # Halt
    CTRL+d      # Logout when no editing command
                # Display the completion for the commmand
    CTRL+g      # Abort the editing command
    CTRL+h      # Delete the character before cursor
    CTRL+j/m    # <RETURN>
    CTRL+k/w    # Delete to the end/begin of the line
    CTRL+l      # Clears the terminal except the current line
    CTRL+n/p    # <DOWN>/<UP>
    CTRL+o      # <RETURN>, then display next line in the history

    CTRL+s/q    # Suspend/Resume shell output
    CTRL+r      # Search backward
    CTRL+t      # Transpose two characters
    CTRL+u      # Delete the line
    CTRL+v      # Enable to insert control strings
    CTRL+y      # Yank (for CTRL+k/u/w)
    CTRL+z      # Stop the current command, resume with 'fg' in the foreground

    CTRL+x (    # Recording a keyboard macro
    CTRL+x )    # Stop recording
    CTRL+x e    # Recall the record

    CTRL+x CTRL+e   # Invoke text editor in $EDITOR 
                    # Recommandation: export EDITOR=vim
                    # In vim, you can type the command
                    # Type 'ZZ' in normal mode to input multi-line commands for bash

    CTRL+S      # Search forword

    ALT+b/f     # Backward/Forward one word
    ALT+c       # Upper character
    ALT+d       # Delete word
    ALT+h       # 'run-help' program 
    ALT+l/u     # Upper, to the end/begin of the line
    ALT+n/p     # Search history to match the edited command
    ALT+r       # Revert changes of the command from the history
    ALT+t       # Transpose two words
    ALT+.       # Paste last word from the last command
    ALT+?       # List completions

    !!          # Repeat the last command
    !<n>        # Refer to command line 'n'
    !<string>   # Refer to command starting with 'string'

## File

touch <file> # Update timestamp # Make a new file mktemp -t <file> # Make a temp file in /tmp/ cat <file> # Display <file> nl <file> # Number of lines wc <file> # Word count more/less <file> # Display a file and type q to quit head/tail <file> # Output the first/last lines of file diff # Compare two files sort <file> # Sort the file line by line rev <file> # Reverse strings in file line by line grep <pat> <file> # Find for the string in the <file> sed # Stream editor

ln -s <file> <link> # Symbolic link to <file> readlink <link> # Display the file name of the symbolic link

## Disk

df # Disk free df -h # Echo the result with human-readable output du # Disk used du -h -d 1 . 2&> /dev/null | grep "G\s" # Echo the size of directories and files of the # current folder. Ignore errors. Grep a space # after ’G’. Useful command to show the large # directories and files

6.3.1 Process and Job

    jobs                # Builtin: List jobs
    ps                  # List processes in snapshot
    top                 # Real-time list processes
    kill/killall        # Builtin: Kill process with PID/name
    bg                  # Builtin: List background jobs
    fg                  # Builtin: Bring the background job to foreground
    time <command>      # Builtin: Execution time
    wait                # Builtin: Wait all background jobs to finish
    sleep <num>         # wait <num> seconds before continuing
    yes                 # Always yes

6.3.2 Variable

    var=value           # Variables, NO <SPACE>
    export VAR=value    # Environment variable to child, NO <SPACE>
    ${#var}             # Length of var

    list=(a b c)        # List
    ${list[@]}          # All elements in list


    read <var>          # Read from input and assign it to <var>
    let <var> = <expr>  # let a result of <expr> 
    declare <var>       # Declare variable and its attribute
Parameter Set and Not NullParameter Set but NullParameter Not Set
${parameter:-word}substitute parametersubstitute wordsubstitute word
${parameter:=word}substitute parameterassign wordassign word
${parameter:?word}substitute parametererror, exiterror, exit
${parameter:+word}substitute parametersubstitute nullsubstitute null
${parameter-word}substitute parametersubstitute nullsubstitute word
${parameter=word}substitute parametersubstitute nullassign word
${parameter?word}substitute wordsubstitute nullerror, exit
${parameter+word}substitute wordsubstitute wordsubstitute null
    ${variable#pattern}     # Remove Smallest Prefix Pattern
    ${variable##pattern}    # Remove Largest Prefix Pattern
    ${variable%pattern}     # Remove Smallest Suffix Pattern    
    ${variable%%pattern}    # Remove Largest Suffix Pattern     

    $0      # The program
    $1      # The first parameter
    $2      # The second parameter
    $#      # The number of parameters
    $      # All parameters in a list

6.3.3 IF Condition

    test expression
    [ expression ]
    [[ expression ]]

6.3.3.1 String

    str1 == str2    # Match
    str1 != str2    # Not match
    str1 < str2     # Less
    str1 > str2     # Greater
    -z str1         # Null
    -n str1         # Not null

6.3.3.2 File

    -a file         # File
    -b file         # Block file
    -c file         # character file
    -d file         # Directory
    -e file         # File
    -f file         # Regular file
    -r file         # Read
    -s file         # Not empty
    -w file         # Write
    -x file         # Execute
    -N file         # File was modified
    -O file         # File belongs to user
    -G file         # File belongs to user group

6.3.3.3 Numbers

    -lt         # Less than
    -le         # Less than or equal
    -eq         # Equal
    -ge         # Greater than or equal
    -gt         # Greater than
    -ne         # Not equal

6.3.4 Input/Output Redirector

    |           # Pipe
    < file      # Redirect input
    > file      # Redirect output
    >> file     # Redirect output and append to a file
    <> file     # uses file as both standard input and standard output
    2>&1        # Redirect error output to standard output
    n<&m        # Redirect input file n to m
    n>&m        # Redirect output file n to m 
    
    cat << EOF # Here document
        Text
    EOF

    tee <file>  # output input to both terminal and a file 

6.3.5 Debug

Run the script

    bash -n scriptname  # Check errors without running
    bash -v scriptname  # Print shell input lines as they are read.
    bash -x scriptname  # Print commands and their arguments as they are executed.

Set options in script

    set -o noexec       # Check errors without running
    set -o verbose      # Print shell input lines as they are read.
    set -o xtrace       # Print commands and their arguments as they are executed.

6.3.6 eval

With eval, bash can print the value of a variable as well as its name In this case, the value of BLACK is a string to control the string’s color The value of COLOR is the string "BLACK"

BLACK='\e[30m'
COLOR=BLACK
eval echo -e '$'{${COLOR}}${COLOR}

6.3.7 Color

    BLACK='\e[30m'
    RED='\e[31m'
    GREEN='\e[32m' 
    YELLOW='\e[33m'
    BLUE='\e[34m'
    PURPLE='\e[35m'
    CYAN='\e[36m'
    WHITE='\e[37m'
    LBLACK='\e[90m'
    LRED='\e[91m'
    LGREEN='\e[92m'
    LYELLOW='\e[93m'
    LBLUE='\e[94m'
    LPURPLE='\e[95m'
    LCYAN='\e[96m'
    LGREY='\e[97m'

    echo -en "${RED}RED"

7 Editor

7.1 Vim

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.

7.1.1 Normal/Visual Mode

Most keymappings both can work in normal and visual mode with slightly difference.

7.1.1.1 Movement

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
<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>)

7.1.1.2 Mark

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

7.1.1.3 Edit and Register

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

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
<C-a/x>     Character-level edit: The first number after the cursor plus/minus 1

Recording-related command

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>

In normal mode, "d/c/y/</>" 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.

d/y         Delete (Cut) / Yank (Copy)
C           Delete (Cut/Change) to the end of the line and enter the insert mode
<           Shift left
>           Shift right
dd/yy       Line-level edit: Delete (Cut) / Yank
cc          Line-level edit: Delete and enter the insert mode
<<          Line-level edit: Shift left
>>          Line-level edit: Shift right

Register-related Command-line mode command

:reg            Show the registers
:messages       Show messages and errors

7.1.1.4 Text Object

[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[/{/(/</"/'/`      # a [\{\( block with [\{\(
i[/{/(/</"/'/`      # inner [\{\( block without [\{\(

7.1.1.5 Keymapings start with ’Z’ and ’z’

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

Quit vim

ZQ          Close and quit vim without saving
ZZ          Save and close the current window

Folding

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

Redraw the window

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

z.          Give spell suggestion 

7.1.1.6 Keymappings start with ’g’

Part of the commands have been listed.

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

7.1.1.7 Window

<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

7.1.1.8 Filter

Filter can lint to other formatters.

!/=             Filter text through an external program 

7.1.2 Insert Mode

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

Most commands in insert mode uses CTRL at first.

7.1.3 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.

:<command>      Run <command> (Enter command-line mode)
Q               Enter Ex mode

7.1.3.2 Substitute

The substitute command is

:[range]s[ubstitute]/<pattern>/<string>/[flags] [count]

It has one repeat single-character command in normal mode.

&               Repeat: The last substitute

7.1.3.3 vimgrep

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

: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

7.1.4 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" >> 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.

7.1.5 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.

7.1.5.1 SpaceVim

SpaceVim 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.

7.1.5.2 LunarVim

LunarVim, 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/‘.

7.1.5.3 NvChad

NvChad 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.

7.1.5.4 Doom-nvim

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.

7.2 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

  • linter (default installation)
  • filemanager
  • wc
  • quickfix

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

7.2.1 Configuration

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

{
  // 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"
      },
}

8 Version Control

8.1 git

8.1.1 Config

git always uses ‘–global‘ option to config for all repos.

git config --global user.name <name>    # Set user name
git config --global user.email <email>@gmail.com
                                        # Set user email

git config --global http.proxy <proxy>  # Set proxy of http to <proxy>
git config --global https.proxy <proxy> # Set proxy of https to <proxy>
git config --global --unset http.proxy  # Unset the http.proxy

git config --global core.editor <editor>
                                        # To set your editor:

git config --global diff.tool vimdiff   # Set vimdiff as the tool to edit diff

subsection Commit

git init                            # Initialize an empty repo
git init --bare                     # Initialize a bare repo. It is useful for the dotfile projcet
git status                          # Show the changed and unstaged files
git add <file>                      # Add(Stage) <file>
git reset <file>                    # Remove <file> from the stage
git reset --hard                    # Remove all uncommitted changes
git rm <file>                       # Removes <file> from both git and system
git rm --cached                     # Removes <file> from git
git commit                          # Commit staged file, it opens an editor
git commit -m "<msg>"               # Commit with message <msg>
git commit --amend                  # Edit previous commit message

git log                             # Show the comment log
git log --oneline                   # Show the commit log in one line

git tag                             # List all tags
git tag -a v1.0 -m "msg"            # Create an annotated tag
git show <tag>                      # Show the description of <tag>
git tag --delete <tag>              # Delete the tag

git rebase -i <commit_id>           # Rebase commits from <commit_id> 

8.1.2 Branch

git branch                          # List branches 
git branch -a                       # List local and remote branches
git branch <branch>                 # Create branch
git branch -d <branch>              # Delete <branch>
git branch -m <new-name>            # Rename the branch

git checkout <branch>               # Checkout <branch>
git checkout <branch> <file>     # Checkout (copy) the file in <branch> to this branch
git merge <branch>                  # Merge <branch> to the current branch

git diff                            # Differences (unstaged files) between now and HEAD
git diff <other> <branch> -- <file>
                                    # Differences between the same file in <other> and <branch>
git diff -cached                    # Differences between staged files and HEAD
git difftool <branch> <file>        # Use difftool (e.g., vimdiff) to open and edit the file

git stash                           # Save uncommitted changes into stash
git stash push -m "<msg>"           # Stash changes with a message:
git stash list                      # List all the stashed changes:

git stash pop                       # Pop changes from stagh

8.1.3 Remote

git remote add <remote> <link>      # Add a remote reposiory named as <remote> 
git remote                          # Show remote
git remote -v                       # Show more details about the remote 
git remote rm <remote>              # Remove a remote repository
git remote set-url <remote> <link>  # Change URL to <link> for <remote>

git clone <link> <path>             # Clone a remote repo to local <Path>

# The following commands require git-remote-add
git push                            # Push this branch to the remote origin repo
git push <remote> <remotebranch>:<localbranch>
                                    # Push <localbranch> to the <remotebranch> from the <remote> repo
git fetch                           # Fetch remote to the branch
git pull                            # Fetch and merge
git pull <remote> <remotebranch:<localbranch>
                                    # Pull <remotebranch> from <remote> to <localbranch>

8.1.4 Submodule

git submodule update --init --recursive                 # Update all submodules:

# git command for prompt in shell
git status --short | wc -l          # Get the number of modified file in git
git branch --show-current           # Show the name of current branch
git rev-list --count @{upstream}..HEAD  
                                        # Count commits that local branch have but upstream does not 

9 Server

9.1 Termux

Termux is an open-source Linux emulator in android. It uses pkg as the package manager. By downloading packages, Termux supports network servers.

9.1.1 ssh

ssh in Termux uses 8022 port by default. To connect it, use ssh -p 8022 <username>@<IP>


10 Network

10.1 iw

iw is a configuration tool for mac80211 in Linux kernel with netlink The code tree of iw.c in iw is

  • main
    • version
    • nl80211_init
      • nl_socket_alloc
      • nl_socket_free
      • nl_socket_set_buffer_size
    • usage
      • __usage_cmd
      • usage_options
    • __handle_cmd
      • error_handler
      • finish_handler
      • ack_handler
      • register_handler
      • valid_handler
      • phy_lookup
    • phy_lookup
    • nl80211_cleanup
  • TOPLEVEL
    • print_help
  • handle_cmd
    • __handle_cmd
  • usage_cmd
    • __usage_cmd

10.2 Clash

clash is a tunnel in Go.

10.2.1 Installation

openSUSE contains clash in its repository, so it can be downloaded directly

sudo zypper in clash

Debian repository does not contain clash, so it can be downloaded from [Github release](https://github.com/Dreamacro/clash/releases). It also can be downloaded in command. As an example

wget https://github.com/Dreamacro/clash/releases/download/v1.18.0/clash-linux-amd64-v1.18.0.gz mv clash-linux-amd64-v1.18.0.gz clash

10.2.2 Basic Usage

If clash is run in the user space, copy the config.yaml file to ~/.config/clash/ directory and run

clash

Clash will download the Country.mmdb file by itselef and load the configuration in ~/.config/clash/.

10.2.3 Autostart

Clash support auto-start after opening the system. In openSUSE, the download version of clash has a systemd service with /lib/system/system/clash.service 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 /etc/clash/ by default. So move the configuration file and mmdb file in the above directory by

sudo mv /path/to/config/file /etc/clash/ sudo mv /path/to/Country.mmdb /etc/clash

Then, enable and start clash service

systemclt enable clash systemclt start clash

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

10.3 Clash for LAN

Clash can support connection from devices in the local area network (LAN). To enable it, just edit the config.yaml file and set the allow-lan to true. Then open clash with manual

clash -d ~/.config/clash/

10.4 snapdrop.net

snapdrop 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.


11 SDR

11.1 GNURadio Period transmisstion

11.1.1 Introduction

Period transmission in GNURadio/USRP platform is the basic function to support time-related systems, such as

  • Time delay measurement between multiple USRPs
  • Time synchronization in designing distributed MIMO systems
  • TX/RX switch at the same antenna
  • Feedback design

The period transmission is based on burst transmission with "tx_time" tag. All the functions have been tested on USRP N310 with GNURadio 3.7.13 and UHD 3.15.

11.1.2 GNURadio Tag

GNURadio tag is an isosynchronous data that runs parallel to the main data stream.

uhd_sink block supports two tags "tx_sob" and "tx_eob" for burst transmission. "tx_sob" tag means "start of burst" that should be added into the first sample of a frame burst. "tx_eob" means "end of burst" that should be added into the last sample. If UHD receives "tx_eob", the TX mode of USRP will be done, until it receives a "tx_sob" tag. The "tx_sob" and "tx_eob" value should simply be PMT_T. As an example, user can use ‘add_item_tag‘ provided by GNURadio to add the "tx_sob" tag in C++.

add_item_tag(0, // Port number
             nitems_written(0) + i, // Offset
             pmt::mp("tx_sob"), // Key
             pmt::PMT_T // Value
        );

In the above code, the "tx_sob" tag will be added at port 0 with nitems_written(0) + i offset. Note that add tag can also in python.

Please refer to this page for a detail description about GNURadio tag.

The third important tag is "tx_time" which is a PMT encoded tuple with two components. The first item in the tuple is the PMT encoded uint64 epoch time in seconds. The second item in the tuple is the PMT encoded double fractional epoch time. The following example can be used to transfer the time from double to a PMT tuple in C++.

double d_next_time = 1.0;
uint64_t t_int = (uint64_t)d_next_time;
double t_double = d_next_time - t_int;
pmt::pmt_t tstamp_tuple = pmt::make_tuple(pmt::from_uint64(t_int), pmt::from_double(t_double));

The "tx_time" tag will be added at port 0 with nitems_written(0) + i offset.

add_item_tag(0, // Port number
             nitems_written(0) + i, // Offset
             pmt::mp("tx_time"), // Key
             tstamp_tuple // Value
        );

Note that if the user directly add the "tx_time" tag with the offset is zero, the USRP will have a bug with unknown reason that the first two burst frames are not sent with the predefined time by "tx_time".

With the help of the above tags, the user can control the transmit time of a burst frame with a fix length, so it can be used to implement period transmission.

11.1.3 USRP Time Control

The last things is to set the time of USRP with gr-uhd, if the time has error, you may get a "L" error in the transmitter. "L" means a late packet in the TX chain. More details please refer to System Configuration for USRP X3x0 Series.

The following code snapshot is used for time setting for both the USRP source and sink in python API.

# Set time to 0 for each USRP
self.uhd_usrp_sink_0.set_time_next_pps(uhd.time_spec(0.0))
self.uhd_usrp_source_0.set_time_next_pps(uhd.time_spec(0.0))

time.sleep(1) # Wait for the PPS signal

# USRP sink sends at time 2.0
# USRP source receives at time 1.0
# This time can be set to any other times
self.uhd_usrp_sink_0.set_start_time(uhd.time_spec(2.0))
self.uhd_usrp_source_0.set_start_time(uhd.time_spec(1.0))

12 Input Method

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

sudo zypper in fcitx5

This command will install a GUI configuration tool fcitx5-configtool. The chinese input method can be chosen from it.