Disable IBus embed preedit text via dbus-send

dbus-send --bus="`ibus address`" --print-reply \
    --dest=org.freedesktop.IBus \
    /org/freedesktop/IBus \
    org.freedesktop.DBus.Properties.Set \
    string:org.freedesktop.IBus string:EmbedPreeditText variant:boolean:false

Over!

Linux simple source policy routing

Dual network connections
eth0:
Address: 192.168.0.2
NetMask: 255.255.255.0
Gateway: 192.168.0.1

eth1:
Address: 192.168.1.2
NetMask: 255.255.255.0
Gateway: 192.168.1.1

Routing policy
* Transmit via eth0 when source address is 192.168.0.2
* Transmit via eth1 when source address is 192.168.1.2

Commands

# eth0
ifconfig eth0 192.168.0.2/24 up
ip rule add from 192.168.0.2 table 251
ip route add default via 192.168.0.1 dev eth0 src 192.168.0.2 table 251
 
# eth1
ifconfig eth1 192.168.1.2/24 up
ip rule add from 192.168.1.2 table 252
ip route add default via 192.168.1.1 dev eth1 src 192.168.1.2 table 252

Over!

Configuring Bonding Manually via Sysfs

Configuring Bonding Manually via Sysfs
------------------------------------------

	Starting with version 3.0.0, Channel Bonding may be configured
via the sysfs interface.  This interface allows dynamic configuration
of all bonds in the system without unloading the module.  It also
allows for adding and removing bonds at runtime.  Ifenslave is no
longer required, though it is still supported.

	Use of the sysfs interface allows you to use multiple bonds
with different configurations without having to reload the module.
It also allows you to use multiple, differently configured bonds when
bonding is compiled into the kernel.

	You must have the sysfs filesystem mounted to configure
bonding this way.  The examples in this document assume that you
are using the standard mount point for sysfs, e.g. /sys.  If your
sysfs filesystem is mounted elsewhere, you will need to adjust the
example paths accordingly.

Creating and Destroying Bonds
-----------------------------
To add a new bond foo:
# echo +foo > /sys/class/net/bonding_masters

To remove an existing bond bar:
# echo -bar > /sys/class/net/bonding_masters

To show all existing bonds:
# cat /sys/class/net/bonding_masters

NOTE: due to 4K size limitation of sysfs files, this list may be
truncated if you have more than a few hundred bonds.  This is unlikely
to occur under normal operating conditions.

Adding and Removing Slaves
--------------------------
	Interfaces may be enslaved to a bond using the file
/sys/class/net//bonding/slaves.  The semantics for this file
are the same as for the bonding_masters file.

To enslave interface eth0 to bond bond0:
# ifconfig bond0 up
# echo +eth0 > /sys/class/net/bond0/bonding/slaves

To free slave eth0 from bond bond0:
# echo -eth0 > /sys/class/net/bond0/bonding/slaves

	When an interface is enslaved to a bond, symlinks between the
two are created in the sysfs filesystem.  In this case, you would get
/sys/class/net/bond0/slave_eth0 pointing to /sys/class/net/eth0, and
/sys/class/net/eth0/master pointing to /sys/class/net/bond0.

	This means that you can tell quickly whether or not an
interface is enslaved by looking for the master symlink.  Thus:
# echo -eth0 > /sys/class/net/eth0/master/bonding/slaves
will free eth0 from whatever bond it is enslaved to, regardless of
the name of the bond interface.

Changing a Bond's Configuration
-------------------------------
	Each bond may be configured individually by manipulating the
files located in /sys/class/net//bonding

	The names of these files correspond directly with the command-
line parameters described elsewhere in this file, and, with the
exception of arp_ip_target, they accept the same values.  To see the
current setting, simply cat the appropriate file.

	A few examples will be given here; for specific usage
guidelines for each parameter, see the appropriate section in this
document.

To configure bond0 for balance-alb mode:
# ifconfig bond0 down
# echo 6 > /sys/class/net/bond0/bonding/mode
 - or -
# echo balance-alb > /sys/class/net/bond0/bonding/mode
	NOTE: The bond interface must be down before the mode can be
changed.

To enable MII monitoring on bond0 with a 1 second interval:
# echo 1000 > /sys/class/net/bond0/bonding/miimon
	NOTE: If ARP monitoring is enabled, it will disabled when MII
monitoring is enabled, and vice-versa.

To add ARP targets:
# echo +192.168.0.100 > /sys/class/net/bond0/bonding/arp_ip_target
# echo +192.168.0.101 > /sys/class/net/bond0/bonding/arp_ip_target
	NOTE:  up to 16 target addresses may be specified.

To remove an ARP target:
# echo -192.168.0.100 > /sys/class/net/bond0/bonding/arp_ip_target

To configure the interval between learning packet transmits:
# echo 12 > /sys/class/net/bond0/bonding/lp_interval
	NOTE: the lp_inteval is the number of seconds between instances where
the bonding driver sends learning packets to each slaves peer switch.  The
default interval is 1 second.

Example Configuration
---------------------
	We begin with the same example that is shown in section 3.3,
executed with sysfs, and without using ifenslave.

	To make a simple bond of two e100 devices (presumed to be eth0
and eth1), and have it persist across reboots, edit the appropriate
file (/etc/init.d/boot.local or /etc/rc.d/rc.local), and add the
following:

modprobe bonding
modprobe e100
echo balance-alb > /sys/class/net/bond0/bonding/mode
ifconfig bond0 192.168.1.1 netmask 255.255.255.0 up
echo 100 > /sys/class/net/bond0/bonding/miimon
echo +eth0 > /sys/class/net/bond0/bonding/slaves
echo +eth1 > /sys/class/net/bond0/bonding/slaves

	To add a second bond, with two e1000 interfaces in
active-backup mode, using ARP monitoring, add the following lines to
your init script:

modprobe e1000
echo +bond1 > /sys/class/net/bonding_masters
echo active-backup > /sys/class/net/bond1/bonding/mode
ifconfig bond1 192.168.2.1 netmask 255.255.255.0 up
echo +192.168.2.100 /sys/class/net/bond1/bonding/arp_ip_target
echo 2000 > /sys/class/net/bond1/bonding/arp_interval
echo +eth2 > /sys/class/net/bond1/bonding/slaves
echo +eth3 > /sys/class/net/bond1/bonding/slaves

See also: https://www.kernel.org/doc/Documentation/networking/bonding.txt
Over!

一个简单、轻量的 Linux 协程实现

HevTaskSystem 是一个简单的、轻量的多任务系统(或称协程),它工作于 Linux 平台,I/O event poll 基于 Epoll。

协程其实是一种古老的技术,协程有这么几个特点:
1. 协程是一个并发运行的多任务系统,一般由一个操作系统线程驱动。
2. 协程任务元数据资源占用比操作系统线程更低,且任务切换开销小。
3. 协程是任务间协作式调度,即某一任务主动放弃执行后进而调度另外一任务投入运行。

与异步、非阻塞式I/O模型类似,协程技术同样适用于处理海量的并发I/O任务,而且还不会像异步方式使业务代码逻辑支离破碎。

基本信息
HevTaskSystem 目前开放了四个类:HevTaskSystem、HevTask、HevTaskPoll 和 HevMemoryAllocator。
HevTaskSystem 是协程任务系统,管理、调度众多的 HevTask 实例运行。由单一操作系统线程驱动,多个线程可并行驱动多套任务系统。
HevTask 是协程任务,实例可加入某一 HevTaskSystem 中调度运行。
HevTaskPoll 是提供了 poll 兼容的系统调用。
HevMemoryAllocator 是一个内存分配器接口,其后端有两套实现:
* 原始分配器,等价于 malloc/free。
* Slice 分配器,按分配大小限量缓存的分配器,缓存替换算法是 LRU。

Public API
TaskSystem – hev-task-system.h
Task – hev-task.h
TaskPoll – hev-task-poll.h
MemoryAllocator – hev-memory-allocator.h

简单示例
该示例演示了在主线程上运行一个协程任务系统,并创建两个独立的协程任务,分别以不同的优先级运行各自的入口函数。各自的入口函数中各循环2次,每次打印一个字符串并 yield 释放CPU 触发调度切换。

/*
 ============================================================================
 Name        : simple.c
 Author      : Heiher <r@hev.cc>
 Copyright   : Copyright (c) 2017 everyone.
 Description :
 ============================================================================
 */
 
#include <stdio.h>
 
#include <hev-task.h>
#include <hev-task-system.h>
 
static void
task_entry1 (void *data)
{
        int i;
 
        for (i=0; i<2; i++) {
                printf ("hello 1\n");
                /* 主动放弃执行,yield 函数会触发重新调度选取另一任务投入执行 */
                hev_task_yield (HEV_TASK_YIELD);
        }
}
 
static void
task_entry2 (void *data)
{
        int i;
 
        for (i=0; i<2; i++) {
                printf ("hello 2\n");
                hev_task_yield (HEV_TASK_YIELD);
        }
}
 
int
main (int argc, char *argv[])
{
        HevTask *task;
 
        /* 在当前线程上初始化 task system */
        hev_task_system_init ();
 
        /* 创建一个新的 task,栈空间采用默认大小 */
        task = hev_task_new (-1);
        /* 设置该 task 的优先级为 1 */
        hev_task_set_priority (task, 1);
        /* 将该 task 放入当前线程的 task system中,任务人口函数为 task_entry1
         * task_entry1 并不会在 hev_task_run 执行后立即调用,需等到该 task 被调度。
         */
        hev_task_run (task, task_entry1, NULL);
 
        task = hev_task_new (-1);
        hev_task_set_priority (task, 0);
        hev_task_run (task, task_entry2, NULL);
 
        /* 运行当前线程上相关的 task system,当无任务可调度时该函数返回 */
        hev_task_system_run ();
 
        /* 销毁当前线程上相关的 task system */
        hev_task_system_fini ();
 
        return 0;
}

Over!

Windows 7 有线局域网组播接收丢包调试

一有线局域网实时流媒体组播传输应用从 Windows 10 迁移至 Windows 7 平台后,迁移后传输质量下降明显。

对比实验发现在同一发送端的同一组播窗口中,运行在 Windows 7 系统上的接收端效果明显劣于 Windows 10 接收端。

分析接收端的收到的数据包发现,Windows 7 平台的接收端存在明显的丢包现象。于是排查了这两个方面:
1. Win7 网卡驱动较 Win10 较旧。
2. Socket 默认接收缓冲区是否太小。

针对第1点,在将 Win7 网卡驱动升级至最新后无明显改善。:(
针对第2点,显式设置了接收缓冲区为 1MB 后,接收质量得到明显改善。:)

Over!

用龙芯EJTAG硬件断点优化Linux ptrace watch性能

在MIPS标准的协处理器0(CP0)中定义一组硬件watchpoints接口,由于某些原因,龙芯3系列处理器并未实现,这就导致了在该架构Linux系统中用gdb watch只能使用软件断点,真心非常、非常慢。:(

好消息是龙芯3系列处理器是实现了MIPS EJTAG的,兼容2.61标准,那么能否利用MIPS EJTAG的硬件断点功能部件实现Linux ptrace的watchpoints功能呢?答案是肯定的。让我们一起看看具体的方法吧。

首先,我们需要更改BIOS中的异常处理函数,将EJTAG调试异常重新路由至Linux内核中处理,因为MIPS EJTAG异常处理程序的入口地址固定为0xbfc00480

         /* Debug exception */
         .align  7           /* bfc00480 */
         .set    push
         .set    noreorder
         .set    arch=mips64r2
         dmtc0   k0, CP0_DESAVE
         mfc0    k0, CP0_DEBUG
         andi    k0, 0x2
         beqz    k0, 1f
          mfc0   k0, CP0_STATUS
         andi    k0, 0x18
         bnez    k0, 2f
          nop
 1:
         mfc0    k0, CP0_EBASE
         ins     k0, zero, 0, 12
         addiu   k0, 0x480
         jr      k0
          dmfc0  k0, CP0_DESAVE
 2:
         la      k0, 0xdeadbeef
         dmtc0   k0, CP0_DEPC
         dmfc0   k0, CP0_DESAVE
         deret
         .set    pop

这段处理程序实现了两个功能:
1. 将来自用户态的sdbbp指令触发的异常路由至地址 0xdeadbeef。
2. 将来自内核态的sdbbp指令触发的异常或是任意态的非sdbbp触发的异常路由至 ebase+0x480。

接着,我们还需要修改内核,实现下列功能:
1. 实现 EJTAG watch 相关的 probe、install、read、clear 等操作,及合适的调试异常处理程序。
2. 实现 Linux ptrace watch 接口与 EJTAG watch 的对接。

See: https://github.com/heiher/linux-stable/commits/ejtag-watch-4.9

Over!

FSH – 助你接入私有网络中的 Linux 终端

Linuxer! 同事、朋友有技术问题需要你远程协助,可是双方计算机都连接在私有网络中怎么办?FSH 能助你接入私有网络中的 Linux 终端。

FSH 是采用服务器中转来穿透 NAT 的一种连接远程 Linux 终端的方案,服务端、客户端的源代码都是开放的,托管在 GitHub 上。

如何编译?

git clone git://github.com/heiher/hev-fsh
cd hev-fsh
git submodule init
git submodule update
make

如何使用?
公共转发服务:222.92.8.138:81

被控端

# 登录模式(root 用户运行)
bin/hev-fsh -s 222.92.8.138 -p 81
 
# 当前用户模式
bin/hev-fsh -s 222.92.8.138 -p 81
 
# 指定用户模式,如 nobody 用户(root 用户运行)
bin/hev-fsh -s 222.92.8.138 -p 81 -u nobody

主控端

bin/hev-fsh -s 222.92.8.138 -p 81 -c TOKEN

自建转发服务端

bin/hev-fsh -a 0.0.0.0 -p 端口
 
# 指定 LOG 文件
bin/hev-fsh -a 0.0.0.0 -p 端口 -l /var/log/fsh.log

Over!

优化 ibus-table 性能

ibus-table 是 Python 语言实现的 ibus 输入法框架的码表引擎,ibus 的绝大多数形码输入法使用该引擎,如郑码、五笔等等。

使用过该引擎的用户或多或少有这样的感觉,就是反应慢,尤其在低性能的计算机上感觉格外明显。无需复杂的性能分析工具,仅用 top 命令就不难发现,用一个约有20万条记录的郑码码表,在连续输入中文时,ibus-table 进程的CPU使用率几乎100%,这还是在一个 i3 2.5GHz 的 PC 平台上。那么在一个更低性能的平台上,输入体验可以想象。

再通过 pref 工具跟踪可以发现,在连续输入时,大部分CPU使用主要来自于 sqlite 数据库查询操作和候选词排序。在阅读引擎代码后,我做了一个实验,在 tabsqlitedb.py 的 select_words 中删除掉 sqlite 查询与排序,返回静态记录。结果CPU使用率降低到了只有5%左右。

因此,给 select_words 加个缓存应该是个不错的选择,就用 HashMap 来实现这个缓存,按键输入作为 key,排序后的结果作为 value。结果很明显,连接输入中文时的进程CPU使用率从几乎100%下降到了10%。

已经合并至 1.9.18: https://github.com/kaio/ibus-table/releases/tag/1.9.18

Over!

解决小米4电信4G版刷LineageOS信号问题

小米4电信4G版 LineageOS 官方版本存在两类网络信号相关的问题:
1. 电信 CDMA 卡无信号。
2. 电信 CDMA 4G卡只能使用 LTE 网络,无法接打电话、收发短信。

解决方法
刷入官方 ROM 后,在 recovery 中挂载 /system,然后编辑 /system/build.prop 文件:

# 文件中原有此行配置,将值修改为 22
ro.telephony.default_network=22
# 额外增加以下三行
ril.subscription.types=NV,RUIM
persist.radio.force_on_dc=true
persist.omh.enabled=true

Over!