精华内容
下载资源
问答
  • linux操作系统大作业PAGEPAGE 1———————————————————————————————— 作者:———————————————————————————————— 日期:个人收集整理,勿做商业用途...

    linux操作系统大作业

    PAGE

    PAGE 1

    ———————————————————————————————— 作者:

    ———————————————————————————————— 日期:

    个人收集整理,勿做商业用途

    个人收集整理,勿做商业用途

    PAGE

    PAGE 7

    个人收集整理,勿做商业用途

    学号

    10212811137

    武汉理工大学华夏学院

    Linux 操作系统大作业

    专 业 软件工程

    班 级 软件1111

    姓 名 董丽敏

    成 绩

    指导教师 凌伟

    Linux 操作系统大作业

    VI编辑器的操作

    请在 /root 这个目录下建立一个名为 vitest 的目录;

    进入 vitest 这个目录当中;

    将 /etc/man.config 拷贝到本目录底下;

    使用 vi 开启本目录下的 man.config 这个档案;

    在 vi 中设定一下行号;

    移动到第58 行,向右移动 40 个字符,请问您看到的双引号内是什么目录?

    移动到第一行,并且向下搜寻一下『MAN』这个字符串,请问他在第几行?

    接着下来,我要将 50 到 100 行之间的 man 改为 MAN ,并且一个一个挑选是否需要修改,如何下达指令?

    修改完之后,突然反悔了,要全部复原,有哪些方法?

    我要复制 51 到 60 行这十行的内容,并且贴到最后一行之后;

    删除 11 到 30 行之间的 20 行;

    将这个档案另存成一个 man.test.config 的檔名;

    去到第 29 行,并且删除 15 个字符;

    请问目前的档案有多少行与多少字符?

    储存后离开吧!

    步骤如下显示

    1. mkdir vitest

    2. cd vitest

    3. cp /etc/man.config .

    4. vi man.config

    5. 『:set nu』然后你会在画面中看到左侧出现数字即为行号。

    6. 先按下『58G』再按下『40→』会看到『/dir/bin/foo』这个字样在双引号内;

    7. 先执行『1G』或『gg』后,直接输入『/MAN』,则会去到第 11行!

    8. 直接下达『 :50,100s/man/MAN/gc 』命令!若一直按『y』最终会出现『在 23 行内置换 25 个字符串』的说明。

    9.一直按『 u 』回复到原始状态。

    10. 『51G』 然后再『 10yy 』最后一行会出现『复制十行』类的说明字样。 按下『 G 』到最1后一行,再给他『 p 』贴上10

    11. 因为 11~30 20 行,因此『 11G 』→『 20dd 』就能删除 20行

    12. 『 :w man.test.config 』,最后一行出现 "man.test.config" [New].. 的字样。

    13. 『29G』 后,再给他『 15x 』即可删除 15 个字符,出现『 you 』的

    14. 直接执行『:w』命令。

    15. 『:wq』

    文件权限的操作

    1.添加一个组 project

    2.添加tom ,jerry .密码:redhat ,属于project

    3.在/tmp目录下创建一个文件夹 share. 所属组是project ,other只能够拥x.

    4. tom .jerry 对share 拥有rwx 权限,但是要求tom 只能够删除自己创建的文件,jerry也只能够删除自己创建的文件。 Tom,jeery在share目录下创建的任何文件都属于project组。

    添加一个新的用户。mike ,不属于project组。 对share文件夹有rx。

    步骤如下:

    1.在root下进行

    su

    123456

    2.创建用户tom

    useradd -r tom

    passwd tom

    redhat

    redhat

    3.创建用户jerry

    useradd -r jerry

    passwd jerry

    redhat

    redhat

    4.创建用户组project

    groupadd project

    5.给tom分配组属于project

    gpasswd -a tom project

    6.给jerry分配组属于project

    gpasswd -a jerry project

    7.显示tom所属组project

    id tom

    8.显示jerry所属组project

    id jerry

    9.在tom目录下创建文件夹share

    su t

    展开全文
  • “计算机操作系统”课程设计大作业 (含答案) 一、题目: 模拟UNIX文件系统的设计及实现 多用户、多目录的文件系统的设计------用VC或Delphi编程模拟文件系统的管理 二、目的 通过OS文件子系统的设计、增强OS设计的...

    欢迎添加微信互相交流学习哦!

    二维码

    项目源码:https://gitee.com/oklongmm/biye


    “计算机操作系统”课程设计大作业
    (含答案)

    一、题目:   模拟UNIX文件系统的设计及实现 
    多用户、多目录的文件系统的设计------用VC或Delphi编程模拟文件系统的管理

    二、目的
    通过OS文件子系统的设计、增强OS设计的技巧,达到提高解决实际OS的设计能力的提高。

    三、内容
    多用户的多级目录的文件系统设计。

    四、功能要求
    1.       多用户 :usr1,usr2,usr3,……,usr8  (1-8个用户)
    2.       多级目录:可有多级子目录;
    3.       具有login (用户登录)
    4.       系统初始化(分配内存空间,创建文件卷,初始化根目录)
    5.       文件的创建: create
    6.       文件的打开:open
    7.       文件的读:read
    8.    文件的写:write
    9.       文件关闭:close
    10.   删除文件:delete
    11.   创建目录(建立子目录):mkdir
    12.   改变当前目录:cd
    13.   列出文件目录:dir(包括文件属性)
    14.   删除目录:rmdir
    15.   退出:logout

    五、实现方法
        该大作业是实现一个类似unix的文件系统,只需要实现上述功能要求中所列出的功能,代码中不能调用OS系统提供的与文件操作和磁盘操作有关的系统调用。设计提示:用内存模拟磁盘操作,对文件和目录的创建、删除、读写都用对内存的操作来模拟。文件的属性信息用内存数据结构保存;所有文件内容和目录信息保存在内存中。文件属性包括:文件名,所有者,创建时间,最后访问时间,文件大小,数据区指针或I-node指针等。当程序运行结束时回收内存,信息不需要保存到磁盘,下次重新运行程序时重头开始。

    六、实验要求
    每人完成一份大作业实验报告。报告分设计思想、数据定义、处理流程、源程序、运行结果截图、设计体会等部分。
    1)    给出数据定义和详细说明;
    2)    给出实现思想和设计流程;
    3)    调试完成源程序;
    4)    屏幕观察运行结果;
    5)    总结自己的设计体会;
    编程语言及操作系统平台不限。

    七、提交内容
    本大作业每个人必须单独完成。最后需提交的内容包括:源程序(关键代码需要注释说明)、可运行程序、算法思路及流程图、心得体会。大作业必须以WORD附件的形式提交。
    大作业严禁抄袭。发现抄袭一律以不及格论。大作业内容要完整,一定要有算法思路、流程图、心得体会、运行输出信息截屏等内容,如果只提交源代码则大作业成绩记为不合格。
                                        
     2017-3-20


    目    录

    1.    摘要    2
    2.    问题描述    2
    3.    设计目的    2
    4.    设计要求    2
    5.    详细设计    2
    5.1界面设计    3
    5.1算法设计.    3
    6.    设计总结    3
    7.   参考文献    4
    8.    致谢    4
    9.    附录    22
     
    模拟UNIX文件系统的设计及实现
    1.    课程设计内容
    多用户的多级目录的文件系统设计。
    2.    概述 
    UNIX采用树型目录结构,每个目录表称为一个目录文件。
    一个目录文件是由目录项组成的。每个目录项包含16B,一个辅存磁盘块(512B)包含32个目录项。在目录项中,第1、2字节为相应文件的外存i节点号,是该文件的内部标识;后14B为文件名,是该文件的外部标识。所以,文件目录项记录了文件内、外部标识的对照关系。根据文件名可以找到辅存i节点号,由此便得到该文件的所有者、存取权、文件数据的地址健在等信息。UNIX的存储介质以512B为单位划分为块,从0开始直到最大容量并顺序加以编号就成了一个文件卷,也叫文件系统。UNIX中的文件系统磁盘存储区分配图如下:
    0#    1#    2#    …    K#    K+1#    K+2#    K+3#    …    n#

        

    本次课程设计是要实现一个简单的模拟UNIX文件系统。我们在内存中开辟一个虚拟磁盘空间(1MB)作为文件存储器,并将该虚拟文件系统保存到磁盘上(以一个文件的形式),以便下次可以再将它恢复到内存的虚拟磁盘空间中。文件存储空间的管理可采用位示图方法。
    3.    课程设计任务及要求
    3.1.    设计任务
    多用户、多级目录结构文件系统的设计与实现。可以实现下列几条命令
    login         用户登录
    logout    退出当前用户
    dir    列文件目录
    creat    创建文件
    delete    删除文件
    open    打开文件
    close    关闭文件
    read    读文件
    write      写文件
    mkdir    创建目录
    ch    改变文件目录
    rd    删除目录树
    format    格式化文件系统
    quit    退出文件系统
    3.2.    设计要求
    1) 多用户 :usr1,usr2,usr3,……,usr8  (1-8个用户)   2) 多级目录:可有多级子目录;
    3) 具有login (用户登录)              4) 系统初始化(建文件卷、提供登录模块)
    5) 文件的创建:create (用命令行来实现)        6) 文件的打开:open
    7) 文件的读:read                 8) 文件的写:write
    9) 文件关闭:close                 10) 删除文件:delete
    11) 创建目录(建立子目录):mkdir         12) 改变当前目录:cd
    13) 列出文件目录:dir              14) 退出:logout
    新增加的功能:
    15) 删除目录树:rd
    16) 格式化文件系统:format
    4.    算法及数据结构
    4.1.    算法的总体思想
    本课程设计是要求我们模拟UNIX文件系统功能设计一个虚拟文件系统,依据UNIX文件系统的特点,其设计思想是:
    申请1M的内存空间来虚拟文件系统,将其以512B每块划分2048块,采用位示图管理文件系统的方法,利用其原理将第1块作为位图区(512B),共有对i节点区和数据块区分别建立位图;每个i节点占16B,每块有512/16=32个i节点,用2、3共两块作为i节点,总共有64个i节点,在位图区占用8B;其余2045块作为数据区(本课设要求只用到512块),在位图区占用接近256B(2045位)。
    文件系统存储区分配图如下:

    位图区    i节点区    数据区

    位图:用0表示未使用,1表示使用;
    i节点:文件控制块(FCB),描述文件信息的一个数据结构;
    数据区:存放用户数据,包括目录文件。
    位示图用以反映整个存储空间的分配情况,由若干字节构成,每个字节中的每一位对应文件存储器中的一块,“1”状态表示相应块已占用,“0”状态表示该块为空闲。存储块分配时,只要把找到的空闲块所对应的位由 "0" 改为 "1", 而在释放时,只要把被释放的物理块所对应的位由 "1" 改为 " 0 " 即可。分配和释放都可以在内存的位示 图上完成,而且速度较快。磁盘 i 节点利用在内存中生成链表或者数组的方法来生成,并且限制磁盘节点数的最大值。同样内存 i 节点利用链表的方法在内存中生成。同时在往文件中 写或者读的时候我们都是对内存中有内容进行读写。
    在该文件系统中,规定一个文件最多只能占用2个数据块,这两个数据块可以是不连续的,其块号记录在一个索引块中,该索引块称为inode结构。
    读入一个文件时,先根据目录找到相应的i节点号,将i节点读入主存i节点,建立打开文件表指向该主存i节点,再将文件内容读入主存数据区。
    4.2.    系统总体框架图
     
    4.3.    系统总体流程图
     
     
    4.4.    各模块功能说明
    4.4.1 format模块
    功能:
    格式化文件系统,即初始化文件系统,相当于硬盘的格式化。将其中原有的用户及用户下的文件系统全部还原初始状态,即没有任何用户和目录、文件,也就是按设计的文件系统格式重建新的文件系统。
    4.4.2 get_blknum和release_blk模块
    功能:
    实现i节点的分配和回收;
    算法:当一个新的文件被建立时,在给该文件分配磁盘存储区之前,应为该文件分配存放该文件的说明信息的磁盘i节点。反之,当从文件系统中删除某个文件时,则要首先删除它的i节点项。
    4.4.3 init()模块
    功能:
    进入文件系统
    算法:初始化用户打开文件系表。在内存中申请一个虚拟存储空间,此空间必须大于或等于可格式化时的空间。将文件系统文件读入虚拟磁盘。
    4.4.4 quit()模块
    功能:退出文件系统函数quit()
    算法:将虚拟磁盘内容保存到磁盘上。释放虚拟磁盘所占据的空间。撤消用用户打开文件表。
    4.4.5 Creat()模块
    功能:
    创建文件
    用法:creat filename
    算法:分配一空目录项,分配磁盘块。可用位示图。填写该空目录项。如文件长度(0),文件名,类型等。分配一个用户打开文件表项,并填写相关目录,读写指针=0。
    4.4.6 open()模块
    功能:
    打开文件open()
    用法:open filename
    算法:if(该文件已打开or该文件不存在)报错(出错信息)。分配一个用户打开文件表项。
    4.4.7 close()模块
    功能:
    关闭文件close()
    用法:close filename
    算法:释放该文件的用户占据的内存空间。清空该文件的用户打开文件表目。
    4.4.8 write()模块
    功能:
    写文件write(fd,buf,len)
    用法:write filename,需要先打开文件。
    算法:指定写入内容长度。buf。修改打开文件表读/写指针。修改目录项中的文件长度。
    4.4.9 read()模块
    功能:read(fd,buf,len)
    用法:read filename,需先打开文件。
    算法:文件信息.修改读/写指针。
    4.4.10 delete()模块
    功能:
    删除文件delete()
    用法:delete filename
    算法:若文件不存在,报错。回收磁盘空间。回收目录项。
    4.5.    该文件系统的数据结构和申明函数
    // 用户(20B)
    typedef struct
    {
        char user_name[10];        // 用户名
        char password[10];            // 密码
    } User;

    // i节点(32B)
    typedef struct
    {
        short    inum;            // 文件i节点号
        char    file_name[10];        // 文件名
        char    type;                // 文件类型
        char    user_name[10];      // 文件所有者
        short    iparent;            // 父目录的i节点号 
        short    length;            // 文件长度
        short    address[2];        // 存放文件的地址        
    } Inode;

    // 打开文件表(16B)
    typedef struct
    {
        short inum;                // i节点号
        char  file_name[10];        // 文件名
        short mode;                // 读写模式(1:read, 2:write, 3:read and write)
        short offset;                // 偏移量
    } File_table;

    // 申明函数
    void login(void);          用户登录,如果是新用户则创建用户
    void init(void);           程序初始化,将所有i节点读入内存
    int  analyse(char *);      输入参数分析,分析用户命令
    void save_inode(int);      将num号i节点保存到虚拟磁盘文件hd.dat
    int  get_blknum(void);     申请一个数据块
    void read_blk(int);        将i节点号为num的文件读入temp
    void write_blk(int);       将temp的内容写入hd.dat的数据区
    void release_blk(int);     释放文件块号为num的文件占用的空间
    void pathset();            打印当前路径
    void deltree(int innum);   实现删除目录树函数
    int  check(int);           检查用户权限

    // 用户命令处理函数
    void help(void);           命令提示帮助函数
    void cd(void);             改变当前目录
    void dir(void);            显示当前目录下所有文件和目录
    void mkdir(void);          创建目录
    void rd(void);             删除目录
    void creat(void);          创建文件
    void open(void);           打开
    void read(void);           读文件
    void write(void);          写文件
    void close(void);          关闭文件
    void del(void);            删除文件
    void logout(void);         用户注销
    void command(void);        命令管理函数
    void format(void);         格式化虚拟磁盘
    5.    程序设计与实现
    5.1.    主要函数列表
    函数原型    功能    入口、出口参数说明
    void login(void)    用户登陆    
    void init(void))    程序初始化    
    int  analyse(char *)    输入参数分析    命令行字符串
    void save_inode(int)    保存i节点到虚拟磁盘文件    i节点号
    int get_blknum(void)    分配一个磁盘块    
    void read_blk(int)    读磁盘快内容    i节点号
    void write_blk(int)    写磁盘块    i节点号
    void release_blk(int)    释放一个磁盘块    i节点号
    void pathset();    打印当前路径    
    void deltree(int innum);    实现删除目录树函数    i节点号
    int  check(int);    检查用户权限    i节点号
    void help(void)    命令提示帮助函数    
    void dir(void)    显示当前目录下所有文件和目录    
    void mkdir(void)    创建目录    
    void creat(void)    创建文件    
    void open(void)    打开文件    
    void read(void)    读文件    
    void write(void)    写文件    
    void close(void)    关闭文件    
    void del(void)    删除文件    
    void logout(void)    用户登出    
    void command(void)    命令管理函数    
    void rd(void)    删除目录    
    void format(void);    格式化虚拟磁盘    
    5.2.    函数之间的关系
     

    5.3.     程序流程图
    各功能模块流程图
                     


                                    

              


           


     

     


           

     
     
    5.4.    源程序
     
    /*main.c*/

    #include "head.h"
    char        choice;
    int        argc;        // 用户命令的参数个数
    char        *argv[5];        // 用户命令的参数
    int        inum_cur;        // 当前目录
    char        temp[2*BLKSIZE];    // 缓冲区
    User        user;        // 当前的用户
    char        bitmap[BLKNUM];    // 位图数组
    Inode    inode_array[INODENUM];    // i节点数组
    File_table file_array[FILENUM];    // 打开文件表数组
    char    image_name[10] = "hd.dat";    // 文件系统名称
    FILE        *fp;                    // 打开文件指针

    //创建映像hd,并将所有用户和文件清除
    void format(void)
    {
    FILE  *fp;
    int   i;
    Inode inode;
    printf("Will be to format filesystem...\n");
    printf("WARNING:ALL DATA ON THIS FILESYSTEM WILL BE LOST!\n");
    printf("Proceed with Format(Y/N)?");
    scanf("%c", &choice);
    gets(temp);
    if((choice == 'y') || (choice == 'Y'))
    {
    if((fp=fopen(image_name, "w+b")) == NULL)
    {
         printf("Can't create file %s\n", image_name);
         exit(-1);
        }
        for(i = 0; i < BLKSIZE; i++)
          fputc('0', fp);
          inode.inum = 0;
          strcpy(inode.file_name, "/");
          inode.type = 'd';
          strcpy(inode.user_name, "all");
          inode.iparent = 0;
          inode.length = 0;
          inode.address[0] = -1;
          inode.address[1] = -1;
          fwrite(&inode, sizeof(Inode), 1, fp);
          inode.inum = -1;
          for(i = 0; i < 31; i++)
            fwrite(&inode, sizeof(Inode), 1, fp);
          for(i = 0; i < BLKNUM*BLKSIZE; i++)
            fputc('\0', fp);
          fclose(fp);
        // 打开文件user.txt
        if((fp=fopen("user.txt", "w+")) == NULL)
        {
          printf("Can't create file %s\n", "user.txt");
            exit(-1);
        }
        fclose(fp);
        printf("Filesystem created successful.Please first login!\n");
    }
    return ;
    }
    // 功能: 用户登陆,如果是新用户则创建用户
    void login(void)
    {
    char *p;
    int  flag;
    char user_name[10];
    char password[10];
    char file_name[10] = "user.txt";
    do 
    {
    printf("login:");
    gets(user_name);
    printf("password:");
    p=password;
    while(*p=getch())
    {
    if(*p == 0x0d) //当输入回车键时,0x0d为回车键的ASCII码
    {
    *p='\0'; //将输入的回车键转换成空格
    break;
    }
    printf("*");   //将输入的密码以"*"号显示
    p++;
    }
    flag = 0;
    if((fp = fopen(file_name, "r+")) == NULL)
    {
    printf("\nCan't open file %s.\n", file_name);
    printf("This filesystem not exist, it will be create!\n");
    format();
    login();
    }
    while(!feof(fp))
    {
    fread(&user, sizeof(User), 1, fp);
    // 已经存在的用户, 且密码正确
    if(!strcmp(user.user_name, user_name) &&
     !strcmp(user.password, password))
    {
    fclose(fp);
    printf("\n");
    return ;
    }
    // 已经存在的用户, 但密码错误
    else if(!strcmp(user.user_name, user_name))
    {
    printf("\nThis user is exist, but password is incorrect.\n");
    flag = 1;
    fclose(fp);
    break;
    }
    }
    if(flag == 0) break;
    }while(flag);
    // 创建新用户
    if(flag == 0)
    {
    printf("\nDo you want to creat a new user?(y/n):");
    scanf("%c", &choice);
    gets(temp);
    if((choice == 'y') || (choice == 'Y'))
    {
    strcpy(user.user_name, user_name);
    strcpy(user.password, password);
    fwrite(&user, sizeof(User), 1, fp);
    fclose(fp);
    return ;
    }
    if((choice == 'n') || (choice == 'N'))
    login();
    }
    }
    // 功能: 将所有i节点读入内存
    void init(void)
    {
    int   i;
    if((fp = fopen(image_name, "r+b")) == NULL)
    {
    printf("Can't open file %s.\n", image_name);
    exit(-1);
    }
    // 读入位图
    for(i = 0; i < BLKNUM; i++)
    bitmap[i] = fgetc(fp);
    // 显示位图
    // 读入i节点信息
    for(i = 0; i < INODENUM; i++)
    fread(&inode_array[i], sizeof(Inode), 1, fp);
    // 显示i节点
    // 当前目录为根目录
    inum_cur = 0;
    // 初始化打开文件表
    for(i = 0; i < FILENUM; i++)
    file_array[i].inum = -1;
    }
    // 功能: 分析用户命令, 将分析结果填充argc和argv
    // 结果: 0-14为系统命令, 15为命令错误
    int analyse(char *str)
    {
    int  i;
    char temp[20];
    char *ptr_char;
    char  *syscmd[]={"help", "cd", "dir", "mkdir", "creat", "open", "read", "write", "close", "delete", "logout", "clear","format","quit","rd"};
    argc = 0;
    for(i = 0, ptr_char = str; *ptr_char != '\0'; ptr_char++)
    {
    if(*ptr_char != ' ')
    {
    while(*ptr_char != ' ' && (*ptr_char != '\0'))
    temp[i++] = *ptr_char++;
    argv[argc] = (char *)malloc(i+1);
    strncpy(argv[argc], temp, i);
    argv[argc][i] = '\0';
    argc++;
    i = 0;
    if(*ptr_char == '\0') break;
    }
    }
    if(argc != 0) 
    {
    for(i = 0; (i < 15) && strcmp(argv[0], syscmd[i]); i++);
    return i;
    }
    else return 15;
    }
    // 功能: 将num号i节点保存到hd.dat
    void save_inode(int num)
    {
    if((fp=fopen(image_name, "r+b")) == NULL)
    {
    printf("Can't open file %s\n", image_name);
    exit(-1);
    }
    fseek(fp, 512+num*sizeof(Inode), SEEK_SET);
    fwrite(&inode_array[num], sizeof(Inode), 1, fp);
    fclose(fp);
    }
    // 功能: 申请一个数据块
    int get_blknum(void)
    {
    int i;
    for(i = 0; i < BLKNUM; i++)
    if(bitmap[i] == '0') break;
    // 未找到空闲数据块
    if(i == BLKNUM)
    {
    printf("Data area is full.\n");
    exit(-1);
    }
    bitmap[i] = '1';
    if((fp=fopen(image_name, "r+b")) == NULL)
    {
    printf("Can't open file %s\n", image_name);
    exit(-1);
    }
    fseek(fp, i, SEEK_SET);
    fputc('1', fp);
    fclose(fp);
    return i;
    }
    // 功能: 将i节点号为num的文件读入temp 
    void read_blk(int num)
    {
    int  i, len;
    char ch;
    int  add0, add1;
    len = inode_array[num].length;
    add0 = inode_array[num].address[0];
    if(len > 512)
    add1 = inode_array[num].address[1];
    if((fp = fopen(image_name, "r+b")) == NULL)
    {
    printf("Can't open file %s.\n", image_name);
    exit(-1);
    }
    fseek(fp, 1536+add0*BLKSIZE, SEEK_SET);
    ch = fgetc(fp);
    for(i=0; (i < len) && (ch != '\0') && (i < 512); i++)
    {
    temp[i] = ch;
    ch = fgetc(fp);
    }
    if(i >= 512)
    {
    fseek(fp, 1536+add1*BLKSIZE, SEEK_SET);
    ch = fgetc(fp);
    for(; (i < len) && (ch != '\0'); i++)
    {
    temp[i] = ch;
    ch = fgetc(fp);    
    }
    }
    temp[i] = '\0';
    fclose(fp);
    }
    // 功能: 将temp的内容输入hd的数据区
    void write_blk(int num)
    {
    int  i, len;
    int  add0, add1;
    add0 = inode_array[num].address[0];
    len  = inode_array[num].length;
    if((fp = fopen(image_name, "r+b")) == NULL)
    {
    printf("Can't open file %s.\n", image_name);
    exit(-1);
    }
    fseek(fp, 1536+add0*BLKSIZE, SEEK_SET);
    for(i=0; (i<len)&&(temp[i]!='\0')&&(i < 512); i++)
    fputc(temp[i], fp);
    if(i == 512)
    {
    add1 = inode_array[num].address[1];
    fseek(fp, 1536+add1*BLKSIZE, SEEK_SET);
    for(; (i < len) && (temp[i] != '\0'); i++)
    fputc(temp[i], fp);
    }
    fputc('\0', fp);
    fclose(fp);
    }
    // 功能: 释放文件块号为num的文件占用的空间
    void release_blk(int num)
    {
    FILE *fp;
    if((fp=fopen(image_name, "r+b")) == NULL)
    {
    printf("Can't open file %s\n", image_name);
    exit(-1);
    }
    bitmap[num] = '0';
    fseek(fp, num, SEEK_SET);
    fputc('0', fp);
    fclose(fp);
    }
    // 功能: 显示帮助命令
    void help(void)
    {
    printf("command: \n\
    help   ---  show help menu \n\
    clear  ---  clear the screen \n\
    cd     ---  change directory \n\
    mkdir  ---  make directory   \n\
    creat  ---  create a new file \n\
    open   ---  open a exist file \n\
    read   ---  read a file \n\
    write  ---  write something to a file \n\
    close  ---  close a file \n\
    delete ---  delete a exist file \n\
    format ---  format a exist filesystem \n\
    logout ---  exit user \n\
    rd     ---  delete a directory \n\
    quit   ---  exit this system\n");
    }
    //设置文件路径
    void pathset()
    {
    char path[50];
    int m,n;
    if(inode_array[inum_cur].inum == 0)
    strcpy(path,user.user_name);
    else
    {
    strcpy(path,user.user_name);
    m=0;
    n=inum_cur;
    while(m != inum_cur)
    {
    while(inode_array[n].iparent != m)
    {
    n = inode_array[n].iparent;
    }
    strcat(path,"/");
    strcat(path,inode_array[n].file_name);
    m = n;
    n = inum_cur;
    }
    }
    printf("[%s]@",path);
    }
    // 功能: 切换目录(cd .. 或者 cd dir1)
    void cd(void)
    {
    int i;
    if(argc != 2)
    {
    printf("Command cd must have two args. \n");
    return ;
    }
    if(!strcmp(argv[1], ".."))
    inum_cur = inode_array[inum_cur].iparent;
    else
    {
    // 遍历i节点数组
    for(i = 0; i < INODENUM; i++)
    if((inode_array[i].inum>0)&&
    (inode_array[i].type=='d')&&
    (inode_array[i].iparent==inum_cur)&&
    !strcmp(inode_array[i].file_name,argv[1])&&
    check(i))
    break;
    if(i == INODENUM) 
    printf("This directory isn't exsited.\n");
    else inum_cur = i;
    }
    }
    // 功能: 显示当前目录下的子目录和文件(dir)
    void dir(void)
    {
    int i;
    int dcount=0,fcount=0;
    short bcount=0;
    if(argc != 1)
    {
    printf("Command dir must have one args. \n");
    return ;
    }
    // 遍历i节点数组, 显示当前目录下的子目录和文件名
    for(i = 0; i < INODENUM; i++)
    if((inode_array[i].inum> 0) && 
    (inode_array[i].iparent == inum_cur))
    {
    if(inode_array[i].type == 'd' && check(i))
    {
    dcount++;
    printf("%-20s<DIR>\n", inode_array[i].file_name);
    }
    if(inode_array[i].type == '-' && check(i))
    {
    fcount++;
    bcount+=inode_array[i].length;
    printf("%-20s%12d bytes\n", inode_array[i].file_name,inode_array[i].length);
    }
    }
    printf("\n                    %d file(s)%11d bytes\n",fcount,bcount);
    printf("                    %d dir(s) %11d bytes FreeSpace\n",dcount,1024*1024-bcount);    
    }
    // 功能: 删除目录树(rd dir1)
    void rd()
    {
    int i,j,t,flag=0;
    if(argc != 2)
    {
    printf("Command delete must have one args. \n");
    return ;
    }
    for(i = 0; i < INODENUM; i++)//查找待删除目录
    if((inode_array[i].inum > 0) &&//是否为空
    (inode_array[i].iparent == inum_cur) &&
    (inode_array[i].type == 'd')&&
    (!strcmp(inode_array[i].file_name,argv[1])))
    {
    chk=check(i);//检查用户权限
    if(chk!=1)  
    {
    printf("This directory is not your !\n");
    return ;
    }
    else j=inode_array[i].inum;
    for(t=0;t<INODENUM;t++)
    {
    if((inode_array[t].inum>0)&&
    (inode_array[t].iparent==j)&&
    (inode_array[i].type == '-'))
    delet(t);//目录下有文件则删除
    else if((inode_array[t].inum>0)&&
    (inode_array[t].iparent==j)&&
    (inode_array[i].type == 'd'))
    delet(t);//目录下有空目录则删除
    }
    if(t == INODENUM)
    delet(j);//下层目录为空删除之
    }
    if(i == INODENUM)
    delet(i);//待删除目录为空删除之
    return;
    }
    // 功能: 在当前目录下创建子目录(mkdir dir1)
    void mkdir(void)
    {
    int i;
    if(argc != 2)
    {
    printf("command mkdir must have two args. \n");
    return ;
    }
    // 遍历i节点数组, 查找未用的i节点
    for(i = 0; i < INODENUM; i++)
    if(inode_array[i].inum < 0) break;
    if(i == INODENUM)
    {
    printf("Inode is full.\n");
    exit(-1);
    }
    inode_array[i].inum = i;
    strcpy(inode_array[i].file_name, argv[1]);
    inode_array[i].type = 'd';
    strcpy(inode_array[i].user_name,user.user_name);
    inode_array[i].iparent = inum_cur;
    inode_array[i].length = 0;
    save_inode(i);
    }
    // 功能: 在当前目录下创建文件(creat file1)
    void creat(void)
    {
    int i;
    if(argc != 2)
    {
    printf("command creat must have one args. \n");
    return ;
    }
    for(i = 0; i < INODENUM; i++)
    {
    if((inode_array[i].inum > 0) &&
    (inode_array[i].type == '-') &&
    !strcmp(inode_array[i].file_name, argv[1]))
    {
    printf("This file is exsit.\n");
    return ;
    }
    }
    for(i = 0; i < INODENUM; i++)
    if(inode_array[i].inum < 0) break;
    if(i == INODENUM)
    {
    printf("Inode is full.\n");
    exit(-1);
    }
    inode_array[i].inum = i;
    strcpy(inode_array[i].file_name, argv[1]);
    inode_array[i].type = '-';
    strcpy(inode_array[i].user_name, user.user_name);
    inode_array[i].iparent = inum_cur;
    inode_array[i].length = 0;
    save_inode(i);
    }
    // 功能: 打开当前目录下的文件(open file1)
    void open()
    {
    int i, inum, mode, filenum,chk;
    if(argc != 2)
    {
    printf("command open must have one args. \n");
    return ;
    }
    for(i = 0; i < INODENUM; i++)
    if((inode_array[i].inum > 0) &&
    (inode_array[i].type == '-') &&
    !strcmp(inode_array[i].file_name,argv[1]))
    break;
    if(i == INODENUM)
    {
    printf("The file you want to open doesn't exsited.\n");
    return ;
    }
    inum = i;
    chk=check(i);
    if(chk!=1)  
    {
    printf("This file is not your !\n");
    return ;  
    }
    printf("Please input open mode:(1: read, 2: write, 3: read and write):");
    scanf("%d", &mode);
    gets(temp);
    if((mode < 1) || (mode > 3))
    {
    printf("Open mode is wrong.\n");
    return;
    }
    for(i = 0; i < FILENUM; i++)
    if(file_array[i].inum < 0) break;
    if(i == FILENUM) 
    {
    printf("The file table is full, please close some file.\n");
    return ;
    }
    filenum = i;
    file_array[filenum].inum = inum;
    strcpy(file_array[filenum].file_name, inode_array[inum].file_name);
    file_array[filenum].mode = mode;
    file_array[filenum].offset = 0;
    printf("Open file %s by ", file_array[filenum].file_name);
    if(mode == 1) printf("read only.\n");
    else if(mode == 2) printf("write only.\n");
    else printf("read and write.\n");
    }
    // 功能: 从文件中读出字符(read file1)
    void read()
    {
    int i, start, num, inum;
    if(argc != 2)
    {
    printf("command read must have one args. \n");
    return;
    }
    for(i = 0; i < FILENUM; i++)
    if((file_array[i].inum > 0) && 
    !strcmp(file_array[i].file_name,argv[1]))
    break;
    if(i == FILENUM)
    {
    printf("Open %s first.\n", argv[1]);
    return ;
    }
    else if(file_array[i].mode == 2)
    {
    printf("Can't read %s.\n", argv[1]);
    return ;
    }
    inum = file_array[i].inum;
    printf("The length of %s:%d.\n", argv[1], inode_array[inum].length);
    if(inode_array[inum].length > 0)
    {
    printf("The start position:");
         scanf("%d", &start);
         gets(temp);
      if((start<0)||(start>=inode_array[inum].length))
    {
    printf("Start position is wrong.\n");
    return;
    }
    printf("The bytes you want to read:");
    scanf("%d", &num);
    gets(temp);
    if(num <= 0)
    {
    printf("The num you want to read is wrong.\n");
    return ;
    }
    read_blk(inum);    
    for(i = 0; (i < num) && (temp[i] != '\0'); i++)
    printf("%c", temp[start+i]);
    printf("\n");
    }
    }
    // 功能: 向文件中写入字符(write file1)
    void write()
    {
    int i, inum, length;
    if(argc != 2)
    {
    printf("Command write must have one args. \n");
    return ;
    }
    for(i = 0; i < FILENUM; i++)
    if((file_array[i].inum>0)&&
    !strcmp(file_array[i].file_name,argv[1])) break;
    if(i == FILENUM)
    {
    printf("Open %s first.\n", argv[1]);
    return ;
    }
    else if(file_array[i].mode == 1)
    {
    printf("Can't write %s.\n", argv[1]);
    return ;
    }
    inum = file_array[i].inum;
    printf("The length of %s:%d\n", inode_array[inum].file_name, inode_array[inum].length);
    if(inode_array[inum].length == 0)
    {
    printf("The length you want to write(0-1024):");
    scanf("%d", &length);
    gets(temp);
    if((length < 0) && (length >1024))
    {
    printf("Input wrong.\n");
    return ;
    }
    inode_array[inum].length = length;
    inode_array[inum].address[0] = get_blknum();
    if(length > 512)
    inode_array[inum].address[1] = get_blknum();
    save_inode(inum);
    printf("Input the data(Enter to end):\n");
    gets(temp);
    write_blk(inum);
    }
    else
    printf("This file can't be written.\n");
    }
    // 功能: 关闭已经打开的文件(close file1)
    void close(void)
    {
    int i;
    if(argc != 2)
    {
    printf("Command close must have one args. \n");
    return ;
    }
    for(i = 0; i < FILENUM; i++)
    if((file_array[i].inum > 0) &&
    !strcmp(file_array[i].file_name, argv[1])) break;
    if(i == FILENUM)
    {
    printf("This file doesn't be opened.\n");
    return ;
    }
    else 
    {
    file_array[i].inum = -1;
    printf("Close %s successful!\n", argv[1]);
    }
    }
    //删除目录树
    void delet(int innum)
    {
    /*int chk;
    chk=check(innum);
    if(chk!=1)  
    {
    //printf("This directory is not yours !\n");
    return ; 
      }*/
    inode_array[innum].inum = -1;
    if(inode_array[innum].length >= 0)
    {
      release_blk(inode_array[innum].address[0]);
      if(inode_array[innum].length >= 512)
    release_blk(inode_array[innum].address[1]);
    }
    save_inode(innum);    
    }
    // 功能: 删除文件(delete file1)
    void del(void)
    {
    int i,chk;
    if(argc != 2)
    {
    printf("Command delete must have one args. \n");
    return ;
    }
    for(i = 0; i < INODENUM; i++)
    if((inode_array[i].inum > 0) &&
    (inode_array[i].type == '-') &&
    !strcmp(inode_array[i].file_name, argv[1])) break;
    if(i == INODENUM)
    {
    printf("This file doesn't exist.\n");
    return ;
    }
    chk=check(i);
    if(chk!=1)  
    {
    printf("This file is not your !\n");
    return ;  
        }
    /*inode_array[i].inum = -1;
    if(inode_array[i].length > 0)
    {
    release_blk(inode_array[i].address[0]);
    if(inode_array[i].length > 512)
    release_blk(inode_array[i].address[1]);
    }
    save_inode(i);*/
    delet(i);    
    }
    // 功能: 退出当前用户(logout)
    void logout()
    {
    char choice;
    printf("Do you want to exit this user(y/n)?");
    scanf("%c", &choice);
    gets(temp);
    if((choice == 'y') || (choice == 'Y'))
    {
    printf("\nCurrent user exited!\nPlease to login by other user!\n");
    login();
    }
    return ;
    }
    //检查当前I节点的文件是否属于当前用户
    int check(int i)
    {
    int j;
    char *uuser,*fuser;
    uuser=user.user_name;
    fuser=inode_array[i].user_name;
      j=strcmp(fuser,uuser);
      if(j==0)  return 1;
    else      return 0;
    }
    // 功能: 退出文件系统(quit)
    void quit()
    {
    char choice;
    printf("Do you want to exist(y/n):");
    scanf("%c", &choice);
    gets(temp);
    if((choice == 'y') || (choice == 'Y'))
    exit(0);
    }
    // 功能: 显示错误
    void errcmd()
    {
    printf("Command Error!!!\n");
    }
    //清空内存中存在的用户名
    free_user()
    {
    int i;
    for(i=0;i<10;i++)
    user.user_name[i]='\0';
    }
    // 功能: 循环执行用户输入的命令, 直到logout
    // "help", "cd", "dir", "mkdir", "creat", "open","read", "write", "close", "delete", "logout", "clear", "format","quit","rd"
    void command(void)
    {
    char cmd[100];
    system("cls");
    do
    {
    pathset();
    gets(cmd);
    switch(analyse(cmd))
    {
    case 0:    
    help(); 
    break;
    case 1: 
    cd(); 
    break;
         case 2: 
           dir(); 
           break;
         case 3: 
           mkdir(); 
           break;
         case 4: 
           creat(); 
           break;
         case 5: 
           open(); 
           break;
         case 6: 
           read(); 
           break;
    case 7: 
           write(); 
           break;
         case 8: 
           close(); 
           break;
         case 9: 
           del(); 
           break;
         case 10: 
           logout();
           break;
         case 11:
           system("cls");
    break;
    case 12:
    format();
    init();
    free_user();
    login();
    break;
    case 13:
    quit();
    break;
    case 14:
    rd();
    break;
    case 15:
    errcmd();
    break;
    default:
    break;
    }
    }while(1);
    }
    // 主函数
    int main(void)
    {
    login();    
    init();
    command();
    return 0;
    }

    /* head.h */

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

    #define BLKSIZE    512        // 数据块的大小 
    #define BLKNUM     512        // 数据块的块数
    #define INODESIZE  32        // i节点的大小
    #define INODENUM   32        // i节点的数目
    #define FILENUM    8        // 打开文件表的数目

    // 用户(20B)
    typedef struct
    {
    char user_name[10];        // 用户名
    char password[10];        // 密码
    } User;

    // i节点(32B)
    typedef struct
    {
    short inum;          // 文件i节点号
    char  file_name[10]; // 文件名
    char  type;          // 文件类型
    char  user_name[10]; // 文件所有者
    short iparent;       // 父目录的i节点号 
    short length;        // 文件长度
    short address[2];    // 存放文件的地址        
    } Inode;

    // 打开文件表(16B)
    typedef struct
    {
    short inum;             // i节点号
    char  file_name[10]; // 文件名
    short mode;             // 读写模式(1:read, 2:write,
    //         3:read and write)
    short offset;        // 偏移量
    } File_table;

    // 申明函数
    void login(void);
    void init(void);
    int  analyse(char *);
    void save_inode(int);
    int    get_blknum(void);
    void read_blk(int);
    void write_blk(int);
    void release_blk(int);
    void pathset();
    void delet(int innum);
    int  check(int i);
    // 用户命令处理函数 
    void help(void);
    void cd(void);
    void dir(void);
    void mkdir(void);
    void creat(void);
    void open(void);
    void read(void);
    void write(void);
    void close(void);
    void del(void);
    void logout(void);
    void command(void);
    void rd();
    void quit();
     
    6.    使用说明
    1.本程序首次运行(假设当前硬盘目录下还未建立user.txt和hd.dat文件)时会提示找不到user.txt文件,虚拟文件系统不存在,此时程序会提示你是否要建立文件系统,得到你的确认后程序将格式化虚拟磁盘建立虚拟文件系统,并在磁盘当前目录里生成这两个文件。文件系统建立后便出现用户登录提示。
     
    2.系统首次登录时,当输入用户名和密码后,则提示是否要新建用户。得到用户确认后即建立了该用户并登录到该用户目录下。即可在该用户下输入命令进行文件、目录的操作。
     
     
    3.当文件系统建好后,也有了新的用户,以后就可以用用户名和密码登录该文件系统了。当再次登录系统时,若输入的用户名不存在,则提示是否要新建用户,得到用户确认后就可以建立新的用户。当要使用其他用户时,则需要先使用注销用户命令logout退出当前用户,再按提示输入新的用户名和密码进入新的用户。
     
     
     
    4.执行help命令的效果截图:
     
    5.当想要清除该文件系统中所有内容时,可以使用format命令,该命令会象DOS里的format命令一样将你系统中的所有信息全部消除,包括所有用户和所有文件及目录,因此该命令要慎用。
     
    6.以下是实现建立、查看、进入、退出、删除子目录的功能:
     
     
    7.以下是实现新建、打开、读、写、关闭、删除文件的功能:
     
    8.本文件系统实现了权限管理,任何用户只能访问自己创建的目录和读写自己创建的文件,禁止其他用户访问。
     
    9.quit 命令直接退出程序。
     
    (该程序操作要点说明:要先打开一个文件,然后才能往该文件中写内容。)
    7.    结论、问题及解决办法
    模拟实现了UNIX文件系统,较好地实现了课程设计的任务和要求及各个功能。
    本系统的功能较完善,实现了文件系统的初始建立,格式化操作,用户的切换,用户权限管理,删除目录树等新增加的功能(改进),完整地实现了课程设计所要求的基本功能:新建用户、文件、目录,删除文件、目录,进入、退出目录,文件的打开、读、写、关闭等。
    在验收时,很好的实现了完整地删除目录树的功能,命令提示符中能显示当前的用户和路径,用dir命令查看时能查看文件类型、长度,能统计当前目录下的文件个数及总大小、剩余空间和目录个数,还实现了切换用户的功能、格式化文件系统的功能。
    在验收时还是有点小问题一直没得到很好解决,就是用当前用户进行对该文件系统格式化后,还可以用刚才的那个当前用户登录,里面的文件信息依然存在,当时和项国富老师一起查找还是没有找到问题的所在,也未得到解决(截图如下)。
     
     
    通过今天上午和XX同学查找、调试,进行了有针对性的讨论:为什么格式化之前的那个用户(user1)在格式化后还存在(程序未关闭),而当程序关闭后再执行程序进入后并不存在这个用户,而且user.txt文件长度为0,内容为空,一切正常。也就是说格式化是很成功的,其问题不是出在格式化功能模块。这说明在格式化后程序未退出前,该用户名还在内存中没有被释放,即user.user_name数组中的用户名还存在,那么问题很有可能出在调用login()功能模块。我们又仔细分析了login()功能模块,在执行下面的这段程序时应该将user.txt文件中的内容(此时该文件无内容)读入user.user_name数组中,应该该数组为空,这样程序就会判断该新输入的用户不存在,则会跳出执行后面建立新用户的程序段,然而并非如此。
    fp = fopen(file_name, "r+")
    … …
    while(!feof(fp))
    {
    fread(&user, sizeof(User), 1, fp);// 已经存在的用户, 且密码正确
    if(!strcmp(user.user_name, user_name) && !strcmp(user.password, password))
    {
    fclose(fp);
    printf("\n");
    return ;
    }
    … …
    因此我们用printf(“[%s]”, user.user_name)语句进行测试,测试结果user.user_name里面的内容仍然是user1,说明fread(&user, sizeof(User), 1, fp)并没有把user.txt里面的空内容写入user.user_name中,那这又是为什么呢?接着我和杨华同学打开VC6.0帮助文档,认真研究文档中fread(buffer,size,count,fp)函数,终于找出了问题所在:原来该函数有一个特性,即“If size or count is 0, fread returns 0 and the buffer contents are unchanged”,意思是说如果要读写的字节数或要进行读写多少个size字节的数据项为0,则fread函数返回0并且不改变读入数据的存放地址中的原有内容。在这里正好格式化后的user.txt文件的字节数为0,因此fread(&user, sizeof(User), 1, fp)并没有改变数组user中的原有内容,即user.user_name的内容还是user1。找到了问题的所在,就好解决了,因此只要格式化后先调用init()函数,初始化i节点,再将user.user_name中的内容填入’\0’,我们就写了下面这个free_user()函数进行调用,最后再调用login()函数。问题得到彻底解决。(见上面的使用说明第5条的截图)
    free_user()
    {
    int i;
    for(i=0;i<10;i++)
    user.user_name[i]='\0';
    }
    8.    收获与体会
    经过两周的共同努力,在XXX老师提供的源代码基础上,我们将程序按要求修改完善,使其能实现课程设计要求的基本功能并增加了一两个新的功能(权限管理与删除目录)。
    操作系统是计算机科学与技术专业中的一门重要基础课,目的是让我们了解操作系统的基本概念,理解计算机系统的资源如何组织,操作系统如何有效地管理这些系统资源,用户如何通过操作系统与计算机系统打交道。通过课程设计,可以进一步理解在计算机系统上运行的其它各类操作系统,并懂得在操作系统的支持下建立自己的应用系统。操作系统课程设计,对于训练我们掌握程序设计、熟悉上机操作和程序调试技术都有重要作用。重点培养我们的思维能力、创新能力和排错能力。
    通过课程设计,进一步融会贯通教材内容,掌握程序各功能模块的工作原理,相互联系和来龙去脉,完整地建立系统的概念。激发我的学习热情和主动性,培养我的独立工作能力,在实践活动中,将所学知识综合运用,增长才干,并积累经验。对编程语言C又有了更深一层次的认识,并对其的编程能力有所加强,但还是很多的不足有待改进,对于编程来说还需要大量的实践,才能在发现问题和解决问题中前进与提高。
    最后,向辛勤指导我们的XXX老师和XXX老师表示深深的谢意!并祝二位恩师新年快乐,身体健康,工作顺利,万事如意!

    展开全文
  • 文章目录燕山大学操作系统大作业问题:解决方案:1.问题探讨:1.1.改进:1.2.升级:2.问题解决:2.1.设计规则:2.2.实现方法2.3.实现原理:2.4.伪代码实现: PS:这文章是软件后四个班(李贤善老师教的班)的作业,...


    PS:这文章是软件后四个班(李贤善老师教的班)的作业,前四个班的作业在下面的下载链接里:
    https://download.csdn.net/download/weixin_45525272/29795260

    这也不是标准答案,只是我自己的见解,总结出来的,仅供参考,如有错误,可以评论留言或者加QQ1795018360,请不吝赐教。


    燕山大学操作系统大作业

    问题:

    教材中提供的读者-写者问题的解决方案存在读者优先问题,即当有一个读进程比较活跃时,随后而来的读进程都将被允许访问资源。这样,会导致写进程可能长时间等待。而这种情况往往与实际应用需求相背

    请认真分析、研究读者-写者问题,给出对读者和写者都较为公平的同步解决方案。要求写出分析过程,写出使用的信号量及进程描述伪代码,并详细解释给出的解决方案。

    解决方案:

    1.问题探讨:

    教材中为读者优先,其特点有写者、读者互斥访问文件资源,多个读者可以同时访问文件资源(通过readcount来控制),只允许一个写者进行写的操作(通过wmutex控制),只要有读者这在读,就不允许写者进入。直到没有读者到达,没有读者到达会导致读者队列为空,即readcount =0,此时写者才可以进入临界区执行写操作。

    由此可看出除非有写者在写,否则读者不需要等待,读者处于高优先级进程,写者处于低优先级进程,两者通过变量wmutex完成互斥。从而导致写进程长时间的等待。

    这相对于写者来说是非常不公平的,举个例子,如果连续一直有读者进行读操作的时候,写者就不能访问系统资源临界区进行写操作。

    1.1.改进:

    首先我想到可以将待访问的数据区域视为临界区,直接只设置一个互斥信号量mutex,然后读者和写者都采用 p(mutex);读取/写入数据; v(mutex);的方式竞争获取数据区域。这样的方法也可以做到先到先得的效果啊。

    虽然达到了读者-写者公平竞争,但是上面忽视了一个严重的问题:丧失了读者的并行性。下面再进行改进。

    1.2.升级:

    我首先想:能不能为读者队列加一个锁,将没进来的锁在外面,即形成两个读者队列:在有写者想要写的时候分成已经读上的读者和没有读上的读者。然后已经读上的读者继续读直到读完为止,再想读的读者就不让读了。当已经读上的读者读完了的时候进来的写者进行写操作。

    大致意思就是:当写者没有写的时候,读者直接进入读者队列等待系统分配资源进行读取数据;但是当有写者要进行写操作的时候,立刻开启读者队列锁,新来的再想进行读操作的读者就不能读了,只有已经读上的可以进行读操作,当读者队列读完了的时候,写者进行写,写完解除读者队列锁。新来的再想读的读者就可以正常读了。

    好了,上面那就是想的过程,下面整点专业的代码和语句。

    2.问题解决:

    2.1.设计规则:

    1. 首先读者、写者肯定要互斥访问
    2. 同一时刻只能允许有一个写者访问资源
    3. 同一时刻可以有多个读者同时访问资源
    4. 读者进程分为两个级别
    5. 写者进程的优先级和读者相同

    2.2.实现方法

    1. 设置fmutex 信号量实现对临界资源的互斥访问。
    2. 设置计数器readcount实现多个读者访问临界资源,通过设置信号量rmutex 实现对readcount 计数器的互斥访问。
    3. 设置信号量fair实现读者进程和写者进程的公平竞争

    2.3.实现原理:

    信号量fair的作用其一是为了阻止读者进程优先(即教材中的只要读者进程到达,就可以进入读者队列,而写者进程必须等待,有了fair可以阻塞没读的读者),其二是为了写者间的互斥(有了fair只有当前一个写者可以进行写操作)。

    例如:开始来了一些读者进程读资源,此时没有写者那么全部进入读者队列,此时来了一个写者,执行P(fair)操作,使得后续到来的读者都阻塞在fair上,不能进入读者队列(这会使得读者队列逐渐为空,即rcount减为0),但是这个写者也不能立马开始写(因为此时读者队列不为空),阻塞在fmutex 上,读者队列中的读者全部读取结束后,最后一个读者进程执行V(fmutex),唤醒刚才的写者,写者开始进行写操作。

    2.4.伪代码实现:

    //公平竞争  
    int readcount = 0;  
    semaphore rmutex = 1;   // 用于读者进程互斥修改readcount;  
    semaphore fmutex = 1;   // 用于读者和写者互斥访问文件   
    semaphore fair = 1;     // 用于实现公平竞争,锁住新进读者队列  
      
    // 写者操作  
    writer()  
    {  
        P(fair);    // 读者队列  
        P(fmutex);      
        ...
        写者操作
        ... 
        V(fmutex);  
        V(fair);  
    }  
      
    // 读者操作  
    reader()  
    {  
        P(fair);  
        P(rmutex);  
        if (readcount == 0)  
            P(fmutex);  
        readcount ++;  
        V(rmutex);  
        V(fair);  
      
        ...
       读者操作
        ... 
      
        P(rmutex);  
        readcount --  
        if (readcount == 0)  
            V(fmutex);  
        V(rmutex);  
    }  
    
    展开全文
  • 操作系统大作业(三)

    千次阅读 2021-06-13 19:14:22
    作业三问题资源分配图死锁定理判断 问题 假设系统有5类独占资源:Rl、R2、R3、R4、R5。各类资源分别有2、2、2、1、1个。系统有5个进程:P1、P2、P3、P4、P5。其中P1已占有2个R1,且申请1个R2和1个R4;P2已占有1个R2...

    问题

    假设系统有5类独占资源:Rl、R2、R3、R4、R5。各类资源分别有2、2、2、1、1个。系统有5个进程:P1、P2、P3、P4、P5。其中P1已占有2个R1,且申请1个R2和1个R4;P2已占有1个R2,且申请1个Rl;P3已占有1个R2,且申请1个R2和1个R3;P4已占有1个R4和1个R5,且申请1个R3;P5已占有1个R3,且申请1个R5。
    (1)试画出该时刻的资源分配图。
    (2)什么是死锁定理?如何判断(1)中给出的资源分配图有无死锁?给出判断过程和结果。

    资源分配图

    在这里插入图片描述

    展开全文
  • 操作系统第一章操作系统引论作业

    千次阅读 2021-03-06 12:52:52
    操作系统第一次课程作业 1.如果计算机不配操作系统,用户编写程序与运行程序需经历怎样的过程 需要人工操作,需要编写机器语言,需要脱机输入输出。 2.什么是操作系统?它有什么基本特征?列举4种操作系统的名称。 ...
  • 操作系统——短作业优先调度算法

    千次阅读 2021-06-02 10:26:39
    操作系统——短作业优先调度算法 实验内容 模拟实现FCFS/SJF调度。 设置作业体:作业名,作业的到达时间,服务时间,作业状态(W——等待,R——运行,F——完成),作业间的链接指针; 作业初始化:由用户输入作业名...
  • 操作系统作业调度和进程调度的理解 含义: 作业调度:是指作业从外存调入到内存的过程 进程调度:是指进程从内存到分配cpu执行的过程 理解: 当我们打开两个程序,不妨设为程序A和程序B,首先这两个程序都是在外存...
  • 实验项目性质:验证性实验 所属课程名称:《操作系统》 实验计划学时:2学时一、实验目的本实验要求学生模拟作业调度的实现,用高级语言编写和调试一个或多个作业调度的模拟程序,了解作业调度在操作系统中的作用,...
  • 操作系统作业调度算法C代码实现

    千次阅读 多人点赞 2021-03-04 17:46:03
    去年学的操作系统,现在有学妹问调度算法实现发现自己没有复习竟然忘了很多,借此机会把原来的知识捡回来。本文是原来通过C实现作业调度算法的集合。 一、进程入队与出队模拟 入队代码: #include <...
  • 一、引入 ★分页系统是以页面作为内存分配的基本单位,能有效地提高内存利用率,但信息共享等不方便; ★分段系统是以段作为内存分配的基本单位,它能够更好地...地址空间划分:作业的地址空间仍按其逻辑结构分段。每
  • 操作系统-短作业优先算法

    千次阅读 2021-06-27 14:50:23
    作业优先 算法思想 短作业优先也可以直接按到达时间来排序,不过第一个位置应该先给条件最优的作业,然后进行时间排序。 计算时,因为是时间大小排序,当作业服务时间更短时,要将其往前移动来达到短作业优先的...
  • 西安电子科技大学-电子工程学院-微机原理与接口技术大作业简介一、实验要求二、程序设计2.1 任务1:将字符串中的小写字母变换成大写字母2.1.1 主框架2.1.2 输入字符串函数2.2 任务2:在字符中找最大值2.2.1 主框架...
  • 所谓按序申请,是指资源是有线性顺序的,申请的时候可以先申请资源序号小的,再申请资源序号的,这样线性化后自然就不存在循环了。 如果感兴趣的话可以去仔细看看05 | 一不小心就死锁了,怎么办?,这里就不多介绍...
  • 操作系统大作业整理

    千次阅读 2020-12-20 20:50:43
    进程在系统中有哪几种基本状态,状态如何发生变化?10.0分) 正确答案: 通常一个进程至少有三种不同的状态:运行状态、就绪状态、等待状态。 (1)运行状态(Running):当一个进程正在处理机上运行时,称其处于运行状态。...
  • 嵌入式系统课程大作业设计报告

    千次阅读 2021-02-07 14:41:23
    嵌入式系统课程大作业设计报告 设计题目 基于Arm-Linux的嵌入式计数器设计 一、需求分析         1.根据系统功能,进行系统需求分析,设计嵌入式设备的软硬件总体方案,...
  • 作业调度和进程调度算法 先来先服务(first-come first-served,FCFS)调度算法:按照作业/进程到达的先后顺序进行服务。 短作业优先(short job first,SJF)的调度算法:最短的作业/进程优先得到服务。 高响应比优先...
  • import java.util.ArrayList; import java.util.List;...public class 短作业优先算法 { public static Job ans[]; public static int time,num; public static List<Job> list; public static void main(St.
  • 按照到达时间从小到排序,第一行输出作业的名字,第二行输出到达时间,第三行输出服务时间,第四行输出完成时间,第五行输出完成时间,第六行输出带权周转时间。 输入样例: 在这里给出一组输入。例如: 5 A B C D ...
  • 《电大计算机本科《操作系统作业3及答案》由会员分享,可在线阅读,更多相关《电大计算机本科《操作系统作业3及答案(4页珍藏版)》请在人人文库网上搜索。1、1.2.3.4.5.6.7.8.9.10.11.12.操作系统课程作业(三)...
  • 问题 1 答案 结果太长,这里仅仅给出命令。 ./paging-policy.py -s 0 -n 10 -p FIFO -c ./paging-policy.py -s 1 -n 10 -p FIFO -c ./paging-policy.py -s 2 -n 10 -p FIFO -c ..../paging-policy.py -s 0 -n 10 -...
  • 《计算机操作系统作业(一)(附答案)》由会员分享,可在线阅读,更多相关《计算机操作系统作业(一)(附答案)(6页珍藏版)》请在人人文库网上搜索。1、一、单选题1、(D)不是基本的操作系统。A批处理操作系统 B分时操作...
  • 操作系统概论名词解释操作系统:是配置在计算机硬件系统上的第一层软件,是对硬件系统的第一次扩充软件:是提高计算机系统效率和方便用户使用计算机的程序.响应时间:指用户发出命令,到系统完成用户命令所需的时间。分...
  • 有一个具有两道作业的批处理系统作业调度采用短作业优先的调度算法,进程调度采用以优先数为基础的抢占式调度算法,在下表所示的作业序列,作业优先数即为进程优先数,优先数越小优先级越高。(1)列出所有作业...
  • 北理工《操作系统》在线作业满分

    千次阅读 2021-06-24 06:16:14
    北理工《操作系统》在线作业试卷总分:100 得分:100一、 单选题 (共 20 道试题,共 40 分)1.很好地解决了“零头”问题的存储管理方法是( )A.页式存储管理B.段式存储管理C.多重分区管理D.可变式分区管理正确答案 :A更 ...
  • 计算机操作系统

    千次阅读 2021-07-13 02:43:47
    spContent=Windows、Linux、Andriod、iOS,以及不久前横空出世的鸿蒙,都是操作系统。你几乎每天都在使用操作系统,可是你有没有想过,操作系统是如何设计实现出来的呢?本课程将带你深入剖析操作系统各个管理模块的...
  • 操作系统 形考 3一、单选题(每题 3 分,共计 16 题)题目 1答案已保存满分 3.00标记题目题干17. 文件的存储空间管理实质上是组织和管理( )。选择一项:A. 辅存已占用区域B. 辅存空闲块C. 文件目录D. 进程控制块题目 2...
  • 操作系统死锁课后作业

    千次阅读 2021-05-11 00:03:04
    设每个进程分配n - 1个资源不会发生死锁 则有:(n – 1) * 5 + 1 > 6 解得n > 2 则当n 时,系统不会发送死锁 (2)某系统有8个进程,每个进程最多申请7个资源,当系统资源数不少于多少时,就不会发生死锁?...
  • 计算机操作系统复习知识点集合

    千次阅读 多人点赞 2020-12-19 18:45:41
    文章目录一、绪论1、操作系统的定义2、操作系统的特征3、操作系统的功能4、操作系统的分类 一、绪论 1、操作系统的定义 操作系统是将系统中的各种软、硬资源有机地组合成一个整体,合理地组织计算机的工作流程,为...
  • "题目:Linux系统中的shell是负责( )的模块。: 解释并执行来自终端的内部命令; 进行系统调用; 解释并执行来自终端的外部命令; 解释并执行来自终端的命令""题目:Linux系统中的进程调度采用( )。: 短作业优先法; 时间...
  • 操作系统的定义及作用 操作系统的定义和作用 **定义:**一、以尽量有效合理的方式组织和管理计算机的各种硬件资源(CPU、内存、磁盘等)。 ​ 二、合理组织计算机的工作流程,控制程序的执行,并在程序执行的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 251,822
精华内容 100,728
关键字:

操作系统大作业