简易操作系统:使用Python 做的图形界面 C 做的内核

目录

实验要求

一、文件管理和用户接口

⑴文件的逻辑结构

⑵磁盘模拟

⑶目录结构

⑷磁盘分配

⑸磁盘空闲存储空间管理

⑹用户接口

⑺屏幕显示

 代码部分

        python调用c的方法:

​编辑

c语言部分,文件名 Operating_System_C.c

python语言部分

运行实例:


实验要求

一、文件管理和用户接口

   文件管理和用户接口部分实现的主要是单用户的磁盘文件管理部分,包括文件的逻辑结构、物理结构、目录、磁盘分配回收、文件的保护和用户接口的实现。

文件的逻辑结构

  文件的逻辑结构采用流式结构;

   文件均采用文本文件;

   系统中有两种文件,一种是存放任意字符的文件,一种是可执行文件。可执行文件的内容就是模拟系统内进程的程序体。

文件中的“可执行”文件,包含的命令非常简单,包括:

x=?;  x 赋值一位数
x++;  x 1
x--;    x 1
!?? 第一个?为 A,B,C 中某个设备,第二个?为一位数,表示使用设备的时间(由于没有实际设备,所以无法知道设备何时工作完成,所以假定一个数,这个数随着系统时间增加而递减,减到 0 时,认为是设备工作完成)
end.   表示文件结束,同时将结果写入文件 out ,其中包括文件路径名和 x 的值。

磁盘模拟

    用一个文本文件disk模拟磁盘,磁盘的每个盘块64字节,模拟磁盘共有128块。第01块存放文件分配表,第2块存放根目录,其余存放子目录和文件。

目录结构

      目录结构采用树型目录结构。

        ①目录项内容(8个字节):

        目录名、文件名:3 个字节;
        扩展名:2 个字节(可执行文件扩展名为 e ,目录没有扩展名);
        目录、文件属性:1 字节;
        起始盘块号:1 个字节;
        文件长度:1 字节(目录没有长度)。

根目录

  根目录位置固定,占用模拟磁盘第2块,大小固定,共8项;

③子目录

  位置不固定,大小不固定。(至少建立一级子目录,最好支持多级子目录)

磁盘分配

       磁盘的分配采用链接结构(显式链接)的分配。

⑸磁盘空闲存储空间管理

    磁盘空闲存储空间管理采用位示图方法。

  位示图和显示链接的指针合在一起组成文件分配表,占用磁盘空间第01

用户接口

    用户接口提供用户命令接口,要求实现以下命令:

创建文件:create     拷贝文件:copy     

删除文件:delete     移动文件:move  

显示文件:type        改变文件属性:change  

建立目录:makdir     改变目录路径:chadir       

删除目录:deldir(deltree修改文件 edit

  运行可执行文件:可执行文件的文件名(创建进程)。

屏幕显示

    屏幕显示要求包括:

n 用户命令接口:用于系统运行时用户输入命令
n 磁盘目录显示:要求显示磁盘的树型目录结构
n 磁盘使用情况:显示磁盘每一个磁盘块的空间是占用还是空闲

 代码部分

c和python各1000多行

        python调用c的方法:

        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/

 下载

这是我下载的文件,仅需1积分(友情链接) 

 并把压缩包解压,将含有g++.exe的文件路径添加到环境变量中

 

 打开cmd 输入gcc --version 若弹出以下内容

表明安装完成

然后就可以用

Operating_System_C = ctypes.cdll.LoadLibrary('./Operating_System_C.dll')

 打开自己写的c文件,调用其中的函数了(函数默认返回值为ctypes.c_int类型,函数的输入也要转化为ctypes的类型才行,具体情况请自己去搜索ctypes教程)

c语言部分,文件名 Operating_System_C.c

需要在控制台输入

gcc Operating_System_C.c -shared -o Operating_System_C.dll

生成.dll文件才能被python调用

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


// 目录项
/*
目录名、文件名: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]<<j+1;
                if(j!=0){
                    index_pointer[0].datas[j-1] = 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]<<j+1;
            if(j!=0){
                index_pointer[0].datas[j-1] = 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]<<j+1;
            if(j!=0){
                index_pointer[0].datas[j-1] = 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;i<entry.len;i++){   // 遍历每个块
        fseek(file,64*start,SEEK_SET);    // 文件指针移动
        fread(directory[i],8,8,file);// 读取
        start = index_variables[start]; // 下一块
    }
    i=0;j=entry.len*8-1;
    while(i!=j){// 撞上就停
        if(directory[i/8][i%8].attribute!=0){//i没指向一个空位
            i++;    // 前进
        }else{
            if(directory[j/8][j%8].attribute==0){//j没指向一个存在的位置
                j--;
            }else{// i指向空位,j指向一个存在的位置
                directory[i/8][i%8]=directory[j/8][j%8];    // 替换
                directory[j/8][j%8].attribute = 0;
            }
        }
    }
    i = (i-1)/8;// 看看指针停在第几块,就保存在前几块
    start=entry.start;
    for(j=0;j<=i;j++){// 遍历块保存新目录
        if(j==i){
            k = start;
        }
        fseek(file,64*start,SEEK_SET);    // 文件指针移动
        fwrite(directory[j],8,8,file);  // 保存
        start = index_variables[start]; // 下一块
    }
    if(start!=0){// 不是最后一块
        index_variables[k] = 0;
        Save_Index(file,k);    // 保存索引表
        Drop_Index(file,start);   // 删后面索引
    }
    Directory_Length_Chenge(file,entry,i-entry.len+1);   // 文件长度改变
}



// 重建根目录
void Rebuild_Root_Directory(FILE* file){
    // 根目录位置固定,占用模拟磁盘第2块,大小固定,共8项;
    // 目录都包含当前目录.和父目录..  采用.=..表示根目录。
    struct catalog_entry root_directory[2];
    char name[3]={'.','\0','\0'};
    char extend[2]={'\0','\0'};
    int i;
    // 只用一个struct catalog_entry更经济,但这么写更直观
    root_directory[0] = Generate_Catalog_Entry(name,extend,1,2,1); // 当前目录
    name[1] = '.';
    root_directory[1] = Generate_Catalog_Entry(name,extend,1,2,1); // 父目录
    fseek(file,64*2,SEEK_SET);    // 文件指针移动
    fwrite(root_directory,8,2,file);    // 保存两个特殊目录项
    name[0] = 0;
    for(i=16;i<128;i++){
        fwrite(name,1,1,file);
    }

}



void Reset_Disk()   // 重置磁盘,直接新建磁盘文件,删除之前所有记录
{
    FILE* file;
    file = fopen("disk.txt","w+");  // 创建磁盘文件
    fprintf(fp,"\n已重新创建磁盘文件 disk.txt ");
    // disk是模拟磁盘,开始生成模拟磁盘的数据
    // 磁盘的分配采用链接结构(显式链接)的分配。
    // 共有128块,每个盘块64字节,共8192字节
    // 第0、1块存放文件分配表,位示图和显示链接的指针合在一起组成文件分配表
    // 第2块存放根目录,其余存放子目录和文件
    // 位视图要有128位,即16字节
    // 初始第0、1、2块都在占用
    int i,j;
    bitwise_view[0].data = 0b11100000;// 前三块必定被占用,
    for(i=1;i<16;i++){
        bitwise_view[i].data = 0;   // 其余暂时置0
    }
    // 数据数组,每个元素字节,元素个数,输出到文件位置
    // 128个块,索引只需7位,刚好(7*128)/4+16=128占两个块
    for(i=0;i<128;i++){ //索引置0
        index_variables[i] = 0;
    }
    Save_Start(file);// 保存位视图和索引表
    Rebuild_Root_Directory(file);// 重建根目录
    // 填补剩下的磁盘
    char t[1] = {0b0};
    fseek(file,64*3,SEEK_SET);    // 文件指针移动
    for(i=192;i<8192;i++){
        fwrite(t,1,1,file);
    }
    fclose(file);
}



// 创建文件,成功返回块号,否则-1   文件名,扩展名,目录 ,文件属性(目录1,文件>1)
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;i<directory[0].len;i++){
            fseek(file,start*64,SEEK_SET);    // 指针准备读取目录内容
            fread(directory8,8,8,file);// 读取
            for(j=0;j<8;j++){// 遍历块,根据类型来递归删除目录或者文件
                if(directory8[j].attribute==1&&(i!=0||j>1)){
                // 递归删除目录,不递归特殊目录项,因为特殊目录项都在第一块前两个,所以看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<directory.len){// 比原来短,去几块
            j = directory.start;
            for(i=0;i<leni-1;i++){
                j=index_variables[j];   // 一直找,直到找到需要删除的索引位置
            }
            Drop_Index(file,index_variables[j]); // 删除索引,解除占用
            index_variables[j] = 0; // 删除该索引
            Save_Index(file,j);    // 保存索引表
            fseek(file,t+7,SEEK_SET);
            m[0]=leni;
            fwrite(m,1,1,file);  // 改变
        }
    }
    t = directory.start;
    for(i=0;i<leni;i++){    // 开始赋新值
        fseek(file,t*64,SEEK_SET);
        if(i==leni-1){  // 最后一块,小心行事
            fwrite(&data[i*64],1,len-i*64-1,file);  // 改变
            m[0]='\0';
            fwrite(m,1,1,file);  // 改变
        }else{
            fwrite(&data[i*64],1,64,file);  // 改变
        }
        t = index_variables[t];
    }
}




// 拷贝文件,将文件拷贝到目录中(不支持目录文件拷贝)
// 返回拷贝的目录项成功,内核是创建一个同名文件,再赋值
struct catalog_entry Copy(FILE* file,struct catalog_entry document,struct catalog_entry entry){
    struct catalog_entry new_document;
    new_document.attribute = 0;
    if(document.attribute == 1){
        fprintf(fp,"\n禁止拷贝目录文件");
        return new_document;
    }
    if(document.attribute == 0){
        fprintf(fp,"\n被拷贝的文件不存在");
        return new_document;
    }
    int t = Create(file,document.name,document.extend,entry,document.attribute);
    if(t == -1){
        return new_document;
    }
    int i,j;
    int *p =&j;// 凑参数
    char data[64*document.len+1];   // 拷贝的文件内容
    data[64*document.len+1]='\0';   // 最后一个赋值
    j = document.start;
    for(i=0;i<document.len;i++){
        fseek(file,j*64,SEEK_SET);
        fread(&data[i*64],1,64,file);  // 读取
        j=index_variables[j];
    }
    Edit(file,entry,document.name,data,strlen(data));
    return LookUp(file,document.name,entry.start,entry.len,p);
}


// 读取文件存到char*
void Read_File(FILE* file,struct catalog_entry entry,char* data){
    int i,j;
    j = entry.start;
    for(i=0;i<entry.len;i++){
        fseek(file,j*64,SEEK_SET);
        fread(&data[i*64],1,64,file);  // 读取
        j=index_variables[j];
    }
}


// 移动文件,将文件移动到目录中(支持目录文件移动)
// 返回移动的目录项成功,内核是移动目录项到指定目录中
struct catalog_entry Move(FILE* file,struct catalog_entry directory,char* name,struct catalog_entry entry){
    int t;
    int *p = &t;
    int d;
    int *q=&d;
    char k[1]={0};
    struct catalog_entry document = LookUp(file,name,directory.start,directory.len,p);// 文件的目录项
    struct catalog_entry new_directory[1];// 新目录项
    new_directory[0] = document;
    if(new_directory[0].attribute == 0){
        fprintf(fp,"\n被移动的文件不存在");
        return document;
    }
    directory.attribute = 0;
    int position = Directory_Overrun(file,entry.start,entry.len);  // 找找空位
    if(position == -1){// 没找到空位
        if(entry.start == 2){   // 是根目录
            fprintf(fp,"\n根目录已满,无法移动");// 根目录只能有1页
            return document;
        }
        else{ // 否则可以新增一页
            int piece = Give_Empty_Block(); // 找一个新块
            if(piece==-1){  // 找不到
                fprintf(fp,"\n磁盘已满,无法移动");
                return document;
            }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
            }
        }
    }
    // 找找有没有同名的,同名抛弃
    if(LookUp(file,name,entry.start,entry.len,q).attribute!=0){// 找到同名
        fprintf(fp,"\n发现同名,移动失败,位置在%d字节处",t);
        return document;
    }
    // 到这里没返回就找到一个空位了
    fseek(file,t+5,SEEK_SET);    // 文件指针移动,将属性改为不存在
    fwrite(k,1,1,file); // 目录更改完毕
    fseek(file,position,SEEK_SET);    // 文件指针移动
    fwrite(new_directory,8,1,file); // 目录的保存
    if(new_directory[0].attribute == 1){ //目录还需要更改目录中的父目录项
        fseek(file,new_directory[0].start*64+8+5,SEEK_SET);    // 文件指针移动
        char a[3]={entry.attribute,entry.start,entry.len};
        fwrite(a,1,3,file); // 目录的保存
    }
    return new_directory[0];
}


// 更改文件扩展名,简单的寻找+赋值,完成1否则-1
int Alter(FILE* file,char* name,char* extend,struct catalog_entry entry)
{
    int t;
    int* p=&t;
    int a = LookUp(file,name,entry.start,entry.len,p).attribute;
    if(a==0){// 未找到
        fprintf(fp,"\n未找到要更改扩展名的文件");
        return -1;
    }
    if(a==1){// 未找到
        fprintf(fp,"\n不能更改目录的扩展名");
        return -1;
    }
    fseek(file,t+3,SEEK_SET);    // 文件指针移动
    fwrite(extend,1,2,file); // 目录的保存
}



// 更改文件属性,简单的寻找+赋值,完成1否则-1
int Change(FILE* file,char* name,int attribute,struct catalog_entry entry)
{
    if(attribute<2){
        fprintf(fp,"\n不被允许的文件属性取值:%d,需要大于等于2",attribute);
        return -1;
    }
    int t;
    int* p=&t;
    int a = LookUp(file,name,entry.start,entry.len,p).attribute;
    if(a==0){// 未找到
        fprintf(fp,"\n未找到要更改属性的文件");
        return -1;
    }
    if(a==1){// 未找到
        fprintf(fp,"\n不能更改目录的属性");
        return -1;
    }
    fseek(file,t+5,SEEK_SET);    // 文件指针移动
    char m[1]={attribute};
    fwrite(m,1,1,file); // 目录的保存
}


// python 调用的打开磁盘文件,返回文件指针
FILE* Openfile()
{
    file = fopen("disk.txt","r+");  //打开磁盘文件
    if(file == NULL)    // 磁盘文件不存在
    {
        Reset_Disk();// 重建磁盘文件
        file = fopen("disk.txt","r+");  //打开磁盘文件
    }
    return file;
}



// python 调用的关闭磁盘文件
void Closefile()
{
    fclose(file);
}


// c输出到文件
void Openfp()
{
    fp = fopen("output.txt","w");  //打开磁盘文件
}


// 关闭输出文件
void Closefp()
{
    fclose(fp);
}


// 索引表
char* Index_Variables()
{
    return index_variables;
}

// 位视图
union bit8* Bitwise_View()
{
    return bitwise_view;
}



// 递归得到目录所有项的列表
void Get_ALL_Entry(FILE* file,struct catalog_entry* entry,int start,int len,int t){
    if(start==0){ // 空了
        return;
    }
    fseek(file,64*start,SEEK_SET);    // 文件指针移动
    fread(&entry[t*8],8,8,file);  // 读取
    Get_ALL_Entry(file,entry,index_variables[start],len-1,t+1);
}



// 得到目录所有非空项的列表
void Get_Entry(FILE* file,struct catalog_entry* entry,int start,int len){
    struct catalog_entry directory[len*8];
    Get_ALL_Entry(file,directory,start,len,0);
    int i,j;
    j=0;
    for(i=0;i<len*8;i++){
        if(directory[i].attribute != 0){
            entry[j]=directory[i];
            j++;
        }
    }
}




/*
int main()
{

    file = fopen("disk.txt","r+");  //打开磁盘文件
    if(file == NULL)    // 磁盘文件不存在
    {
        Reset_Disk();// 重建磁盘文件
    }
    file = fopen("disk.txt","r+");  //打开磁盘文件
    {
        int i,j;
        int t;
        int *p=&t;
        Read_Start(file);// 读取位视图和索引表
        struct catalog_entry entry[8];
        fseek(file,64*2,SEEK_SET);    // 文件指针移动
        fread(entry,8,8,file);// 读取
        char name[3]={'a','\0','\0'};
        char name1[3]={'b','\0','\0'};
        char extend[2]={'x','y'};
        char data[500]={0};
        int len = 65;
        for(i=0;i<len;i++){
            data[i] = 'o';
        }
        data[len] = '\0';
        len = strlen(data);
        //Create(file,name1,extend,entry[0],2);// 保存
        //Delete(file,name,entry[0]);//删除
        //Catalog_Organization(file,entry[0]);//整理
        //Makdir(file,name,entry[0]);//建立目录
        //Deldir(file,name,entry[0]);//删除目录
        //Edit(file,entry[0],name1,data,len);// 修改文件
        //Copy(file,LookUp(file,name1,2,1,p),LookUp(file,name,2,1,p));// 拷贝文件


        //Create(file,name1,extend,entry[0],2);// 保存
        //Makdir(file,name,entry[0]);//建立目录
        //Edit(file,entry[0],name1,data,len);// 修改文件
        //Move(file,entry[0],name1,LookUp(file,name,2,1,p));// 拷贝文件
        Change(file,name1,3,entry[0]);

        //Copy(file,LookUp(file,name1,2,1,p),LookUp(file,name,2,1,p));// 拷贝文件

        //Delete(file,name1,entry[0]);//删除
        //Deldir(file,name,entry[0]);//删除目录

        Printf_Entry(LookUp(file,name,2,1,p));//查找
        Type(file,2,1); // 输出根目录

        Type(file,4,1);
        Printf_Bitwise_View();  // 输出位视图
        Printf_Index_variables();   // 输出索引表
    }
    fclose(file);
    file = NULL;
    return 0;
}
*/
// gcc Operating_System_C.c -shared -o Operating_System_C.dll

python语言部分

需要四张图片,

文件夹图标.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("<Control-s>", 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('<Key>', "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('<Key>', "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('<Key>', "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('<Key>', "break")
    device_B.bind('<Key>', "break")
    device_C.bind('<Key>', "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("<Control-c>"))
# 绑定右键事件
user_interface_bar.output_entry.bind("<Button-3>", Get_Menu)
user_interface_bar.output_entry.bind('<Key>', 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("<Return>",Execute)  # 回车的回调函数
user_interface_bar.input_entry.bind("<Tab>",Tab_input)  # Tab索引
user_interface_bar.input_entry.bind("<Up>", Up_input)  # 代码看看上面的
user_interface_bar.input_entry.bind("<Down>", 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()  # 恢复标准输出

运行实例:

这个是加了图片的示例

 下面几张是加图片前的示例

 现在支持Ctrl+s了,(确实就一行的事情)

 

程序进程展示

操作系统阻塞展示

猜你喜欢

转载自blog.csdn.net/weixin_58196051/article/details/131147148
今日推荐