PMDA(3) Library Functions ManualPMDA(3)PMDA- introduction to the Performance Metrics Domain Agent support library
#include <pcp/pmapi.h>#include <pcp/pmda.h> ... assorted routines ...cc ... -lpcp_pmda -lpcp
To assist in the development of Performance Metric Domain Agents (PMDAs) for the Performance Co-Pilot (PCP), a procedural interface is provided that extends the Performance Metrics Application Pro‐ gramming Interface (PMAPI(3)) library. These procedures are de‐ signed to enable a programmer to quickly build a PMDA which can then be tested and refined. However, this also implies that a PM‐ DA has a particular structure which may not be suitable for all PMDA implementations. Once you are familiar with the PCP and PMDA frameworks, you can quickly implement a new PMDA with only a few data structures and functions. This is covered in far greater detail in thePerfor‐mance Co-Pilot Programmer's Guide. A PMDA is responsible for a set of performance metrics, in the sense that it must respond to requests frompmcd(1) for informa‐ tion about performance metrics, instance domains, and instantiated values. This man page contains sections of thesimple PMDAwhich is locat‐ ed at$PCP_PMDAS_DIR/simple.
Two approaches may be used for connecting a PMDA to apmcd(1) process. A Dynamic Shared Object (DSO) can be attached bypmcd(1) usingdlopen(3) when thepmcd(1) process is started. A procedural interface referenced through a shared data structure is used to handle requests frompmcd(1) to the PMDA . The preferred approach is for a separate process (daemon) to com‐ municate withpmcd(1) using the Performance Data Units (PDU) In‐ ter-Process Communication (IPC) protocol. All PMDAs are launched and controlled by thepmcd(1) process on the local host. The requests from the clients are received bypmcd(1) and forwarded to the appropriate PMDAs. Responses, when required, are returned throughpmcd(1) to the clients. The re‐ quests (PDUs) that may be sent to a PMDA frompmcd(1) arePDU_FETCH,PDU_PROFILE,PDU_INSTANCE_REQ,PDU_DESC_REQ,PDU_TEXT_REQandPDU_RESULT. If the PMDA implements any dynamic metrics it may also receivePDU_PMNS_CHILD,PDU_PMNS_IDS,PDU_PMNS_NAMESandPDU_PMNS_TRAVERSEPDUs.
To allow a consistent framework,pmdaMain(3) can be used by a dae‐ mon PMDA to handle the communication protocol using the same call‐ backs as a DSO PMDA. The structurepmdaInterfaceis used to con‐ vey the common procedural interface and state information that is used bypmcd(1) and a PMDA. This state information includes ta‐ bles describing the supported metrics and instance domains. As most of the procedural interface is identical for all PMDAs, they are provided as part of this support library (pmdaProfile(3),pmdaFetch(3),pmdaInstance(3),pmdaDesc(3),pmdaText(3) andpmdaStore(3)). However, these routines require access to thepm‐daInterfacestate information so it must be correctly initialized usingpmdaConnect(3),pmdaDaemon(3),pmdaOpenLog(3),pmdaDSO(3),pmdaGetOpt(3) andpmdaInit(3).
Three structures are declared in/usr/include/pcp/pmda.h which provide a framework for declaring the metrics and instances sup‐ ported by the PMDA. Every instance requires a unique integer identifier and a unique name, as defined by the structurepmdaInstid: /* * Instance description: index and name */ typedef struct { int i_inst; /* internal instance identifier */ char *i_name; /* external instance identifier */ } pmdaInstid; An instance domain requires its own unique identification (pmIn‐Dom), the number of instances the domain represents, and a pointer to an array of instance descriptions. This is defined in the structurepmdaIndom: /* * Instance domain description: unique instance id, * number of instances in this domain, and the list of * instances (not null terminated). */ typedef struct { pmInDom it_indom; /* indom, filled in */ int it_numinst; /* number of instances */ pmdaInstid *it_set; /* instance identifiers */ } pmdaIndom; Thesimple PMDAhas one instance domain forsimple.color with three instances (red,green andblue), and a second instance do‐ main forsimple.now with instances which can be specified at run- time. These instance domains are defined as: static pmdaInstid _color[] = { { 0, "red" }, { 1, "green" }, { 2, "blue" } }; static pmdaInstid *_timenow = NULL; static pmdaIndom indomtab[] = { #define COLOR_INDOM 0 { COLOR_INDOM, 3, _color }, #define NOW_INDOM 1 { NOW_INDOM, 0, NULL }, }; The preprocessor macrosCOLOR_INDOMandNOW_INDOMare used in the metric description table to identify the instance domains of indi‐ vidual metrics. These correspond to theserial value in the in‐ stance domainpmInDomstructure (thedomain field is set bypmdaInit(3) at run-time). The serial value must be unique for each instance domain within the PMDA. The indom table shown above which is usually passed topmdaInit(3) does not need to be created if one wants to write one's own Fetch and Instance functions. SeepmdaInit(3) for more details. Every PMDA has its own uniquenamespaceusing the format defined inPMNS(5). In summary, the namespace matches the names of the metrics to the unique identifier. Thesimple PMDAdefines five metrics:simple.numfetch,simple.color,simple.time.user,sim‐ple.time.sys andsimple.now. The namespace for these metrics is defined in$PCP_PMDAS_DIR/simple/pmns and is installed as: simple { numfetch 253:0:0 color 253:0:1 time now 253:2:4 } simple.time { user 253:1:2 sys 253:1:3 } The domain number of253 is obtained from$PCP_VAR_DIR/pmns/stdp‐ mid. New PMDAs should specify a unique domain number in this file, and obtain the number during installation. This allows the domain number to change by modifying only the file$PCP_VAR_DIR/pmns/stdpmid. Thesimple.time andsimple.now metrics are defined in separate clusters to the other metrics which allows a PMDA to support more than 1024 metrics, as well as grouping similar metrics together. Therefore, the item numbers for a new cluster may be identical to the item numbers in other clusters. Thesimple PMDAcontinues to increment the item numbers to permit direct mapping (seepmdaInit(3)). The namespace file should be installed and removed with the agent usingpmnsadd(1) andpmnsdel(1). See the later sections on IN‐ STALLATION and REMOVAL. A simple ASCII namespace can be constructed by creating a file similar to$PCP_PMDAS_DIR/simple/root: /* * fake "root" for validating the local PMNS subtree */ #include "$PCP_VAR_DIR/pmns/stdpmid" root { simple } #include "pmns" and can be referred to with the-noption in most PCP tools. Each metric requires a description (pmDesc), which contains its Performance Metric Identifier (PMID), data type specification, in‐ stance domain, semantics and units (seepmLookupDesc(3)). A han‐ dle is also provided for application specific information in thepmdaMetricstructure: /* * Metric description: handle for extending description, * and the description. */ typedef struct { void* m_user; /* for users external use */ pmDesc m_desc; /* metric description */ } pmdaMetric; Thesimple PMDAdefines the metrics as: static pmdaMetric metrictab[] = { /* numfetch */ { (void *)0, { PMDA_PMID(0,0), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, { 0,0,0,0,0,0} }, }, /* color */ { (void *)0, { PMDA_PMID(0,1), PM_TYPE_32, COLOR_INDOM, PM_SEM_INSTANT, { 0,0,0,0,0,0} }, }, /* time.user */ { (void*)0, { PMDA_PMID(1,2), PM_TYPE_DOUBLE, PM_INDOM_NULL, PM_SEM_COUNTER, { 0, 1, 0, 0, PM_TIME_SEC, 0 } }, }, /* time.sys */ { (void*)0, { PMDA_PMID(1,3), PM_TYPE_DOUBLE, PM_INDOM_NULL, PM_SEM_COUNTER, { 0, 1, 0, 0, PM_TIME_SEC, 0 } }, }, /* now */ { NULL, { PMDA_PMID(2,4), PM_TYPE_U32, NOW_INDOM, PM_SEM_INSTANT, { 0,0,0,0,0,0 } }, }, }; The macroPMDA_PMID(defined in/usr/include/pcp/pmda.h) is used to specify each metric'scluster anditem fields of the associatedpmID. As with instance domains, thedomain field is set bypmdaInit(3) at run-time, however, the default domain is assumed to be defined by the PMDA in the macroMYDOMAIN. The metric table shown above which is usually passed topmdaInit(3) does not need to be created if one wants to write one's own Fetch and Descriptor functions. SeepmdaInit(3) for more details.A PMDA that is run as a DSO is opened bypmcd(1) withdlopen(3).pmcd(1) will call the PMDA's initialization function that is spec‐ ified in$PCP_PMCDCONF_PATH. This function is passed a pointer to apmdaInterfacestructure which must be completed. Any callbacks which arenot the default PMDA support library callbacks must be specified in thepmdaInterfacestructure. Thesimple PMDAuses its own store and fetch callback.sim‐ple_fetch() callspmdaFetch(3) which requires a callback to be set withpmdaSetFetchCallBack(3) as can be seen in$PCP_PMDAS_DIR/sim‐ ple/simple.c. The flag_isDSOis used to determine if the PMDA is a daemon or a DSO so that the correct initialization routine,pmdaDaemon(3) orpmdaDSO(3), is called.
A PMDA that is run as a daemon is forked and executed bypmcd(1). Therefore, unlike a DSO PMDA, the starting point for a daemon PMDA ismain(). The agent should parse the command line arguments, create a log file and initialize some data structures thatpmcd(1) would initialize for a DSO agent. ThepmdaInterfacestructure must be completely defined by the dae‐ mon PMDA. The functionpmdaDaemon(3) can be called at the start ofmain() to set most of these fields. Command line parsing can be simplified by usingpmdaGetOpt(3), which is similar togetopt(2), but extracts a common set of options into thepmdaIn‐terfacestructure.stderr can be mapped to a log file usingpmdaOpenLog(3) to simplify debugging and error messages. The con‐ nection topmcd(1) can be made withpmdaConnect(3) and the loop which handles the incoming PDUs,pmdaMain(3), should be the last function called. This can be seen in$PCP_PMDAS_DIR/simple/sim‐ ple.c. Thesimple_init() routine is common to an agent that can be run as both a Daemon and DSO PMDA.
Each PMDA must be able to providepmcd(1) with the help text for each metric. Most PMDAs use specially created files with indexes to support efficient retrieval of the help text. Tools are pro‐ vided with PCP to create the help text files of appropriate for‐ mat. Seenewhelp(1).
A series of shell procedures are defined in$PCP_SHARE_DIR/lib/pm‐ daproc.sh which greatly simplify the installation and removal of a PMDA. TheInstall scripts for most PMDAs should only need to specify the name of the PMDA iniam, callpmdaSetupwhich sets up some default variables, checks permissions (you have to be ``root'' to install or remove a PMDA), checks that you're in the right directory (somewhere that ends with /pmdas/$iam), optionally generate the Performance Metrics Name Space (PMNS) and PMDA domain number files for Perl or Python PMDAs, checks the PMDA domain number is valid, etc., specify the communication protocols, and finally callpm‐daInstallto do all the work of updating the PMNS, updating thepmcd(1) control file, notifying or restartingpmcd(1), BeyondpmdaSetupandpmdaInstall, another optional helper routines ispmdaChooseConfigFilethat may be used to interactively select or create a PMDA-specific configuration file, e.g.pmdalogger(1). TheRemove scripts are even simpler as setting up the communica‐ tion protocols are not required, so set the name of the PMDA iniam, then callpmdaSetupfollowed by a call topmdaRemove. Further information is contained in the$PCP_SHARE_DIR/lib/pm‐ daproc.sh file and the following section. Optionally, a PMDA may provide anUpgrade script alongsideInstall andRemove. If present this script will be used by thepmcd startup process to ensure corrections to an installation have been made before starting the PMDA. Examples of such corrections in‐ clude: updates topmcd.conf when a PMDA script or binary has been renamed, when the PMDA supports a new format of its configuration file, or if there is some latent problem from an earlier install (e.g. some PMDAs may need to introduce use of thenotreadykeyword inpmcd.conf, as described below).
As outlined below there are a number of variables that can be set in a PMDA'sInstall script to influence the behaviour of the in‐ stallation procedures. These would typically need to be set be‐ fore the call topmdaInstall, but in some instances (like$iam and the cases specifically noted below), before the call topmdaSetup. The following variables control the communication options between the PMDA andpmcd(1). At least one of$daemon_opt,$dso_opt,$perl_opt or$python_opt must be set to define the supported mode(s) of communication. If more than one of these is set the user will be prompted to make a selection when theInstall script is run.daemon_opt We are willing to install the PMDA as a daemon. Default: truedso_opt We are willing to install the PMDA as a DSO, sopmcd(1) will use the dynamic linking loader to attach the PMDA's DSO at run-time and communication frompmcd(1) to the PMDA and back uses procedure calls, not an IPC channel. Default: falsedso_entry For a DSO PMDA, this is the name of the PMDA's initializa‐ tion routine. Default:${iam}_initdso_name For a DSO PMDA, this is the full pathanme of the PMDA's DSO file. Default:$PCP_PMDAS_DIR/$iam/pmda_$iam.$dso_suffixpipe_opt For a daemon PMDA, is the default IPC channel via apipe(2)? Default: Platform-specific, sotruefor most, butfalsefor Windowsperl_opt We are willing to install the PMDA as a Perl script andpmcd(1) will use theperl(1) interpreter to run the PMDA. Default: falsepmda_dir Full pathname to the directory where the PMDA's installa‐ tion files (executable, script, PMNS source, help text source, etc) are to be found. Default: output from pwd(1) If set, must be done before the call topmdaSetup.pmda_name For a daemon PMDA, this is the name of the PMDA's exe‐ cutable binary relative to the$pmda_dir directory. Default: pmda$iampython_opt We are willing to install the PMDA as a Python script andpmcd(1) will use thepython(1) interpreter to run the PMDA. Default: falseipc_prot For a daemon PMDA, this can be set to eitherbinaryortext. The default isbinaryandtextis rarely used. In addition, an optional IPC parameternotreadycan be used to signify that the PMDA will start up in thenotreadystate, e.g.ipc_prot="binary notready". Note that the quotes are required. The IPC parameters for a PMDA appear inpm‐cd.confin theIPC Paramscolumn. For further details, seepmcd(1) but basicallypmcdwill not issue any requests to a PMDA that has started in thenotreadystate until the PMDA sends aPM_ERR_PMDAREADYPDU. This allows PMDAs with long startup times to initialize correctly without timing out. For details, seepmdaSendError(3) andpmcd(1). When a PMDA is in thenotreadystate, any client requests sent topmcd for the PMDA domain will return with thePM_ERR_PMDAN‐OTREADYerror.socket_inet_def For a daemon PMDA using asocket(2) as the IPC channel the default Internet port number or service name (if known). Default: ""socket_opt For a daemon PMDA, is the default IPC channel via asocket(2)? Default: Platform-specific, sofalsefor most, buttruefor Windows The following variables control the PMNS options.pmns_dupok Most PMDAs do not have duplicate names for the same PMID in their PMNS. But if this is not the case,pmns_dupok should be set totrue. Default: falsepmns_name Each PMDA will add one or more non-leaf nodes to the top of the PMNS. The most common case is that all of the metrics for a PMDA will be placed below the node named$iam. If this is not the case, and especially when the PMDA adds more than one non-leaf node at the top of the PMNS,pmns_name needs to be set to the list of node names (sepa‐ rated by white space), e.g. forpmdaproc(1)pmns_name is set to "proc cgroup hotproc". Default:$iam It is most important that ifpmns_name is set to a non-default value in theInstall script then it must also be set to the same value in theRemove script.pmns_source The name of the PMDA's PMNS source file. By default, the name is interpreted as a relative pathname from the$pm‐da_dir directory. Default: pmns The following variables provide assorted additional options asso‐ ciated with the installation of a PMDA.args Additional command line args for the PMDA. These will be appended to the PMDA's control line in$PCP_PMCDCONF_PATH. Default: ""check_delay Delay (in seconds) after finishing the PMDA installation (or removal) before checking the availability of metrics from the PMDA. May need to be increased if the PMDA has a lengthy startup procedure. Default: 0.3signal_delay Delay (in seconds) after notifyingpmcd(1) with a signal. Required to allowpmcd(1) to complete processing before proceeding to the next step of the installation (or re‐ moval). Default: 1configdir Determines the directory in which a PMDA's configuration file will be stored. Used bypmdaChooseConfigFileso should be set before calling that procedure. Default:$PCP_VAR_DIR/config/$iamconfigfile Preferred configuration file for the PMDA. Used bypmda‐ChooseConfigFileso should be set before calling that pro‐ cedure. Default: ""default_configfile Default configuration file for the PMDA. Used bypmda‐ChooseConfigFileso should be set before calling that pro‐ cedure. Default: ""dso_suffix Standard suffix for a DSO. Should not need to be changed under normal circumstances. Default: Platform-specific, so 'so' for Linux, 'dylib' for Mac OS X, 'dll' for Windows, etc. If set, must be done before the call topmdaSetup.help_source The name of the help text source file that should be used as input topmnewhelp(1). By default, the name is inter‐ preted as a relative pathname from the$pmda_dir directory. Default: helppython_name Full pathname of the Python script for a Python PMDA. Default:$pmda_dir/pmda$iam.python or$pmda_dir/pmda$iam.py The shell procedures in$PCP_SHARE_DIR/lib/pmdaproc.sh manipulate a number of temporary files using the variable$tmp as the prefix for the name of the temporary files.$tmp is a directory that is created, used and removed internally within the procedures of$PCP_SHARE_DIR/lib/pmdaproc.sh but can also be used as the prefix for temporary files needed by a PMDA'sInstall orRemove scripts. When used in this way,$tmp should be followed by a ``/'' and then a suffix, e.g.$tmp/myfoo. TheInstall andRemove scripts should not use other temporary file name prefixes nor usesh(1)trap statements to clean up temporary files as this is all done within$PCP_SHARE_DIR/lib/pmdaproc.sh.Failing to complete any of the data structures or calling any of the library routines out of order may cause unexpected behavior in the PMDA. Due to changes to thePMAPI(3) andPMDA(3) API in the PCP 2.0 re‐ lease, as described in the product release notes, PMDAs built us‐ ing PCP 2.0 must specifyPMDA_INTERFACE_2or later and link withlibpcp_pmda.so.2 andlibpcp.so.2. Pre-existing Daemon PMDAs spec‐ ifyingPMDA_INTERFACE_1will continue to function using the back‐ wards compatiblelibpcp_pmda.so.1 andlibpcp.so.1 libraries and may be recompiled using the headers installed in/usr/in‐clude/pcp1.x/ without any modification. These backwards compati‐ ble headers and libraries are contained in thepcp.sw.compat sub‐ system.
Any PMDA which uses this library can setPMAPI(3) debugging con‐ trol optionlibpmda(with-Dlibpmdaon the command line or via3pmSetDebug(3))to to enable the display of debugging information which may be useful during development (seepmdbg(1)). Thestatus field of thepmdaInterfacestructure should be zero af‐ terpmdaDaemon,pmdaDSO,pmdaGetOpt,pmdaConnectandpmdaInitare called. A value less than zero indicates that initialization has failed. Some error messages that are common to most functions in this li‐ brary are:PMDA interface versioninterfacenot supported Most of the functions require that thecomm.version field of thepmdaInterfacestructure be set toPMDA_INTERFACE_2 or later.PMDA_INTERFACE_2orPMDA_INTERFACE_3implies that theversion.two fields are correctly initialized, whilePMDA_INTERFACE_4implies that theversion.four fields are correctly initialized (seepmdaDaemon(3) andpmdaDSO(3)).
/usr/include/pcp/pmda.h Header file for the PMDA support library./usr/lib/libpcp_pmda.so Dynamic library containing PMDA support library routines.$PCP_PMDAS_DIR/trivial The source of thetrivial PMDA.$PCP_PMDAS_DIR/simple The source of thesimple PMDA.$PCP_PMDAS_DIR/txmon The source of thetxmon PMDA.$PCP_PMCDCONF_PATH Configuration file forpmcd(1).$PCP_VAR_DIR/pmns Location of namespace descriptions for every PMDA.$PCP_VAR_DIR/pmns/stdpmid The unique domain identifiers for each PMDA.$PCP_SHARE_DIR/lib/pmdaproc.sh Shell procedures for installing and removing a PMDA.
Environment variables with the prefixPCP_are used to parameter‐ ize the file and directory names used by PCP. On each installa‐ tion, the file/etc/pcp.conf contains the local values for these variables. The$PCP_CONF variable may be used to specify an al‐ ternative configuration file, as described inpcp.conf(5). Values for these variables may be obtained programmatically using thepmGetConfig(3) function.
dbpmda(1),newhelp(1),pmcd(1),pmnsadd(1),pmnsdel(1),PMAPI(3),PMWEBAPI(3),pmdaConnect(3),pmdaDaemon(3),pmdaDesc(3),pmdaDSO(3),pmdaFetch(3),pmdaGetOpt(3),pmdaInit(3),pmdaInstance(3),pmdaMain(3),pmdaOpenLog(3),pmdaProfile(3),pmdaStore(3),pmdaText(3),pmLookupDesc(3) andPMNS(5). For a complete description of thepcp_pmda library and the PMDA development process, refer to the Insight bookPerformance Co-Pi‐lot Programmer's Guide.
This page is part of thePCP (Performance Co-Pilot) project. In‐ formation about the project can be found at ⟨http://www.pcp.io/⟩. If you have a bug report for this manual page, send it to pcp@groups.io. This page was obtained from the project's upstream Git repository ⟨https://github.com/performancecopilot/pcp.git⟩ on 2025-08-11. (At that time, the date of the most recent commit that was found in the repository was 2025-08-11.) If you discover any rendering problems in this HTML version of the page, or you believe there is a better or more up-to-date source for the page, or you have corrections or improvements to the information in this COLOPHON (which isnot part of the original manual page), send a mail to man-pages@man7.orgPerformance Co-Pilot PCPPMDA(3)Pages that refer to this page:dbpmda(1), genpmda(1), indomcachectl(1), pcpcompat(1), pmcd(1), pmdarocestat(1), pmdaroot(1), pmdasimple(1), pmdatrivial(1), pmdatxmon(1), pmdaweblog(1), weblogvis(1), pmapi(3), pmda(3), pmdaattribute(3), pmdacache(3), pmdachildren(3), pmdaconnect(3), pmdadaemon(3), pmdadesc(3), pmdadso(3), pmdaeventarray(3), pmdaeventclient(3), pmdaeventqueue(3), pmdafetch(3), pmdagetoptions(3), pmdahelp(3), pmdainit(3), pmdainstance(3), pmdainterfacemoved(3), pmdalabel(3), pmdamain(3), pmdaname(3), pmdaopenlog(3), pmdapmid(3), pmdaprofile(3), pmdarootconnect(3), pmdasenderror(3), pmdastore(3), pmdatext(3), pmdatrace(3), pmjsonget(3), mmv(5)
HTML rendering created 2025-09-06 byMichael Kerrisk, author ofThe Linux Programming Interface. For details of in-depthLinux/UNIX system programming training courses that I teach, lookhere. Hosting byjambit GmbH. | ![]() |