读漫谈WINE的系统结构笔记

本文介绍了WINE如何作为Windows应用与Linux内核之间的适配层工作,详细阐述了其执行流程,包括Wineserver服务进程、X11进程和Windows应用程序之间的交互。关键数据结构如SERVER_START_REQ和SERVER_END_REQ宏以及req_handlers数组在进程通信中的作用也得到了解析。最后,总结了WINE执行过程中涉及的进程间切换带来的效率问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

读漫谈WINE的系统结构笔记

试验环境: Debian + wine 1.0+ vim7.2+ctags

联系方式:hongmy525atgmail.com

20081225

这不是我第一次阅读毛老师的漫谈系列了,不知道是因为太久以前看的,还是以前看的时候没有理解,现在竟然忘记得干干净净,呵呵。其实在毛老师的漫谈中,已经讲得很清楚了,但好记性不如烂笔头,我还是记一下:)

概述

WineWindows应用软件与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中,详细的解释请参考毛老师的漫谈。:)

 

执行流程

       Winesocketpipe来进行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;

       ……

}

 

ServerWineserver):

Main() > main_loop()

{

       通过循环检查socketpipe是否有内容

       当接受到消息后进行处理

       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 developerWorksLinux 环境进程间通信(六)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值