操作系统-用Linux下基于文本的终端图形编程库curses,分窗口实时监测(即周期性刷新显示)CPU、内存和网络的详细使用情况和它们的利用率,每个进程监控一个设备
代码
//
#include<curses.h>
#include<time.h>
#include<string.h>
#include<sys/wait.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<stdio.h>
#include<sys/types.h>
#include<stdlib.h>
#include<sys/sem.h>
#include<sys/ipc.h>
#include<sys/shm.h>
int main()
{
pid_t pid1,pid2,pid3;
unsigned int receive0,send0;
initscr();
refresh();
WINDOW *wp1,*wp2,*wp3;
wp3=subwin(stdscr,LINES,COLS/3,0,0);
wp2=subwin(stdscr,LINES,COLS/3,0,COLS/3);
wp1=subwin(stdscr,LINES,COLS/3,0,COLS/3*2);
if(start_color()==OK)
{
box(wp1,ACS_VLINE,ACS_HLINE);
box(wp2,ACS_VLINE,ACS_HLINE);
box(wp3,ACS_VLINE,ACS_HLINE);
touchwin(stdscr);
init_pair(1,COLOR_BLUE,COLOR_WHITE);
wattron(wp1,COLOR_PAIR(1));
init_pair(2,COLOR_BLUE,COLOR_WHITE);
wattron(wp2,COLOR_PAIR(2));
init_pair(3,COLOR_BLUE,COLOR_WHITE);
wattron(wp3,COLOR_PAIR(3));
int sum0,i;
FILE *fp2;
char buf2[256];
char ch[20];
unsigned int receive1,send1;
float usage5;
fp2=fopen("/proc/net/dev","r");
if(fp2==NULL)
{
perror("fopen");
exit(0);
}
fgets(buf2,sizeof(buf2),fp2);
fgets(buf2,sizeof(buf2),fp2);
fgets(buf2,sizeof(buf2),fp2);
fgets(buf2,sizeof(buf2),fp2);
sscanf(buf2,"%s,%u,%u",ch,&send0,&receive0);
fclose(fp2);
if(0==(pid1=fork()))
{
while(1)
{
fp2=fopen("/proc/net/dev","r");
rewind(fp2);
sleep(1);
memset(buf2,0,sizeof(buf2));
ch[0]='\0';
fgets(buf2,sizeof(buf2),fp2);
fgets(buf2,sizeof(buf2),fp2);
fgets(buf2,sizeof(buf2),fp2);
fgets(buf2,sizeof(buf2),fp2);
sscanf(buf2,"%s,%u,%u",ch,&send1,&receive1);
wmove(wp1,LINES/2,1);
wprintw(wp1,"current send:%u\n",send1-send0);
wprintw(wp1,"current receive:%u\n",receive1-receive0);
usage5=(float)((send1-send0)+(receive1-receive0))/2;
wprintw(wp1,"average net load:%.2f\n",usage5);
box(wp1,ACS_VLINE,ACS_HLINE);
wrefresh(wp1);
fclose(fp2);
}
}
else if(0==(pid2=fork()))
{
FILE *fp1;
char buf1[256];
char name1[20];
char name2[20];
unsigned long MemT,MemF;
float usage3,usage4;
while(1)
{
fp1=fopen("/proc/meminfo","r");
if(fp1==NULL)
{
perror("fopen");
exit(0);
}
fgets(buf1,sizeof(buf1),fp1);
sscanf(buf1,"%s %lu %s",name1,&MemT,name2);
fgets(buf1,sizeof(buf1),fp1);
sscanf(buf1,"%s %lu %s",name2,&MemF,name2);
wmove(wp2,LINES/2,0);
wprintw(wp2,"current memF:%lu\n",MemF);
wprintw(wp2,"current memT:%lu\n",MemT);
usage3=(float)MemF/100;
usage4=(float)MemT/100;
usage3=(double)(1-(usage3/usage4))*100;
wprintw(wp2,"current Mem use:%.2f\n",usage3);
box(wp2,ACS_VLINE,ACS_HLINE);
fclose(fp1);
sleep(2);
wrefresh(wp2);
}
}
else if(0==(pid3=fork()))
{
FILE *fp;
char buf[256];
char cpu[5];
long user,nice,sys,idle;
long a111,a112,idle1,idle2;
float usage,usage1,usage2;
while(1)
{
fp=fopen("/proc/stat","r");
if(fp==NULL)
{
perror("fopen:");
exit(0);
}
fgets(buf,sizeof(buf),fp);
sscanf(buf,"%s %ld %ld %ld %ld",cpu,&user,&nice,&sys,&idle);
wmove(wp3,LINES/2,1);
wprintw(wp3,"current cpu:%ld,%ld,%ld,%ld\n",user,nice,sys,idle);
a111=(user+nice+idle)/100;
idle1=idle/100;
rewind(fp);
sleep(1);
memset(buf,0,sizeof(buf));
cpu[0]='\0';
user=nice=sys=idle=0;
fgets(buf,sizeof(buf),fp);
sscanf(buf,"%s %ld %ld %ld %ld",cpu,&user,&nice,&sys,&idle);
a112=(user+nice+sys+idle)/100;
idle2=idle/100;
usage1=(float)(a111-idle1)/a111*100;
usage2=(float)(a112-idle2)/a112*100;
usage=(usage1+usage2)/2;
wprintw(wp3,"current cpu use:%.2f%%\n",usage);
box(wp3,ACS_VLINE,ACS_HLINE);
fclose(fp);
sleep(3);
wrefresh(wp3);
}
}
waitpid(pid1,NULL,0);
waitpid(pid2,NULL,0);
waitpid(pid3,NULL,0);
wattroff(wp1,COLOR_PAIR(1));
wattroff(wp2,COLOR_PAIR(2));
wattroff(wp3,COLOR_PAIR(3));
refresh();
getch();
}
else
{
waddstr(stdscr,"Can not init color");
refresh();
getch();
}
getch();
endwin();
return 0;
}
运行截图
分析设计
分屏展示游标集打印的内容,以及读取最初的网络状态(设备收发包相关的数据)。
创建三个子进程,分别获取以下内容:
- /proc/net/dev读取网络设备收发包时相关的数据
- /proc/meminfoLinux系统内存使用状况的主要接口,即内存使用情况和利用率
- /proc/stat获取所有CPU活动的信息,即CPU使用情况和利用率
然后子进程1,还需要计算平均负载;子进程2,监控内存使用情况和利用率;子进程3,获取两次求平均值。
程序解释
首先代码要求在屏幕上显示三个窗口,分别用来显示网络发送和接收数据、内存使用情况以及CPU利用率信息。
再获取最初的网络状态,以便后面计算,
子进程1,每秒读取一次网络发送和接收的数据,计算参数变化量,并求均值,即平均负载;
子进程2,每隔两秒读取一次内存使用情况;
子进程3,每隔三秒读取一次CPU利用率。
出现的问题
- 出现什么找不到目录或者文件
此时 gcc -o 生成文件名 编译的.c -l curses
这里的-l 和curses分开
当然记得安装curses库
sudo apt-get install libncurses5-dev
声明
如果有错误请联系我,谢谢。