有必要么?

近期客户提出需要在龙芯(Loongson)硬件环境上支持QQ程序。没听错吧?确实如此。

在国产化大背景下,一些特定的办公环境中需要完全国产化,不允许使用老美或他国的东西,需要将命运掌握在自己手中,这其中的两个最关键的组件就是操作系统和CPU,Windows的各种安全问题屡遭诟病,Intel的CPU也偶报出各种安全漏洞,但是很多年以来,我们都只能一直默默忍受,国产化提了很多年,但是就是没做起来,国家也是无奈,恨铁不成钢,一直到如今,看似软硬件都有了不错的基础,下了很大的决心,也列出了 切换 的时间表,所以,一些地方已经行动起来了,国产化看来已势在必行。

国产化 即要完全替换国外的软硬件,实现自主可控,其中两个最关键的组件:CPU和操作系统的替换首当其冲。国产CPU做了很多年,路线和基因各不相同,但似乎都在向好的方向发展,而且目前取得了不错的效果,其中龙芯CPU可谓最彻底,也最具代表性,最新的龙芯3A3000芯片单核性能得到了较大提升,官方性能数据已经领先于其它国产CPU。

操作系统方面,国产操作系统经过多年的发展,虽然可能没有达到大众的预期,但是还是在各自道路上做出了一定的成绩,同时也积累了相当的技术基础和经验,逐步替换也是大势所趋。

所以,在国产化后,PC机不再是 Intel Inside, 而是 Loongson Inside或者Phytium Inside了,而操作系统可能清一色Linux OS了。平台搭建好后,缺的就是应用软件了,这估计也是目前国产化进展最大的障碍了,自然,对QQ的需求也就产生了。

有可能么?

几个问题:

  • QQ有Linux版本么? 有,但是早就不维护了,功能缺失严重,基本不可用。所以,可以算是没有。

  • QQ有龙芯版本么? 这个,当然没有。QQ显然目前只有X86的版本。

    这两个关键版本都没有,那要咋整?

    先回答如下问题:

  • Windows版本QQ能在Linux上运行么? 当然可以,看看龙井QQ、深度QQ、NewStart QQ,他们都能跑,但都有一个共同的基础:Wine,很多同学都应该听说过。

  • X86应用程序能运行在龙芯环境中么? 当然可以,怎么弄?很多种方式,比如各种虚拟机、应用虚拟化,这些(基本)也有一个共同的基础:Qemu ,这个同学们应该也听说过。

所以,要在龙芯上运行QQ,需要解决两大技术问题:

1、Windows API到Linux API翻译(转换),这个理论上可以通过Wine解决。 2、X86硬件指令到龙芯(Mips64)硬件指令的翻译,这样理论上可以通过Qemu解决。

那么,看似有可能了,Qemu+Wine,应该能解决问题。

About Wine

什么是Wine?

Wine简单说就是在Unix平台模拟Windows API的一个“模拟器”,与传统理解的模拟器不同,其不做底层的指令翻译,而仅仅模拟Windows的各种API,可以理解为为Wine在Unix平台(如Linux系统)山提供了一整套Windows的API接口,这些API接口,将Windows应用程序调用的Windows接口转接到Unix系统中的本地接口上,从而使Windows上的应用程序(EXE文件)能直接运行在Unix环境中,而且性能损失不大。

通过Wine已经适配了大量的Windows程序,使他们能在Linux环境中正常运行,其中包括QQ。

如想了解详细信息请访问其官网:

Wine官网

About Qemu

Qemu是一个真正的模拟器,用于各种硬件架构平台的模拟,其包括system和Linux-user两种模式,其中system模式可模拟一个完整系统,包括CPU、内存和各种外设,为用户提供一个完整的虚拟机,目前的流行的虚拟机技术,绝大部分都依赖于Qemu的system模式,包括KVM。

Linux-user模式为用户提供一种轻量级的指令模拟,而不模拟完整的系统,被用来执行一个独立的异构应用程序。比如在我们的场景中,可以在龙芯环境中直接通过qemu的Linux-user模式运行一个在x86环境中编译的二进制程序。

Linux-user模式,顾名思义,其完全运行于用户态。其基本原理是将应用程序的指令(x86指令)逐条 翻译 成与架构无关的中间指令,然后再将中间指令翻译成主机上能运行的目标指令(Mips64指令),翻译后的指令能直接在主机上执行,所以相应的应用程序既能正常运行。在翻译过程中,如果遇到系统调用(如:int 0x80)指令,则会进行特殊处理,将其转换为主机(龙芯/Mips64)的系统调用过程,使其进入主机的内核态,内核态中运行主机的内核,完成相应任务,然后返回用户态继续执行。另外,还有一些特殊的处理,比如信号等,这里不关注。总的来看,就是对程序指令进行翻译,并共享内核空间。

有问题么?

Qemu linux-user模式+Wine 的方案看起来都有现成技术,实现看似not so hard,有问题么?

当然有,问题很多。不信?你可以在X86环境中写个helloworld程序,编译,然后放到龙芯环境中使用qemu linux-user模式运行,直接crash。

说明啥?现实的情况下,龙芯环境中连最简单的x86程序都跑不起来,更别说wine,更别提QQ了。

为啥会这样?

因为这是 龙芯,不是X86,也不是Arm。龙芯是Mips架构,相对非主流,无论是qemu、内核还是wine,都涉及硬件相关的实现,而这些关键的组件中,对龙芯(Mips)支持都不好,一方面不稳定,另一方面很多功能缺失。所以,想要在龙芯上运行QQ,目前看仍是一个遥远而未知的梦。(即使是Arm,梦想也比较遥远)

另外,龙芯架构自身的特殊设计也是一大障碍,比如16k page size,会导致意想不到的问题。

除此之外,还有一个关键问题:性能。

想想,即使在X86 PC机上使用Qemu以纯软件的方式模拟执行其它架构的应用程序,也会有较明显的性能问题,因为qemu模拟指令,需要经过两次转换(如前面的原理描述),一条guest指令翻译成host指令后,可能是十条,甚至更多,综合来看,纯软件的指令翻译,性能损失基本是一个数量级。X86尚且如此,而龙芯则更甚,结果可能是无法忍受的慢。

除上述的技术问题外,还有一个大麻烦:调试very very难! 由于需要经过 两层翻译,任何问题的分析调试都异常困难,而QQ在成功运行的道路上可能出现的问题可能不计其数,而每个问题的分析调试都是一次考虑和折磨。你可以想想。。。

只能说,要实现这个梦想很难、很难。

我们做了啥?

虽然很难,但对我们来说,其实也是挑战,我们在操作系统领域深耕十余载,在涉及的内核、虚拟化、wine方面都还有一定的积累和自信,在经过慎重讨论后,最终确定接受挑战。经过一段时间的摸索和分析,也取得了一定的成果,目前单线程的X86应用程序(比如SourceInsight3、Notepad++等)已能在NewStart桌面系统中正常运行,但QQ程序(多线程程序)还不行,持续崩溃中。

这里,看看是否需要截图???

我们解决了啥问题?

单线程程序成功运行前,我们解决了如下几个关键问题:

  1. Qemu用户模式运行x86程序崩溃问题,这个是qemu的核心翻译模块tcg中,mips架构相关部分的实现bug,目前已经针对该bug提交了两个补丁给qemu社区,并且已经合入了主分支。

这里是否需要链接?????

  1. 龙芯16k pagesize导致qemu的翻译异常的问题。qemu指令翻译过程中,会有较多涉及page size的地方,由于龙芯的默认page size为16k,会导致一些意料之外的问题,这部分问题已经通过修改代码得到控制,但无法合入上游社区。

  2. qemu+wine的运行环境搭建。需要搭建专门的运行环境,结合内核的binfmt支持,同时需要qemu-static、C库、16k对齐等,种种看似繁琐但却不乏技术含量的工作。

  3. Wine QQ特定的一些问题,比如:Wine QQ启动过程中会加载大量的dll,其中有一些dll会加载失败,原因各不相同,有一些很奇怪的是因为QQ自身的一些特殊设计,做了特殊处理,解决了部分问题。

接下来的挑战

  1. qemu用户模式的多线程支持。据分析,目前多线程程序无法运行最主要的原因是,qemu用户模式不支持多线程应用程序。或者不能说不支持,应该说支持得不好(部分架构比如Arm可能会好一些),至少对Mips来说是这样的。所以,需要在qemu用户模式中的增加(或加固)multithread支持,需要实现两个关键点:原子操作和内存屏障,涉及底层硬件,问题复杂度和难度很大,需要细心专研。

  2. wine本地化及性能问题。目前的方案为Qemu+wine,即将Wine运行于qemu中,这里将qemu理解为一个虚拟机的话,即将整个wine+QQ都运行与虚拟机中,而这其中,wine属于相当重量级,对wine的翻译会消耗CPU可能会超过QQ本身,会成为严重的性能瓶颈,所以,该方案只能作为预研和研究使用,基本不太可能使其达到可用状态。所以,处于性能考虑,还需要更轻量级的方案,换个位置:Wine+Qemu或许能行,将Wine本地化,即将Wine直接在龙芯环境中编译和运行,使其运行于虚拟机外,如此,可以省下大部分的指令翻译时间,大大提升性能。说起容易,做起来就难了(应该说很难),难点在于:

- Wine自身对Mips的支持完全没有(X86和Arm架构支持不错),这部分工作需要自己做,社区不可能帮你做,这部分工作的难度和工作量都不小。
- Wine和qemu和应用程序的接口问题。Wine本地化后,如何才能正确的与应用程序和Qemu接口,比如,如何才能让运行于qemu(虚拟机)中的应用程序调用qemu外的wine提供的API,他们之间如何通信。这将是一项难度极大的任务,很有挑战性。
   
- 由于Windows没有Mips版本,Wine支持mips的开发将很难进行,包括调试。
  1. qemu+wine的多线程调试问题,也是一个让人头疼的问题。

  2. 其它未知问题,前期的经验告诉我们,前面肯定还会有很多很深的坑。