This chapter describes the C interface to extended accounting and covers the following topics:
Projects and tasks are used to label and separate workloads. The extended accounting subsystem is used to monitor resource consumption by workloads that are running on the system. Extended accounting produces accounting records for the workload tasks and processes.
For an overview of extended accounting and example procedures for administering extended accounting, see Chapter 4, Extended Accounting (Overview), in System Administration Guide: Solaris Containers-Resource Management and Solaris Zones and Chapter 5, Administering Extended Accounting (Tasks), in System Administration Guide: Solaris Containers-Resource Management and Solaris Zones.
The extended accounting API contains functions that perform the following:
exacct system calls
Operations on the exacct file
Operations on exacct objects
Miscellaneous Operations
The following table lists the system calls that interact with the extended accounting subsystem.
Table 3–1 Extended Accounting System Calls
Function |
Description |
---|---|
Provides privileged processes with the ability to tag accounting records with additional data that is specific to the process |
|
Enables privileged processes to request extended accounting buffers from the kernel for currently executing tasks and processes |
|
Requests the kernel to write resource usage data for a specified task or process |
These functions provide access to the exacct files:
Table 3–2 exacct File Functions
Function |
Description |
---|---|
Opens an exacct file. |
|
Closes an exacct file. |
|
First time use on a group of objects reads data into an ea_object_t structure. Subsequent use on the group cycles through the objects in the group. |
|
Appends the specified object to the open exacct file. |
|
Reads the basic fields (eo_catalog and eo_type) into an ea_object_t structure and rewinds to the head of the record. |
|
Skips back one object in the exacct file and reads the basic fields (eo_catalog and eo_type) into an ea_object_t. |
|
Gets the name of the host on which the exacct file was created. |
|
Determines the creator of the exacct file. |
These functions are used to access exacct objects:
Table 3–3 exacct Object Functions
Function |
Description |
---|---|
Assigns an exacct object and sets the value(s). |
|
Sets the values of a group of exacct objects. |
|
Checks an exacct object's mask to see if that object has a specific catalog tag. |
|
Attaches an exacct object to a specified exacct object. |
|
Attaches a chain of exacct objects as member items of a specified group. |
|
Frees the value fields in the specified exacct object. |
|
Frees the specified exacct object and any attached hierarchies of objects. |
These functions are associated with miscellaneous operations:
This section provides code examples for accessing exacct files.
This example displays a specific pid's exacct data snapshot from the kernel.
... 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); ...
This example evaluates kernel builds and displays a string that describes the portion of the source tree being built by this task make. Display the portion of the source being built to aid in the per-source-directory analysis.
The key points for this example include the following:
To aggregate the time for a make, which could include many processes, each make 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 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); ...
This example shows how to read and display a system exacct file for a process or a task.
The key points for this example include the following:
Call ea_get_object() to get the next object in the file. Call ea_get_object() in a loop until EOF enables a complete traversal of the exacct file.
catalog_name() uses the catalog_item structure to convert a 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.
disp_group() 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 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); } }