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

📄 intr_stat.c

📁 linux 系统控制硬盘旋转和停止的程序(spin down/up)
💻 C
字号:
/* * <intr_stat.c> * * Copyright (C) 2001 Laurent Pelecq * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA *  * $Id: intr_stat.c,v 1.6 2003/10/12 15:32:36 nold Exp $ * */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include "noflushd.h"#include "bug.h"#include "util.h"#include "intr_stat.h"#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <ctype.h>#include <sys/types.h>#include <time.h>#define UNKNOWN_INTERRUPT	"unknown"#define LIST_DELIMITERS		",;"/* FIXME I'd rather use args like "idle"/"active" to a single script to limit * footprint on disk caches. Even better something like: * /etc/noflushd/notify /dev/hda spinup, or .../notify irq idle. */#define CMD_IF_IDLE		"/etc/noflushd/do_idle"#define CMD_IF_ACTIVE		"/etc/noflushd/do_active"typedef struct irq_stat_s_t *irq_stat_t;struct irq_stat_s_t {	int nr;				/* Irq line */	long unsigned int count;	/* Stat counter */	int active;			/* True if it should be monitored */	char *name;			/* Name as in /proc/interrupts */	irq_stat_t next;};static struct {	irq_stat_t irq_head;	/* Linked list of irq line structs */	int timeout;		/* Idle timeout for inactivity */	int is_idle;		/* Inactivity flag */	unsigned int nb_watch;	/* Number of irq lines watched */	time_t stamp;		/* last modification */} global;/* Query for irq line n in irq list. Returns NULL on failure, irq entry * on success. */static irq_stat_t get_irq(irq_stat_t head, int n){	while (head) {		if (head->nr == n)			break;		head = head->next;	}	return head;}/* Allocate new entry for irq line n. Returns new list head on success, * NULL on failure. */static irq_stat_t alloc_irq(irq_stat_t head, int n){	irq_stat_t irq;	/* Sanity check. Don't do anything if irq already present. */	irq = get_irq(head, n);	if (irq) {		DEBUG("Double alloc of irq #%d", n);		return NULL;	}	irq = malloc(sizeof(*irq));	if (!irq) {		ERR("No mem for irq stat");		return NULL;	}	irq->nr = n;	irq->count = 0;	irq->active = 0;	irq->name = NULL;	irq->next = head;	return irq;}		static irq_stat_t add_interrupt(irq_stat_t head, int n,		                unsigned long int count, const char *name){	irq_stat_t irq;		if (!(irq = alloc_irq(head, n)))		return NULL;		irq->count = count;	irq->name = strdup(name);	if (!irq->name)		irq->name = UNKNOWN_INTERRUPT;	return irq;}static int parse_interrupts(time_t now){	FILE *stat;	char *line, *entry, *tmp;	irq_stat_t irq;	int ret = 1;	unsigned int lineno = 0;	stat = fopen("/proc/interrupts", "r");	if (!stat)		return 0;	while ((line=get_line(stat))) {		int n, nr;		unsigned long int count;		lineno++;				entry = get_entry(line, 0);		if (!entry || !isdigit(*entry)) {			release_entry(entry);			goto next_line;		}		nr = atoi(entry);		release_entry(entry);		n=1;		count=0;				while ((entry=get_entry(line, n++))) {			if (!isdigit(*entry)) {				break;			}			count += atol(entry);			release_entry(entry);		}		if (!entry) {			ERR("Weird line #%u in /proc/interrupts", lineno);			ret = 0;			goto err;		}		/* Argh!  The layout of /proc/interrupts differs across		 * architectures.  Some contain the IRQ type in the		 * next-to-last field, some don't.		 */		if ((tmp = get_remains(line, n))) {			release_entry(entry);			entry = tmp;		}		irq = get_irq(global.irq_head, nr);		if (irq) {			if (irq->active && irq->count != count) {				DEBUG("Updated irq #%d %12lu %s",						nr, count, entry);				global.stamp = now;			}			irq->count = count;		} else			if ((irq = add_interrupt(global.irq_head, nr,			                         count, entry)))				 global.irq_head = irq;				release_remains(entry);next_line:		release_line(line);	}err:	fclose(stat);	return ret;}/* Initialize interrupts monitoring */int intr_stat_init(void){	time_t now = time(NULL);	global.is_idle = 0;	global.timeout = 0;	global.nb_watch = 0;	global.stamp = now;	global.irq_head = NULL;	return parse_interrupts(now);}void intr_set_timeout(int timeout){	global.timeout = timeout;}/* Release allocated resources */void intr_stat_release(void){	irq_stat_t irq = global.irq_head;		while (irq) {		irq_stat_t tmp = irq->next;		if (irq->name && strcmp(irq->name, UNKNOWN_INTERRUPT))			free(irq->name);		free(irq);		irq = tmp;	}}/* Register a given interrupt to monitor it */int intr_stat_register(int n){	irq_stat_t irq = get_irq(global.irq_head, n);	if (!irq) {		ERR("No irq line #%d found", n);		return 0;	}	irq->active = 1;	global.nb_watch++;	INFO("Monitoring interrupt #%d \"%s\"", n,	     irq->name ? irq->name : UNKNOWN_INTERRUPT);	return 1;}/* Register interrupts given as a comma separated list of interrupt   ids */int intr_stat_register_byids(const char *ids){	char *buffer = strdup(ids);	char *persist = NULL;	const char *p = NULL;	int status = 1;	if (!buffer)		return 0;	for (p = strtok_r(buffer, LIST_DELIMITERS, &persist);	     p; p = strtok_r(NULL, LIST_DELIMITERS, &persist)) {		if (isdigit(*p)) {			status = intr_stat_register(atoi(p));		} else {			irq_stat_t irq = global.irq_head;			while (irq) {				if (!strcmp(irq->name, p)) {					status = intr_stat_register(irq->nr);					break;				}				irq = irq->next;			}							}	}	free(buffer);	return status;}/* Return 1 if not idle */int intr_stat_check_idleness(void){	int is_idle;	char *cmd;	time_t now = time(NULL);		/* No irqs watched -> we're always idle */	if (!global.nb_watch)		return 1;		if (!parse_interrupts(now))		BUG("Failed updating irq stats");			is_idle = (now - global.stamp > global.timeout);		if (global.is_idle == is_idle)		return is_idle;			cmd = (is_idle) ? CMD_IF_IDLE : CMD_IF_ACTIVE;	DEBUG("state is %s", (is_idle) ? "idle" : "active");		if (access(cmd, X_OK) == 0 && system(cmd) < 0) {		ERR("cannot execute %s", cmd);		return global.is_idle;	/* Will retry next time */	}		global.is_idle = is_idle;		return is_idle;}

⌨️ 快捷键说明

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