1. 程式人生 > >Linux下C獲取CPU使用率和記憶體和網路丟包率

Linux下C獲取CPU使用率和記憶體和網路丟包率

在Linux中如果要監視一個程序的執行情況,如檢視它的CPU使用效率和記憶體使用情況,就需要從系統的 /proc目錄的讀取一些系統資訊。然後分析得到結果,proc檔案系統是一個偽檔案系統,它只存在記憶體當中,而不佔用外存空間。它以檔案系統的方式為訪問系統核心資料的操作提供介面。使用者和應用程式 可以通過proc得到系統的資訊,並可以改變核心的某些引數。

1、從/proc檔案系統獲取相關的效能引數
cpu使用率:    /proc/stat
記憶體使用情況:      /proc/meminfo
網路負載資訊:    /proc/net/dev

相應的計算方法:(摘自:什麼是proc檔案系統,見參考資料)
(1)   處理器使用率   
(2)   記憶體使用率   
(3)   流入流出資料包   
(4)   整體網路負載   

這些資料分別要從/proc/stat、/proc/net/dev、/proc/meminfo三個檔案中提取。如裡有問題或對要提取的資料不太清楚, 可以使用man   proc來檢視proc檔案系統的聯機手冊。  

(1)   處理器使用率   
這裡要從/proc/stat中提取四個資料:使用者模式(user)、低優先順序的使用者模式(nice)、核心模式(system)以及空閒的處理器時間 (idle)。它們均位於/proc/stat檔案的第一行。CPU的使用率使用如下公式來計算。

在Linux系統中,CPU利用率的計算來源在/proc/stat檔案,這個檔案的頭幾行記錄了每個CPU的使用者態,系統態,空閒態等狀態下的不同的 Jiffies,常用的監控軟體就是利用/proc/stat裡面的這些資料來計算CPU的利用率的。/proc/stat/


[email protected]:~# cat /proc/stat
cpu  2262 0 4387 204441 3670 101 27 0 0
cpu0 2262 0 4387 204441 3670 101 27 0 0

輸出解釋
CPU 每行的每個引數意思(cpu是所有cpu資料和例如cpu0,cpu1,cpu2等等)為:
引數 解釋
user (2662) 從系統啟動開始累計到當前時刻,使用者態的CPU時間(單位:jiffies) ,不包含 nice值為負程序。1jiffies=0.01秒
nice (0) 從系統啟動開始累計到當前時刻,nice值為負的程序所佔用的CPU時間(單位:jiffies)
system (4387) 從系統啟動開始累計到當前時刻,核心時間(單位:jiffies)
idle (204441) 從系統啟動開始累計到當前時刻,除硬碟IO等待時間以外其它等待時間(單位:jiffies)
iowait (3670) 從系統啟動開始累計到當前時刻,硬碟IO等待時間(單位:jiffies) ,
irq (101) 從系統啟動開始累計到當前時刻,硬中斷時間(單位:jiffies)
softirq (27) 從系統啟動開始累計到當前時刻,軟中斷時間(單位:jiffies)

  
CPU使用率 =  100   *(user   +   nice   +   system)/(user   +   nice   +   system   +   idle)

要計算使用者和系統的相對使用率要對/proc/stat資料進行兩次採集,再進行計算

total1 = user1 + nice1 + system1 + idle1 ,total2同理(total1採集時間比total2晚,所以total1> total2)

使用者使用率 = 100 * (user1 - user2)/ (total1 - total2)

系統使用率 = 100 * (system1 - system2)/ (total1 - total2)

(2)   記憶體使用率   

這裡需要從/proc/meminfo檔案中提取兩個資料,當前記憶體的未使用量(MemFree)以及記憶體總量(MemTotal)。   
記憶體使用百分比   =   100   *   ((MemTotal - MemFree)   /  MemTotal)  
 

[email protected]:~# cat /proc/meminfo
MemTotal:         509208 kB
MemFree:           93596 kB

(3)網路利用率   

為了得到網路利用率的相關資料,需要從/proc/net/dev檔案中獲得兩個資料:從本機輸出的資料包數,流入本機的資料包數。它們都位於這個檔案的 第四行。效能收集程式開始記錄下這兩個資料的初始值,以後每次獲得這個值後均減去這個初始值即為從叢集啟動開始從本節點通過的資料包。利用上述資料計算出網路的丟包率,方法如下:   
丟包率   =   (第二次採集總丟包數 - 第一次採集總丟包數)   /   採集時間

Inter-|   Receive                                                |  Transmit
 face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed
    lo:   10732     132    0    0    0     0          0         0    10732     132    0    0    0     0       0          0
  eth0:   33096     179    0    0    0     0          0         0    15743     146    0    0    0     0       0          0

下面是我寫的程式碼,其中用到了定時器30S進行一次資訊採集,最開始獲取cpu對於total使用率,而不是使用者和系統相對的使用率

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#include <time.h>
#include <signal.h>
#include <pthread.h>

static int g_cpu_used_user = 0;		//表示cpu使用者使用率
static int g_cpu_used_system = 0;	//表示cpu系統使用率
static unsigned long cpu_total = 0;	
static unsigned long cpu_user = 0;
static unsigned long cpu_system = 0;//分別cpu總時間,使用者時間,系統時間
static unsigned int mem_free;		//存放未使用記憶體
static unsigned int mem_used;		//存放已使用記憶體
static unsigned int R_bytes = 0;
static unsigned int R_packets = 0;
static short int R_drop = 0;
static unsigned int T_bytes = 0;
static unsigned int T_packets = 0;
static short T_drop = 0;
static short int R_drop_per = 0;	//網路接收丟包率
static short int T_drop_per = 0;	//網路接收丟包率 

struct occupy						//存放cpu資料結構體
{
	char name[20];
	unsigned int user;
	unsigned int nice;
	unsigned int system;
	unsigned int idle;
};

struct mem_occupy					//存放記憶體資料結構體
{
	char name_total[20];
	unsigned int total;
	char name_free[20];
	unsigned int free;
};

struct net_occupy					//存放網口資料結構體
{
	char name[20];
	unsigned int R_bytes;
	unsigned int R_packets;
	unsigned int R_errs;
	unsigned int R_drop;
	unsigned int fifo;
	unsigned int frame;
	unsigned int compressed;
	unsigned int multicast;
	unsigned int T_bytes;
	unsigned int T_packets;
	unsigned int T_errs;
	unsigned int T_drop;
};

int cal_occupy(struct occupy *ncpu);
void get_occupy(struct occupy *ocpu);
int get_cpu_info(void);
int get_mem_info(struct mem_occupy *mem);
int get_net_info(void);
static void get_opera_data(void);
void settimer_get_opera_data(void);


/*******獲取cpu資料,存入靜態全域性變數
g_cpu_used_eser和g_cpu_used_system中*/
int get_cpu_info()
{
	struct occupy cpu;
	get_occupy(&cpu);		//獲取資料存入結構體
	cal_occupy(&cpu);		//根據資料計算cpu使用率
	
	printf("cpu_num = 1 user used:%d system used:%d\n",
			 g_cpu_used_user, g_cpu_used_system);
}

int cal_occupy(struct occupy *ncpu)
{
	unsigned long od,nd;
	unsigned long id,sd;
	od = cpu_total;
	nd = (unsigned long)(ncpu->user + ncpu->nice + ncpu->system + ncpu->idle);
	id = (unsigned long)(ncpu->user - cpu_user);
	sd = (unsigned long)(ncpu->system - cpu_system);
	if ((nd - od) != 0) {
		g_cpu_used_user = (int)(id * 100)/(nd - od);
		g_cpu_used_system = (int)(sd * 100)/(nd - od);
	} else {
		g_cpu_used_user = 0;
		g_cpu_used_system = 0;
	}
	
	//將計算獲得資料儲存
	cpu_total = nd;
	cpu_user = ncpu->user;
	cpu_system = ncpu->system;
	return (1);
}

/*從/proc/stat檔案中提取cpu資料狀態*/
void get_occupy(struct occupy *ocpu)
{
	FILE *fd;
	char buff[256];
	struct occupy *ncpu;
	ncpu = ocpu;

	fd = fopen("/proc/stat", "r");
	if (!fd) {
		perror("cannot open /proc/stat");
		exit(EXIT_FAILURE);
	}

	while(fgets(buff, sizeof(buff), fd)) {
		if(strstr(buff, "cpu") != NULL) {
			sscanf(buff,"%s %u %u %u %u", ncpu->name, &(ncpu->user),
					&(ncpu->nice), &(ncpu->system), &(ncpu->idle));
			break;
		} 
	}
	printf("%u %u %u %u",ncpu->user,ncpu->nice,ncpu->system,ncpu->idle); 	
	fclose(fd);
}

/*從 /proc/meminfo 檔案中提取記憶體資料*/
int get_mem_info(struct mem_occupy *mem)
{
	FILE *fd;
	char buff[256];

	fd = fopen("/proc/meminfo", "r");
	if (!fd) {
		perror("Cannot open /proc/meminfo");
		return(0);
	}
	fgets(buff, sizeof(buff), fd);
	if (strstr(buff, "MemTotal") != NULL) {
		sscanf(buff, "%s %u", mem->name_total, &mem->total);
	} else return(0);
	fgets(buff, sizeof(buff), fd);
	if (strstr(buff, "MemFree") != NULL) {
		sscanf(buff, "%s %u", mem->name_free, &mem->free);
	} else return(0);
	mem_free = mem->free;
	mem_used = mem->total - mem->free;

	printf("mem_free = %u ,mem_used = %u",mem_free,mem_used);
	return (1);
}

/*提取網口資料,計算丟包率*/
int get_net_info()
{
	FILE *fd;
	int i, n = 0;
	char buff[256];
	unsigned int R_bytes_new = 0;
	unsigned int R_packets_new = 0;
	unsigned int R_drop_new = 0;
	unsigned int T_bytes_new = 0;
	unsigned int T_packets_new = 0;
	unsigned int T_drop_new = 0;
	struct net_occupy netinfo[4];

	fd = fopen("/proc/net/dev", "r+");
	if (!fd) {
		perror("Cannot open /proc/net/dev");
		return(0);
	}
	while(fgets(buff, sizeof(buff), fd)) {
		n++;
		if(n > 3) {
			sscanf(buff,"%s %u %u %u %u %u %u %u %u %u %u %u %u",
				netinfo[n-4].name, &netinfo[n-4].R_bytes, &netinfo[n-4].R_packets, 
				&netinfo[n-4].R_errs, &netinfo[n-4].R_drop, &netinfo[n-4].fifo,
				&netinfo[n-4].frame, &netinfo[n-4].compressed, &netinfo[n-4].multicast,
				&netinfo[n-4].T_bytes, &netinfo[n-4].T_packets, &netinfo[n-4].T_errs,
				&netinfo[n-4].T_drop);
		}
	}

	for(i = 0; i < n - 4; i++) {
		R_bytes_new += netinfo[i].R_bytes;
		R_packets_new += netinfo[i].R_packets;
		R_drop_new += netinfo[i].R_drop;
		T_bytes_new += netinfo[i].T_bytes;
		T_packets_new += netinfo[i].T_packets;
		T_drop_new += netinfo[i].T_drop;
	}
	if (0 == (R_packets_new - R_packets)) {
		R_drop_per = 0;
	}
	else 
		R_drop_per = (unsigned short int)((R_drop_new - R_drop)* 100.0 / 
									(R_packets_new - R_packets));
	if (0 == (T_packets_new - T_packets)) {
		T_drop_per = 0;
	}
	else 
		T_drop_per = (unsigned short int)((T_drop_new - T_drop)* 100.0 / 
									(T_packets_new - T_packets));

	printf("R_drop = %u T_drop = %u\n",R_drop_per,T_drop_per);
	R_bytes = R_bytes_new;
	R_drop = R_drop_new;
	R_packets = R_packets_new;
	T_bytes = T_bytes_new;
	T_drop = T_drop_new;
	T_packets = T_packets_new;
	return(1);
}

static void get_opera_data(void)
{	
	struct mem_occupy mem;
	get_cpu_info();
	get_mem_info(&mem);
	get_net_info();
} 

void settimer_get_opera_data(void)
{
	struct sigevent se;
	struct itimerspec ts, ots;
	timer_t tid;

	memset(&se, 0, sizeof(se));
	se.sigev_notify = SIGEV_THREAD;
	se.sigev_notify_function = get_opera_data;//定時執行函式,獲取運維資料
	se.sigev_value.sival_int = 0;
	if (timer_create(CLOCK_REALTIME, &se, &tid) < 0) {
		perror("timer_creat of operation and maintenance\n");
	}
	ts.it_value.tv_sec = 28;
	ts.it_value.tv_nsec = 0;
	ts.it_interval = ts.it_value;
	if (timer_settime(tid, 0, &ts, &ots) < 0) {
		perror("time_settime of operation and maintenance\n");
	}
}

int main()
{
	get_opera_data();
	settimer_get_opera_data();
	while(1);
	return(1);
}


相關推薦

LinuxC獲取CPU使用率記憶體網路

在Linux中如果要監視一個程序的執行情況,如檢視它的CPU使用效率和記憶體使用情況,就需要從系統的 /proc目錄的讀取一些系統資訊。然後分析得到結果,proc檔案系統是一個偽檔案系統,它只存在記憶體當中,而不佔用外存空間。它以檔案系統的方式為訪問系統核心資料的操作提供介

Linuxjava獲取CPU記憶體、磁碟IO、網路頻寬使用率

原文地址:https://www.cnblogs.com/gisblogs/p/3985393.html 一、CPU 使用proc檔案系統,"proc檔案系統是一個偽檔案系統,它只存在記憶體當中,而不佔用外存空間。它以檔案系統的方式為訪問系統核心資料的操作提供介面。使用者和應用程式可以通過p

Linux c獲取當前時間(精確到秒毫秒或者微秒)

獲取當前的時間的秒數和微秒數本方法需要用到gettimeofday()函式,該函式需要引入的標頭檔案是sys/time.h 。 函式說明int gettimeofday (struct timeval * tv, struct timezone * tz)

Linuxjava獲取CPU記憶體、磁碟IO、網路IO

獲取linux命令執行結果 下面的程式碼用於獲取執行一個Linux命令之後的結果,函式返回一個字串,即命令的執行結果 import java.io.IOException; import java.io.InputStreamReader; i

linuxC獲取文件的大小

錯誤代碼 返回 system sys string 文件系統 識別碼 連接 chm 獲取文件大小這裏有兩種方法: 方法一、 範例: unsigned long get_file_size(const char *path) { unsigned lo

LinuxC程式動態庫的生成呼叫

Linux下C程式動態庫的生成和呼叫 文章目錄 Linux下C程式動態庫的生成和呼叫 1 動態庫的打包和呼叫 2 靜態庫打包和呼叫 3 常用命令 4 gcc 和 g++ 區別 5 編譯和連結的理解

linuxC獲取系統時間的方法

asctime(將時間和日期以字串格式表示)   相關函式  time,ctime,gmtime,localtime   表頭檔案  #include<time.h>   定義函式  char * asctime(const struct tm * ti

LinuxC獲取所有可用網絡卡資訊

在Linux下開發網路程式時,經常會遇到需要取本地網路介面名、IP、廣播地址、子網掩碼或者MAC地址等資訊的需求,最常見的辦法是配合巨集SIOCGIFHWADDR、SIOCGIFADDR、SIOCGIFBRDADDR與SIOCGIFNETMASK作為引數呼叫函式

Qt linux獲取cpu使用率、記憶體網路收發速度、磁碟讀寫速度、磁碟剩餘空間等

#include "resource_minitor.h" #include "sys/statfs.h" resource_minitor::resource_minitor(QObject *parent) : QObject(parent) { connect(&monito

LinuxC程式設計-----IO/檔案操作/記憶體對映 實現簡單記錄儲存(3)

利用linux下的檔案記憶體對映可以實現程序共享資料,我們可以把一個檔案對映到虛擬記憶體中使多個程序進行共享, 到這裡我們大概能想到他能應用到的領域 是很廣泛的  主要涉及到 mmap  munmap   msync 三個函式的應用 下面貼程式碼  下面一段程式碼是為檔案

linuxC獲取檔案的大小

stat(取得檔案狀態)    相關函式     fstat,lstat,chmod,chown,readlink,utime 表頭檔案     #include <sys/stat.h>#include <unistd.h> 定義函式     int   stat(const   c

獲取CPU利用率 系統記憶體程序記憶體

#include <iostream> #include <windows.h> #include <Psapi.h> using namespace std; __int64 CompareFileTime(FILETIME t1,FILETIME t2) { _

linuxc++獲取程序號

如何在linux下通過c++程式獲取ps -ef | grep “****” 的執行結果,並分解其中的程序號,廢話少說,直接上程式碼:   [cpp] view plain copy

httping監控網路/延時/狀態

web介面新增監控專案 型別: Zabbix客戶端 鍵值:如下 httping.status[failed,www.baidu.com,443,https] httping.status[max,www.baidu.com,443,https] httping.stat

linuxc語言獲取當前時間

keyword spa pre urn markdown view 技術分享 時間 tle 和時間有關的函數定義在頭文件”time.h”中 常用函數: time_t time(time_t *t); 函數說明:此函數會返回從公元 1970 年1 月1 日的UTC

LinuxC語言獲取本機IP地址

#include <sys/ioctl.h> #include <net/if.h> #include <arpa/inet.h>   char* GetLocalIp() { int MA

Linux C語言 open() fopen() 區別

fopen() #include <stdio.h> FILE *fopen(const char *path, const char *mode); mode 指定檔案的開啟模式: r:只讀方式開啟一個文字檔案(該檔案必須存在) r+:可讀可寫方式開啟一個文字檔案(該檔

linuxC/C++網路程式設計基本:socket實現tcpudp的例子

簡單的linux下socket程式設計,分別基於TCP和UDP協議實現的簡單程式 linux下socket程式設計可以概括為以下幾個函式的運用: socket() bind() listen

LinuxC語言實現獲取當前時間

C語言獲取當前時間 簡介 在工作中,經常涉及到獲取當前時間,用於寫日誌,基於此,今特意利用C語言寫一個獲取時間函式,用於後面用到時,能夠及時查到。獲取當前時間,要用到time.h中的time()和localtime()函式,二者具體介紹與使用,參見 ht

linux c 編譯除錯

警告資訊:   -Wall : 顯示所有常用的編譯警告資訊。 -W    : 顯示更多的常用編譯警告,如:變數未使用、一些邏輯錯誤。 -Wconversion : 警告隱式型別轉換。 -Wshadow : 警告影子變數(在程式碼塊中再次宣告已宣告的變數) -Wcast-qual :警告指標修改了變數的修