Jul 6, 2019 - Fedora 删除 swap 后修复 Kernel Parameters

笔者近日为自己的笔记本电脑升级到了 32G 内存,就想着删掉 swap 分区,为自己捉襟见肘的 SSD 释放一些空间。参考着 Arch Wiki,整体而言比较顺利,但也有一点小小的插曲。

首先,运行 # lvs 查看分区情况。我的系统里,Volume Group 是 fedora_zhenbo。 删除 swap 分区不需要运行 # umount /<mountpoint> 。相反,运行 swapoff -a 即可。 接下来,删除 LV # lvremove <volume_group>/<logical_volume>,并修改 etc/fstab

可是,重启后,系统并没有正确启动,而是进入了 dracut 环境,提示 fedora_zhenbo/swap 未找到。重新检查了一遍,发现 Kernel parameters 里有一行 rd.lvm.lv=fedora_zhenbo/swap。将其删去后,可以顺利启动。尝试运行 grub2-mkconfig,生成的 grub.cfg 里依旧有 swap。把 /etc/grub.d/ 翻了一遍,也没有任何头绪。

幸运的是,网友 Oren Bell 在 2017 年遇到了一样的问题。LVM 分区被硬编码到了 /etc/default/grub。编辑该文件的 GRUB_CMDLINE_LINUX= 一栏,删掉 rd.lvm.lv=fedora_zhenbo/swap 后重新 grub2-mkconfig -o /boot/efi/EFI/fedora/grub.cfg 即可。

最后,参考 Arch Wiki,把释放出来的空间添加到 home

# lvresize -l +100%FREE --resizefs fedora_zhenbo/home

Oct 26, 2018 - 跟着 clang 的 libcxx 学习二分查找

哪个算法简单到初学编程的人都能轻松实现,但有多年编程经验的人也可能会写出严重的 bug 呢?没错,正是二分查找。既然普通人的二分查找容易写错,那专业人士会如何实现二分查找呢?不妨参考一下 clang 7.0 的实现。

lower_bound 是指在区间 [first, last) 中,对于任意 i < j,若 comp(A[i]) 为真,则 comp(A[j]) 必为真。如下图

lower_bound

让我们看一看 lower_bound 的实现

__lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_, _Compare __comp)
{
    typedef typename iterator_traits<_ForwardIterator>::difference_type difference_type;
    difference_type __len = _VSTD::distance(__first, __last);
    while (__len != 0)
    {
        difference_type __l2 = __len / 2;
        _ForwardIterator __m = __first;
        _VSTD::advance(__m, __l2);
        if (__comp(*__m, __value_))
        {
            __first = ++__m;
            __len -= __l2 + 1;
        }
        else
            __len = __l2;
    }
    return __first;
}
// This file is dual licensed under the MIT and the UIUC license.

代码很精简,不到十行,注意几个关键点就不会写错

  1. 定义:first 是第一个有可能为真的元素
  2. 迭代:l2 < len 恒成立,因此 first+l2 就不会越界。同时,每次迭代时 len 严格递减
  3. 迭代结束:l2 == 0 当且仅当 len == 1。这是我们最后一次进行迭代
  4. 特殊情况:如果所有的元素都为假,那最后一次迭代时, ++m 的结果正是 last

相比我之前写的不时丢弃真值、出现死循环的二分查找,clang 的代码可是高到不知道哪里去了。

upper_bound 的实现 看起来是相反的,不过从布尔值的角度看,与 lower_bound 是一样的,我就不复制代码了。

上文中的示意图使用 R 语言绘制,参考了 Stack Overflow 上画棋盘的讨论。代码如下

b <- matrix(nrow=1,ncol=6)            
colorindex <- c(rep(0, 4), rep(1, 2))
# for each square
colors <- c("red", "green")[colorindex+1] # choose colors
side <- 1/8                               # side of one square
ux <- col(b)*side                         # upper x values
lx <- ux-side                             # lower x values
uy <- row(b)*side                         # upper y
ly <- uy-side                             # upper y
plot.new()                                # initialize R graphics
rect(lx, ly, ux, uy, col=colors, asp=1)   # draw the board

最后,按照惯例推荐一本书 Effective C++:改善程序与设计的55个具体做法(第3版)

Sep 15, 2018 - 用 distcc 加快编译 续篇-clang

上一篇文章 简单介绍了使用 distcc 编译 wine 代码。有人在朋友圈里问我,能不能用 clang 编译。我当时的回答是,为什么不能呢?这周在摸鱼的时候,我完成了测试。

理论分析

我看了一下 distcc 的代码,发现其机制还是比较简单的。distcc 后的一个参数会被当成编译器名称。理论上,不管是 gcc 还是 clang,都应该可以用类似的机制在多台电脑间分发。

实战演练

因为这里仅仅是为了测试,而不是实际运行,我就不用麻烦地在 32-bit 和 64-bit下编译 wine 两次了。workflow如下

function mkwine_clang()
{
    export CC="clang-6.0"
    export CXX="clang-6.0"
    export CFLAGS="-O0"
    export JOBS=8
    mkdir -p ~/src/wine_n_extras/wine-clang
    cd ~/src/wine_n_extras/wine-clang
    ../wine/configure --enable-win64
    make -j$JOBS
}

wine 项目组对 clang 投入的精力 是有回报的。我没有做任何额外的设置,就在本机成功编译了 wine

在 Ubuntu 上安装 clang 非常简单。很有趣的是,在我的 Ubuntu 14 工作站上,clang 默认是指向 clang-3.3clang-3.5 的软链接。不过,在工作站和笔记本上,/usr/bin/clang-6.0 都是可用的。因此,我们可以对编译的 workflow 稍加修改

function mkwine_clang()
{
    export CC="distcc clang-6.0"
    export CXX="distcc clang-6.0"
    export CFLAGS="-O0"
    export JOBS=8
    export DISTCC_HOSTS="@beddp,lzo"
    mkdir -p ~/src/wine_n_extras/wine-clang
    cd ~/src/wine_n_extras/wine-clang
    ../wine/configure --enable-win64
    make -j$JOBS
}

在我的电脑上,这一流程非常的顺利。理论分析和实践演练同时成功的情景真是太少了。

In theory, theory and practice are the same. In practice, they are not. -Anonymous

不仅仅是C

上文提到,distcc 判断编译器的方法很简单。那么,能不能用它来分发其他语言呢?很抱歉,这可能不行。dcc_scan_args 函数会尝试解析编译选项。如果要使用其他的编译器,个人猜测,必要条件包括使用与 gccclang 相同的编译选项。[Rust 社区在 2017 年年末进行了讨论](https://users.rust-lang.org/t/contract-opportunity-mozilla-distributed-compilation-cache-written-in-rust/13898),但好像并没有得出太好的解决方案。
不过,这也称不上太大的损失。人生苦短,在 C/C++/Rust 以外,我们也不再需要一门编译超慢的语言了,不是吗?

Creative Commons License
This work is licensed under a Creative Commons Attribution 4.0 International License.