实验六 存储管理

实验六 :存储管理

编写一个程序,利用内存映象文件,实现less工具的功能(多屏显示)。

  • 首先对less工具做一下介绍:less命令在linux下可以用于查看文件的内容,使用了 less 时,就可以使用 ↑ ↓ 等按 键的功能来往前往后翻看文件,更容易查看一个文件的内容、除此之外,在 less 里头可以拥有更多的搜索功能,不止可以向下搜,也可以向上搜

本题要求利用镜像文件简单实现less工具的功能,并且能够多屏显示内容。所以在下属代码书写中,使用了一次最多可以输出7行的显示方法,当继续使用空格时,可以继续显示下面7行的内容,除此之外,可以使用d命令实现查看以当前行为参照的下一行的内容,u命令用于显示以当前行为参照的上一行的内容,q表示退出指令。

代码如下:

#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
#include <memory.h>
#include <stdlib.h>
#include <stdio.h>
int lastrow(char *s, int d);
int nextrow(char *s, int d);
int onepage(char *s, int d);
int main()
{
    int fd, play = 0;
    char lab;
    char *start;
    struct stat sb;
    fd = open("王伟家.txt", O_RDONLY); //以只读方式打开文件
    fstat(fd, &sb);               //用来获取文件的大小
    /*
    *NULL表示让系统自动选定地址,
    *sb.st_size表示上一句的文件大小,对应到内存中的大小
    *PROT_READ表示映射区域可被读取
    *MAP_PRIVATE 对映射区域的写入操作会产生一个映射文件的复制,
    *即私人的“写入时复制”(copy on write)对此区域作的任何修改都不会写回原来的文件内容。
    *fd代表映射到内存的文件
    *0代表文件映射的偏移量
    *返回值为映射区的内存的起始地址
    */
    start = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
    if (start == MAP_FAILED) //MAP_FAILED表示映射不成功 直接返回
        return (1);
    play = onepage(start, play) + 1;
    lab = getchar();
    while (lab != 'q' && lab != 'Q')     //输入的字符为Q或者q 那么就会退出
    {
        if (play > sb.st_size)          //如果onepage返回的字节数大于文件的大小 则任意输入一个数退出
        {
            lab = getchar();
            break;
        }
        else if (lab == ' ')           //如果输入的是空格字符 则从上次结束的地方继续向屏幕读处下面10行的内容
            play = play + 1 + onepage(start, play);
        else if (lab == 'D' || lab == 'd')  //如果输入的是D或d则读出下一行
            play = play + 1 + nextrow(start, play);
        else if (lab == 'U' || lab == 'u')
            play = 1 + lastrow(start, play);
        lab = getchar();
    }
    munmap(start, sb.st_size);  //解除映射
    close(fd);                  //关闭文件
    return 0;
}
int onepage(char *s, int d)
{
    int i, count = 0;            //count在这里表示文件中行的数量
    char *buffer = malloc(2048); //配置内存空间,由buffer指向该空间

    s += d;              /*每7行作为一页输出*/
    for (i = 0; i < 2048; i++)
    {
        if (s[i] == '\n')
            count++;
        if (count == 7)
            break;            //当达到7行之后 跳出循环
    }
    memcpy(buffer, s, i);    //从s处开始的地方拷贝i个字节到buffer区域
    buffer[i] = '\0';        //给buffer添加结束符
    printf("%s\n", buffer);
    return i;
}
int nextrow(char *s, int d)   //输出以当前为参照的下一行的内容
{
    int i;
    char *buffer = malloc(100);
    s += d;
    for (i = 0; i < 100; i++)
        if (s[i] == '\n')
            break;
    memcpy(buffer, s, i);
    buffer[i] = '\0';
    printf("%s\n", buffer);
    return i;
}
int lastrow(char *s, int d)   //输出以当前为参照的上一行的内容
{
    int i, count = 0;
    char *buffer = malloc(100);
    int py = d;
    for (; d > 0; d--)
    {
        if (s[d] == '\n')
            count++;
        if (count == 2)
            break;
    }
    memcpy(buffer, s + d + 1, py - d - 2);
    buffer[py - d - 2] = '\0';
    printf("%s\n", buffer);
    return d;
}

打开的文件以及执行示意图如下:
在这里插入图片描述在这里插入图片描述

对上述代码所做的解释:

在上述代码中,首先以只读的方式打开一个文件,使用fstat()函数获取到该文件的大小,以防止在后续读取文件内容时越界。使用mmap()函数将文件的内容映射到内存中,加快读写的速率,并返回该文件的内容在内存中的起始地址。使用onepage函数一次性显示7行的内容,并返回该7行中左右的字节数,接下来输入字符,用于来决定进行何种操作,如果输入q指令,则退出读取文件的操作,如果使用空格指令,则继续读取下面的7行内容,实现分屏显示的功能。使用d指令,表示读取以当前行为参照的下一行的内容,使用u命令表示读取以当前行为参照的上一行的内容。最后读取文件内容完毕之后,解除映射,并关闭文件。

发布了33 篇原创文章 · 获赞 2 · 访问量 1728

猜你喜欢

转载自blog.csdn.net/weixin_42469716/article/details/89892220