Go to main content

Resource Management and Oracle® Solaris Zones Developer's Guide

Exit Print View

Updated: February 2021
 
 

C Code Examples for Accessing exacct Files

This section provides code examples for accessing exacct files.

Example 3  Displaying exacct Data for a Designated pid

This example displays an exacct file data snapshot from the kernel for a specific pid.

…
  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);
…
Example 4  Identifying Individual Tasks During a Kernel Build

This example evaluates kernel builds and displays a string that describes the portion of the source tree being built by this task. It displays the portion of the source being built to aid in the per-source-directory analysis.

Note the following key points for this example:

  • To aggregate the time for a make operation, which could include many processes, each make operation is initiated as a task. Child make processes are created as different tasks. To aggregate across the makefile tree, the parent-child task relationship must be identified.

  • Add a tag with this information to the task's exacct file. Add a current working directory string that describes the portion of the source tree being built by this task's make operation.

    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);
…
Example 5  Reading and Displaying the Contents of a System exacct File

This example shows how to read and display a system exacct file for a process or a task.

Note the following key points for this example:

  • Calls the ea_get_object function to get the next object in the file. Calls the ea_get_object function in a loop until EOF enables a complete traversal of the exacct file.

  • The catalog_name function uses the catalog_item structure to convert an Oracle Solaris catalog's type ID to a meaningful string that describes the content of the object's data. The type ID is obtained by masking the lowest 24 bits, or 3 bytes.

    switch(o->eo_catalog & EXT_TYPE_MASK) {
      case EXT_UINT8:
          printf(" 8: %u", o->eo_item.ei_uint8);
          break;
      case EXT_UINT16:
    …
    }
  • The upper 4 bits of TYPE_MASK are used to find out the data type to print the object's actual data.

  • The disp_group function takes a pointer to a group object and the number of objects in the group. For each object in the group, disp_group calls disp_obj and recursively calls disp_group if the object is a group object.

/* 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 Oracle 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);
        }
 }