linux 视频窗口 句柄,Linux下的“句柄”(文件句柄,窗口句柄)

在windows中,句柄是一个32位的整数,是内存中维护的一个对象的地址列表的整数索引,这些对象包括:窗口(window)、块(module)、任务(task)、实例 (instance)、文件(file)、内存块(block of memory)、菜单(menu)、控制(control)、字体(font)、资源(resource),包括图标(icon),光标 (cursor),字符串(string)等、GDI对象(GDI object),包括位图(bitmap),画刷(brush),元文件(metafile),调色板(palette),画笔(pen),区域(region),以及设备描述表(device context)。

在Linux中,每一个进程都由task_struct 数据结构来定义,即PCB,进程通过PCB中的文件描述符表找到文件描述符fd所指向的文件指针filp,文件描述符表是一个指针数组,每一个元素都指向一个内核的打开文件对象,而fd,就是这个表的下标。当用户打开一个文件时,内核会在内部生成一个打开文件对象,并在这个表里找到一个空项,让这一项指向生成的打开文件对象,并返回这一项的下标作为fd,Linux中的文件描述符类似于Windows下文件句柄的概念,但区别是Windows的文件句柄是一个全局的概念,而Linux下文件句柄的作用域只在本进程空间,其中0(标准输入)、1(标准输出)、2(标准错误)是每一个进程中相同的文件描述符,由操作系统规定好,文件描述符所指向元素的文件指针为struct file结构体,在系统中是一个全局的指针。

c46ad0773c992a2e0f1da8eb68991c36.png

在linux的X Window桌面环境下,Window 类似于Windows下的窗口句柄,X11/X.h中定义如下:

typedef unsigned long int XID;

typedef XID Window;

typedef XID Font;

typedef XID Pixmap;

typedef XID Drawable;

typedef XID Cursor;

typedef XID Colormap;

typedef XID GContext;

typedef XID KeySym;

同时,X的官方解释(参考https://www.x.org/wiki/guide/concepts/#index10h4)如下:

XIDs

Many resources managed by the server are assigned a 32-bit identification number, called an XID, from a server-wide namespace. Each client is assigned a range of identifiers when it first connects to the X server, and whenever it sends a request to create a new Window, Pixmap, Cursor or other XID-labeled resource, the client (usually transparently in Xlib or xcb libraries) picks an unused XID from it's range and includes it in the request to the server to identify the object created by this request. This allows further requests operating on the new resource to be sent to the server without having to wait for it to process the creation request and return an identifier assignment. Since the namespace is global to the Xserver, clients can reference XID's from other clients in some contexts, such as moving a window belonging to another client.

大概意思是:

X Server通过一个32比特的标识号标识资源。每一个客户端在第一次连接到X Server时,会被赋值一个标识范围,无论是向X Server请求创建一个Window、Pixmap、或者其他XID标记的资源,客户端(通常对于Xlib或xcb库来说是透明的)从此范围选择一个未使用的XID,同时在向X Server发送请求时包含此XID以识别此次请求创建的资源。这种方式允许同时向X Server请求多个新的资源,而不需要等待每次资源创建成功并返回XID。因为对于X Server来说,域名是全局的,所以在同一个上下文中,不同的客户端之间可以相互引用XID,例如在一个客户端中移动属于另一个客户端的窗口。

在Xorg中,客户端资源使用一个数组保存(dix/resource.c):

static ClientResourceRec clientTable[MAXCLIENTS];

xorg是server/client架构,一个xorg server 最多可以有MAXCLIENTS个client,clientTable中的数据项为ClientResourceRec类型,数组中的每一个元素指向client的资源,定义如下:

typedef struct_ClientResource {

ResourcePtr *resources;

intelements;

intbuckets;

int hashsize; /*log(2)(buckets) */XID fakeID;

XID endFakeID;

} ClientResourceRec;

其中ResourcePtr *resources为一个数组,存放某个客户端的资源,定义如下:

typedef struct_Resource {

struct _Resource *next;

XID id;

RESTYPE type;

void *value;

} ResourceRec, *ResourcePtr;

用户进入Linux桌面环境后,使用xwininfo可以获取每个窗口的Window id,即XID,XID中的第0~20位为每个客户端的资源ID,第21~28位为客户端编号,请看如下代码:

Bool

InitClientResources(ClientPtr client)

{inti, j;if (client ==serverClient) {

lastResourceType=RT_LASTPREDEF;

lastResourceClass=RC_LASTPREDEF;

TypeMask= RC_LASTPREDEF - 1;free(resourceTypes);

resourceTypes= malloc(sizeof(predefTypes));if (!resourceTypes)returnFALSE;

memcpy(resourceTypes, predefTypes,sizeof(predefTypes));

}

clientTable[i= client->index].resources =

malloc(INITBUCKETS * sizeof(ResourcePtr));if (!clientTable[i].resources)returnFALSE;

clientTable[i].buckets=INITBUCKETS;

clientTable[i].elements= 0;

clientTable[i].hashsize=INITHASHSIZE;/*Many IDs allocated from the server client are visible to clients,

* so we don't use the SERVER_BIT for them, but we have to start

* past the magic value constants used in the protocol. For normal

* clients, we can start from zero, with SERVER_BIT set.*/clientTable[i].fakeID= client->clientAsMask |(client->index ?SERVER_BIT : SERVER_MINID);

clientTable[i].endFakeID= (clientTable[i].fakeID | RESOURCE_ID_MASK) + 1;for (j = 0; j < INITBUCKETS; j++) {

clientTable[i].resources[j]=NULL;

}returnTRUE;

}intHashResourceID(XID id,intnumBits)

{

id&=RESOURCE_ID_MASK;switch(numBits)

{case 6:return ((int)(0x03F & (id ^ (id>>6) ^ (id>>12))));case 7:return ((int)(0x07F & (id ^ (id>>7) ^ (id>>13))));case 8:return ((int)(0x0FF & (id ^ (id>>8) ^ (id>>16))));case 9:return ((int)(0x1FF & (id ^ (id>>9))));case 10:return ((int)(0x3FF & (id ^ (id>>10))));case 11:return ((int)(0x7FF & (id ^ (id>>11))));

}if (numBits >= 11)return ((int)(0x7FF & (id ^ (id>>11))));else{

assert(numBits>= 0);return id & ~((~0) <

}

}staticXID

AvailableID(intclient, XID id, XID maxid, XID goodid)

{

ResourcePtr res;if ((goodid >= id) && (goodid <=maxid))returngoodid;for (; id <= maxid; id++) {

res=clientTable[client].resources[HashResourceID(id, clientTable[client].hashsize)];while (res && (res->id !=id))

res= res->next;if (!res)returnid;

}return 0;

}

从以上代码分析,Xorg通过XID的第21~28位作为索引(假设索引号为client)定位clientTable中的客户端结构体,此结构体中的resources也是一个数组,每个元素指向一个ResourcePtr,此数组大小为INITBUCKETS,相当于创建了INITBUCKETS个资源池,通过0~20位获取资源号后,通过hash算法(xorg中一般使用((int)(0x03F & (id ^ (id>>6) ^ (id>>12))))),将新建的Resource资源放入某个资源池,在一个池子中的Resource以链表方式连接到一起。此种方式应该是在XID查询和资源释放效率间获得一定的平衡。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值