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

📄 sysinfo.c

📁 linux下获取一些环境信息的代码
💻 C
📖 第 1 页 / 共 3 页
字号:
// Copyright (C) 1992-1998 by Michael K. Johnson, johnsonm@redhat.com// Copyright 1998-2003 Albert Cahalan//// This file is placed under the conditions of the GNU Library// General Public License, version 2, or any later version.// See file COPYING for information on distribution conditions.//// File for parsing top-level /proc entities. *///// June 2003, Fabian Frederick, disk and slab info#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include <locale.h>#include <unistd.h>#include <fcntl.h>#include "version.h"#include "sysinfo.h" /* include self to verify prototypes */#ifndef HZ#include <netinet/in.h>  /* htons */#endiflong smp_num_cpus;     /* number of CPUs */#define BAD_OPEN_MESSAGE					\"Error: /proc must be mounted\n"				\"  To mount /proc at boot you need an /etc/fstab line like:\n"	\"      /proc   /proc   proc    defaults\n"			\"  In the meantime, run \"mount /proc /proc -t proc\"\n"#define STAT_FILE    "/proc/stat"static int stat_fd = -1;#define UPTIME_FILE  "/proc/uptime"static int uptime_fd = -1;#define LOADAVG_FILE "/proc/loadavg"static int loadavg_fd = -1;#define MEMINFO_FILE "/proc/meminfo"static int meminfo_fd = -1;#define VMINFO_FILE "/proc/vmstat"static int vminfo_fd = -1;static char buf[1024];/* This macro opens filename only if necessary and seeks to 0 so * that successive calls to the functions are more efficient. * It also reads the current contents of the file into the global buf. */#define FILE_TO_BUF(filename, fd) do{				\    static int local_n;						\    if (fd == -1 && (fd = open(filename, O_RDONLY)) == -1) {	\	fputs(BAD_OPEN_MESSAGE, stderr);			\	fflush(NULL);						\	_exit(102);						\    }								\    lseek(fd, 0L, SEEK_SET);					\    if ((local_n = read(fd, buf, sizeof buf - 1)) < 0) {	\	perror(filename);					\	fflush(NULL);						\	_exit(103);						\    }								\    buf[local_n] = '\0';					\}while(0)/* evals 'x' twice */#define SET_IF_DESIRED(x,y) do{  if(x) *(x) = (y); }while(0)/***********************************************************************/int uptime(double *restrict uptime_secs, double *restrict idle_secs) {    double up=0, idle=0;    char *restrict savelocale;    FILE_TO_BUF(UPTIME_FILE,uptime_fd);    savelocale = setlocale(LC_NUMERIC, NULL);    setlocale(LC_NUMERIC,"C");    if (sscanf(buf, "%lf %lf", &up, &idle) < 2) {        setlocale(LC_NUMERIC,savelocale);        fputs("bad data in " UPTIME_FILE "\n", stderr);	    return 0;    }    setlocale(LC_NUMERIC,savelocale);    SET_IF_DESIRED(uptime_secs, up);    SET_IF_DESIRED(idle_secs, idle);    return up;	/* assume never be zero seconds in practice */}/*********************************************************************** * Some values in /proc are expressed in units of 1/HZ seconds, where HZ * is the kernel clock tick rate. One of these units is called a jiffy. * The HZ value used in the kernel may vary according to hacker desire. * According to Linus Torvalds, this is not true. He considers the values * in /proc as being in architecture-dependant units that have no relation * to the kernel clock tick rate. Examination of the kernel source code * reveals that opinion as wishful thinking. * * In any case, we need the HZ constant as used in /proc. (the real HZ value * may differ, but we don't care) There are several ways we could get HZ: * * 1. Include the kernel header file. If it changes, recompile this library. * 2. Use the sysconf() function. When HZ changes, recompile the C library! * 3. Ask the kernel. This is obviously correct... * * Linus Torvalds won't let us ask the kernel, because he thinks we should * not know the HZ value. Oh well, we don't have to listen to him. * Someone smuggled out the HZ value. :-) * * This code should work fine, even if Linus fixes the kernel to match his * stated behavior. The code only fails in case of a partial conversion. * * Recent update: on some architectures, the 2.4 kernel provides an * ELF note to indicate HZ. This may be for ARM or user-mode Linux * support. This ought to be investigated. Note that sysconf() is still * unreliable, because it doesn't return an error code when it is * used with a kernel that doesn't support the ELF note. On some other * architectures there may be a system call or sysctl() that will work. */unsigned long long Hertz;static void old_Hertz_hack(void){  unsigned long long user_j, nice_j, sys_j, other_j;  /* jiffies (clock ticks) */  double up_1, up_2, seconds;  unsigned long long jiffies;  unsigned h;  char *restrict savelocale;  savelocale = setlocale(LC_NUMERIC, NULL);  setlocale(LC_NUMERIC, "C");  do{    FILE_TO_BUF(UPTIME_FILE,uptime_fd);  sscanf(buf, "%lf", &up_1);    /* uptime(&up_1, NULL); */    FILE_TO_BUF(STAT_FILE,stat_fd);    sscanf(buf, "cpu %Lu %Lu %Lu %Lu", &user_j, &nice_j, &sys_j, &other_j);    FILE_TO_BUF(UPTIME_FILE,uptime_fd);  sscanf(buf, "%lf", &up_2);    /* uptime(&up_2, NULL); */  } while((long long)( (up_2-up_1)*1000.0/up_1 )); /* want under 0.1% error */  setlocale(LC_NUMERIC, savelocale);  jiffies = user_j + nice_j + sys_j + other_j;  seconds = (up_1 + up_2) / 2;  h = (unsigned)( (double)jiffies/seconds/smp_num_cpus );  /* actual values used by 2.4 kernels: 32 64 100 128 1000 1024 1200 */  switch(h){  case    9 ...   11 :  Hertz =   10; break; /* S/390 (sometimes) */  case   18 ...   22 :  Hertz =   20; break; /* user-mode Linux */  case   30 ...   34 :  Hertz =   32; break; /* ia64 emulator */  case   48 ...   52 :  Hertz =   50; break;  case   58 ...   61 :  Hertz =   60; break;  case   62 ...   65 :  Hertz =   64; break; /* StrongARM /Shark */  case   95 ...  105 :  Hertz =  100; break; /* normal Linux */  case  124 ...  132 :  Hertz =  128; break; /* MIPS, ARM */  case  195 ...  204 :  Hertz =  200; break; /* normal << 1 */  case  253 ...  260 :  Hertz =  256; break;  case  393 ...  408 :  Hertz =  400; break; /* normal << 2 */  case  790 ...  808 :  Hertz =  800; break; /* normal << 3 */  case  990 ... 1010 :  Hertz = 1000; break; /* ARM */  case 1015 ... 1035 :  Hertz = 1024; break; /* Alpha, ia64 */  case 1180 ... 1220 :  Hertz = 1200; break; /* Alpha */  default:#ifdef HZ    Hertz = (unsigned long long)HZ;    /* <asm/param.h> */#else    /* If 32-bit or big-endian (not Alpha or ia64), assume HZ is 100. */    Hertz = (sizeof(long)==sizeof(int) || htons(999)==999) ? 100UL : 1024UL;#endif    fprintf(stderr, "Unknown HZ value! (%d) Assume %Ld.\n", h, Hertz);  }}// same as:   euid != uid || egid != gid#ifndef AT_SECURE#define AT_SECURE      23     // secure mode boolean (true if setuid, etc.)#endif#ifndef AT_CLKTCK#define AT_CLKTCK       17    // frequency of times()#endif#define NOTE_NOT_FOUND 42//extern char** environ;/* for ELF executables, notes are pushed before environment and args */static unsigned long find_elf_note(unsigned long findme){  unsigned long *ep = (unsigned long *)environ;  while(*ep++);  while(*ep){    if(ep[0]==findme) return ep[1];    ep+=2;  }  return NOTE_NOT_FOUND;}int have_privs;static int check_for_privs(void){  unsigned long rc = find_elf_note(AT_SECURE);  if(rc==NOTE_NOT_FOUND){    // not valid to run this code after UID or GID change!    // (if needed, may use AT_UID and friends instead)    rc = geteuid() != getuid() || getegid() != getgid();  }  return !!rc;}static void init_libproc(void) __attribute__((constructor));static void init_libproc(void){  have_privs = check_for_privs();  // ought to count CPUs in /proc/stat instead of relying  // on glibc, which foolishly tries to parse /proc/cpuinfo  //  // SourceForge has an old Alpha running Linux 2.2.20 that  // appears to have a non-SMP kernel on a 2-way SMP box.  // _SC_NPROCESSORS_CONF returns 2, resulting in HZ=512  // _SC_NPROCESSORS_ONLN returns 1, which should work OK  smp_num_cpus = sysconf(_SC_NPROCESSORS_ONLN);  if(smp_num_cpus<1) smp_num_cpus=1; /* SPARC glibc is buggy */  if(linux_version_code > LINUX_VERSION(2, 4, 0)){     Hertz = find_elf_note(AT_CLKTCK);    if(Hertz!=NOTE_NOT_FOUND) return;    fputs("2.4+ kernel w/o ELF notes? -- report this\n", stderr);  }  old_Hertz_hack();}#if 0/*********************************************************************** * The /proc filesystem calculates idle=jiffies-(user+nice+sys) and we * recover jiffies by adding up the 4 or 5 numbers we are given. SMP kernels * (as of pre-2.4 era) can report idle time going backwards, perhaps due * to non-atomic reads and updates. There is no locking for these values. */#ifndef NAN#define NAN (-0.0)#endif#define JT unsigned long longvoid eight_cpu_numbers(double *restrict uret, double *restrict nret, double *restrict sret, double *restrict iret, double *restrict wret, double *restrict xret, double *restrict yret, double *restrict zret){    double tmp_u, tmp_n, tmp_s, tmp_i, tmp_w, tmp_x, tmp_y, tmp_z;    double scale;  /* scale values to % */    static JT old_u, old_n, old_s, old_i, old_w, old_x, old_y, old_z;    JT new_u, new_n, new_s, new_i, new_w, new_x, new_y, new_z;    JT ticks_past; /* avoid div-by-0 by not calling too often :-( */    tmp_w = 0.0;    new_w = 0;    tmp_x = 0.0;    new_x = 0;    tmp_y = 0.0;    new_y = 0;    tmp_z = 0.0;    new_z = 0;     FILE_TO_BUF(STAT_FILE,stat_fd);    sscanf(buf, "cpu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu", &new_u, &new_n, &new_s, &new_i, &new_w, &new_x, &new_y, &new_z);    ticks_past = (new_u+new_n+new_s+new_i+new_w+new_x+new_y+new_z)-(old_u+old_n+old_s+old_i+old_w+old_x+old_y+old_z);    if(ticks_past){      scale = 100.0 / (double)ticks_past;      tmp_u = ( (double)new_u - (double)old_u ) * scale;      tmp_n = ( (double)new_n - (double)old_n ) * scale;      tmp_s = ( (double)new_s - (double)old_s ) * scale;      tmp_i = ( (double)new_i - (double)old_i ) * scale;      tmp_w = ( (double)new_w - (double)old_w ) * scale;      tmp_x = ( (double)new_x - (double)old_x ) * scale;      tmp_y = ( (double)new_y - (double)old_y ) * scale;      tmp_z = ( (double)new_z - (double)old_z ) * scale;    }else{      tmp_u = NAN;      tmp_n = NAN;      tmp_s = NAN;      tmp_i = NAN;      tmp_w = NAN;      tmp_x = NAN;      tmp_y = NAN;      tmp_z = NAN;    }    SET_IF_DESIRED(uret, tmp_u);    SET_IF_DESIRED(nret, tmp_n);    SET_IF_DESIRED(sret, tmp_s);    SET_IF_DESIRED(iret, tmp_i);    SET_IF_DESIRED(wret, tmp_w);    SET_IF_DESIRED(xret, tmp_x);    SET_IF_DESIRED(yret, tmp_y);    SET_IF_DESIRED(zret, tmp_z);    old_u=new_u;    old_n=new_n;    old_s=new_s;    old_i=new_i;    old_w=new_w;    old_x=new_x;    old_y=new_y;    old_z=new_z;}#undef JT#endif

⌨️ 快捷键说明

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