[FreeBSD] Контроль загрузки процессора (cpu sysctl bsd)
Ключевые слова: cpu, sysctl, bsd, (найти похожие документы)
- BEST_PEOPLE (2:5077/15.22) ---------------------- BEST_PEOPLE (RU.UNIX.BSD) -
From : Valentin Nechayev 2:5020/400 24 Jan 01 16:52:34
Subj : [FreeBSD] Контроль загрузки процессора
-------------------------------------------------------------------------------
* Forwarded from area 'RU.UNIX.BSD'
From: [email protected] (Valentin Nechayev)
>> >Существует ли утилитка типа top или vmstat которая бы отслеживала
>> >загрузку процессора и памяти, но данные выводила бы не на экран,
>> >а в какой-нибудь файл?
Для начала - `sysctl -a | less' и внимательно рассмотреть.
Hе менее половины данных там будет.
AI> uptime показывает усредненную цифру, непонятно как вычисляющуюся и что,
AI> собственно говоря, показывающую.
Тебе неизвестно? В такой формулировке - согласен.;))
uptime показывает среднее за: 1, 5, 15 минут соответственно - там три числа -
количество процессов готовых к выполнению, то есть не находящихся в
какой-нибудь спячке. Если ты будешь снимать раз в минуту - вполне достаточно.
AI> Интервал, ну, скажем, 1 минута. Или 5. Как пожелаю.
AI> Записывать хотя бы idle для процессора и сумму Inact и Free для памяти.
AI> Желательно, конечно, чтбы это были не мгновенные снимки состояния
AI> системы,
AI> а средние цифры за период между записями в файл.
Idlt для процессора считается следующим образом. Из kvm получается количество
тиков statclock'а, в которых процесс был в каждом из пяти состояний.
В ядре есть инкрементальные счетчики этих тиков-при-состоянии.
Сняв в два разных момента значения этих счетчиков и разделив разность значений
счетчика idle на сумму по всем значениям разности этих значений, получаешь
долю процессора в idle, с учетом погрешности самого метода измерения
"вспышками statclock'а". Сколько у тебя времени проходит между снимками -
твое дело, но предел - 2**22 секунд (~2 месяца) для процессора.
Вот программка, снимающая значения счетчиков типов занятости процессора
и случившихся прерываний (частично передрана из systat/vmstat.c):
=== cut ===
#include <sys/param.h>
#include <sys/dkstat.h>
#include <sys/time.h>
#include <fcntl.h>
#include <err.h>
#include <kvm.h>
#include <time.h>
#include <syslog.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define NVAL(indx) namelist[(indx)].n_value
#define NPTR(indx) (void *)NVAL((indx))
#define NREAD(indx, buf, len) kvm_ckread(NPTR((indx)), (buf), (len))
static void rdtsc( unsigned long*, unsigned long* );
static struct nlist namelist[] = {
#define N_CPTIME 0
{ "_cp_time" },
#define N_INTRCNT 1
{ "_intrcnt" },
#define N_EINTRCNT 2
{ "_eintrcnt" },
#define N_INTRNAMES 3
{ "_intrnames" },
#define N_EINTRNAMES 4
{ "_eintrnames" },
{ "" }
};
int
main( void )
{
kvm_t *kd;
char errbuf[80];
long p_time_cnts[CPUSTATES];
unsigned long tsc_edx, tsc_eax;
struct timeval tvnow;
int i, nintr;
static const char* p_time_names[] = {
"t_sys", "t_intr", "t_user", "t_nice", "t_idle"
};
long* intrcnts;
char** intrnames;
char* intrnamebuf;
char* cp;
char obuf[1000];
char* opos;
char* olim;
olim = obuf + sizeof obuf;
opos = obuf;
gettimeofday( &tvnow, NULL );
rdtsc( &tsc_edx, &tsc_eax );
snprintf( opos, olim-opos, "time=%lu.%ld tsc=%lu:%lu",
tvnow.tv_sec, tvnow.tv_usec, tsc_edx, tsc_eax );
opos += strlen( opos );
kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
if( kd == NULL ) {
errx(1,"%s", errbuf);
}
if( kvm_nlist( kd, namelist ) != 0 )
err( 1, "kvm_nlist() failed" );
if( !namelist[0].n_type )
errx( 1, "no namelist after kvm_nlist()" );
if( kvm_read( kd, namelist[N_CPTIME].n_value, p_time_cnts,
sizeof( p_time_cnts ) ) != sizeof( p_time_cnts ) )
errx( 1, "kvm_read() failed" );
for( i = 0; i < CPUSTATES; i++ ) {
snprintf( opos, olim-opos, " p.%s=%ld",
p_time_names[i], p_time_cnts[i] );
opos += strlen( opos );
}
nintr = ( namelist[N_EINTRCNT].n_value - namelist[N_INTRCNT].n_value )
/ sizeof(long);
intrcnts = (long*) calloc(nintr, sizeof(long));
intrnames = (char**) calloc(nintr, sizeof(long));
intrnamebuf = (char*) malloc(
namelist[N_EINTRNAMES].n_value - namelist[N_INTRNAMES].n_value );
if( !intrcnts || !intrnames || !intrnamebuf )
errx( 1, "no memory" );
if( kvm_read( kd, namelist[N_INTRNAMES].n_value, intrnamebuf,
namelist[N_EINTRNAMES].n_value - namelist[N_INTRNAMES].n_value )
== 0 )
errx( 1, "kvm_read(intrnamebuf)" );
for( cp = intrnamebuf, i = 0; i < nintr; i++ ) {
char* p1;
intrnames[i] = p1 = cp;
while( p1 && *p1 ) {
if( *p1 == ' ' )
*p1 = '_';
p1++;
}
cp += strlen(cp) + 1;
}
if( kvm_read( kd, namelist[N_INTRCNT].n_value, intrcnts,
nintr*sizeof(long) ) != nintr*sizeof(long) )
errx( 1, "kvm_read(intrcnts)" );
for( i = 0; i < nintr; i++ ) {
if( !intrnames[i] || !intrnames[i][0] )
continue;
snprintf( opos, olim-opos,
" i.%s=%ld", intrnames[i], intrcnts[i] );
opos += strlen( opos );
}
#if 0
printf( "%s\n", obuf );
#else
openlog( "syscounters", LOG_PID, LOG_DAEMON );
syslog( LOG_NOTICE, "%s", obuf );
#endif
return 0;
}
static void
rdtsc( unsigned long* tsc_edx, unsigned long* tsc_eax )
{
asm( "rdtsc" : "=d"(*tsc_edx), "=a"(*tsc_eax) );
}
=== end cut ===
/netch
--- ifmail v.2.15dev5
* Origin: Lucky Netch Incorporated (2:5020/400)