Chinaunix首页 | 论坛 | 博客
  • 博客访问: 667848
  • 博文数量: 237
  • 博客积分: 4285
  • 博客等级: 上校
  • 技术积分: 2701
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-15 14:05
文章分类

全部博文(237)

文章存档

2014年(2)

2013年(3)

2012年(47)

2011年(15)

2010年(68)

2009年(102)

我的朋友

分类: LINUX

2010-03-31 13:15:54

转载时请注明出处和作者联系方式
作者联系方式:李先静

10.X Window扩展机制--扩展(Extension)

XWindow 中有大量扩展模块,每个扩展模块完成一组相关的功能,把扩展功能从核心功能中剥离出来,可以大大提高X Server的可配置性和扩展性。扩展模块的实现机制很简单:每一个扩展模块都有一个初始化函数,这个函数在X Window起动时被调用,在这里面会初始化一些该模块的数据结构,然后会调用AddExtension把相关回调函数注册进去。

AddExtension 的函数原型如下:


ExtensionEntry 
*
AddExtension(
char *name, int NumEvents, int NumErrors,
             
int (*MainProc)(ClientPtr c1),
             
int (*SwappedMainProc)(ClientPtr c2),
             
void (*CloseDownProc)(ExtensionEntry *e),
             unsigned 
short (*MinorOpcodeProc)(ClientPtr c3))

  1. Name: 插件的名称。
  2. NumEvents: 为扩展保留的事件数。
  3. NumErrors:为扩展保留的错误码数。
  4. MainProc: 扩展的处理函数。
  5. SwappedMainProc: 扩展的处理函数,在处理前先交换字节顺序。
  6. CloseDownProc: 扩展的析构函数。
  7. MinorOpcodeProc: 用来得到子处理号,一般没有什么用处,在出错时,设置到错误信息里。

从 AddExtension的实现中,我们很容易看出,扩展其实也是通过前一章所说的ProcVector来实现的。

   i = NumExtensions;
    newexts 
= (ExtensionEntry **) xrealloc(extensions,
                       (i 
+ 1* sizeof(ExtensionEntry *));
    
if (!newexts)
    
{
    xfree(ext
->name);
    xfree(ext);
    
return((ExtensionEntry *) NULL);
    }

    NumExtensions
++;
    extensions 
= newexts;
    extensions[i] 
= ext;
    ext
->index = i;
    ext
->base = i + EXTENSION_BASE;
    ext
->CloseDown = CloseDownProc;
    ext
->MinorOpcode = MinorOpcodeProc;
    ProcVector[i 
+ EXTENSION_BASE] = MainProc;
   SwappedProcVector[i 
+ EXTENSION_BASE] = SwappedMainProc;


从 理论上说,框架完全是独立于扩展的,增加增/删扩展不需要修改框架的代码。但实际情况往往不是这样的,有的扩展依赖框架提供一些特殊功能,有的扩展依赖另 外一些扩展,所以在X Server的代码中,常常出现很多ifdef之类的宏,这些宏用来控制是否启用某些扩展。

下面我们来看一个实际 的例子(render):

在mi/miinitext.c: InitExtensions函数中,
RenderExtensionInit函数被调用,RenderExtensionInit的实现如下:

void
RenderExtensionInit (INITARGS)
{
    ExtensionEntry 
*extEntry;

    
if (!PictureType)
    
return;
    
if (!PictureFinishInit ())
    
return;
    RenderClientPrivateIndex 
= AllocateClientPrivateIndex ();
    
if (!AllocateClientPrivate (RenderClientPrivateIndex,
                
sizeof (RenderClientRec)))
    
return;
    
if (!AddCallback (&ClientStateCallback, RenderClientCallback, 0))
    
return;
   
    extEntry 
= AddExtension (RENDER_NAME, 0, RenderNumberErrors,
                 ProcRenderDispatch, SProcRenderDispatch,
                 RenderResetProc, StandardMinorOpcode);
    
if (!extEntry)
    
return;
#if 0
    RenderReqCode 
= (CARD8) extEntry->base;
#endif
    RenderErrBase 
= extEntry->errorBase;
}


ProcRenderDispatch 是扩展的主分发函数,它调用子处理函数去完成实际的请求。其中stuff->data是子处理号,以子处理号从ProcRenderVector中 找到对应的函数,并调用它。

static int
ProcRenderDispatch (ClientPtr client)
{
    REQUEST(xReq);

    
if (stuff->data < RenderNumberRequests)
    
return (*ProcRenderVector[stuff->data]) (client);
    
else
    
return BadRequest;
}


(待续)
阅读(1330) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~