📄 solaris.c
字号:
/* GKrellM| Copyright (C) 1999-2006 Bill Wilson|| Author: Bill Wilson billw@gkrellm.net| Latest versions might be found at: http://gkrellm.net|| Solaris code: Daisuke Yabuki <dxy@acm.org>|| This program is free software which I release under the GNU General Public| License. You may redistribute and/or modify this program under the terms| of that license as published by the Free Software Foundation; either| version 2 of the License, or (at your option) any later version.|| This program 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 General Public License for more details. Version 2 is in the| COPYRIGHT file in the top level directory of this distribution.| | To get a copy of the GNU General Puplic License, write to the Free Software| Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/#include <kstat.h>#include <kvm.h>#include <fcntl.h>kstat_ctl_t *kc;kvm_t *kd = NULL;struct nlist nl[] = { { "mpid" }, { 0 }};extern void solaris_list_harddisks(void);voidgkrellm_sys_main_init(void) { /* * Most of stats (cpu, proc, disk, memory, net and uptime) are * unavailable if kstat_open() failed. So we just exit in that case. */ if ((kc = kstat_open()) == NULL) { perror("kstat_open"); exit(1); } /* * kvm is utilized solely for getting a value for proc.n_forks * from kernel variable called mpid. Even if kvm_open() fails, * we proceed without it. */ if ((kd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL)) != NULL) { kvm_nlist(kd, nl); } /* * a function called by the following requires sys gid privilege. * the folowing function should be performed here just for that reason. */ solaris_list_harddisks(); if (setgid(getgid()) != 0) { perror("Failed to drop setgid privilege"); exit(1); } }voidgkrellm_sys_main_cleanup(void) { }/* ===================================================================== *//* CPU monitor interface */#include <kstat.h>#include <sys/sysinfo.h>voidgkrellm_sys_cpu_read_data(void){ extern kstat_ctl_t *kc; kstat_t *ksp; cpu_stat_t cs; if (kstat_chain_update(kc) == -1) { perror("kstat_chain_update"); return; } for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { if (strcmp(ksp->ks_module, "cpu_stat")) continue; if (kstat_read(kc, ksp, &cs) == -1) { perror("kstat_read"); continue; } gkrellm_cpu_assign_data(ksp->ks_instance, cs.cpu_sysinfo.cpu[CPU_USER], cs.cpu_sysinfo.cpu[CPU_WAIT], cs.cpu_sysinfo.cpu[CPU_KERNEL], cs.cpu_sysinfo.cpu[CPU_IDLE]); }}/* * note: on some SPARC systems, you can monitor temperature of CPUs * with kstat (unix::temperature:[min/max/state/trend...]) */gbooleangkrellm_sys_cpu_init() { extern kstat_ctl_t *kc; kstat_t *ksp; gint n_cpus = 0; if(kstat_chain_update(kc) == -1) { perror("kstat_chain_update"); return FALSE; } for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { if (strcmp(ksp->ks_module, "cpu_stat")) continue; if (kstat_read(kc, ksp, NULL) != -1) { gkrellm_cpu_add_instance(ksp->ks_instance); ++n_cpus; } } gkrellm_cpu_set_number_of_cpus(n_cpus); return TRUE;}/* ===================================================================== *//* Proc monitor interface */#include <utmp.h>#include <sys/types.h>#include <dirent.h>#include <sys/loadavg.h>#include <kstat.h>#include <fcntl.h>#include <kvm.h>#include <sys/sysinfo.h>voidgkrellm_sys_proc_read_data(void){ double avenrun[LOADAVG_NSTATS], fload = 0; guint n_processes = 0, n_forks = 0; int last_pid; extern kstat_ctl_t *kc; kstat_t *ksp; kstat_named_t *knp; extern kvm_t *kd; extern struct nlist nl[]; if (!GK.second_tick) /* Only one read per second */ return; if (getloadavg(avenrun, LOADAVG_NSTATS) > 0) fload = avenrun[LOADAVG_1MIN]; if (kstat_chain_update(kc) == -1) { perror("kstat_chain_update"); return; } ksp = kstat_lookup(kc, "unix", -1, "system_misc"); if (ksp && kstat_read(kc, ksp, NULL) >= 0) { knp = (kstat_named_t *)kstat_data_lookup(ksp, "nproc"); if (knp) { n_processes = knp->value.ui32; } } if (kd) { if (kvm_kread(kd, nl[0].n_value, (char *)&last_pid, sizeof(int)) != -1) n_forks = last_pid; } else { n_forks = 0; } /* NOTE: code to get 'n_running' is not implemented (stays untouched). * but it wouldn't do any harm since nobody seems to refer to it. */ gkrellm_proc_assign_data(n_processes, 0, n_forks, fload);}voidgkrellm_sys_proc_read_users(void) { static struct utmp *utmpp; gint n_users; n_users = 0; setutent(); while ((utmpp = getutent()) != NULL) { if (utmpp->ut_type == USER_PROCESS && utmpp->ut_name[0] != '\0') n_users++; } gkrellm_proc_assign_users(n_users);}gbooleangkrellm_sys_proc_init(void) { return TRUE; }/* ===================================================================== *//* Disk monitor interface */#include <sys/types.h>#include <sys/sysinfo.h>#include <unistd.h>#include <kstat.h>#include <libdevinfo.h>#include <errno.h>#include <sys/dkio.h>#define UNIT_SHIFT 3#define NAME2MAJOR 0#define MAJOR2NAME 1typedef struct { gint major; gchar name[32];} name_to_major_t;static gint check_media_type(kstat_t *);static gint isharddisk(kstat_t *);void solaris_list_harddisks(void); /* called from main.c */static gint lookup_name_to_major(name_to_major_t *, int);static gint get_major(gchar *);static gint get_devname(gint, gchar *);static gint get_minor(gint);static gint get_instance(gint); typedef struct { char name[8];} probed_harddisk;GList *hard_disk_list;gchar *gkrellm_sys_disk_name_from_device(gint device_number, gint unit_number, gint *order) { return NULL; /* Disk data by device not implemented in Solaris */ }gintgkrellm_sys_disk_order_from_name(gchar *name) { return -1; /* Append as added */ }voidgkrellm_sys_disk_read_data(void){ probed_harddisk *drive; GList *list; extern kstat_ctl_t *kc; kstat_t *ksp; kstat_io_t kios; if (kstat_chain_update(kc) == -1) { perror("kstat_chain_update"); return; } for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { for (list = hard_disk_list; list; list = list->next) { drive = (probed_harddisk *)list->data; if(strcmp(drive->name, ksp->ks_name)) continue; memset((void *)&kios, 0, sizeof(kstat_io_t)); kstat_read(kc, ksp, &kios); gkrellm_disk_assign_data_by_name(drive->name, kios.nread, kios.nwritten, FALSE); } }}gbooleangkrellm_sys_disk_init(void) { return TRUE; } /* Is this needed any longer? */static gintlookup_name_to_major(name_to_major_t *name_to_major, gint type) { FILE *fp; char line[80]; char *name, *maj; gint name2major, major2name; gint majnum; name2major = major2name = 0; switch (type) { case NAME2MAJOR: name2major = 1; break; case MAJOR2NAME: major2name = 1; break; default: break; } if ((fp = fopen("/etc/name_to_major", "r")) == NULL) { perror("fopen"); return -1; } while (fgets(line, sizeof(line), fp) != NULL) { name = strtok(line, " \t"); if (name == NULL) continue; maj = strtok(NULL, "\n"); if (maj == NULL) continue; majnum = (gint) atol(maj); if (name2major) { if (strcmp(name_to_major->name, name) == 0) { name_to_major->major = majnum; fclose(fp); return 0; } } else if (major2name) { if (name_to_major->major == majnum) { strcpy(name_to_major->name, name); fclose(fp); return 0; } } } fclose(fp); return -1;}#if 0 /* Is this needed any longer? */static gintget_major(gchar *devname) { /* xlation from device name to major (e.g. sd -> 32) */ name_to_major_t name_to_major; strcpy(name_to_major.name, devname); if (lookup_name_to_major(&name_to_major, NAME2MAJOR) < 0) return -1; return name_to_major.major;} /* Is this needed any longer? */static gintget_devname(gint major, gchar *devname) { /* xlation from major to device name (e.g. 118 -> ssd) */ name_to_major_t name_to_major; name_to_major.major = major; if (lookup_name_to_major(&name_to_major, MAJOR2NAME) < 0) return -1; strcpy(devname, name_to_major.name); return 0;} /* Is this needed any longer? */static gintget_minor(gint instance) { return instance << UNIT_SHIFT;} /* Is this needed any longer? */static gintget_instance(gint minor) { return minor >> UNIT_SHIFT;}#endif/* * An sd instance could be a cdrom or a harddrive. You can't simply tell, * from contents of kstat, which type of device an sd device is * (well, maybe you could, but at least i can't.) * It, however, doesn't make much sense to count cdrom read/write as * "Disk" activity. So I'd like to exclude removable media's from * monitoring target. In order to do this, I try to open a physical * device of a corresponding sd instance. If it's succeeded, I assume * it's a hard drive. If I get ENXIO or EBUSY, I'll guess it's CDROM. * If you come up with a better (simpler or safer) way to tell it's * a removable media or a hard drive, please drop me an e-mail at * Daisuke Yabuki <dxy@acm.org>. * I don't know any other driver which handle both hard drive and * removable media, by the way. I hope it wouldn't do any harm on * other type of devices, i.e. ssd, or IDE drivers. */ static gintcheck_media_type(kstat_t *ksp) { gint fd; char *phys_path, devices_path[256]; /* or OBP_MAXPATHLEN? */ di_node_t node; static di_node_t root_node = NULL;#if 0 /* Not supported on Solaris 7 */ struct dk_minfo dk;#else int dkRemovable;#endif if (root_node == NULL) { if ((root_node = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) { perror("di_init"); return -1; } } node = di_drv_first_node(ksp->ks_module, root_node); while (node != DI_NODE_NIL) { if (di_instance(node) != ksp->ks_instance) { node = di_drv_next_node(node); continue; } if ((phys_path = di_devfs_path(node)) == NULL) { perror("di_devfs_path"); return -1; } if (sprintf(devices_path, "/devices%s:c,raw", phys_path) <= 0) { di_devfs_path_free(phys_path); return -1; } if ((fd = open(devices_path, O_RDONLY)) == -1) { if (errno == ENXIO || errno == EBUSY) { close(fd); di_devfs_path_free(phys_path); return 0; /* guess it's removable media */ } else {#ifdef DEBUG printf("opening %s\n", devices_path); printf("unexpected errno: %d\n", errno); printf("disabled auto-detection/exclusion of removable media\n");#endif close(fd); di_devfs_path_free(phys_path); return -1; /* EACCESS (unless setgid sys) or suchlike */ } }#if 0 /* Not supported on Solaris 7 */ if (ioctl(fd, DKIOCGMEDIAINFO, &dk) < 0)#else if (ioctl(fd, DKIOCREMOVABLE, &dkRemovable) < 0)#endif { close(fd); di_devfs_path_free(phys_path); return -1; }#if 0 if (dk.dki_media_type == DK_FIXED_DISK)#else if (!dkRemovable)#endif { close(fd); di_devfs_path_free(phys_path); return 1; } return 0; } return -1; /* shouldn't be reached */} static gintisharddisk(kstat_t *ksp) { if (ksp->ks_type != KSTAT_TYPE_IO) return 0; if (strncmp(ksp->ks_class, "disk", 4)) return 0; /* excluding nfs etc. */ if (!strcmp(ksp->ks_module, "fd")) return 0; /* excluding fd */ if (check_media_type(ksp) == 0) return 0; /* guess it's removable media (e.g. CD-ROM, CD-R/W etc) */ return 1;}/* * creating a preliminary list of drives, which should be a complete * list of drives available on the system. the list is not supposed to * contain nfs, fd, cdrom, cdrw etc. */voidsolaris_list_harddisks(void) { extern kstat_ctl_t *kc; kstat_t *ksp; probed_harddisk *drive; if (kstat_chain_update(kc) == -1) { perror("kstat_chain_update"); return; } for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { if(isharddisk(ksp)) { drive = g_new0(probed_harddisk, 1); hard_disk_list = g_list_append(hard_disk_list, drive); strcpy(drive->name, ksp->ks_name); } }}/* ===================================================================== *//* Inet monitor interface */#include "../inet.h"#include <stropts.h>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -