library: sysstat and vmstat api changes

Use the standard libc declarations.
For protecting the headers for C++ procps used to have its
own defines, this change makes them use the standard libc ones.

getstat() -> procps_stat_*
vminfo() -> procps_vmstat_*
These two components of the library now use the newer version of
the API with less exposed global variables. The old methods are
there for now.

Signed-off-by: Craig Small <csmall@enc.com.au>
This commit is contained in:
Craig Small
2015-06-20 07:43:02 +10:00
parent 6a0850be7b
commit a410e236ab
18 changed files with 600 additions and 106 deletions

View File

@@ -1,9 +1,9 @@
#ifndef PROCPS_PROC_ALLOC_H
#define PROCPS_PROC_ALLOC_H
#include "procps.h"
#include <proc/procps.h>
EXTERN_C_BEGIN
__BEGIN_DECLS
/* change xalloc_err_handler to override the default fprintf(stderr... */
extern message_fn xalloc_err_handler;
@@ -13,6 +13,6 @@ extern void *xmalloc(size_t size) MALLOC;
extern void *xrealloc(void *oldp, unsigned int size) MALLOC;
extern char *xstrdup(const char *str) MALLOC;
EXTERN_C_END
__END_DECLS
#endif

View File

@@ -1,10 +1,9 @@
#ifndef PROC_DEVNAME_H
#define PROC_DEVNAME_H
#include "procps.h"
#include "readproc.h"
#include <proc/procps.h>
EXTERN_C_BEGIN
__BEGIN_DECLS
#define ABBREV_DEV 1 /* remove /dev/ */
#define ABBREV_TTY 2 /* remove tty */
@@ -14,5 +13,5 @@ extern unsigned dev_to_tty(char *__restrict ret, unsigned chop, dev_t dev_t_dev,
extern int tty_to_dev(const char *__restrict const name);
EXTERN_C_END
__END_DECLS
#endif

View File

@@ -1,12 +1,10 @@
#ifndef PROCPS_PROC_ESCAPE_H
#define PROCPS_PROC_ESCAPE_H
//#include <stdio.h>
#include <sys/types.h>
#include "procps.h"
#include "readproc.h"
#include <proc/procps.h>
#include <proc/readproc.h>
EXTERN_C_BEGIN
__BEGIN_DECLS
#define ESC_STRETCH 1 // since we mangle to '?' this is 1 (would be 4 for octal escapes)
@@ -19,5 +17,5 @@ extern int escape_str(char *__restrict dst, const char *__restrict src, int bufs
extern int escape_command(char *__restrict const outbuf, const proc_t *__restrict const pp, int bytes, int *cells, unsigned flags);
extern int escaped_copy(char *__restrict dst, const char *__restrict src, int bufsize, int *maxroom);
EXTERN_C_END
__END_DECLS
#endif

View File

@@ -60,6 +60,17 @@ global:
uptime;
user_from_uid;
procps_linux_version;
procps_stat_new;
procps_stat_read;
procps_stat_ref;
procps_stat_unref;
procps_stat_get_cpu;
procps_stat_get;
procps_vmstat_new;
procps_vmstat_read;
procps_vmstat_ref;
procps_vmstat_unref;
procps_vmstat_get;
local:
*;
};

View File

@@ -1,13 +1,7 @@
#ifndef PROCPS_PROC_PROCPS_H
#define PROCPS_PROC_PROCPS_H
#ifdef __cplusplus
#define EXTERN_C_BEGIN extern "C" {
#define EXTERN_C_END }
#else
#define EXTERN_C_BEGIN
#define EXTERN_C_END
#endif
#include <features.h>
// Some ports make the mistake of running a 32-bit userspace
// on a 64-bit kernel. Shame on them. It's not at all OK to

View File

@@ -2,9 +2,9 @@
#define PROCPS_PROC_PWCACHE_H
#include <sys/types.h>
#include "procps.h"
#include <proc/procps.h>
EXTERN_C_BEGIN
__BEGIN_DECLS
// used in pwcache and in readproc to set size of username or groupname
#define P_G_SZ 33
@@ -12,6 +12,6 @@ EXTERN_C_BEGIN
extern char *user_from_uid(uid_t uid);
extern char *group_from_gid(gid_t gid);
EXTERN_C_END
__END_DECLS
#endif

View File

@@ -10,13 +10,13 @@
// in the file COPYING
#include "procps.h"
#include "pwcache.h"
#include <proc/procps.h>
#include <proc/pwcache.h>
#define SIGNAL_STRING
#define QUICK_THREADS /* copy (vs. read) some thread info from parent proc_t */
EXTERN_C_BEGIN
__BEGIN_DECLS
// ld cutime, cstime, priority, nice, timeout, alarm, rss,
// c state,
@@ -311,5 +311,5 @@ extern proc_t * get_proc_stats(pid_t pid, proc_t *p);
#define PROC_SPARE_3 0x04000000
#define PROC_SPARE_4 0x08000000
EXTERN_C_END
__END_DECLS
#endif

205
proc/readstat.c Normal file
View File

@@ -0,0 +1,205 @@
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <proc/readstat.h>
#include "procps-private.h"
#define STAT_FILE "/proc/stat"
struct stat_data {
jiff cpu_user;
jiff cpu_nice;
jiff cpu_sys;
jiff cpu_idle;
jiff cpu_iowait;
jiff cpu_irq;
jiff cpu_sirq;
jiff cpu_stol;
jiff cpu_guest;
jiff cpu_gnice;
unsigned int intr;
unsigned int ctxt;
unsigned int btime;
unsigned int procs;
unsigned int procs_blocked;
unsigned int procs_running;
};
struct procps_stat_info {
int refcount;
int stat_fd;
struct stat_data data;
};
/*
* procps_stat_new:
*
* Create a new container to hold the stat information
*
* The initial refcount is 1, and needs to be decremented
* to release the resources of the structure.
*
* Returns: a new stat info container
*/
PROCPS_EXPORT int procps_stat_new(struct procps_stat_info **info)
{
struct procps_stat_info *v;
v = calloc(1, sizeof(struct procps_stat_info));
if (!v)
return -ENOMEM;
v->refcount = 1;
v->stat_fd = -1;
*info = v;
return 0;
}
/*
* procps_stat_read:
*
* Read the data out of /proc/stat putting the information
* into the supplied info structure.
*
* If CPU stats only needed, set cpu_only to non-zero
*/
PROCPS_EXPORT int procps_stat_read(struct procps_stat_info *info, const int cpu_only)
{
char buf[8192];
char *head, *tail;
int size;
if (info == NULL)
return -1;
memset(&(info->data), 0, sizeof(struct stat_data));
/* read in the data */
if (-1 == info->stat_fd && (info->stat_fd = open(STAT_FILE, O_RDONLY)) == -1) {
return -errno;
}
if (lseek(info->stat_fd, 0L, SEEK_SET) == -1) {
return -errno;
}
if ((size = read(info->stat_fd, buf, sizeof(buf)-1)) < 0) {
return -1;
}
buf[size] = '\0';
/* Scan the file */
head = buf;
do {
tail = strchr(head, ' ');
if (!tail)
break;
*tail = '\0';
if (0 == strcmp(head, "cpu")) {
if (sscanf(tail+1, "%Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu",
&(info->data.cpu_user),
&(info->data.cpu_nice),
&(info->data.cpu_sys),
&(info->data.cpu_idle),
&(info->data.cpu_iowait),
&(info->data.cpu_irq),
&(info->data.cpu_sirq),
&(info->data.cpu_stol),
&(info->data.cpu_guest),
&(info->data.cpu_nice)
) != 10)
return -1;
if (cpu_only)
return 0; // we got what we need
} else if (0 == strcmp(head, "intr")) {
info->data.intr = strtoul(tail+1, &tail, 10);
} else if (0 == strcmp(head, "ctxt")) {
info->data.ctxt = strtoul(tail+1, &tail, 10);
} else if (0 == strcmp(head, "btime")) {
info->data.btime = strtoul(tail+1, &tail, 10);
} else if (0 == strcmp(head, "processes")) {
info->data.procs = strtoul(tail+1, &tail, 10);
} else if (0 == strcmp(head, "procs_blocked")) {
info->data.procs_blocked = strtoul(tail+1, &tail, 10);
} else if (0 == strcmp(head, "procs_running")) {
info->data.procs_running = strtoul(tail+1, &tail, 10);
}
if (tail[0] != '\n')
tail = strchr(tail+1, '\n');
if (!tail)
break;
head = tail + 1;
} while(tail);
if (info->data.procs)
info->data.procs--; // exclude this process
return 0;
}
PROCPS_EXPORT struct procps_stat_info *procps_stat_ref(struct procps_stat_info *info)
{
if (info == NULL)
return NULL;
info->refcount++;
return info;
}
PROCPS_EXPORT struct procps_stat_info *procps_stat_unref(struct procps_stat_info *info)
{
if (info == NULL)
return NULL;
info->refcount--;
if (info->refcount > 0)
return NULL;
free(info);
return NULL;
}
PROCPS_EXPORT jiff procps_stat_get_cpu(struct procps_stat_info *info, enum procps_cpu_item item)
{
switch(item) {
case PROCPS_CPU_USER:
return info->data.cpu_user;
case PROCPS_CPU_NICE:
return info->data.cpu_nice;
case PROCPS_CPU_SYSTEM:
return info->data.cpu_sys;
case PROCPS_CPU_IDLE:
return info->data.cpu_idle;
case PROCPS_CPU_IOWAIT:
return info->data.cpu_iowait;
case PROCPS_CPU_IRQ:
return info->data.cpu_irq;
case PROCPS_CPU_SIRQ:
return info->data.cpu_sirq;
case PROCPS_CPU_STOLEN:
return info->data.cpu_stol;
case PROCPS_CPU_GUEST:
return info->data.cpu_guest;
case PROCPS_CPU_GNICE:
return info->data.cpu_gnice;
}
return 0;
}
PROCPS_EXPORT unsigned int procps_stat_get(struct procps_stat_info *info, enum procps_stat_item item)
{
switch(item) {
case PROCPS_STAT_INTERRUPTS:
return info->data.intr;
case PROCPS_STAT_CONTEXT:
return info->data.ctxt;
case PROCPS_STAT_BTIME:
return info->data.btime;
case PROCPS_STAT_PROCS:
return info->data.procs;
case PROCPS_STAT_PROCS_BLK:
return info->data.procs_blocked;
case PROCPS_STAT_PROCS_RUN:
return info->data.procs_running;
}
return 0;
}

56
proc/readstat.h Normal file
View File

@@ -0,0 +1,56 @@
/*
* libprocps - Library to read proc filesystem
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef PROC_READ_STAT_H
#define PROC_READ_STAT_H
#include <proc/procps.h>
__BEGIN_DECLS
enum procps_cpu_item {
PROCPS_CPU_USER,
PROCPS_CPU_NICE,
PROCPS_CPU_SYSTEM,
PROCPS_CPU_IDLE,
PROCPS_CPU_IOWAIT,
PROCPS_CPU_IRQ,
PROCPS_CPU_SIRQ,
PROCPS_CPU_STOLEN,
PROCPS_CPU_GUEST,
PROCPS_CPU_GNICE
};
enum procps_stat_item {
PROCPS_STAT_INTERRUPTS,
PROCPS_STAT_CONTEXT,
PROCPS_STAT_BTIME,
PROCPS_STAT_PROCS,
PROCPS_STAT_PROCS_BLK,
PROCPS_STAT_PROCS_RUN
};
typedef unsigned long long jiff;
struct procps_stat_info;
int procps_stat_new(struct procps_stat_info **info);
int procps_stat_read(struct procps_stat_info *info, const int cpu_only);
struct procps_stat_info *procps_stat_ref(struct procps_stat_info *info);
struct procps_stat_info *procps_stat_unref(struct procps_stat_info *info);
jiff procps_stat_get_cpu(struct procps_stat_info *info, enum procps_cpu_item item);
unsigned int procps_stat_get(struct procps_stat_info *info, enum procps_stat_item item);
__END_DECLS
#endif

View File

@@ -11,9 +11,9 @@
* GNU Library General Public License for more details.
*/
#include "procps.h"
#include <proc/procps.h>
EXTERN_C_BEGIN
__BEGIN_DECLS
/* return -1 on failure */
extern int signal_name_to_number(const char *__restrict name);
@@ -28,5 +28,5 @@ extern void pretty_print_signals(void);
extern void unix_print_signals(void);
EXTERN_C_END
__END_DECLS
#endif

View File

@@ -2,21 +2,15 @@
#define PROC_SYSINFO_H
#include <sys/types.h>
#include <dirent.h>
#include "procps.h"
#include <proc/procps.h>
EXTERN_C_BEGIN
__BEGIN_DECLS
extern unsigned long long Hertz; /* clock tick frequency */
extern long smp_num_cpus; /* number of CPUs */
extern int have_privs; /* boolean, true if setuid or similar */
extern long page_bytes; /* this architecture's bytes per page */
#if 0
#define JT double
extern void eight_cpu_numbers(JT *uret, JT *nret, JT *sret, JT *iret, JT *wret, JT *xret, JT *yret, JT *zret);
#undef JT
#endif
extern int uptime (double *uptime_secs, double *idle_secs);
extern unsigned long getbtime(void);
extern void loadavg(double *av1, double *av5, double *av15);
@@ -140,5 +134,5 @@ extern unsigned get_pid_digits(void) FUNCTION;
extern void cpuinfo (void);
EXTERN_C_END
__END_DECLS
#endif /* SYSINFO_H */

View File

@@ -23,9 +23,9 @@
#ifndef PROC_VERSION_H
#define PROC_VERSION_H
#ifdef __cplusplus
extern "C" {
#endif
#include <proc/procps.h>
__BEGIN_DECLS
int procps_linux_version(void);
@@ -35,8 +35,6 @@ int procps_linux_version(void);
#define LINUX_VERSION_MINOR(x) (((x)>> 8) & 0xFF)
#define LINUX_VERSION_PATCH(x) ( (x) & 0xFF)
#ifdef __cplusplus
} /* extern "C" */
#endif
__END_DECLS
#endif /* PROC_VERSION_H */

153
proc/vmstat.c Normal file
View File

@@ -0,0 +1,153 @@
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <proc/vmstat.h>
#include "procps-private.h"
#define VMSTAT_FILE "/proc/vmstat"
#define ROW_NAME_LEN 32
struct vmstat_data {
unsigned long pgpgin;
unsigned long pgpgout;
unsigned long pswpin;
unsigned long pswpout;
};
struct mem_table_struct {
const char *name;
unsigned long *slot;
};
struct vmstat_info {
int refcount;
int vmstat_fd;
struct vmstat_data data;
};
/*
* procps_vmstat_new:
*
* Create a new container to hold the vmstat information
*
* The initial refcount is 1, and needs to be decremented
* to release the resources of the structure.
*
* Returns: a new vmstat info container
*/
PROCPS_EXPORT int procps_vmstat_new(struct vmstat_info **info)
{
struct vmstat_info *v;
v = calloc(1, sizeof(struct vmstat_info));
if (!v)
return -ENOMEM;
v->refcount = 1;
v->vmstat_fd = -1;
*info = v;
return 0;
}
/*
* procps_vmstat_read:
*
* Read the data out of /proc/vmstat putting the information
* into the supplied info structure
*/
PROCPS_EXPORT int procps_vmstat_read(struct vmstat_info *info)
{
char buf[8192];
char *head, *tail;
int size;
unsigned long *valptr;
if (info == NULL)
return -1;
memset(&(info->data), 0, sizeof(struct vmstat_data));
/* read in the data */
if (-1 == info->vmstat_fd && (info->vmstat_fd = open(VMSTAT_FILE, O_RDONLY)) == -1) {
return -errno;
}
if (lseek(info->vmstat_fd, 0L, SEEK_SET) == -1) {
return -errno;
}
if ((size = read(info->vmstat_fd, buf, sizeof(buf)-1)) < 0) {
return -1;
}
buf[size] = '\0';
/* Scan the file */
head = buf;
do {
tail = strchr(head, ' ');
if (!tail)
break;
*tail = '\0';
valptr = NULL;
if (0 == strcmp(head, "pgpgin")) {
valptr = &(info->data.pgpgin);
}else if (0 == strcmp(head, "pgpgout")) {
valptr = &(info->data.pgpgout);
}else if (0 == strcmp(head, "pswpin")) {
valptr = &(info->data.pswpin);
}else if (0 == strcmp(head, "pswpout")) {
valptr = &(info->data.pswpout);
}
head = tail+1;
if (valptr) {
*valptr = strtoul(head, &tail, 10);
}
tail = strchr(head, '\n');
if (!tail)
break;
head = tail + 1;
} while(tail);
return 0;
}
PROCPS_EXPORT struct vmstat_info *procps_vmstat_ref(struct vmstat_info *info)
{
if (info == NULL)
return NULL;
info->refcount++;
return info;
}
PROCPS_EXPORT struct vmstat_info *procps_vmstat_unref(struct vmstat_info *info)
{
if (info == NULL)
return NULL;
info->refcount--;
if (info->refcount > 0)
return NULL;
free(info);
return NULL;
}
/* Accessor functions */
PROCPS_EXPORT unsigned long procps_vmstat_get(
struct vmstat_info *info,
enum vmstat_item item)
{
switch(item) {
case VMSTAT_INFO_PGPGIN:
return info->data.pgpgin;
case VMSTAT_INFO_PGPGOUT:
return info->data.pgpgout;
case VMSTAT_INFO_PSWPIN:
return info->data.pswpin;
case VMSTAT_INFO_PSWPOUT:
return info->data.pswpout;
}
return 0;
}

44
proc/vmstat.h Normal file
View File

@@ -0,0 +1,44 @@
/*
* libprocps - Library to read proc filesystem
*
* Copyright (C) 1995 Martin Schulze <joey@infodrom.north.de>
* Copyright (C) 1996 Charles Blake <cblake@bbn.com>
* Copyright (C) 2003 Albert Cahalan
* Copyright (C) 2015 Craig Small <csmall@enc.com.au>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef PROC_VMSTAT_H
#define PROC_VMSTAT_H
#include <proc/procps.h>
__BEGIN_DECLS
struct vmstat_info;
int procps_vmstat_new(struct vmstat_info **info);
int procps_vmstat_read(struct vmstat_info *info);
struct vmstat_info *procps_vmstat_ref(struct vmstat_info *info);
struct vmstat_info *procps_vmstat_unref(struct vmstat_info *info);
enum vmstat_item {
VMSTAT_INFO_PGPGIN,
VMSTAT_INFO_PGPGOUT,
VMSTAT_INFO_PSWPIN,
VMSTAT_INFO_PSWPOUT
};
unsigned long procps_vmstat_get(struct vmstat_info *info, enum vmstat_item item);
__END_DECLS
#endif

View File

@@ -1,12 +1,12 @@
#ifndef PROCPS_PROC_WCHAN_H
#define PROCPS_PROC_WCHAN_H
#include "procps.h"
#include <proc/procps.h>
EXTERN_C_BEGIN
__BEGIN_DECLS
extern const char * lookup_wchan (int pid);
EXTERN_C_END
__END_DECLS
#endif

View File

@@ -1,13 +1,13 @@
#ifndef PROC_WHATTIME_H
#define PROC_WHATTIME_H
#include "procps.h"
#include <proc/procps.h>
EXTERN_C_BEGIN
__BEGIN_DECLS
extern void print_uptime(int human_readable);
extern char *sprint_uptime(int human_readable);
EXTERN_C_END
__END_DECLS
#endif