Linux kernel experiment (1): proc file system

I. Introduction

The Proc file system provides users with the current state of the system in the form of a file system, and dynamically reads the required information from the same kernel, which only exists in the memory and does not occupy external memory space.

2. Experimental content

Question A:
1. cpu type
2, kernel version

Question B:
1. The time since the system was started, reported as dd:hh:mm:ss

Question C:
1. How long does it take for the CPU to execute user mode, system mode, and idle state
? 2. How many disk requests
? 3. How many context switches?
4. How many processes are started

Question D:
1. Total memory
2. Available memory
3. System load average

3. Experimental code

/*****************************************
*
* Proc 文件系统
*
* Copyright: (C) 2018.3.31 by shaomingshan
*
* Compile: gcc -o main main.c
*
* Execute: ./main -a
*
*****************************************/
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#define LB_SIZE 80

enum TYPE{STANDARD,SHORT,LONG};
FILE *thisProcFile; //Proc 打开文件指针
struct timeval now; //系统时间日期
enum TYPE reportType; //观察报告类型
char repTypeName[16];
char *lineBuf; //proc 文件读出行缓冲
int interval; //系统负荷监测时间间隔
int duration; //系统负荷监测时段
int iteration;
char c1,c2; //字符处理单元

void sampleLoadAvg() { //观察系统负荷
    int i=0;
    //打开负荷文件
    if ((thisProcFile = fopen("/proc/loadavg", "r")) == NULL)
    {
        printf("Open Failed\n");
        return;
    }
    //读出、处理读出行,如去除前导空格和无用空格
    fgets(lineBuf, LB_SIZE+1, thisProcFile);
    char * c3 = strtok(lineBuf, " ");
    //将读出行分出不同字段,按照字段的不同含义处理为可阅读格式
    //打印处理好的信息内容
    while (c3 != NULL) {
        i ++;
        switch (i) {
            case 1:
                printf("1分钟内平均负载: ");
                break;
            case 2:
                printf("5分钟内平均负载: ");
                break;
            case 3:
                printf("15分钟内平均负载: ");
                break;
            case 4:
                printf("活动进程比: ");
                break;
            case 5:
                printf("最近进程号: ");
                break;
        }
        printf("%s\n", c3);
        c3 = strtok(NULL, " ");
    }
    fclose(thisProcFile);
}

void sampleTime() {//观察系统启动时间
    long uptime,idletime;
    int day,hour,minute,second;
    int i,j;
    char temp[80];
    i=j=0;
    //打开计时文件
    //读出、处理读出行,如去除前导空格和无用空格
    thisProcFile = fopen("/proc/uptime", "r");
    fgets(lineBuf, LB_SIZE+1, thisProcFile);
    //将读出行分出不同字段,按照字段的不同含义处理为可阅读格式
    //将启动时间的秒数转换为长整数
    uptime = atol(strtok(lineBuf, " "));
    //转换成日时钟秒
    day = uptime/3600/24;
    hour = uptime/3600%24;
    minute = uptime/60%60;
    second = uptime%60;
    //打印处理好的信息内容
    printf("uptime: %2ldd:%2ldh:%2ldm:%2lds\n",
            day, hour, minute, second);
    //将启动时间的空闲秒数转换为长整数
    idletime = atol(strtok(NULL, " "));
    //转换成日时钟秒
    day = idletime/3600/24;
    hour = idletime/3600%24;
    minute = idletime/60%60;
    second = idletime%60;
    //打印处理好的信息内容
    printf("idletime: %2ldd:%2ldh:%2ldm:%2lds\n",
            day, hour, minute, second);
}

int main(int argc,char *argv[])
{
    lineBuf = (char *)malloc(LB_SIZE+1);
    reportType = STANDARD;
    strcpy(repTypeName,"Standard");
    if(argc >1){
        sscanf(argv[1],"%c%c",&c1,&c2);//取命令行选择符
        if(c1!='-'){ //提示本程序命令参数的用法
            exit(1);
        }
        if(c2 == 'a'){
            //观察部分 A
            printf("**********PART A **********\n");
            reportType = SHORT;
            strcpy(repTypeName,"Short");
            //取出并显示系统当前时间
            //读出并显示机器名
            //读出并显示全部 CPU 信息
            //读出并显示系统版本信息
            thisProcFile = fopen("/proc/cpuinfo", "r");
            while (!feof(thisProcFile)) {
                fgets(lineBuf, LB_SIZE+1, thisProcFile);
                if (strstr(lineBuf, "model name")) {
                    printf("%s", lineBuf);
                    break;
                }
            }
            fclose(thisProcFile);
            system("uname -r");
        }
        else if(c2 == 'b'){
            //观察部分 B
            printf("**********PART B **********\n");
            //打开内存信息文件
            //读出文件全部的内容
            //处理并用方便阅读的格式显示
            //观察系统启动时间
            sampleTime();
        }
        else if(c2 == 'c'){
            //观察部分 C
            printf("**********PART C**********\n");
            //打开系统状态信息文件
            thisProcFile = fopen("/proc/stat", "r");
            //读出文件全部的内容
            //处理并用方便阅读的格式显示
            fgets(lineBuf, LB_SIZE+1, thisProcFile);
            while (!feof(thisProcFile)) {
                char *output = strtok(lineBuf, " ");
                if (!strcmp(output, "cpu")) {
                    int i = 0;
                    while (i < 4) {
                        output = strtok(NULL, " ");
                        switch (i) {
                            case 0:
                                printf("用户态时间: %s\n", output);
                                break;
                            case 1:
                                break;
                            case 2:
                                printf("系统态时间: %s\n", output);
                                break;
                            case 3:
                                printf("空闲态时间: %s\n", output);
                                break;
                        }
                        i++;
                    }
                } else if (!strcmp(output, "intr")) {
                    output = strtok(NULL, " ");
                    printf("磁盘请求: %s\n", output);
                } else if (!strcmp(output, "ctxt")) {
                    output = strtok(NULL, " ");
                    printf("上下文切换: %s\n", output);
                } else if (!strcmp(output, "processes")) {
                    output = strtok(NULL, " ");
                    printf("启动进程数: %s\n", output);
                }
                fgets(lineBuf, LB_SIZE+1, thisProcFile);
            }   
            fclose(thisProcFile);
        }
        else if(c2 == 'd'){
            //观察部分 D
            printf("**********PART D **********\n");
            if(argc<4){
                printf("usage:observer [-b] [-c][-d int dur]\n");
                exit(1);
            }
            thisProcFile = fopen("/proc/meminfo", "r");
            int i = 0;
            // 内存信息文件
            while (i++ < 3) {
                fgets(lineBuf, LB_SIZE+1, thisProcFile);
                strtok(lineBuf, " ");
                char *output = strtok(NULL, " ");
                switch (i) {
                    case 1:
                        printf("总内存: ");
                        break;
                    case 2:
                        printf("空闲内存:");
                        break;
                    case 3:
                        printf("可用内存:");
                }
                printf("%s\n", output);
            }
            fclose(thisProcFile);
            reportType = LONG;
            strcpy(repTypeName,"Long");
            //用命令行参数指定的时间段和时间间隔连续的
            interval = atol(argv[2]);
            duration = atol(argv[3]);
            //读出系统负荷文件的内容用方便阅读的格式显示
            for (int i = 0; i < duration / interval; ++i) {
                sampleLoadAvg();
                // 系统负荷信息
                sleep(interval);
            }
        }
    }
}

4. Operation results

write picture description here
write picture description here
write picture description here
write picture description here

Please correct me if there is any mistake

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325952452&siteId=291194637