WINE
是
32
位代码,
Linux
中的
stdcall(gcc)
支持
Windows
常规调用,因此可以直接替换
WINE
处理器中的地址导入
Win32
代码,但对于
16
位模块还需要添加
thunk
进行地址等方面的转换。
三、
WINE
启动分析
由于
Linux
早期版本提供的线程
API
不够强大,不足以实现
Windows API
线程部分,
WINE
利用
Linux kernel thread
重新构建了
Windows
线程
API
函数,该部分在
WINE
中称为
WINE-kthread
。随着
Linux
的发展,
Linux
后来的版本中出现了功能强大的
NPTL
线程子系统,
WINE
利用此系统提供的
API
函数粘合了
Windows
线程
API
函数,此部分称为
WINE-pthread
。
WINE
在启动前首先检查用户使用的线程模式并执行由
WINE-pthread
或
WINE-kthread
实现的
WINE preloader
。它是一个没有
main
主函数的
ELF
文件,用于在新建立的
WINE
进程中设置
Win32
类型的进程地址空间布局后转入
WINE
的
main
函数,
WINE
被启动。
Preloader
通过这种方式传递一些必要信息到
libwine
(
WINE
的动态库)中,并调用函数
Wine-init
进行
debug
功能和地址空间方面的处理。以后顺次执行:
1
.
-WINE-process-init
建立
Win32
程序运行所必需的结构,如
PEB
、
TEB
、进程堆以及与
WINE server
的连接等。
2
.
-Wine-kernel-init
依次执行:从
WINE server
获得新进程启动时必需的信息;初始化新进程的的注册以及其它相关部分;确定被加载文件的类型以后该应用程序被载入内存。
3
.新载入
Windows
程序运行的开始。首先,
start-process
建立
SHE
,调用
NtdllLdr-Initializer Thuck
执行进程初始化的其他部分,如进行重定位以及调用
DLL
的构造函数等。最后,执行转入被载入应用程序的入口点,应用程序开始执行,
WINE
提供的
API
就可以被正确地调用了,随后当执行从应用程序返回时,调用
ExitProcess
函数结束该进程。
四、
Win32
启动分析
从命令行启动一个
WINE
进程时,
WIN-E
首先检查操作系统使用的线程模式,启动
WINE
装载器。
WINE
从
Linux
中取得诸如运行环境、命令行参数等必要的资源的后依次执行:
1.
NTDLL.dll.so
被
Linux
的标准共享库装载器载入内存,在
Linux
中建立
PEB
、
TEB
、进程堆以及与
WINE Server
的连接等。
2.
利用
Windows
动态装载能力加载
Ke-rne132
,
-WINE-kernel-init
处理所有装载与执行的逻辑过程,包括初始化命令行参数,在文件系统中寻找相应的可执行文件。如果没有找到,
WINE
装载器停止装载并返回出错信息;否则,将找到的文件载入内存,建立一个堆栈供新建立的可执行文件的进程作用,堆栈大小由该文件结构中
PE-header
定义。
3.
Ntdll.LdrInitializeThunk
执行其他部分如解析所有在可执行文件中引用的
DLL
与
TLS
槽的初始化。
4.
执行转入到可执行文件的入口点,可执行文件开始运行。
如果有多个
Win32
程序要求运行,
WINE
为这些
Win32
程序分别建立
WINE
进程。这些
Win32
程序在各自的
WINE
进程中运行。(如图
2
所示)。
五、
Winelib
启动分析
图
2
Winelib
(假定有一个文件
example.exe
)对应有两个文件:
example
为一个链接到
WINE
装载器的符号链接;
example.exe.so
相当于一个
Linux
中的动态连接库。
从命令行启动一个
Winelib
程序时,
Linux shell
将
example
作为一个
Linux
的可执行文件。由于它实际是
WINE
的一个装载器,所有
WINE
被启动并利用
Linux
的共享库机制加载第二个文件
example.exe.so
。
WINE
根据文件的描述符确认它是一个
32
位模块,于是共享库被加载,再处理该可执行文件的导入节,调用全局对象的构造器,便于以后加载动态库函数,最后执行转入可执行文件的入口点,载入的文件开始运行。
六、
Win16
与
DOS
程序启动分析
一个
Win16
程序要求运行时,
WINE
将该程序交给虚拟
DOS
机(
VDM
)。虚拟机首先建立一个
16
位的运行环境,
Win16
程序就在该虚拟环境中运行。此后由该程序创建的子程序均在同一虚拟机实例中运行。虚拟机为
16
位的进程提供了诸如多任务协作,共享地址空间,管理为
16
位进程建立的代码段、数据段与堆栈段的选择器等功能。
DOS
程序的启动与
Win16
的启动过程类似,对虚拟机对
DOS
程序还采用互斥机制保证
DOS
程序的运行是单线程的,如图
2
所示。
七、
Wine
实战
我们可以在
http://fedoraproject.org/wiki/AndreasBierfert/Wine下载到针对Fedora12的Wine最新版本是1.1.38
当下载到
tar
包后
Cd
到安装目录中运行
wineinstall(
安装释放文件)文件,之后它会运行
./configure
,然后显示:
We need to install wine as root user, do you want us to build wine,'su root' and install Wine? Enter 'no' to continue without installing(yes/no)
我们选
yes
并回车如果在此处出现错误,请检查此命令的输出,如果他没有找到一些需要的包,而你又希望使用那个包提供的功能时,请安装相应的
devel
包。
如果你
root
用户设置了密码,还会提示你输入密码。
待屏幕上出现:
Installation complete for now. Good luck (this is still alpha software).
If you have problems with WINE, please read the documentation first,
as many kinds of potential problems are explained there.
看到这条提示,则表示安装成功了。
在
shell
下运行
wine
,第一次运行不成功,这是正常
,
因为没有在
/root/.wine/config
文件里配置好
.
找到这些吧。
[Drive C]
"Path" = "/usr/share/win_c"
"Type" = "hd"
"Label" = "MS-DOS"
"Filesystem" = "win95"
改为
:[Drive C]
"Path" = "/winc"
"Type" = "hd"
"Label" = "MS-DOS"
"Filesystem" = "win95"
就可以了,如果你安装了
simsun
字体
.wine
默认就会找到这个字体的。
我们在运行
windows
程序时,常常会出现看不到中文的情况,那是因为在
GBK
或
GB2312
编码状态下可以输入中文,但如果没有进行默认编码设置,就无法输入中文。
通过设置
locale
可以解决。具体方法如下:
编辑
.bashrc
文件在该文件尾部添加如下两行:
export LANG=zh_CN.gb2312
export LC_ALL=zh_CN.2312
重新运行
bash
后敲入
locale
命令,默认的编码就会显示
GB2312
另外,
还有就是如果没有中文字体也无法显示中文,自然也就看不见汉字。
下一步该运行应用程序
了,可以通过两种方式运行:
1.
自动运行
在
KDE
或者
GNOME
的文件管理器中切换到应用程序所在目录,单击就可以打开。虽然程序运行速度十分缓慢,不过聊胜于无。
2.
手工运行
在
Console
模式下,键入以下命令:
wine
<将要运行的应用程序>
3.
举个例子来说吧
想要通过
WINE
在
Linux
下使用
Winzip,
这么做呢
?
重新运行
winesetup
,在配置
Windows
安装路径窗口中,选择“
Create a new windows directory
(创建一个新的
Windows
安装目录)”,其它的一切都很简单,在
Linux
中直接运行
Winzip
安装文件安装
Winzip
然后就可以调用了。
总结
本文对在
Linux
系统中运行
Windows
程序的一种实现
--WINE
内核运行的机理和实例进行了详尽分析。
在比较了
W
indows
程序转移到
Linux
中各种技术实现及各自特点的基础上,阐述了
WINE
的体系结构及各部分的功能,并通过对不同类型
Windows
程序启动过程的分析,揭示了
WINE
在
Linux
中创建
Win32
线程
/
进程环境与调用动态链接库的技术。由于当前
Linux
平台上应用程序的类型与数目不多,大部分企业还不能确定是否应该将
Windows
应用程序移植到
Linux
系统中,更多的厂商在等待
Linux
系统大规模应用于桌面。将
Windows
应用程序移植到
Linux
环境中运行对于此难题的解决则是一个非常有效的方式。