Exemplo n.º 1
0
int get_swap_stats(Digikam::KMemoryInfo::KMemoryInfoData* const data)
{

#ifdef Q_WS_MAC
    Q_UNUSED(data);
#endif
    
#ifdef Q_OS_HPUX
    struct pst_swapinfo pstat_swapinfo[SWAP_BATCH];
    int                 swapidx = 0;
    int                 num, i;
#endif // Q_OS_HPUX

#ifdef Q_OS_SOLARIS
    struct anoninfo ai;
    int             pagesize;
#endif // Q_OS_SOLARIS

#if defined(Q_OS_LINUX) //|| defined(Q_OS_CYGWIN)
    FILE*              f        = 0;
    char*              line_ptr = 0;
    unsigned long long value;
#endif // defined(Q_OS_LINUX)

#if defined(Q_OS_FREEBSD)
    int pagesize;
#ifdef Q_OS_FREEBSD5
    struct xswdev xsw;
    int           mib[16], n;
    size_t        mibsize, size;
#else
    struct kvm_swap swapinfo;
    kvm_t*          kvmd = 0;
#endif // Q_OS_FREEBSD5

#endif // defined(Q_OS_FREEBSD)

#if defined(Q_OS_NETBSD) || defined(Q_OS_OPENBSD)
    struct uvmexp* uvm = 0;
#endif // defined(Q_OS_NETBSD) || defined(Q_OS_OPENBSD)

#ifdef Q_OS_WIN
    MEMORYSTATUSEX memstats;
#endif // Q_OS_WIN

#ifdef Q_OS_HPUX
    data->totalSwap = 0;
    data->usedSwap  = 0;
    data->freeSwap  = 0;

    while (1)
    {
        num = pstat_getswap(pstat_swapinfo, sizeof pstat_swapinfo[0], SWAP_BATCH, swapidx);

        if (num == -1)
        {
            //sg_set_error_with_errno(SG_ERROR_PSTAT,"pstat_getswap");
            return 0;
        }
        else if (num == 0)
        {
            break;
        }

        for (i = 0; i < num; i++)
        {
            struct pst_swapinfo* si = &pstat_swapinfo[i];

            if ((si->pss_flags & SW_ENABLED) != SW_ENABLED)
            {
                continue;
            }

            if ((si->pss_flags & SW_BLOCK) == SW_BLOCK)
            {
                data->totalSwap += ((long long) si->pss_nblksavail) * 1024LL;
                data->usedSwap  += ((long long) si->pss_nfpgs)      * 1024LL;
                data->freeSwap   = data->totalSwap - data->usedSwap;
            }

            if ((si->pss_flags & SW_FS) == SW_FS)
            {
                data->totalSwap += ((long long) si->pss_limit)     * 1024LL;
                data->usedSwap  += ((long long) si->pss_allocated) * 1024LL;
                data->freeSwap   = data->totalSwap - data->usedSwap;
            }
        }

        swapidx = pstat_swapinfo[num - 1].pss_idx + 1;
    }

    return 1;
#endif // Q_OS_HPUX

#ifdef Q_OS_SOLARIS
    if((pagesize=sysconf(_SC_PAGESIZE)) == -1)
    {
        //sg_set_error_with_errno(SG_ERROR_SYSCONF, "_SC_PAGESIZE");
        return 0;
    }

    if (swapctl(SC_AINFO, &ai) == -1)
    {
        //sg_set_error_with_errno(SG_ERROR_SWAPCTL, NULL);
        return 0;
    }

    data->totalSwap = (long long)ai.ani_max  * (long long)pagesize;
    data->usedSwap  = (long long)ai.ani_resv * (long long)pagesize;
    data->freeSwap  = data->totalSwap - data->usedSwap;

    return 1;
#endif // Q_OS_SOLARIS

#if defined(Q_OS_LINUX) || defined(Q_OS_CYGWIN)
    if ((f = fopen("/proc/meminfo", "r")) == NULL)
    {
        //sg_set_error_with_errno(SG_ERROR_OPEN, "/proc/meminfo");
        return 0;
    }

    while ((line_ptr = sg_f_read_line(f, "")) != NULL)
    {
        if (sscanf(line_ptr, "%*s %llu kB", &value) != 1)
        {
            continue;
        }

        value *= 1024;

        if (strncmp(line_ptr, "SwapTotal:", 10) == 0)
        {
            data->totalSwap = value;
        }
        else if (strncmp(line_ptr, "SwapFree:", 9) == 0)
        {
            data->freeSwap = value;
        }
    }

    fclose(f);
    data->usedSwap = data->totalSwap - data->freeSwap;

    return 1;
#endif // defined(Q_OS_LINUX) || defined(Q_OS_CYGWIN)

#if defined(Q_OS_FREEBSD) || defined(Q_OS_DFBSD)
    pagesize = getpagesize();

#ifdef Q_OS_FREEBSD5
    data->totalSwap = 0;
    data->usedSwap  = 0;

    mibsize = sizeof mib / sizeof mib[0];

    if (sysctlnametomib("vm.swap_info", mib, &mibsize) < 0)
    {
        //sg_set_error_with_errno(SG_ERROR_SYSCTLNAMETOMIB, "vm.swap_info");
        return 0;
    }

    for (n = 0; ; ++n)
    {
        mib[mibsize] = n;
        size         = sizeof xsw;

        if (sysctl(mib, mibsize + 1, &xsw, &size, NULL, 0) < 0)
        {
            break;
        }

        if (xsw.xsw_version != XSWDEV_VERSION)
        {
            //sg_set_error(SG_ERROR_XSW_VER_MISMATCH, NULL);
            return 0;
        }

        data->totalSwap += (long long) xsw.xsw_nblks;
        data->usedSwap  += (long long) xsw.xsw_used;
    }

    if (errno != ENOENT)
    {
        //sg_set_error_with_errno(SG_ERROR_SYSCTL, "vm.swap_info");
        return 0;
    }
#else // Q_OS_FREEBSD5
    if((kvmd = sg_get_kvm()) == NULL)
    {
        return 0;
    }

    if ((kvm_getswapinfo(kvmd, &swapinfo, 1,0)) == -1)
    {
        //sg_set_error(SG_ERROR_KVM_GETSWAPINFO, NULL);
        return 0;
    }

    data->totalSwap = (long long)swapinfo.ksw_total;
    data->usedSwap  = (long long)swapinfo.ksw_used;
#endif // Q_OS_FREEBSD5
    data->totalSwap *= pagesize;
    data->usedSwap  *= pagesize;
    data->freeSwap   = data->totalSwap - data->usedSwap;

    return 1;
#endif // defined(Q_OS_FREEBSD) || defined(Q_OS_DFBSD)

#if defined(Q_OS_NETBSD) || defined(Q_OS_OPENBSD)
    if ((uvm = sg_get_uvmexp()) == NULL)
    {
        return 0;
    }

    data->totalSwap = (long long)uvm->pagesize * (long long)uvm->swpages;
    data->usedSwap  = (long long)uvm->pagesize * (long long)uvm->swpginuse;
    data->freeSwap  = data->totalSwap - data->usedSwap;

    return 1;
#endif // defined(Q_OS_NETBSD) || defined(Q_OS_OPENBSD)

#ifdef Q_OS_WIN
    memstats.dwLength = sizeof(memstats);

    if (!GlobalMemoryStatusEx(&memstats))
    {
        //sg_set_error_with_errno(SG_ERROR_MEMSTATUS, "GloblaMemoryStatusEx");
        return 0;
    }

    /* the PageFile stats include Phys memory "minus an overhead".
     * Due to this unknown "overhead" there's no way to extract just page
     * file use from these numbers */
    data->totalSwap = memstats.ullTotalPageFile;
    data->freeSwap  = memstats.ullAvailPageFile;
    data->usedSwap  = data->totalSwap - data->freeSwap;

    return 1;
#endif

    return -1;
}
Exemplo n.º 2
0
sg_fs_stats *sg_get_fs_stats(int *entries){
	VECTOR_DECLARE_STATIC(disk_stats, sg_fs_stats, 10,
			      disk_stat_init, disk_stat_destroy);

	int num_disks=0;
#if defined(LINUX) || defined (SOLARIS) || defined(CYGWIN) || defined(HPUX)
	FILE *f;
#endif

	sg_fs_stats *disk_ptr;

#ifdef SOLARIS
	struct mnttab mp;
	struct statvfs fs;
#endif
#if defined(LINUX) || defined(CYGWIN) || defined(HPUX)
	struct mntent *mp;
	struct statvfs fs;
#endif
#ifdef ALLBSD
	int nummnt;
#ifdef HAVE_STATVFS
	struct statvfs *mp, **fs;
#else
	struct statfs *mp, **fs;
#endif
#endif
#ifdef WIN32
	char lp_buf[MAX_PATH];
	char volume_name_buf[BUFSIZE];
	char filesys_name_buf[BUFSIZE];
	char drive[4] = " :\\";
	char *p;
	int drive_type; //@
	lp_buf[0]='\0';
#endif

#ifdef ALLBSD
	nummnt=getmntinfo(&mp, MNT_WAIT);
	if (nummnt<=0){
		sg_set_error_with_errno(SG_ERROR_GETMNTINFO, NULL);
		return NULL;
	}
	for(fs = &mp; nummnt--; (*fs)++){
#endif

#if defined(LINUX) || defined(CYGWIN) || defined(HPUX)
#ifdef MNT_MNTTAB
	if ((f=setmntent(MNT_MNTTAB, "r" ))==NULL){
#else
	if ((f=setmntent("/etc/mtab", "r" ))==NULL){
#endif
		sg_set_error(SG_ERROR_SETMNTENT, NULL);
		return NULL;
	}

	while((mp=getmntent(f))){
		if((statvfs(mp->mnt_dir, &fs)) !=0){
			continue;
		}	

#endif

#ifdef SOLARIS
	if ((f=fopen("/etc/mnttab", "r" ))==NULL){
		sg_set_error_with_errno(SG_ERROR_OPEN, "/etc/mnttab");
		return NULL;
	}
	while((getmntent(f, &mp)) == 0){
		if ((statvfs(mp.mnt_mountp, &fs)) !=0){
			continue;
		}
#endif

#ifdef WIN32
	if (!(GetLogicalDriveStringsA(BUFSIZE-1, lp_buf))) {
		sg_set_error(SG_ERROR_GETMNTINFO, "GetLogicalDriveStrings");
		return NULL;
	}
	p = lp_buf;
	do {
		// Copy drive letter to template string
		*drive = *p;
		// Only interested in harddrives.
		drive_type = GetDriveTypeA(drive);

		if(drive_type == DRIVE_FIXED) {
#else
		if(is_valid_fs_type(SG_MP_FSTYPENAME(mp))){
#endif
			if (VECTOR_RESIZE(disk_stats, num_disks + 1) < 0) {
				return NULL;
			}
			disk_ptr=disk_stats+num_disks;

#ifndef WIN32
			/* Maybe make this char[bigenough] and do strncpy's and put a null in the end? 
			 * Downside is its a bit hungry for a lot of mounts, as MNT_MAX_SIZE would prob 
			 * be upwards of a k each 
			 */
			if (sg_update_string(&disk_ptr->device_name, SG_MP_DEVNAME(mp)) < 0) {
				return NULL;
			}
			if (sg_update_string(&disk_ptr->fs_type, SG_MP_FSTYPENAME(mp)) < 0) {
				return NULL;
			}
			if (sg_update_string(&disk_ptr->mnt_point, SG_MP_MOUNTP(mp)) < 0) {
				return NULL;
			}

			disk_ptr->size  = SG_FS_FRSIZE(fs) * SG_FS_BLOCKS(fs);
			disk_ptr->avail = SG_FS_FRSIZE(fs) * SG_FS_BAVAIL(fs);
			disk_ptr->used  = (disk_ptr->size) - (SG_FS_FRSIZE(fs) * SG_FS_BFREE(fs));
		
			disk_ptr->total_inodes = SG_FS_FILES(fs);
			disk_ptr->free_inodes  = SG_FS_FFREE(fs);
			/* Linux, FreeBSD don't have a "available" inodes */
			disk_ptr->used_inodes  = disk_ptr->total_inodes - disk_ptr->free_inodes;
			disk_ptr->avail_inodes = SG_FS_FAVAIL(fs);

			disk_ptr->io_size      = SG_FS_BSIZE(fs);
			disk_ptr->block_size   = SG_FS_FRSIZE(fs);
			disk_ptr->total_blocks = SG_FS_BLOCKS(fs);
			disk_ptr->free_blocks  = SG_FS_BFREE(fs);
			disk_ptr->avail_blocks = SG_FS_BAVAIL(fs);
			disk_ptr->used_blocks  = disk_ptr->total_blocks - disk_ptr->free_blocks;
#else
			if(!GetVolumeInformationA(drive, volume_name_buf, BUFSIZE,
						NULL, NULL, NULL, 
						filesys_name_buf, BUFSIZE)) {
				sg_set_error_with_errno(SG_ERROR_DISKINFO, 
					"GetVolumeInformation");
				return NULL;
			}

			if (sg_update_string(&disk_ptr->device_name, 
						volume_name_buf) < 0) {
				return NULL;
			}
			if (sg_update_string(&disk_ptr->fs_type, 
						filesys_name_buf) < 0) {
				return NULL;
			}
			if (sg_update_string(&disk_ptr->mnt_point,
						drive) < 0) {
				return NULL;
			}
			if (!GetDiskFreeSpaceExA(drive, NULL,
					(PULARGE_INTEGER)&disk_ptr->size,
					(PULARGE_INTEGER)&disk_ptr->avail)) {
				sg_set_error_with_errno(SG_ERROR_DISKINFO,
					"GetDiskFreeSpaceEx");
				return NULL;
			}
			disk_ptr->used = disk_ptr->size - disk_ptr->avail;
			disk_ptr->total_inodes = 0;
			disk_ptr->free_inodes  = 0;
			disk_ptr->used_inodes  = 0;
			disk_ptr->avail_inodes = 0;

			/* I dunno what to do with these... so have nothing */
			disk_ptr->io_size = 0;
			disk_ptr->block_size = 0;
			disk_ptr->total_blocks = 0;
			disk_ptr->free_blocks = 0;
			disk_ptr->avail_blocks = 0;
			disk_ptr->used_blocks = 0;
#endif
			num_disks++;
		}
#ifdef WIN32
		while(*p++);
	} while(*p);
#else
	}
#endif

	*entries=num_disks;	

	/* If this fails, there is very little i can do about it, so
	   I'll ignore it :) */
#if defined(LINUX) || defined(CYGWIN) || defined(HPUX)
	endmntent(f);
#endif
#if defined(SOLARIS)
	fclose(f);
#endif

	return disk_stats;

}

int sg_fs_compare_device_name(const void *va, const void *vb) {
	const sg_fs_stats *a = (const sg_fs_stats *)va;
	const sg_fs_stats *b = (const sg_fs_stats *)vb;

	return strcmp(a->device_name, b->device_name);
}

int sg_fs_compare_mnt_point(const void *va, const void *vb) {
	const sg_fs_stats *a = (const sg_fs_stats *)va;
	const sg_fs_stats *b = (const sg_fs_stats *)vb;

	return strcmp(a->mnt_point, b->mnt_point);
}

static void diskio_stat_init(sg_disk_io_stats *d) {
	d->disk_name = NULL;
}

static void diskio_stat_destroy(sg_disk_io_stats *d) {
	free(d->disk_name);
}

VECTOR_DECLARE_STATIC(diskio_stats, sg_disk_io_stats, 10,
		      diskio_stat_init, diskio_stat_destroy);

#ifdef LINUX
typedef struct {
	int major;
	int minor;
} partition;
#endif

sg_disk_io_stats *sg_get_disk_io_stats(int *entries){
	int num_diskio;
#ifndef LINUX
	sg_disk_io_stats *diskio_stats_ptr;
#endif

#ifdef HPUX
	long long rbytes = 0, wbytes = 0;
	struct dirent *dinfo = NULL;
	struct stat lstatinfo;
	struct pst_diskinfo pstat_diskinfo[DISK_BATCH];
	char fullpathbuf[1024] = {0};
	dev_t diskid;
	DIR *dh = NULL;
	int diskidx = 0;
	int num, i;
#endif
#ifdef SOLARIS
	kstat_ctl_t *kc;
	kstat_t *ksp;
	kstat_io_t kios;
#endif
#ifdef LINUX
	FILE *f;
	char *line_ptr;
	int major, minor;
	int has_pp_stats = 1;
	VECTOR_DECLARE_STATIC(parts, partition, 16, NULL, NULL);
	int i, n;
	time_t now;
	const char *format;
	static regex_t not_part_re, part_re;
	static int re_compiled = 0;
#endif
#if defined(FREEBSD) || defined(DFBSD)
	static struct statinfo stats;
	static int stats_init = 0;
	int counter;
	struct device_selection *dev_sel = NULL;
	int n_selected, n_selections;
	long sel_gen;
	struct devstat *dev_ptr;
#endif
#ifdef NETBSD
	struct disk_sysctl *stats;
#endif
#ifdef OPENBSD
	int diskcount;
	char *disknames, *name, *bufpp;
	char **dk_name;
	struct diskstats *stats;
#endif
#ifdef NETBSD
#define MIBSIZE 3
#endif
#ifdef OPENBSD
#define MIBSIZE 2
#endif
#if defined(NETBSD) || defined(OPENBSD)
	int num_disks, i;
	int mib[MIBSIZE];
	size_t size;
#endif
#ifdef WIN32
	char *name;
	long long rbytes;
	long long wbytes;
#endif

	num_diskio=0;

#ifdef HPUX
	while (1) {
		num = pstat_getdisk(pstat_diskinfo, sizeof pstat_diskinfo[0],
		                    DISK_BATCH, diskidx);
		if (num == -1) {
			sg_set_error_with_errno(SG_ERROR_PSTAT,
			                        "pstat_getdisk");
			return NULL;
		} else if (num == 0) {
			break;
		}

		for (i = 0; i < num; i++) {
			struct pst_diskinfo *di = &pstat_diskinfo[i];

			/* Skip "disabled" disks. */
			if (di->psd_status == 0) {
				continue;
			}
	
			/* We can't seperate the reads from the writes, we'll
			 * just give the same to each. (This value is in
			 * 64-byte chunks according to the pstat header file,
			 * and can wrap to be negative.)
			 */
			rbytes = wbytes = ((unsigned long) di->psd_dkwds) * 64LL;
	
			/* Skip unused disks. */
			if (rbytes == 0 && wbytes == 0) {
				continue;
			}
	
			if (VECTOR_RESIZE(diskio_stats, num_diskio + 1) < 0) {
				return NULL;
			}
	
			diskio_stats_ptr = diskio_stats + num_diskio;
	
			diskio_stats_ptr->read_bytes = rbytes;
			diskio_stats_ptr->write_bytes = wbytes;
	
			diskio_stats_ptr->systime = time(NULL);
	
			num_diskio++;
	
			/* FIXME This should use a static cache, like the Linux
			 * code below. */
			if (diskio_stats_ptr->disk_name == NULL) {
				dh = opendir("/dev/dsk");
				if (dh == NULL) {
					continue;
				}
	
				diskid = (di->psd_dev.psd_major << 24) | di->psd_dev.psd_minor;
				while (1) {
					dinfo = readdir(dh);
					if (dinfo == NULL) {
						break;
					}
					snprintf(fullpathbuf, sizeof(fullpathbuf), "/dev/dsk/%s", dinfo->d_name);
					if (lstat(fullpathbuf, &lstatinfo) < 0) {
						continue;
					}
	
					if (lstatinfo.st_rdev == diskid) {
						if (sg_update_string(&diskio_stats_ptr->disk_name, dinfo->d_name) < 0) {
							return NULL;
						}
						break;
					}
				}
				closedir(dh);
	
				if (diskio_stats_ptr->disk_name == NULL) {
					if (sg_update_string(&diskio_stats_ptr->disk_name, di->psd_hw_path.psh_name) < 0) {
						return NULL;
					}
				}
			}
		}
		diskidx = pstat_diskinfo[num - 1].psd_idx + 1;
	}
#endif
#ifdef OPENBSD
	mib[0] = CTL_HW;
	mib[1] = HW_DISKCOUNT;

	size = sizeof(diskcount);
	if (sysctl(mib, MIBSIZE, &diskcount, &size, NULL, 0) < 0) {
		sg_set_error_with_errno(SG_ERROR_SYSCTL, "CTL_HW.HW_DISKCOUNT");
		return NULL;
	}

	mib[0] = CTL_HW;
	mib[1] = HW_DISKNAMES;

	if (sysctl(mib, MIBSIZE, NULL, &size, NULL, 0) < 0) {
		sg_set_error_with_errno(SG_ERROR_SYSCTL, "CTL_HW.HW_DISKNAMES");
		return NULL;
	}

	disknames = sg_malloc(size);
	if (disknames == NULL) {
		return NULL;
	}

	if (sysctl(mib, MIBSIZE, disknames, &size, NULL, 0) < 0) {
		sg_set_error_with_errno(SG_ERROR_SYSCTL, "CTL_HW.HW_DISKNAMES");
		return NULL;
	}

	dk_name = sg_malloc(diskcount * sizeof(char *));
	bufpp = disknames;
	for (i = 0; i < diskcount && (name = strsep(&bufpp, ",")) != NULL; i++) {
		dk_name[i] = name;
	}
#endif

#if defined(NETBSD) || defined(OPENBSD)
	mib[0] = CTL_HW;
	mib[1] = HW_DISKSTATS;
#ifdef NETBSD
	mib[2] = sizeof(struct disk_sysctl);
#endif

	if (sysctl(mib, MIBSIZE, NULL, &size, NULL, 0) < 0) {
		sg_set_error_with_errno(SG_ERROR_SYSCTL, "CTL_HW.HW_DISKSTATS");
		return NULL;
	}

#ifdef NETBSD
	num_disks = size / sizeof(struct disk_sysctl);
#else
	num_disks = size / sizeof(struct diskstats);
#endif

	stats = sg_malloc(size);
	if (stats == NULL) {
		return NULL;
	}

	if (sysctl(mib, MIBSIZE, stats, &size, NULL, 0) < 0) {
		sg_set_error_with_errno(SG_ERROR_SYSCTL, "CTL_HW.HW_DISKSTATS");
		return NULL;
	}

	for (i = 0; i < num_disks; i++) {
		const char *name;
		u_int64_t rbytes, wbytes;

#ifdef NETBSD
#ifdef HAVE_DK_RBYTES
		rbytes = stats[i].dk_rbytes;
		wbytes = stats[i].dk_wbytes;
#else
		/* Before 2.0, NetBSD merged reads and writes. */
		rbytes = wbytes = stats[i].dk_bytes;
#endif
#else
#ifdef HAVE_DS_RBYTES
		rbytes = stats[i].ds_rbytes;
		wbytes = stats[i].ds_wbytes;
#else
		/* Before 3.5, OpenBSD merged reads and writes */
		rbytes = wbytes = stats[i].ds_bytes;
#endif
#endif

		/* Don't keep stats for disks that have never been used. */
		if (rbytes == 0 && wbytes == 0) {
			continue;
		}

		if (VECTOR_RESIZE(diskio_stats, num_diskio + 1) < 0) {
			return NULL;
		}
		diskio_stats_ptr = diskio_stats + num_diskio;
		
		diskio_stats_ptr->read_bytes = rbytes;
		diskio_stats_ptr->write_bytes = wbytes;
#ifdef NETBSD
		name = stats[i].dk_name;
#else
		name = dk_name[i];
#endif
		if (sg_update_string(&diskio_stats_ptr->disk_name, name) < 0) {
			return NULL;
		}
		diskio_stats_ptr->systime = time(NULL);
	
		num_diskio++;	
	}

	free(stats);
#ifdef OPENBSD
	free(dk_name);
	free(disknames);
#endif
#endif

#if defined(FREEBSD) || defined(DFBSD)
	if (!stats_init) {
		stats.dinfo=sg_malloc(sizeof(struct devinfo));
		if(stats.dinfo==NULL) return NULL;
		bzero(stats.dinfo, sizeof(struct devinfo));
		stats_init = 1;
	}
#ifdef FREEBSD5
	if ((devstat_getdevs(NULL, &stats)) < 0) {
		/* FIXME devstat functions return a string error in
		   devstat_errbuf */
		sg_set_error(SG_ERROR_DEVSTAT_GETDEVS, NULL);
		return NULL;
	}
	/* Not aware of a get all devices, so i said 999. If we ever
	 * find a machine with more than 999 disks, then i'll change
	 * this number :)
	 */
	if (devstat_selectdevs(&dev_sel, &n_selected, &n_selections, &sel_gen, stats.dinfo->generation, stats.dinfo->devices, stats.dinfo->numdevs, NULL, 0, NULL, 0, DS_SELECT_ONLY, 999, 1) < 0) {
		sg_set_error(SG_ERROR_DEVSTAT_SELECTDEVS, NULL);
		return NULL;
	}
#else
	if ((getdevs(&stats)) < 0) {
		sg_set_error(SG_ERROR_DEVSTAT_GETDEVS, NULL);
		return NULL;
	}
	/* Not aware of a get all devices, so i said 999. If we ever
	 * find a machine with more than 999 disks, then i'll change
	 * this number :)
	 */
	if (selectdevs(&dev_sel, &n_selected, &n_selections, &sel_gen, stats.dinfo->generation, stats.dinfo->devices, stats.dinfo->numdevs, NULL, 0, NULL, 0, DS_SELECT_ONLY, 999, 1) < 0) {
		sg_set_error(SG_ERROR_DEVSTAT_SELECTDEVS, NULL);
		return NULL;
	}
#endif

	for(counter=0;counter<stats.dinfo->numdevs;counter++){
		dev_ptr=&stats.dinfo->devices[dev_sel[counter].position];

		/* Throw away devices that have done nothing, ever.. Eg "odd" 
		 * devices.. like mem, proc.. and also doesn't report floppy
		 * drives etc unless they are doing stuff :)
		 */
#ifdef FREEBSD5
		if((dev_ptr->bytes[DEVSTAT_READ]==0) && (dev_ptr->bytes[DEVSTAT_WRITE]==0)) continue;
#else
		if((dev_ptr->bytes_read==0) && (dev_ptr->bytes_written==0)) continue;
#endif

		if (VECTOR_RESIZE(diskio_stats, num_diskio + 1) < 0) {
			return NULL;
		}
		diskio_stats_ptr=diskio_stats+num_diskio;

#ifdef FREEBSD5		
		diskio_stats_ptr->read_bytes=dev_ptr->bytes[DEVSTAT_READ];
		diskio_stats_ptr->write_bytes=dev_ptr->bytes[DEVSTAT_WRITE];
#else
		diskio_stats_ptr->read_bytes=dev_ptr->bytes_read;
		diskio_stats_ptr->write_bytes=dev_ptr->bytes_written;
#endif
		if(diskio_stats_ptr->disk_name!=NULL) free(diskio_stats_ptr->disk_name);
		if (asprintf((&diskio_stats_ptr->disk_name), "%s%d", dev_ptr->device_name, dev_ptr->unit_number) == -1) {
			sg_set_error_with_errno(SG_ERROR_ASPRINTF, NULL);
			return NULL;
		}
		diskio_stats_ptr->systime=time(NULL);

		num_diskio++;
	}
	free(dev_sel);

#endif
#ifdef SOLARIS
	if ((kc = kstat_open()) == NULL) {
		sg_set_error(SG_ERROR_KSTAT_OPEN, NULL);
		return NULL;
	}

	for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
		if (!strcmp(ksp->ks_class, "disk")) {

			if(ksp->ks_type != KSTAT_TYPE_IO) continue;
			/* We dont want metadevices appearins as num_diskio */
			if(strcmp(ksp->ks_module, "md")==0) continue;
			if((kstat_read(kc, ksp, &kios))==-1){	
			}
			
			if (VECTOR_RESIZE(diskio_stats, num_diskio + 1) < 0) {
				kstat_close(kc);
				return NULL;
			}
			diskio_stats_ptr=diskio_stats+num_diskio;
			
			diskio_stats_ptr->read_bytes=kios.nread;
			diskio_stats_ptr->write_bytes=kios.nwritten;
			if (sg_update_string(&diskio_stats_ptr->disk_name,
					     sg_get_svr_from_bsd(ksp->ks_name)) < 0) {
				kstat_close(kc);
				return NULL;
			}
			diskio_stats_ptr->systime=time(NULL);

			num_diskio++;
		}
	}

	kstat_close(kc);
#endif

#ifdef LINUX
	num_diskio = 0;
	n = 0;

	/* Read /proc/partitions to find what devices exist. Recent 2.4 kernels
	   have statistics in here too, so we can use those directly.
	   2.6 kernels have /proc/diskstats instead with almost (but not quite)
	   the same format. */

	f = fopen("/proc/diskstats", "r");
	format = " %d %d %99s %*d %*d %lld %*d %*d %*d %lld";
	if (f == NULL) {
		f = fopen("/proc/partitions", "r");
		format = " %d %d %*d %99s %*d %*d %lld %*d %*d %*d %lld";
	}
	if (f == NULL) goto out;
	now = time(NULL);

	if (!re_compiled) {
		if (regcomp(&part_re, "^(.*/)?[^/]*[0-9]$", REG_EXTENDED | REG_NOSUB) != 0) {
			sg_set_error(SG_ERROR_PARSE, NULL);
			goto out;
		}
		if (regcomp(&not_part_re, "^(.*/)?[^/0-9]+[0-9]+d[0-9]+$", REG_EXTENDED | REG_NOSUB) != 0) {
			sg_set_error(SG_ERROR_PARSE, NULL);
			goto out;
		}
		re_compiled = 1;
	}

	while ((line_ptr = sg_f_read_line(f, "")) != NULL) {
		char name[100];
		long long rsect, wsect;

		int nr = sscanf(line_ptr, format,
			&major, &minor, name, &rsect, &wsect);
		if (nr < 3) continue;

		/* Skip device names ending in numbers, since they're
		   partitions, unless they match the c0d0 pattern that some
		   RAID devices use. */
		/* FIXME: For 2.6+, we should probably be using sysfs to detect
		   this... */
		if ((regexec(&part_re, name, 0, NULL, 0) == 0)
		    && (regexec(&not_part_re, name, 0, NULL, 0) != 0)) {
			continue;
		}

		if (nr < 5) {
			has_pp_stats = 0;
			rsect = 0;
			wsect = 0;
		}

		if (VECTOR_RESIZE(diskio_stats, n + 1) < 0) {
			goto out;
		}
		if (VECTOR_RESIZE(parts, n + 1) < 0) {
			goto out;
		}

		if (sg_update_string(&diskio_stats[n].disk_name, name) < 0) {
			goto out;
		}
		diskio_stats[n].read_bytes = rsect * 512;
		diskio_stats[n].write_bytes = wsect * 512;
		diskio_stats[n].systime = now;
		parts[n].major = major;
		parts[n].minor = minor;

		n++;
	}

	fclose(f);
	f = NULL;

	if (!has_pp_stats) {
		/* This is an older kernel where /proc/partitions doesn't
		   contain stats. Read what we can from /proc/stat instead, and
		   fill in the appropriate bits of the list allocated above. */

		f = fopen("/proc/stat", "r");
		if (f == NULL) goto out;
		now = time(NULL);

		line_ptr = sg_f_read_line(f, "disk_io:");
		if (line_ptr == NULL) goto out;

		while((line_ptr=strchr(line_ptr, ' '))!=NULL){
			long long rsect, wsect;

			if (*++line_ptr == '\0') break;

			if((sscanf(line_ptr,
				"(%d,%d):(%*d, %*d, %lld, %*d, %lld)",
				&major, &minor, &rsect, &wsect)) != 4) {
					continue;
			}

			/* Find the corresponding device from earlier.
			   Just to add to the fun, "minor" is actually the disk
			   number, not the device minor, so we need to figure
			   out the real minor number based on the major!
			   This list is not exhaustive; if you're running
			   an older kernel you probably don't have fancy
			   I2O hardware anyway... */
			switch (major) {
			case 3:
			case 21:
			case 22:
			case 33:
			case 34:
			case 36:
			case 56:
			case 57:
			case 88:
			case 89:
			case 90:
			case 91:
				minor *= 64;
				break;
			case 9:
			case 43:
				break;
			default:
				minor *= 16;
				break;
			}
			for (i = 0; i < n; i++) {
				if (major == parts[i].major
					&& minor == parts[i].minor)
					break;
			}
			if (i == n) continue;

			/* We read the number of blocks. Blocks are stored in
			   512 bytes */
			diskio_stats[i].read_bytes = rsect * 512;
			diskio_stats[i].write_bytes = wsect * 512;
			diskio_stats[i].systime = now;
		}
	}

	num_diskio = n;
out:
	if (f != NULL) fclose(f);
#endif

#ifdef CYGWIN
	sg_set_error(SG_ERROR_UNSUPPORTED, "Cygwin");
	return NULL;
#endif

#ifdef WIN32
	sg_set_error(SG_ERROR_NONE, NULL);

	while((name = get_diskio(num_diskio, &rbytes, &wbytes)) != NULL) {
		if (VECTOR_RESIZE(diskio_stats, num_diskio+1)) {
			return NULL;
		}

		diskio_stats_ptr = diskio_stats + num_diskio;

		if (sg_update_string(&diskio_stats_ptr->disk_name, name) < 0) {
			return NULL;
		}
		sg_update_string(&name, NULL);
		diskio_stats_ptr->read_bytes = rbytes;
		diskio_stats_ptr->write_bytes = wbytes;

		diskio_stats_ptr->systime = 0;

		num_diskio++;
	}
#endif

	*entries=num_diskio;

	return diskio_stats;
}

sg_disk_io_stats *sg_get_disk_io_stats_diff(int *entries){
#ifndef WIN32
	VECTOR_DECLARE_STATIC(diff, sg_disk_io_stats, 1,
			      diskio_stat_init, diskio_stat_destroy);
	sg_disk_io_stats *src = NULL, *dest;
	int i, j, diff_count, new_count;

	if (diskio_stats == NULL) {
		/* No previous stats, so we can't calculate a difference. */
		return sg_get_disk_io_stats(entries);
	}

	/* Resize the results array to match the previous stats. */
	diff_count = VECTOR_SIZE(diskio_stats);
	if (VECTOR_RESIZE(diff, diff_count) < 0) {
		return NULL;
	}

	/* Copy the previous stats into the result. */
	for (i = 0; i < diff_count; i++) {
		src = &diskio_stats[i];
		dest = &diff[i];

		if (sg_update_string(&dest->disk_name, src->disk_name) < 0) {
			return NULL;
		}
		dest->read_bytes = src->read_bytes;
		dest->write_bytes = src->write_bytes;
		dest->systime = src->systime;
	}

	/* Get a new set of stats. */
	if (sg_get_disk_io_stats(&new_count) == NULL) {
		return NULL;
	}

	/* For each previous stat... */
	for (i = 0; i < diff_count; i++) {
		dest = &diff[i];

		/* ... find the corresponding new stat ... */
		for (j = 0; j < new_count; j++) {
			/* Try the new stat in the same position first,
			   since that's most likely to be it. */
			src = &diskio_stats[(i + j) % new_count];
			if (strcmp(src->disk_name, dest->disk_name) == 0) {
				break;
			}
		}
		if (j == new_count) {
			/* No match found. */
			continue;
		}

		/* ... and subtract the previous stat from it to get the
		   difference. */
		dest->read_bytes = src->read_bytes - dest->read_bytes;
		dest->write_bytes = src->write_bytes - dest->write_bytes;
		dest->systime = src->systime - dest->systime;
	}

	*entries = diff_count;
	return diff;
#else /* WIN32 */
	return sg_get_disk_io_stats(entries);
#endif
}

int sg_disk_io_compare_name(const void *va, const void *vb) {
	const sg_disk_io_stats *a = (const sg_disk_io_stats *)va;
	const sg_disk_io_stats *b = (const sg_disk_io_stats *)vb;

	return strcmp(a->disk_name, b->disk_name);
}
Exemplo n.º 3
0
sg_page_stats *sg_get_page_stats() {
#ifdef SOLARIS
    kstat_ctl_t *kc;
    kstat_t *ksp;
    cpu_stat_t cs;
#endif
#if defined(LINUX) || defined(CYGWIN)
    FILE *f;
    char *line_ptr;
#endif
#if defined(FREEBSD) || defined(DFBSD)
    size_t size;
#endif
#if defined(NETBSD) || defined(OPENBSD)
    struct uvmexp *uvm;
#endif

    page_stats.systime = time(NULL);
    page_stats.pages_pagein=0;
    page_stats.pages_pageout=0;

#ifdef SOLARIS
    if ((kc = kstat_open()) == NULL) {
        sg_set_error(SG_ERROR_KSTAT_OPEN, NULL);
        return NULL;
    }
    for (ksp = kc->kc_chain; ksp!=NULL; ksp = ksp->ks_next) {
        if ((strcmp(ksp->ks_module, "cpu_stat")) != 0) continue;
        if (kstat_read(kc, ksp, &cs) == -1) {
            continue;
        }

        page_stats.pages_pagein+=(long long)cs.cpu_vminfo.pgpgin;
        page_stats.pages_pageout+=(long long)cs.cpu_vminfo.pgpgout;
    }

    kstat_close(kc);
#endif
#if defined(LINUX) || defined(CYGWIN)
    if ((f = fopen("/proc/vmstat", "r")) != NULL) {
        while ((line_ptr = sg_f_read_line(f, "")) != NULL) {
            long long value;

            if (sscanf(line_ptr, "%*s %lld", &value) != 1) {
                continue;
            }

            if (strncmp(line_ptr, "pgpgin ", 7) == 0) {
                page_stats.pages_pagein = value;
            } else if (strncmp(line_ptr, "pgpgout ", 8) == 0) {
                page_stats.pages_pageout = value;
            }
        }

        fclose(f);
    } else if ((f = fopen("/proc/stat", "r")) != NULL) {
        if ((line_ptr = sg_f_read_line(f, "page")) == NULL) {
            sg_set_error(SG_ERROR_PARSE, "page");
            fclose(f);
            return NULL;
        }

        if (sscanf(line_ptr, "page %lld %lld", &page_stats.pages_pagein, &page_stats.pages_pageout) != 2) {
            sg_set_error(SG_ERROR_PARSE, "page");
            fclose(f);
            return NULL;
        }

        fclose(f);
    } else {
        sg_set_error(SG_ERROR_OPEN, "/proc/stat");
        return NULL;
    }
#endif
#if defined(FREEBSD) || defined(DFBSD)
    size = sizeof page_stats.pages_pagein;
    if (sysctlbyname("vm.stats.vm.v_swappgsin", &page_stats.pages_pagein, &size, NULL, 0) < 0) {
        sg_set_error(SG_ERROR_SYSCTLBYNAME, "vm.stats.vm.v_swappgsin");
        return NULL;
    }
    size = sizeof page_stats.pages_pageout;
    if (sysctlbyname("vm.stats.vm.v_swappgsout", &page_stats.pages_pageout, &size, NULL, 0) < 0) {
        sg_set_error(SG_ERROR_SYSCTLBYNAME, "vm.stats.vm.v_swappgsout");
        return NULL;
    }
#endif
#if defined(NETBSD) || defined(OPENBSD)
    if ((uvm = sg_get_uvmexp()) == NULL) {
        return NULL;
    }

    page_stats.pages_pagein = uvm->pgswapin;
    page_stats.pages_pageout = uvm->pgswapout;
#endif

    return &page_stats;
}
Exemplo n.º 4
0
int get_mem_stats(Digikam::KMemoryInfo::KMemoryInfoData* const data)
{

#ifdef Q_OS_HPUX
    struct pst_static* pstat_static = 0;
    struct pst_dynamic pstat_dynamic;
    long long          pagesize;
#endif // Q_OS_HPUX

#ifdef Q_OS_SOLARIS
    kstat_ctl_t*   kc  = 0;
    kstat_t*       ksp = 0;
    kstat_named_t* kn  = 0;
    long           totalmem;
    int            pagesize;
#endif // Q_OS_SOLARIS

#if defined(Q_OS_LINUX) || defined(Q_OS_CYGWIN)
    char*              line_ptr = 0;
    unsigned long long value;
    FILE*              f        = 0;
#endif // defined(Q_OS_LINUX) || defined(Q_OS_CYGWIN)

#if defined(Q_OS_FREEBSD) || defined(Q_OS_DFBSD)
    int    mib[2];
    u_long physmem;
    size_t size;
    u_long free_count;
    u_long cache_count;
    u_long inactive_count;
    int    pagesize;
#endif // defined(Q_OS_FREEBSD) || defined(Q_OS_DFBSD)

#if defined(Q_OS_NETBSD)
    struct uvmexp* uvm = 0;
#endif // defined(Q_OS_NETBSD)

#if defined(Q_OS_OPENBSD)
    int    mib[2];
    struct vmtotal vmtotal;
    size_t size;
    int    pagesize, page_multiplier;
#endif // defined(Q_OS_OPENBSD)

#ifdef Q_OS_WIN
    MEMORYSTATUSEX memstats;
#endif

#ifdef Q_WS_MAC
    Q_UNUSED(data);
#endif

#ifdef Q_OS_HPUX
    data->platform = QString("HPUX");

    if((pagesize = sysconf(_SC_PAGESIZE)) == -1)
    {
        //sg_set_error_with_errno(SG_ERROR_SYSCONF, "_SC_PAGESIZE");
        return 0;
    }

    if (pstat_getdynamic(&pstat_dynamic, sizeof(pstat_dynamic), 1, 0) == -1)
    {
        //sg_set_error_with_errno(SG_ERROR_PSTAT, "pstat_dynamic");
        return 0;
    }

    pstat_static = sg_get_pstat_static();

    if (pstat_static == NULL)
    {
        return 0;
    }

    /* FIXME Does this include swap? */
    data->totalRam = ((long long) pstat_static->physical_memory) * pagesize;
    data->freeRam  = ((long long) pstat_dynamic.psd_free)        * pagesize;
    data->usedRam  = data->totalRam - data->freeRam;

    return 1;
#endif // Q_OS_HPUX

#ifdef Q_OS_SOLARIS
    data->platform = QString("SOLARIS");

    if((pagesize = sysconf(_SC_PAGESIZE)) == -1)
    {
        //sg_set_error_with_errno(SG_ERROR_SYSCONF, "_SC_PAGESIZE");
        return 0;
    }

    if((totalmem = sysconf(_SC_PHYS_PAGES)) == -1)
    {
        //sg_set_error_with_errno(SG_ERROR_SYSCONF, "_SC_PHYS_PAGES");
        return 0;
    }

    if ((kc = kstat_open()) == NULL)
    {
        //sg_set_error(SG_ERROR_KSTAT_OPEN, NULL);
        return 0;
    }

    if((ksp = kstat_lookup(kc, "unix", 0, "system_pages")) == NULL)
    {
        //sg_set_error(SG_ERROR_KSTAT_LOOKUP, "unix,0,system_pages");
        return 0;
    }

    if (kstat_read(kc, ksp, 0) == -1)
    {
        //sg_set_error(SG_ERROR_KSTAT_READ, NULL);
        return 0;
    }

    if((kn = (kstat_named_t*)kstat_data_lookup(ksp, "freemem")) == NULL)
    {
        //sg_set_error(SG_ERROR_KSTAT_DATA_LOOKUP, "freemem");
        return 0;
    }

    kstat_close(kc);

    data->totalRam = (long long)totalmem * (long long)pagesize;
    data->freeRam  = ((long long)kn->value.ul) * (long long)pagesize;
    data->usedRam  = data->totalRam - data->freeRam;

    return 1;
#endif // Q_OS_SOLARIS

#if defined(Q_OS_LINUX) || defined(Q_OS_CYGWIN)
    data->platform = QString("LINUX");

    if ((f = fopen("/proc/meminfo", "r")) == NULL)
    {
        //sg_set_error_with_errno(SG_ERROR_OPEN, "/proc/meminfo");
        return 0;
    }

    while ((line_ptr = sg_f_read_line(f, "")) != NULL)
    {
        if (sscanf(line_ptr, "%*s %llu kB", &value) != 1)
        {
            continue;
        }

        value *= 1024;

        if (strncmp(line_ptr, "MemTotal:", 9) == 0)
        {
            data->totalRam = value;
        }
        else if (strncmp(line_ptr, "MemFree:", 8) == 0)
        {
            data->freeRam = value;
        }
        else if (strncmp(line_ptr, "Cached:", 7) == 0)
        {
            data->cacheRam = value;
        }
    }

    fclose(f);
    data->usedRam = data->totalRam - data->freeRam;

    return 1;
#endif // defined(Q_OS_LINUX) || defined(Q_OS_CYGWIN)

#if defined(Q_OS_FREEBSD)
    data->platform = QString("FREEBSD");

    /* Returns bytes */
    mib[0] = CTL_HW;
    mib[1] = HW_PHYSMEM;
    size   = sizeof physmem;

    if (sysctl(mib, 2, &physmem, &size, NULL, 0) < 0)
    {
        //sg_set_error_with_errno(SG_ERROR_SYSCTL, "CTL_HW.HW_PHYSMEM");
        return 0;
    }

    data->totalRam = physmem;

    /*returns pages*/
    size           = sizeof free_count;

    if (sysctlbyname("vm.stats.vm.v_free_count", &free_count, &size, NULL, 0) < 0)
    {
        //sg_set_error_with_errno(SG_ERROR_SYSCTLBYNAME, "vm.stats.vm.v_free_count");
        return 0;
    }

    size = sizeof inactive_count;

    if (sysctlbyname("vm.stats.vm.v_inactive_count", &inactive_count , &size, NULL, 0) < 0)
    {
        //sg_set_error_with_errno(SG_ERROR_SYSCTLBYNAME, "vm.stats.vm.v_inactive_count");
        return 0;
    }

    size = sizeof cache_count;

    if (sysctlbyname("vm.stats.vm.v_cache_count", &cache_count, &size, NULL, 0) < 0)
    {
        //sg_set_error_with_errno(SG_ERROR_SYSCTLBYNAME, "vm.stats.vm.v_cache_count");
        return 0;
    }

    /* Because all the vm.stats returns pages, I need to get the page size.
     * After that I then need to multiple the anything that used vm.stats to
     * get the system statistics by pagesize
     */
    pagesize       = getpagesize();
    data->cacheRam = cache_count * pagesize;

    /* Of couse nothing is ever that simple :) And I have inactive pages to
     * deal with too. So I'm going to add them to free memory :)
     */
    data->freeRam  = (free_count*pagesize)+(inactive_count*pagesize);
    data->usedRam  = physmem-data->freeRam;

    return 1;
#endif // defined(Q_OS_FREEBSD)

#if defined(Q_OS_NETBSD)
    data->platform = QString("NETBSD");

    if ((uvm = sg_get_uvmexp()) == NULL)
    {
        return 0;
    }

    data->totalRam = uvm->pagesize * uvm->npages;
    data->cacheRam = uvm->pagesize * (uvm->filepages + uvm->execpages);
    data->freeRam  = uvm->pagesize * (uvm->free + uvm->inactive);
    data->usedRam  = data->totalRam - data->freeRam;

    return 1;
#endif // defined(Q_OS_NETBSD)

#if defined(Q_OS_OPENBSD)
    data->platform = QString("OPENBSD");

    /* The code in this section is based on the code in the OpenBSD
     * top utility, located at src/usr.bin/top/machine.c in the
     * OpenBSD source tree.
     *
     * For fun, and like OpenBSD top, we will do the multiplication
     * converting the memory stats in pages to bytes in base 2.
     */

    /* All memory stats in OpenBSD are returned as the number of pages.
     * To convert this into the number of bytes we need to know the
     * page size on this system.
     */
    pagesize = sysconf(_SC_PAGESIZE);

    /* The pagesize gives us the base 10 multiplier, so we need to work
     * out what the base 2 multiplier is. This means dividing
     * pagesize by 2 until we reach unity, and counting the number of
     * divisions required.
     */
    page_multiplier = 0;

    while (pagesize > 1)
    {
        page_multiplier++;
        pagesize >>= 1;
    }

    /* We can now ret the raw VM stats (in pages) using the
     * sysctl interface.
     */
    mib[0] = CTL_VM;
    mib[1] = VM_METER;
    size   = sizeof(vmtotal);

    if (sysctl(mib, 2, &vmtotal, &size, NULL, 0) < 0)
    {
        bzero(&vmtotal, sizeof(vmtotal));
        //sg_set_error_with_errno(SG_ERROR_SYSCTL, "CTL_VM.VM_METER");
        return 0;
    }

    /* Convert the raw stats to bytes, and return these to the caller
     */
    data->usedRam  = (vmtotal.t_rm << page_multiplier);   /* total real mem in use */
    data->cacheRam = 0;                                  /* no cache stats */
    data->freeRam  = (vmtotal.t_free << page_multiplier); /* free memory pages */
    data->totalRam = (data->usedRam + data->freeRam);

    return 1;
#endif // defined(Q_OS_OPENBSD)

#ifdef Q_OS_WIN
    data->platform = QString("WINDOWS");

    memstats.dwLength = sizeof(memstats);

    if (!GlobalMemoryStatusEx(&memstats))
    {
        //sg_set_error_with_errno(SG_ERROR_MEMSTATUS, NULL);
        return 0;
    }

    data->freeRam  = memstats.ullAvailPhys;
    data->totalRam = memstats.ullTotalPhys;
    data->usedRam  = data->totalRam - data->freeRam;

    //if(read_counter_large(SG_WIN32_MEM_CACHE, &data->cacheRam)) {
        data->cacheRam = 0;
    //}

    return 1;
#endif // Q_OS_WIN

    return -1;
}
Exemplo n.º 5
0
sg_process_stats *sg_get_process_stats(int *entries){
	VECTOR_DECLARE_STATIC(proc_state, sg_process_stats, 64,
			      proc_state_init, proc_state_destroy);
	int proc_state_size = 0;
	sg_process_stats *proc_state_ptr;
#ifdef HPUX
	struct pst_status pstat_procinfo[PROCESS_BATCH];
	long procidx = 0;
	long long pagesize;
	int num, i;
#endif
#ifdef AIX
	struct procentry64 *procs = NULL;
	long long pagesize;
	int fetched = 0;
	pid_t index = 0;
	unsigned proc_idx;
	time_t utime, stime;
	int ncpus;
	struct timeval now_tval;
	double now_time;
	char cmndline[ARG_MAX];
	char comm[ARG_MAX];
	struct procentry64 curproc_for_getargs;
#define PROCS_TO_FETCH  1000
#endif
#ifdef ALLBSD
	int mib[4];
	size_t size;
	struct kinfo_proc *kp_stats;
	int procs, i;
	char *proctitle;
#if (defined(FREEBSD) && !defined(FREEBSD5)) || defined(DFBSD)
	kvm_t *kvmd;
	char **args, **argsp;
	int argslen = 0;
#else
	long buflen;
	char *p, *proctitletmp;
#endif
#ifdef NETBSD2
	int lwps;
	struct kinfo_lwp *kl_stats;
#endif
#endif
#if defined(SOLARIS) || defined(LINUX)
	DIR *proc_dir;
	struct dirent *dir_entry;
	char filename[MAX_FILE_LENGTH];
	FILE *f;
#ifdef SOLARIS
	psinfo_t process_info;
#endif
#ifdef LINUX
	char s;
	/* If someone has a executable of 4k filename length, they deserve to get it truncated :) */
	char ps_name[4096];
	char *ptr;
	VECTOR_DECLARE_STATIC(psargs, char, 128, NULL, NULL);
	unsigned long stime, utime, starttime;
	int x;
	int fn;
	int len;
	int rc;
	time_t uptime;
	long tickspersec;
#endif

#ifdef LINUX
	if ((f=fopen("/proc/uptime", "r")) == NULL) {
		sg_set_error_with_errno(SG_ERROR_OPEN, "/proc/uptime");
		return NULL;
	}
	if((fscanf(f,"%lu %*d",&uptime)) != 1){
		sg_set_error(SG_ERROR_PARSE, NULL);
		return NULL;
	}
	fclose(f);
#endif

	if((proc_dir=opendir(PROC_LOCATION))==NULL){
		sg_set_error_with_errno(SG_ERROR_OPENDIR, PROC_LOCATION);
		return NULL;
	}

	while((dir_entry=readdir(proc_dir))!=NULL){
		if(atoi(dir_entry->d_name) == 0) continue;

#ifdef SOLARIS
		snprintf(filename, MAX_FILE_LENGTH, "/proc/%s/psinfo", dir_entry->d_name);
#endif
#ifdef LINUX
		snprintf(filename, MAX_FILE_LENGTH, "/proc/%s/stat", dir_entry->d_name);
#endif
		if((f=fopen(filename, "r"))==NULL){
			/* Open failed.. Process since vanished, or the path was too long.
			 * Ah well, move onwards to the next one */
			continue;
		}
#ifdef SOLARIS
		fread(&process_info, sizeof(psinfo_t), 1, f);
		fclose(f);
#endif

		if (VECTOR_RESIZE(proc_state, proc_state_size + 1) < 0) {
			return NULL;
		}
		proc_state_ptr = proc_state+proc_state_size;

#ifdef SOLARIS		
		proc_state_ptr->pid = process_info.pr_pid;
		proc_state_ptr->parent = process_info.pr_ppid;
		proc_state_ptr->pgid = process_info.pr_pgid;
		proc_state_ptr->uid = process_info.pr_uid;
		proc_state_ptr->euid = process_info.pr_euid;
		proc_state_ptr->gid = process_info.pr_gid;
		proc_state_ptr->egid = process_info.pr_egid;
		proc_state_ptr->proc_size = (process_info.pr_size) * 1024;
		proc_state_ptr->proc_resident = (process_info.pr_rssize) * 1024;
		proc_state_ptr->time_spent = process_info.pr_time.tv_sec;
		proc_state_ptr->cpu_percent = (process_info.pr_pctcpu * 100.0) / 0x8000;
		proc_state_ptr->nice = (int)process_info.pr_lwp.pr_nice - 20;
		if (sg_update_string(&proc_state_ptr->process_name,
				     process_info.pr_fname) < 0) {
			return NULL;
		}
		if (sg_update_string(&proc_state_ptr->proctitle,
				     process_info.pr_psargs) < 0) {
			return NULL;
		}

		switch (process_info.pr_lwp.pr_state) {
		case 1:
			proc_state_ptr->state = SG_PROCESS_STATE_SLEEPING;
			break;
		case 2:
		case 5:
			proc_state_ptr->state = SG_PROCESS_STATE_RUNNING; 
			break;
		case 3:
			proc_state_ptr->state = SG_PROCESS_STATE_ZOMBIE; 
			break;
		case 4:
			proc_state_ptr->state = SG_PROCESS_STATE_STOPPED; 
			break;
		}
#endif
#ifdef LINUX
		x = fscanf(f, "%d %4096s %c %d %d %*d %*d %*d %*u %*u %*u %*u %*u %lu %lu %*d %*d %*d %d %*d %*d %lu %llu %llu %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*d %*d\n", &(proc_state_ptr->pid), ps_name, &s, &(proc_state_ptr->parent), &(proc_state_ptr->pgid), &utime, &stime, &(proc_state_ptr->nice), &starttime, &(proc_state_ptr->proc_size), &(proc_state_ptr->proc_resident));
		/* +3 becuase man page says "Resident  Set Size: number of pages the process has in real memory, minus 3 for administrative purposes." */
		proc_state_ptr->proc_resident = (proc_state_ptr->proc_resident + 3) * getpagesize();
		switch (s) {
		case 'S':
			proc_state_ptr->state = SG_PROCESS_STATE_SLEEPING;
			break;
		case 'R':
			proc_state_ptr->state = SG_PROCESS_STATE_RUNNING;
			break;
		case 'Z':
			proc_state_ptr->state = SG_PROCESS_STATE_ZOMBIE;
			break;
		case 'T':
		case 'D':
			proc_state_ptr->state = SG_PROCESS_STATE_STOPPED;
			break;
		}
	
		/* pa_name[0] should = '(' */
		ptr = strchr(&ps_name[1], ')');	
		if(ptr !=NULL) *ptr='\0';

		if (sg_update_string(&proc_state_ptr->process_name,
				     &ps_name[1]) < 0) {
			return NULL;
		}

		/* cpu */
		proc_state_ptr->cpu_percent = (100.0 * (utime + stime)) / ((uptime * 100.0) - starttime);
		tickspersec = sysconf (_SC_CLK_TCK);
		if (tickspersec < 0) {
			proc_state_ptr->time_spent = 0;
		}
		else {
			proc_state_ptr->time_spent = (utime + stime) / tickspersec;
		}

		fclose(f);

		/* uid / gid */
		snprintf(filename, MAX_FILE_LENGTH, "/proc/%s/status", dir_entry->d_name);
		if ((f=fopen(filename, "r")) == NULL) {
			/* Open failed.. Process since vanished, or the path was too long.
			 * Ah well, move onwards to the next one */
			continue;
		}

		if((ptr=sg_f_read_line(f, "Uid:"))==NULL){
			fclose(f);
			continue;
		}
		sscanf(ptr, "Uid:\t%d\t%d\t%*d\t%*d\n", &(proc_state_ptr->uid), &(proc_state_ptr->euid));

		if((ptr=sg_f_read_line(f, "Gid:"))==NULL){
			fclose(f);
			continue;
		}
		sscanf(ptr, "Gid:\t%d\t%d\t%*d\t%*d\n", &(proc_state_ptr->gid), &(proc_state_ptr->egid));

		fclose(f);

		/* proctitle */	
		snprintf(filename, MAX_FILE_LENGTH, "/proc/%s/cmdline", dir_entry->d_name);

		if((fn=open(filename, O_RDONLY)) == -1){
			/* Open failed.. Process since vanished, or the path was too long.
			 * Ah well, move onwards to the next one */
			continue;
		}

#define READ_BLOCK_SIZE 128
		len = 0;
		do {
			if (VECTOR_RESIZE(psargs, len + READ_BLOCK_SIZE) < 0) {
				return NULL;
			}
			rc = read(fn, psargs + len, READ_BLOCK_SIZE);
			if (rc > 0) {
				len += rc;
			}
		} while (rc == READ_BLOCK_SIZE);
		close(fn);

		if (rc == -1) {
			/* Read failed; move on. */
			continue;
		}

		/* Turn \0s into spaces within the command line. */
		ptr = psargs;
		for(x = 0; x < len; x++) {
			if (*ptr == '\0') *ptr = ' ';
			ptr++;
		}

		if (len == 0) {
			/* We want psargs to be NULL. */
			if (VECTOR_RESIZE(psargs, 0) < 0) {
				return NULL;
			}
		} else {
			/* Not empty, so append a \0. */
			if (VECTOR_RESIZE(psargs, len + 1) < 0) {
				return NULL;
			}
			psargs[len] = '\0';
		}

		if (sg_update_string(&proc_state_ptr->proctitle, psargs) < 0) {
			return NULL;
		}
#endif

		proc_state_size++;
	}
	closedir(proc_dir);
#endif

#ifdef ALLBSD
	mib[0] = CTL_KERN;
	mib[1] = KERN_PROC;
	mib[2] = KERN_PROC_ALL;

	if(sysctl(mib, 3, NULL, &size, NULL, 0) < 0) {
		sg_set_error_with_errno(SG_ERROR_SYSCTL,
		                        "CTL_KERN.KERN_PROC.KERN_PROC_ALL");
		return NULL;
	}

	procs = size / sizeof(struct kinfo_proc);

	kp_stats = sg_malloc(size);
	if(kp_stats == NULL) {
		return NULL;
	}
	memset(kp_stats, 0, size);

	if(sysctl(mib, 3, kp_stats, &size, NULL, 0) < 0) {
		sg_set_error_with_errno(SG_ERROR_SYSCTL,
		                        "CTL_KERN.KERN_PROC.KERN_PROC_ALL");
		free(kp_stats);
		return NULL;
	}

#if (defined(FREEBSD) && !defined(FREEBSD5)) || defined(DFBSD)
	kvmd = sg_get_kvm2();
#endif

	for (i = 0; i < procs; i++) {
		const char *name;

#ifdef FREEBSD5
		if (kp_stats[i].ki_stat == 0) {
#else
		if (kp_stats[i].kp_proc.p_stat == 0) {
#endif
			/* FreeBSD 5 deliberately overallocates the array that
			 * the sysctl returns, so we'll get a few junk
			 * processes on the end that we have to ignore. (Search
			 * for "overestimate by 5 procs" in
			 * src/sys/kern/kern_proc.c for more details.) */
			continue;
		}

		if (VECTOR_RESIZE(proc_state, proc_state_size + 1) < 0) {
			return NULL;
		}
		proc_state_ptr = proc_state+proc_state_size;

#ifdef FREEBSD5
		name = kp_stats[i].ki_comm;
#elif defined(DFBSD)
		name = kp_stats[i].kp_thread.td_comm;
#else
		name = kp_stats[i].kp_proc.p_comm;
#endif
		if (sg_update_string(&proc_state_ptr->process_name, name) < 0) {
			return NULL;
		}

#if defined(FREEBSD5) || defined(NETBSD) || defined(OPENBSD)

#ifdef FREEBSD5
		mib[2] = KERN_PROC_ARGS;
		mib[3] = kp_stats[i].ki_pid;
#else
		mib[1] = KERN_PROC_ARGS;
		mib[2] = kp_stats[i].kp_proc.p_pid;
		mib[3] = KERN_PROC_ARGV;
#endif

		free(proc_state_ptr->proctitle);
		proc_state_ptr->proctitle = NULL;

/* Starting size - we'll double this straight away */
#define PROCTITLE_START_SIZE 64
		buflen = PROCTITLE_START_SIZE;
		size = buflen;
		proctitle = NULL;

		do {
			if((long) size >= buflen) {
				buflen *= 2;
				size = buflen;
				proctitletmp = sg_realloc(proctitle, buflen);
				if(proctitletmp == NULL) {
					free(proctitle);
					proctitle = NULL;
					proc_state_ptr->proctitle = NULL;
					size = 0;
					break;
				}
				proctitle = proctitletmp;
				bzero(proctitle, buflen);
			}

			if(sysctl(mib, 4, proctitle, &size, NULL, 0) < 0) {
				free(proctitle);
				proctitle = NULL;
				proc_state_ptr->proctitle = NULL;
				size = 0;
				break;
			}
		} while((long) size >= buflen);

		if(size > 0) {
			proc_state_ptr->proctitle = sg_malloc(size+1);
			if(proc_state_ptr->proctitle == NULL) {
				return NULL;
			}
			p = proctitle;
#ifdef OPENBSD
			/* On OpenBSD, this value has the argv pointers (which
			 * are terminated by a NULL) at the front, so we have
			 * to skip over them to get to the strings. */
			while (*(char ***)p != NULL) {
				p += sizeof(char **);
			}
			p += sizeof(char **);
#endif
			proc_state_ptr->proctitle[0] = '\0';
			do {
				sg_strlcat(proc_state_ptr->proctitle, p, size+1);
				sg_strlcat(proc_state_ptr->proctitle, " ", size+1);
				p += strlen(p) + 1;
			} while (p < proctitle + size);
			free(proctitle);
			proctitle = NULL;
			/* remove trailing space */
			proc_state_ptr->proctitle[strlen(proc_state_ptr->proctitle)-1] = '\0';
		}
		else {
			if(proctitle != NULL) {
				free(proctitle);
				proctitle = NULL;
			}
			proc_state_ptr->proctitle = NULL;
		}
#else
		free(proc_state_ptr->proctitle);
		proc_state_ptr->proctitle = NULL;
		if(kvmd != NULL) {
			args = kvm_getargv(kvmd, &(kp_stats[i]), 0);
			if(args != NULL) {
				argsp = args;
				while(*argsp != NULL) {
					argslen += strlen(*argsp) + 1;
					argsp++;
				}
				proctitle = sg_malloc(argslen + 1);
				proctitle[0] = '\0';
				if(proctitle == NULL) {
					return NULL;
				}
				while(*args != NULL) {
					sg_strlcat(proctitle, *args, argslen + 1);
					sg_strlcat(proctitle, " ", argslen + 1);
					args++;
				}
				/* remove trailing space */
				proctitle[strlen(proctitle)-1] = '\0';
				proc_state_ptr->proctitle = proctitle;
			}
			else {
				proc_state_ptr->proctitle = NULL;
			}
		}
		else {
			proc_state_ptr->proctitle = NULL;
		}
#endif

#ifdef FREEBSD5
		proc_state_ptr->pid = kp_stats[i].ki_pid;
		proc_state_ptr->parent = kp_stats[i].ki_ppid;
		proc_state_ptr->pgid = kp_stats[i].ki_pgid;
#else
		proc_state_ptr->pid = kp_stats[i].kp_proc.p_pid;
		proc_state_ptr->parent = kp_stats[i].kp_eproc.e_ppid;
		proc_state_ptr->pgid = kp_stats[i].kp_eproc.e_pgid;
#endif

#ifdef FREEBSD5
		proc_state_ptr->uid = kp_stats[i].ki_ruid;
		proc_state_ptr->euid = kp_stats[i].ki_uid;
		proc_state_ptr->gid = kp_stats[i].ki_rgid;
		proc_state_ptr->egid = kp_stats[i].ki_svgid;
#elif defined(DFBSD)
		proc_state_ptr->uid = kp_stats[i].kp_eproc.e_ucred.cr_ruid;
		proc_state_ptr->euid = kp_stats[i].kp_eproc.e_ucred.cr_svuid;
		proc_state_ptr->gid = kp_stats[i].kp_eproc.e_ucred.cr_rgid;
		proc_state_ptr->egid = kp_stats[i].kp_eproc.e_ucred.cr_svgid;
#else
		proc_state_ptr->uid = kp_stats[i].kp_eproc.e_pcred.p_ruid;
		proc_state_ptr->euid = kp_stats[i].kp_eproc.e_pcred.p_svuid;
		proc_state_ptr->gid = kp_stats[i].kp_eproc.e_pcred.p_rgid;
		proc_state_ptr->egid = kp_stats[i].kp_eproc.e_pcred.p_svgid;
#endif

#ifdef FREEBSD5
		proc_state_ptr->proc_size = kp_stats[i].ki_size;
		/* This is in pages */
		proc_state_ptr->proc_resident =
			kp_stats[i].ki_rssize * getpagesize();
		/* This is in microseconds */
		proc_state_ptr->time_spent = kp_stats[i].ki_runtime / 1000000;
		proc_state_ptr->cpu_percent =
			((double)kp_stats[i].ki_pctcpu / FSCALE) * 100.0;
		proc_state_ptr->nice = kp_stats[i].ki_nice;
#else
		proc_state_ptr->proc_size =
			kp_stats[i].kp_eproc.e_vm.vm_map.size;
		/* This is in pages */
		proc_state_ptr->proc_resident =
			kp_stats[i].kp_eproc.e_vm.vm_rssize * getpagesize();
#if defined(NETBSD) || defined(OPENBSD)
		proc_state_ptr->time_spent =
			kp_stats[i].kp_proc.p_rtime.tv_sec;
#elif defined(DFBSD)
		proc_state_ptr->time_spent = 
			( kp_stats[i].kp_thread.td_uticks +
			kp_stats[i].kp_thread.td_sticks +
			kp_stats[i].kp_thread.td_iticks ) / 1000000;
#else
		/* This is in microseconds */
		proc_state_ptr->time_spent =
			kp_stats[i].kp_proc.p_runtime / 1000000;
#endif
		proc_state_ptr->cpu_percent =
			((double)kp_stats[i].kp_proc.p_pctcpu / FSCALE) * 100.0;
		proc_state_ptr->nice = kp_stats[i].kp_proc.p_nice;
#endif

#ifdef NETBSD2
		{
			size_t size;
			int mib[5];

			mib[0] = CTL_KERN;
			mib[1] = KERN_LWP;
			mib[2] = kp_stats[i].kp_proc.p_pid;
			mib[3] = sizeof(struct kinfo_lwp);
			mib[4] = 0;

			if(sysctl(mib, 5, NULL, &size, NULL, 0) < 0) {
				sg_set_error_with_errno(SG_ERROR_SYSCTL, "CTL_KERN.KERN_LWP.pid.structsize.0");
				return NULL;
			}

			lwps = size / sizeof(struct kinfo_lwp);
			mib[4] = lwps;

			kl_stats = sg_malloc(size);
			if(kl_stats == NULL) {
				return NULL;
			}

			if(sysctl(mib, 5, kl_stats, &size, NULL, 0) < 0) {
				sg_set_error_with_errno(SG_ERROR_SYSCTL, "CTL_KERN.KERN_LWP.pid.structsize.buffersize");
				return NULL;
			}
		}

		switch(kp_stats[i].kp_proc.p_stat) {
		case SIDL:
			proc_state_ptr->state = SG_PROCESS_STATE_RUNNING;
			break;
		case SACTIVE:
			{
				int i;

				for(i = 0; i < lwps; i++) {
					switch(kl_stats[i].l_stat) {
					case LSONPROC:
					case LSRUN:
						proc_state_ptr->state = SG_PROCESS_STATE_RUNNING;
						goto end;
					case LSSLEEP:
						proc_state_ptr->state = SG_PROCESS_STATE_SLEEPING;
						goto end;
					case LSSTOP:
					case LSSUSPENDED:
						proc_state_ptr->state = SG_PROCESS_STATE_STOPPED;
						goto end;
					}
					proc_state_ptr->state = SG_PROCESS_STATE_UNKNOWN;
				}
				end: ;
			}
			break;
		case SSTOP:
			proc_state_ptr->state = SG_PROCESS_STATE_STOPPED;
			break;
		case SZOMB:
			proc_state_ptr->state = SG_PROCESS_STATE_ZOMBIE;
			break;
		default:
			proc_state_ptr->state = SG_PROCESS_STATE_UNKNOWN;
			break;
		}

		free(kl_stats);
#else
#ifdef FREEBSD5
		switch (kp_stats[i].ki_stat) {
#else
		switch (kp_stats[i].kp_proc.p_stat) {
#endif
		case SIDL:
		case SRUN:
#ifdef SONPROC
		case SONPROC: /* NetBSD */
#endif
			proc_state_ptr->state = SG_PROCESS_STATE_RUNNING;
			break;
		case SSLEEP:
#ifdef SWAIT
		case SWAIT: /* FreeBSD 5 */
#endif
#ifdef SLOCK
		case SLOCK: /* FreeBSD 5 */
#endif
			proc_state_ptr->state = SG_PROCESS_STATE_SLEEPING;
			break;
		case SSTOP:
			proc_state_ptr->state = SG_PROCESS_STATE_STOPPED;
			break;
		case SZOMB:
#ifdef SDEAD
		case SDEAD: /* OpenBSD & NetBSD */
#endif
			proc_state_ptr->state = SG_PROCESS_STATE_ZOMBIE;
			break;
		default:
			proc_state_ptr->state = SG_PROCESS_STATE_UNKNOWN;
			break;
		}
#endif
		proc_state_size++;
	}

	free(kp_stats);
#endif

#ifdef HPUX
	if ((pagesize = sysconf(_SC_PAGESIZE)) == -1) {
		sg_set_error_with_errno(SG_ERROR_SYSCONF, "_SC_PAGESIZE");
		return NULL;
	}

	while (1) {
		num = pstat_getproc(pstat_procinfo, sizeof pstat_procinfo[0],
		                    PROCESS_BATCH, procidx);
		if (num == -1) {
			sg_set_error_with_errno(SG_ERROR_PSTAT,
			                        "pstat_getproc");
			return NULL;
		} else if (num == 0) {
			break;
		}

		for (i = 0; i < num; i++) {
			struct pst_status *pi = &pstat_procinfo[i];

			if (VECTOR_RESIZE(proc_state, proc_state_size + 1) < 0) {
				return NULL;
			}
			proc_state_ptr = proc_state+proc_state_size;
	
			proc_state_ptr->pid = pi->pst_pid;
			proc_state_ptr->parent = pi->pst_ppid;
			proc_state_ptr->pgid = pi->pst_pgrp;
			proc_state_ptr->uid = pi->pst_uid;
			proc_state_ptr->euid = pi->pst_euid;
			proc_state_ptr->gid = pi->pst_gid;
			proc_state_ptr->egid = pi->pst_egid;
			proc_state_ptr->proc_size = (pi->pst_dsize + pi->pst_tsize + pi->pst_ssize) * pagesize;
			proc_state_ptr->proc_resident = pi->pst_rssize * pagesize;
			proc_state_ptr->time_spent = pi->pst_time;
			proc_state_ptr->cpu_percent = (pi->pst_pctcpu * 100.0) / 0x8000;
			proc_state_ptr->nice = pi->pst_nice;
	
			if (sg_update_string(&proc_state_ptr->process_name,
					     pi->pst_ucomm) < 0) {
				return NULL;
			}
			if (sg_update_string(&proc_state_ptr->proctitle,
					     pi->pst_cmd) < 0) {
				return NULL;
			}
	
			switch (pi->pst_stat) {
			case PS_SLEEP:
				proc_state_ptr->state = SG_PROCESS_STATE_SLEEPING;
				break;
			case PS_RUN:
				proc_state_ptr->state = SG_PROCESS_STATE_RUNNING;
				break;
			case PS_STOP:
				proc_state_ptr->state = SG_PROCESS_STATE_STOPPED;
				break;
			case PS_ZOMBIE:
				proc_state_ptr->state = SG_PROCESS_STATE_ZOMBIE;
				break;
			case PS_IDLE:
			case PS_OTHER:
				proc_state_ptr->state = SG_PROCESS_STATE_UNKNOWN;
				break;
			}
	
			proc_state_size++;
		}
		procidx = pstat_procinfo[num - 1].pst_idx + 1;
	}
#endif

#ifdef AIX
#define	TVALU_TO_SEC(x)	((x).tv_sec + ((double)((x).tv_usec) / 1000000.0))
#define	TVALN_TO_SEC(x)	((x).tv_sec + ((double)((x).tv_usec) / 1000000000.0))
	ncpus = sysconf(_SC_NPROCESSORS_ONLN);
	if( -1 == ncpus ) {
		ncpus = 1; /* sysconf error - assume 1 */
	}

	if ((pagesize = sysconf(_SC_PAGESIZE)) == -1) {
		sg_set_error_with_errno(SG_ERROR_SYSCONF, "_SC_PAGESIZE");
		return NULL;
	}

	proc_idx = 0;
	procs = /* (struct procentry64 *) */ malloc(sizeof(*procs) * PROCS_TO_FETCH);
	if(NULL == procs) {
		sg_set_error_with_errno(SG_ERROR_MALLOC, "sg_get_process_stats");
		return 0;
	}

	gettimeofday(&now_tval, 0);
	now_time = TVALU_TO_SEC(now_tval);

	/* keep on grabbing chunks of processes until getprocs returns a smaller
	   block than we asked for */
	do {
		int i;
		fetched = getprocs64(procs, sizeof(*procs), NULL, 0, &index, PROCS_TO_FETCH);
		if (VECTOR_RESIZE(proc_state, proc_state_size + fetched) < 0) {
			sg_set_error_with_errno(SG_ERROR_MALLOC, "sg_get_process_stats");
			free(procs);
			return NULL;
		}
		for( i = 0; i < fetched; ++i ) {
			struct procentry64 *pi = procs+i;
			int zombie = 0;

			proc_state_ptr = proc_state + proc_idx;

			zombie = 0;

			/* set a descriptive name for the process state */
			switch( pi->pi_state ) {
			case SSLEEP:
				proc_state_ptr->state = SG_PROCESS_STATE_SLEEPING;
				break;
			case SRUN:
				proc_state_ptr->state = SG_PROCESS_STATE_RUNNING;
				break;
			case SZOMB:
				proc_state_ptr->state = SG_PROCESS_STATE_ZOMBIE;
				zombie = 1;
				break;
			case SSTOP:
				proc_state_ptr->state = SG_PROCESS_STATE_STOPPED;
				break;
			case SACTIVE:
				proc_state_ptr->state = SG_PROCESS_STATE_RUNNING;
				break;
			case SIDL:
			default:
				proc_state_ptr->state = SG_PROCESS_STATE_UNKNOWN;
				break;
			}

			if( zombie ) {
				utime = pi->pi_utime;
				stime = pi->pi_stime;
			} else {
				utime = TVALN_TO_SEC(pi->pi_ru.ru_utime) + TVALN_TO_SEC(pi->pi_cru.ru_utime);
				stime = TVALN_TO_SEC(pi->pi_ru.ru_stime) + TVALN_TO_SEC(pi->pi_cru.ru_stime);
			}

			proc_state_ptr->pid = pi->pi_pid;
			proc_state_ptr->parent = pi->pi_ppid;
			proc_state_ptr->pgid = pi->pi_pgrp;
			proc_state_ptr->uid = pi->pi_cred.crx_ruid;
			proc_state_ptr->euid = pi->pi_cred.crx_uid;
			proc_state_ptr->gid = pi->pi_cred.crx_rgid;
			proc_state_ptr->egid = pi->pi_cred.crx_gid;
			proc_state_ptr->proc_size = pi->pi_size;
			proc_state_ptr->proc_resident = pi->pi_drss + pi->pi_trss; /* XXX might be wrong, see P::PT */
			proc_state_ptr->time_spent = utime + stime;
			proc_state_ptr->cpu_percent = (((double)(utime + stime) * 100) / ( now_time - pi->pi_start )) / ncpus;
			proc_state_ptr->nice = pi->pi_nice;

			/* determine comm & cmndline */
			if( (pi->pi_flags & SKPROC) == SKPROC ) {
				if( pi->pi_pid == 0 ) {
					snprintf(comm, ARG_MAX, "kproc (swapper)");
					snprintf(cmndline, ARG_MAX, "kproc (swapper)");
				} else {
					snprintf(comm, ARG_MAX, "kproc (%s)", pi->pi_comm);
					snprintf(cmndline, ARG_MAX, "kproc (%s)", pi->pi_comm);
				}
			} else {
				snprintf(comm, ARG_MAX, "%s", pi->pi_comm);
				curproc_for_getargs.pi_pid = pi->pi_pid;
				if( getargs(&curproc_for_getargs, sizeof(curproc_for_getargs), cmndline, ARG_MAX) < 0 ) {
					snprintf(cmndline, ARG_MAX, "%s", pi->pi_comm);
				} else {
					int done = 0;
					/* replace NUL characters in command line with spaces */
					char *c = cmndline;
					while( ! done ) {
						if( *c == '\0' ) {
							if( *(c+1) == '\0' ) {
								done = 1;
							} else {
								*c++ = ' ';
							}
						} else {
							++c;
						}
					}
				}
			}


			if (sg_update_string(&proc_state_ptr->process_name, comm) < 0) {
				free(procs);
				return NULL;
			}
			if (sg_update_string(&proc_state_ptr->proctitle, cmndline) < 0) {
				free(procs);
				return NULL;
			}

			proc_idx++;
		}
	} while( fetched >= PROCS_TO_FETCH );

	proc_state_size = proc_idx;

	free(procs);
#endif


#ifdef CYGWIN
	sg_set_error(SG_ERROR_UNSUPPORTED, "Cygwin");
	return NULL;
#endif
#ifdef WIN32
	/* FIXME The data needed for this is probably do able with the 
	 * "performance registry". Although using this appears to be a black
	 * art and closely guarded secret.
	 * This is not directly used in ihost, so not considered a priority */
	sg_set_error(SG_ERROR_UNSUPPORTED, "Win32");
	return NULL;
#endif

	*entries = proc_state_size;
	return proc_state;
}

sg_process_count *sg_get_process_count() {
	static sg_process_count process_stat;
#ifndef WIN32
	sg_process_stats *ps;
	int ps_size, x;
#else
	DWORD aProcesses[1024];
	DWORD cbNeeded;
#endif

	process_stat.sleeping = 0;
	process_stat.running = 0;
	process_stat.zombie = 0;
	process_stat.stopped = 0;
	process_stat.total = 0;

#ifndef WIN32
	ps = sg_get_process_stats(&ps_size);
	if (ps == NULL) {
		return NULL;
	}

	for(x = 0; x < ps_size; x++) {
		switch (ps->state) {
		case SG_PROCESS_STATE_RUNNING:
			process_stat.running++;
			break;
		case SG_PROCESS_STATE_SLEEPING:
			process_stat.sleeping++;
			break;
		case SG_PROCESS_STATE_STOPPED:
			process_stat.stopped++;
			break;
		case SG_PROCESS_STATE_ZOMBIE:
			process_stat.zombie++;
			break;
		default:
			/* currently no mapping for SG_PROCESS_STATE_UNKNOWN in
			 * sg_process_count */
			break;
		}
		ps++;
	}

	process_stat.total = ps_size;
#else
	if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded))
		return NULL;
	process_stat.total = cbNeeded / sizeof(DWORD);
#endif

	return &process_stat;
}

int sg_process_compare_name(const void *va, const void *vb) {
	const sg_process_stats *a = (sg_process_stats *)va;
	const sg_process_stats *b = (sg_process_stats *)vb;

	return strcmp(a->process_name, b->process_name);
}

int sg_process_compare_pid(const void *va, const void *vb) {
	const sg_process_stats *a = (sg_process_stats *)va;
	const sg_process_stats *b = (sg_process_stats *)vb;

	if (a->pid < b->pid) {
		return -1;
	} else if (a->pid == b->pid) {
		return 0;
	} else {
		return 1;
	}
}

int sg_process_compare_uid(const void *va, const void *vb) {
	const sg_process_stats *a = (sg_process_stats *)va;
	const sg_process_stats *b = (sg_process_stats *)vb;

	if (a->uid < b->uid) {
		return -1;
	} else if (a->uid == b->uid) {
		return 0;
	} else {
		return 1;
	}
}

int sg_process_compare_gid(const void *va, const void *vb) {
	const sg_process_stats *a = (sg_process_stats *)va;
	const sg_process_stats *b = (sg_process_stats *)vb;

	if (a->gid < b->gid) {
		return -1;
	} else if (a->gid == b->gid) {
		return 0;
	} else {
		return 1;
	}
}

int sg_process_compare_size(const void *va, const void *vb) {
	const sg_process_stats *a = (sg_process_stats *)va;
	const sg_process_stats *b = (sg_process_stats *)vb;

	if (a->proc_size < b->proc_size) {
		return -1;
	} else if (a->proc_size == b->proc_size) {
		return 0;
	} else {
		return 1;
	}
}

int sg_process_compare_res(const void *va, const void *vb) {
	const sg_process_stats *a = (sg_process_stats *)va;
	const sg_process_stats *b = (sg_process_stats *)vb;

	if (a->proc_resident < b->proc_resident) {
		return -1;
	} else if (a->proc_resident == b->proc_resident) {
		return 0;
	} else {
		return 1;
	}
}

int sg_process_compare_cpu(const void *va, const void *vb) {
	const sg_process_stats *a = (sg_process_stats *)va;
	const sg_process_stats *b = (sg_process_stats *)vb;

	if (a->cpu_percent < b->cpu_percent) {
		return -1;
	} else if (a->cpu_percent == b->cpu_percent) {
		return 0;
	} else {
		return 1;
	}
}

int sg_process_compare_time(const void *va, const void *vb) {
	const sg_process_stats *a = (sg_process_stats *)va;
	const sg_process_stats *b = (sg_process_stats *)vb;

	if (a->time_spent < b->time_spent) {
		return -1;
	} else if (a->time_spent == b->time_spent) {
		return 0;
	} else {
		return 1;
	}
}
Exemplo n.º 6
0
sg_page_stats *sg_get_page_stats(){
#ifdef SOLARIS
	kstat_ctl_t *kc;
	kstat_t *ksp;
	cpu_stat_t cs;
#endif
#if defined(LINUX) || defined(CYGWIN)
	FILE *f;
	char *line_ptr;
#endif
#if defined(FREEBSD) || defined(DFBSD)
	size_t size;
#endif
#if defined(NETBSD) || defined(OPENBSD)
	struct uvmexp *uvm;
#endif
#ifdef AIX
       perfstat_memory_total_t mem;
#endif
#ifdef HPUX
       struct pst_vminfo vminfo;
#endif

	page_stats.systime = time(NULL);
	page_stats.pages_pagein=0;
	page_stats.pages_pageout=0;

#ifdef SOLARIS
	if ((kc = kstat_open()) == NULL) {
		sg_set_error(SG_ERROR_KSTAT_OPEN, NULL);
		return NULL;
	}
	for (ksp = kc->kc_chain; ksp!=NULL; ksp = ksp->ks_next) {
		if ((strcmp(ksp->ks_module, "cpu_stat")) != 0) continue;
		if (kstat_read(kc, ksp, &cs) == -1) {
			continue;
		}

		page_stats.pages_pagein+=(long long)cs.cpu_vminfo.pgpgin;
		page_stats.pages_pageout+=(long long)cs.cpu_vminfo.pgpgout;
	}

	kstat_close(kc);
#endif
#if defined(LINUX) || defined(CYGWIN)
	if ((f = fopen("/proc/vmstat", "r")) != NULL) {
		while ((line_ptr = sg_f_read_line(f, "")) != NULL) {
			long long value;

			if (sscanf(line_ptr, "%*s %lld", &value) != 1) {
				continue;
			}

			if (strncmp(line_ptr, "pgpgin ", 7) == 0) {
				page_stats.pages_pagein = value;
			} else if (strncmp(line_ptr, "pgpgout ", 8) == 0) {
				page_stats.pages_pageout = value;
			}
		}

		fclose(f);
	} else if ((f = fopen("/proc/stat", "r")) != NULL) {
		if ((line_ptr = sg_f_read_line(f, "page")) == NULL) {
			sg_set_error(SG_ERROR_PARSE, "page");
			fclose(f);
			return NULL;
		}

		if (sscanf(line_ptr, "page %lld %lld", &page_stats.pages_pagein, &page_stats.pages_pageout) != 2) {
			sg_set_error(SG_ERROR_PARSE, "page");
			fclose(f);
			return NULL;
		}

		fclose(f);
	} else {
		sg_set_error_with_errno(SG_ERROR_OPEN, "/proc/stat");
		return NULL;
	}
#endif
#if defined(FREEBSD) || defined(DFBSD)
	size = sizeof page_stats.pages_pagein;
	if (sysctlbyname("vm.stats.vm.v_swappgsin", &page_stats.pages_pagein, &size, NULL, 0) < 0){
		sg_set_error_with_errno(SG_ERROR_SYSCTLBYNAME,
		                        "vm.stats.vm.v_swappgsin");
		return NULL;
	}
	size = sizeof page_stats.pages_pageout;
	if (sysctlbyname("vm.stats.vm.v_swappgsout", &page_stats.pages_pageout, &size, NULL, 0) < 0){
		sg_set_error_with_errno(SG_ERROR_SYSCTLBYNAME,
		                        "vm.stats.vm.v_swappgsout");
		return NULL;
	}
#endif
#if defined(NETBSD) || defined(OPENBSD)
	if ((uvm = sg_get_uvmexp()) == NULL) {
		return NULL;
	}

	page_stats.pages_pagein = uvm->pgswapin;
	page_stats.pages_pageout = uvm->pgswapout;
#endif
#ifdef AIX
	/* return code is number of structures returned */
	if(perfstat_memory_total(NULL, &mem, sizeof(perfstat_memory_total_t), 1) != 1) {
		sg_set_error_with_errno(SG_ERROR_SYSCTLBYNAME, "perfstat_memory_total");
		return NULL;
	}

	page_stats.pages_pagein  = mem.pgins;
	page_stats.pages_pageout = mem.pgouts;
#endif
#ifdef HPUX
	if( pstat_getvminfo( &vminfo, sizeof(vminfo), 1, 0 ) == -1 ) {
		sg_set_error_with_errno(SG_ERROR_SYSCTLBYNAME, "pstat_getswap");
		return NULL;
	};

	page_stats.pages_pagein  = vminfo.psv_spgin;
	page_stats.pages_pageout = vminfo.psv_spgout;
#endif
#ifdef WIN32
	sg_set_error(SG_ERROR_UNSUPPORTED, "Win32");
	return NULL;
#endif

	return &page_stats;
}
Exemplo n.º 7
0
static sg_error
sg_get_page_stats_int(sg_page_stats *page_stats_buf){
#ifdef SOLARIS
	kstat_ctl_t *kc;
	kstat_t *ksp;
	cpu_stat_t cs;
#elif defined(LINUX) || defined(CYGWIN)
	FILE *f;
#define LINE_BUF_SIZE 256
	char line_buf[LINE_BUF_SIZE];
#elif defined(HAVE_HOST_STATISTICS) || defined(HAVE_HOST_STATISTICS64)
# if defined(HAVE_HOST_STATISTICS64)
	struct vm_statistics64 vm_stats;
# else
	struct vm_statistics vm_stats;
# endif
	mach_msg_type_number_t count;
	kern_return_t rc;
#elif defined(HAVE_STRUCT_UVMEXP_SYSCTL) && defined(VM_UVMEXP2)
	int mib[2];
	struct uvmexp_sysctl uvm;
	size_t size = sizeof(uvm);
#elif defined(HAVE_STRUCT_UVMEXP) && defined(VM_UVMEXP)
	int mib[2];
	struct uvmexp uvm;
	size_t size = sizeof(uvm);
#elif defined(FREEBSD) || defined(DFBSD)
	size_t size;
#elif defined(NETBSD) || defined(OPENBSD)
	int mib[2];
	struct uvmexp uvm;
	size_t size = sizeof(uvm);
#elif defined(AIX)
	perfstat_memory_total_t mem;
#elif defined(HPUX)
	struct pst_vminfo vminfo;
#endif

	page_stats_buf->systime = time(NULL);
	page_stats_buf->pages_pagein=0;
	page_stats_buf->pages_pageout=0;

#ifdef SOLARIS
	if ((kc = kstat_open()) == NULL) {
		RETURN_WITH_SET_ERROR("page", SG_ERROR_KSTAT_OPEN, NULL);
	}

	for (ksp = kc->kc_chain; ksp!=NULL; ksp = ksp->ks_next) {
		if ((strcmp(ksp->ks_module, "cpu_stat")) != 0)
			continue;
		if (kstat_read(kc, ksp, &cs) == -1)
			continue;

		page_stats_buf->pages_pagein  += (long long)cs.cpu_vminfo.pgpgin;
		page_stats_buf->pages_pageout += (long long)cs.cpu_vminfo.pgpgout;
	}

	kstat_close(kc);
#elif defined(LINUX) || defined(CYGWIN)
	if ((f = fopen("/proc/vmstat", "r")) != NULL) {
		unsigned matches = 0;

		while( (matches < 2) && (fgets(line_buf, sizeof(line_buf), f) != NULL) ) {
			unsigned long long value;

			if (sscanf(line_buf, "%*s %llu", &value) != 1)
				continue;

			if (strncmp(line_buf, "pgpgin ", 7) == 0) {
				page_stats_buf->pages_pagein = value;
				++matches;
			}
			else if (strncmp(line_buf, "pgpgout ", 8) == 0) {
				page_stats_buf->pages_pageout = value;
				++matches;
			}
		}

		fclose(f);

		if( matches < 2 ) {
			RETURN_WITH_SET_ERROR( "page", SG_ERROR_PARSE, "/proc/vmstat" );
		}
	}
	else if ((f = fopen("/proc/stat", "r")) != NULL) {
		if (sg_f_read_line(f, line_buf, sizeof(line_buf), "page") == NULL) {
			fclose(f);
			RETURN_FROM_PREVIOUS_ERROR( "page", sg_get_error() );
		}

		fclose(f);

		if( sscanf( line_buf, "page %llu %llu", &page_stats_buf->pages_pagein, &page_stats_buf->pages_pageout ) != 2 ) {
			RETURN_WITH_SET_ERROR("page", SG_ERROR_PARSE, "page");
		}
	}
	else {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("page", SG_ERROR_OPEN, "/proc/stat");
	}
#elif defined(HAVE_HOST_STATISTICS) || defined(HAVE_HOST_STATISTICS64)
	self_host_port = mach_host_self();
# if defined(HAVE_HOST_STATISTICS64)
	count = HOST_VM_INFO64_COUNT;
	rc = host_statistics64(self_host_port, HOST_VM_INFO64, (host_info64_t)(&vm_stats), &count);
# else
	count = HOST_VM_INFO_COUNT;
	rc = host_statistics(self_host_port, HOST_VM_INFO, (host_info_t)(&vm_stats), &count);
# endif
	if( rc != KERN_SUCCESS ) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO_CODE( "mem", SG_ERROR_MACHCALL, rc, "host_statistics" );
	}

	page_stats_buf->pages_pagein = vm_stats.pageins;
	page_stats_buf->pages_pageout = vm_stats.pageouts;
#elif defined(HAVE_STRUCT_UVMEXP_SYSCTL) && defined(VM_UVMEXP2)
	mib[0] = CTL_VM;
	mib[1] = VM_UVMEXP2;

	if (sysctl(mib, 2, &uvm, &size, NULL, 0) < 0) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_SYSCTL, "CTL_VM.VM_UVMEXP2");
	}

	page_stats_buf->pages_pagein = uvm.pgswapin;
	page_stats_buf->pages_pageout = uvm.pgswapout;
#elif defined(HAVE_STRUCT_UVMEXP) && defined(VM_UVMEXP)
	mib[0] = CTL_VM;
	mib[1] = VM_UVMEXP;

	if (sysctl(mib, 2, &uvm, &size, NULL, 0) < 0) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_SYSCTL, "CTL_VM.VM_UVMEXP");
	}

	page_stats_buf->pages_pagein = uvm.pgswapin;
	page_stats_buf->pages_pageout = uvm.pgswapout;
#elif defined(FREEBSD) || defined(DFBSD)
	size = sizeof(page_stats_buf->pages_pagein);
	if (sysctlbyname("vm.stats.vm.v_swappgsin", &page_stats_buf->pages_pagein, &size, NULL, 0) < 0) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("page", SG_ERROR_SYSCTLBYNAME, "vm.stats.vm.v_swappgsin");
	}

	size = sizeof(page_stats_buf->pages_pageout);
	if (sysctlbyname("vm.stats.vm.v_swappgsout", &page_stats_buf->pages_pageout, &size, NULL, 0) < 0) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("page", SG_ERROR_SYSCTLBYNAME, "vm.stats.vm.v_swappgsout");
	}
#elif defined(AIX)
	/* return code is number of structures returned */
	if(perfstat_memory_total(NULL, &mem, sizeof(perfstat_memory_total_t), 1) != 1) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("page", SG_ERROR_SYSCTLBYNAME, "perfstat_memory_total");
	}

	page_stats_buf->pages_pagein  = mem.pgins;
	page_stats_buf->pages_pageout = mem.pgouts;
#elif defined(HPUX)
	if( pstat_getvminfo( &vminfo, sizeof(vminfo), 1, 0 ) == -1 ) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("page", SG_ERROR_SYSCTLBYNAME, "pstat_getswap");
	}

	page_stats_buf->pages_pagein  = vminfo.psv_spgin;
	page_stats_buf->pages_pageout = vminfo.psv_spgout;
#else
	RETURN_WITH_SET_ERROR("page", SG_ERROR_UNSUPPORTED, OS_TYPE);
#endif

	return SG_ERROR_NONE;
}
Exemplo n.º 8
0
sg_mem_stats *sg_get_mem_stats(){

	static sg_mem_stats mem_stat;

#ifdef SOLARIS
	kstat_ctl_t *kc;
	kstat_t *ksp;
	kstat_named_t *kn;
	long totalmem;
	int pagesize;
#endif
#if defined(LINUX) || defined(CYGWIN)
	char *line_ptr;
	unsigned long long value;
	FILE *f;
#endif
#if defined(FREEBSD) || defined(DFBSD)
	int mib[2];
	u_long physmem;
	size_t size;
	u_int free_count;
	u_int cache_count;
	u_int inactive_count;
	int pagesize;
#endif
#if defined(NETBSD) || defined(OPENBSD)
	struct uvmexp *uvm;
#endif

#ifdef SOLARIS
	if((pagesize=sysconf(_SC_PAGESIZE)) == -1){
		sg_set_error_with_errno(SG_ERROR_SYSCONF, "_SC_PAGESIZE");
		return NULL;	
	}

	if((totalmem=sysconf(_SC_PHYS_PAGES)) == -1){
		sg_set_error_with_errno(SG_ERROR_SYSCONF, "_SC_PHYS_PAGES");
		return NULL;
	}

	if ((kc = kstat_open()) == NULL) {
		sg_set_error(SG_ERROR_KSTAT_OPEN, NULL);
		return NULL;
	}
	if((ksp=kstat_lookup(kc, "unix", 0, "system_pages")) == NULL){
		sg_set_error(SG_ERROR_KSTAT_LOOKUP, "unix,0,system_pages");
		return NULL;
	}
	if (kstat_read(kc, ksp, 0) == -1) {
		sg_set_error(SG_ERROR_KSTAT_READ, NULL);
		return NULL;
	}
	if((kn=kstat_data_lookup(ksp, "freemem")) == NULL){
		sg_set_error(SG_ERROR_KSTAT_DATA_LOOKUP, "freemem");
		return NULL;
	}
	kstat_close(kc);

	mem_stat.total = (long long)totalmem * (long long)pagesize;
	mem_stat.free = ((long long)kn->value.ul) * (long long)pagesize;
	mem_stat.used = mem_stat.total - mem_stat.free;
#endif

#if defined(LINUX) || defined(CYGWIN)
	if ((f = fopen("/proc/meminfo", "r")) == NULL) {
		sg_set_error_with_errno(SG_ERROR_OPEN, "/proc/meminfo");
		return NULL;
	}

	while ((line_ptr = sg_f_read_line(f, "")) != NULL) {
		if (sscanf(line_ptr, "%*s %llu kB", &value) != 1) {
			continue;
		}
		value *= 1024;

		if (strncmp(line_ptr, "MemTotal:", 9) == 0) {
			mem_stat.total = value;
		} else if (strncmp(line_ptr, "MemFree:", 8) == 0) {
			mem_stat.free = value;
		} else if (strncmp(line_ptr, "Cached:", 7) == 0) {
			mem_stat.cache = value;
		}
	}

	fclose(f);
	mem_stat.used = mem_stat.total - mem_stat.free;
#endif

#if defined(FREEBSD) || defined(DFBSD)
	/* Returns bytes */
	mib[0] = CTL_HW;
	mib[1] = HW_PHYSMEM;
	size = sizeof physmem;
	if (sysctl(mib, 2, &physmem, &size, NULL, 0) < 0) {
		sg_set_error_with_errno(SG_ERROR_SYSCTL, "CTL_HW.HW_PHYSMEM");
		return NULL;
	}
	mem_stat.total = physmem;

	/*returns pages*/
	size = sizeof free_count;
	if (sysctlbyname("vm.stats.vm.v_free_count", &free_count, &size, NULL, 0) < 0){
		sg_set_error_with_errno(SG_ERROR_SYSCTLBYNAME,
		                        "vm.stats.vm.v_free_count");
		return NULL;
	}

	size = sizeof inactive_count;
	if (sysctlbyname("vm.stats.vm.v_inactive_count", &inactive_count , &size, NULL, 0) < 0){
		sg_set_error_with_errno(SG_ERROR_SYSCTLBYNAME,
		                        "vm.stats.vm.v_inactive_count");
		return NULL;
	}

	size = sizeof cache_count;
	if (sysctlbyname("vm.stats.vm.v_cache_count", &cache_count, &size, NULL, 0) < 0){
		sg_set_error_with_errno(SG_ERROR_SYSCTLBYNAME,
		                        "vm.stats.vm.v_cache_count");
		return NULL;
	}

	/* Because all the vm.stats returns pages, I need to get the page size.
	 * After that I then need to multiple the anything that used vm.stats to
	 * get the system statistics by pagesize 
	 */
	pagesize = getpagesize();
	mem_stat.cache=cache_count*pagesize;

	/* Of couse nothing is ever that simple :) And I have inactive pages to
	 * deal with too. So I'm going to add them to free memory :)
	 */
	mem_stat.free=(free_count*pagesize)+(inactive_count*pagesize);
	mem_stat.used=physmem-mem_stat.free;
#endif

#if defined(NETBSD) || defined(OPENBSD)
	if ((uvm = sg_get_uvmexp()) == NULL) {
		return NULL;
	}

	mem_stat.total = uvm->pagesize * uvm->npages;
#ifdef NETBSD
	mem_stat.cache = uvm->pagesize * (uvm->filepages + uvm->execpages);
#else
	/* Can't find cache memory on OpenBSD */
	mem_stat.cache = 0;
#endif
	mem_stat.free = uvm->pagesize * (uvm->free + uvm->inactive);
	mem_stat.used = mem_stat.total - mem_stat.free;
#endif

	return &mem_stat;
}
Exemplo n.º 9
0
sg_process_stats *sg_get_process_stats(int *entries){
	VECTOR_DECLARE_STATIC(proc_state, sg_process_stats, 64,
			      proc_state_init, proc_state_destroy);
	int proc_state_size = 0;
	sg_process_stats *proc_state_ptr;
#ifdef ALLBSD
	int mib[4];
	size_t size;
	struct kinfo_proc *kp_stats;
	int procs, i;
	char *proctitle;
#if (defined(FREEBSD) && !defined(FREEBSD5)) || defined(DFBSD)
	kvm_t *kvmd;
	char **args, **argsp;
	int argslen = 0;
#else
	long buflen;
	char *p, *proctitletmp;
#endif
#ifdef NETBSD2
	int lwps;
	struct kinfo_lwp *kl_stats;
#endif
#endif
#if defined(SOLARIS) || defined(LINUX)
	DIR *proc_dir;
	struct dirent *dir_entry;
	char filename[MAX_FILE_LENGTH];
	FILE *f;
#ifdef SOLARIS
	psinfo_t process_info;
#endif
#ifdef LINUX
	char s;
	/* If someone has a executable of 4k filename length, they deserve to get it truncated :) */
	char ps_name[4096];
	char *ptr;
	VECTOR_DECLARE_STATIC(psargs, char, 128, NULL, NULL);
	unsigned long stime, utime, starttime;
	int x;
	int fn;
	int len;
	int rc;
	time_t uptime;
#endif

#ifdef LINUX
	if ((f=fopen("/proc/uptime", "r")) == NULL) {
		sg_set_error_with_errno(SG_ERROR_OPEN, "/proc/uptime");
		return NULL;
	}
	if((fscanf(f,"%lu %*d",&uptime)) != 1){
		sg_set_error(SG_ERROR_PARSE, NULL);
		return NULL;
	}
	fclose(f);
#endif

	if((proc_dir=opendir(PROC_LOCATION))==NULL){
		sg_set_error_with_errno(SG_ERROR_OPENDIR, PROC_LOCATION);
		return NULL;
	}

	while((dir_entry=readdir(proc_dir))!=NULL){
		if(atoi(dir_entry->d_name) == 0) continue;

#ifdef SOLARIS
		snprintf(filename, MAX_FILE_LENGTH, "/proc/%s/psinfo", dir_entry->d_name);
#endif
#ifdef LINUX
		snprintf(filename, MAX_FILE_LENGTH, "/proc/%s/stat", dir_entry->d_name);
#endif
		if((f=fopen(filename, "r"))==NULL){
			/* Open failed.. Process since vanished, or the path was too long.
			 * Ah well, move onwards to the next one */
			continue;
		}
#ifdef SOLARIS
		fread(&process_info, sizeof(psinfo_t), 1, f);
		fclose(f);
#endif

		if (VECTOR_RESIZE(proc_state, proc_state_size + 1) < 0) {
			return NULL;
		}
		proc_state_ptr = proc_state+proc_state_size;

#ifdef SOLARIS		
		proc_state_ptr->pid = process_info.pr_pid;
		proc_state_ptr->parent = process_info.pr_ppid;
		proc_state_ptr->pgid = process_info.pr_pgid;
		proc_state_ptr->uid = process_info.pr_uid;
		proc_state_ptr->euid = process_info.pr_euid;
		proc_state_ptr->gid = process_info.pr_gid;
		proc_state_ptr->egid = process_info.pr_egid;
		proc_state_ptr->proc_size = (process_info.pr_size) * 1024;
		proc_state_ptr->proc_resident = (process_info.pr_rssize) * 1024;
		proc_state_ptr->time_spent = process_info.pr_time.tv_sec;
		proc_state_ptr->cpu_percent = (process_info.pr_pctcpu * 100.0) / 0x8000;
		proc_state_ptr->nice = (int)process_info.pr_lwp.pr_nice - 20;
		if (sg_update_string(&proc_state_ptr->process_name,
				     process_info.pr_fname) < 0) {
			return NULL;
		}
		if (sg_update_string(&proc_state_ptr->proctitle,
				     process_info.pr_psargs) < 0) {
			return NULL;
		}

		if(process_info.pr_lwp.pr_state==1) proc_state_ptr->state = SG_PROCESS_STATE_SLEEPING;
		if(process_info.pr_lwp.pr_state==2) proc_state_ptr->state = SG_PROCESS_STATE_RUNNING; 
		if(process_info.pr_lwp.pr_state==3) proc_state_ptr->state = SG_PROCESS_STATE_ZOMBIE; 
		if(process_info.pr_lwp.pr_state==4) proc_state_ptr->state = SG_PROCESS_STATE_STOPPED; 
		if(process_info.pr_lwp.pr_state==6) proc_state_ptr->state = SG_PROCESS_STATE_RUNNING; 
#endif
#ifdef LINUX
		x = fscanf(f, "%d %4096s %c %d %d %*d %*d %*d %*u %*u %*u %*u %*u %lu %lu %*d %*d %*d %d %*d %*d %lu %llu %llu %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*d %*d\n", &(proc_state_ptr->pid), ps_name, &s, &(proc_state_ptr->parent), &(proc_state_ptr->pgid), &utime, &stime, &(proc_state_ptr->nice), &starttime, &(proc_state_ptr->proc_size), &(proc_state_ptr->proc_resident));
		/* +3 becuase man page says "Resident  Set Size: number of pages the process has in real memory, minus 3 for administrative purposes." */
		proc_state_ptr->proc_resident = (proc_state_ptr->proc_resident + 3) * getpagesize();
		if(s == 'S') proc_state_ptr->state = SG_PROCESS_STATE_SLEEPING;
		if(s == 'R') proc_state_ptr->state = SG_PROCESS_STATE_RUNNING;
		if(s == 'Z') proc_state_ptr->state = SG_PROCESS_STATE_ZOMBIE;
		if(s == 'T') proc_state_ptr->state = SG_PROCESS_STATE_STOPPED;
		if(s == 'D') proc_state_ptr->state = SG_PROCESS_STATE_STOPPED;
	
		/* pa_name[0] should = '(' */
		ptr = strchr(&ps_name[1], ')');	
		if(ptr !=NULL) *ptr='\0';

		if (sg_update_string(&proc_state_ptr->process_name,
				     &ps_name[1]) < 0) {
			return NULL;
		}

		/* cpu */
		proc_state_ptr->cpu_percent = (100.0 * (utime + stime)) / ((uptime * 100.0) - starttime);

		fclose(f);

		/* uid / gid */
		snprintf(filename, MAX_FILE_LENGTH, "/proc/%s/status", dir_entry->d_name);
		if ((f=fopen(filename, "r")) == NULL) {
			/* Open failed.. Process since vanished, or the path was too long.
			 * Ah well, move onwards to the next one */
			continue;
		}

		if((ptr=sg_f_read_line(f, "Uid:"))==NULL){
			fclose(f);
			continue;
		}
		sscanf(ptr, "Uid:\t%d\t%d\t%*d\t%*d\n", &(proc_state_ptr->uid), &(proc_state_ptr->euid));

		if((ptr=sg_f_read_line(f, "Gid:"))==NULL){
			fclose(f);
			continue;
		}
		sscanf(ptr, "Gid:\t%d\t%d\t%*d\t%*d\n", &(proc_state_ptr->gid), &(proc_state_ptr->egid));

		fclose(f);

		/* proctitle */	
		snprintf(filename, MAX_FILE_LENGTH, "/proc/%s/cmdline", dir_entry->d_name);

		if((fn=open(filename, O_RDONLY)) == -1){
			/* Open failed.. Process since vanished, or the path was too long.
			 * Ah well, move onwards to the next one */
			continue;
		}

#define READ_BLOCK_SIZE 128
		len = 0;
		do {
			if (VECTOR_RESIZE(psargs, len + READ_BLOCK_SIZE) < 0) {
				return NULL;
			}
			rc = read(fn, psargs + len, READ_BLOCK_SIZE);
			if (rc > 0) {
				len += rc;
			}
		} while (rc == READ_BLOCK_SIZE);
		close(fn);

		if (rc == -1) {
			/* Read failed; move on. */
			continue;
		}

		/* Turn \0s into spaces within the command line. */
		ptr = psargs;
		for(x = 0; x < len; x++) {
			if (*ptr == '\0') *ptr = ' ';
			ptr++;
		}

		if (len == 0) {
			/* We want psargs to be NULL. */
			if (VECTOR_RESIZE(psargs, 0) < 0) {
				return NULL;
			}
		} else {
			/* Not empty, so append a \0. */
			if (VECTOR_RESIZE(psargs, len + 1) < 0) {
				return NULL;
			}
			psargs[len] = '\0';
		}

		if (sg_update_string(&proc_state_ptr->proctitle, psargs) < 0) {
			return NULL;
		}
#endif

		proc_state_size++;
	}
	closedir(proc_dir);
#endif

#ifdef ALLBSD
	mib[0] = CTL_KERN;
	mib[1] = KERN_PROC;
	mib[2] = KERN_PROC_ALL;

	if(sysctl(mib, 3, NULL, &size, NULL, 0) < 0) {
		sg_set_error_with_errno(SG_ERROR_SYSCTL,
		                        "CTL_KERN.KERN_PROC.KERN_PROC_ALL");
		return NULL;
	}

	procs = size / sizeof(struct kinfo_proc);

	kp_stats = sg_malloc(size);
	if(kp_stats == NULL) {
		return NULL;
	}
	memset(kp_stats, 0, size);

	if(sysctl(mib, 3, kp_stats, &size, NULL, 0) < 0) {
		sg_set_error_with_errno(SG_ERROR_SYSCTL,
		                        "CTL_KERN.KERN_PROC.KERN_PROC_ALL");
		free(kp_stats);
		return NULL;
	}

#if (defined(FREEBSD) && !defined(FREEBSD5)) || defined(DFBSD)
	kvmd = sg_get_kvm2();
#endif

	for (i = 0; i < procs; i++) {
		const char *name;

#ifdef FREEBSD5
		if (kp_stats[i].ki_stat == 0) {
#else
		if (kp_stats[i].kp_proc.p_stat == 0) {
#endif
			/* FreeBSD 5 deliberately overallocates the array that
			 * the sysctl returns, so we'll get a few junk
			 * processes on the end that we have to ignore. (Search
			 * for "overestimate by 5 procs" in
			 * src/sys/kern/kern_proc.c for more details.) */
			continue;
		}

		if (VECTOR_RESIZE(proc_state, proc_state_size + 1) < 0) {
			return NULL;
		}
		proc_state_ptr = proc_state+proc_state_size;

#ifdef FREEBSD5
		name = kp_stats[i].ki_comm;
#elif defined(DFBSD)
		name = kp_stats[i].kp_thread.td_comm;
#else
		name = kp_stats[i].kp_proc.p_comm;
#endif
		if (sg_update_string(&proc_state_ptr->process_name, name) < 0) {
			return NULL;
		}

#if defined(FREEBSD5) || defined(NETBSD) || defined(OPENBSD)

#ifdef FREEBSD5
		mib[2] = KERN_PROC_ARGS;
		mib[3] = kp_stats[i].ki_pid;
#else
		mib[1] = KERN_PROC_ARGS;
		mib[2] = kp_stats[i].kp_proc.p_pid;
		mib[3] = KERN_PROC_ARGV;
#endif

		free(proc_state_ptr->proctitle);
		proc_state_ptr->proctitle = NULL;

/* Starting size - we'll double this straight away */
#define PROCTITLE_START_SIZE 64
		buflen = PROCTITLE_START_SIZE;
		size = buflen;
		proctitle = NULL;

		do {
			if(size >= buflen) {
				buflen *= 2;
				size = buflen;
				proctitletmp = sg_realloc(proctitle, buflen);
				if(proctitletmp == NULL) {
					free(proctitle);
					proctitle = NULL;
					proc_state_ptr->proctitle = NULL;
					size = 0;
					break;
				}
				proctitle = proctitletmp;
				bzero(proctitle, buflen);
			}

			if(sysctl(mib, 4, proctitle, &size, NULL, 0) < 0) {
				free(proctitle);
				proctitle = NULL;
				proc_state_ptr->proctitle = NULL;
				size = 0;
				break;
			}
		} while(size >= buflen);

		if(size > 0) {
			proc_state_ptr->proctitle = sg_malloc(size+1);
			if(proc_state_ptr->proctitle == NULL) {
				return NULL;
			}
			p = proctitle;
#ifdef OPENBSD
			/* On OpenBSD, this value has the argv pointers (which
			 * are terminated by a NULL) at the front, so we have
			 * to skip over them to get to the strings. */
			while (*(char ***)p != NULL) {
				p += sizeof(char **);
			}
			p += sizeof(char **);
#endif
			proc_state_ptr->proctitle[0] = '\0';
			do {
				sg_strlcat(proc_state_ptr->proctitle, p, size+1);
				sg_strlcat(proc_state_ptr->proctitle, " ", size+1);
				p += strlen(p) + 1;
			} while (p < proctitle + size);
			free(proctitle);
			proctitle = NULL;
			/* remove trailing space */
			proc_state_ptr->proctitle[strlen(proc_state_ptr->proctitle)-1] = '\0';
		}
		else {
			if(proctitle != NULL) {
				free(proctitle);
				proctitle = NULL;
			}
			proc_state_ptr->proctitle = NULL;
		}
#else
		free(proc_state_ptr->proctitle);
		proc_state_ptr->proctitle = NULL;
		if(kvmd != NULL) {
			args = kvm_getargv(kvmd, &(kp_stats[i]), 0);
			if(args != NULL) {
				argsp = args;
				while(*argsp != NULL) {
					argslen += strlen(*argsp) + 1;
					argsp++;
				}
				proctitle = sg_malloc(argslen + 1);
				proctitle[0] = '\0';
				if(proctitle == NULL) {
					return NULL;
				}
				while(*args != NULL) {
					sg_strlcat(proctitle, *args, argslen + 1);
					sg_strlcat(proctitle, " ", argslen + 1);
					args++;
				}
				/* remove trailing space */
				proctitle[strlen(proctitle)-1] = '\0';
				proc_state_ptr->proctitle = proctitle;
			}
			else {
				proc_state_ptr->proctitle = NULL;
			}
		}
		else {
			proc_state_ptr->proctitle = NULL;
		}
#endif

#ifdef FREEBSD5
		proc_state_ptr->pid = kp_stats[i].ki_pid;
		proc_state_ptr->parent = kp_stats[i].ki_ppid;
		proc_state_ptr->pgid = kp_stats[i].ki_pgid;
#else
		proc_state_ptr->pid = kp_stats[i].kp_proc.p_pid;
		proc_state_ptr->parent = kp_stats[i].kp_eproc.e_ppid;
		proc_state_ptr->pgid = kp_stats[i].kp_eproc.e_pgid;
#endif

#ifdef FREEBSD5
		proc_state_ptr->uid = kp_stats[i].ki_ruid;
		proc_state_ptr->euid = kp_stats[i].ki_uid;
		proc_state_ptr->gid = kp_stats[i].ki_rgid;
		proc_state_ptr->egid = kp_stats[i].ki_svgid;
#elif defined(DFBSD)
		proc_state_ptr->uid = kp_stats[i].kp_eproc.e_ucred.cr_ruid;
		proc_state_ptr->euid = kp_stats[i].kp_eproc.e_ucred.cr_svuid;
		proc_state_ptr->gid = kp_stats[i].kp_eproc.e_ucred.cr_rgid;
		proc_state_ptr->egid = kp_stats[i].kp_eproc.e_ucred.cr_svgid;
#else
		proc_state_ptr->uid = kp_stats[i].kp_eproc.e_pcred.p_ruid;
		proc_state_ptr->euid = kp_stats[i].kp_eproc.e_pcred.p_svuid;
		proc_state_ptr->gid = kp_stats[i].kp_eproc.e_pcred.p_rgid;
		proc_state_ptr->egid = kp_stats[i].kp_eproc.e_pcred.p_svgid;
#endif

#ifdef FREEBSD5
		proc_state_ptr->proc_size = kp_stats[i].ki_size;
		/* This is in pages */
		proc_state_ptr->proc_resident =
			kp_stats[i].ki_rssize * getpagesize();
		/* This is in microseconds */
		proc_state_ptr->time_spent = kp_stats[i].ki_runtime / 1000000;
		proc_state_ptr->cpu_percent =
			((double)kp_stats[i].ki_pctcpu / FSCALE) * 100.0;
		proc_state_ptr->nice = kp_stats[i].ki_nice;
#else
		proc_state_ptr->proc_size =
			kp_stats[i].kp_eproc.e_vm.vm_map.size;
		/* This is in pages */
		proc_state_ptr->proc_resident =
			kp_stats[i].kp_eproc.e_vm.vm_rssize * getpagesize();
#if defined(NETBSD) || defined(OPENBSD)
		proc_state_ptr->time_spent =
			kp_stats[i].kp_proc.p_rtime.tv_sec;
#elif defined(DFBSD)
		proc_state_ptr->time_spent = 
			( kp_stats[i].kp_thread.td_uticks +
			kp_stats[i].kp_thread.td_sticks +
			kp_stats[i].kp_thread.td_iticks ) / 1000000;
#else
		/* This is in microseconds */
		proc_state_ptr->time_spent =
			kp_stats[i].kp_proc.p_runtime / 1000000;
#endif
		proc_state_ptr->cpu_percent =
			((double)kp_stats[i].kp_proc.p_pctcpu / FSCALE) * 100.0;
		proc_state_ptr->nice = kp_stats[i].kp_proc.p_nice;
#endif

#ifdef NETBSD2
		{
			size_t size;
			int mib[5];

			mib[0] = CTL_KERN;
			mib[1] = KERN_LWP;
			mib[2] = kp_stats[i].kp_proc.p_pid;
			mib[3] = sizeof(struct kinfo_lwp);
			mib[4] = 0;

			if(sysctl(mib, 5, NULL, &size, NULL, 0) < 0) {
				sg_set_error_with_errno(SG_ERROR_SYSCTL, "CTL_KERN.KERN_LWP.pid.structsize.0");
				return NULL;
			}

			lwps = size / sizeof(struct kinfo_lwp);
			mib[4] = lwps;

			kl_stats = sg_malloc(size);
			if(kl_stats == NULL) {
				return NULL;
			}

			if(sysctl(mib, 5, kl_stats, &size, NULL, 0) < 0) {
				sg_set_error_with_errno(SG_ERROR_SYSCTL, "CTL_KERN.KERN_LWP.pid.structsize.buffersize");
				return NULL;
			}
		}

		switch(kp_stats[i].kp_proc.p_stat) {
		case SIDL:
			proc_state_ptr->state = SG_PROCESS_STATE_RUNNING;
			break;
		case SACTIVE:
			{
				int i;

				for(i = 0; i < lwps; i++) {
					switch(kl_stats[i].l_stat) {
					case LSONPROC:
					case LSRUN:
						proc_state_ptr->state = SG_PROCESS_STATE_RUNNING;
						goto end;
					case LSSLEEP:
						proc_state_ptr->state = SG_PROCESS_STATE_SLEEPING;
						goto end;
					case LSSTOP:
					case LSSUSPENDED:
						proc_state_ptr->state = SG_PROCESS_STATE_STOPPED;
						goto end;
					}
					proc_state_ptr->state = SG_PROCESS_STATE_UNKNOWN;
				}
				end: ;
			}
			break;
		case SSTOP:
			proc_state_ptr->state = SG_PROCESS_STATE_STOPPED;
			break;
		case SZOMB:
			proc_state_ptr->state = SG_PROCESS_STATE_ZOMBIE;
			break;
		default:
			proc_state_ptr->state = SG_PROCESS_STATE_UNKNOWN;
			break;
		}

		free(kl_stats);
#else
#ifdef FREEBSD5
		switch (kp_stats[i].ki_stat) {
#else
		switch (kp_stats[i].kp_proc.p_stat) {
#endif
		case SIDL:
		case SRUN:
#ifdef SONPROC
		case SONPROC: /* NetBSD */
#endif
			proc_state_ptr->state = SG_PROCESS_STATE_RUNNING;
			break;
		case SSLEEP:
#ifdef SWAIT
		case SWAIT: /* FreeBSD 5 */
#endif
#ifdef SLOCK
		case SLOCK: /* FreeBSD 5 */
#endif
			proc_state_ptr->state = SG_PROCESS_STATE_SLEEPING;
			break;
		case SSTOP:
			proc_state_ptr->state = SG_PROCESS_STATE_STOPPED;
			break;
		case SZOMB:
#ifdef SDEAD
		case SDEAD: /* OpenBSD & NetBSD */
#endif
			proc_state_ptr->state = SG_PROCESS_STATE_ZOMBIE;
			break;
		default:
			proc_state_ptr->state = SG_PROCESS_STATE_UNKNOWN;
			break;
		}
#endif
		proc_state_size++;
	}

	free(kp_stats);
#endif

#ifdef CYGWIN
	sg_set_error(SG_ERROR_UNSUPPORTED, "Cygwin");
	return NULL;
#endif

	*entries = proc_state_size;
	return proc_state;
}

sg_process_count *sg_get_process_count() {
	static sg_process_count process_stat;
	sg_process_stats *ps;
	int ps_size, x;

	process_stat.sleeping = 0;
	process_stat.running = 0;
	process_stat.zombie = 0;
	process_stat.stopped = 0;
	process_stat.total = 0;

	ps = sg_get_process_stats(&ps_size);
	if (ps == NULL) {
		return NULL;
	}

	for(x = 0; x < ps_size; x++) {
		switch (ps->state) {
		case SG_PROCESS_STATE_RUNNING:
			process_stat.running++;
			break;
		case SG_PROCESS_STATE_SLEEPING:
			process_stat.sleeping++;
			break;
		case SG_PROCESS_STATE_STOPPED:
			process_stat.stopped++;
			break;
		case SG_PROCESS_STATE_ZOMBIE:
			process_stat.zombie++;
			break;
		default:
			/* currently no mapping for SG_PROCESS_STATE_UNKNOWN in
			 * sg_process_count */
			break;
		}
		ps++;
	}

	process_stat.total = ps_size;

	return &process_stat;
}

int sg_process_compare_name(const void *va, const void *vb) {
	const sg_process_stats *a = (sg_process_stats *)va;
	const sg_process_stats *b = (sg_process_stats *)vb;

	return strcmp(a->process_name, b->process_name);
}

int sg_process_compare_pid(const void *va, const void *vb) {
	const sg_process_stats *a = (sg_process_stats *)va;
	const sg_process_stats *b = (sg_process_stats *)vb;

	if (a->pid < b->pid) {
		return -1;
	} else if (a->pid == b->pid) {
		return 0;
	} else {
		return 1;
	}
}

int sg_process_compare_uid(const void *va, const void *vb) {
	const sg_process_stats *a = (sg_process_stats *)va;
	const sg_process_stats *b = (sg_process_stats *)vb;

	if (a->uid < b->uid) {
		return -1;
	} else if (a->uid == b->uid) {
		return 0;
	} else {
		return 1;
	}
}

int sg_process_compare_gid(const void *va, const void *vb) {
	const sg_process_stats *a = (sg_process_stats *)va;
	const sg_process_stats *b = (sg_process_stats *)vb;

	if (a->gid < b->gid) {
		return -1;
	} else if (a->gid == b->gid) {
		return 0;
	} else {
		return 1;
	}
}

int sg_process_compare_size(const void *va, const void *vb) {
	const sg_process_stats *a = (sg_process_stats *)va;
	const sg_process_stats *b = (sg_process_stats *)vb;

	if (a->proc_size < b->proc_size) {
		return -1;
	} else if (a->proc_size == b->proc_size) {
		return 0;
	} else {
		return 1;
	}
}

int sg_process_compare_res(const void *va, const void *vb) {
	const sg_process_stats *a = (sg_process_stats *)va;
	const sg_process_stats *b = (sg_process_stats *)vb;

	if (a->proc_resident < b->proc_resident) {
		return -1;
	} else if (a->proc_resident == b->proc_resident) {
		return 0;
	} else {
		return 1;
	}
}

int sg_process_compare_cpu(const void *va, const void *vb) {
	const sg_process_stats *a = (sg_process_stats *)va;
	const sg_process_stats *b = (sg_process_stats *)vb;

	if (a->cpu_percent < b->cpu_percent) {
		return -1;
	} else if (a->cpu_percent == b->cpu_percent) {
		return 0;
	} else {
		return 1;
	}
}

int sg_process_compare_time(const void *va, const void *vb) {
	const sg_process_stats *a = (sg_process_stats *)va;
	const sg_process_stats *b = (sg_process_stats *)vb;

	if (a->time_spent < b->time_spent) {
		return -1;
	} else if (a->time_spent == b->time_spent) {
		return 0;
	} else {
		return 1;
	}
}