This is a personal blog website that named as Shell Cottage. The blog focuses on Linux platform and wireless network.
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.
Arch | Debian | Fedora | |
---|---|---|---|
Default desktop | - | GNOME | GNOME |
Init system | systemd | systemd | systemd |
Package manager | pacman | apt | dnf |
C library | glibc | glibc | glibc |
Utility | coreutils | coreutils | coreutils |
Installer | CLI | Debian-Installer | Anaconda |
NixOS | Void | Deepin | |
---|---|---|---|
Default desktop | GNOME | xfce | DDE |
Init system | systemd | runit | systemd |
Package manager | Nix | xbps | - |
C library | glibc | musl | glibc |
Utility | coreutils | coreutils | coreutils |
Installer | Calamares | CLI | deepin-installer |
The distributions for embeded devices
Openwrt | Alpine | |
---|---|---|
Init system | init | OpenRC |
Package manager | opkg | apk |
Utility | Busybox | Busybox |
The follow lists common package managers that in different distributions.
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
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
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>
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.
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.
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
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.
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.
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‘.
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
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.
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
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.
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.
KDE | GNOME | xfce | |
---|---|---|---|
Toolkit | QT | GTK | GTK |
Display manager | SDDM | gdm | LightDM |
Session manager | ksmserver | gnome-session | xfce4-session |
Windows manager | KWin | gnome-shell | xfwm4 |
Desktop manager | - | - | xfdesktop |
File manager | Dolphin | Nautilus | Thunar |
Launcher | Kickoff | - | xfce-panel |
Editor | Kate | gnome-text-editor | Mousepad |
Terminal | Konsole | gnome-terminal | xfce4-terminal |
Network | Network Manager | Network Manager | - |
Capturer | Spectacle | GNOME Screenshot | xfce4-screenshooter |
Document viewer | Okular | Evince | - |
Image viewer | Gwenview | Loupe | Ristretto |
Input method | - | - | - |
Advanced setting | - | gnome-tweaks | - |
Development | KDevelop | GNOME Builder | - |
LXQT | DDE | |
---|---|---|
Toolkit | QT | QT |
Display manager | SDDM | LightDM |
Session manager | lxqt-session | dde-session |
Windows manager | Openbox | Treeland |
Desktop manager | - | - |
File manager | PcManFm-qt | dde-file-manager |
Launcher | lxqt-runner | dde-launcher |
Editor | - | deepin-editor |
Terminal | QTerminal | deepin-terminal |
Network | - | - |
Capturer | Screengrab | deepin-screenshot |
Document viewer | - | deepin-reader |
Image viewer | Lximage-qt | deepin-image-viewer |
Input method | - | deepin-im |
Advanced setting | - | deepin-tweak |
Development | - | Deepin-IDE |
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).
Graphicless tests xfce4 in Debian 12. It uses xfce4-terminal and firefox as the default applications for terminal and web browser, respectively.
Openbox | i3 | xmonad | sway | |
---|---|---|---|---|
Protocol | x11 | x11 | Wayland | Wayland |
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"
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.
# 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
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.
Tools to manage Linux.
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
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.
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.
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
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.
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.
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.
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.
All the usage are an example of the *iwlwifi* module.
lsmod
is a command to list all installed module in the kernel.
It contains some information such as name, dependencies, etc.
Usage: lsmod
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.
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.
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
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.
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.
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.
This blog is based on Github page and jekyll.
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
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
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.
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.
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.
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
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
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 Null | Parameter Set but Null | Parameter Not Set | |
---|---|---|---|
${parameter:-word} | substitute parameter | substitute word | substitute word |
${parameter:=word} | substitute parameter | assign word | assign word |
${parameter:?word} | substitute parameter | error, exit | error, exit |
${parameter:+word} | substitute parameter | substitute null | substitute null |
${parameter-word} | substitute parameter | substitute null | substitute word |
${parameter=word} | substitute parameter | substitute null | assign word |
${parameter?word} | substitute word | substitute null | error, exit |
${parameter+word} | substitute word | substitute word | substitute 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
test expression [ expression ] [[ expression ]]
str1 == str2 # Match str1 != str2 # Not match str1 < str2 # Less str1 > str2 # Greater -z str1 # Null -n str1 # Not null
-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
-lt # Less than -le # Less than or equal -eq # Equal -ge # Greater than or equal -gt # Greater than -ne # Not equal
| # 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
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.
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}
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"
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.
Most keymappings both can work in normal and visual mode with slightly difference.
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>)
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
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
[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 [\{\(
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
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
<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
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.
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
% 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
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
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
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.
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.
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.
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/‘.
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.
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 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
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
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" }, }
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>
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
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>
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
iw is a configuration tool for mac80211 in Linux kernel with netlink
The code tree of iw.c
in iw is
clash is a tunnel in Go.
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
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/
.
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.
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/
Period transmission in GNURadio/USRP platform is the basic function to support time-related systems, such as
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.
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.
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))
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.