Fork me on GitHub

Linux环境指定动态链接库路径

目标

我们的目的是:链接这个动态链接库,并放在可执行文件目录下,使可执行文件执行时能找到这个库。

当然。我们最终应该可以将动态链接库放在任何位置,同时保证我们的可执行文件可以找到这些动态链接库。

这对我们组织、打包整个项目相当有帮助。你可以使用命令: ldd <可执行文件名> 看看可执行文件所链接的动态库,及其路径。

创建动态链接库

gcc -shared -fpic x1.o x2.o x3.o -o libqazwsx.so

上面这条命令将 x1.o、x2.0、 x3.o 三个文件打包成一个动态链接库文件 libqazwsx.so

指定位置

下面是我们的核心编译命令

gcc test.o -o test -Wl,-rpath,./ -L./ -lqazwsx

这条命令会告诉可执行文件,他需要的动态链接的位置,这个是我们创建的实验文件目录。

.--test
|-------test.c
|-------x1.c
|-------x2.c
|-------x3.c
|-------test.o
|-------x1.o
|-------x2.o
|-------x3.o
|-------libqazwsx.so

命令解释

现在我们已经有了一个指定了链接位置的动态链接库,来详细解释一下这条命令。

test.o -o testtest.o 与动态库链接并输出可执行文件 test

-Wl,-rpath,./ 告诉链接器,test 在执行时应当在 ./ 下找动态库

-L./ -lqazwsx 告诉链接器,链接时在 ./ 下找动态库

测试代码

// x1.c
#include <stdio.h>
void print_x1 (void) {
    printf("I am x1.o\n");
}
// x2.c
#include <stdio.h>
void print_x2 (void) {
    printf("I am x2.o\n");
}
// x3.c
#include <stdio.h>
void print_x3 (void) {
    printf("I am x3.o\n");
}
//test.c
#include <stdio.h>
extern void print_x1 (void);
extern void print_x2 (void);
extern void print_x3 (void);
int main (void) {
    print_x1();
    print_x2();
    print_x3();
    printf("I am main function\n");
    return 0;
}

这里是完整的编译指令

gcc -c x1.c
gcc -c x2.c
gcc -c x3.c
gcc -c test.c
gcc -shared -fpic x1.o x2.o x3.o -o libqazwsx.so
gcc test.o -o test -Wl,-rpath,./ -L./ -lqazwsx

执行测试

# ??? @ ??? in ~/workspace/cpp [19:18:35]
$ ./test
I am x1.o
I am x2.o
I am x3.o
I am main function

# ??? @ ??? in ~/workspace/cpp [19:18:39]
$ ldd test
linux-vdso.so.1 (0x00007fff755fd000)
libqazwsx.so => ./libqazwsx.so (0x00007f9708264000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f9707ea2000)
/lib64/ld-linux-x86-64.so.2 (0x0000564acd3d3000)

# ??? @ ??? in ~/workspace/cpp [19:22:57]
$ rm libqazwsx.so
rm:是否删除普通文件 'libqazwsx.so'?y

# ??? @ ??? in ~/workspace/cpp [19:23:04]
$ ./test
./test: error while loading shared libraries: libqazwsx.so: cannot open shared object file: No such file or directory

# ??? @ ??? in ~/workspace/cpp [19:23:07] C:127
$ ldd test
linux-vdso.so.1 (0x00007ffda6fdb000)
libqazwsx.so => not found
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f702f741000)
/lib64/ld-linux-x86-64.so.2 (0x000055c80d664000)

可以看到,我们创建的动态链接库放在了可执行文件的同级目录下,这时可执行文件可以找到这个动态链接库。当我们删除了这个库时,可执行文件就因为找不到链接库而无法运行了。

总结

现在,我们知道了指定动态链接库到可执行文件的同级目录下,换言之,我们也可以将库放到其他位置。这样我们可以做到系统的模块化。不同功能的代码封装到不同的动态链接库中,这样可以做到系统的热更新。

Linux内存JDK

目的

把 JDK 放到内存里是个好想法。可以加速 JDK 的调用。而且,我的电脑是固态硬盘,频繁的读写硬盘,会减少固态寿命。所以,我要把 JDK 扔到内存里。不过,固态其实已经很快了,即使把 JDK 放到内存里,速度的提升也感觉不到。

安装工具

# 安装 squashfs-tools
sudo apt install squashfs-tools

# 安装 openjdk
sudo apt install openjdk-8-jdk openjdk-8-jre

squashfs-tools 这个工具可以创建 squash 文件系统,将整个文件系统或者某个单一的目录压缩在一起, 存放在某个设备, 某个分区或者普通的文件中。

我们要做的就是,把 openjdk 的目录压缩到一个文件里,然后挂载到内存里。感觉就是把 JDK 打个包,变成镜像文件,然后挂在到内存。

做些准备

注意:由于 openjdk 的目录里 docs、src.zip 是链接符号,所以我们要先把他们替换成真正的文件。

# 把整个jdk目录复制到主目录下。
sudo cp -r /usr/lib/jvm/java-8-openjdk-amd64 ~/

# 替换文件链接符号为真正的文件
sudo rm -rf ~/java-8-openjdk-amd64/docs ~/java-8-openjdk-amd64/drc.zip
sudo cp -r /usr/share/doc/openjdk-8-jre-headless/ ~/java-8-openjdk-amd64/docs
sudo cp /usr/lib/jvm/openjdk-8/src.zip ~/java-8-openjdk-amd64/src.zip

创建 JDK 镜像

# 创建 squash 文件系统文件
sudo mksquashfs ~/java-8-openjdk-amd64 ~/openjdk-8.sqsh

# 移动到 /usr/lib/jvm 下
sudo mv ~/openjdk-8.sqsh /usr/lib/jvm/

挂载

# 创建目录以供挂载
sudo mkdir /media/memory-jdk-8

修改 /etc/fstab 文件,添加类似以下的一行:

/usr/lib/jvm/openjdk-8.sqsh  /media/memory-jdk-8  squashfs  ro,defaults,loop  0 0

完成。

CDDA大灾变编译安装

CDDA 简述

CDDA 大灾变,是个不错的游戏。你在扮演一个在末世里幸存的一个普通人、探险家、生存狂、科学家……在这个世界里,你可以肆意破化、屠杀丧尸、建造基地……

不过嘛,这是字符终端下的游戏,额,这个画风不是所有人都可以接受的。

获取源码

不要去官网下载代码编译,官网的代码太旧,估计这个网站很久没更新了吧。而且提供的二进制包是 32 位的,一些库的位置和 64 位不一样。

所以,果断点去 GitHub 吧。

git clone https://github.com/CleverRaven/Cataclysm-DDA.git

开始编译

看看 makefile 吧,里面写了编译的方法,以及如何编译中文版本。

make -j4 NATIVE=linux64 RELEASE=1 LUA=1 LANGUAGES=zh_CN

如果报错没有 lua 就对了,想要使用完整的 mod 功能,就要在编译时加上 LUA=1 ,当然,你可以不用 mod。为了使用 mod 功能,就要安装 lua。

apt-get install lua5.3 liblua5.3-dev

这时执行 make 时依然会报错:没有 lua 命令,注意,这里安装的是 lua5.3,所以 lua 命令是 lua5.3。可以使用软链接解决。

ln -s /usr/bin/lua5.3 /usr/bin/lua

踩坑:编译图形界面版

上面的 make 是编译字符版的,编译 SDL 版时,编译成功,但无法运行,运行会给出个错误:libpng warning: iCCP: known incorrect sRGB profile

我不知道咋办,网上有说 png 图片问题,载入重新覆盖就好,我用 Gimp 试了,不行。也罢,字符界面版玩着更高大上。话说,有大神知道如何解决,告诉我一下啊,感激!!

踩坑:astyle报错

make 会使用到 astyle 这个软件,你可以先安装了试试。一般不安装这个,会提示缺少 astyle,但是不影响编译。如果你安装了,可能会无法编译了,这时,卸了 astyle 可以了。

踩坑:中文乱码

cdda 最近更新的版本,编译后可能会出现中文乱码,我当时编译时看了输出,发现没有链接 ncursesw 库,makefile 里现在链接的是 ncursesw6,然而你的系统现在的 ncursesw 可能还是 ncursesw5。现在奉上解决方案:更改 makefile 的第 566 到 572 行如下:把 ncurses 换成 ncursesw 即可

566:ifeq ($(HAVE_PKGCONFIG),1)
567: CXXFLAGS += $(shell pkg-config --cflags ncursesw)
568: LDFLAGS += $(shell pkg-config --libs ncursesw)
569:else
570: ifeq ($(HAVE_NCURSES5CONFIG),1)
571: CXXFLAGS += $(shell ncursesw5-config --cflags)
572: LDFLAGS += $(shell ncursesw5-config --libs)

这样会强制链接 ncursesw 库,不管系统的 ncursesw 版本是多少,不管 makefile 链接的版本是多少,都会链接 ncursesw。强烈建议,没有出现这个问题的,请不要更改 makefile。更改后,如果以后要更新时,请先撤销 makefile 的更改。

博客迁移

第一次写博客

记得第一次写博客还是因为 CDDA 大灾变。当初为了玩这个游戏,花了一天的时间折腾。毕竟 makefile 我用的一直都不熟,我一直都是把 makefile 当作 shell 脚本来写。

在安装这个游戏时,被逼看了大概 500行 makefile 代码。这次应该是我第一次大量的阅读别人的代码。

虽然,我直到现在,依然写不好 makefile,不过,让我看懂一个 makefile 干了啥,还是很轻松的。

从那此开始,我就开始了写博客。写博客最初的目的就是当个记事本,方便日后,有的东西忘了,可以快速找到。这时,我应该是高三,高考最大嘛。于是,就写了几篇,就没在写过了。

这个时候,我的博客都在开源中国上面。

迁移到 Wordpress

大一入学时,买了一台阿里云的 ECS,还买下了 huanggefan.cn 这个域名,嗯嗯嗯,我自己的名字嘛。花了一个月的时间备案了域名,这个域名算是正是开通了。不过,我一直都没有开始部署博客,服务器上唯一的应用是我给学校写的网络报修系统。

到了大一下学期,我部署了 Wordpress。这时,我开始决定,运营一个自己的网站。写博客不再只是记日记了,我决定写一些对自己对别人都有用的内容。

奈何,Wordpress 写作体验确实不如 Markdown。而且,从部署了 Wordpress 我就开始折腾 Wordpress。改主题、安全配置、漏洞填补啥的。博客反而没写几篇。

迁移到 Hugo

现在,我把博客迁移到了 Hugo。还是 Markdown 写的舒服。纯静态网站安全性肯定比 Wordpress 高,性能就不用说了。最重要的是:部署简单、写作体验很棒。

Hugo 的部署真的很简单,直接使用 Nginx 就好。如果想进一步追求性能,可以把 public 目录挂载到 tmpfs。Ubuntu 自带了一个 /dev/shm,在这里面创建目录,然后使用软链接即可。都不用更改 /etc/fatab 文件。

Hugo 生成的静态网站的发布我选择了 Git。本地电脑通过 Git 推送到服务器端,然后 ssh 到服务器,手动执行构建命令。其实这样也不麻烦,没必要写一个自动脚本。ssh 后还可以看看访问日志。当然,直接使用 scp 更简单一些,不过使用 Git 给了自己一个后悔选项不是吗。

未来

说到未来,这个真的很难确定,也许以后还会迁移,不过,以后再迁移,也是换个静态网站生成器罢了,也许我会用 Python 写一个。Hugo 虽然已经很好用了,但是还是满足不了我的所有需求。

现在使用的时别人写的 Hugo 主题,虽然进行了不少修改,不过感觉还是自己写一个更合适。