本节提供访问 exacct 文件的代码示例。
...
  ea_object_t *scratch;
  int unpk_flag = EUP_ALLOC;  /* use the same allocation flag */
                              /* for unpack and free */
  /* Omit return value checking, to keep code samples short */
  bsize = getacct(P_PID, pid, NULL, 0);
  buf = malloc(bsize);
  /* Retrieve exacct object and unpack */
  getacct(P_PID, pid, buf, bsize);
  ea_unpack_object(&scratch, unpk_flag, buf, bsize);
  /* Display the exacct record */
  disp_obj(scratch);
  if (scratch->eo_type == EO_GROUP) {
         disp_group(scratch);
  }
  ea_free_object(scratch, unpk_flag);
		...	
本示例评估了内核生成并显示了描述此 make 任务要生成的那部分源代码树的字符串。显示正在生成的且在按源目录的分析中有帮助的源代码部分。
本示例的要点包括以下内容:
要聚合 make(可以包括许多进程)的时间,可以将每个 make 作为任务来启动。make 子进程是作为不同的任务来创建的。要跨越 makefile 树进行聚合,必须确定父子任务关系。
将包含此信息的标记添加到任务的 exacct 文件中。添加描述此 make 任务要生成的那部分源代码树的当前工作目录字符串。
ea_set_item(&cwd, EXT_STRING | EXC_LOCAL | MY_CWD, 
                               cwdbuf, strlen(cwdbuf));
... /* Omit return value checking and error processing */ /* to keep code sample short */ ptid = gettaskid(); /* Save "parent" task-id */ tid = settaskid(getprojid(), TASK_NORMAL); /* Create new task */ /* Set data for item objects ptskid and cwd */ ea_set_item(&ptskid, EXT_UINT32 | EXC_LOCAL | MY_PTID, &ptid, 0); ea_set_item(&cwd, EXT_STRING | EXC_LOCAL | MY_CWD, cwdbuf, strlen(cwdbuf)); /* Set grp object and attach ptskid and cwd to grp */ ea_set_group(&grp, EXT_GROUP | EXC_LOCAL | EXD_GROUP_HEADER); ea_attach_to_group(&grp, &ptskid); ea_attach_to_group(&grp, &cwd); /* Pack the object and put it back into the accounting stream */ ea_buflen = ea_pack_object(&grp, ea_buf, sizeof(ea_buf)); putacct(P_TASKID, tid, ea_buf, ea_buflen, EP_EXACCT_OBJECT); /* Memory management: free memory allocate in ea_set_item */ ea_free_item(&cwd, EUP_ALLOC); ...
本示例显示如何读取并显示进程或任务的系统 exacct 文件。
本示例的要点包括以下内容:
调用 ea_get_object() 以获取该文件中的下一个对象。调用 ea_get_object(),循环遍历 exacct 文件,直到遇见 EOF。
catalog_name() 使用 catalog_item 结构将 Solaris 目录的类型 ID 转换为有意义的字符串,该字符串描述了该对象数据的内容。该类型 ID 是通过屏蔽最低的 24 位(即 3 个字节)获取的。
switch(o->eo_catalog & EXT_TYPE_MASK) {
  case EXT_UINT8:
      printf(" 8: %u", o->eo_item.ei_uint8);
      break;
  case EXT_UINT16:
  ...
}
TYPE_MASK 的前 4 位用于查找列显该对象的实际数据的数据类型。
disp_group() 将使用指向组对象的指针及该组中的对象个数作为其参数。对于组中的每个对象,disp_group() 将调用 disp_obj() 并递归调用 disp_group()(如果该对象是组对象)。
/* Omit return value checking and error processing */
/* to keep code sample short */
main(int argc, char *argv)
{
  ea_file_t ef;
  ea_object_t scratch;
  char *fname;
		
  fname = argv[1];
  ea_open(&ef, fname, NULL,  EO_NO_VALID_HDR, O_RDONLY, 0);
  bzero(&scratch, sizeof (ea_object_t));
  while (ea_get_object(&ef, &scratch)  != -1) {
	     disp_obj(&scratch);
	     if (scratch.eo_type == EO_GROUP)
	         disp_group(&ef, scratch.eo_group.eg_nobjs);
	     bzero(&scratch, sizeof (ea_object_t));
  }
  ea_close(&ef);
}
struct catalog_item {   /* convert Solaris catalog's type ID */
                        /* to a meaningful string */
	 int	type;
	 char *name;
 } catalog[] = {
	 { EXD_VERSION, 	"version\t" },
	 ...
	 { EXD_PROC_PID,	"  pid\t" },
	 ...
   };
 static char *
 catalog_name(int type)
 {
	 int i = 0;
	 while (catalog[i].type != EXD_NONE) {
		 if (catalog[i].type == type)
			 return (catalog[i].name);	
		 else
			 i++;
	 }
	 return ("unknown\t");
 }
 static void disp_obj(ea_object_t *o)
 {
	 printf("%s\t", catalog_name(o->eo_catalog & 0xffffff));
	 switch(o->eo_catalog & EXT_TYPE_MASK) {
	 case EXT_UINT8:
		 printf(" 8: %u", o->eo_item.ei_uint8);
		 break;
	 case EXT_UINT16:
	 ...
 }
 static void disp_group(ea_file_t *ef, uint_t nobjs)
 {
	 for (i = 0; i < nobjs; i++) {
		 ea_get_object(ef, &scratch));
             	 disp_obj(&scratch);
		 if (scratch.eo_type == EO_GROUP)
                disp_group(ef, scratch.eo_group.eg_nobjs);
        }
 }