1*065db2d9SYang Yang.. include:: ../disclaimer-zh_CN.rst 2*065db2d9SYang Yang 3*065db2d9SYang Yang:Original: Documentation/accounting/taskstats.rst 4*065db2d9SYang Yang 5*065db2d9SYang Yang:Translator: Yang Yang <yang.yang29@zte.com.cn> 6*065db2d9SYang Yang 7*065db2d9SYang Yang================ 8*065db2d9SYang Yang每任务的统计接口 9*065db2d9SYang Yang================ 10*065db2d9SYang Yang 11*065db2d9SYang YangTaskstats是一个基于netlink的接口,用于从内核向用户空间发送每任务及每进程的 12*065db2d9SYang Yang统计信息。 13*065db2d9SYang Yang 14*065db2d9SYang YangTaskstats设计目的: 15*065db2d9SYang Yang 16*065db2d9SYang Yang- 在任务生命周期内和退出时高效的提供统计信息 17*065db2d9SYang Yang- 统一不同计数子系统的接口 18*065db2d9SYang Yang- 支持未来计数系统的扩展 19*065db2d9SYang Yang 20*065db2d9SYang Yang术语 21*065db2d9SYang Yang---- 22*065db2d9SYang Yang 23*065db2d9SYang Yang“pid”、“tid”、“任务”互换使用,用于描述由struct task_struct定义的标准 24*065db2d9SYang YangLinux任务。“每pid的统计数据”等价于“每任务的统计数据”。 25*065db2d9SYang Yang 26*065db2d9SYang Yang“tgid”、“进程”、“线程组”互换使用,用于描述共享mm_struct的任务集, 27*065db2d9SYang Yang也就是传统的Unix进程。尽管使用了tgid这个词,即使一个任务是线程组组长, 28*065db2d9SYang Yang对它的处理也没有什么不同。只要一个进程还有任何归属它的任务,它就被认为 29*065db2d9SYang Yang活着。 30*065db2d9SYang Yang 31*065db2d9SYang Yang用法 32*065db2d9SYang Yang---- 33*065db2d9SYang Yang 34*065db2d9SYang Yang为了在任务生命周期内获得统计信息,用户空间需打开一个单播的netlink套接字 35*065db2d9SYang Yang(NETLINK_GENERIC族)然后发送指定pid或tgid的命令。响应消息中包含单个 36*065db2d9SYang Yang任务的统计信息(若指定了pid)或进程所有任务汇总的统计信息(若指定了tgid)。 37*065db2d9SYang Yang 38*065db2d9SYang Yang为了在任务退出时获取统计信息,用户空间的监听者发送一个指定cpu掩码的注册命令。 39*065db2d9SYang Yangcpu掩码内的cpu上有任务退出时,每pid的统计信息将发送给注册成功的监听者。使用 40*065db2d9SYang Yangcpu掩码可以限制一个监听者收到的数据,并有助于对netlink接口进行流量控制,后文 41*065db2d9SYang Yang将进行更详细的解释。 42*065db2d9SYang Yang 43*065db2d9SYang Yang如果正在退出的任务是线程组中最后一个退出的线程,额外一条包含每tgid统计信息的 44*065db2d9SYang Yang记录也将发送给用户空间。后者包含线程组中所有线程(包括过去和现在)的每pid统计 45*065db2d9SYang Yang信息总和。 46*065db2d9SYang Yang 47*065db2d9SYang Yanggetdelays.c是一个简单的示例,用以演示如何使用taskstats接口获取延迟统计信息。 48*065db2d9SYang Yang用户可注册cpu掩码、发送命令和处理响应、监听每tid/tgid退出数据、将收到的数据 49*065db2d9SYang Yang写入文件、通过增大接收缓冲区进行基本的流量控制。 50*065db2d9SYang Yang 51*065db2d9SYang Yang接口 52*065db2d9SYang Yang---- 53*065db2d9SYang Yang 54*065db2d9SYang Yang内核用户接口封装在include/linux/taskstats.h。 55*065db2d9SYang Yang 56*065db2d9SYang Yang为避免本文档随着接口的演进而过期,本文仅给出当前版本的概要。当本文与taskstats.h 57*065db2d9SYang Yang不一致时,以taskstats.h为准。 58*065db2d9SYang Yang 59*065db2d9SYang Yangstruct taskstats是每pid和每tgid数据共用的计数结构体。它是版本化的,可在内核新增 60*065db2d9SYang Yang计数子系统时进行扩展。taskstats.h中定义了各字段及语义。 61*065db2d9SYang Yang 62*065db2d9SYang Yang用户、内核空间的数据交换是属于NETLINK_GENERIC族的netlink消息,使用netlink属性 63*065db2d9SYang Yang接口。消息格式如下:: 64*065db2d9SYang Yang 65*065db2d9SYang Yang +----------+- - -+-------------+-------------------+ 66*065db2d9SYang Yang | nlmsghdr | Pad | genlmsghdr | taskstats payload | 67*065db2d9SYang Yang +----------+- - -+-------------+-------------------+ 68*065db2d9SYang Yang 69*065db2d9SYang YangTaskstats载荷有三种类型: 70*065db2d9SYang Yang 71*065db2d9SYang Yang1. 命令:由用户发送给内核。获取指定pid/tgid数据的命令包含一个类型为 72*065db2d9SYang YangTASKSTATS_CMD_ATTR_PID/TGID的属性,该属性包含u32的pid或tgid载荷。 73*065db2d9SYang Yangpid/tgid指示用户空间要统计的任务/进程。 74*065db2d9SYang Yang 75*065db2d9SYang Yang注册/注销获取指定cpu集上退出数据的命令包含一个类型为 76*065db2d9SYang YangTASKSTATS_CMD_ATTR_REGISTER/DEREGISTER_CPUMASK的属性,该属性包含cpu掩码载荷。 77*065db2d9SYang Yangcpu掩码是以ascii码表示,用逗号分隔的cpu范围。例如若需监听1,2,3,5,7,8号cpu的 78*065db2d9SYang Yang退出数据,cpu掩码表示为"1-3,5,7-8"。若用户空间在关闭监听套接字前忘了注销监听 79*065db2d9SYang Yang的cpu集,随着时间的推移,内核会清理此监听集。但是,出于提效的目的,建议明确 80*065db2d9SYang Yang执行注销。 81*065db2d9SYang Yang 82*065db2d9SYang Yang2. 命令的应答:内核发出应答用户空间的命令。载荷有三类属性: 83*065db2d9SYang Yang 84*065db2d9SYang Yanga) TASKSTATS_TYPE_AGGR_PID/TGID: 本属性不包含载荷,用以指示其后为被统计对象 85*065db2d9SYang Yang的pig/tgid。 86*065db2d9SYang Yang 87*065db2d9SYang Yangb) TASKSTATS_TYPE_PID/TGID:本属性的载荷为pig/tgid,其统计信息将被返回。 88*065db2d9SYang Yang 89*065db2d9SYang Yangc) TASKSTATS_TYPE_STATS:本属性的载荷为一个struct taskstats实例。每pid和 90*065db2d9SYang Yang每tgid统计信息共用该结构体。 91*065db2d9SYang Yang 92*065db2d9SYang Yang3. 内核会在任务退出时发送新消息。其载荷包含一系列以下类型的属性: 93*065db2d9SYang Yang 94*065db2d9SYang Yanga) TASKSTATS_TYPE_AGGR_PID:指示其后两个属性为pid+stats。 95*065db2d9SYang Yangb) TASKSTATS_TYPE_PID:包含退出任务的pid。 96*065db2d9SYang Yangc) TASKSTATS_TYPE_STATS:包含退出任务的每pid统计信息 97*065db2d9SYang Yangd) TASKSTATS_TYPE_AGGR_TGID:指示其后两个属性为tgid+stats。 98*065db2d9SYang Yange) TASKSTATS_TYPE_TGID:包含任务所属进程的tgid 99*065db2d9SYang Yangf) TASKSTATS_TYPE_STATS:包含退出任务所属进程的每tgid统计信息 100*065db2d9SYang Yang 101*065db2d9SYang Yang每tgid的统计 102*065db2d9SYang Yang------------ 103*065db2d9SYang Yang 104*065db2d9SYang Yang除了每任务的统计信息,taskstats还提供每进程的统计信息,因为资源管理通常以进程 105*065db2d9SYang Yang粒度完成,并且仅在用户空间聚合任务统计信息效率低下且可能不准确(缺乏原子性)。 106*065db2d9SYang Yang 107*065db2d9SYang Yang然而,除了每任务统计信息,在内核中维护每进程统计信息存在额外的时间和空间开销。 108*065db2d9SYang Yang为解决此问题,taskstats代码将退出任务的统计信息累积到进程范围的数据结构中。 109*065db2d9SYang Yang当进程最后一个任务退出时,累积的进程级数据也会发送到用户空间(与每任务数据一起)。 110*065db2d9SYang Yang 111*065db2d9SYang Yang当用户查询每tgid数据时,内核将指定线程组中所有活动线程的统计信息相加,并添加到 112*065db2d9SYang Yang该线程组的累积总数(含之前退出的线程)。 113*065db2d9SYang Yang 114*065db2d9SYang Yang扩展taskstats 115*065db2d9SYang Yang------------- 116*065db2d9SYang Yang 117*065db2d9SYang Yang有两种方法可在未来修改内核扩展taskstats接口,以导出更多的每任务/进程统计信息: 118*065db2d9SYang Yang 119*065db2d9SYang Yang1. 在现有struct taskstats末尾增加字段。该结构体中的版本号确保了向后兼容性。 120*065db2d9SYang Yang用户空间将仅使用与其版本对应的结构体字段。 121*065db2d9SYang Yang 122*065db2d9SYang Yang2. 定义单独的统计结构体并使用netlink属性接口返回对应的数据。由于用户空间独立 123*065db2d9SYang Yang处理每个netlink属性,所以总是可以忽略其不理解类型的属性(因为使用了旧版本接口)。 124*065db2d9SYang Yang 125*065db2d9SYang Yang在1.和2.之间进行选择,属于权衡灵活性和开销的问题。若仅需增加少数字段,那么1.是 126*065db2d9SYang Yang首选方法,因为内核和用户空间无需承担处理新netlink属性的开销。但若新字段过多的 127*065db2d9SYang Yang扩展现有结构体,导致不同的用户空间计数程序不必要的接收大型结构体,而对结构体 128*065db2d9SYang Yang字段并不感兴趣,那么2.是值得的。 129*065db2d9SYang Yang 130*065db2d9SYang YangTaskstats的流量控制 131*065db2d9SYang Yang------------------- 132*065db2d9SYang Yang 133*065db2d9SYang Yang当退出任务数速率变大,监听者可能跟不上内核发送每tid/tgid退出数据的速率,而导致 134*065db2d9SYang Yang数据丢失。taskstats结构体变大、cpu数量上升,都会导致这种可能性增加。 135*065db2d9SYang Yang 136*065db2d9SYang Yang为避免统计信息丢失,用户空间应执行以下操作中至少一项: 137*065db2d9SYang Yang 138*065db2d9SYang Yang- 增大监听者用于接收退出数据的netlink套接字接收缓存区。 139*065db2d9SYang Yang 140*065db2d9SYang Yang- 创建更多的监听者,减少每个监听者监听的cpu数量。极端情况下可为每个cpu创建 141*065db2d9SYang Yang 一个监听者。用户还可考虑将监听者的cpu亲和性设置为监听cpu的子集,特别是当他们 142*065db2d9SYang Yang 仅监听一个cpu。 143*065db2d9SYang Yang 144*065db2d9SYang Yang尽管采取了这些措施,若用户空间仍收到指示接收缓存区溢出的ENOBUFS错误消息, 145*065db2d9SYang Yang则应采取其他措施处理数据丢失。 146