QNX-9—QNX官网文档翻译—Resource Managers—Alphabetical listing of connect and I/O functions
注:本文翻译自
QNX Software Development Platform --> Programming --> Getting Started with QNX Neutrino --> Resource Managers
http://www.qnx.com/developers/docs/7.1/index.html#com.qnx.doc.neutrino.getting_started/topic/s1_resmgr_alphalist.html
一、Alphabetical listing of connect and I/O functions
1. Access control list I/O function handler
Prototype:
int (*acl)( resmgr_context_t *ctp, io_acl_t *msg, RESMGR_OCB_T *ocb )
Classification: I/O
Default handler: iofunc_acl_default()
Helper functions: iofunc_acl()
Client functions: acl_*(),如 acl_set_permset()
Messages: _IO_ACL
Data structure:
struct _io_acl { uint16_t type; uint16_t combine_len; uint32_t subtype; int32_t zero[2]; /* struct _acl_header hdr; */ /* void acl_data */ }; enum _io_acl_subtypes { _IO_ACL_GET, _IO_ACL_SET, _IO_ACL_CHK }; struct _io_acl_reply { uint32_t zero[4]; /* struct _acl_header hdr; */ /* void acl_data */ }; typedef union { struct _io_acl i; struct _io_acl_reply o; } io_acl_t;
Description: 获取、设置或检查访问控制列表 (ACL)。
返回:通过辅助宏 _RESMGR_STATUS() 和回复缓冲区(如果需要,带有回复数据)的状态。
引用者:resmgr_io_funcs_t I/O table
权限检查:默认实现 iofunc_acl_default() 调用辅助函数 iofunc_acl()),该函数不执行任何权限检查,也不需要任何权限检查。
2. Change file mode I/O function handler
Prototype:
int (*chmod) ( resmgr_context_t *ctp, io_chmod_t *msg, RESMGR_OCB_T *ocb )
Classification: I/O function
Default handler: iofunc_chmod_default()
Helper functions: iofunc_ability_check(), iofunc_chmod()
Client functions: chmod(), fchmod(), fchmodat()
Messages: _IO_CHMOD
Data structure:
struct _io_chmod { uint16_t type; uint16_t combine_len; mode_t mode; }; typedef union { struct _io_chmod i; } io_chmod_t;
Description: 负责将传递的 ocb 标识的资源的模式更改为模式消息成员指定的值。
Returns: 通过辅助宏 _RESMGR_STATUS() 获取状态。
引用者:resmgr_io_funcs_t I/O 表
权限检查:默认实现 iofunc_chmod_default() 调用辅助函数 iofunc_chmod() 来检查客户端是否是文件的所有者(即,它具有相同的用户 ID)并且它不是只读文件系统。 辅助功能还可以防止用户设置粘性位和设置组 ID 位,除非它是 root。
3. Change ownership I/O function handler
Prototype:
int (*chown)( resmgr_context_t *ctp, io_chown_t *msg, RESMGR_OCB_T *ocb )
Classification: I/O function
Default handler: iofunc_chown_default()
Helper functions: iofunc_ability_check(), iofunc_chown()
Client functions: chown(), fchown(), fchownat()
Messages: _IO_CHOWN
Data structure:
struct _io_chown { uint16_t type; uint16_t combine_len; int32_t gid; int32_t uid; }; typedef union { struct _io_chown i; } io_chown_t;
Description: 负责将传递的 ocb 标识的资源的用户 ID 和组 ID 字段分别更改为 uid 和 gid。 请注意,应检查挂载结构标志 IOFUNC_PC_CHOWN_RESTRICTED 和 OCB 标志字段,以确定文件系统是否允许非 root 用户执行 chown()。
返回:通过辅助宏 _RESMGR_STATUS() 获取状态。
引用者:resmgr_io_funcs_t I/O 表
权限检查:默认实现 iofunc_chown_default() 调用辅助函数 iofunc_chown() 来检查 IOFUNC_PC_CHOWN_RESTRICTED 标志,以确定是否允许用户更改条目上的用户 ID。 帮助器函数还检查客户端是否具有 iofunc/chown (IOFUNC_ABILITY_CHOWN) 动态能力(使用 iofunc_ability_check(),这允许它像 root 一样设置用户 ID。最后,帮助器检查以确保它不是只读文件系统。
当 iofunc_chown() 设置新的用户 ID 或组 ID 时,它会删除设置的用户 ID 和设置的组 ID 位(如果它们已在文件中设置)。 用户或组 ID 的值为 -1 意味着调用者不想更改该 ID。
4. Change timestamps I/O function handler
Prototype:
int (*utime) ( resmgr_context_t *ctp, io_utime_t *msg, RESMGR_OCB_T *ocb )
Classification: I/O
Default handler: iofunc_utime_default()
Helper functions: iofunc_utime()
Client function: utime()
Messages: _IO_UTIME or _IO_UTIME64
Data structure:
struct _io_utime { uint16_t type; uint16_t combine_len; int32_t cur_flag; struct __utimbuf32 times; }; struct _io_utime64 { uint16_t type; uint16_t combine_len; int32_t cur_flag; int64_t atime_s; int64_t atime_ns; int64_t mtime_s; int64_t mtime_ns; }; typedef union { struct _io_utime i; struct _io_utime i64; } io_utime_t;
描述:将访问和修改时间更改为“现在”(如果为零)或指定值。 请注意,可能需要此消息处理程序根据 POSIX 规则修改属性结构中的 IOFUNC_ATTR_* 标志。 您自己几乎永远不会使用此呼出,而是使用 POSIX 层帮助函数。
返回:通过辅助宏 _RESMGR_STATUS() 获取状态。
引用者:resmgr_io_funcs_t I/O 表
权限检查:默认实现 iofunc_utime_default() 调用辅助函数 iofunc_utime() 来检查该条目是否由当前用户拥有或当前用户对其具有写访问权限。 该帮助程序还检查只读文件系统。 实体的所有者可以设置任意时间,而只有写权限的用户只能设置当前时间(cur_flag 为 1)。
5. Close duplicate OCB I/O function handler
Prototype:
int (*close_dup) ( resmgr_context_t *ctp, io_close_t *msg, RESMGR_OCB_T *ocb )
Classification: I/O function
Default handler: iofunc_close_dup_default()
Helper functions: iofunc_close_dup()
Client functions: close(), fclose()
Messages: _IO_CLOSE
Data structure:
struct _io_close { uint16_t type; uint16_t combine_len; }; typedef union { struct _io_close i; } io_close_t;
描述:这是客户端 close() 或 fclose() 函数调用的真正函数处理程序。
如果你接管这个函数,除了你所做的工作之外,你几乎总是会调用 iofunc_close_dup_default() 。 这是因为基础层跟踪为特定 OCB 发出的 open()、dup() 和 close() 消息的数量,然后当 已收到特定 OCB 的最后 close() 消息。
请注意,ctp->rcvid 中存在的接收 ID 不一定与传递给打开连接函数处理程序的接收 ID 匹配。 例如,当客户端在未发送 _IO_CLOSE 的情况下断开连接时,资源管理器框架会处理生成的脉冲并伪造 _IO_CLOSE 消息。 任何通过 ctp->rcvid(应该为 0)直接回复此消息的尝试,或者将其保留为“阻止”并稍后回复的尝试都将失败。
如果您的资源管理器使客户端被阻止(例如,在 read()、write() 或 devctl() 调用时),您将需要接管此函数,以便您可以跟踪哪些客户端被阻止,如果有必要的话并取消阻止。 有关更多信息,请参阅《编写资源管理器》的“解除阻止客户端和处理中断”一章中的 “Unblocking if someone closes the file descriptor”。
与大多数其他 I/O 函数处理程序不同,资源管理器框架运行 close_dup() 而不锁定 OCB 结构 (ocb)。如果您需要修改此结构中的字段并且您的服务器进程是多线程的,则必须序列化对该结构的访问以避免竞争条件。 有关更多信息,请参阅编写资源管理器中的“如果有人关闭文件描述符则解除阻塞”中有关锁定属性结构的注释。
返回:通过辅助宏 _RESMGR_STATUS() 获取状态。
引用者:resmgr_io_funcs_t I/O Table
权限检查:默认实现 iofunc_close_dup_default() 调用辅助函数 iofunc_close_dup(),该函数不执行任何权限检查。
6. Close OCB I/O function handler
Prototype:
int (*close_ocb) ( resmgr_context_t *ctp, void *reserved, RESMGR_OCB_T *ocb )
Classification: I/O function (synthesized by library)
Default handler: iofunc_close_ocb_default()
Helper functions: none
Client function: none—synthesized by library
Messages: none—synthesized by library
Data structure:
// synthesized by library struct _io_close { uint16_t type; uint16_t combine_len; }; typedef union { struct _io_close i; } io_close_t;
描述:这是当收到特定 OCB 的最后一个 close() 时由基础层库合成的函数。 您可以在 OCB 被销毁之前执行所需的任何最终清理工作。 请注意,ctp->rcvid 中的接收 ID 为零,因为该函数是由库合成的,不一定对应于任何特定消息。
返回:通过辅助宏 _RESMGR_STATUS() 获取状态。
参考者:resmgr_io_funcs_t I/O table
权限检查:默认实现 iofunc_close_ocb_default() 和辅助函数 iofunc_close_ocb() 不执行权限检查。 无需进行权限检查。 如果您创建了自己的 OCB,则只需实现此函数(另请参阅 iofunc_close_ocb_calloc 和 iofunc_close_ocb_free)。
7. Create file link connect function handler
Prototype:
int (*link) ( resmgr_context_t *ctp, io_link_t *msg, RESMGR_HANDLE_T *handle, io_link_extra_t *extra )
Classification: Connect
Default handler: none
Helper functions: iofunc_link()
Client functions: link(), linkat(), symlink(), symlinkat()
Messages: _IO_CONNECT with subtype _IO_CONNECT_LINK
Data structure:
struct _io_connect { // internal fields (as described above) uint16_t path_len; uint8_t extra_type; uint16_t extra_len; char path [1]; }; struct _io_connect_link_reply { uint32_t reserved1; uint32_t file_type; uint8_t eflag; uint8_t reserved2[1]; uint16_t chroot_len; uint32_t umask; uint16_t nentries; uint16_t path_len; }; struct _io_connect_ftype_reply { uint16_t status; /* Typically an errno */ uint16_t reserved; uint32_t file_type; /* _FTYPE_? in sys/ftype.h */ }; typedef union { struct _io_connect connect; struct _io_connect_link_reply link_reply; struct _io_connect_ftype_reply ftype_reply; } io_link_t; typedef union _io_link_extra { struct _msg_info info; void *ocb; char path [1]; struct _io_resmgr_link_extra resmgr; } io_link_extra_t;
描述:使用 msg 的路径成员中给定的名称创建一个新链接,链接到 extra 的路径成员指定的现有路径名(传递给您的函数)。 为了方便起见,extra 的 ocb 成员包含一个指向现有路径名的 OCB 的指针。
返回:通过辅助宏 _RESMGR_STATUS() 获取状态。
参考者:resmgr_connect_funcs_t 连接表
权限检查:iofunc_link() 函数使用带有 S_ISUID、S_ISGID 和 S_IREAD 标志的 iofunc_check_access() 来检查 OCB 上现有路径名的访问。
8. Device control I/O function handler
Prototype:
int (*devctl) (resmgr_context_t *ctp, io_devctl_t *msg, RESMGR_OCB_T *ocb )
Classification: I/O
Default handler: iofunc_devctl_default()
Helper functions: iofunc_devctl(), iofunc_devctl_verify()
Client functions: devctl(), ioctl()
Messages: _IO_DEVCTL
Data structure:
struct _io_devctl { uint16_t type; uint16_t combine_len; int32_t dcmd; uint32_t nbytes; int32_t zero; }; struct _io_devctl_reply { uint32_t zero; int32_t ret_val; uint32_t nbytes; int32_t zero2; }; typedef union { struct _io_devctl i; struct _io_devctl_reply o; } io_devctl_t;
描述:执行从 dcmd 中客户端的 devctl() 传递的设备 I/O 操作。 客户端将方向编码到 dcmd 的前两位中,指示 devctl() 如何传输数据(“to”字段指 _POSIX_DEVDIR_TO 位;“from”字段指 _POSIX_DEVDIR_FROM 位):
-------------------------------------------- to field from field Meaning -------------------------------------------- 0 0 无数据传输 0 1 从驱动程序传输到客户端 1 0 从客户端传输到驱动程序 1 1 双向传输 --------------------------------------------
在没有数据传输的情况下,驱动程序应简单地执行 dcmd 中给出的命令。
(1) 访问客户端发送的数据
如果客户端提供数据,它会紧跟在 msg 参数提供的 io_devctl_t 标头之后。 在访问任何数据之前,您需要验证其长度。
由于组合消息会使确定消息的长度变得更加复杂,因此当您禁止使用它们时,验证会更简单。 (允许组合消息没有任何优势。)
为了防止使用组合消息,请检查 ctp->rcvid 是否为零,如果为零则返回错误。
检查消息长度的方式取决于您要处理的消息的长度:
a. 如果处理程序仅处理短消息(小于 1500 字节),则消息长度为 ctp->size。 这种类型的处理程序稍微简单一些。
b. 如果处理程序必须处理大消息,则消息长度为 (ctp->info.srcmsglen – ctp->offset)。 然而,在这种情况下,消息缓冲区中只有 ctp->size 可以直接使用。 您需要使用 resmgr_msgget() 或 resmgr_msgread() 等函数读取其余部分。
如果您的处理程序支持多个设备控制操作,则您可能拥有来自这两个类别的操作。
您需要验证实际消息长度至少与预期长度一样大。 如果您需要访问消息的任何部分以确定预期大小,则需要确保 ctp->size 足够大以包含此数据。
验证消息长度后,您需要访问数据。 如果您的设备控制操作仅处理短消息(上面的类别 1),则消息有效负载完全包含在消息缓冲区中。 如果您的操作必须处理大消息(类别 2),您可能必须使用 resmgr_msgget() 或 resmgr_msggetv() 来读取至少部分有效负载。
(2) 返回数据给客户端
如果可以的话,在执行请求之前,您应该验证将返回的数据量加上 io_devctl_t 标头的大小是否小于或等于 ctp->info.dstmsglen。 否则,客户端将不会收到您发送的所有数据。 如果您的设备控制操作返回的数据量是可变的,则返回的数据最好包括大小或计算方法。
(3) 结构填充
请注意,输入和输出数据结构是用零填充的,以便它们彼此对齐。 这意味着隐式数据区域从输入和输出结构中的相同地址开始。
(4) 无法识别的命令
如果使用辅助例程 iofunc_devctl(),请注意,如果它无法对 devctl() 消息执行任何操作,它将返回常量 _RESMGR_DEFAULT。 该返回值用于将合法的 errno 返回值与“无法识别的命令”返回值分离。 收到 _RESMGR_DEFAULT 后,基础层库将响应 ENOSYS 错误号,客户端的 devctl() 库函数将其转换为 ENOTTY。
(5) 检查打开模式
由您的函数根据操作检查打开模式; 在客户端的 devctl() 库或资源管理器库中的任何地方都不会进行任何检查。 例如,可以“只读”打开资源管理器,然后向其发出 devctl() 告诉它“格式化硬盘”(这在很大程度上是一个“写入”操作)。 在继续操作之前,请先验证打开模式是谨慎的做法。
有关检查消息安全性和有效性的更多信息,请参阅下面“Permission checking.”。
(6) 可用的 dcmd 值
请注意,您可以使用的 dcmd 值的范围是有限的(0x0000 到 0x0FFF(含)为 BlackBerry QNX 保留)。 可能使用其他值; 查看名为 <sys/dcmd_*.h> 的包含文件。
返回:通过辅助宏 _RESMGR_STATUS() 和回复缓冲区(如果需要,带有回复数据)的状态。例如,请查看下面的 “A simple device control I/O function handler example,” 。
引用者:resmgr_io_funcs_t I/O 表
权限检查:
默认实现 iofunc_devctl_default() 处理程序不执行权限检查,因为该处理程序不实现任何需要保护的功能。 实现 devctl() 的资源管理器必须根据要执行的命令应用权限检查。 由于 devctl() 操作的灵活性,这很复杂。 例如,当更改串行设备的波特率时,可以打开该设备进行只读访问,然后执行 devctl() 来更改波特率。 尽管此操作执行修改,但它不需要已打开文件描述符进行写入。 因此,每个单独的 devctl() 命令通常需要进行适当的权限检查。
处理 devctl() 的可能方法包括以下策略:
(1) 根据文件打开模式强制执行全局权限检查。 例如,如果尚未打开 OCB 进行写访问,则资源管理器坚持根本不执行 devctl() 操作可能是可以接受的,如以下代码所示(位于 devctl() 的开头) 处理函数):
if (!(ocb->ioflag & _IO_FLAG_WR)) { return EPERM; }
(2) 执行特定于命令的权限检查,检查每个 devctl() 操作,以确定必须根据命令的特定功能强制执行的权限。 您还可以实施类似于以下检查的检查,该检查验证文件是否以读取权限打开:
if ( (ocb->ioflag & _IO_FLAG_RD) == 0 ) { return EPERM; }
QNX 不建议使用 iofunc_devctl_verify() 执行验证。
有关包含权限和长度检查的示例处理程序,请参阅 “A simple device control I/O function handler example” 。
9. Duplicate a file descriptor I/O function handler
10. File descriptor information I/O function handler
11. File locking I/O function handler
12. Flush data I/O function handler
13. Lock OCB I/O function handler
原型:
int (*lock_ocb) ( resmgr_context_t *ctp, void *reserved, RESMGR_OCB_T *ocb )
分类:I/O(由库合成)
默认处理程序:iofunc_lock_ocb_default()
辅助函数:无
客户端函数:全部
消息:无——由库合成
数据结构:没有
描述:
该函数负责锁定 OCB 指向的属性结构。 这样做是为了确保一次只有一个线程可以对 OCB 和相应的属性结构进行操作。 锁定(和相应的解锁)函数由资源管理器库在消息处理完成之前和之后合成。有关更多详细信息,请参阅上面的 “Combine messages” 部分。 你自己几乎永远不会使用这种调用; 相反,使用 POSIX 层默认函数。
返回:通过辅助宏 _RESMGR_STATUS() 获取状态。
引用者:resmgr_io_funcs_t I/O table
权限检查:默认实现 iofunc_lock_ocb_default() 不执行任何权限检查,并且没有辅助函数。 无需进行权限检查。
14. Make filesystem node connect function handler
15. Map memory I/O function handler
16. Mount connect function handler
17. Open connect function handler
Prototype:
int (*open) (resmgr_context_t *ctp, io_open_t *msg, RESMGR_HANDLE_T *handle, void *extra )
Classification: Connect
Default handler: iofunc_open_default()
Helper functions: iofunc_ability_check(), iofunc_ocb_attach(), iofunc_open()
Client functions: open(), openat(), fopen(), sopen() (and others)
Messages: _IO_CONNECT with one of _IO_CONNECT_COMBINE, _IO_CONNECT_COMBINE_CLOSE or _IO_CONNECT_OPEN subtypes.
Data structure:
struct _io_connect { // internal fields (as described above) uint16_t path_len; uint8_t extra_type; uint16_t extra_len; char path [1]; }; struct _io_connect_link_reply { uint32_t reserved1; uint32_t file_type; uint8_t eflag; uint8_t reserved2[1]; uint16_t chroot_len; uint32_t umask; uint16_t nentries; uint16_t path_len; }; struct _io_connect_ftype_reply { uint16_t status; /* Typically an errno */ uint16_t reserved; uint32_t file_type; /* _FTYPE_? in sys/ftype.h */ }; typedef union { struct _io_connect connect; struct _io_connect_link_reply link_reply; struct _io_connect_ftype_reply ftype_reply; } io_open_t;
描述:这是新文件描述符的处理函数。 它检查客户端是否确实具有打开文件的适当权限,将 OCB 绑定到内部库结构(通过 resmgr_bind_ocb() 或 iofunc_ocb_attach()),并返回 errno。 请注意,并非所有输入和输出结构成员都与此函数相关。
返回:通过辅助宏 _IO_SET_CONNECT_RET() 获取状态。
引用者:resmgr_connect_funcs_t connect table
权限检查:当您覆盖默认函数时,QNX 建议您在实现任何附加功能之前调用 iofunc_open_default()(它根据请求的访问权限实现多项权限检查)。 请注意,由于文件可以在没有读或写权限的情况下打开,因此在实现锁定之类的操作之前检查 iofunc_open_default() (或相关的 iofunc_open())是否返回 EOK 是不够的(例如,对于一次只能由一名客户端打开访问的资源)。
18. Open file descriptor I/O function handler
Prototype:
int (*openfd) ( resmgr_context_t *ctp, io_openfd_t *msg, RESMGR_OCB_T *ocb )
Classification: I/O
Default handler: iofunc_openfd_default()
Helper functions: iofunc_ability_check(), iofunc_openfd()
Client function: openfd()
Messages: _IO_OPENFD
Data structure:
struct _io_openfd { uint16_t type; uint16_t combine_len; uint32_t ioflag; uint16_t sflag; uint16_t reserved1; struct _msg_info32 info; uint32_t reserved2; uint32_t key; }; typedef union { struct _io_openfd i; } io_openfd_t;
描述:
此函数类似于为 open connect 函数提供的处理程序,不同之处在于传递的不是路径名,而是已打开的文件描述符(通过在函数调用中传递 ocb)##########。
返回:
通过辅助宏 _RESMGR_STATUS() 获取状态。
引用者:
resmgr_io_funcs_t I/O table
权限检查:
默认实现 iofunc_openfd_default() 检查扩展类型,然后调用辅助函数 iofunc_openfd。 帮助程序功能确保新权限的限制不低于当前打开的访问模式。
19. pathconf I/O function handler
20. Power I/O function handler
21. Read I/O function handler
Prototype:
int (*read) ( resmgr_context_t *ctp, io_read_t *msg, RESMGR_OCB_T *ocb )
Classification: I/O
Default handler: iofunc_read_default()
Helper functions: iofunc_read_verify()
Client functions: read(), readdir()
Messages: _IO_READ, _IO_READ64
Data structure:
struct _io_read { uint16_t type; uint16_t combine_len; uint32_t nbytes; uint32_t xtype; uint32_t zero; }; struct _io_read64 { uint16_t type; uint16_t combine_len; uint32_t nbytes; uint32_t xtype; uint32_t nbytes_hi; }; typedef union { struct _io_read i; struct _io_read i64; /* unsigned char data[nbytes]; */ /* nbytes is returned with MsgReply */ } io_read_t;
描述:
负责从资源中读取数据。 客户端在 nbytes 输入成员中指定准备读取的字节数。 您返回数据,提前 OCB 中的偏移量,并更新相应的时间字段。
请注意以下事项:
(1) 仅当长度大于 4 GB 时,客户端库才使用 _IO_READ64 形式。 您可以使用 _IO_READ_GET_NBYTES() 宏(在 <sys/iofunc.h> 中定义)来确定字节数。
(2) xtype 成员可以指定per-read-message覆盖标志。 应该对此进行检查。 如果您不支持任何扩展覆盖标志,则应返回 EINVAL。 我们将在下面的读 I/O 函数处理程序和写 I/O 函数处理程序示例中看到一个特别重要(且棘手!)的覆盖标志(称为 _IO_XTYPE_OFFSET)的处理。
(3) _IO_READ 或 _IO_READ64 消息的到达不仅用于常规文件,还用于读取目录的内容。 您必须确保在目录情况下返回整数个 struct dirent 成员。 有关返回目录条目的更多信息,请参阅“高级主题”部分中 “Returning directory entries.” 下的示例。
在 QNX Neutrino 7.0 或更高版本中,readdir() 将 xtype 设置为 _IO_XTYPE_READDIR。 如果有人尝试从目录中 read(),则此消息的处理程序可能会给出错误。
您应该调用辅助函数 iofunc_read_verify() 来确定文件是否以与读取兼容的模式打开。 您还应该调用 iofunc_sync_verify() 函数来验证数据是否需要同步到介质。(对于 read(),这意味着返回的数据保证位于介质上。)
返回:
通过辅助宏 _IO_SET_READ_NBYTES() 读取的字节数或状态,以及通过消息回复的数据本身。 有关仅返回数据的示例,请查看下面的“A simple read I/O function handler example”。 有关返回数据和目录条目的更复杂示例,请查看“返回目录条目”下的“高级主题”部分。
引用者:
resmgr_io_funcs_t I/O table
权限检查:
默认实现 iofunc_read_default() 调用 iofunc_read_verify(),然后不返回任何数据。 由于可以在没有读或写权限的情况下打开文件,因此您必须验证 OCB 是否已在每次调用中打开以供读取。 iofunc_read_verify() 函数默认执行此操作。此外,资源管理器应该验证扩展类型(xtype;请参阅编写资源管理器中的 “If you aren't expecting extended types (xtype)” )。
22. Read link connect function handler
23. Rename connect function handler
24. Register for notification I/O function handler
Prototype:
int (*notify) ( resmgr_context_t *ctp, io_notify_t *msg, RESMGR_OCB_T *ocb )
Classification: I/O
Default handler: none
Helper functions: iofunc_notify(), iofunc_notify_remove(), iofunc_notify_remove_strict(), iofunc_notify_trigger(), iofunc_notify_trigger_strict()
Client functions: poll(), select(), ionotify()
Messages: _IO_NOTIFY, _IO_NOTIFY64
Data structure:
struct _io_notify { uint16_t type; uint16_t combine_len; int32_t action; int32_t flags; struct __sigevent32 event; /* The fields `mgr` to `timo` are only valid if (flags & _NOTIFY_COND_EXTEN) * The full header must be present regardless of the flags. */ int32_t mgr[2]; /* For use by manager */ int32_t flags_extra_mask; int32_t flags_exten; int32_t nfds; int32_t fd_first; int32_t nfds_ready; int64_t timo; /* struct pollfd fds[nfds]; */ }; struct _io_notify64 { uint16_t type; uint16_t combine_len; int32_t action; int32_t flags; struct __sigevent32 old_event; /* The fields `mgr` to `timo` are only valid if (flags & _NOTIFY_COND_EXTEN) * The full header must be present regardless of the flags. */ int32_t mgr[2]; /* For use by manager */ int32_t flags_extra_mask; int32_t flags_exten; int32_t nfds; int32_t fd_first; int32_t nfds_ready; int64_t timo; union { struct __sigevent32 event32; struct __sigevent64 event64; }; /* struct pollfd fds[nfds]; */ }; struct _io_notify_reply { uint32_t zero; uint32_t flags; /* actions above */ int32_t flags2; /* flags above */ struct __sigevent32 event; /* Following fields only updated by new managers (if valid) */ int32_t mgr[2]; /* For use by manager */ int32_t flags_extra_mask; int32_t flags_exten; int32_t nfds; int32_t fd_first; int32_t nfds_ready; int64_t timo; /* struct pollfd fds[nfds]; */ }; struct _io_notify_reply64 { uint32_t zero; uint32_t flags; /* actions */ int32_t flags2; /* flags above */ struct __sigevent32 old_event; /* Following fields only updated by new managers (if valid) */ int32_t mgr[2]; /* For use by manager */ int32_t flags_extra_mask; int32_t flags_exten; int32_t nfds; int32_t fd_first; int32_t nfds_ready; int64_t timo; union { struct __sigevent32 event32; struct __sigevent64 event64; }; /* struct pollfd fds[nfds]; */ }; typedef union { struct _io_notify i; struct _io_notify64 i64; struct _io_notify_reply o; struct _io_notify_reply64 o64; } io_notify_t;
描述:
该处理程序负责安装、轮询或删除通知处理程序。 action 和 flags 决定了通知操作的种类和条件; 该事件是一个 struct sigevent 结构,它定义了客户端希望收到信号的通知事件(如果有)。 您可以使用 MsgDeliverEvent() 或 iofunc_notify_trigger() 函数将事件传递给客户端。
返回:
通过辅助宏 _RESMGR_STATUS() 获取状态; 标志通过消息回复返回。
引用者:
resmgr_io_funcs_t I/O table
权限检查:
iofunc_notify() 辅助函数不执行权限检查。 但是,如果尚未打开 OCB 进行读取,则可能不允许请求该 OCB 上发生的与读取数据相关的条件的通知(例如,设置了 _NOTIFY_CONDE_RDNORM 标志)。 与读取或写入数据无关的通知(例如,_NOTIFY_CONDE_HUP 和 _NOTIFY_CONDE_NVAL)不需要与读取或写入访问绑定。 尽管在这种情况下信息泄漏非常有限(例如,了解文件描述符何时准备好读取或写入或具有可用的带外数据),但它可能被用于各种攻击,例如竞争条件。 QNX 建议您拒绝对尚未打开文件描述符进行读取或写入的调用方进行 notification() 调用。 彻底的权限检查将根据提供给notify()函数的标志来应用适当的决定。
对于处理用户输入(例如键盘)的资源管理器,请注意不要通过通知消息的传递泄漏计时数据。 攻击者可以使用此计时数据来构建用户输入内容的配置文件。 同样,不要提供特定于进程的特征(例如 CPU 使用情况和分配内存的变化)的通知。
25. Resize file I/O function handler
26. Set file position I/O function handler
27. Shutdown I/O function handler
28. stat I/O function handler
29. Unblock connect function handler
原型:
int (*unblock) ( resmgr_context_t *ctp, io_pulse_t *msg, RESMGR_HANDLE_T *handle, void *reserved )
分类:Connect(由内核、库进行合成)
默认处理程序:无
辅助函数:iofunc_unblock()
客户端函数:none——这是由于信号或超时而导致的内核操作
消息:无 —— 由库合成
数据结构:(参见解锁功能的I/O版本)
描述:这是解锁呼出的连接消息版本,由库根据客户端在连接消息阶段尝试解锁而产生的内核脉冲而合成。 有关更多详细信息,请参阅解锁 I/O 函数处理程序。
返回:通过辅助宏 _RESMGR_STATUS() 获取状态。
有关解锁策略的详细讨论,请参阅消息传递一章中标题为 “Using the _NTO_MI_UNBLOCK_REQ” 的部分。
引用者:resmgr_connect_funcs_t table
权限检查:iofunc_unblock() 函数不执行任何权限检查。
30. Unblock I/O function handler
原型:
int (*unblock) ( resmgr_context_t *ctp, io_pulse_t *msg, RESMGR_OCB_T *ocb )
分类:I/O(由内核、库合成)
默认处理程序:iofunc_unblock_default()
辅助函数:iofunc_unblock()
客户端函数:none——由于信号或超时而导致的内核操作
消息:无——由库合成
数据结构:指向被中断的消息结构的指针
描述:这是解锁呼出的 I/O 消息版本,由库合成,是由于客户端在 I/O 消息阶段尝试解锁而产生的内核脉冲的结果。 解锁连接函数处理程序基本相同(请参阅上一节)。
两个解锁处理程序(连接和 I/O)的共同点是客户端希望解锁,但受资源管理器的支配。 资源管理器必须回复客户端的消息才能解锁客户端。 (当我们查看 ChannelCreate() 标志,特别是 _NTO_CHF_UNBLOCK 标志时,这在消息传递章节中进行了讨论)。
返回:
通过辅助宏 _RESMGR_STATUS() 获取状态。
有关解锁策略的详细讨论,请参阅消息传递一章中标题为“使用 _NTO_MI_UNBLOCK_REQ”的部分。
引用者:resmgr_io_funcs_t I/O table
权限检查:默认实现 iofunc_unblock_default() 不执行任何权限检查。
31. Unlink connect function handler
32. Unlock OCB I/O function handler
原型:
int (*unlock_ocb) ( resmgr_context_t *ctp, void *reserved, RESMGR_OCB_T *ocb )
分类:I/O(由库合成)
默认处理程序:iofunc_unlock_ocb_default()
辅助函数:无
客户端功能:全部
消息:无 —— 由库合成
数据结构:无
描述:
是上面的“lock OCB I/O function handler”的逆操作。 也就是说,它负责解锁 OCB 指向的属性结构。 此操作释放属性结构,以便资源管理器中的其他线程可以对其进行操作。有关更多详细信息,请参阅上面的 “Combine messages” 部分。
返回:通过辅助宏 _RESMGR_STATUS() 获取状态。
引用者:resmgr_io_funcs_t I/O table
权限检查:默认实现 iofunc_unlock_ocb_default() 不执行任何权限检查,并且没有辅助函数。 无需进行权限检查。
33. User-defined message I/O function handler
原型:
int (*msg) ( resmgr_context_t *ctp, io_msg_t *msg, RESMGR_OCB_T *ocb )
分类:输入/输出
默认处理程序:无
辅助函数:无
客户端函数:无——手动组装并通过 MsgSend() 发送
消息:_IO_MSG
数据结构:
struct _io_msg { uint16_t type; uint16_t combine_len; uint16_t mgrid; uint16_t subtype; }; typedef union { struct _io_msg i; } io_msg_t;
描述:
与 devctl() 一样,_IO_MSG 接口允许您发送各种请求。 mgrid 用于识别特定的manager - 您不应该对不符合您的manager ID 的请求执行操作。 subtype 实际上是客户端希望执行的命令。 隐式传输的任何数据都遵循输入结构。 返回给客户端的数据自行发送,状态通过 _RESMGR_STATUS() 返回。
验证此处理程序消息的方法与设备控制 I/O 函数处理程序相同,但请注意以下差异:
(1) 与设备控制 I/O 函数处理程序(具有 devctl() 和 devctlv())不同,用户定义的消息处理程序没有 libc 函数来帮助发送消息。
(2) 输入标头的大小是 io_msg_t,而不是 io_devctl_t。
(3) 未定义输出标头。
返回:通过辅助宏 _RESMGR_STATUS() 获取状态。
引用者:resmgr_io_funcs_t I/O table
权限检查:
此函数没有默认处理程序或帮助程序。 它处理通过 MsgSend() 手动发送的消息。 任何权限检查都是特定于正在实现的功能的。 如果消息处理程序支持类似于 devctl() 的各种命令,则可能需要对每个命令进行访问检查。
34. Write I/O function handler
原型:
int (*write) ( resmgr_context_t *ctp, io_write_t *msg, RESMGR_OCB_T *ocb )
分类:输入/输出
默认处理程序:iofunc_write_default()
辅助函数:iofunc_write_verify()
客户端函数:write()、fwrite() 等
引用:_IO_WRITE,_IO_WRITE64
数据结构:
struct _io_write { uint16_t type; uint16_t combine_len; uint32_t nbytes; uint32_t xtype; uint32_t zero; /* unsigned char data[nbytes]; */ }; struct _io_write64 { uint16_t type; uint16_t combine_len; uint32_t nbytes; uint32_t xtype; uint32_t nbytes_hi; /* unsigned char data[nbytes]; */ }; typedef union { struct _io_write i; struct _io_write i64; /* nbytes is returned with MsgReply */ } io_write_t;
描述:
该消息处理程序负责获取客户端写入资源管理器的数据。它获取客户端尝试在 nbytes 成员中写入的字节数; 数据隐式遵循输入数据结构(除非 xtype 覆盖为 _IO_XTYPE_OFFSET;请参阅下面的 “A simple write I/O function handler example” !)该实现需要使用 resmgr_msggetv( ) 或同等内容。 返回状态是实际写入的字节数或错误号。
请注意以下事项:
(1) 要确保处理程序支持大于 4 GB 的写入(无论形式是 _IO_WRITE 还是 _IO_WRITE64),请使用 _IO_WRITE_GET_NBYTES() 宏(在 <sys/iofunc.h> 中定义)。
(2) 您应该使用辅助函数 iofunc_write_verify() 来确定文件是否以与写入兼容的模式打开。 您还应该调用 iofunc_sync_verify() 函数来验证数据是否需要同步到介质。
返回:
通过辅助宏 _IO_SET_WRITE_NBYTES() 获取状态。有关示例,请查看下面的“A simple write I/O function handler example”。
引用者:
resmgr_io_funcs_t I/O table
权限检查:
默认实现 iofunc_write_default() 调用 iofunc_write_verify(),然后默默地丢弃所有写入的数据。 由于可以在没有读或写权限的情况下打开文件,因此您必须验证 OCB 是否已在每次调用中打开以进行写入。 默认情况下,此验证是使用 iofunc_write_verify() 完成的。 此外,资源管理器应该验证扩展类型(xtype)。
posted on 2023-07-09 21:00 Hello-World3 阅读(306) 评论(0) 编辑 收藏 举报