dmp_ctl 内核服务

用途

添加和除去主转储表中的条目。

语法

#include <sys/types.h>
     #include <errno.h>
     #include <sys/dump.h>

     int dmp_ctl(op, parmp)
     int op;
     struct dmpctl_data *parmp;

描述

使用 dmp_ctl 内核服务来管理转储例程。 它将替换出于兼容性原因仍受支持的 dmp_adddmp_del 内核服务。 使用 dmp_add () 命令添加的例程与使用 dmp_ctl () 命令添加的例程之间的主要差别如下所示:
  • 这些例程的调用方式与使用 dmp_add 内核服务添加的例程不同。 使用 dmp_ctl 内核服务添加的例程将返回空指针,转储表或转储大小估算值。
  • dmp_ctl 内核服务一起添加的例程应该忽略它们不支持的函数。 例如,如果接收到无法识别的请求,那么不应将其捕获。 这允许在不需要更改所有用户的情况下添加未来功能。

dmp_ctl 内核服务用于请求在全局缓冲区中预留一定数量的内存。 然后,例程将使用此参数来存储不在内存中的数据。 此类数据的一个示例是由适配器提供的转储数据。 如果没有全局缓冲区,那么需要将数据放置在配置时分配的锁定缓冲区中。 每个组件都需要分配其自己的锁定缓冲区。

系统转储设施维护此类数据的全局缓冲区。 此缓冲区是在首次请求时使用所请求的大小进行分配的。 另一个请求更多数据的转储例程会导致以更大的大小重新分配缓冲区。 由于在系统的生命周期内必须将此缓冲区保留在固定存储器中,因此只需要尽可能多的内存。 要求过多的存储空间将会保留过多的固定存储空间,从而降低系统性能。

只要需要转储数据,就会调用使用全局缓冲区的任何转储例程。 例程仅调用一次以提供此类数据。 如果转储重新启动,那么将保存并使用其转储表地址。

注: dmp_ctl 内核服务也可以由转储例程用来报告例程故障。 如果例程检测到由于某些原因 (例如数据结构损坏) 而无法转储需要转储的内容,那么可能需要执行此操作。
注意:采用 6100-02 技术级的AIX® 6.1版开始,dmp_ctl内核服务支持 DMPFUNC_SERIALIO 操作标志。

转储表

转储例程返回以 DMP_MAGIC 开头的组件转储表,该转储表是 32 位或 64 位转储表的幻数。 如果使用无限大小的转储表,那么幻数为 DMP_MAGIC_U ,并使用 CDT_u 结构。 如果是这种情况,那么将重复调用转储例程,直到它返回空 CDT_u 指针为止。 无限大小转储表的目的是提供一种方法来转储未知数量的数据区,而不必按照经典转储表的要求预先分配最大可能数量的 cdt_entry 元素数组。 转储表的定义位于 sys/dump.h 包含文件中。

参数

dmp_ctl 操作和 dmpctl_data 结构在 dump.h 文本文件中定义。

描述
op 指定要执行的操作。
帕姆普 指向包含所指定操作的值的 dmpctl_data 结构。 dmpctl_data 结构在 /usr/include/sys/dump.h 文件中定义,如下所示:
/* Dump Routine failures data. */
struct __rtnf {
       int rv;                    /* error code. */
       ulong vaddr;               /* address. */
       vmhandle_t handle;         /* handle */
};

typedef       void *((*__CDTFUNCENH)(int op, void *buf));
struct dmpctl_data {
       int dmpc_magic;            /* magic number       */
       int dmpc_flags;           /* dump       routine       flags. */
       __CDTFUNCENH dmpc_func;
       union {
              u_longlong_t bsize;    /* Global buffer size requested. */
              struct __rtnf rtnf;
       } dmpc_u;
};
#define       DMPC_MAGIC1 0xdcdcdc01
#define       DMPC_MAGIC DMPC_MAGIC1
#define       dmpc_bsize dmpc_u.bsize
#define dmpcf_rv dmpc_u.rtnf.rv
#define dmpcf_vaddr dmpc_u.rtnf.vaddr
#define dmpcf_handle dmpc_u.rtnf.handle

受支持的操作及其关联数据为:

描述
DMPCTL_ADD 将指定的转储例程添加到主转储表。 这需要指向函数和函数类型标志的指针。 受支持的类型标志为:
DMPFUNC_CALL_ON_RESTART
如果转储重新启动,那么再次调用此函数。 转储函数仅调用一次以提供转储数据。 如果必须调用该函数,并且在辅助转储设备上重新启动转储,那么必须设置此标志。 如果此函数使用全局转储缓冲区,那么必须设置 DMPFUNC_CALL_ON_RESTART 标志。 如果该函数使用无限大小的转储表,那么也必须设置此参数,该表将 DMP_MAGIC_U 作为幻数。
DMPFUNC_GLOBAL_BUFFER
此函数使用全局转储缓冲区。 大小是使用 dmpc_bsize 字段指定的。
DMPFUNC_SERIALIO
在转储期间启用序列化 I/O。 需要此标志是特定于设备的。 只有设备的开发人员才能确定是否需要设置此标志。 仅对于可位于转储 I/O 路径上的设备才推荐使用。 在转储期间对 I/O 进行序列化可能会降低转储性能。 缺省值 (不带此标志) 是允许与 CDT 函数调用并行进行 I/O。
DMPCTL_DEL 从主转储表中删除指定的转储函数。
DMPCTL_RTNFAILURE 报告无法转储所需数据。 例程必须设置 dmpc_func、dmpcf_rV, dmpcf_vaddr 和 dmpcf_handle 字段。

转储函数调用参数:

描述
操作码 指定该例程要执行的操作。 操作码如下所示:
DMPRTN_START
此转储表的转储正在启动。 提供数据。
DMPRTN_DONE
转储已完成。 提供了此调用,以便转储例程可以在转储后执行所需的任何清除。 这特定于已为其收集信息的设备。 它不释放内存,因为在执行转储之前必须分配此类内存。
DMPRTN_AGAIN
提供此无限制转储表的更多数据。 例程必须首先传递回以 DMP_MAGIC_U 开头的转储表。 完成时,该函数必须返回 NULL。
DMPRTN_ESTIMATE
提供大小估算值。 该函数必须返回一个指向类型为 dmp_sizeest_t 的项的指针。 请参阅本文后面的示例。
缓冲区指针 这是指向全局缓冲区的指针,如果未请求全局缓冲区空间,那么为 NULL。

返回值

描述
0 如果成功,那么返回。
EINVAL 如果一个或多个参数值无效,那么返回。
ENOMEM 如果无法满足全局缓冲区请求,那么返回。
EEXIST 如果已添加转储功能,那么返回。

示例

  1. 要添加可以调用一次以提供数据的转储例程 (dmprtn) ,请输入:
    void *dmprtn(int op, void *buf);
              struct cdt cdt;
              dmp_sizeest_t estimate;
    
              config()
              {
                      struct dmpctl_data parm;
                      ...
    
                      parm.dmpc_magic = DMPC_MAGIC1;
                      parm.dmpc_func = dmprtn;
                      parm.dmpc_flags = 0;
                      ret = dmp_ctl(DMPCTL_ADD, &parm);
    
                      ...
              }
    
              /*
               * Dump routine.
               *
               * input:
               *   op - dump routine operation.
               *   buf - NULL since no global buffer is used.
               *
               * returns:
               *   A pointer to the component dump table.
               */
              void *
              dmprtn(int op, void *buf)
              {
                      void *ret;
    
                      switch(op) {
                      case DMPRTN_START: /* Provide dump data. */
                              ...
                              ret = (void *)&cdt;
                              break;
                      case DMPRTN_ESTIMATE:
                              ret = (void *)&estimate;
                              break;
                      default:
                                      break;
                      }
    
                      return(ret);
              }
  2. 要添加请求 16 kb 全局缓冲区空间的转储例程 (dmprtn) ,请输入:
    ...
              #define BSIZ 16*1024
              dmp_sizeest_t estimate;
    
              config()
              {
                      ...
                      parm.dmpc_magic = DMPC_MAGIC1;
                      parm.dmpc_func = dmprtn;
                      parm.dmpc_flags = DMPFUNC_CALL_ON_RESTART|DMPC_GLOBAL_BUFFER;
                      parm.dmpc_bsize = BSIZ;
                      ret = dmp_ctl(DMPCTL_ADD, &parm);
                      ...
              }
    
              /*
               * Dump routine.
               *
               * input:
               *   op - dump routine operation.
               *   buf - points to the global buffer.
               *
               * output:
               *   Return a pointer to the dump table or to the estimate.
               */
              void *
              dmprtn(int op, void *buf)
              {
                      void *ret;
    
                      switch(op) {
                      case DMPRTN_START: /* Provide dump data. */
                              ...
                              (Put data in buffer at buf.)
                              ret = (void *)&cdt;
                              break;
                      case DMPRTN_ESTIMATE:
                              ret = (void *)&estimate;
                              break;
                      default:
                                      break;
                      }
    
                      return(ret);
              }