DOS 内存粗解

今天搞明白了,为啥 dos 有个 A20 地址线,以及 DOS 所谓高位内存的技术了。原因出在那个段地址的计算上面,经常看到的段的计算方式,实际上不止可以访问到 1M 的内存,而是 1M 再多一些:

0xffff * 16 + 0xffff

可以访问到比 1M 高一点的 64k 内存。实际上不是 64k,而是 64k-16 字节。因为 ffff:0010 就是 1M

比较早的 DOS 程序,会利用 8086 的 bug,访问这段内存实际上是访问 0000:0000 这一段内存。后来 80286 出现,这个 bug 就失效了。

由此引申出 DOS 内存的几个概念。

类型:LinuxApp,创建时间:Oct. 18, 2022, 11:32 p.m. 点击查看完整内容。。。
Qt Quick 编译器简介

Qt 6.3 重镑发布了新的 Qt Quick 编译器,号称性能至少有 30% 的提升,能够以接近 native 的速度运行 Qt Quick 程序。我觉得这是一个在工程上相当漂亮的技术,所以在此做了一个介绍。

其基本原理是改造 QML 语言,现在已经不是一个纯粹的 JavaScript 了,而是类似于 TypeScript,能够在变量声明、函数参数、函数返回值添加类型标志。有了类型以后,Qt 提供了两个部件也就顺理成章了:

  1. QML 脚本编译器qmlsc,负责把 JavaScript 脚本编译成 C++ 代码。
  2. QML 类型编译器qmltc,负责把 QML 文档编译成 C++ 代码。

脚本编译器仍然不能完整翻译动态的 JavaScript 语法,但是能够准确地识别其中 QML 类型的属性访问,算术指令和 ifelse 判断,循环等等结构并翻译成 C++. 其它的仍然被翻译成字节码供 QML 虚拟机解释执行或者 JIT. 目前脚本编译器暂时只对 Qt Device Creation 商业用户开放。普通的开源用户,仍然只能使用自 Qt 5.8 以来的qmlgencache.

而类型编译器,则能够比较准确地把 QML 文档翻译成 C++ 代码,目前这个 QML 类型编译器已经向所有 Qt 6.3 用户开放了。

类型:C++ & Qt4,创建时间:April 13, 2022, 12:03 a.m. 点击查看完整内容。。。
在 openSUSE 底下跨平台编译 mingw64 程序

在 openSUSE Leap 15.3 底下跨平台编译 mingw64 程序,只要安装跨平台编译的安装包就行了:

sudo zypper in mingw64-cross-gcc-c++

接下来我们就来操作一下:

// main.c
#include <stdio.h>
void main() { printf("hello, world!\n"); }

然后运行:

$ x86_64-w64-mingw32-gcc -o test003.exe main.c
$ wine ./test003.exe

可以看到打印出结果。

类型:LinuxApp,C++ & Qt4,创建时间:March 8, 2022, 9:01 p.m. 点击查看完整内容。。。
激活 Python 虚拟环境

使用 Python 开发的朋友们应该都知道 virtualenv 和 venv 创建虚拟环境了吧。

使用虚拟环境不会破坏 Python 的系统环境,也方便了布署,实在是非常好的编程实践。比较常用的几个 IDE,比如 PyCharm 和 Visual Studio 对虚拟环境的支持都不错。创建工程的时候可以选择一起创建虚拟环境,或者在 IDE 里面点几下搞定。实在非常方便。终端下则是 .env/bin/activate 激活。

不过虚拟环境要怎么布署呢。还有什么小技巧大家不知道的呢。本文跟大家分享使用 activate_this.py 和检测 python 解释器的两种小技巧。

类型:Python,创建时间:July 8, 2020, 12:23 p.m. 点击查看完整内容。。。
安装与编译最简 windows qt

Qt 为 windows 提供了一个在线安装包,以及一个巨大的离线安装包。使用在线安装包能够自由选择 Qt 版本。使用离线安装包可以在不需要网络地方或者在多台机器上使用。

但是两个安装器安装的 Qt 容量都太过于巨大了,包含了所有的 Qt 模块以及它们的 debug 信息。如果我们只使用 C++ 以及 QtWidgets 做 Qt 开发,就没必要安装那么多的组件,浪费空间。这时候可以考虑自己编译一下 Qt

类型:C++ & Qt4,创建时间:June 11, 2020, 11:48 a.m. 点击查看完整内容。。。
如何存储密码(KDF)

在线系统经常需要存储用户名和密码等认证信息,以便在用户登录的时候认证密码。但存储密码的时候其实有很多学问。在原始的互联网时期,使用明文存储密码。在经历了多次严重的泄露事件以后,没过几年即使是最蠢的程序员都知道得在存储前使用 MD5 哈希一下。

现在我们已经知道使用 MD5 存储也不靠谱了。拿着 MD5 哈希后后的一串代码放到搜索引擎里面搜一下(彩虹表攻击),密码就出来了。对抗这种攻击的办法是给密码加盐,就是每次哈希前都带上一段随机字符串,并且和密码一起存储起来,这大大提高了破解的难度,即使你使用的是 123456 这么简单的密码,也不容易一眼就看出来了。

类型:Python,C++ & Qt4,创建时间:Aug. 9, 2018, 11:11 p.m. 点击查看完整内容。。。
静态编译 Qt 简单教程

跟我打交道过的人都知道我一直在唱衰桌面端 Qt,但是又一直在推荐大家使用 Qt 作为服务端开发的标准库。服务端开发除了完成功能之外,还需要考虑到服务端运维。一般希望布署的程序越简单越好,只好不依赖于特定的系统,一个文件复制到服务端就搞定。这时候静态编译就用上了。

简而言之,静态编译 Qt 不过是使用特殊的参数配置 Qt 而已:

./configure -release -opensource -static -no-gui -no-icu -no-glib -no-iconv -nomake examples

更详细的步骤请看原文吧。

类型:C++ & Qt4,创建时间:March 8, 2018, 11:07 a.m. 点击查看完整内容。。。
bcache 的使用

下午花了一些时间测试 bcache 与 lvm cache 的使用。lvm cache 相对来说功能比较丰富,能够跟 raid1 一起组 lv,而 bcache 就只能简单地处理 cache。从安全性与性能的角度来看,我倒觉得 bcache 更为专业一些。接下来说一下 bcache 的基本使用:

首先要安装 bcache-tools

# zypper install bcache-tools

由两个设备创建 bcache 是很简单的事,假设 sda 是 ssd,而 sdb 是 hdd,

# make-bcache -w 4k -b 2m -C /dev/sda -B /dev/sdb

其中的-w参数指定底层设备的簇大小,而-b参数指定 bcache 管理的块大小。-C指定 cache 设备,-B指定 backend 设备。如果有多个 backend 设备可以写多个。

类型:LinuxApp,创建时间:Nov. 17, 2017, 2:50 p.m. 点击查看完整内容。。。
Linux 下超频 Ryzen 1700

下载与简单使用 ZenStates-Linux:

$ git clone https://github.com/r4m0n/ZenStates-Linux.git
$ cd ZenStates-Linux
$ sudo ./zenstates.py -l

上面这条命令会输出当前的 pstate 列表。正常可以看到 ryzen 1700 的 p0 是 3.0GHz

$ sudo ./zenstates.py -p 0 -f 94

上面这个命令设置 p0 state 的频率是 3.7GHz

类型:LinuxApp,创建时间:Nov. 14, 2017, 11:43 a.m. 点击查看完整内容。。。
怎么样在 virtualenv 里面使用 PyQt

PyQt 现在还不支持从pip下载安装,习惯virtualenv开发的时候会比较麻烦,总不能为了一个 PyQt 就放弃了virtualenv吧。

有多种方案可以实现这个目标。我这里从源代码开始安装 PyQt,好像是不同的项目可以使用不同的版本。编译的时候我只编译了QtCore, QtGui, QtWidgets三个模块。

具体的步骤与命令看正文吧。

类型:Python,C++ & Qt4,创建时间:May 5, 2017, 10:23 a.m. 点击查看完整内容。。。
谈谈 Qt 程序安装包的大小,以及简要打包指南

经常看到网上有些论调说 Qt 程序无比庞大,甚至拿 .NET 程序来比,说 Qt 程序打包以后跟 .NET 安装包差不多大。由此影响了很多人对 Qt 的选择。我觉得有必要对此做一些澄清——

显然这个说法是错误的!!

很容易理解,虽然 Qt 提供了很多组件,但并非所有的组件都会被程序使用,也并非所有的组件都需要打包到程序安装包里面。以 Qt 5.7 为例,一个可以正常使用的 helloworld.exe 程序未压缩不过 20M,使用 lzma 压缩算法,压缩率 25%,压缩完才 6M!

那盛传的 Qt 上百 M 的容量又是怎么回事呢?

这事从头说起。

类型:C++ & Qt4,创建时间:March 2, 2017, 7:52 p.m. 点击查看完整内容。。。
Windows GDI加速的详细支持情况

自从 Vista 以后,Windows 对于 GDI 加速发生了很大的变化。简单地说,在 Vista 出现时,为了支持 Desktop Window Manager(DWM), GDI 是不加速的。为啥 DWM 不支持 GDI 加速呢。因为 DWM 是使用 DirectX 进行渲染的,它调用 DirectX 将显存里面的两个窗口内容合并渲染出来。不幸地是在 WINXP 的架构里面,GDI 是和 DirectX 分开的,两者没有一致的内存空间。所以 DWM 只好舍弃 GDI 的所有加速功能,让 GDI 程序把内容渲染到内存区域,再把这块内存复制到显存里面进行渲染。Windows 7 做了一些改进,要求驱动程序支持一个特殊的内存区域,能够让 GPU 和 CPU 都同时读取到的内存区域。GDI操作都写入到这个内存区域。这样的话,就不需要再做一次复制了,而且因为那个内存区域也是 GPU 可读的,于是 GDI 又可以支持 GPU 加速了。然而 Windows 7 并不像以前的 GDI 那样子,要求显卡驱动程序支持各种 2D 加速命令,而只要支持 BltBit, AlphaBlend 等几个命令就够了。

类型:C++ & Qt4,创建时间:Jan. 23, 2017, 1:20 p.m. 点击查看完整内容。。。
可以启用 firefox 的多进程模式了

今天我的 opensuse 自动更新了 firefox 48。最重要的变化就是现在有了与 chrome 类似的多进程模式。但是看起来很奇怪,只有两个进程?一个 firefox ui 进程,我为 firefox,一个remote tab 进程,名为 web,居然不是每个 tab 一个进程。。

不管怎么样,总归是件好事,现在 ui 进程不至于卡到暴了。启用的方式是,当然是打开about:config

browser.tabs.remote.autostart改为trueextensions.e10sBlockedByAddons改为false

前者启用多进程,后者当你安装了第三方应用的时候也强制启动多进程。

类型:LinuxApp,创建时间:Aug. 6, 2016, 2:18 p.m. 点击查看完整内容。。。
systemd 的时间控制命令

以前使用 date/hwclock 来调整时间,以及自己弄个 /etc/localtime 的软链接到真正的时区文件里面。现在不用折腾这个了。 systemd 提供了一条命令叫做 timedatectl 处理这些事情。。它接收几条子命令:

  • timedatectl status

    打印出当前的状态。

  • timedatectl set-time [TIME]

    修改当前时间

  • timedatectl set-timezone [TIMEZONE]

    修改当前时区

  • timedatectl list-timezones

    列出所有时区的名字。

  • timedatectl set-local-rtc [BOOL]

    设置硬件时钟是否使用本地时间。一般设置为 0 表示不使用本地时钟。

  • timedatectl set-ntp [BOOL]

    设置是否开启 ntp 同步。使用前需要先安装 ntp

这些命令在 openSUSE 和 CentOS7 下面都测试过可行。

类型:LinuxApp,创建时间:May 3, 2016, 5:50 p.m. 点击查看完整内容。。。
监视redis服务器的数据变化

在某些情况下,我们往redis服务器里面存储了大量的数据。这么大量的数据,我们怎么样看到数据发生了哪些变化呢?新版本的redis提供了事件监听,可以把数据内所有的事件变化都打印出来。它的使用方法很简单。

  1. 首先打开发送数据事件。这个特性会额外消耗CPU,所以一般不要用。推荐使用命令行打开这个功能:

    $ redis-cli
    redis> config set notify-keyspace-events KA
    

    关于参数KA的作用,请见正文。

  2. 开始监听事件。redis-cli会把接下来的所有变化都打印出来。

    redis> psubscribe '__key*__:*'
    
  3. 想要结束了,按Ctrl+C就行。不过似乎也会把redis-cli也直接关掉。最好是重新运行一下redis-cli,然后禁用这个特性:

    redis > config set notify-keyspace-events ""
    
类型:LinuxApp,创建时间:Jan. 26, 2016, 5:38 p.m. 点击查看完整内容。。。
vmware/firefox 在 opensuse 13.2 里面会卡住的问题

最近经常发现 vmware/firefox 在切换页面的时候会卡住一会,导致整个系统没有响应。忘了怎么回事看到这个东西:http://neilstechdocs.blogspot.com/2013/09/fun-with-opensuse-vmware-and-firefox.html,只要禁用 transparent_hugepage 就可以解决问题了。办法是:

echo 0 > /sys/kernel/mm/transparent_hugepage/khugepaged/defrag
echo never > /sys/kernel/mm/transparent_hugepage/defrag

不过我不知道要怎么样把这两条语句优雅地写入到系统启动脚本里面。所以我干脆在内核里面禁用了 transparent_hugepage,开启 yast 的引导加载器配置,在内核参数里面写上:

transparent_hugepage=never

重启搞定。

类型:LinuxApp,创建时间:March 2, 2015, 12:12 a.m. 点击查看完整内容。。。
为什么不要使用QThread

之前我在Python中使用线程的技巧一文中提到,尽量不要在 PyQt 里面使用QThread,但是当时没有给出示例程序。这里补上一个会引起Python崩溃的代码。其实主要原因是QThread被强制关闭的时候会引起Python崩溃。

代码请见正文。

类型:Python,C++ & Qt4,创建时间:Jan. 6, 2015, 5:08 p.m. 点击查看完整内容。。。
安装Trac

Trac是开源世界一个很流行的BUG管理系统。类似的系统还有BugZilla这样的东西。各自详细的特性我还没有做比较。有空再研究一下。

要搭建Trac的话,首先要安装Python。然后下载Trac的安装包,解压之后:

setup.py install

它会自动地下载genshi,所以,虽然INSTALL文件说明了要依赖于genshi这个包,实际上并不需要安装。

安装之后,首先类似于SVN或者MoinMoin那样,创建一个工程项。命令是:

C:\Python26\Scripts\trac-admin.exe testproj initenv

其中testproj是工程名字。

接下来还要创建用户名与密码。因为Trac使用Apache的htpasswd文件,所以必须使用Apache的工具来生成用户名与密码。或者用在线生成器Online password generation and encryption for .htpasswd files生成用户名和密码。密码必须使用SHA1(或者MD5?没有仔细看文档)。把生成的数据填入users.txt里面,每项一行。比如:

goldfish:{SHA}fEqNCco3Yq9h5ZUglD3CZJT4lBs=
panda:{SHA}fEqNCco3Yq9h5ZUglD3CZJT4lBs=

接下来还要给其中一个用户分配管理员权限,命令如下:

trac-admin testproj permission add goldfish TRAC_ADMIN

最后就是启动Web服务器了。Trac可以和各种服务器配合使用,支持mod_wsgi或者fastcgi。不过我这里用最简单的内置的tracd来启动。

tracd --port 8000 --basic-auth "*,users.txt,anything" testproj
类型:LinuxApp,创建时间:Sept. 9, 2014, 1:52 p.m. 点击查看完整内容。。。
使用Qt作为C++的标准库

目前大家都使用cpp的stl和boost作为cpp的标准库。不过个人觉得stl和boost用起来不是很爽。不如用Qt。

很多人觉得Qt这个库太大,而且如果不打算使用Qt的GUI也需要安装一大堆没用的dll。其实这都不是问题,我们可以在编译Qt的时候使用no-gui选项,告诉Qt我们只对它的非GUI部分感兴趣,避免编译与安装大量无用的Qt组件。最终我们可以得到一个

请点击进入正文,查看详细的操作步骤。

类型:C++ & Qt4,创建时间:July 31, 2014, 11:17 a.m. 点击查看完整内容。。。
在OpenSUSE和Ubuntu里面怎么配置一个smb服务器

微软的smb服务与nfs一样,真是一个很好的发明。它们都能够方便地让客户端直接访问文件内容,而不需要把文件内容传回客户端。

因为做服务器的时候我默认使用linux,所以接下来我打算安装一个Samba服务,实现简单的文件共享,要求必须输入密码才能连接到这个服务器。不提供默认用户的使用。其它的如WINS、NETBIOS服务这些东西都不需要,因为我们只需要一个类似于NFS这样的文件系统。

首先当然是安装samba服务。

zypper install samba

接下来修改一个samba服务器的配置文件,把目录共享出来。按照samba书上面的做法,可以有两种方案来提供服务,一是明确定义要共享的目录,并配置好它的路径、权限等信息。另一种做法是配置homes目录,把所有用户的目录都共享出来。我选择了后者。无他,刚好需要而已。

openSUSE果然是个尽职的女仆,安装完samba以后这件事情基本就搞定了。只要我们把goldfish这个系统已有的帐号加入到它的帐号数据库里面。

useradd -m goldfish #添加一个UNIX用户,如果有不用加了。
smbpasswd -a goldfish #添加相同名称的samba用户
systemctl restart smb #重启samba服务

至此,我们可以访问这个共享了。

smbclient --user goldfish //hostname/homes/

Ubuntu的配置稍微麻烦一些,请看正文。

类型:LinuxApp,创建时间:June 19, 2014, 5:54 p.m. 点击查看完整内容。。。