!sphinx.addnodesdocument)}( rawsourcechildren]( translations LanguagesNode)}(hhh](h pending_xref)}(hhh]docutils.nodesTextEnglish}parenthsba attributes}(ids]classes]names]dupnames]backrefs] refdomainstdreftypedoc reftarget/core-api/watch_queuemodnameN classnameN refexplicitutagnamehhh ubh)}(hhh]hChinese (Traditional)}hh2sbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget(/translations/zh_TW/core-api/watch_queuemodnameN classnameN refexplicituh1hhh ubh)}(hhh]hItalian}hhFsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget(/translations/it_IT/core-api/watch_queuemodnameN classnameN refexplicituh1hhh ubh)}(hhh]hJapanese}hhZsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget(/translations/ja_JP/core-api/watch_queuemodnameN classnameN refexplicituh1hhh ubh)}(hhh]hKorean}hhnsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget(/translations/ko_KR/core-api/watch_queuemodnameN classnameN refexplicituh1hhh ubh)}(hhh]hPortuguese (Brazilian)}hhsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget(/translations/pt_BR/core-api/watch_queuemodnameN classnameN refexplicituh1hhh ubh)}(hhh]hSpanish}hhsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget(/translations/sp_SP/core-api/watch_queuemodnameN classnameN refexplicituh1hhh ubeh}(h]h ]h"]h$]h&]current_languageChinese (Simplified)uh1h hh _documenthsourceNlineNubhcomment)}(h!SPDX-License-Identifier: GPL-2.0+h]h!SPDX-License-Identifier: GPL-2.0+}hhsbah}(h]h ]h"]h$]h&] xml:spacepreserveuh1hhhhhhU/var/lib/git/docbuild/linux/Documentation/translations/zh_CN/core-api/watch_queue.rsthKubhnote)}(hX{此文件的目的是为让中文读者更容易阅读和理解,而不是作为一个分支。 因此, 如果您对此文件有任何意见或更新,请先尝试更新原始英文文件。 如果您发现本文档与原始文件有任何不同或者有翻译问题,请发建议或者补丁给 该文件的译者,或者请求中文文档维护者和审阅者的帮助。h]h paragraph)}(hX{此文件的目的是为让中文读者更容易阅读和理解,而不是作为一个分支。 因此, 如果您对此文件有任何意见或更新,请先尝试更新原始英文文件。 如果您发现本文档与原始文件有任何不同或者有翻译问题,请发建议或者补丁给 该文件的译者,或者请求中文文档维护者和审阅者的帮助。h]hX{此文件的目的是为让中文读者更容易阅读和理解,而不是作为一个分支。 因此, 如果您对此文件有任何意见或更新,请先尝试更新原始英文文件。 如果您发现本文档与原始文件有任何不同或者有翻译问题,请发建议或者补丁给 该文件的译者,或者请求中文文档维护者和审阅者的帮助。}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hh5Documentation/translations/zh_CN/disclaimer-zh_CN.rsthKhhubah}(h]h ]h"]h$]h&]uh1hhhhhhhhNubh field_list)}(hhh](hfield)}(hhh](h field_name)}(hOriginalh]hOriginal}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhhhKubh field_body)}(h'Documentation/core-api/watch_queue.rst h]h)}(h&Documentation/core-api/watch_queue.rsth]h&Documentation/core-api/watch_queue.rst}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1hhhubeh}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hhh](h)}(h翻译h]h翻译}(hj"hhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhKubj)}(hhh]h}(h]h ]h"]h$]h&]uh1hhjubeh}(h]h ]h"]h$]h&]uh1hhhhKhhhhubeh}(h]h ]h"]h$]h&]uh1hhhhhhhhKubh)}(h.周彬彬 Binbin Zhou h](h周彬彬 Binbin Zhou <}(hjEhhhNhNubh reference)}(hzhoubinbin@loongson.cnh]hzhoubinbin@loongson.cn}(hjOhhhNhNubah}(h]h ]h"]h$]h&]refurimailto:zhoubinbin@loongson.cnuh1jMhjEubh>}(hjEhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK hhhhubh)}(hhh]h)}(hhh](h)}(h校译h]h校译}(hjohhhNhNubah}(h]h ]h"]h$]h&]uh1hhjlhhhKubj)}(hhh]h}(h]h ]h"]h$]h&]uh1hhjlubeh}(h]h ]h"]h$]h&]uh1hhhhK hjihhubah}(h]h ]h"]h$]h&]uh1hhhhhhhhK ubh)}(hV司延腾 Yanteng Si 吴想成 Wu Xiangcheng h](h司延腾 Yanteng Si <}(hjhhhNhNubjN)}(hsiyanteng@loongson.cnh]hsiyanteng@loongson.cn}(hjhhhNhNubah}(h]h ]h"]h$]h&]refurimailto:siyanteng@loongson.cnuh1jMhjubh> 吴想成 Wu Xiangcheng <}(hjhhhNhNubjN)}(hbobwxc@email.cnh]hbobwxc@email.cn}(hjhhhNhNubah}(h]h ]h"]h$]h&]refurimailto:bobwxc@email.cnuh1jMhjubh>}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK hhhhubhsection)}(hhh](htitle)}(h通用通知机制h]h通用通知机制}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjhhhhhKubh)}(h通用通知机制是建立在标准管道驱动之上的,它可以有效地将来自内核的通知消息拼接到用 户空间打开的管道中。这可以与以下方面结合使用::h]h通用通知机制是建立在标准管道驱动之上的,它可以有效地将来自内核的通知消息拼接到用 户空间打开的管道中。这可以与以下方面结合使用:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh literal_block)}(h* Key/keyring 通知h]h* Key/keyring 通知}hjsbah}(h]h ]h"]h$]h&]hhuh1jhhhKhjhhubh)}(h0通知缓冲区可以通过以下方式启用:h]h0通知缓冲区可以通过以下方式启用:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh block_quote)}(hJ“General setup”/“General notification queue” (CONFIG_WATCH_QUEUE) h]h)}(hI“General setup”/“General notification queue” (CONFIG_WATCH_QUEUE)h]hI“General setup”/“General notification queue” (CONFIG_WATCH_QUEUE)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1j hhhKhjhhubh)}(h文档包含以下章节:h]h文档包含以下章节:}(hj#hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubhtopic)}(hhh]h bullet_list)}(hhh](h list_item)}(hhh]h)}(hhh]jN)}(hhh]h概述}(hjChhhNhNubah}(h]id10ah ]h"]h$]h&]refidid2uh1jMhj@ubah}(h]h ]h"]h$]h&]uh1hhj=ubah}(h]h ]h"]h$]h&]uh1j;hj8ubj<)}(hhh]h)}(hhh]jN)}(hhh]h 消息结构}(hjehhhNhNubah}(h]id11ah ]h"]h$]h&]refidid3uh1jMhjbubah}(h]h ]h"]h$]h&]uh1hhj_ubah}(h]h ]h"]h$]h&]uh1j;hj8ubj<)}(hhh]h)}(hhh]jN)}(hhh]h观测列表(通知源)API}(hjhhhNhNubah}(h]id12ah ]h"]h$]h&]refidapiuh1jMhjubah}(h]h ]h"]h$]h&]uh1hhjubah}(h]h ]h"]h$]h&]uh1j;hj8ubj<)}(hhh]h)}(hhh]jN)}(hhh]h!观测队列(通知输出)API}(hjhhhNhNubah}(h]id13ah ]h"]h$]h&]refidid4uh1jMhjubah}(h]h ]h"]h$]h&]uh1hhjubah}(h]h ]h"]h$]h&]uh1j;hj8ubj<)}(hhh]h)}(hhh]jN)}(hhh]h观测订阅API}(hjhhhNhNubah}(h]id14ah ]h"]h$]h&]refidid5uh1jMhjubah}(h]h ]h"]h$]h&]uh1hhjubah}(h]h ]h"]h$]h&]uh1j;hj8ubj<)}(hhh]h)}(hhh]jN)}(hhh]h通知发布API}(hjhhhNhNubah}(h]id15ah ]h"]h$]h&]refidid6uh1jMhjubah}(h]h ]h"]h$]h&]uh1hhjubah}(h]h ]h"]h$]h&]uh1j;hj8ubj<)}(hhh]h)}(hhh]jN)}(hhh]h 观测源}(hjhhhNhNubah}(h]id16ah ]h"]h$]h&]refidid7uh1jMhj ubah}(h]h ]h"]h$]h&]uh1hhj ubah}(h]h ]h"]h$]h&]uh1j;hj8ubj<)}(hhh]h)}(hhh]jN)}(hhh]h 事件过滤}(hj1hhhNhNubah}(h]id17ah ]h"]h$]h&]refidid8uh1jMhj.ubah}(h]h ]h"]h$]h&]uh1hhj+ubah}(h]h ]h"]h$]h&]uh1j;hj8ubj<)}(hhh]h)}(hhh]jN)}(hhh]h用户空间代码示例}(hjShhhNhNubah}(h]id18ah ]h"]h$]h&]refidid9uh1jMhjPubah}(h]h ]h"]h$]h&]uh1hhjMubah}(h]h ]h"]h$]h&]uh1j;hj8ubeh}(h]h ]h"]h$]h&]uh1j6hj3hhhNhNubah}(h]contentsah ](contentslocaleh"]contentsah$]h&]uh1j1hhhK"hjhhubj)}(hhh](j)}(h概述h]h概述}(hjhhhNhNubah}(h]h ]h"]h$]h&]refidjLuh1jhjhhhhhK%ubh)}(hXP该设施以一种特殊模式打开的管道形式出现,管道的内部环形缓冲区用于保存内核生成的消 息。然后通过read()读出这些消息。在此类管道上禁用拼接以及类似的操作,因为它们希望 在某些情况下将其添加的内容还原到环中-这可能最终会与通知消息重叠。h]hXP该设施以一种特殊模式打开的管道形式出现,管道的内部环形缓冲区用于保存内核生成的消 息。然后通过read()读出这些消息。在此类管道上禁用拼接以及类似的操作,因为它们希望 在某些情况下将其添加的内容还原到环中-这可能最终会与通知消息重叠。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK'hjhhubh)}(h管道的所有者必须告诉内核它想通过该管道观察哪些源。只有连接到该管道上的源才会将消 息插入其中。请注意,一个源可能绑定到多个管道,并同时将消息插入到所有管道中。h]h管道的所有者必须告诉内核它想通过该管道观察哪些源。只有连接到该管道上的源才会将消 息插入其中。请注意,一个源可能绑定到多个管道,并同时将消息插入到所有管道中。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK+hjhhubh)}(hl还可以将过滤器放置在管道上,以便在不感兴趣时可以忽略某些源类型和子事件。h]hl还可以将过滤器放置在管道上,以便在不感兴趣时可以忽略某些源类型和子事件。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK.hjhhubh)}(hX如果环中没有可用的插槽,或者没有预分配的消息缓冲区可用,则将丢弃消息。在这两种情 况下,read()都会在读取缓冲区中当前的最后一条消息后,将WATCH_META_LOSS_NOTIFICATION 插入到输出缓冲区中。h]hX如果环中没有可用的插槽,或者没有预分配的消息缓冲区可用,则将丢弃消息。在这两种情 况下,read()都会在读取缓冲区中当前的最后一条消息后,将WATCH_META_LOSS_NOTIFICATION 插入到输出缓冲区中。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK0hjhhubh)}(h请注意,当生成一个通知时,内核不会等待消费者收集它,而是继续执行。这意味着可以在 持有自旋锁的同时生成通知,并且还可以保护内核不被用户空间故障无限期地阻碍。h]h请注意,当生成一个通知时,内核不会等待消费者收集它,而是继续执行。这意味着可以在 持有自旋锁的同时生成通知,并且还可以保护内核不被用户空间故障无限期地阻碍。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK4hjhhubeh}(h]jRah ]h"]概述ah$]h&]uh1jhjhhhhhK%ubj)}(hhh](j)}(h 消息结构h]h 消息结构}(hjhhhNhNubah}(h]h ]h"]h$]h&]jjnuh1jhjhhhhhK9ubh)}(h,通知消息由一个简短的头部开始::h]h+通知消息由一个简短的头部开始:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK;hjhhubj)}(hhstruct watch_notification { __u32 type:24; __u32 subtype:8; __u32 info; };h]hhstruct watch_notification { __u32 type:24; __u32 subtype:8; __u32 info; };}hjsbah}(h]h ]h"]h$]h&]hhuh1jhhhK=hjhhubh)}(hX“type”表示通知记录的来源,“subtype”表示该来源的记录类型(见下文观测源章节)。该类 型也可以是“WATCH_TYPE_META”。这是一个由观测队列本身在内部生成的特殊记录类型。有两 个子类型:h]hX“type”表示通知记录的来源,“subtype”表示该来源的记录类型(见下文观测源章节)。该类 型也可以是“WATCH_TYPE_META”。这是一个由观测队列本身在内部生成的特殊记录类型。有两 个子类型:}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKChjhhubj )}(hA* WATCH_META_REMOVAL_NOTIFICATION * WATCH_META_LOSS_NOTIFICATION h]j7)}(hhh](j<)}(hWATCH_META_REMOVAL_NOTIFICATIONh]h)}(hj"h]hWATCH_META_REMOVAL_NOTIFICATION}(hj$hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKGhj ubah}(h]h ]h"]h$]h&]uh1j;hjubj<)}(hWATCH_META_LOSS_NOTIFICATION h]h)}(hWATCH_META_LOSS_NOTIFICATIONh]hWATCH_META_LOSS_NOTIFICATION}(hj;hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKHhj7ubah}(h]h ]h"]h$]h&]uh1j;hjubeh}(h]h ]h"]h$]h&]bullet*uh1j6hhhKGhjubah}(h]h ]h"]h$]h&]uh1j hhhKGhjhhubh)}(hf第一个表示安装了观察的对象已被删除或销毁,第二个表示某些消息已丢失。h]hf第一个表示安装了观察的对象已被删除或销毁,第二个表示某些消息已丢失。}(hj]hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKJhjhhubh)}(h+“info”表示一系列东西,包括:h]h+“info”表示一系列东西,包括:}(hjkhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKLhjhhubj )}(hX.* 消息的长度,以字节为单位,包括头(带有WATCH_INFO_LENGTH的掩码,并按 WATCH_INFO_LENGTH__SHIFT移位)。这表示记录的大小,可能在8到127字节之间。 * 观测ID(带有WATCH_INFO_ID掩码,并按WATCH_INFO_ID__SHIFT移位)。这表示观测的主 叫ID,可能在0到255之间。多个观测组可以共享一个队列,这提供了一种区分它们的方法。 * 特定类型的字段(WATCH_INFO_TYPE_INFO)。这是由通知生产者设置的,以指示类型和 子类型的某些特定含义。 h]j7)}(hhh](j<)}(h消息的长度,以字节为单位,包括头(带有WATCH_INFO_LENGTH的掩码,并按 WATCH_INFO_LENGTH__SHIFT移位)。这表示记录的大小,可能在8到127字节之间。 h]h)}(h消息的长度,以字节为单位,包括头(带有WATCH_INFO_LENGTH的掩码,并按 WATCH_INFO_LENGTH__SHIFT移位)。这表示记录的大小,可能在8到127字节之间。h]h消息的长度,以字节为单位,包括头(带有WATCH_INFO_LENGTH的掩码,并按 WATCH_INFO_LENGTH__SHIFT移位)。这表示记录的大小,可能在8到127字节之间。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKNhjubah}(h]h ]h"]h$]h&]uh1j;hj}ubj<)}(h观测ID(带有WATCH_INFO_ID掩码,并按WATCH_INFO_ID__SHIFT移位)。这表示观测的主 叫ID,可能在0到255之间。多个观测组可以共享一个队列,这提供了一种区分它们的方法。 h]h)}(h观测ID(带有WATCH_INFO_ID掩码,并按WATCH_INFO_ID__SHIFT移位)。这表示观测的主 叫ID,可能在0到255之间。多个观测组可以共享一个队列,这提供了一种区分它们的方法。h]h观测ID(带有WATCH_INFO_ID掩码,并按WATCH_INFO_ID__SHIFT移位)。这表示观测的主 叫ID,可能在0到255之间。多个观测组可以共享一个队列,这提供了一种区分它们的方法。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKQhjubah}(h]h ]h"]h$]h&]uh1j;hj}ubj<)}(h特定类型的字段(WATCH_INFO_TYPE_INFO)。这是由通知生产者设置的,以指示类型和 子类型的某些特定含义。 h]h)}(h特定类型的字段(WATCH_INFO_TYPE_INFO)。这是由通知生产者设置的,以指示类型和 子类型的某些特定含义。h]h特定类型的字段(WATCH_INFO_TYPE_INFO)。这是由通知生产者设置的,以指示类型和 子类型的某些特定含义。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKThjubah}(h]h ]h"]h$]h&]uh1j;hj}ubeh}(h]h ]h"]h$]h&]jUjVuh1j6hhhKNhjyubah}(h]h ]h"]h$]h&]uh1j hhhKNhjhhubh)}(h?除长度外,信息中的所有内容都可以用于过滤。h]h?除长度外,信息中的所有内容都可以用于过滤。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKWhjhhubh)}(hQ头部后面可以有补充信息。此格式是由类型和子类型决定的。h]hQ头部后面可以有补充信息。此格式是由类型和子类型决定的。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKYhjhhubeh}(h]jtah ]h"] 消息结构ah$]h&]uh1jhjhhhhhK9ubj)}(hhh](j)}(h观测列表(通知源)APIh]h观测列表(通知源)API}(hjhhhNhNubah}(h]h ]h"]h$]h&]jjuh1jhjhhhhhK]ubh)}(hXx“观测列表“是订阅通知源的观测者的列表。列表可以附加到对象(比如键或超级块),也可 以是全局的(比如对于设备事件)。从用户空间的角度来看,一个非全局的观测列表通常是 通过引用它所属的对象来引用的(比如使用KEYCTL_NOTIFY并给它一个密钥序列号来观测特定 的密钥)。h]hXx“观测列表“是订阅通知源的观测者的列表。列表可以附加到对象(比如键或超级块),也可 以是全局的(比如对于设备事件)。从用户空间的角度来看,一个非全局的观测列表通常是 通过引用它所属的对象来引用的(比如使用KEYCTL_NOTIFY并给它一个密钥序列号来观测特定 的密钥)。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK_hjhhubh)}(h3为了管理观测列表,提供了以下函数:h]h3为了管理观测列表,提供了以下函数:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKdhjhhubj )}(hX* :: void init_watch_list(struct watch_list *wlist, void (*release_watch)(struct watch *wlist)); 初始化一个观测列表。 如果 ``release_watch`` 不是NULL,那么这表示当watch_list对 象被销毁时,应该调用函数来丢弃观测列表对被观测对象的任何引用。 * ``void remove_watch_list(struct watch_list *wlist);`` 这将删除订阅watch_list的所有观测,并释放它们,然后销毁watch_list对象本身。 h]j7)}(hhh](j<)}(hXA:: void init_watch_list(struct watch_list *wlist, void (*release_watch)(struct watch *wlist)); 初始化一个观测列表。 如果 ``release_watch`` 不是NULL,那么这表示当watch_list对 象被销毁时,应该调用函数来丢弃观测列表对被观测对象的任何引用。 h](j)}(hpvoid init_watch_list(struct watch_list *wlist, void (*release_watch)(struct watch *wlist));h]hpvoid init_watch_list(struct watch_list *wlist, void (*release_watch)(struct watch *wlist));}hj/sbah}(h]h ]h"]h$]h&]hhuh1jhhhKhhj+ubh)}(h初始化一个观测列表。 如果 ``release_watch`` 不是NULL,那么这表示当watch_list对 象被销毁时,应该调用函数来丢弃观测列表对被观测对象的任何引用。h](h&初始化一个观测列表。 如果 }(hj=hhhNhNubhliteral)}(h``release_watch``h]h release_watch}(hjGhhhNhNubah}(h]h ]h"]h$]h&]uh1jEhj=ubh 不是NULL,那么这表示当watch_list对 象被销毁时,应该调用函数来丢弃观测列表对被观测对象的任何引用。}(hj=hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKkhj+ubeh}(h]h ]h"]h$]h&]uh1j;hj(ubj<)}(h``void remove_watch_list(struct watch_list *wlist);`` 这将删除订阅watch_list的所有观测,并释放它们,然后销毁watch_list对象本身。 h](h)}(h5``void remove_watch_list(struct watch_list *wlist);``h]jF)}(hjkh]h1void remove_watch_list(struct watch_list *wlist);}(hjmhhhNhNubah}(h]h ]h"]h$]h&]uh1jEhjiubah}(h]h ]h"]h$]h&]uh1hhhhKnhjeubh)}(he这将删除订阅watch_list的所有观测,并释放它们,然后销毁watch_list对象本身。h]he这将删除订阅watch_list的所有观测,并释放它们,然后销毁watch_list对象本身。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKphjeubeh}(h]h ]h"]h$]h&]uh1j;hj(ubeh}(h]h ]h"]h$]h&]jUjVuh1j6hhhKfhj$ubah}(h]h ]h"]h$]h&]uh1j hhhKfhjhhubeh}(h]jah ]h"]观测列表(通知源)apiah$]h&]uh1jhjhhhhhK]ubj)}(hhh](j)}(h!观测队列(通知输出)APIh]h!观测队列(通知输出)API}(hjhhhNhNubah}(h]h ]h"]h$]h&]jjuh1jhjhhhhhKtubh)}(h“观测队列”是由应用程序分配的用以记录通知的缓冲区,其工作原理完全隐藏在管道设备驱 动中,但必须获得对它的引用才能设置观测。可以通过以下方式进行管理:h]h“观测队列”是由应用程序分配的用以记录通知的缓冲区,其工作原理完全隐藏在管道设备驱 动中,但必须获得对它的引用才能设置观测。可以通过以下方式进行管理:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKvhjhhubj )}(hX* ``struct watch_queue *get_watch_queue(int fd);`` 由于观测队列在内核中通过实现缓冲区的管道的文件描述符表示,用户空间必须通过系 统调用传递该文件描述符,这可以用于从系统调用中查找指向观测队列的不透明指针。 * ``void put_watch_queue(struct watch_queue *wqueue);`` 该函数用以丢弃从 ``get_watch_queue()`` 获得的引用。 h]j7)}(hhh](j<)}(hX``struct watch_queue *get_watch_queue(int fd);`` 由于观测队列在内核中通过实现缓冲区的管道的文件描述符表示,用户空间必须通过系 统调用传递该文件描述符,这可以用于从系统调用中查找指向观测队列的不透明指针。 h](h)}(h0``struct watch_queue *get_watch_queue(int fd);``h]jF)}(hjh]h,struct watch_queue *get_watch_queue(int fd);}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jEhjubah}(h]h ]h"]h$]h&]uh1hhhhKyhjubh)}(h由于观测队列在内核中通过实现缓冲区的管道的文件描述符表示,用户空间必须通过系 统调用传递该文件描述符,这可以用于从系统调用中查找指向观测队列的不透明指针。h]h由于观测队列在内核中通过实现缓冲区的管道的文件描述符表示,用户空间必须通过系 统调用传递该文件描述符,这可以用于从系统调用中查找指向观测队列的不透明指针。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK{hjubeh}(h]h ]h"]h$]h&]uh1j;hjubj<)}(hz``void put_watch_queue(struct watch_queue *wqueue);`` 该函数用以丢弃从 ``get_watch_queue()`` 获得的引用。 h](h)}(h5``void put_watch_queue(struct watch_queue *wqueue);``h]jF)}(hjh]h1void put_watch_queue(struct watch_queue *wqueue);}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jEhjubah}(h]h ]h"]h$]h&]uh1hhhhK~hjubh)}(hA该函数用以丢弃从 ``get_watch_queue()`` 获得的引用。h](h该函数用以丢弃从 }(hjhhhNhNubjF)}(h``get_watch_queue()``h]hget_watch_queue()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jEhjubh 获得的引用。}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjubeh}(h]h ]h"]h$]h&]uh1j;hjubeh}(h]h ]h"]h$]h&]jUjVuh1j6hhhKyhjubah}(h]h ]h"]h$]h&]uh1j hhhKyhjhhubeh}(h]jah ]h"]!观测队列(通知输出)apiah$]h&]uh1jhjhhhhhKtubj)}(hhh](j)}(h观测订阅APIh]h观测订阅API}(hjShhhNhNubah}(h]h ]h"]h$]h&]jjuh1jhjPhhhhhKubh)}(h“观测”是观测列表上的订阅,表示观测队列,从而表示应写入通知记录的缓冲区。观测队列 对象还可以携带该对象的过滤规则,由用户空间设置。watch结构体的某些部分可以由驱动程 序设置::h]h“观测”是观测列表上的订阅,表示观测队列,从而表示应写入通知记录的缓冲区。观测队列 对象还可以携带该对象的过滤规则,由用户空间设置。watch结构体的某些部分可以由驱动程 序设置:}(hjahhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjPhhubj)}(hXAstruct watch { union { u32 info_id; /* 在info字段中进行OR运算的ID */ ... }; void *private; /* 被观测对象的私有数据 */ u64 id; /* 内部标识符 */ ... };h]hXAstruct watch { union { u32 info_id; /* 在info字段中进行OR运算的ID */ ... }; void *private; /* 被观测对象的私有数据 */ u64 id; /* 内部标识符 */ ... };}hjosbah}(h]h ]h"]h$]h&]hhuh1jhhhKhjPhhubh)}(h``info_id`` 值是从用户空间获得并按WATCH_INFO_ID__SHIFT移位的8位数字。当通知写入关 联的观测队列缓冲区时,这将与struct watch_notification::info的WATCH_INFO_ID字段进 行或运算。h](jF)}(h ``info_id``h]hinfo_id}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jEhj}ubh 值是从用户空间获得并按WATCH_INFO_ID__SHIFT移位的8位数字。当通知写入关 联的观测队列缓冲区时,这将与struct watch_notification::info的WATCH_INFO_ID字段进 行或运算。}(hj}hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjPhhubh)}(hy``private`` 字段是与watch_list相关联的驱动程序数据,并由 ``watch_list::release_watch()`` 函数清除。h](jF)}(h ``private``h]hprivate}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jEhjubh? 字段是与watch_list相关联的驱动程序数据,并由 }(hjhhhNhNubjF)}(h``watch_list::release_watch()``h]hwatch_list::release_watch()}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jEhjubh 函数清除。}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjPhhubh)}(hG``id`` 字段是源的ID。使用不同ID发布的通知将被忽略。h](jF)}(h``id``h]hid}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jEhjubhA 字段是源的ID。使用不同ID发布的通知将被忽略。}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjPhhubh)}(h"提供以下函数来管理观测:h]h"提供以下函数来管理观测:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjPhhubj )}(hX* ``void init_watch(struct watch *watch, struct watch_queue *wqueue);`` 初始化一个观测对象,把它的指针设置到观察队列中,使用适当的限制来避免死锁。 * ``int add_watch_to_object(struct watch *watch, struct watch_list *wlist);`` 将观测订阅到观测列表(通知源)。watch结构体中的driver-settable字段必须在调用 它之前设置。 * :: int remove_watch_from_object(struct watch_list *wlist, struct watch_queue *wqueue, u64 id, false); 从观测列表中删除一个观测,该观测必须与指定的观测队列(``wqueue``)和对象标识 符(``id``)匹配。通知(``WATCH_META_REMOVAL_NOTIFICATION``)被发送到观测队列 表示该观测已被删除。 * ``int remove_watch_from_object(struct watch_list *wlist, NULL, 0, true);`` 从观测列表中删除所有观测。预计这将被称为销毁前的准备工作,届时新的观测将无法 访问观测列表。通知(``WATCH_META_REMOVAL_NOTIFICATION``)被发送到每个订阅观测 的观测队列,以表明该观测已被删除。 h]j7)}(hhh](j<)}(h``void init_watch(struct watch *watch, struct watch_queue *wqueue);`` 初始化一个观测对象,把它的指针设置到观察队列中,使用适当的限制来避免死锁。 h](h)}(hE``void init_watch(struct watch *watch, struct watch_queue *wqueue);``h]jF)}(hjh]hAvoid init_watch(struct watch *watch, struct watch_queue *wqueue);}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jEhjubah}(h]h ]h"]h$]h&]uh1hhhhKhjubh)}(ho初始化一个观测对象,把它的指针设置到观察队列中,使用适当的限制来避免死锁。h]ho初始化一个观测对象,把它的指针设置到观察队列中,使用适当的限制来避免死锁。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubeh}(h]h ]h"]h$]h&]uh1j;hjubj<)}(h``int add_watch_to_object(struct watch *watch, struct watch_list *wlist);`` 将观测订阅到观测列表(通知源)。watch结构体中的driver-settable字段必须在调用 它之前设置。 h](h)}(hK``int add_watch_to_object(struct watch *watch, struct watch_list *wlist);``h]jF)}(hj-h]hGint add_watch_to_object(struct watch *watch, struct watch_list *wlist);}(hj/hhhNhNubah}(h]h ]h"]h$]h&]uh1jEhj+ubah}(h]h ]h"]h$]h&]uh1hhhhKhj'ubh)}(h{将观测订阅到观测列表(通知源)。watch结构体中的driver-settable字段必须在调用 它之前设置。h]h{将观测订阅到观测列表(通知源)。watch结构体中的driver-settable字段必须在调用 它之前设置。}(hjBhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj'ubeh}(h]h ]h"]h$]h&]uh1j;hjubj<)}(hX:: int remove_watch_from_object(struct watch_list *wlist, struct watch_queue *wqueue, u64 id, false); 从观测列表中删除一个观测,该观测必须与指定的观测队列(``wqueue``)和对象标识 符(``id``)匹配。通知(``WATCH_META_REMOVAL_NOTIFICATION``)被发送到观测队列 表示该观测已被删除。 h](j)}(hint remove_watch_from_object(struct watch_list *wlist, struct watch_queue *wqueue, u64 id, false);h]hint remove_watch_from_object(struct watch_list *wlist, struct watch_queue *wqueue, u64 id, false);}hjZsbah}(h]h ]h"]h$]h&]hhuh1jhhhKhjVubh)}(h从观测列表中删除一个观测,该观测必须与指定的观测队列(``wqueue``)和对象标识 符(``id``)匹配。通知(``WATCH_META_REMOVAL_NOTIFICATION``)被发送到观测队列 表示该观测已被删除。h](hQ从观测列表中删除一个观测,该观测必须与指定的观测队列(}(hjhhhhNhNubjF)}(h ``wqueue``h]hwqueue}(hjphhhNhNubah}(h]h ]h"]h$]h&]uh1jEhjhubh)和对象标识 符(}(hjhhhhNhNubjF)}(h``id``h]hid}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jEhjhubh)匹配。通知(}(hjhhhhNhNubjF)}(h#``WATCH_META_REMOVAL_NOTIFICATION``h]hWATCH_META_REMOVAL_NOTIFICATION}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jEhjhubh:)被发送到观测队列 表示该观测已被删除。}(hjhhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjVubeh}(h]h ]h"]h$]h&]uh1j;hjubj<)}(hXW``int remove_watch_from_object(struct watch_list *wlist, NULL, 0, true);`` 从观测列表中删除所有观测。预计这将被称为销毁前的准备工作,届时新的观测将无法 访问观测列表。通知(``WATCH_META_REMOVAL_NOTIFICATION``)被发送到每个订阅观测 的观测队列,以表明该观测已被删除。 h](h)}(hJ``int remove_watch_from_object(struct watch_list *wlist, NULL, 0, true);``h]jF)}(hjh]hFint remove_watch_from_object(struct watch_list *wlist, NULL, 0, true);}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jEhjubah}(h]h ]h"]h$]h&]uh1hhhhKhjubh)}(hX 从观测列表中删除所有观测。预计这将被称为销毁前的准备工作,届时新的观测将无法 访问观测列表。通知(``WATCH_META_REMOVAL_NOTIFICATION``)被发送到每个订阅观测 的观测队列,以表明该观测已被删除。h](h从观测列表中删除所有观测。预计这将被称为销毁前的准备工作,届时新的观测将无法 访问观测列表。通知(}(hjhhhNhNubjF)}(h#``WATCH_META_REMOVAL_NOTIFICATION``h]hWATCH_META_REMOVAL_NOTIFICATION}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jEhjubhU)被发送到每个订阅观测 的观测队列,以表明该观测已被删除。}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjubeh}(h]h ]h"]h$]h&]uh1j;hjubeh}(h]h ]h"]h$]h&]jUjVuh1j6hhhKhjubah}(h]h ]h"]h$]h&]uh1j hhhKhjPhhubeh}(h]jah ]h"]观测订阅apiah$]h&]uh1jhjhhhhhKubj)}(hhh](j)}(h通知发布APIh]h通知发布API}(hj hhhNhNubah}(h]h ]h"]h$]h&]jjuh1jhjhhhhhKubh)}(h\要将通知发布到观测列表以便订阅的观测可以看到,应使用以下函数::h]h[要将通知发布到观测列表以便订阅的观测可以看到,应使用以下函数:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj)}(hvoid post_watch_notification(struct watch_list *wlist, struct watch_notification *n, const struct cred *cred, u64 id);h]hvoid post_watch_notification(struct watch_list *wlist, struct watch_notification *n, const struct cred *cred, u64 id);}hj%sbah}(h]h ]h"]h$]h&]hhuh1jhhhKhjhhubh)}(h应预先设置通知格式,并应传入一个指向头部(``n``)的指针。通知可能大于此值,并且缓 冲槽为单位的大小在 ``n->info & WATCH_INFO_LENGTH`` 中注明。h](h?应预先设置通知格式,并应传入一个指向头部(}(hj3hhhNhNubjF)}(h``n``h]hn}(hj;hhhNhNubah}(h]h ]h"]h$]h&]uh1jEhj3ubhP)的指针。通知可能大于此值,并且缓 冲槽为单位的大小在 }(hj3hhhNhNubjF)}(h``n->info & WATCH_INFO_LENGTH``h]hn->info & WATCH_INFO_LENGTH}(hjMhhhNhNubah}(h]h ]h"]h$]h&]uh1jEhj3ubh 中注明。}(hj3hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(h``cred`` 结构体表示源(对象)的证书,并传递给LSM,例如SELinux,以允许或禁止根据该队 列(对象)的证书在每个单独队列中记录注释。h](jF)}(h``cred``h]hcred}(hjihhhNhNubah}(h]h ]h"]h$]h&]uh1jEhjeubh 结构体表示源(对象)的证书,并传递给LSM,例如SELinux,以允许或禁止根据该队 列(对象)的证书在每个单独队列中记录注释。}(hjehhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(hn``id`` 是源对象ID(如密钥上的序列号)。只有设置相同ID的观测才能看到这个通知。h](jF)}(h``id``h]hid}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jEhjubhh 是源对象ID(如密钥上的序列号)。只有设置相同ID的观测才能看到这个通知。}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubeh}(h]jah ]h"]通知发布apiah$]h&]uh1jhjhhhhhKubj)}(hhh](j)}(h 观测源h]h 观测源}(hjhhhNhNubah}(h]h ]h"]h$]h&]jjuh1jhjhhhhhKubh)}(hM任何特定的缓冲区都可以从多个源获取信息。 这些源包括:h]hM任何特定的缓冲区都可以从多个源获取信息。 这些源包括:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj )}(h* WATCH_TYPE_KEY_NOTIFY 这种类型的通知表示密钥和密钥环的变化,包括密钥环内容或密钥属性的变化。 更多信息请参见Documentation/security/keys/core.rst。 h]j7)}(hhh]j<)}(hWATCH_TYPE_KEY_NOTIFY 这种类型的通知表示密钥和密钥环的变化,包括密钥环内容或密钥属性的变化。 更多信息请参见Documentation/security/keys/core.rst。 h](h)}(hWATCH_TYPE_KEY_NOTIFYh]hWATCH_TYPE_KEY_NOTIFY}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubh)}(hi这种类型的通知表示密钥和密钥环的变化,包括密钥环内容或密钥属性的变化。h]hi这种类型的通知表示密钥和密钥环的变化,包括密钥环内容或密钥属性的变化。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubh)}(h<更多信息请参见Documentation/security/keys/core.rst。h]h<更多信息请参见Documentation/security/keys/core.rst。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubeh}(h]h ]h"]h$]h&]uh1j;hjubah}(h]h ]h"]h$]h&]jUjVuh1j6hhhKhjubah}(h]h ]h"]h$]h&]uh1j hhhKhjhhubeh}(h]jah ]h"] 观测源ah$]h&]uh1jhjhhhhhKubj)}(hhh](j)}(h 事件过滤h]h 事件过滤}(hj hhhNhNubah}(h]h ]h"]h$]h&]jj:uh1jhj hhhhhKubh)}(hV当创建观测队列后,我们可以应用一组过滤器以限制接收的事件::h]hU当创建观测队列后,我们可以应用一组过滤器以限制接收的事件:}(hj" hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj hhubj)}(histruct watch_notification_filter filter = { ... }; ioctl(fd, IOC_WATCH_QUEUE_SET_FILTER, &filter)h]histruct watch_notification_filter filter = { ... }; ioctl(fd, IOC_WATCH_QUEUE_SET_FILTER, &filter)}hj0 sbah}(h]h ]h"]h$]h&]hhuh1jhhhKhj hhubh)}(h&过滤器的描述的类型变量是::h]h%过滤器的描述的类型变量是:}(hj> hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj hhubj)}(hstruct watch_notification_filter { __u32 nr_filters; __u32 __reserved; struct watch_notification_type_filter filters[]; };h]hstruct watch_notification_filter { __u32 nr_filters; __u32 __reserved; struct watch_notification_type_filter filters[]; };}hjL sbah}(h]h ]h"]h$]h&]hhuh1jhhhKhj hhubh)}(h其中“nr_filters”表示filters[]数组中过滤器的数量,而“__reserved”应为0。 “filter”数组有以下类型的元素::h]h其中“nr_filters”表示filters[]数组中过滤器的数量,而“__reserved”应为0。 “filter”数组有以下类型的元素:}(hjZ hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj hhubj)}(hstruct watch_notification_type_filter { __u32 type; __u32 info_filter; __u32 info_mask; __u32 subtype_filter[8]; };h]hstruct watch_notification_type_filter { __u32 type; __u32 info_filter; __u32 info_mask; __u32 subtype_filter[8]; };}hjh sbah}(h]h ]h"]h$]h&]hhuh1jhhhKhj hhubh)}(h 其中:h]h 其中:}(hjv hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj hhubj )}(hX* ``type`` 是过滤的事件类型,应类似于“WATCH_TYPE_KEY_NOTIFY”。 * ``info_filter`` 与 ``info_mask`` 充当通知记录的信息字段的过滤器,只有在以下情 况,通知才会写入缓冲区:: (watch.info & info_mask) == info_filter 例如,这可以用于忽略不在一个挂载树上的观测点的事件。 * ``subtype_filter`` 是一个位掩码,表示感兴趣的子类型。subtype_filter[0]的 bit[0]对应子类型0,bit[1]对应子类型1,以此类推。 h]j7)}(hhh](j<)}(hO``type`` 是过滤的事件类型,应类似于“WATCH_TYPE_KEY_NOTIFY”。 h]h)}(hN``type`` 是过滤的事件类型,应类似于“WATCH_TYPE_KEY_NOTIFY”。h](jF)}(h``type``h]htype}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jEhj ubhF 是过滤的事件类型,应类似于“WATCH_TYPE_KEY_NOTIFY”。}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1j;hj ubj<)}(hX``info_filter`` 与 ``info_mask`` 充当通知记录的信息字段的过滤器,只有在以下情 况,通知才会写入缓冲区:: (watch.info & info_mask) == info_filter 例如,这可以用于忽略不在一个挂载树上的观测点的事件。 h](h)}(h``info_filter`` 与 ``info_mask`` 充当通知记录的信息字段的过滤器,只有在以下情 况,通知才会写入缓冲区::h](jF)}(h``info_filter``h]h info_filter}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jEhj ubh 与 }(hj hhhNhNubjF)}(h ``info_mask``h]h info_mask}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jEhj ubhf 充当通知记录的信息字段的过滤器,只有在以下情 况,通知才会写入缓冲区:}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhj ubj)}(h'(watch.info & info_mask) == info_filterh]h'(watch.info & info_mask) == info_filter}hj sbah}(h]h ]h"]h$]h&]hhuh1jhhhKhj ubh)}(hN例如,这可以用于忽略不在一个挂载树上的观测点的事件。h]hN例如,这可以用于忽略不在一个挂载树上的观测点的事件。}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubeh}(h]h ]h"]h$]h&]uh1j;hj ubj<)}(h``subtype_filter`` 是一个位掩码,表示感兴趣的子类型。subtype_filter[0]的 bit[0]对应子类型0,bit[1]对应子类型1,以此类推。 h]h)}(h``subtype_filter`` 是一个位掩码,表示感兴趣的子类型。subtype_filter[0]的 bit[0]对应子类型0,bit[1]对应子类型1,以此类推。h](jF)}(h``subtype_filter``h]hsubtype_filter}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jEhj ubh 是一个位掩码,表示感兴趣的子类型。subtype_filter[0]的 bit[0]对应子类型0,bit[1]对应子类型1,以此类推。}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1j;hj ubeh}(h]h ]h"]h$]h&]jUjVuh1j6hhhKhj ubah}(h]h ]h"]h$]h&]uh1j hhhKhj hhubh)}(hk若ioctl()的参数为NULL,则过滤器将被移除,并且来自观测源的所有事件都将通过。h]hk若ioctl()的参数为NULL,则过滤器将被移除,并且来自观测源的所有事件都将通过。}(hj7 hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj hhubeh}(h]j@ah ]h"] 事件过滤ah$]h&]uh1jhjhhhhhKubj)}(hhh](j)}(h用户空间代码示例h]h用户空间代码示例}(hjO hhhNhNubah}(h]h ]h"]h$]h&]jj\uh1jhjL hhhhhMubh)}(h 缓冲区的创建如下所示::h]h缓冲区的创建如下所示:}(hj] hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjL hhubj)}(hDpipe2(fds, O_TMPFILE); ioctl(fds[1], IOC_WATCH_QUEUE_SET_SIZE, 256);h]hDpipe2(fds, O_TMPFILE); ioctl(fds[1], IOC_WATCH_QUEUE_SET_SIZE, 256);}hjk sbah}(h]h ]h"]h$]h&]hhuh1jhhhM hjL hhubh)}(h5它可以被设置成接收密钥环变化的通知::h]h4它可以被设置成接收密钥环变化的通知:}(hjy hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM hjL hhubj)}(hAkeyctl(KEYCTL_WATCH_KEY, KEY_SPEC_SESSION_KEYRING, fds[1], 0x01);h]hAkeyctl(KEYCTL_WATCH_KEY, KEY_SPEC_SESSION_KEYRING, fds[1], 0x01);}hj sbah}(h]h ]h"]h$]h&]hhuh1jhhhMhjL hhubh)}(h5然后,这些通知可以被如下方式所使用::h]h4然后,这些通知可以被如下方式所使用:}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjL hhubj)}(hX>static void consumer(int rfd, struct watch_queue_buffer *buf) { unsigned char buffer[128]; ssize_t buf_len; while (buf_len = read(rfd, buffer, sizeof(buffer)), buf_len > 0 ) { void *p = buffer; void *end = buffer + buf_len; while (p < end) { union { struct watch_notification n; unsigned char buf1[128]; } n; size_t largest, len; largest = end - p; if (largest > 128) largest = 128; memcpy(&n, p, largest); len = (n->info & WATCH_INFO_LENGTH) >> WATCH_INFO_LENGTH__SHIFT; if (len == 0 || len > largest) return; switch (n.n.type) { case WATCH_TYPE_META: got_meta(&n.n); case WATCH_TYPE_KEY_NOTIFY: saw_key_change(&n.n); break; } p += len; } } }h]hX>static void consumer(int rfd, struct watch_queue_buffer *buf) { unsigned char buffer[128]; ssize_t buf_len; while (buf_len = read(rfd, buffer, sizeof(buffer)), buf_len > 0 ) { void *p = buffer; void *end = buffer + buf_len; while (p < end) { union { struct watch_notification n; unsigned char buf1[128]; } n; size_t largest, len; largest = end - p; if (largest > 128) largest = 128; memcpy(&n, p, largest); len = (n->info & WATCH_INFO_LENGTH) >> WATCH_INFO_LENGTH__SHIFT; if (len == 0 || len > largest) return; switch (n.n.type) { case WATCH_TYPE_META: got_meta(&n.n); case WATCH_TYPE_KEY_NOTIFY: saw_key_change(&n.n); break; } p += len; } } }}hj sbah}(h]h ]h"]h$]h&]hhuh1jhhhMhjL hhubeh}(h]jbah ]h"]用户空间代码示例ah$]h&]uh1jhjhhhhhMubeh}(h]id1ah ]h"]通用通知机制ah$]h&]uh1jhhhhhhhKubeh}(h]h ]h"]h$]h&]sourcehuh1hcurrent_sourceN current_lineNsettingsdocutils.frontendValues)}(jN generatorN datestampN source_linkN source_urlN toc_backlinksentryfootnote_backlinksK sectnum_xformKstrip_commentsNstrip_elements_with_classesN strip_classesN report_levelK halt_levelKexit_status_levelKdebugNwarning_streamN tracebackinput_encoding utf-8-siginput_encoding_error_handlerstrictoutput_encodingutf-8output_encoding_error_handlerj error_encodingutf-8error_encoding_error_handlerbackslashreplace language_codeenrecord_dependenciesNconfigN id_prefixhauto_id_prefixid dump_settingsNdump_internalsNdump_transformsNdump_pseudo_xmlNexpose_internalsNstrict_visitorN_disable_configN_sourcehnj _destinationN _config_files]7/var/lib/git/docbuild/linux/Documentation/docutils.confafile_insertion_enabled raw_enabledKline_length_limitM'pep_referencesN pep_base_urlhttps://peps.python.org/pep_file_url_templatepep-%04drfc_referencesN rfc_base_url&https://datatracker.ietf.org/doc/html/ tab_widthKtrim_footnote_reference_spacesyntax_highlightlong smart_quotessmartquotes_locales]character_level_inline_markupdoctitle_xform docinfo_xformKsectsubtitle_xform image_loadinglinkembed_stylesheetcloak_email_addressessection_self_linkenvNubreporterNindirect_targets]substitution_defs}substitution_names}refnames}refids}nameids}(j j j|jwjjRjjtjjjMjjjjjj jjI j@j jbu nametypes}(j j|jjjjMjjj jI j uh}(j jjwj3jRjjtjjjjjjjPjjjjj@j jbjL jLjCjnjejjjjjjjjjjj:j1j\jSu footnote_refs} citation_refs} autofootnotes]autofootnote_refs]symbol_footnotes]symbol_footnote_refs] footnotes] citations]autofootnote_startKsymbol_footnote_startK id_counter collectionsCounter}j KsRparse_messages]transform_messages] transformerN include_log]9Documentation/translations/zh_CN/core-api/watch_queue.rst(NNNNta decorationNhhub.