实验二 观察Linux,使用proc文件系统
实验目的:学习Linux内核、进程、存储和其他资源的一些重要特征。读/proc/stat文件,计算并显示系统CPU占用率和用户态CPU占用率。(编写一个程序使用/proc机制获得以及修改机器的各种资源参数。需要使用fopen(),fscanf(),printf())
2.1 介绍
Linux操作系统提供了一套非常有用的在用户态检查内核状态的机制——/proc文件系统。在该文件系统将 进程的地址空间,系统的硬件信息(包括CUP、内存状态以及网卡等各种硬件设备)以及操作系统系统(中断、IO)等内容全部设置成虚拟的Linux文件——它只存在内存当中,而不占用外存空间。它以文件系统的方式为访问系统内核数据的操作提供接口。
/proc 中的每个文件都有一组分配给它的非常特殊的文件许可权,并且每个文件属于特定的用户标识,这里面的文件仅仅包含以下三种权限(除非root用户特别授权):
1. 只读:任何用户都不能更改该文件;它用于表示系统信息;
2. root 写:如果 /proc 中的某个文件是可写的,则通常只能由 root 用户来写;
3. root 读:有些文件对一般系统用户是不可见的,而只对 root 用户是可见的;
4. 其它:出于各种原因,您可能会看到不同于上面常见的三种许可权的组合。
当然,除了/proc/sys目录以外,其余大部分目录下的文件对于root用户是只读的,该目录下存放的是内核参数,并被设计成为运行时刻修改的。
以下列出了/proc文件系统各个子目录的内容:
目录名 | 内容描述 |
---|---|
apm | 高级电源管理信息 |
cmdline | 内核命令行 |
cpuinfo | cup信息 |
devices | 可用的设备信息 |
dma | 已经使用的 DMA 管道 |
filesystems | 系统支持的文件系统 |
interrupts | 中断信息 |
ioports | 端口使用信息 |
kcore | 内核核心映像 |
kmsg | 内核消息 |
ksyms | 内核符号表 |
loadavg | 平均负载 |
locks | 内核锁 |
meminfo | 内存信息 |
misc | misc信息 |
modules | 内核加载模块列表 |
mounts | 已加载文件信息 |
partitions | 系统识别的分区表 |
rtc | 实时锁 |
slab | slab 对象池的信息 |
stat | 全面信息统计状态表 |
swaps | 交换分区使用情况 |
version | 内核版本 |
uptime | 系统正常运行时间 |
sys | 内核参数 |
并不是所有的目录在你的系统中都有,这取决于你内核的配置和装载的模块。另外,/proc目录下还有两个很重要的目录:net和scsi,均依赖于内核的配置。例如,如果你的系统不支持sici设备则sici目录不存在。
除此之外,你还会发现一些以数字命名的目录,它们是进程目录。系统中当前运行的每一个进程都有一个对应的目录在/proc下,以进程的ID号为目录名,他们就是读取进程信息的接口。每个进程目录的结构如下:
子目录名称 | 包含内容 |
---|---|
cmdline | 该进程的命令行参数 |
enviroment | 进程换进变量的值 |
fd | 该进程所打开的文件的描述符 |
mem | 该进程的内存使用情况 |
stat | 进程状态 |
cwd | 进程的当前目录 |
root | 进程的根目录 |
maps | 内存映像 |
statm | 进程内存状态信息 |
exe | 当前进程的可执行文件(链接) |
如果你要察看系统信息,可以使用cat命令,例如:
# cat /proc/interrupts
CPU0
0: 8728810 XT-PIC timer
1: 895 XT-PIC keyboard
2: 0 XT-PIC cascade
3: 531695 XT-PIC aha152x
4: 2014133 XT-PIC serial
5: 44401 XT-PIC pcnet_cs
8: 2 XT-PIC rtc
11: 8 XT-PIC i82365
12: 182918 XT-PIC Mouse
13: 1 XT-PIC fpu PS/2
14: 1232265 XT-PIC ide0
15: 7 XT-PIC ide1
NMI: 0
前面已经说过,/proc/sys目录不仅提供了内核信息,而且可以通过它修改内核参数。(但是你必须很小心,因为可能会造成系统崩溃。最好是先找一台无关紧要的机子,调试成功后再应用到你的系统上。) 要改变内核的参数,只要用vi编辑或echo参数重定向到文件中即可。下面有一个例子:
# cat /proc/sys/fs/file-max
4096
# echo 8192 > /proc/sys/fs/file-max
# cat /proc/sys/fs/file-max
8192
2.2 实验内容
部分A
以超级用户的身份进入/proc目录,在终端上键入ls命令,察看该目录下的内容,同时察看每个文件的读写权限。
如图所示:
选择一台机器,试着回答下列问题:
l CPU的类型和型号。
使用如下命令:cat /proc/cpuinfo | grep “model name”,如图所示:
l 所使用的Linux的版本。
使用命令uname -r来查看当前虚拟机的内核版本,如图所示:
l 从启动到当前时刻经过的时间。
使用命令uptime来查看从启动到当前时刻经过的时间,如图所示:
l 内存状态。
使用命令:cat /proc/meminfo来查看内存状态,如图所示:
部分B
l 编写一个程序,用来获得内核参数(任意的参数均可)。
以下是读取内核参数swappiness(用于控制系统的内存管理,特别是交换空间(swap)的使用行为。它的值范围是 0 到 100)的值的代码:
#include <stdio.h>
#include <stdlib.h>int main() {int swappiness;FILE *fp;// 打开 /proc/sys/vm/swappiness 文件fp = fopen("/proc/sys/vm/swappiness", "r");if (fp == NULL) {perror("fopen");return 1;}// 读取 swappiness 值fscanf(fp, "%d", &swappiness);fclose(fp);printf("现在的swappiness值为: %d\n", swappiness);return 0;
}
我创建了一个getparameter.c 的文件,使用命令gcc -o getparameter getparameter.c命令来编译这个C语言文件,在使用./getparameter指令来执行上述C语言文件,执行之后的结果如下:
l I 编写一个程序,用来修改内核参数(任意的参数均可),现在我们编了一个可以更改swappiness(低值(如 10-20): 适用于需要高性能的场景,例如游戏或实时应用。这种情况下,系统会尽量保留数据在物理内存中,以提高访问速度;高值(如 60-80): 适用于服务器或需要长时间运行的应用,尤其是在内存较小的情况下。这样可以更好地利用交换空间,避免因内存不足导致的应用崩溃)的代码,我们选择将swappiness的值修改为10,代码如下:
#include <stdio.h>
#include <stdlib.h>int main() {int new_swappiness = 10; // 设置新的 swappiness 值FILE *fp;// 打开 /proc/sys/vm/swappiness 文件进行写入fp = fopen("/proc/sys/vm/swappiness", "w");if (fp == NULL) {perror("fopen");return 1;}// 写入新的 swappiness 值fprintf(fp, "%d", new_swappiness);fclose(fp);printf("Swappiness的值被设置为: %d\n", new_swappiness);return 0;
}
执行之后,如图所示:
此时,swappiness的值就成功的修改为了10。
2.3 实验步骤
1) 使用man命令了解/proc/stat文件的内容和格式:
man proc
如图所示:
2) 使用man命令了解下列函数的使用方法:
fopen:
命令:man fopen
原型:FILE *fopen( const char *filename, const char *mode );
以打开一个流(文件)。filename——文件名,mode——访问许可类型。
如图所示:
fscanf:
命令:man fscanf
原型:int fscanf( FILE *stream, const char *format [, argument ]… );
从流中读取格式化的数据。
例子fscanf (fp ,“cpu %ld”, &user)是指跳过字符串"cpu "及其前面的字符流,读取一个长整数并存入user中。其中fp为文件流指针。%ld对应长整数,%d对应整数,%s对应字符串。
如图所示:
fclose:
命令:man fclose
原型:int fclose( FILE *stream );
关闭流(文件)。
如图所示:
3)用c语言编程
总CPU时间 = 用户占用时间+系统占用时间+优先进程占用时间+闲置进程占用时间
系统CPU占用率 = 系统占用时间 / 总CPU时间
用户态CPU占用率 = 用户占用时间 / 总CPU时间
代码如下:
#include <stdio.h>
#include <unistd.h>unsigned long long get_cpu_time() {unsigned long long user, nice, system, idle;// 读取/proc/stat文件中的CPU时间信息FILE* file = fopen("/proc/stat", "r");fscanf(file, "cpu %llu %llu %llu %llu", &user, &nice, &system, &idle);fclose(file);return user + nice + system + idle;
}
int main() {unsigned long long prev_total_time = 0, prev_user_time = 0;double system_cpu_usage, user_cpu_usage;while (1) {// 获取当前的CPU时间信息unsigned long long total_time = get_cpu_time();unsigned long long user_time = total_time - get_cpu_time();// 计算系统CPU占用率和用户态CPU占用率if (prev_total_time != 0) {system_cpu_usage = (double)(total_time - prev_total_time - (user_time - prev_user_time)) / (total_time - prev_total_time);user_cpu_usage = (double)(user_time - prev_user_time) / (total_time - prev_total_time);printf("系统CPU占用率:%.2f%%\n", system_cpu_usage * 100);printf("用户态CPU占用率:%.2f%%\n", user_cpu_usage * 100);}prev_total_time = total_time;prev_user_time = user_time;sleep(1); // 每隔1秒钟更新一次CPU时间信息}return 0;
}
4)编译和运行
使用命令vim CpuInfo.c创建一个C语言文件,将上述的代码复制进去
使用命令gcc -o CpuInfo CpuInfo.c编译此C语言文件
使用命令./CpuInfo运行此文件,结果如图所示:
2.4 实验总结
1.在本次实验中,我深入探索了Linux的proc文件系统,了解其在系统监控和管理中的重要性。proc文件系统以虚拟文件的形式提供了内核和进程的信息,位于 /proc
目录下。通过读取这些文件,我能够获取系统的实时状态,包括CPU使用率、内存占用、进程信息等。
2.使用命令如 cat /proc/cpuinfo
和 cat /proc/meminfo
,我获取了详细的CPU和内存信息,帮助我理解系统资源的分配情况。此外,/proc/[pid]/status
文件让我能够查看特定进程的状态和资源使用情况,增强了我对进程管理的理解。
3.通过对proc文件系统的观察,我认识到其在系统调试和性能监控中的关键作用。这次实验不仅提升了我对Linux内核的理解,也为后续的系统优化和故障排查打下了基础。未来,我希望能进一步研究proc文件系统的其他功能,如进程调度和内核参数调整。