⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 linux.c

📁 系统任务管理器
💻 C
📖 第 1 页 / 共 5 页
字号:
/* GKrellM|  Copyright (C) 1999-2006 Bill Wilson||  Author:  Bill Wilson    billw@gkrellm.net|  Latest versions might be found at:  http://gkrellm.net||  This program is free software which I release under the GNU General Public|  License. You may redistribute and/or modify this program under the terms|  of that license as published by the Free Software Foundation; either|  version 2 of the License, or (at your option) any later version.||  This program is distributed in the hope that it will be useful,|  but WITHOUT ANY WARRANTY; without even the implied warranty of|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the|  GNU General Public License for more details.  Version 2 is in the|  COPYRIGHT file in the top level directory of this distribution.| |  To get a copy of the GNU General Puplic License, write to the Free Software|  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA*/#include <limits.h>#include <errno.h>#include <locale.h>#include <sys/types.h>#include <dirent.h>static gboolean		need_locale_fix,					have_diskstats,					have_partition_stats,					have_sysfs,					have_sysfs_stats,					have_sysfs_sensors;static gchar		locale_decimal_point;static gboolean		kernel_2_4,					kernel_2_6;static gint			os_major,					os_minor,					os_rev;static gbooleanos_release(gint major, gint minor, gint rev)	{	if (   os_major > major		|| (os_major == major && os_minor > minor)		|| (os_major == os_major && os_minor == minor && os_rev >= rev)	   )		return TRUE;	return FALSE;	}voidgkrellm_sys_main_init(void)	{	FILE	*f;	gchar	buf[1024];	if ((f = fopen("/proc/sys/kernel/osrelease", "r")) != NULL)		{		if (fgets(buf, sizeof(buf), f) != NULL)			sscanf(buf, "%d.%d.%d", &os_major, &os_minor, &os_rev);		fclose(f);		kernel_2_4 = os_release(2, 4, 0);		kernel_2_6 = os_release(2, 6, 0);		}	/* Various stats are in sysfs since 2.5.47, but it may not be mounted.	*/	if ((f = fopen("/proc/mounts", "r")) != NULL)		{		while (fgets(buf, sizeof(buf), f) != NULL)			if (strstr(buf, "sysfs"))				{				have_sysfs = TRUE;				break;				}		fclose(f);		}	}voidgkrellm_sys_main_cleanup(void)	{	}  /* Linux /proc always reports floats with '.' decimal points, but sscanf()  |  for some locales needs commas in place of periods.  So, if current  |  locale doesn't use periods, must insert the correct decimal point char.  */static voidlocale_fix(gchar *buf)	{	gchar	*s;	for (s = buf; *s; ++s)		if (*s == '.')			*s = locale_decimal_point;	}/* ===================================================================== *//* CPU, disk, and swap monitor interfaces might all get data from /proc/stat|  (depending on kernel version) so they will share reading of /proc/stat.*/#define	PROC_STAT_FILE	"/proc/stat"static gint		n_cpus;static gulong	swapin,				swapout;  /* CPU, and Disk monitors call this in their update routine.   |  Whoever calls it first will read the data for everyone.  |  | /proc/stat has cpu entries like:  |		cpu		total_user	total_nice	total_sys	total_idle  |		cpu0	cpu0_user	cpu0_nice	cpu0_sys	cpu0_idle  |			...  |		cpuN	cpuN_user	cpuN_nice	cpuN_sys	cpuN_idle  |  where ticks for cpu are jiffies * smp_num_cpus  |  and ticks for cpu[i] are jiffies (1/CLK_TCK)  */static voidlinux_read_proc_stat(void)	{	static FILE	*f;	gint		n, i, ncpu;	gchar		*s, buf[1024];	gulong		rblk[4], wblk[4];	guint64		user, nice, sys, idle, iowait;	static gint	data_read_tick	= -1;	n = gkrellm_get_timer_ticks();	if (data_read_tick == n)		return;		/* Just one read per tick (multiple monitors call this) */	if (!f && (f = fopen(PROC_STAT_FILE, "r")) == NULL)		return;	data_read_tick = n;	gkrellm_disk_reset_composite();	ncpu = 0;	while ((fgets(buf, sizeof(buf), f)) != NULL)		{		if (buf[0] == 'c' && buf[1] == 'p')			{			n = sscanf(buf, "%*s %Lu %Lu %Lu %Lu %Lu",						&user, &nice, &sys, &idle, &iowait);			if (n == 5)			/* iowait is new in kernel 2.5	*/				idle += iowait;			if (n_cpus > 1)				{				if (ncpu == 0)					gkrellm_cpu_assign_composite_data(user, nice, sys, idle);				else					gkrellm_cpu_assign_data(ncpu - 1, user, nice, sys, idle);				}			/* If have cpu and cpu0 on single cpu machines, won't use cpu0.			*/			else if (ncpu == 0)				gkrellm_cpu_assign_data(0, user, nice, sys, idle);			++ncpu;			continue;			}		if (!kernel_2_6 && !strncmp("swap", buf, 4))			{			sscanf(buf + 5, "%lu %lu", &swapin, &swapout);			continue;			}		if (buf[0] != 'd')			continue;		if (!strncmp("disk_rblk", buf, 9))			{			s = buf + 10;			for (i = 0; i < 4; ++i)				rblk[i] = strtoul(s, &s, 0);			}		else if (!strncmp("disk_wblk", buf, 9))			{			s = buf + 10;			for (i = 0; i < 4; ++ i)				{				wblk[i] = strtoul(s, &s, 0);				gkrellm_disk_assign_data_nth(i,							512 * rblk[i], 512 * wblk[i], FALSE);				}			}		else if (!strncmp("disk_io:", buf, 8))		/* Kernel 2.4 only	*/			{			gint	major, i_disk;			gulong	rblk, wblk, rb1, rb2, wb1, wb2;			s = strtok(buf + 9, " \t\n");			while (s)				{				/* disk_io lines in 2.4.x kernels have had 2 formats */				n = sscanf(s, "(%d,%d):(%*d,%lu,%lu,%lu,%lu)",						&major, &i_disk, &rb1, &rb2, &wb1, &wb2);				if (n == 6)	/* patched as of 2.4.0-test1-ac9 */					{		/* (major,disk):(total_io,rio,rblk,wio,wblk) */					rblk = rb2;					wblk = wb2;					}				else	/* 2.3.99-pre8 to 2.4.0-testX */					{		/* (major,disk):(rio,rblk,wio,wblk) */					rblk = rb1;					wblk = wb1;					}				/* floppys and CDroms don't show up in /proc/partitions.				*/				if (have_partition_stats)					{					gchar	name[32];					name[0] = '\0';					if (major == 2)						sprintf(name, "fd%d", i_disk);					else if (major == 11)						sprintf(name, "scd%d", i_disk);					if (name[0])						gkrellm_disk_assign_data_by_name(name,								512 * rblk, 512 * wblk, FALSE);					}				else					{					gkrellm_disk_assign_data_by_device(major, i_disk,								512 * rblk, 512 * wblk,								(major == 9) ? TRUE : FALSE);					}				s = strtok(NULL, " \t\n");				}			}		}	rewind(f);	}/* ===================================================================== *//* CPU monitor interface */voidgkrellm_sys_cpu_read_data(void)	{	/* One routine reads cpu, disk, and swap data.  All three monitors will	| call it, but only the first call per timer tick will do the work.	*/	linux_read_proc_stat();	}gbooleangkrellm_sys_cpu_init(void)	{	FILE	*f;	gchar	buf[1024];	if ((f = fopen(PROC_STAT_FILE, "r")) == NULL)		return FALSE;	while (fgets(buf, sizeof(buf), f))		{		if (strncmp(buf, "cpu", 3) != 0)			continue;		++n_cpus;		}	fclose(f);	/* If multiple CPUs, the first one will be a composite.  Report only real.	*/	if (n_cpus > 1)		--n_cpus;	gkrellm_cpu_set_number_of_cpus(n_cpus);	return TRUE;	}/* ===================================================================== *//* Disk monitor interface */#define	PROC_PARTITIONS_FILE	"/proc/partitions"#define	PROC_DISKSTATS_FILE		"/proc/diskstats"#include <linux/major.h>#if ! defined (SCSI_DISK0_MAJOR)#define SCSI_DISK0_MAJOR	8#endif#if ! defined (MD_MAJOR)#define MD_MAJOR	9#endif#if !defined(IDE4_MAJOR)#define IDE4_MAJOR	56#endif#if !defined(IDE5_MAJOR)#define IDE5_MAJOR	57#endif#if !defined(IDE6_MAJOR)#define IDE6_MAJOR	88#endif#if !defined(IDE7_MAJOR)#define IDE7_MAJOR	89#endif#if !defined(IDE8_MAJOR)#define IDE8_MAJOR	90#endif#if !defined(IDE9_MAJOR)#define IDE9_MAJOR	91#endif#if !defined(DAC960_MAJOR)#define DAC960_MAJOR	48#endif#if !defined(COMPAQ_SMART2_MAJOR)#define COMPAQ_SMART2_MAJOR	72#endif#if !defined(COMPAQ_CISS_MAJOR)#define COMPAQ_CISS_MAJOR	104#endif#if !defined(LVM_BLK_MAJOR)#define LVM_BLK_MAJOR 58#endif#if !defined(NBD_MAJOR)#define NBD_MAJOR 43#endifstruct _disk_name_map	{	gchar	*name;	gint	major;	gint	minor_mod;	gchar	suffix_base;	};  /* Disk charts will appear in GKrellM in the same order as this table.  */static struct _disk_name_map	disk_name_map[] =	{	{"hd",	IDE0_MAJOR,					64,	'a' },	/* 3:  hda, hdb */	{"hd",	IDE1_MAJOR,					64,	'c' },	/* 22: hdc, hdd */	{"hd",	IDE2_MAJOR,					64,	'e' },	/* 33: hde, hdf */	{"hd",	IDE3_MAJOR,					64,	'g' },	/* 34: hdg, hdh */	{"hd",	IDE4_MAJOR,					64,	'i' },	/* 56: hdi, hdj */	{"hd",	IDE5_MAJOR,					64,	'k' },	/* 57: hdk, hdl */	{"hd",	IDE6_MAJOR,					64,	'm' },	/* 88: hdm, hdn */	{"hd",	IDE7_MAJOR,					64,	'o' },	/* 89: hdo, hdp */	{"hd",	IDE8_MAJOR,					64,	'q' },	/* 90: hdq, hdr */	{"hd",	IDE9_MAJOR,					64,	's' },	/* 91: hds, hdt */	{"sd",	SCSI_DISK0_MAJOR,			16,	'a' },	/* 8:  sda-sdh */	{"sg",	SCSI_GENERIC_MAJOR,			16,	'0' },	/* 21: sg0-sg16 */	{"scd",	SCSI_CDROM_MAJOR,			16,	'0' },	/* 11: scd0-scd16 */	{"sr",	SCSI_CDROM_MAJOR,			16,	'0' },	/* 11: sr0-sr16 */	{"md",	MD_MAJOR,					0,	'0' },	/* 9:  md0-md3 */	{"c0d",	DAC960_MAJOR,				32,	'0' },	/* 48:  c0d0-c0d31 */	{"c1d",	DAC960_MAJOR + 1,			32,	'0' },	/* 49:  c1d0-c1d31 */	{"c2d",	DAC960_MAJOR + 2,			32,	'0' },	/* 50:  c2d0-c2d31 */	{"c3d",	DAC960_MAJOR + 3,			32,	'0' },	/* 51:  c3d0-c3d31 */	{"c4d",	DAC960_MAJOR + 4,			32,	'0' },	/* 52:  c4d0-c4d31 */	{"c5d",	DAC960_MAJOR + 5,			32,	'0' },	/* 53:  c5d0-c5d31 */	{"c6d",	DAC960_MAJOR + 6,			32,	'0' },	/* 54:  c6d0-c6d31 */	{"c7d",	DAC960_MAJOR + 7,			32,	'0' },	/* 55:  c7d0-c7d31 */	{"cs0d", COMPAQ_SMART2_MAJOR,		16,	'0' },	/* 72:  c0d0-c0d15 */	{"cs1d", COMPAQ_SMART2_MAJOR + 1,	16,	'0' },	/* 73:  c1d0-c1d15 */	{"cs2d", COMPAQ_SMART2_MAJOR + 2,	16,	'0' },	/* 74:  c2d0-c2d15 */	{"cs3d", COMPAQ_SMART2_MAJOR + 3,	16,	'0' },	/* 75:  c3d0-c3d15 */	{"cs4d", COMPAQ_SMART2_MAJOR + 4,	16,	'0' },	/* 76:  c4d0-c4d15 */	{"cs5d", COMPAQ_SMART2_MAJOR + 5,	16,	'0' },	/* 77:  c5d0-c5d15 */	{"cs6d", COMPAQ_SMART2_MAJOR + 6,	16,	'0' },	/* 78:  c6d0-c6d15 */	{"cs7d", COMPAQ_SMART2_MAJOR + 7,	16,	'0' },	/* 79:  c7d0-c7d15 */	{"cc0d", COMPAQ_CISS_MAJOR,			16,	'0' },	/* 104:  c0d0-c0d15 */	{"cc1d", COMPAQ_CISS_MAJOR + 1,		16,	'0' },	/* 105:  c1d0-c1d15 */	{"cc2d", COMPAQ_CISS_MAJOR + 2,		16,	'0' },	/* 106:  c2d0-c2d15 */	{"cc3d", COMPAQ_CISS_MAJOR + 3,		16,	'0' },	/* 107:  c3d0-c3d15 */	{"cc4d", COMPAQ_CISS_MAJOR + 4,		16,	'0' },	/* 108:  c4d0-c4d15 */	{"cc5d", COMPAQ_CISS_MAJOR + 5,		16,	'0' },	/* 109:  c5d0-c5d15 */	{"cc6d", COMPAQ_CISS_MAJOR + 6,		16,	'0' },	/* 110:  c6d0-c6d15 */	{"cc7d", COMPAQ_CISS_MAJOR + 7,		16,	'0' },	/* 111:  c7d0-c7d15 */	{"fd",	FLOPPY_MAJOR,				0,	'0' }	/* 2:  fd0-fd3  */	};static gbooleandisk_major_ok(gint major)	{	gint		i;	for (i = 0; i < sizeof(disk_name_map) / sizeof(struct _disk_name_map); ++i)		{		if (major == disk_name_map[i].major)			return TRUE;		}	return FALSE;	}gchar *gkrellm_sys_disk_name_from_device(gint device_number, gint unit_number,			gint *order)	{	struct _disk_name_map	*dm	= NULL;	gint		i;	gchar		suffix;	static gchar name[32];	for (i = 0; i < sizeof(disk_name_map) / sizeof(struct _disk_name_map); ++i)		{		if (device_number != disk_name_map[i].major)			continue;		dm = &disk_name_map[i];		break;		}	if (dm)		{		suffix = dm->suffix_base + unit_number;		sprintf(name, "%s%c", dm->name, suffix);		}	else		sprintf(name, "(%d,%d)", device_number, unit_number);	*order = i;	return name;	}gintgkrellm_sys_disk_order_from_name(gchar *name)	{	struct _disk_name_map	*dm, *dm_next;	gint		i, len, table_size;	gchar		suffix;	table_size = sizeof(disk_name_map) / sizeof(struct _disk_name_map);	for (i = 0; i < table_size; ++i)		{		dm = &disk_name_map[i];		len = strlen(dm->name);		if (strncmp(dm->name, name, len))			continue;		suffix = name[len];			/* So far looked at only for "hd" series */		if (i < table_size - 1)			{			dm_next = &disk_name_map[i + 1];			if (   !strcmp(dm_next->name, dm->name)				&& dm_next->suffix_base <= suffix			   )				continue;			}		break;		}	if (i >= table_size)		i = -1;	return i;	}  /* Given a /proc/partitions or /proc/diskstats line disk name in "partition",  |  make "disk" have the whole disk name (eg hda) and "partition" have the  |  partition (eg hda1) or NULL if not a partition.  For simple names,  |  "disk" is expected to initially have the whole disk name from the  |  previous call (or NULL if this is the first call per /proc file parse).  */static gbooleandisk_get_device_name(gint major, gint minor, gchar *disk, gchar *partition)	{	struct _disk_name_map	*dm	= NULL;	gint					i, unit = 0;	gchar					*p, *d;			for (p = partition; *p; ++p)		if (*p == '/')			break;	if (!*p)		{	/* Have a simple name like hda, hda1, sda, ... */		d = disk;		p = partition;		while (*d && *p && *d++ == *p++)			;		if (d == disk || *d || *p < '0' || *p > '9')			{			strcpy(disk, partition);			partition[0] = '\0';			}		return TRUE;		}	/* Have a devfs name like ide/host0/bus0/target0/lun0/part1, so construct	|  a name based on major, minor numbers and the disk_name_map[].	*/	for (i = 0; i < sizeof(disk_name_map) / sizeof(struct _disk_name_map); ++i)		{		if (major != disk_name_map[i].major)			continue;		dm = &disk_name_map[i];		if (dm->minor_mod > 0 && minor >= dm->minor_mod)			{			unit = minor / dm->minor_mod;			minor = minor % dm->minor_mod;			}		sprintf(disk, "%s%c", dm->name, dm->suffix_base + unit);		if (minor > 0)			sprintf(partition, "%s%d", disk, minor);		else			partition[0] = '\0';		return TRUE;		}	return FALSE;	}  /* Kernels >= 2.5.69 have /proc/diskstats which can be more efficient to  |  read than getting stats from sysfs.  See:  |      /usr/src/linux/Documentation/iostats.txt  |  But gkrellm calls this only for 2.6+ kernels since there were some  |  format incompatible /proc/diskstats patches for 2.4.  */static voidlinux_read_proc_diskstats(void)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -