实验四 PROC文件系统
- 格式:ppt
- 大小:238.00 KB
- 文档页数:18
什么是proc文件系统?proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间。
它以文件系统的方式为访问系统内核数据的操作提供接口。
用户和应用程序可以通过proc得到系统的信息,并可以改变内核的某些参数。
由于系统的信息,如进程,是动态改变的,所以用户或应用程序读取proc文件时,proc文件系统是动态从系统内核读出所需信息并提交的。
它的目录结构如下:目录名称目录内容apm 高级电源管理信息cmdline 内核命令行Cpuinfo 关于Cpu信息Devices 可以用到的设备(块设备/字符设备)Dma 使用的DMA通道Filesystems 支持的文件系统Interrupts 中断的使用Ioports I/O端口的使用Kcore 内核核心印象Kmsg 内核消息Ksyms 内核符号表Loadavg 负载均衡Locks 内核锁Meminfo 内存信息Misc 杂项Modules 加载模块列表Mounts 加载的文件系统Partitions 系统识别的分区表Rtc 实时时钟Slabinfo Slab池信息Stat 全面统计状态表Swaps 对换空间的利用情况V ersion 内核版本Uptime 系统正常运行时间并不是所有这些目录在你的系统中都有,这取决于你的内核配置和装载的模块。
另外,在/proc下还有三个很重要的目录:net,scsi和sys。
Sys目录是可写的,可以通过它来访问或修改内核的参数(见下一部分),而net和scsi则依赖于内核配置。
例如,如果系统不支持scsi,则scsi 目录不存在。
除了以上介绍的这些,还有的是一些以数字命名的目录,它们是进程目录。
系统中当前运行的每一个进程都有对应的一个目录在/proc下,以进程的PID号为目录名,它们是读取进程信息的接口。
而self目录则是读取进程本身的信息接口,是一个link。
Proc文件系统的名字就是由之而起。
进程目录的结构如下:目录名称目录内容Cmdline 命令行参数Environ 环境变量值Fd 一个包含所有文件描述符的目录Mem 进程的内存被利用情况Stat 进程状态Status 进程当前状态,以可读的方式显示出来Cwd 当前工作目录的链接Exe 指向该进程的执行命令文件Maps 内存映象Statm 进程内存状态信息Root 链接此进程的root目录用户如果要查看系统信息,可以用cat命令。
第12章/proc文件系统实验目的●学习使用/proc文件系统●使用/proc文件系统显示缺页状态●使用/proc文件系统输出超过一个页面的信息。
请注意:你在第一阶段的学习中可以先把重点放在怎样使用proc文件系统上;关于proc 文件系统的内部实现细节,由于牵涉到太多文件系统原理与相关概念,建议你在学习完本书《文件系统》这一章之后,在回过头来对照相应代码进行分析。
实验内容1. 在/proc文件系统中添加必要的节点,以统计操作系统发生的缺页中断次数。
2. 实现一个proc文件接口,每次当用户读取这个proc文件的时候,要求打印出系统中所有进程的pid,comm,start_time,utime,stime,policy,priority 实验原理12.1 /proc文件系统procfs,是process fs的缩写。
最开始的时候只是一些进程相关的信息的集合,Linux 扩展了这个概念,可以通过/proc文件系统交互几乎任何内核的信息。
/proc不是一个真正的文件系统(这么说的意思是,/proc不像普通的文件系统是用于管理磁盘上的文件,并且要占用磁盘上的空间;/proc只存在于内存中,更确切地说是只有管理模块存在于内存中,所有具体的信息都动态地从运行中的内核里面读取)。
proc文件系统的历史有点复杂,基本上,随着Unix的演化而到了今天这个样子,为我们带来方便。
/proc文件系统是一个接口,用户与内核交互的接口,用户从/proc文件系统中读取很多内核释放出来的信息(包括内核各个管理模块的动态信息,CPU信息,硬件驱动释放出来的信息等等);同时内核也可以在必要的时候从用户得到输入,进而改变内核的变量,或者运行状态。
/proc文件系统中主要包含两方面的文件(或者说主要有两个大的用途):一是只读文。
proc⽂件系统介绍(1)linux内核是⼀个⾮常庞⼤、⾮常复杂的⼀个单独的程序,对于这样的⼀个程序来说调试是⾮常复杂的。
(2)项kernel这样庞⼤的项⽬,给⾥⾯添加/更改⼀个功能是⾮常⿇烦的,因为你这添加的⼀个功能可能会影响其他已经有的。
(3)早期内核版本中尽管调试很⿇烦,但是⾼⼿们还可以凭借个⼈超凡脱俗的能⼒去驾驭。
但是到了2.4左右的版本的时候,这个难度已经⾮常⼤了。
(4)为了降低内核调试和学习的难度,内核开发者们在内核中添加了⼀些属性专门⽤于调试内核,proc⽂件系统就是⼀个尝试。
(5)proc⽂件系统的思路是:在内核中构建⼀个虚拟⽂件系统/proc,内核运⾏时将内核中⼀些关键的数据结构以⽂件的⽅式呈现在/proc⽬录中的⼀些特定⽂件中,这样相当于将不可见的内核中的数据结构以可视化的⽅式呈现给内核的开发者。
(6)proc⽂件系统给了开发者⼀种调试内核的⽅法:我们通过实时的观察/proc/xxx⽂件,来观看内核中特定数据结构的值。
在我们添加⼀个新功能的前后来对⽐,就可以知道这个新功能产⽣的影响对还是不对。
(7)proc⽬录下的⽂件⼤⼩都是0,因为这些⽂件本⾝并不存在于硬盘中,他也不是⼀个真实⽂件,他只是⼀个接⼝,当我们去读取这个⽂件时,其实内核并不是去硬盘上找这个⽂件,⽽是映射为内核内部⼀个数据结构被读取并且格式化成字符串返回给我们。
所以尽管我们看到的还是⼀个⽂件内容字符串,和普通⽂件⼀样的;但是实际上我们知道这个内容是实时的从内核中数据结构来的,⽽不是硬盘中来的。
1、常⽤proc中的⽂件介绍(1)/proc/cmdline(2)/proc/cpuinfo(3)/proc/devices(4)/proc/interrupts2、proc⽂件系统的使⽤cat以⼿⼯查看程序中可以⽂件IO访问在shell程序中⽤cat命令结合正则表达式来获取并处理内核信息#include <stdio.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>int main(int argc ,char **argv){int fd=-1;char buf[500]={0};if(argc!=2){printf("eg: %s -d|-v\n",argv[0]);return -1;}if(!strcmp(argv[1],"-v")){fd=open("/proc/version",O_RDONLY);read(fd,buf,sizeof(buf));printf("结果:\n%s\n",buf);}else if(!strcmp(argv[1],"-d")){fd=open("/proc/devices",O_RDONLY);read(fd,buf,sizeof(buf));printf("结果:\n%s\n",buf);}}3、扩展:sys⽂件系统(1)sys⽂件系统本质上和proc⽂件系统是⼀样的,都是虚拟⽂件系统,都在根⽬录下有个⽬录(⼀个是/proc⽬录,另⼀个是/sys⽬录),因此都不是硬盘中的⽂件,都是内核中的数据结构的可视化接⼝。
实验十一:Linux proc文件系统实验学时:4实验类型:验证实验要求:选修一、实验目的通过本实验的学习,理解和分析proc文件系统,掌握Linux proc文件的特点和使用方法,访问有关内核的状态、计算机的属性、正在运行的进程状态等信息。
二、实验内容实验内容:了解proc文件系统,编写一个c程序,获取系统相关信息,实时监测(周期性显示)CPU、主存和网络的详细使用情况以及它们的利用率。
三、实验原理、方法和手段实验原理:proc 文件系统介绍:proc 文件系统是一个虚拟文件系统,是一种内核和内核模块用来向进程(process) 发送信息的机制 (所以叫做proc)。
这个虚拟文件系统让你可以和内核内部数据结构进行交互,获取有关进程的有用信息,在运行中 (on the fly) 改变设置 (通过改变内核参数)。
与其他文件系统不同,proc 存在于内存之中而不是硬盘上。
proc文件系统包含一些目录和虚拟文件。
大部分proc中的文件和目录提供系统物理环境最新的信息。
/proc目录中有一些以数字命名的目录,它们是进程目录。
系统中当前运行的每一个进程在/proc下都对应一个以进程号为目录名的目录/proc/pid,它们是读取进程信息的接口。
此外,在Linux2.6.0-test6以上的版本中/proc/pid 目录中有一个task目录,/proc/pid/task目录中也有一些以该进程所拥有的线程的线程号命名的目录/proc/pid/task/tid,它们是读取线程信息的接口。
/proc 由内核控制,没有承载 /proc 的设备。
因为 /proc 主要存放由内核控制的状态信息,所以大部分这些信息的逻辑位置位于内核控制的内存。
对/proc 进行一次 'ls -l' 可以看到大部分文件都是 0 字节大的;不过察看这些文件的时候,确实可以看到一些信息。
这是因为 /proc 文件系统和其他常规的文件系统一样把自己注册到虚拟文件系统层 (VFS) 了。
实验四文件系统实验一. 目的要求1、用高级语言编写和调试一个简单的文件系统,模拟文件管理的工作过程。
从而对各种文件操作命令的实质内容和执行过程有比较深入的了解。
2、要求设计一个n个用户的文件系统,每次用户可保存m个文件,用户在一次运行中只能打开一个文件,对文件必须设置保护措施,且至少有Create、delete、open、close、read、write等命令。
二. 例题:1、设计一个10个用户的文件系统,每次用户可保存10个文件,一次运行用户可以打开5个文件。
2、程序采用二级文件目录(即设置主目录[MFD])和用户文件目录(UED)。
另外,为打开文件设置了运行文件目录(AFD)。
3、为了便于实现,对文件的读写作了简化,在执行读写命令时,只需改读写指针,并不进行实际的读写操作。
4、算法与框图:①因系统小,文件目录的检索使用了简单的线性搜索。
②文件保护简单使用了三位保护码:允许读写执行、对应位为1,对应位为0,则表示不允许读写、执行。
③程序中使用的主要设计结构如下:主文件目录和用户文件目录(MFD、UFD)打开文件目录(AFD)(即运行文件目录)文件目录指针文件名··文件系统算法的流程图如下:三. 实验题:1、增加2~3个文件操作命令,并加以实现。
(如移动读写指针,改变文件属性,更换文件名,改变文件保护级别)。
代码如下://1、增加2~3个文件操作命令,并加以实现。
(如移动读写指针,改变文件属性,更换文件名,改变文件保护级别)。
#include<iostream>#include<string>#include<conio.h>using namespace std;struct TYPE_UFD{string File_Name;bool Read;bool Write;bool Execute;int Length_File;};struct TYPE_MFD{string User_Name;TYPE_UFD *Pointer;};struct TYPE_AFD{int File_ID;bool Read;bool Write;bool Execute;int Pointer;};class TYPE_FILE_SYSTEM{public:void Initial( void );void Start( void );private:int _Number_Users;int _Number_Files;int _MaxNumber_Open_Files;TYPE_MFD *_MFD;TYPE_UFD *_UFD;TYPE_AFD *_AFD;};void TYPE_FILE_SYSTEM::Initial( void ){_Number_Users = 10;_Number_Files = 10;_MaxNumber_Open_Files = 5;_UFD = new TYPE_UFD [_Number_Users*_Number_Files];_MFD = new TYPE_MFD [_Number_Users];int i=0;for( i=0 ; i<_Number_Users ; i++ ){_MFD[i].Pointer = &(_UFD[i*_Number_Files]);}_AFD = new TYPE_AFD [_MaxNumber_Open_Files];_MFD[0].User_Name = "zaq";_UFD[0].File_Name = "file1.txt";_UFD[0].Length_File = 10;_UFD[0].Read = true;_UFD[0].Write = false;_UFD[0].Execute = true;_UFD[1].File_Name = "file2.txt";_UFD[1].Length_File = 20;_UFD[1].Read = true;_UFD[1].Write = false;_UFD[1].Execute = false;for( i=2 ; i<_Number_Files ; i++ ){_UFD[i].File_Name = "";_UFD[i].Length_File = -1;_UFD[i].Read = false;_UFD[i].Write = false;_UFD[i].Execute = false;}}void TYPE_FILE_SYSTEM::Start( void ){int User_ID;int i,temp_int;string temp;char choice;int Number_Open_Files;string User_Name;string Command;TYPE_UFD *UFD;do{do{cout << "已创建用户名为zaq\n指令有:create delete open dir diropen write read logout shutdown \n\n";cout << "请输入用户名:";cin >> User_Name;for( User_ID=0 ; User_ID<_Number_Users ; User_ID++ ){if( _MFD[User_ID].User_Name == User_Name )break;}if( User_ID == _Number_Users )cout << "用户名错误,请再次输入." << endl;}while( User_ID == _Number_Users );cout << "欢迎登录, " << User_Name << " !" << endl;UFD = _MFD[User_ID].Pointer;for( i=0 ; i<_MaxNumber_Open_Files ; i++ ){_AFD[i].File_ID = -1;}Number_Open_Files = 0;do{cout << "C:\\" << User_Name << ">" ;cin >> Command;if( Command == "dir" ){cout << endl;cout << "打开用户" << User_Name <<"的文件" << endl;cout << "\t" << "State\t" << "Length\t" << "File name" << endl;for( i=0 ; i<_Number_Files ; i++ ){if( UFD[i].Length_File != -1 ){cout << "\t" ;if( UFD[i].Read == true )cout << "R";elsecout << "-";if( UFD[i].Write == true )cout << "W";elsecout << "-";if( UFD[i].Execute == true )cout << "E";elsecout << "-";cout << "\t";cout << UFD[i].Length_File;cout << "\t";cout << UFD[i].File_Name << endl;}}cout << endl;}else if( Command == "diropen" ){cout << endl;cout << "打开用户" << User_Name << "的文件"<<endl;cout << "\t" << "State\t" << "Open File name" << endl;for( i=0 ; i<_MaxNumber_Open_Files ; i++ ){if( _AFD[i].File_ID != -1 ){cout << "\t" ;if( _AFD[i].Read == true )cout << "R";elsecout << "-";if( _AFD[i].Write == true )cout << "W";elsecout << "-";if( _AFD[i].Execute == true )cout << "E";elsecout << "-";cout << "\t";cout << UFD[_AFD[i].File_ID].File_Name << endl;}}cout << endl;}else if( Command == "create" ){for( i=0 ; i<_Number_Files ; i++ )if( UFD[i].Length_File == -1 )break;if( i == _Number_Files )cout << "Error: 已有名为" << _Number_Files << " 的文件." << endl;else{cout << "请输入新文件信息:" << endl;cout << "文件名: ";cin >> temp;UFD[i].File_Name = temp;cout << "文件权限: ";cout << "Read (y/n):";do{choice = getch();}while( choice!='y' && choice!='n' );if( choice == 'y' )UFD[i].Read = true;elseUFD[i].Read = false;cout << endl;cout << "Write (y/n):";do{choice = getch();}while( choice!='y' && choice!='n' );if( choice == 'y' )UFD[i].Write = true;elseUFD[i].Write = false;cout << endl;cout << "Execute (y/n):";do{choice = getch();}while( choice!='y' && choice!='n' );if( choice == 'y' )UFD[i].Execute = true;elseUFD[i].Execute = false;cout << endl;cout << "Length :";cin >> temp_int;if( temp_int > 0 )UFD[i].Length_File = temp_int;cout << "新文件" << UFD[i].File_Name << " 已建立!" << endl;}}else if( Command == "delete" ){cout << "请输入文件名:";cin >> temp;for( i=0 ; i<_Number_Files ; i++ )if( (UFD[i].Length_File!=-1)&&(UFD[i].File_Name==temp) )break;if( i == _Number_Files )cout << "文件名错误,请再次输入." << endl;else{UFD[i].Length_File = -1;cout << "文件" << UFD[i].File_Name << " 已删除." << endl;}}else if( Command == "open" ){if( Number_Open_Files == _MaxNumber_Open_Files )cout << "Error: 你已经打开了" <<Number_Open_Files << " 文件." << endl;else{cout << "请输入文件名:";cin >> temp;for( i=0 ; i<_Number_Files ; i++ )if( (UFD[i].Length_File!=-1)&&(UFD[i].File_Name==temp) )break;if( i == _Number_Files )cout << "文件名错误,请再次输入." << endl;else{Number_Open_Files++;for( temp_int=0 ;temp_int<_MaxNumber_Open_Files ; temp_int++ )if( _AFD[temp_int].File_ID == -1 )break;_AFD[temp_int].File_ID = i;_AFD[temp_int].Pointer = 0;cout << "请定义打开方式:" << endl;if( UFD[i].Read == true ){cout << "Read (y/n):";do{choice = getch();}while( choice!='y' && choice!='n' );if( choice == 'y' )_AFD[temp_int].Read = true;else_AFD[temp_int].Read = false;cout << endl;}else_AFD[temp_int].Read = false;if( UFD[i].Write == true ){cout << "Write (y/n):";do{choice = getch();}while( choice!='y' && choice!='n' );if( choice == 'y' )_AFD[temp_int].Write = true;else_AFD[temp_int].Write = false;cout << endl;}else_AFD[temp_int].Write = false;if( UFD[i].Execute == true ){cout << "Execute (y/n):";do{choice = getch();}while( choice!='y' && choice!='n' );if( choice == 'y' )_AFD[temp_int].Execute = true;else_AFD[temp_int].Execute = false;cout << endl;}else_AFD[temp_int].Execute;cout << "文件" << temp << " 已打开." << endl;}}}else if( Command == "logout" ){cout << "再见, " << User_Name << " !" << endl;break;}else if( Command == "close" ){cout << "请输入文件名:";cin >> temp;for( i=0 ; i<_Number_Files ; i++ )if( (UFD[i].Length_File!=-1)&&(UFD[i].File_Name==temp) )break;if( i == _Number_Files )cout << "文件名错误,请再次输入." << endl;else{for( temp_int=0 ;temp_int<_MaxNumber_Open_Files ; temp_int++ )if( _AFD[temp_int].File_ID == i )break;if( temp_int == _MaxNumber_Open_Files )cout << "文件" << temp << " 未打开." << endl;else{_AFD[temp_int].File_ID = -1;Number_Open_Files--;cout << "文件" << temp << " 已关闭." << endl;}}}else if( Command == "read" ){cout << "请输入文件名:";cin >> temp;for( i=0 ; i<_Number_Files ; i++ )if( (UFD[i].Length_File!=-1)&&(UFD[i].File_Name==temp) )break;if( i == _Number_Files )cout << "文件名错误,请再次输入." << endl;else{for( temp_int=0 ;temp_int<_MaxNumber_Open_Files ; temp_int++ )if( _AFD[temp_int].File_ID == i )break;if( temp_int == _MaxNumber_Open_Files )cout << "文件" << temp << " 未打开." << endl;else{if( _AFD[temp_int].Read == true )cout << "文件" << temp << " 成功读取." << endl;elsecout << "Error: 文件打开模式错误." << endl;}}}else if( Command == "write" ){cout << "请输入文件名:";cin >> temp;for( i=0 ; i<_Number_Files ; i++ )if( (UFD[i].Length_File!=-1)&&(UFD[i].File_Name==temp) )break;if( i == _Number_Files )cout << "文件名错误,请再次输入." << endl;else{for( temp_int=0 ;temp_int<_MaxNumber_Open_Files ; temp_int++ )if( _AFD[temp_int].File_ID == i )break;if( temp_int == _MaxNumber_Open_Files )cout << "文件" << temp << " 未打开." << endl;else{if( _AFD[temp_int].Write == true )cout << "文件" << temp << " 成功写入." << endl;elsecout << "Error: 文件打开模式错误." << endl;}}}else if( Command == "shutdown" ){cout << "正在注销........" << endl;cout << "再见, " << User_Name << " !" << endl;cout << "正在关机.........." << endl;break;}else{cout << "指令错误,请再次输入." << endl;}}while( Command != "logout" && Command != "shutdown" );}while( Command != "shutdown" );}int main(){TYPE_FILE_SYSTEM FS;FS.Initial();FS.Start();return 0;}2、编一个通过屏幕选择命令的文件管理系统,每屏要为用户提供足够的选择信息,不需要打入冗长的命令。