读漫谈WINE的系统结构笔记
试验环境: Debian + wine 1.0+ vim7.2+ctags
联系方式:hongmy525(at)gmail.com
2008年12月25日
这不是我第一次阅读毛老师的漫谈系列了,不知道是因为太久以前看的,还是以前看的时候没有理解,现在竟然忘记得干干净净,呵呵。其实在毛老师的漫谈中,已经讲得很清楚了,但好记性不如烂笔头,我还是记一下:)
概述
Wine是Windows应用软件与Linux内核之间的适配层,通俗的说就是让linux支持windows软件的程序。
在wine运行时,一般应该有3部分,且这三部分相互有联系:
1、Wineserver服务进程。用来管理和协调windows应用程序的。
2、X11进程。处理图形显示、键盘鼠标输入等。
3、 Windows应用程序。Windows应用程序运行本身。
那天写这文章的时候死活找不到这个图,现在找到了补上:)
Wine Architecture:
+---------------------+ /
| Windows EXE | } application
+---------------------+ /
+---------+ +---------+ /
| Windows | | Windows | / application & system DLLs
| DLL | | DLL | /
+---------+ +---------+ /
+---------+ +---------+ +-----------+ +--------+ /
| GDI32 | | USER32 | | | | | /
| DLL | | DLL | | | | Wine | /
+---------+ +---------+ | | | Server | / core system DLLs
+---------------------+ | | | | / (on the left side)
| Kernel32 DLL | | Subsystem | | NT-like| /
| (Win32 subsystem) | |Posix, OS/2| | Kernel | /
+---------------------+ +-----------+ | | /
| |
+---------------------------------------+ | |
| NTDLL | | |
+---------------------------------------+ +--------+
+---------------------------------------+ /
| Wine executable (wine-?thread) | } unix executable
+---------------------------------------+ /
+---------------------------------------------------+ /
| Wine drivers | } Wine specific DLLs
+---------------------------------------------------+ /
+------------+ +------------+ +--------------+ /
| libc | | libX11 | | other libs | } unix shared libraries
+------------+ +------------+ +--------------+ / (user space)
+---------------------------------------------------+ /
| Unix kernel (Linux,*BSD,Solaris,OS/X) | } (Unix) kernel space
+---------------------------------------------------+ /
+---------------------------------------------------+ /
| Unix device drivers | } Unix drivers (kernel space)
+---------------------------------------------------+ /
关键数据结构
-
SERVEER_START_REQ() 与SERVER_END_REQ宏
#define SERVER_START_REQ(type) /
do { /
struct __server_request_info __req; /
struct type##_request * const req = &__req.u.req.type##_request; /
const struct type##_reply * const reply = &__req.u.reply.type##_reply; /
memset( &__req.u.req, 0, sizeof(__req.u.req) ); /
__req.u.req.request_header.req = REQ_##type; /
__req.data_count = 0; /
(void)reply ; /
do
#define SERVER_END_REQ /
while(0); /
} while(0)
这两个宏连在一块使用,就成了两个嵌套do while循环。
-
DECL_HANDLER宏
#define DECL_HANDLER(name) /
void req_##name( const struct name##_request *req, struct name##_reply *reply )
这个宏展开后:
void req_flush_file ( const struct flush_file_request *req, struct flush_file_reply *reply )
{
. . . . . .
}
就变成这样一个函数定义,所以wine_server_call()函数call后,就传到这个函数来了。
-
req_handler[ ]数组
static const req_handler req_handlers[REQ_NB_REQUESTS] =
{
(req_handler)req_new_process,
(req_handler)req_new_thread,
(req_handler)req_terminate_process,
……..
(req_handler)req_flush_file,
……..
(req_handler)req_set_focus_window,
(req_handler)req_set_global_windows,
…… 共有将近200个函数
};
这个函数集的代码在server/request.h中,详细的解释请参考毛老师的漫谈。:)
执行流程
Wine用socket和pipe来进行wineserver进程和windows应用程序进程通讯。所以wineserver进程起来以后创建windows进程执行,当中有很多操作(例如下面提到的NtFlushBufferdFile),windows应用程序需要向wineserver请求执行linux系统调用。(详细请参考毛老师的《漫谈Wine之一:WINE的系统结构》)
这里假如windows应用程序调用了flush buffer 这样的函数,这些API最终都要走到ntdll中去调用与之对应的函数,这里我随便举个例子,我们这里重点观察的是wine的执行流程。示例函数我和毛老师的漫谈里面使用NtFlushBufferdFile( )吧。
此时应用程序是一个客户端(Client),而Wineserver则是一个服务端。
Client(Windows应用程序):
NtFlushBuffersFile()
{
……
SERVER_START_REQ( flush_file )
{
req->handle = hFile;
wine_server_call( req )
{
切换到wineserver服务进程(windows进程睡眠等待)
DECL_HANDLER(flush_file)
切换回应用进程
}
hEvent = reply->event;
}
SERVER_END_REQ;
……
}
Server(Wineserver):
Main() > main_loop()
{
通过循环检查socket和pipe是否有内容
当接受到消息后进行处理
fd_poll_event() > thread_poll_event() > read_request() > call_req_handler()
{
执行发送的请求,即漫谈前面提到的req_handler[req]数组函数
req_handler[req](req, &reply);
……
处理完请求后,向Client发送信息
Send_reply(reply);
}
继续循环等待请求
}
总结
通过这样的复杂而频繁的进程间切换后(进程切换会引起进程堆栈等的地址空间切换),可以看到wine确实走了很多的弯路,如果采用兼容内核的方式,省掉这方面的开销,确实会让程序运行的效率提高起来。
Reference
《漫谈Wine之一:WINE的系统结构》 毛德操
Wine 1.0 的源码
《Wine Developer's Guide》
《嵌入式Linux应用程序开发详解》华清远见 人民有电出版社
IBM developerWorks《Linux 环境进程间通信(六) 》