目录
实验要求
一、文件管理和用户接口
⑴文件的逻辑结构
⑵磁盘模拟
⑶目录结构
⑷磁盘分配
⑸磁盘空闲存储空间管理
⑹用户接口
⑺屏幕显示
代码部分
python调用c的方法:
编辑
c语言部分,文件名 Operating_System_C.c
python语言部分
运行实例:
文件管理和用户接口部分实现的主要是单用户的磁盘文件管理部分,包括文件的逻辑结构、物理结构、目录、磁盘分配回收、文件的保护和用户接口的实现。
文件的逻辑结构采用流式结构;
文件均采用文本文件;
系统中有两种文件,一种是存放任意字符的文件,一种是可执行文件。可执行文件的内容就是模拟系统内进程的程序体。
文件中的“可执行”文件,包含的命令非常简单,包括:
用一个文本文件disk模拟磁盘,磁盘的每个盘块64字节,模拟磁盘共有128块。第0、1块存放文件分配表,第2块存放根目录,其余存放子目录和文件。
目录结构采用树型目录结构。
①目录项内容(8个字节):
②根目录
根目录位置固定,占用模拟磁盘第2块,大小固定,共8项;
③子目录
位置不固定,大小不固定。(至少建立一级子目录,最好支持多级子目录)。
磁盘的分配采用链接结构(显式链接)的分配。
磁盘空闲存储空间管理采用位示图方法。
位示图和显示链接的指针合在一起组成文件分配表,占用磁盘空间第0、1块。
用户接口提供用户命令接口,要求实现以下命令:
创建文件:create 拷贝文件:copy
删除文件:delete 移动文件:move
显示文件:type 改变文件属性:change
建立目录:makdir 改变目录路径:chadir
删除目录:deldir(deltree) 修改文件 edit
运行可执行文件:可执行文件的文件名(创建进程)。
屏幕显示要求包括:
c和python各1000多行
python导入ctypes库,在pycham控制台输入
gcc Operating_System_C.c -shared -o Operating_System_C.dll
若提示
可能是你的路径不对,注意切换到.c文件的目录
若提示,没有gcc之类的,请去MinGW-w64 - for 32 and 64 bit Windows - Browse Files at SourceForge.netA complete runtime environment for gcchttps://sourceforge.net/projects/mingw-w64/files/
下载
并把压缩包解压,将含有g++.exe的文件路径添加到环境变量中
打开cmd 输入gcc --version 若弹出以下内容
表明安装完成
然后就可以用
Operating_System_C = ctypes.cdll.LoadLibrary('./Operating_System_C.dll')
打开自己写的c文件,调用其中的函数了(函数默认返回值为ctypes.c_int类型,函数的输入也要转化为ctypes的类型才行,具体情况请自己去搜索ctypes教程)
需要在控制台输入
gcc Operating_System_C.c -shared -o Operating_System_C.dll
生成.dll文件才能被python调用
#include
#include
#include
#include
// 目录项
/*
目录名、文件名:3个字节;
扩展名:2个字节(可执行文件扩展名为e,目录没有扩展名);
目录、文件属性:1字节;
起始盘块号:1个字节;
文件长度:1字节(目录没有长度)。
*/
struct catalog_entry{
char name[3];
char extend[2];
unsigned char attribute : 8; // 1目录,2文件,0不存在
unsigned char start : 8;
unsigned char len : 8;
};
// 八位数据类型,主要用于位视图
union bit8{
unsigned char data : 8;
struct bits8{ // 注意排列 b0 b1 b2 b3 b4 b5 b6 b7
unsigned char b7 : 1;
unsigned char b6 : 1;
unsigned char b5 : 1;
unsigned char b4 : 1;
unsigned char b3 : 1;
unsigned char b2 : 1;
unsigned char b1 : 1;
unsigned char b0 : 1;
}bit8;
};
// 索引7*8
union index56{
unsigned char datas[7];
};
// 索引变量 记录索引的值
unsigned char index_variables[128];
// 位视图
union bit8 bitwise_view[16];
// 文件变量
FILE* file;
// 输出文件
FILE* fp;
// 保存位视图,给出块号,保存它,负数保存所有
void Save_Bitview(FILE* file,int position){
if(position<0){
fseek(file,0,SEEK_SET); // 文件指针移动
fwrite(bitwise_view,1,16,file);
}else{
char t[1] = {bitwise_view[position/8].data};
fseek(file,position/8,SEEK_SET); // 文件指针移动
fwrite(t,1,1,file);
}
}
// 从位视图中返回一个空块的位置失败返回-1
int Give_Empty_Block(){
int i,j;
for(i=0;i<16;i++){
if(bitwise_view[i].bit8.b0 == 0)
return i*8+0;
if(bitwise_view[i].bit8.b1 == 0)
return i*8+1;
if(bitwise_view[i].bit8.b2 == 0)
return i*8+2;
if(bitwise_view[i].bit8.b3 == 0)
return i*8+3;
if(bitwise_view[i].bit8.b4 == 0)
return i*8+4;
if(bitwise_view[i].bit8.b5 == 0)
return i*8+5;
if(bitwise_view[i].bit8.b6 == 0)
return i*8+6;
if(bitwise_view[i].bit8.b7 == 0)
return i*8+7;
}
return -1;
}
// 占用块,成功1,失败-1
int Occupy_Block(FILE* file,int i){
switch(i%8){ // 挨个位看
case 0:if(bitwise_view[i/8].bit8.b0==1){return -1;}else{bitwise_view[i/8].bit8.b0=1;}break;
case 1:if(bitwise_view[i/8].bit8.b1==1){return -1;}else{bitwise_view[i/8].bit8.b1=1;}break;
case 2:if(bitwise_view[i/8].bit8.b2==1){return -1;}else{bitwise_view[i/8].bit8.b2=1;}break;
case 3:if(bitwise_view[i/8].bit8.b3==1){return -1;}else{bitwise_view[i/8].bit8.b3=1;}break;
case 4:if(bitwise_view[i/8].bit8.b4==1){return -1;}else{bitwise_view[i/8].bit8.b4=1;}break;
case 5:if(bitwise_view[i/8].bit8.b5==1){return -1;}else{bitwise_view[i/8].bit8.b5=1;}break;
case 6:if(bitwise_view[i/8].bit8.b6==1){return -1;}else{bitwise_view[i/8].bit8.b6=1;}break;
case 7:if(bitwise_view[i/8].bit8.b7==1){return -1;}else{bitwise_view[i/8].bit8.b7=1;}break;
}
// 保存更改
Save_Bitview(file,i);
char t[1];
int j;
// 清空原有块中的东西
fseek(file,i*64,SEEK_SET); // 文件指针移动
t[0] = 0b00000000;
for(j=0;j<64;j++) // 0掩盖
fwrite(t,1,1,file);
return 1;
}
// 取消占用块
void Unoccupie_Block(FILE* file,int i){
switch(i%8){ // 挨个位看
case 0:bitwise_view[i/8].bit8.b0=0;break;
case 1:bitwise_view[i/8].bit8.b1=0;break;
case 2:bitwise_view[i/8].bit8.b2=0;break;
case 3:bitwise_view[i/8].bit8.b3=0;break;
case 4:bitwise_view[i/8].bit8.b4=0;break;
case 5:bitwise_view[i/8].bit8.b5=0;break;
case 6:bitwise_view[i/8].bit8.b6=0;break;
case 7:bitwise_view[i/8].bit8.b7=0;break;
}
// 保存更改
Save_Bitview(file,i);
}
// 返回索引最后一个块的编号
int Index_End(int x){
if (index_variables[x] == 0){ // 末尾0,索引到了
return x;
}else{
Index_End(index_variables[x]); // 继续
}
}
// 保存索引表,给出块号,保存它,负数保存所有
void Save_Index(FILE* file,int position){
union index56 index_pointer[1];//索引指针,保存用
int i,j;
if(position<0){
fseek(file,16,SEEK_SET); // 文件指针移动
for(i=0;i<16;i++){
index_pointer[0].datas[6] = index_variables[i*8+7];
for(j=6;j>=0;j--){
index_pointer[0].datas[j] += index_variables[i*8+j]<>7-j;
}
}
fwrite(index_pointer,7,1,file);
}
}else{
fseek(file,16+position/8*7,SEEK_SET); // 文件指针移动
i = position/8*8;
index_pointer[0].datas[6] = index_variables[i+7];
for(j=6;j>=0;j--){
index_pointer[0].datas[j] += index_variables[i+j]<>7-j;
}
}
fwrite(index_pointer,7,1,file);
}
}
// 删除索引,连着删除这一块后面所有的索引,同时取消块占用
void Drop_Index(FILE* file,int x){
if (index_variables[x] != 0){ // 不是最后一个
Drop_Index(file,index_variables[x]); // 往下走
index_variables[x] = 0; // 删除该索引
Save_Index(file,x); // 保存索引表
}
Unoccupie_Block(file,x); //取消块占用
// 末尾0,索引结束
}
// 保存位视图和索引表,
void Save_Start(FILE* file){
union index56 index_pointer[1];//索引指针,保存用
int i,j;
fseek(file,0,SEEK_SET); // 文件指针移动
fwrite(bitwise_view,1,16,file);
for(i=0;i<16;i++){
index_pointer[0].datas[6] = index_variables[i*8+7];
for(j=6;j>=0;j--){
index_pointer[0].datas[j] += index_variables[i*8+j]<>7-j;
}
}
fwrite(index_pointer,7,1,file);
}
}
// 读取位视图和索引表
void Read_Start(FILE* file){
fseek(file,0,SEEK_SET); // 文件指针移动
// 数据数组,每个元素字节,元素个数,输入文件位置
fread(bitwise_view,1,16,file);
int i,j;
union index56 index_pointer[1];//索引指针,读取用
for(i=0;i<16;i++){
fread(index_pointer,7,1,file);
index_variables[i*8] = index_pointer[0].datas[0]>>1;
for(j=0;j<7;j++){
index_variables[i*8+j+1] = (index_pointer[0].datas[j]<<(6-j))%128;
if(j!=6){
index_variables[i*8+j+1] += index_pointer[0].datas[j+1]>>(j+2);
}
}
}
}
// 查看目录在块中文件是否存满,存满返回-1,否则返回第一个空的文件位置(字节位置)
// 带递归翻页
int Directory_Overrun(FILE* file,int start,int len){
if(start==0){ // 空了,前面都没找到
return -1;
}
fseek(file,64*start,SEEK_SET); // 文件指针移动
struct catalog_entry directory[8]; // 读取到的目录
fread(directory,8,8,file);// 读取
int i;
for(i=0;i<8;i++)
{
if(directory[i].attribute==0)
{
return 64*start+8*i;
}
}
return Directory_Overrun(file,index_variables[start],len-1); // 到这里没有,看看下一页
}
// 输出位视图
void Printf_Bitwise_View(){
int i;
fprintf(fp,"\n位视图:");
for(i=0;i<16;i++)
{
fprintf(fp,"\n%d",bitwise_view[i].bit8.b0);
fprintf(fp," %d",bitwise_view[i].bit8.b1);
fprintf(fp," %d",bitwise_view[i].bit8.b2);
fprintf(fp," %d",bitwise_view[i].bit8.b3);
fprintf(fp," %d",bitwise_view[i].bit8.b4);
fprintf(fp," %d",bitwise_view[i].bit8.b5);
fprintf(fp," %d",bitwise_view[i].bit8.b6);
fprintf(fp," %d",bitwise_view[i].bit8.b7);
}
fprintf(fp,"\n");
}
// 输出索引阵列
void Printf_Index_variables(){
int i,j;
fprintf(fp,"\n索引变量\n");
for(i=0;i<16;i++){
for(j=0;j<8;j++)
{
fprintf(fp,"%5d",index_variables[i*8+j]);
}
fprintf(fp,"\n");
}
}
// 输出目录
void Printf_Entry(struct catalog_entry entry){
if(entry.attribute == 0){
fprintf(fp,"\n目录不存在");
return;
}
fprintf(fp,"\n名称:");
int i;
for(i=0;i<3;i++){
if(entry.name[i]!='\0'){
fprintf(fp,"%c",entry.name[i]);
}
else{
break;
}
}
if(entry.attribute > 1){
fprintf(fp,"\n扩展名:");
for(i=0;i<2;i++){
if(entry.extend[i]!='\0'){
fprintf(fp,"%c",entry.extend[i]);
}else{
if(i==0){
fprintf(fp,"无");}
break;
}
}
}
fprintf(fp,"\n属性:");
switch(entry.attribute){
case 0: fprintf(fp,"不存在");break;
case 1: fprintf(fp,"目录");break;
case 2: fprintf(fp,"文件");break;
default: fprintf(fp,"其他");break;}
fprintf(fp," %d",entry.attribute);
fprintf(fp,"\n起始块:%d\n长度:%d\n",entry.start,entry.len);
}
// 生成目录项
// 名字,扩展名,属性,起始块号,文件长度
struct catalog_entry Generate_Catalog_Entry(char* name,char* extend,int attribute,int start,int len){
struct catalog_entry entry = {"","",attribute,start,len};
entry.name[0]=name[0];entry.name[1]=name[1];entry.name[2]=name[2];
entry.extend[0]=extend[0];entry.extend[1]=extend[1];
return entry;
}
// 在块中按名查找文件或目录,返回目录项,同时最后一个数据指针的值更改为文件目录项字节位置,没有不会更改
struct catalog_entry LookUp(FILE* file,char* name,int start,int len,int *p){
struct catalog_entry directory[8]; // 读取到的目录
if(start==0){ // 空了,前面都没找到
directory[0].attribute = 0;
return directory[0];
}
fseek(file,64*start,SEEK_SET); // 文件指针移动
fread(directory,8,8,file);// 读取
int i;
for(i=0;i<8;i++){
if(directory[i].attribute!=0){// 这个东西存的有
// 开始名称匹配
if(directory[i].name[0]==name[0]){// 第一个匹配
if(name[0]=='\0'){// 结束了
*p = start*64+i*8;
return directory[i];
}else{
if(directory[i].name[1]==name[1]){// 第二个匹配
if(name[1]=='\0'){// 结束了
*p = start*64+i*8;
return directory[i];
}else{
if(directory[i].name[2]==name[2]){// 第三个匹配
*p = start*64+i*8;
return directory[i];
}
}
}
}
}
}
}
return LookUp(file,name,index_variables[start],len-1,p); // 到这里没有,看看下一页
}
// 目录长度改变,要改变的目录,改变值
void Directory_Length_Chenge(FILE* file,struct catalog_entry entry,int change){
char lend[1] = {entry.len+change};
struct catalog_entry directory[1]; // 读取到的目录
int t;
int *p=&t;
fseek(file,64*entry.start+7,SEEK_SET); // 文件指针移动到当前目录的长度属性
fwrite(lend,1,1,file); // 改变
fseek(file,64*entry.start+8,SEEK_SET); // 文件指针移动到父目录
fread(directory,8,1,file);// 读取
if(LookUp(file,entry.name,directory[0].start,directory[0].len,p).attribute == 0){ // 查找目录字节位置
fprintf(fp,"\n严重错误,对目录的父目录中未找到自己,目录长度改变失败");// 没找到
}else{
fseek(file,t+7,SEEK_SET); // 移动到该目录项的长度位置
fwrite(lend,1,1,file); // 改变
}
}
// 目录整理,整理参数中目录表指向的目录,顺便会删除空的目录项
// 带翻页,不整花活,直接暴力读取,排序,修改
int Catalog_Organization(FILE* file,struct catalog_entry entry){
int i,j,k=entry.len-1,l=7,start=entry.start;
struct catalog_entry directory[entry.len][8];
for(i=0;i1)
int Create(FILE* file,char* name,char* extend,struct catalog_entry entry,char attribute){
if(attribute <= 0){
fprintf(fp,"\n创建参数错误,创建失败");
return -1;
}
int position = Directory_Overrun(file,entry.start,entry.len); // 找找空位
if(position == -1){// 没找到空位
if(entry.start == 2){ // 是根目录
fprintf(fp,"\n根目录已满,无法创建");// 根目录只能有1页
return -1;
}
else{ // 否则可以新增一页
int piece = Give_Empty_Block(); // 找一个新块
if(piece==-1){ // 找不到
fprintf(fp,"\n磁盘已满,无法创建");
return -1;
}else{ // 新增一页
int iend = Index_End(entry.start);// 找到目录的末页
Occupy_Block(file,piece); // 占用新块,刚找到的新块,就不看在不在了
index_variables[iend] = piece; // 索引延申
Save_Index(file,iend); // 改完索引要保存
// 新增页了,文件长度需要+1
Directory_Length_Chenge(file,entry,1);
position = piece*64; // 新的空位在新页的第一格
// 由于都重置为0,里面的文件,目录属性也应该是0
}
}
}
// 找找有没有同名的,同名抛弃
int t;
int *p=&t;
if(LookUp(file,name,entry.start,entry.len,p).attribute!=0){// 找到同名
fprintf(fp,"\n发现同名,创建失败,位置在%d字节处",t);
return -1;
}
// 到这里没返回就找到一个空位了
int piece1 = Give_Empty_Block(); // 找一个新块
if(piece1==-1){ // 找不到
fprintf(fp,"\n磁盘已满,无法创建");
return -1;
}else{
Occupy_Block(file,piece1); // 占用新块,刚找到的新块,就不看在不在了
struct catalog_entry directory[1];// 新目录项
directory[0] = Generate_Catalog_Entry(name,extend,attribute,piece1,1);// 创建的目录项
fseek(file,position,SEEK_SET); // 文件指针移动
fwrite(directory,8,1,file); // 目录的保存
return piece1;
}
}
// 删除文件,成功返回1否则-1 文件名,目录
// 拒绝删除目录文件
int Delete(FILE* file,char* name,struct catalog_entry entry){
int t; // 字节位置
int *p=&t;
char k[1];
struct catalog_entry directory[1]; // 读到的目录项
directory[0] = LookUp(file,name,entry.start,entry.len,p);// 找位置
if(directory[0].attribute == 0){ // 不存在
fprintf(fp,"\n未找到删除对象");
return -1;
}else{
if(directory[0].attribute == 1){
fprintf(fp,"\n拒绝使用文件删除来删除目录");
return -1;
}
k[0] = 0;
directory[0].attribute = 0;
fseek(file,t+5,SEEK_SET); // 文件指针移动,将属性改为不存在
fwrite(k,1,1,file); // 目录更改完毕
Drop_Index(file,directory[0].start); // 删除索引表链接,同时取消块占用
// 这里不做空白目录页的删除(目录整理,由用户手动执行)
}
return 1;
}
// 建立目录 成功返回块号 否则-1 文件名,目录,套用创建文件,不过微改一点地方
int Makdir(FILE* file,char* name,struct catalog_entry entry){
// 目录都包含当前目录.和父目录.. 采用.=..表示根目录。
char extend[2]={'\0','\0'};
int t=Create(file,name,extend,entry,1); // 生成目录
if(t == -1){
return -1;}
struct catalog_entry root_directory[2];
char name1[3]={'.','\0','\0'};
int i;
root_directory[0] = Generate_Catalog_Entry(name1,extend,1,t,1); // 当前目录
name1[1] = '.';
root_directory[1] = Generate_Catalog_Entry(name1,extend,1,entry.start,1); // 父目录
fseek(file,64*t,SEEK_SET); // 文件指针移动
fwrite(root_directory,8,2,file); // 保存两个特殊目录项
// 占用块时,会格式化0,所以不用管后面的
return t;
}
// 删除目录,成功返回1否则-1 目录名,目录
// 拒绝删除根目录,会递归调用自己,删除所有子目录和文件。
int Deldir(FILE* file,char* name,struct catalog_entry entry){
int t,i,j,start; // 字节位置
int *p=&t;
char k[1];
struct catalog_entry directory[1]; // 读到的目录项
struct catalog_entry directory8[8];
directory[0] = LookUp(file,name,entry.start,entry.len,p);// 找位置
if(directory[0].attribute == 0){ // 不存在
fprintf(fp,"\n未找到删除对象");
return -1;
}else{
if(directory[0].start==2){
fprintf(fp,"\n试图删除根目录,请求遭到拒绝");
return -1;
}
if(directory[0].attribute != 1){
fprintf(fp,"\n拒绝使用目录删除来删除文件");
return -1;
}
// 开始递归删除要删除目录的所有内容
start = directory[0].start; // 要读取目录的块
for(i=0;i1)){
// 递归删除目录,不递归特殊目录项,因为特殊目录项都在第一块前两个,所以看i,j就行
Deldir(file,directory8[j].name,directory[0]);
}else{
if(directory8[j].attribute>1){// 递归删除文件
Delete(file,directory8[j].name,directory[0]);
}
}
}
start = index_variables[start]; // 准备读取下一块
}
Drop_Index(file,directory[0].start); // 删除索引表链接,同时取消块占用
// 在当前目录删除要删除的目录项
k[0] = 0;
directory[0].attribute = 0;
fseek(file,t+5,SEEK_SET); // 文件指针移动,将属性改为不存在
fwrite(k,1,1,file); // 目录更改完毕
// 这里不做空白目录页的删除(目录整理,由用户手动执行)
}
return 1;
}
// 显示文件 给出目录项块号和长度,显示目录项所包含的文件(目录文件和文本文件)无返回
void Type(FILE* file,int start,int len){
struct catalog_entry directory[8]; // 读取到的目录
if(start==0){ // 空了,结束
return ;
}
fseek(file,64*start,SEEK_SET); // 文件指针移动
fread(directory,8,8,file);// 读取
int i;
for(i=0;i<8;i++){
if(directory[i].attribute!=0){// 这个东西存的有
Printf_Entry(directory[i]); // 输出目录项
}
}
Type(file,index_variables[start],len-1);
}
// 给出文件所在的目录和文件名,将字符数组的值赋值给文件,成功1,否则-1
// len单位:字节;可以直接用data的长度。这里会自动+1来带上\0,strlen(data)
int Edit(FILE* file,struct catalog_entry entry,char* name,char* data,int len){
len++;// 怕64个的时候,没有\0终结
int t;
int *p = &t;
struct catalog_entry directory=LookUp(file,name,entry.start,entry.len,p); // 获取文件目录项
if(directory.attribute==0){
fprintf(fp,"\n文件不存在");
return -1;
}
float lenf = ((float)len)/64; // 计算所需块数
int leni = (int)lenf;
leni = lenf - leni > 1e-3 ? (leni+1) : leni; // 向上取整
int i,j;
char m[1];
if(leni>directory.len){// 比原来长,加几块
int iend = Index_End(directory.start);// 找到目录的末页
for(i=directory.len+1;i<=leni;i++)
{
int piece = Give_Empty_Block(); // 给一个空块
if(piece==-1){
fprintf(fp,"\n磁盘已满");
return-1;
}
Occupy_Block(file,piece); // 占用新块,刚找到的新块,就不看在不在了
index_variables[iend] = piece; // 索引延申
Save_Index(file,iend); // 改完索引要保存
// 新增块了,文件长度需要+1
fseek(file,t+7,SEEK_SET); // 文件指针移动到文件的长度属性
m[0]=i;
fwrite(m,1,1,file); // 改变
iend = index_variables[iend];
}
}
else{
if(leni
需要四张图片,
文件夹图标.png
可执行文件.png
空文件夹.png
文本文件.png
不想要图片了删除代码中的读取文件
None_directory_image = tk.PhotoImage(file="空文件夹.png") # 空文件夹图标 directory_image = tk.PhotoImage(file="文件夹图标.png") # 文件夹图标 text_image = tk.PhotoImage(file="文本文件.png") # 文本文件图标 executable_image = tk.PhotoImage(file="可执行文件.png") # 可执行文件图标
Establish_Current_Directory_Bar的判断
if len(item[i]) > 1: # 是目录 if len(item[i][1]) > 0: now_image = directory_image # 文件夹 else: now_image = None_directory_image # 空文件夹 elif item[i][0].extend == b'e': # 是可执行文件 now_image = executable_image else: now_image = text_image # 是文本文件
以及Establish_Current_Directory_Bar的使用(删除这个别忘了右括号不能删)
image=now_image)
import ctypes # 用来调用c
import re # 正则匹配用
import sys # 输出重定向
import tkinter as tk # gui用
import tkinter.messagebox # 弹出来的对话框
import tkinter.filedialog # 文件相关窗口
from tkinter import ttk # 仅仅用到了树视图
import time # 记录时间和线程睡眠用
from threading import Thread # 进程
# 用于重定向输出到文本框
class Redirect:
# Redirect(文本控件)
def __init__(self, text): # 构造函数
self.text = text
# 备份
self.stdout = sys.stdout
self.stderr = sys.stderr
def write(self, data):
self.text.insert('end', data)
self.text.see(tk.END)
self.text.update() # 更新显示的文本
def restoreStd(self):
# 还原
sys.stdout = self.stdout
sys.stderr = self.stdout
# 读取C的输出
def Out_Put_C():
try:
# 读取文件内容
with open('output.txt', 'r', encoding='utf-8') as f:
print(f.read())
except FileNotFoundError:
print('文件 output.txt 不存在')
# 目录项结构体
class catalog_Entry(ctypes.Structure):
_fields_ = [("name", ctypes.c_char * 3),
("extend", ctypes.c_char * 2),
("attribute", ctypes.c_ubyte),
("start", ctypes.c_ubyte),
("len", ctypes.c_ubyte), ]
# 从byte中取第bit位(从右数)
def Byte_Bit(byte, bit):
# 原理:
# 11001000 & 00001000
if byte & (1 << bit):
return 1
else:
return 0
# 创建文件编辑窗口
def File_Editing(entry, directory, name):
def Close_Callback(): # 关闭的回调函数
user_interface_bar.input_entry['state'] = 'normal' # 启用用户输入
edit_window.destroy() # 销毁窗口
def Save_File(): # 保存+关闭
content = edit_window.text.get('1.0', 'end-1c') # 读取全部文本,不加-1末尾会多一个回车
data = ctypes.c_char_p(content.encode())
new_data = ctypes.cast(data, ctypes.POINTER(ctypes.c_char * len(content))).contents
Operating_System_C.Edit(file, entry, name, new_data, ctypes.c_int(len(content)))
# 保存数据
Change_Disk_Bar() # 位视图索引表更新
Change_Current_Directory_Bar() # 目录更新
Close_Callback()
# 已经判断过是文件了
# Operating_System_C.Read_File(file,entry,char* data) # 读取文件内容
edit_window = tk.Toplevel(main_window) # 生成编辑窗口
edit_window.title("文件编辑")
edit_window.geometry("400x200")
user_interface_bar.input_entry['state'] = 'disabled' # 禁用用户输入
edit_window.protocol("WM_DELETE_WINDOW", Close_Callback) # 绑定关闭回调
edit_window.scrollbar = tk.Scrollbar(edit_window, orient=tk.VERTICAL) # 滚动条y
edit_window.text = tk.Text(edit_window, yscrollcommand=edit_window.scrollbar.set, ) # 用户文本框
edit_window.text.bind("", lambda g: Save_File()) # Ctrl+s回调
data = (ctypes.c_char * (directory.len * 64 + 1))()
Operating_System_C.Read_File(file, directory, data) # 读取文件
edit_window.text.insert('end', data.value.decode())
edit_window.scrollbar.pack(side=tk.RIGHT, fill=tk.Y) # 靠右,拉满y
edit_window.scrollbar.config(command=edit_window.text.yview)
edit_window.text.pack(fill=tk.BOTH, expand=1)
menubar = tk.Menu(edit_window) # 菜单栏
# 文件菜单是菜单栏的子菜单,且不能窗口化
submenu_file = tk.Menu(menubar, tearoff=False)
submenu_file.add_command(label='保存文件', command=Save_File)
submenu_file.add_separator() # 分割线
submenu_file.add_command(label='关闭', command=Close_Callback) # command为要调用的函数
menubar.add_cascade(label='文件', menu=submenu_file) # 菜单添加文件子菜单项
edit_window.config(menu=menubar) # 生成菜单栏,窗口与菜单关联
pass
# 创建文件运行窗口
def Run_File(entry, way, directory):
def Close_Callback(): # 关闭的回调函数
run_window.destroy() # 销毁窗口
def Save_X(x, directory):
# 从后往前按最后一个/分割一次
route = directory.rsplit('/', 1)
if not len(route) == 2: # 如果长度不是2
tkinter.messagebox.showerror('程序运行发生错误', "输出路径'" + directory + "'错误\n")
Close_Callback()
return
entry = Get_Route(route[0]) # 目录
dir = Get_Route(directory) # 文件的目录项
if not entry.attribute == 1 or dir.attribute < 2:
tkinter.messagebox.showerror('程序运行发生错误', "输出路径'" + directory + "'错误\n", )
Close_Callback()
return
name = (ctypes.c_char * 3)()
# 将Python字符串赋值给数组
String_C_char(name, route[1], 3)
content = way + ' x=' + str(x.get())
out_str = ctypes.c_char_p(content.encode())
out_str = ctypes.cast(out_str, ctypes.POINTER(ctypes.c_char * len(content))).contents
Operating_System_C.Edit(file, entry, name, out_str, ctypes.c_int(len(content)))
# 保存数据
Change_Disk_Bar() # 位视图索引表更新
Change_Current_Directory_Bar() # 目录更新
tkinter.messagebox.showinfo("文件保存完成", "代码的输出已经保存到" + way, )
Close_Callback()
def Get_Row(current_row): # 返回下一行文本
try:
row_str = data_bar.text.get(f"{current_row[0]}.0", f"{current_row[0]}.end") # 获得一行文本
current_row[0] += 1 # 下次找下一行
current_instruction.set(row_str) # 文本赋值
except:
row_str = ""
return row_str # 返回文本
def Execute(str):
# 正则表达式,来匹配输入是不是要求的五种之一
pattern = [r'^x=(-?\d+);', r'^x([+]){2};', r'^x([-]){2};', r"!([ABC])(\d+|x);", r'^end\.$']
match = re.match(pattern[0], str)
if match: # x=?
num = int(match.group(1)) # 得到数字部分
x.set(num) # 赋值
return [0]
elif re.match(pattern[1], str): # x++
x.set(x.get() + 1) # 赋值
return [1]
elif re.match(pattern[2], str): # x--
x.set(x.get() - 1) # 赋值
return [2]
else:
match = re.match(pattern[3], str)
if match: # !??
letter = match.group(1)
number = match.group(2)
number1 = re.match(r"^\d+$", number) # 判断是不是正整数
if number1:
return [3, letter, int(number)] # 是正整数
else:
return [3, letter, x.get()] # 不是正整数
elif re.match(pattern[4], str): # end.
return [4]
else: # 未匹配
return [-1]
def working():
while 1:
row_str = Get_Row(current_row)
if row_str == "" or row_str is None:
break
mate = Execute(row_str)
if mate[0] == -1:
# 报错+回调关闭
tkinter.messagebox.showerror('程序运行发生错误', "代码'" + row_str + "'匹配错误\n", )
Close_Callback()
break
if mate[0] == 3: # 使用机子并等待使用完毕
for i in range(101): # 相当于100秒
if i == 100:
# 报错+回调关闭
tkinter.messagebox.showerror('程序运行等待超时', "等待" + str(mate[1]) + "超时", )
Close_Callback()
break
if device[str(mate[1])].get() == 0: # 没有被占用
# 使用设备
using_devices = Thread(target=lambda d=mate[1], t=mate[2]: Change_device_time(d, t))
device[str(mate[1])].set(mate[2])
using_devices.start()
using_devices.join() # 等待运行结束操作系统阻塞展示
break
time.sleep(1)
if mate[0] == 4: # 运行完毕
Save_X(x, directory)
time.sleep(1)
current_row = [1]
run_window = tk.Toplevel(main_window) # 生成运行窗口========================================================
run_window.title("文件运行")
run_window.geometry("600x400")
run_window.rowconfigure(0, weight=1, minsize=100) # row为0,缩放比为1
run_window.rowconfigure(1, weight=1, minsize=100) # row为1,缩放比为1
run_window.rowconfigure(2, weight=1, minsize=100) # row为2,缩放比为1
run_window.columnconfigure(0, weight=1, minsize=300) # column为0,缩放比为1
run_window.columnconfigure(1, weight=1, minsize=200) # column为1,缩放比为1
data_bar = tk.LabelFrame(run_window, text="文件已加载") # 文件显示框架========================================
data_bar.grid(row=0, column=0, rowspan=3) # 三行
data_bar.scrollbar = tk.Scrollbar(data_bar, orient=tk.VERTICAL) # 滚动条y
data_bar.text = tk.Text(data_bar, yscrollcommand=data_bar.scrollbar.set)
data_bar.scrollbar.pack(side=tk.RIGHT, fill=tk.Y) # 靠右,拉满y
data_bar.scrollbar.config(command=data_bar.text.yview)
data_bar.text.bind('', "break")
data_bar.text.pack(fill=tk.BOTH)
data = (ctypes.c_char * (entry.len * 64 + 1))()
Operating_System_C.Read_File(file, entry, data) # 读取文件
data_bar.text.insert('end', data.value.decode())
current_instruction_bar = tk.LabelFrame(run_window, text="当前指令") # 当前指令框架===========================
current_instruction_bar.grid(row=0, column=1)
current_instruction = tk.StringVar()
current_instruction.set("")
current_instruction_bar.entry = tk.Entry(current_instruction_bar, exportselection=0, borderwidth=3,
textvariable=current_instruction, relief='sunken') # 当前指令文本框
current_instruction_bar.entry.bind('', "break")
current_instruction_bar.entry.pack(fill=tk.BOTH)
x_price_bar = tk.LabelFrame(run_window, text="x的值") # x的值框架============================================
x_price_bar.grid(row=1, column=1)
x = tk.IntVar()
x.set(0)
x_price_bar.entry = tk.Entry(x_price_bar, exportselection=0, borderwidth=3,
textvariable=x, relief='sunken') # x的值文本框
x_price_bar.entry.bind('', "break")
x_price_bar.entry.pack(fill=tk.BOTH)
device_bar = tk.LabelFrame(run_window, text="设备") # 当前设备框架============================================
device_bar.grid(row=2, column=1)
lable_A = tk.Label(device_bar, text="A") # A标签
lable_B = tk.Label(device_bar, text="B") # B标签
lable_C = tk.Label(device_bar, text="C") # C标签
device_A = tk.Entry(device_bar, textvariable=device["A"], relief='sunken') # A的值文本框
device_B = tk.Entry(device_bar, textvariable=device["B"], relief='sunken') # B的值文本框
device_C = tk.Entry(device_bar, textvariable=device["C"], relief='sunken') # C的值文本框
device_bar.rowconfigure(0, weight=1, minsize=10)
device_bar.rowconfigure(1, weight=1, minsize=10)
device_bar.columnconfigure(0, weight=1, minsize=30) # column为0,缩放比为1
device_bar.columnconfigure(1, weight=1, minsize=30) # column为1,缩放比为1
device_bar.columnconfigure(2, weight=1, minsize=30) # column为2,缩放比为1
device_A.bind('', "break")
device_B.bind('', "break")
device_C.bind('', "break")
lable_A.grid(row=0, column=0)
lable_B.grid(row=0, column=1)
lable_C.grid(row=0, column=2)
device_A.grid(row=1, column=0)
device_B.grid(row=1, column=1)
device_C.grid(row=1, column=2)
working()
# 根据路径获得目录项
def Get_Route(str_in):
entry = catalog_Entry()
route = str_in.split("/") # 按 / 分离
if route[0] == '..': # 父目录
entry = user_interface_bar.up_entry.entry
elif route[0] == '.': # 当前目录
entry = user_interface_bar.now_entry.entry
else:
if not route[0] == 'S': # 初始不是根目录
print(" 格式错误,文件路径的表示: S 是根目录,S/A 是根目录下的文件或目录A, S/A/B 是根目录下的目录A中的B")
entry.attribute = 0 # 不存在
return entry
entry.name = b'S' # 根目录
entry.start = 2
entry.len = 1
entry.attribute = 1
t = ctypes.c_int()
p = ctypes.pointer(t)
for i in route[1:]:
data = ctypes.c_char_p(i.encode())
name = ctypes.cast(data, ctypes.POINTER(ctypes.c_char * len(i))).contents
entry = Operating_System_C.LookUp(file, name, entry.start, entry.len, p)
return entry
# 将str前l个给char(python 字符串给C字符串)
def String_C_char(char, str, l):
for i in range(l):
if i >= len(str):
char[i] = b'\0'
break
char[i] = str[i].encode()
# 提示
def Prompt(word):
print(" 输入‘提示’了解更多,输入‘help’了解支持的函数。\n"
" 左上角是位视图和索引表,颜色是绿色表示未占用,蓝色表示占用,上面的数字表示下一位的索引\n"
" 右上角是是树形目录结构,修改目录结构后会更新\n"
" 中间是当前目录和父目录,根目录时相同,可使用 . 和 .. 表示\n"
" 文件路径的表示: S 是根目录,S/A 是根目录下的文件或目录A, S/A/B 是根目录下的目录A中的B"
""
)
# 帮助
def Help(word):
print(
"支持的输入:\n"
"-----------------------------------------\n"
"提示\n"
"help\n"
"Printf_Bitwise_View-------------输出位视图\n"
"Printf_Index_variables----------输出索引阵列\n"
"Printf_Entry 路径----------------输出目录\n"
"Catalog_Organization 路径--------目录整理\n"
"Reset_Disk----------------------重建磁盘\n"
"Create 目录路径 文件名 扩展名------创建文件\n"
"Delete 路径----------------------删除文件\n"
"Makdir 目录路径 目录名-------------建立目录\n"
"Deldir 目录路径-------------------删除目录\n"
"Type 路径------------------------显示文件\n"
"Edit 路径------------------------修改文件\n"
"Copy 文件路径 目标目录路径---------拷贝文件\n"
"Move 文件路径 目标目录路径---------移动文件或目录\n"
"Change 文件路径 属性--------------更改文件属性\n"
"Alter 文件路径 扩展名-------------更改文件扩展名\n"
"Run 文件路径 结果输出路径----------执行文件\n"
"CD 路径--------------------------前往目录\n"
"Release 设备名-------------------强行释放设备\n"
)
# Printf_Bitwise_View-------------输出位视图
def Printf_Bitwise_View(word):
if len(word) > 1:
print(" ".join(word[1:]), "是多余的参数\n")
print("函数用法:Printf_Bitwise_View-------------输出位视图")
return
Operating_System_C.Printf_Bitwise_View()
# Printf_Index_variables----------输出索引阵列
def Printf_Index_variables(word):
if len(word) > 1:
print(" ".join(word[1:]), "是多余的参数\n")
print("函数用法:Printf_Index_variables----------输出索引阵列")
return
Operating_System_C.Printf_Index_variables()
# Printf_Entry 路径----------------输出目录
def Printf_Entry(word):
if len(word) > 2:
print(" ".join(word[2:]), "是多余的参数\n")
print("函数用法:Printf_Entry 路径----------------输出目录")
return
if len(word) < 2:
print("参数过少")
print("函数用法:Printf_Entry 路径----------------输出目录")
return
entry = Get_Route(word[1])
Operating_System_C.Printf_Entry(entry)
# Catalog_Organization 路径--------目录整理
def Catalog_Organization(word):
if len(word) > 2:
print(" ".join(word[2:]), "是多余的参数\n")
print("函数用法:Catalog_Organization 路径--------目录整理")
return
if len(word) < 2:
print("参数过少")
print("函数用法:Catalog_Organization 路径--------目录整理")
return
entry = Get_Route(word[1])
if not entry.attribute == 1: # 不是目录
print("路径不是目录")
return
Operating_System_C.Catalog_Organization(file, entry)
Change_Disk_Bar() # 位视图索引表更新
Change_Current_Directory_Bar() # 目录更新
# Reset_Disk----------------------重建磁盘
def Reset_Disk(word):
if len(word) > 1:
print(" ".join(word[1:]), "是多余的参数\n")
print("函数用法:Reset_Disk----------------------重建磁盘")
return
Operating_System_C.Reset_Disk()
Change_Disk_Bar() # 位视图索引表更新
Change_Current_Directory_Bar() # 目录更新
# Create 目录路径 文件名 扩展名------创建文件
def Create(word):
if len(word) > 4:
print(" ".join(word[4:]), "是多余的参数\n")
print("函数用法:Create 目录路径 文件名 扩展名------创建文件")
return
if len(word) < 4:
print("参数过少")
print("函数用法:Create 目录路径 文件名 扩展名------创建文件")
return
entry = Get_Route(word[1])
if not entry.attribute == 1:
print("路径错误")
return
# 将Python字符串赋值给数组
name = (ctypes.c_char * 3)()
String_C_char(name, word[2], 3)
extend = (ctypes.c_char * 2)()
String_C_char(extend, word[3], 2)
Operating_System_C.Create(file, name, extend, entry, ctypes.c_char(2))
Change_Disk_Bar() # 位视图索引表更新
Change_Current_Directory_Bar() # 目录更新
# Delete 路径----------------------删除文件
def Delete(word):
if len(word) > 2:
print(" ".join(word[2:]), "是多余的参数\n")
print("函数用法:Delete 路径----------------------删除文件")
return
if len(word) < 2:
print("参数过少")
print("函数用法:Delete 路径----------------------删除文件")
return
# 从后往前按最后一个/分割一次
route = word[1].rsplit('/', 1)
if not len(route) == 2: # 如果长度不是2
print("路径错误")
return
entry = Get_Route(route[0]) # 目录
if not entry.attribute == 1:
print("路径错误")
return
# 将Python字符串赋值给数组
name = (ctypes.c_char * 3)()
String_C_char(name, route[1], 3)
# c中会拒绝删除目录
Operating_System_C.Delete(file, name, entry)
Change_Disk_Bar() # 位视图索引表更新
Change_Current_Directory_Bar() # 目录更新
# Makdir 目录路径 目录名-------------建立目录
def Makdir(word):
if len(word) > 3:
print(" ".join(word[3:]), "是多余的参数\n")
print("函数用法:Makdir 目录路径 目录名-------------建立目录")
return
if len(word) < 3:
print("参数过少")
print("函数用法:Makdir 目录路径 目录名-------------建立目录")
return
entry = Get_Route(word[1])
if not entry.attribute == 1:
print("路径错误")
return
name = (ctypes.c_char * 3)()
# 将Python字符串赋值给数组
String_C_char(name, word[2], 3)
Operating_System_C.Makdir(file, name, entry)
Change_Disk_Bar() # 位视图索引表更新
Change_Current_Directory_Bar() # 目录更新
# Deldir 目录路径-------------------删除目录
def Deldir(word):
if len(word) > 2:
print(" ".join(word[2:]), "是多余的参数\n")
print("函数用法:Deldir 目录路径-------------------删除目录")
return
if len(word) < 2:
print("参数过少")
print("函数用法:Deldir 目录路径-------------------删除目录")
return
# 从后往前按最后一个/分割一次
route = word[1].rsplit('/', 1)
if not len(route) == 2: # 如果长度不是2
print("路径错误")
return
entry = Get_Route(route[0]) # 目录
if not entry.attribute == 1:
print("路径错误")
return
name = (ctypes.c_char * 3)()
# 将Python字符串赋值给数组
String_C_char(name, route[1], 3)
Operating_System_C.Deldir(file, name, entry)
Change_Disk_Bar() # 位视图索引表更新
Change_Current_Directory_Bar() # 目录更新
# Type 路径------------------------显示文件
def Type(word):
if len(word) > 2:
print(" ".join(word[2:]), "是多余的参数\n")
print("函数用法:Type 路径------------------------显示文件")
return
if len(word) < 2:
print("参数过少")
print("函数用法:Type 路径------------------------显示文件")
return
entry = Get_Route(word[1])
if not entry.attribute == 1: # 不是目录
print("路径不是目录")
return
Operating_System_C.Type(file, entry.start, entry.len)
pass
# Edit 路径------------------------修改文件
def Edit(word):
if len(word) > 2:
print(" ".join(word[2:]), "是多余的参数\n")
print("函数用法:Edit 路径------------------------修改文件")
return
if len(word) < 2:
print("参数过少")
print("函数用法:Edit 路径------------------------修改文件")
return
# 从后往前按最后一个/分割一次
route = word[1].rsplit('/', 1)
if not len(route) == 2: # 如果长度不是2
print("路径错误")
return
entry = Get_Route(route[0]) # 目录
directory = Get_Route(word[1]) # 文件的目录项
if not entry.attribute == 1 or directory.attribute < 2:
print("路径错误")
return
name = (ctypes.c_char * 3)()
# 将Python字符串赋值给数组
String_C_char(name, route[1], 3)
File_Editing(entry, directory, name) # 创建文件编辑窗口
# Copy 文件路径 目标目录路径---------拷贝文件
def Copy(word):
if len(word) > 3:
print(" ".join(word[3:]), "是多余的参数\n")
print("函数用法:Copy 文件路径 目标目录路径---------拷贝文件")
return
if len(word) < 3:
print("参数过少")
print("函数用法:Copy 文件路径 目标目录路径---------拷贝文件")
return
document = Get_Route(word[1]) # 文件的目录项
entry = Get_Route(word[2]) # 目标目录
if not entry.attribute == 1:
print("路径错误")
return
Operating_System_C.Copy(file, document, entry)
Change_Disk_Bar() # 位视图索引表更新
Change_Current_Directory_Bar() # 目录更新
# Move 文件路径 目标目录路径---------移动文件或目录
def Move(word):
if len(word) > 3:
print(" ".join(word[3:]), "是多余的参数\n")
print("函数用法:Move 文件路径 目标目录路径---------移动文件或目录")
return
if len(word) < 3:
print("参数过少")
print("函数用法:Move 文件路径 目标目录路径---------移动文件或目录")
return
route = word[1].rsplit('/', 1)
if not len(route) == 2: # 如果长度不是2
print("路径错误")
return
directory = Get_Route(route[0]) # 目录
if not directory.attribute == 1:
print("路径错误")
return
name = (ctypes.c_char * 3)()
# 将Python字符串赋值给数组
String_C_char(name, route[1], 3)
entry = Get_Route(word[2]) # 目标目录
if not entry.attribute == 1:
print("路径错误")
return
Operating_System_C.Move(file, directory, name, entry)
Change_Disk_Bar() # 位视图索引表更新
Change_Current_Directory_Bar() # 目录更新
# Change 文件路径 属性--------------更改文件属性
def Change(word):
if len(word) > 3:
print(" ".join(word[3:]), "是多余的参数\n")
print("函数用法:Change 文件路径 属性--------------更改文件属性")
return
if len(word) < 3:
print("参数过少")
print("函数用法:Change 文件路径 属性--------------更改文件属性")
return
# 从后往前按最后一个/分割一次
route = word[1].rsplit('/', 1)
if not len(route) == 2: # 如果长度不是2
print("路径错误")
return
entry = Get_Route(route[0]) # 目录
if not entry.attribute == 1:
print("路径错误")
return
name = (ctypes.c_char * 3)()
# 将Python字符串赋值给数组
String_C_char(name, route[1], 3)
try:
attribute = int(word[2])
except:
print("属性的值存在问题,属性只能是大于1的正整数")
return
Operating_System_C.Change(file, name, attribute, entry)
Change_Disk_Bar() # 位视图索引表更新
Change_Current_Directory_Bar() # 目录更新
# Alter 文件路径 扩展名-------------更改文件扩展名
def Alter(word):
if len(word) > 3:
print(" ".join(word[3:]), "是多余的参数\n")
print("函数用法:Alter 文件路径 扩展名-------------更改文件扩展名")
return
if len(word) < 3:
print("参数过少")
print("函数用法:Alter 文件路径 扩展名-------------更改文件扩展名")
return
# 从后往前按最后一个/分割一次
route = word[1].rsplit('/', 1)
if not len(route) == 2: # 如果长度不是2
print("路径错误")
return
entry = Get_Route(route[0]) # 目录
if not entry.attribute == 1:
print("路径错误")
return
name = (ctypes.c_char * 3)()
# 将Python字符串赋值给数组
String_C_char(name, route[1], 3)
extend = (ctypes.c_char * 2)()
String_C_char(extend, word[2], 2)
Operating_System_C.Alter(file, name, extend, entry)
Change_Disk_Bar() # 位视图索引表更新
Change_Current_Directory_Bar() # 目录更新
# Run 文件路径 结果输出路径----------执行文件
def Run(word):
if len(word) > 3:
print(" ".join(word[2:]), "是多余的参数\n")
print("函数用法:Run 文件路径 结果输出路径----------执行文件")
return
if len(word) < 3:
print("参数过少")
print("函数用法:Run 文件路径 结果输出路径----------执行文件")
return
entry = Get_Route(word[1])
if entry.attribute < 2 or not entry.extend == b'e': # 不是文件
print("不是可执行文件")
return
directory = word[2]
# 创建线程
run_file_thread = Thread(
target=lambda entry=entry, way=word[1], directory=directory: Run_File(entry, way, directory))
# 运行文件
run_file_thread.start()
pass
# CD 路径--------------------------前往目录
def CD(word):
if len(word) > 2:
print(" ".join(word[2:]), "是多余的参数\n")
print("函数用法:CD 路径--------------------------前往目录")
return
if len(word) < 2:
print("参数过少")
print("函数用法:CD 路径--------------------------前往目录")
return
route = word[1].split("/")
if route[0] == '..': # 父目录
str_in = user_interface_bar.up_entry.get() + word[1][2:]
elif route[0] == '.': # 当前目录
str_in = user_interface_bar.now_entry.get() + word[1][1:]
else:
str_in = word[1]
entry = Get_Route(str_in) # 目标目录
if not entry.attribute == 1:
print("路径错误")
return
route = str_in.rsplit('/', 1)
user_interface_bar.now_entry.set(str_in)
user_interface_bar.now_entry.entry = entry
user_interface_bar.up_entry.set(route[0])
user_interface_bar.up_entry.entry = Get_Route(route[0])
# Release 设备名-------------------释放设备
def Release(word):
if len(word) > 2:
print(" ".join(word[2:]), "是多余的参数\n")
print("函数用法:Release 设备名-------------------强行释放设备")
return
if len(word) < 2:
print("参数过少")
print("函数用法:Release 设备名-------------------强行释放设备")
return
if word[1] == 'A' or word[1] == 'B' or word[1] == 'C':
device[word[1]].set(0)
else:
print(word[1], '设备不存在')
# 用于线程的设备到时归0
def Change_device_time(d, t):
for i in range(t):
if device[d].get() <= 0: # 被强制结束了
device[d].set(0)
break
time.sleep(1) # 睡一下
device[d].set(device[d].get() - 1) # 减一下
def Function_Selection(word):
if len(word) == 0: # 没有输入
return
if word[0] in user_function: # 输入的是函数
user_function[word[0]](word)
else:
print(word[0], "不是可行的函数,请使用 help 查询可用函数")
# 分析用户输入
def Input_Analysis(user_input):
word = user_input.split() # 按空格分离
print('>>>', " ".join(word)) # 输出你的输入
Function_Selection(word) # 按输入选择函数
# 输入框回车的执行内容
def Execute(event):
user_input = user_interface_bar.input.get() # 用户输入
user_interface_bar.input.set("") # 清空输入
if len(user_input) > 0:
if len(old_input[0]) > 20: # 最多存20条
old_input[0].pop()
old_input[0].insert(0, user_input[:])
old_input[1] = -1
Operating_System_C.Openfp() # c语言打开c的输出文件
# 分析用户输入
Input_Analysis(user_input)
Operating_System_C.Closefp() # c语言关闭c的输出文件
Out_Put_C() # python读取并输出C的输出
pass
def Tab_input(event):
now_input = user_interface_bar.input.get() # 获得当前输入
now_input = now_input.split() # 按空格分离
if not len(now_input) == 1: # 不是长度为1,没反应
return 'break'
matched = [] # 匹配到的键
for key in user_function: # 遍历所有键
if key.startswith(now_input[0]):
matched.append(key)
if len(matched) < 1:
return 'break'
elif len(matched) == 1:
user_interface_bar.input.set(matched[0]) # 赋值
# 将插入点设置为最后一个字符的位置
user_interface_bar.input_entry.icursor(tk.END)
else:
print(matched)
return 'break'
# 按下上键
def Up_input(event):
if old_input[1] + 1 >= len(old_input[0]): # 到头了
return "break" # 已经是最后的了,不动
old_input[1] += 1
user_interface_bar.input.set(old_input[0][old_input[1]]) # 赋值、
# 将插入点设置为最后一个字符的位置
user_interface_bar.input_entry.icursor(tk.END)
# 按下下键
def Down_input(event):
if old_input[1] < 1:
return "break" # 已经是最后的了,不动
old_input[1] -= 1
user_interface_bar.input.set(old_input[0][old_input[1]]) # 赋值
# 将插入点设置为最后一个字符的位置
user_interface_bar.input_entry.icursor(tk.END)
# 更新磁盘框架的内容
def Change_Disk_Bar():
for i in range(8):
for j in range(16):
disk_bar.index_variables[i * 16 + j].set('[' + str(index_variables[i * 16 + j]) + ']')
disk_bar.label[i * 16 + j]['bg'] = 'blue' if Byte_Bit(bitwise_view[(i * 16 + j) // 8],
7 - (i * 16 + j) % 8) else 'green',
# 生成磁盘框架的内容
def Generate_Disk_Bar():
# 128个块,128个标签。
for j in range(16):
disk_bar.columnconfigure(j, weight=5) # column为j,缩放比为1
for i in range(8):
disk_bar.rowconfigure(i, weight=1) # row为i,缩放比为1
for j in range(16):
disk_bar.index_variables.append(tk.StringVar())
disk_bar.index_variables[i * 16 + j].set('[' + str(index_variables[i * 16 + j]) + ']')
# 父窗口, 文本内容关联的变量, fg 文字颜色, bg 背景颜色,borderwidth 边框大小,ridge 边框样式
disk_bar.label.append(tk.Label(disk_bar, textvariable=disk_bar.index_variables[i * 16 + j],
fg='white', bg='blue' if Byte_Bit(bitwise_view[(i * 16 + j) // 8],
7 - (i * 16 + j) % 8) else 'green',
borderwidth=5, relief='ridge'))
disk_bar.label[i * 16 + j].grid(row=i, column=j, padx=1, pady=1)
# 获取当前的目录
def Obtain_Current_Directory_Bar(updict, start, len):
directory = (catalog_Entry * (len * 8))() # 目录大小
Operating_System_C.Get_Entry(file, directory, start, len) # 获取目录
for i in range(2, len * 8): # 不看父目录和当前目录(前两个)
if directory[i].attribute == 0: # 空了
break
updict[directory[i].name] = [directory[i]]
if directory[i].attribute == 1: # 是目录
updict[directory[i].name].append({})
Obtain_Current_Directory_Bar(updict[directory[i].name][1], directory[i].start, directory[i].len)
# 按item建立新树图
def Establish_Current_Directory_Bar(item, uptree):
for i in item:
if len(item[i]) > 1: # 是目录
if len(item[i][1]) > 0:
now_image = directory_image # 文件夹
else:
now_image = None_directory_image # 空文件夹
elif item[i][0].extend == b'e': # 是可执行文件
now_image = executable_image
else:
now_image = text_image # 是文本文件
now_tree = current_directory_bar.treeview.insert(uptree, tk.END, text=item[i][0].name,
values=(
item[i][0].name, item[i][0].extend, item[i][0].attribute,
item[i][0].start, item[i][0].len,),
image=now_image)
if len(item[i]) > 1: # 长度大于1是目录
Establish_Current_Directory_Bar(item[i][1], now_tree)
pass
# 更新当前目录框架的内容,时间有限,暴力更新,
def Change_Current_Directory_Bar():
current_directory_bar.item.clear() # 空置
Obtain_Current_Directory_Bar(current_directory_bar.item, 2, 1) # 获得当前的数据
current_directory_bar.treeview.delete(*current_directory_bar.treeview.get_children()) # 清空之前的所有树图
current_directory_bar.treeview.update() # 刷新显示
Establish_Current_Directory_Bar(current_directory_bar.item, "") # 递归建立新树
# 生成当前目录框架的内容
def Generate_Current_Directory_Bar():
# 创建style对象
style = ttk.Style()
# 设置文本大小
style.configure("Treeview", font=("Arial", 12), rowheight=30)
# 创建滚动条
current_directory_bar.scrollbar_x = tk.Scrollbar(current_directory_bar, orient=tk.HORIZONTAL) # 滚动条x
current_directory_bar.scrollbar_y = tk.Scrollbar(current_directory_bar, orient=tk.VERTICAL) # 滚动条y
# 创建树视图,带滚动条,带标签
current_directory_bar.treeview = ttk.Treeview(current_directory_bar, show="tree headings", displaycolumns="#all",
columns=('name', 'extend', 'attribute', 'start', 'len'),
xscrollcommand=current_directory_bar.scrollbar_x.set,
yscrollcommand=current_directory_bar.scrollbar_y.set,
style="Treeview")
# column设定列宽,heading设定标题
current_directory_bar.treeview.column("#0", width=100)
current_directory_bar.treeview.heading("#0", text="目录")
current_directory_bar.treeview.column("name", width=60)
current_directory_bar.treeview.heading('name', text="名称")
current_directory_bar.treeview.column("extend", width=60)
current_directory_bar.treeview.heading('extend', text="扩展名")
current_directory_bar.treeview.column("attribute", width=50)
current_directory_bar.treeview.heading('attribute', text="属性")
current_directory_bar.treeview.column("start", width=50)
current_directory_bar.treeview.heading('start', text="起始块")
current_directory_bar.treeview.column("len", width=50)
current_directory_bar.treeview.heading('len', text="长度")
# 将他们显示出来
current_directory_bar.scrollbar_x.pack(side=tk.BOTTOM, fill=tk.X) # 靠下,拉满x
current_directory_bar.scrollbar_x.config(command=current_directory_bar.treeview.xview)
current_directory_bar.scrollbar_y.pack(side=tk.RIGHT, fill=tk.Y) # 靠右,拉满y
current_directory_bar.scrollbar_y.config(command=current_directory_bar.treeview.yview)
# 居中,填充
current_directory_bar.treeview.pack(fill=tk.BOTH, expand=1)
# 调用更新树图
Change_Current_Directory_Bar()
# 初始化c的函数返回值
def Initialization_Operating_System_C():
# 默认c_int
# file 4字节,其他的几个1字节
Operating_System_C.Generate_Catalog_Entry.restype = catalog_Entry
Operating_System_C.LookUp.restype = catalog_Entry
Operating_System_C.Move.restype = catalog_Entry
Operating_System_C.Openfile.restype = ctypes.POINTER(ctypes.c_uint) # 声明函数返回值为指针
Operating_System_C.Index_Variables.restype = ctypes.POINTER(ctypes.c_ubyte)
Operating_System_C.Bitwise_View.restype = ctypes.POINTER(ctypes.c_ubyte)
def Get_Menu(event):
try:
menu.tk_popup(event.x_root, event.y_root, 0)
finally:
# 确保在任何情况下都能隐藏菜单
menu.grab_release()
# 拦截输入
def Intercept_Input(event):
if event.keycode != 67 and event.state != 4: # 67代表复制快捷键,state=4表示按下Ctrl键
return "break" # 如果不是复制快捷键,就拦截事件
'''
┏┓┃┫┣┳┻╋━┗┛
┏━━━━━━━━━━┳━━━━━━━━━━┓
┃ 位视图和 ┃ 目录内容 ┃
┃ 索引表 ┃ ┃
┣━━━━━━━━━━╋━━━━━━━━━━┫
┃ 当前目录 ┃ 上级目录 ┃
┣━━━━━━━━━━┻━━━━━━━━━━┫
┃ 用户接口 ┃
┗━━━━━━━━━━━━━━━━━━━━━┛
'''
# 加载用C写的函数
Operating_System_C = ctypes.cdll.LoadLibrary('./Operating_System_C.dll')
Operating_System_C.Openfp() # c语言打开c的输出文件
Initialization_Operating_System_C() # 初始化返回值
file = Operating_System_C.Openfile() # 读取文件,获得文件指针,没有文件会创建
Operating_System_C.Read_Start(file) # 读取位视图和索引表
index_variables = Operating_System_C.Index_Variables() # 获得位视图和索引表的指针
bitwise_view = Operating_System_C.Bitwise_View()
old_input = [[], -1] # 以前的输入
open("output.txt", 'w').close() # 清空以前的输入
user_function = { # 用户函数表
"提示": Prompt,
"help": Help,
"Printf_Bitwise_View": Printf_Bitwise_View,
"Printf_Index_variables": Printf_Index_variables,
"Printf_Entry": Printf_Entry,
"Catalog_Organization": Catalog_Organization,
"Reset_Disk": Reset_Disk,
"Create": Create,
"Delete": Delete,
"Makdir": Makdir,
"Deldir": Deldir,
"Type": Type,
"Edit": Edit,
"Copy": Copy,
"Move": Move,
"Change": Change,
"Alter": Alter,
"Run": Run,
"CD": CD,
"Release": Release
}
# 主窗口==========================================================================
# 主窗口==========================================================================
main_window = tk.Tk() # 调用Tk()创建主窗口
main_window.title("操作系统") # 给主窗口起一个名字
main_window.geometry("1000x800+200+100") # 大小
# main_window.config(menu=Generate_Menu(main_window)) # 生成菜单栏,窗口与菜单关联
main_window.rowconfigure(0, weight=1, minsize=200) # row为0,缩放比为1
main_window.rowconfigure(1, weight=1, minsize=200) # row为1,缩放比为1,最小200
main_window.columnconfigure(1, weight=1) # column为1,缩放比为1
None_directory_image = tk.PhotoImage(file="空文件夹.png") # 空文件夹图标
directory_image = tk.PhotoImage(file="文件夹图标.png") # 文件夹图标
text_image = tk.PhotoImage(file="文本文件.png") # 文本文件图标
executable_image = tk.PhotoImage(file="可执行文件.png") # 可执行文件图标
# 位视图和索引表===================================================================
# 位视图和索引表===================================================================
disk_bar = tk.LabelFrame(main_window, text="磁盘") # 放左边磁盘的框架
disk_bar.grid(row=0, column=0, sticky="nsew")
disk_bar.index_variables = [] # 128个标签的文本
disk_bar.label = [] # 128个标签列表
Generate_Disk_Bar() # 生成磁盘框架的内容
# 树型目录结构====================================================================
# 树型目录结构====================================================================
current_directory_bar = tk.LabelFrame(main_window, text="当前目录内容") # 放右边目录树的框架
current_directory_bar.grid(row=0, column=1, sticky="nsew")
current_directory_bar.treeview = ttk.Treeview()
current_directory_bar.item = {} # 所有项目字典
Generate_Current_Directory_Bar() # 生成当前目录框架的内容
# 用户接口=======================================================================
# 用户接口=======================================================================
# 用户接口比较特殊,放在主体中
user_interface_bar = tk.LabelFrame(main_window, text="用户接口") # 放下边用户接口的框架
user_interface_bar.grid(row=1, column=0, columnspan=2, sticky="nsew")
user_interface_bar.rowconfigure(0, weight=1, minsize=50) # row为0,缩放比为1
user_interface_bar.rowconfigure(1, weight=2, minsize=150) # row为1,缩放比为3
user_interface_bar.columnconfigure(0, weight=1) # column为0,缩放比为1
user_interface_bar.columnconfigure(1, weight=1) # column为1,缩放比为1
# 当前目录=========================================
user_interface_bar.now_entry_bar = tk.LabelFrame(user_interface_bar, text="当前目录") # 当前目录
user_interface_bar.now_entry = tk.StringVar() # 当前目录变量
user_interface_bar.now_entry.set('S')
user_interface_bar.now_entry.entry = catalog_Entry()
user_interface_bar.now_entry.entry.name = b'S' # 根目录
user_interface_bar.now_entry.entry.start = 2
user_interface_bar.now_entry.entry.len = 1
user_interface_bar.now_entry.entry.attribute = 1
user_interface_bar.now_lable = tk.Label(user_interface_bar.now_entry_bar, textvariable=user_interface_bar.now_entry,
bg='white', borderwidth=2, relief='ridge') # 当前目录标签
# 上级目录=========================================
user_interface_bar.up_entry_bar = tk.LabelFrame(user_interface_bar, text="上级目录") # 上级目录
user_interface_bar.up_entry = tk.StringVar() # 上级目录变量
user_interface_bar.up_entry.set('S')
user_interface_bar.up_entry.entry = catalog_Entry()
user_interface_bar.up_entry.entry.name = b'S' # 根目录
user_interface_bar.up_entry.entry.start = 2
user_interface_bar.up_entry.entry.len = 1
user_interface_bar.up_entry.entry.attribute = 1
user_interface_bar.up_lable = tk.Label(user_interface_bar.up_entry_bar, textvariable=user_interface_bar.up_entry,
bg='white', borderwidth=2, relief='ridge') # 上级目录标签
# 文本控制台=========================================
user_interface_bar.text_bar = tk.LabelFrame(user_interface_bar, text="文本控制台") # 文本控制台
user_interface_bar.text_bar.rowconfigure(0, weight=1) # row为0,缩放比为1
user_interface_bar.text_bar.rowconfigure(1, weight=1, minsize=30) # row为2,缩放比为1
user_interface_bar.text_bar.columnconfigure(0, weight=1) # column为0,缩放比为1
user_interface_bar.out_bar = tk.LabelFrame(user_interface_bar.text_bar, text="输出框") # 文本输出框框架
user_interface_bar.scrollbar = tk.Scrollbar(user_interface_bar.out_bar, orient=tk.VERTICAL) # 滚动条y
# 字体本来想显示一点文字图之类的,但是会错位,就算了
user_interface_bar.output_entry = tk.Text(user_interface_bar.out_bar, font=('Microsoft Yahei UI', '12',),
yscrollcommand=user_interface_bar.scrollbar.set) # 输出文本框本体
# 创建右键菜单
menu = tk.Menu(user_interface_bar.output_entry, tearoff=0)
menu.add_command(label="复制", command=lambda: user_interface_bar.output_entry.event_generate(""))
# 绑定右键事件
user_interface_bar.output_entry.bind("", Get_Menu)
user_interface_bar.output_entry.bind('', Intercept_Input) # 键盘输入拦截
sys.stdout = Redirect(user_interface_bar.output_entry) # 重定向输出到输出文本框
user_interface_bar.input = tk.StringVar() # 用户输入的变量
user_interface_bar.input.set("")
user_interface_bar.input_entry = tk.Entry(user_interface_bar.text_bar, exportselection=0, borderwidth=3,
textvariable=user_interface_bar.input, relief='sunken') # 用户输入文本框
user_interface_bar.input_entry.bind("",Execute) # 回车的回调函数
user_interface_bar.input_entry.bind("",Tab_input) # Tab索引
user_interface_bar.input_entry.bind("", Up_input) # 代码看看上面的
user_interface_bar.input_entry.bind("", Down_input) # 代码看看后面的
# 部件安放====================================================
user_interface_bar.now_entry_bar.grid(row=0, column=0, sticky="nsew")
user_interface_bar.up_entry_bar.grid(row=0, column=1, sticky="nsew")
user_interface_bar.now_lable.pack(fill=tk.BOTH, expand=1)
user_interface_bar.up_lable.pack(fill=tk.BOTH, expand=1)
user_interface_bar.text_bar.grid(row=1, column=0, columnspan=2, sticky="nsew")
user_interface_bar.out_bar.grid(row=0, column=0, sticky="nsew")
user_interface_bar.scrollbar.pack(side=tk.RIGHT, fill=tk.Y) # 靠右,拉满y
user_interface_bar.output_entry.pack(fill=tk.BOTH)
user_interface_bar.scrollbar.config(command=user_interface_bar.output_entry.yview)
user_interface_bar.input_entry.grid(row=1, column=0, sticky="nsew")
# =========================================
# =========================================
Operating_System_C.Closefp() # c语言关闭c的输出文件
Out_Put_C()
device = {"A": tk.IntVar(), "B": tk.IntVar(), "C": tk.IntVar()} # 三个设备
device["A"].set(0)
device["B"].set(0)
device["C"].set(0)
print("欢迎使用i道i操作系统,输入‘提示’了解更多,输入‘help’了解支持的函数。")
main_window.mainloop() # 开启主循环,让窗口处于显示状态
Operating_System_C.Closefile() # 关闭文件
sys.stdout.restoreStd() # 恢复标准输出
这个是加了图片的示例
下面几张是加图片前的示例
程序进程展示
操作系统阻塞展示