📄 linux.c
字号:
{ static FILE *f; gchar buf[1024], part[128], disk[128]; gint major, minor, n; gulong rd, wr, rd1, wr1; gboolean inactivity_override, is_MD; static gboolean initial_read = TRUE; if (!f && (f = fopen(PROC_DISKSTATS_FILE, "r")) == NULL) return; disk[0] = '\0'; part[0] = '\0'; while ((fgets(buf, sizeof(buf), f)) != NULL) { /* major minor name rio rmerge rsect ruse wio wmerge wsect wuse | running use aveq | --or for a partition-- | major minor name rio rsect wio wsect */ n = sscanf(buf, "%d %d %127s %*d %lu %lu %lu %*d %*d %lu", &major, &minor, part, &rd, &rd1, &wr, &wr1); if (n == 7) { rd = rd1; wr = wr1; } /* Make sure all real disks get reported (so they will be added to the | disk monitor in order) the first time this function is called. | Use disk_major_ok() instead of simply initial_read until I'm sure | I'm testing for all the right "major" exclusions. | Note: disk_get_device_name() assumes "part[]" retains results from | previous calls and that disk/subdisk parsing will be in order | (ie hda will be encountered before hda1). */ inactivity_override = initial_read ? disk_major_ok(major) : FALSE; if ( (n != 7 && n != 6) || (rd == 0 && wr == 0 && !inactivity_override) || major == LVM_BLK_MAJOR || major == NBD_MAJOR || major == RAMDISK_MAJOR || major == LOOP_MAJOR || !disk_get_device_name(major, minor, disk, part) ) continue; is_MD = (major == MD_MAJOR); if (part[0] == '\0') gkrellm_disk_assign_data_by_name(disk, 512 * rd, 512 * wr, is_MD); else gkrellm_disk_subdisk_assign_data_by_name(part, disk, 512 * rd, 512 * wr); } rewind(f); initial_read = FALSE; } /* /proc/partitions can have diskstats in 2.4 kernels or in 2.5+ it's just | a list of disk names which can be used to get names to look for in sysfs. | But, with gkrellm 2.1.15 and for 2.6+kernels /proc/diskstats is | used instead of sysfs. */static voidlinux_read_proc_partitions_or_sysfs(void) { FILE *f, *sf; gchar buf[1024], part[128], disk[128], sysfspath[256]; gint major, minor, n; gulong sectors, rd, wr; gboolean is_MD; if ((f = fopen(PROC_PARTITIONS_FILE, "r")) != NULL) { fgets(buf, sizeof(buf), f); /* header */ fgets(buf, sizeof(buf), f); disk[0] = '\0'; part[0] = '\0'; while ((fgets(buf, sizeof(buf), f)) != NULL) { major = 0; if (have_partition_stats) { /* major minor #blocks name | rio rmerge rsect ruse wio wmerge wsect wuse running use aveq */ n = sscanf(buf, "%d %d %lu %127s %*d %*d %lu %*d %*d %*d %lu", &major, &minor, §ors, part, &rd, &wr); if ( n < 6 || sectors <= 1 || major == LVM_BLK_MAJOR || !disk_get_device_name(major, minor, disk, part) ) continue; } if (have_sysfs_stats) { n = sscanf(buf, "%d %d %lu %127s", &major, &minor, §ors, part); if ( n < 4 || sectors <= 1 || major == LVM_BLK_MAJOR || !disk_get_device_name(major, minor, disk, part) ) continue; if (part[0] == '\0') sprintf(sysfspath, "/sys/block/%s/stat", disk); else sprintf(sysfspath, "/sys/block/%s/%s/stat", disk, part); if ((sf = fopen(sysfspath, "r")) != NULL) { fgets(buf, sizeof(buf), sf); fclose(sf); if (part[0] == '\0') n = sscanf(buf,"%*d %*d %lu %*d %*d %*d %lu",&rd, &wr); else n = sscanf(buf,"%*d %lu %*d %lu", &rd, &wr); if (n < 2) continue; } } is_MD = (major == MD_MAJOR); if (part[0] == '\0') gkrellm_disk_assign_data_by_name(disk, 512 * rd, 512 * wr, is_MD); else gkrellm_disk_subdisk_assign_data_by_name(part, disk, 512 * rd, 512 * wr); } fclose(f); } }voidgkrellm_sys_disk_read_data(void) { /* If have_partition_stats, still need to get floppy and CDrom data | from /proc/stat */ if (!have_sysfs_stats && !have_diskstats) linux_read_proc_stat(); if (have_diskstats) linux_read_proc_diskstats(); else if (have_partition_stats || have_sysfs_stats) linux_read_proc_partitions_or_sysfs(); }gbooleangkrellm_sys_disk_init(void) { FILE *f = NULL; gchar buf[1024]; /* There were some incompatible /proc/diskstats patches for 2.4 */ if (os_release(2,6,0) && (f = fopen(PROC_DISKSTATS_FILE, "r")) != NULL) have_diskstats = TRUE; else if ((f = fopen(PROC_PARTITIONS_FILE, "r")) != NULL) { if (fgets(buf, sizeof(buf), f)) { if (strstr(buf, "rsect")) have_partition_stats = TRUE; else { if (have_sysfs) have_sysfs_stats = TRUE; } } } if (f) fclose(f); if (_GK.debug_level & DEBUG_SYSDEP) printf("diskstats=%d partition_stats=%d sysfs_stats=%d\n", have_diskstats, have_partition_stats, have_sysfs_stats); return TRUE; }/* ===================================================================== *//* Proc monitor interface */#include <utmp.h>#include <paths.h>#define PROC_LOADAVG_FILE "/proc/loadavg"voidgkrellm_sys_proc_read_data(void) { FILE *f; gchar buf[160]; gint n_running = 0, n_processes = 0; gulong n_forks = 0; gfloat fload = 0; if ((f = fopen(PROC_LOADAVG_FILE, "r")) != NULL) { /* sscanf(buf, "%f") might fail to convert because for some locales | commas are used for decimal points. */ fgets(buf, sizeof(buf), f); if (need_locale_fix) locale_fix(buf); sscanf(buf,"%f %*f %*f %d/%d %lu", &fload, &n_running, &n_processes, &n_forks); fclose(f); gkrellm_proc_assign_data(n_processes, n_running, n_forks, fload); } }voidgkrellm_sys_proc_read_users(void) { struct utmp *ut; struct stat s; static time_t utmp_mtime; gint n_users = 0; if (stat(_PATH_UTMP, &s) == 0 && s.st_mtime != utmp_mtime) { setutent(); while ((ut = getutent()) != NULL) if (ut->ut_type == USER_PROCESS && ut->ut_name[0] != '\0') ++n_users; endutent(); utmp_mtime = s.st_mtime; gkrellm_proc_assign_users(n_users); } }gbooleangkrellm_sys_proc_init(void) { struct lconv *lc; lc = localeconv(); locale_decimal_point = *lc->decimal_point; if (locale_decimal_point != '.') need_locale_fix = TRUE; return TRUE; }/* ===================================================================== *//* Inet monitor interface */#include "../inet.h"#define PROC_NET_TCP_FILE "/proc/net/tcp"#if defined(INET6)#define PROC_NET_TCP6_FILE "/proc/net/tcp6"#endifvoidgkrellm_sys_inet_read_tcp_data(void) { FILE *f; ActiveTCP tcp; gchar buf[512]; gint tcp_status; gulong addr; if ((f = fopen(PROC_NET_TCP_FILE, "r")) != NULL) { fgets(buf, sizeof(buf), f); /* header */ while (fgets(buf, sizeof(buf), f)) { sscanf(buf, "%*d: %*x:%x %lx:%x %x", &tcp.local_port, &addr, &tcp.remote_port, &tcp_status); tcp.remote_addr.s_addr = (uint32_t) addr; tcp.family = AF_INET; if (tcp_status != TCP_ALIVE) continue; gkrellm_inet_log_tcp_port_data(&tcp); } fclose(f); }#if defined(INET6) if ((f = fopen(PROC_NET_TCP6_FILE, "r")) != NULL) { fgets(buf, sizeof(buf), f); /* Waste first line */ while (fgets(buf, sizeof(buf), f)) { sscanf(buf, "%*d: %*x:%x %8x%8x%8x%8x:%x %x", &tcp.local_port, &tcp.remote_addr6.s6_addr32[0], &tcp.remote_addr6.s6_addr32[1], &tcp.remote_addr6.s6_addr32[2], &tcp.remote_addr6.s6_addr32[3], &tcp.remote_port, &tcp_status); tcp.family = AF_INET6; if (tcp_status != TCP_ALIVE) continue; gkrellm_inet_log_tcp_port_data(&tcp); } fclose(f); }#endif /* INET6 */ }gbooleangkrellm_sys_inet_init(void) { return TRUE; }/* ===================================================================== *//* Net monitor interface */#define PROC_NET_DEV_FILE "/proc/net/dev"#define PROC_NET_ROUTE_FILE "/proc/net/route"typedef struct { gchar *name; gboolean cur_up, up; } NetUp;static GList *net_routed_list;static gint rx_bytes_index, tx_bytes_index, rx_packets_index, tx_packets_index;voidgkrellm_sys_net_check_routes(void) { static FILE *f; GList *list; NetUp *net; gchar *s; gchar buf[512]; for (list = net_routed_list; list; list = list->next) ((NetUp *) list->data)->cur_up = FALSE; if (f || (f = fopen(PROC_NET_ROUTE_FILE, "r")) != NULL) { fgets(buf, sizeof(buf), f); /* Waste the first line */ while (fgets(buf, sizeof(buf), f)) { if ( ((s = strtok(buf, " \t\n")) == NULL) || !strncmp(s, "dummy", 5) || (*s == '*' && *(s+1) == '\0') ) continue; for (list = net_routed_list; list; list = list->next) { net = (NetUp *) list->data; if (!strcmp(net->name, s)) { net->cur_up = TRUE; break; } } if (!list) { net = g_new0(NetUp, 1); net_routed_list = g_list_append(net_routed_list, net); net->name = g_strdup(s); net->cur_up = TRUE; } } rewind(f); } for (list = net_routed_list; list; list = list->next) { net = (NetUp *) list->data; if (net->up && !net->cur_up) gkrellm_net_routed_event(net->name, FALSE); else if (!net->up && net->cur_up) gkrellm_net_routed_event(net->name, TRUE); net->up = net->cur_up; } } /* I read both the bytes (kernel 2.2.x) and packets (all kernels). Some | net drivers for 2.2.x do not update the bytes counters. */voidgkrellm_sys_net_read_data(void) { static FILE *f; gchar buf[512]; gchar *name, *s, *s1; gint i; gulong rx, tx; gulong rx_packets = 0, tx_packets = 0; guint64 ll; if (!f && (f = fopen(PROC_NET_DEV_FILE, "r")) == NULL) return; fgets(buf, sizeof(buf), f); /* 2 line header */ fgets(buf, sizeof(buf), f); while (fgets(buf, sizeof(buf), f)) { /* Virtual net interfaces have a colon in the name, and a colon seps | the name from data, + might be no space between data and name! | Eg. this is possible -> eth2:0:11249029 0 ... | So, replace the colon that seps data from the name with a space. */ s = strchr(buf, (int) ':'); if (s) { s1 = strchr(s + 1, (int) ':'); if (s1) *s1 = ' '; else *s = ' '; } if ((name = strtok(buf, " \t\n")) == NULL) /* Get name of interface */ { fclose(f); f = NULL; return; } if (!strncmp(name, "dummy", 5)) continue; rx = tx = 0; for (i = 1; (s = strtok(NULL, " \t\n")) != NULL; ++i) { if (i == rx_bytes_index) { rx = strtoul(s, NULL, 0); /* Can have 32 bit library / 64 bit kernel mismatch. | If so, just using the 32 low bits of a long long is OK. */ if ( rx == ULONG_MAX && errno == ERANGE && sscanf(s, "%Ld", &ll) == 1 ) rx = (gulong) ll; } else if (i == tx_bytes_index) { tx = strtoul(s, NULL, 0); if ( tx == ULONG_MAX && errno == ERANGE && sscanf(s, "%Ld", &ll) == 1 ) tx = (gulong) ll; } else if (i == rx_packets_index) rx_packets = strtoul(s, NULL, 0); else if (i == tx_packets_index) tx_packets = strtoul(s, NULL, 0); if (i > tx_bytes_index && i > tx_packets_index) break; } if (rx == 0 && tx == 0) { rx = rx_packets; tx = tx_packets; } gkrellm_net_assign_data(name, rx, tx); } rewind(f); }gbooleangkrellm_sys_net_isdn_online(void) { gint f = 0; gchar buffer[BUFSIZ], *p, *end; if ( (f = open("/dev/isdninfo", O_RDONLY)) == -1 && (f = open("/dev/isdn/isdninfo", O_RDONLY)) == -1 ) { if (_GK.debug_level & DEBUG_NET) printf("sys_net_isdn__online: no /dev/isdninfo?\n"); return FALSE; } memset(buffer, 0, BUFSIZ); if (read(f, buffer, BUFSIZ) <= 0) { close(f); return FALSE; } close(f); if ((p = strstr(buffer, "flags:")) == NULL) return FALSE; for(p += 6; *p; ) { if (isspace(*p)) { p++; continue; } for (end = p; *end && !isspace(*end); end++) ; if (*end == '\0' || *end == '\t') break; else *end = 0; if (!strcmp(p, "?") || !strcmp(p, "0")) { p = end+1; continue; } return TRUE; /* ISDN is online */ } return FALSE; /* ISDN is off line */ }static const char *delim = " :|\t\n";static voidget_io_indices(void) { FILE *f; gchar *s; gchar buf[184];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -