模块定义 (.def) 文件

本文介绍模块定义(.def)文件的作用及语法,重点讲解如何利用.def文件为链接器提供程序导出、属性等信息,特别关注EXPORTS语句的使用方法。此外,文章还列举了一些关键保留字。

模块定义 (.def) 文件

模块定义 (.def) 文件为链接器提供有关被链接程序的导出、属性及其他方面的信息。生成 DLL 时,.def 文件最有用。由于存在可代替模块定义语句使用的链接器选项,通常不需要 .def 文件。也可以将 __declspec(dllexport) 用作指定导出函数的手段。

在链接器阶段可以使用 /DEF(指定模块定义文件)链接器选项调用 .def 文件。

如果生成的 .exe 文件没有导出,使用 .def 文件将使输出文件较大并降低加载速度。

模块定义语句的规则

下列语法规则适用于 .def 文件中的所有语句。其他适用于特定语句的规则与各语句一起加以说明。

语句、属性关键字和用户指定的标识符区分大小写。

包含空格或分号 (;) 的长文件名必须用引号 (") 引起。

使用一个或多个空格、制表符或换行符,将语句关键字同其参数分开和将各语句分开。指定参数的冒号 (:) 或等号 (=) 两旁有零个或多个空格、制表符或换行符。

如果使用 NAME LIBRARY 语句,则这些语句必须位于所有其他语句之前。

.def 文件中,SECTIONS EXPORTS 语句可以出现多次。每个语句都可以采用多个规范,各规范间必须用一个或多个空格、制表符或换行符分开。语句关键字必须在第一个规范的前面出现一次,并且可以在每个附加规范的前面重复。

许多语句都具有等效的 LINK 命令行选项。有关其他详细信息,请参见相应的 LINK 选项说明。

.def 文件中的注释由每个注释行开始处的分号 (;) 指定。注释不能与语句共享一行,但可以在多行语句的规范间出现。(SECTIONS EXPORTS 为多行语句。)

以十进制或十六进制为基础指定数值参数。

如果字符串参数与保留字匹配,则必须用双引号 (") 将字符串参数引起。

 

EXPORTS

EXPORTS 关键字可以在第一个定义所在的同一行或前一行上。.def 文件可以包含一个或多个 EXPORTS 语句。

导出 definitions 的语法为:

entryname[=internalname] [@ordinal [NONAME]] [PRIVATE] [DATA]

entryname 是要导出的函数名或变量名。这是必选项。如果导出的名称与 DLL 中的名称不同,则通过 internalname 指定 DLL 中导出的名称。例如,如果 DLL 导出函数 func1(),要将它用作 func2(),则应指定:

EXPORTS

func2=func1

@ordinal 允许指定是序号而不是函数名将进入 DLL 的导出表。这有助于最小化 DLL 的大小。.LIB 文件将包含序号与函数之间的映射,这使您得以像通常在使用 DLL 的项目中那样使用函数名。

可选的 NONAME 关键字允许只按序号导出,并减小结果 DLL 中导出表的大小。但是,如果要在 DLL 上使用 GetProcAddress,则必须知道序号,因为名称将无效。

可选的 PRIVATE 关键字禁止将 entryname 放到由 LINK 生成的导入库中。它对同样是由 LINK 生成的图像中的导出无效。

可选的 DATA 关键字指定导出的是数据,而不是代码。例如,可以导出数据变量,如下所示:

EXPORTS

i DATA

当对同一导出使用 PRIVATE DATA 时,PRIVATE 必须位于 DATA 的前面。

有三种导出定义的方法,按照建议的使用顺序依次为:

源代码中的 __declspec(dllexport) 关键字

.def 文件中的 EXPORTS 语句

LINK 命令中的 /EXPORT 规范

所有这三种方法可以用在同一个程序中。LINK 在生成包含导出的程序时还创建导入库,除非生成中使用了 .exp 文件。

以下是 EXPORTS 节的示例:

EXPORTS

DllCanUnloadNow      @1     PRIVATE   DATA

DllWindowName = Name        DATA

DllGetClassObject    @4 NONAME   PRIVATE

DllRegisterServer    @7

DllUnregisterServer

注意,使用 .def 文件从 DLL 中导出变量时,不需要在变量上指定 __declspec(dllexport)。但是,在任何使用 DLL 的文件中,仍必须在数据声明上使用 __declspec(dllimport)

HEAPSIZE

/HEAP 选项设置堆的大小(以字节为单位)。此选项仅在生成 .exe 文件时使用。

reserve 参数指定虚拟内存中总的堆分配。默认堆大小为 1 MB。链接器将指定值向上舍入为最接近的 4 个字节。

可选 commit 参数取决于操作系统的解释。在 Windows NT/Windows 2000 中,它指定一次分配的物理内存的数量。提交的虚拟内存导致空间被保留在页面文件中。更高的 commit 值在应用程序需要更多堆空间时可节省时间,但会增加内存需求并有可能延长启动时间。

以十进制或 C 语言表示法指定 reserve 值和 commit 值。

通过带 HEAPSIZE 的模块定义文件也可以实现该功能。

Visual Studio 开发环境中设置此链接器选项

打开该项目的属性页对话框。有关详细信息,请参见设置 Visual C++ 项目属性

单击链接器文件夹。

单击系统属性页。

修改堆提交大小属性。

以编程方式设置此链接器选项

LIBRARY

告知 LINK 创建 DLLLINK 同时还创建导入库,除非生成中使用了 .exp 文件。

library 参数指定 DLL 的名称。也可以使用 /OUT 链接器选项指定 DLL 输出名。

BASE=address 参数设置操作系统用来加载 DLL 的基址。该参数重写 0x10000000 的默认 DLL 位置。有关基址的详细信息,请参见 /BASE 选项说明。

请记住,在生成 DLL 时使用 /DLL 链接器选项。

NAME (C/C++)

另一种指定输出文件名的方法是使用 /OUT 链接器选项,而另一种设置基址的方法是使用 /BASE 链接器选项。如果两种方法都指定了,则 /OUT 重写 NAME

如果生成 DLLNAME 将只影响 DLL 名。

SECTIONS (C/C++)

引入了一个由一个或多个 definitions(关于项目输出文件各节的访问说明符)组成的节。

每个定义必须在单独一行上。SECTIONS 关键字可以在第一个定义所在的同一行或前一行上。.def 文件可以包含一个或多个 SECTIONS 语句。

SECTIONS 语句为图像文件中的一节或多节设置属性,并可用于重写每种节类型的默认属性。

definitions 的格式为:

.section_name specifier

此处,.section_name 为程序图像中的节名,specifier 为下列一个或多个访问修饰符:

EXECUTE

READ

SHARED

WRITE

用空格分开修饰符名。例如:

SECTIONS

.rdata READ WRITE

SECTIONS 标记 definitions 节列表的开始位置。每个定义必须在单独一行上。SECTIONS 关键字可以在第一个定义所在的同一行或前一行上。.def 文件可以包含一个或多个 SECTIONS 语句。支持 SEGMENTS 关键字作为 SECTIONS 的同义词。

Visual C++ 的早期版本支持:

section [CLASS 'classname'] specifier

出于兼容性考虑,支持 CLASS 关键字,但忽略了它。

另一种指定节属性的方法是使用 /SECTION 选项。

STACKSIZE

设置堆栈的大小(以字节为单位)。

另一种设置堆栈的方法是使用堆栈分配 (/STACK) 选项。有关 reserve commit 参数的详细信息,请参见关于该选项的文档。

该选项对 DLL 无效。

STUB

当用于生成虚拟设备驱动程序 (VxD) 的模块定义文件时,STUB 允许指定包含将在 VxD 中使用的 IMAGE_DOS_HEADER 结构(在 WINNT.H 中定义)而不是默认头的文件名。

另一种指定 filename 的方法是使用 /STUB 链接器选项。

在模块定义文件中,STUB 仅在生成 VxD 时有效。

VERSION (C/C++)

通知 LINK 将一个数字放到 .exe 文件或 DLL 的头中。

major minor 参数是从 0 65,535 的范围内的十进制数。默认值为 0.0 版。

另一种指定版本号的方法是使用版本信息 (/VERSION) 选项。

保留字

下列字是为链接器保留的。仅当将这些名称用双引号 ("") 括起来时,它们才可用作 模块定义语句 中的参数。

APPLOADER1

INITINSTANCE2

PRELOAD

BASE

IOPL

PRIVATE

CODE

LIBRARY1

PROTMODE2

CONFORMING

LOADONCALL1

PURE1

DATA

LONGNAMES2

READONLY

DESCRIPTION

MOVABLE1

READWRITE

DEV386

MOVEABLE1

REALMODE1

DISCARDABLE

MULTIPLE

RESIDENT

DYNAMIC

NAME

RESIDENTNAME1

EXECUTE-ONLY

NEWFILES2

SECTIONS

EXECUTEONLY

NODATA1

SEGMENTS

EXECUTEREAD

NOIOPL1

SHARED

EXETYPE

NONAME

SINGLE

EXPORTS

NONCONFORMING1

STACKSIZE

FIXED1

NONDISCARDABLE

STUB

FUNCTIONS2

NONE

VERSION

HEAPSIZE

NONSHARED

WINDOWAPI

IMPORTS

NOTWINDOWCOMPAT1

WINDOWCOMPAT

IMPURE1

OBJECTS

WINDOWS

INCLUDE2

OLD1

 

1 链接器在遇到此术语时发出警告(忽略)。不过,该保留字仍然保留。

2 链接器忽略该字,但是不发出警告。

 参考:http://msdn.microsoft.com/zh-cn/library/28d6s79h(v=VS.80).aspx

 

<think>我们正在讨论DB2的公共别名(Public Alias),而用户现在提到了“.def文件”,这可能是指DB2中的定义文件(例如在联邦数据库配置中使用的文件)。在DB2联邦系统中,.def文件通常用于定义远程数据源的包装器(wrapper)、服务器(server)、用户映射(user mapping)和昵称(nickname)等对象。公共别名可以与联邦对象结合使用,以提供全局访问点。 然而,用户的问题具体是:“DB2 public alias .def file usage or configuration”,即DB2公共别名与.def文件的使用或配置。这里需要澄清:公共别名本身并不直接与.def文件关联,因为公共别名是数据库内部的对象,而.def文件通常用于联邦数据库的配置(即创建联邦对象时使用的DDL脚本文件)。 但是,我们可以这样理解:在联邦数据库环境中,我们可能会使用.def文件定义联邦对象,然后为这些联邦对象(比如昵称)创建公共别名,以便全局访问。 因此,我将从以下角度回答: 1. 解释.def文件在DB2联邦系统中的作用(通常包含创建联邦对象的SQL语句)。 2. 说明如何在联邦对象上创建公共别名。 3. 给出一个结合.def文件和公共别名的配置示例。 注意:公共别名也可以用于非联邦对象(如本地表),但用户提到了.def文件,所以重点放在联邦数据库场景。 步骤: 1. **联邦数据库配置中的.def文件**: 在DB2联邦系统中,我们通常使用脚本文件(扩展名可能是.def.sql)来定义联邦对象。例如,一个名为`federation.def`的文件可能包含如下内容: ```sql -- 创建包装器 CREATE WRAPPER wrapper_name LIBRARY 'libdb2drda.so' OPTIONS(ADD DB2_FENCED 'N'); -- 创建服务器 CREATE SERVER server_name TYPE DB2/LINUXX8664 VERSION '11.5' WRAPPER wrapper_name OPTIONS (ADD DBNAME 'remote_db'); -- 创建用户映射 CREATE USER MAPPING FOR local_user SERVER server_name OPTIONS (ADD REMOTE_AUTHID 'remote_user', ADD REMOTE_PASSWORD 'password'); -- 创建昵称 CREATE NICKNAME local_schema.remote_table FOR server_name.remote_schema.remote_table; ``` 2. **为联邦对象(昵称)创建公共别名**: 在创建了昵称之后,我们可以为这个昵称创建一个公共别名,使得所有用户都可以通过这个别名访问,而无需知道昵称所在的模式。 ```sql CREATE PUBLIC ALIAS global_table FOR local_schema.remote_table; ``` 3. **使用公共别名访问联邦数据**: 用户可以直接使用公共别名查询: ```sql SELECT * FROM global_table; ``` 4. **配置示例**: 假设我们有一个.def文件(比如`federation_setup.def`),我们可以在其中包含创建公共别名的语句: ```sql -- 创建联邦对象(包装器、服务器、用户映射、昵称)的语句 ... (如上) -- 然后为昵称创建公共别名 CREATE PUBLIC ALIAS global_table FOR local_schema.remote_table; ``` 然后,我们可以使用db2命令执行这个.def文件: ```bash db2 -tvf federation_setup.def ``` 5. **注意事项**: - 公共别名的创建需要`CREATE_PUBLIC_ALIAS`权限,通常只有DBA有此权限。 - 在.def文件中,创建公共别名的语句应该放在创建昵称的语句之后,因为依赖关系。 - 公共别名一旦创建,所有用户都可以访问,但是对底层昵称(以及最终远程表)的访问权限仍然需要授权。也就是说,公共别名只是提供了一个全局名称,但实际数据访问权限还需要在昵称(或远程表)上授权。 6. **权限控制**: 虽然公共别名是全局可见的,但是用户要访问实际数据,必须被授予对昵称(或公共别名所指向的对象)的相应权限。例如: ```sql GRANT SELECT ON local_schema.remote_table TO PUBLIC; ``` 这样,所有用户都可以通过公共别名`global_table`进行查询。 7. **与.def文件结合的最佳实践**: 在编写.def文件时,建议将公共别名的创建与联邦对象的创建放在同一个事务中,以确保一致性。但注意,DB2中DDL是自动提交的,所以不能放在一个事务中。因此,要确保脚本按顺序执行,并且每一步都成功。 8. **错误处理**: 如果.def文件中的某条语句失败(例如因为对象已存在),可以使用`db2`命令的`-c`选项(自动提交)或使用`BEGIN`和`COMMIT`来管理事务(但DDL通常自动提交,所以需要单独处理)。 由于公共别名和.def文件都是DB2中的高级特性,这里只提供一个基本的使用框架。具体配置需要根据实际环境调整。 如果用户的问题不是针对联邦数据库,而是其他上下文中的.def文件(比如DB2的导出定义文件),那么需要进一步澄清。但根据之前的对话(用户提到了DB2公共别名),联邦数据库是最可能的场景。 因此,总结回答如下: ### DB2公共别名与.def文件的使用配置 在DB2联邦数据库系统中,`.def`文件通常用于定义联邦对象(包装器、服务器、用户映射和昵称)。公共别名(Public Alias)可以与这些联邦对象结合,为远程数据提供全局访问点。 #### 典型配置流程 1. **创建联邦对象** 在`.def`文件定义远程数据源访问: ```sql -- 创建DRDA包装器 CREATE WRAPPER drda_wrapper LIBRARY 'libdb2drda.so'; -- 创建目标服务器 CREATE SERVER prod_server TYPE DB2/LINUX WRAPPER drda_wrapper OPTIONS (DBNAME 'remote_db', HOST '192.168.1.100', PORT '50000'); -- 映射本地用户到远程认证 CREATE USER MAPPING FOR db2user SERVER prod_server OPTIONS (REMOTE_AUTHID 'remote_user', REMOTE_PASSWORD 'password'); -- 为远程表创建昵称 CREATE NICKNAME fed_schema.remote_customers FOR prod_server.remote_schema.customers; ``` 2. **为昵称添加公共别名** 在同一个`.def`文件中追加公共别名创建语句: ```sql CREATE PUBLIC ALIAS global_customers FOR fed_schema.remote_customers; ``` 3. **执行定义文件** 使用命令行工具部署配置: ```bash db2 -tvf federation_config.def ``` 4. **权限授予**(可选步骤) 如果希望所有用户都能访问,需显式授权: ```sql GRANT SELECT ON fed_schema.remote_customers TO PUBLIC; ``` #### 权限控制机制 | 对象 | 权限要求 | 说明 | |------------------|------------------------------|-------------------------------| | 公共别名 | 自动获得访问权 | 任何用户可直接使用别名查询 | | 底层昵称 | 需显式`GRANT` | 实际控制数据访问能力[^2] | | 远程数据源 | 依赖用户映射的认证信息 | 通过`USER MAPPING`传递凭证 | #### 注意事项 1. **执行顺序** 必须确保昵称创建成功后再创建公共别名,否则会报错`SQL0204N` 2. **错误处理** 建议在`.def`文件中使用`--`注释掉已存在的对象创建语句,或通过条件检查避免重复创建 3. **安全风险** 公共别名+`GRANT TO PUBLIC`会使所有用户都能访问数据,生产环境应使用更细粒度的角色授权 4. **依赖关系** 删除昵称时需先删除公共别名,否则会导致残留无效别名 > 示例错误:当昵称被删除后访问公共别名 > ```sql > SELECT * FROM global_customers; > -- SQL0601N 别名 "GLOBAL_CUSTOMERS" 所指向的对象不存在 > ``` #### 高级应用:联邦模块别名 在跨数据库函数调用场景中,可为远程模块创建公共别名: ```sql CREATE PUBLIC ALIAS db_mon FOR MODULE dba_tools.monitoring@remote_db; ``` 调用时直接使用别名: ```sql CALL db_mon.check_tablespace(); -- 无需指定远程模式路径[^1] ``` ### 相关问题 1. 如何避免公共别名与本地表名冲突? 2. 在DB2联邦系统中如何监控公共别名的使用性能? 3. 公共别名是否支持DB2 pureScale环境下的高可用?</think>### DB2公共别名与.def文件配置详解 在DB2中,`.def`文件通常用于**联邦数据库配置**(Federated Systems),而公共别名(Public Alias)可与其结合使用,实现跨数据源的全局访问点。以下是关键配置和使用方法: #### 1. .def文件的核心作用 `.def`文件是**联邦对象定义文件**,包含创建远程数据源访问所需的SQL语句: ```sql -- 示例:federation.def 文件内容 CREATE WRAPPER DRDA LIBRARY 'libdb2drda.so'; -- DRDA协议包装器[^1] CREATE SERVER remote_db TYPE DB2/LINUX WRAPPER DRDA OPTIONS (DBNAME 'prod_db', HOST '192.168.1.100'); CREATE USER MAPPING FOR local_user SERVER remote_db OPTIONS (REMOTE_AUTHID 'remote_user', REMOTE_PASSWORD 'pass123'); CREATE NICKNAME fed_schema.remote_table FOR remote_db.remote_schema.table; ``` #### 2. 公共别名与联邦对象集成 为联邦昵称(Nickname)创建公共别名,提供全局访问入口: ```sql -- 在联邦对象创建后执行 CREATE PUBLIC ALIAS global_table FOR fed_schema.remote_table; ``` 此时所有用户可直接访问: ```sql SELECT * FROM global_table; -- 无需知道底层联邦细节 ``` #### 3. 完整配置流程 | 步骤 | 操作 | 命令示例 | |------|------|----------| | 1 | 创建包装器(Wrapper) | `CREATE WRAPPER DRDA...` | | 2 | 定义远程服务器 | `CREATE SERVER remote_db...` | | 3 | 配置用户映射 | `CREATE USER MAPPING...` | | 4 | 创建昵称 | `CREATE NICKNAME...` | | **5** | **添加公共别名** | `CREATE PUBLIC ALIAS...` | | 6 | 执行.def文件 | `db2 -tvf federation.def` | #### 4. 权限控制要点 - **公共别名权限**:自动授予所有用户`SELECT`权限 - **底层数据权限**:需单独授权联邦对象[^2] ```sql GRANT SELECT ON fed_schema.remote_table TO PUBLIC; ``` #### 5. 故障排查常见错误 - **SQL0601N**:别名指向的对象不存在 → 检查联邦服务器状态 - **SQL30082N**:认证失败 → 验证`.def`中的`USER MAPPING`凭证 - **SQL0204N**:对象未定义 → 确认昵称创建顺序在别名之前 #### 6. 最佳实践建议 1. **命名规范**:使用`global_`前缀区分公共别名 2. **版本兼容**:DB2 11.5+推荐使用`CREATE FEDERATED SERVER`替代传统.def 3. **安全加固**: ```sql REVOKE CREATE_PUBLIC_ALIAS FROM PUBLIC; -- 限制别名创建权限 ``` 4. **依赖管理**:删除顺序必须为: ```sql DROP PUBLIC ALIAS global_table; DROP NICKNAME fed_schema.remote_table; ``` > **性能提示**:在联邦查询中使用公共别名时,启用`FEDERATED_OPTIMIZATION`参数可提升效率[^3]: > ```sql > SET CURRENT MAINTAINED TABLE TYPES FOR OPTIMIZATION = ALL; > ``` ### 典型应用场景 **跨云数据库统一接口**: ```sql -- AWS RDS SQL Server联邦访问 CREATE PUBLIC ALIAS global_orders FOR fed_schema.aws_orders; -- Azure Cosmos DB联邦访问 CREATE PUBLIC ALIAS global_users FOR fed_schema.azure_users; ``` 应用层只需调用`global_orders`/`global_users`,无需感知后端数据源变化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值