Linux內核實驗(一):proc文件系統

一、引言

Proc文件系統,以文件系統的形式向用戶提供系統當前狀態,動態地從同內核中讀出所需的信息,只存在內存中,不佔用外存空間。

二、實驗內容

問題A:
1、cpu類型
2、內核版本

問題B:
1、系統啓動以來的時間,以dd:hh:mm:ss報告

問題C:
1、cpu執行用戶態、系統態、空閒態所用時間
2、多少次磁盤請求
3、多少次上下文切換
4、啓動了多少次進程

問題D:
1、內存總量
2、可用內存
3、系統平均負荷

三、實驗代碼

/*****************************************
*
* 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);
            }
        }
    }
}

四、運行結果

這裏寫圖片描述
這裏寫圖片描述
這裏寫圖片描述
這裏寫圖片描述

如有錯誤請指正

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章