Linux文件系统实验(C语言实现新建、打开、关闭、读写文件以及查改文件权限)

操作系统实验导航
实验一:银行家算法 https://blog.csdn.net/weixin_46291251/article/details/115384510
实验二:多级队列调度和多级反馈队列调度算法 https://blog.csdn.net/weixin_46291251/article/details/115530582
实验三:动态分区式内存管理 https://blog.csdn.net/weixin_46291251/article/details/115772341
实验四:Linux下多进程通信 https://blog.csdn.net/weixin_46291251/article/details/116274665
实验五:进程通信的三种方式 https://blog.csdn.net/weixin_46291251/article/details/116301250
实验六:Linux文件系统实验 https://blog.csdn.net/weixin_46291251/article/details/116423798
实验七:自制简单U盘引导程序 https://blog.csdn.net/weixin_46291251/article/details/116427629
实验八:磁盘调度算法 https://blog.csdn.net/weixin_46291251/article/details/116431907
实验九:请求分页系统中的置换算法 https://blog.csdn.net/weixin_46291251/article/details/116443021
学习笔记:操作系统复习笔记 https://blog.csdn.net/weixin_46291251/article/details/117086851

题目描述:

使用文件系统调用编写一个文件工具 filetools,使其具有以下功能:

  • 1.创建新文件
  • 2.写文件
  • 3.读文件
  • 4.修改文件权限
  • 5.查看当前文件权限
  • 0.退出
  • 提示用户输入功能号,并根据用户输入的功能选择相应的功能。

文件按可变记录文件组织,具体记录内容自行设计。

算法设计:

打开/新建文件(open)

调用open可以打开或创建一个文件。

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int oflag, ... /* mode_t mode */);

返回若成功为文件描述符,若出错为- 1
参数:
第一个参数**pathname*是要打开或创建的文件的名字。
第二个参数oflag参数可用来说明此函数的多个选择项。用下列一个或多个常数进行或运算构成oflag*参数(这些常数定义在< fcntl . h >头文件中, 在这三个常数中应当只指定一个):

O_RDONLY 只读打开
O_WRONLY 只写打开
O_RDWR 读、写打开

第三个可选参数:

O_APPEND 每次写时都加到文件的尾端。
O_CREAT 若此文件不存在则创建它。使用此选择项时,需同时说明第三个参数mode,用其说明该新文件的存取许可权位。
O_EXCL 如果同时指定了O_CREAT,而文件已经存在,则出错。这可测试一个文件是否存在。
O_TRUNC 如果此文件存在,而且为只读或只写成功打开,则将其长度截短为0。
O_NONBLOCK 如果pathname指的是一个FIFO、一个块特殊文件或一个字符特殊文件,则此选择项为此文件的本次打开操作和后续的I /
O操作设置非阻塞方式。
O_SYNC 使每次write都等到物理I / O操作完成。

读文件(read)

#include <unistd.h>
ssize_t read(int fd, void *buff, size_t nbytes) ;

返回:读到的字节数,若已到文件尾为0,若出错为-1

写文件(write)

#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t nbytes) ;
  • 返回:若成功为已写的字节数,若出错为-1
  • 对于普通文件,写操作从文件的当前位移量处开始。如果在打开该文件时,指定了O_APPEND选择项,则在每次写操作之前,将文件位移量设置在文件的当前结尾处。在一次成功写之后,该文件位移量增加实际写的字节数。

查权限

char* pargv[4]={"ls","-l","file1",NULL};
 显示文件权限 execv("/bin/ls",pargv); 
 
  • 所以查询文件权限只需要:
    1.pargv[2]改为待操作的文件名
    2.执行execv("/bin/ls",pargv);

由于进程执行完execv后会退出而无法执行其他逻辑,于是fork一个子进程来作查权限的操作,主进程调用wait等子进程结束即可。

int p =fork();
            if(p==0)
                check_file_mod();
            else
                wait(NULL);       

改权限chmod

  • linux下的文件权限分三级:owner,group,others三类。每类占权限位的三位。
  • r 表示可读取,w 表示可写入,x 表示可执行,X 表示只有当该档案是个子目录或者该档案已经被设定过为可执行。
  • 其中:r=4,w=2,x=1
    例如:若要rwx属性则4+2+1=7;
    若要rw-属性则4+2=6;
    若要r-x属性则4+1=7。
  • 常见权限:

-rw------- (600) – 只有属主有读写权限。
-rw-r–r-- (644) – 只有属主有读写权限;而属组用户和其他用户只有读权限。
-rwx------ (700) – 只有属主有读、写、执行权限。
-rwxr-xr-x (755) – 属主有读、写、执行权限;而属组用户和其他用户只有读、执行权限。
-rwx–x--x (711) – 属主有读、写、执行权限;而属组用户和其他用户只有执行权限。
-rw-rw-rw- (666) – 所有用户都有文件读、写权限。这种做法不可取。
-rwxrwxrwx (777) – 所有用户都有读、写、执行权限。更不可取的做法。

lseek调用

每个打开的文件都有一个与其相关联的“当前文件位移量”。它是一个非负整数,用以度量从文件开始处计算的字节数。通常,读、写操作都从当前文件位移量处开始,并使位移量增加所读或写的字节数。按系统默认,当打开一个文件时,除非指定O_APPEND选择项,否则该位移量被设置为0。

#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence) ;

参数offset 的解释与参数whence的值有关

若whence是SEEK_SET,则将该文件的位移量设置为距文件开始处offset 个字节

若whence是SEEK_CUR,则将该文件的位移量设置为其当前值加offset, offset可为正或负

若whence是SEEK_END,则将该文件的位移量设置为文件长度加offset, offset可为正或负

具体代码:

/*
1.
open 	打开文件
creat 	创建新文件
close 	关闭文件描述字
read 	读文件
write 	写文件
*/

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>

int C_fd;           //文件描述符
char filename[100]; //文件名
int isopen = 0;     //打开状态
char *pargv[4] = {"ls", "-l", NULL, NULL};

void Open_Creat_file()
{
    printf("请输入要打开/创建的文件名: ");
    scanf("%s", filename);
    C_fd = open(filename, O_RDWR, 0666);
    if (C_fd >= 0)
    {
        isopen = 1, printf("%s已存在,打开成功\n", filename);
        pargv[2] = (char *)malloc(50);
        strcpy(pargv[2], filename);
    }
    else
    {
        C_fd = open(filename, O_CREAT, 0666);
        if (C_fd >= 0)
            isopen = 1, printf("%s不存在,新建成功\n", filename);
        else
            isopen = 0, printf("打开/新建%s失败\n", filename);
    }
    //close(fd);
}
void read_file()
{
    if (!isopen)
    {
        printf("没有打开的文件,请先打开一个文件\n");
        return;
    }
    else
        printf("当前处理的文件是:%s\n", filename);
    char buffer[100];

    lseek(C_fd, 0, SEEK_SET); //从头开始读
    int t = read(C_fd, buffer, 1024);
    if (t != -1)
        printf("文件内容为:%s\n", buffer);
    else
        printf("读取失败\n");
}
void write_file()
{
    if (!isopen)
    {
        printf("没有打开的文件,请先打开一个文件\n");
        return;
    }
    else
        printf("当前处理的文件是:%s\n", filename);
    char buffer[1024];
    printf("请输入待写入内容:\n");
    scanf("%s", buffer);

    int t = write(C_fd, buffer, strlen(buffer));
    if (t == -1)
        printf("写入失败!\n");
    else
        printf("写入成功!\n");
}
void change_file_mod()
{
    if (!isopen)
    {
        printf("没有打开的文件,请先打开一个文件\n");
        return;
    }
    else
        printf("当前处理的文件是:%s\n", filename);
    int new_mode;
    printf("输入新的模式(十进制)");
    scanf("%d", &new_mode);
    int mode_u = new_mode / 100;
    int mode_g = new_mode / 10 % 10;
    int mode_o = new_mode % 10;
    new_mode = (mode_u * 8 * 8) + (mode_g * 8) + mode_o; //八进制转换
    int t = chmod(filename, new_mode);
    if (t == -1)
        printf("改变模式失败!\n");
    else{
        printf("成功改变模式!\n");
        printf("新模式:%d\n",new_mode);               
    }
}
void check_file_mod()
{
    if (!isopen)
    {
        printf("没有打开的文件,请先打开一个文件\n");
        return;
    }
    else
        printf("当前处理的文件是:%s\n", filename);
    printf("文件权限为");
    int t = execv("/bin/ls", pargv);
    if (t == -1)
        printf("查看失败\n");
}
int main()
{

    printf("-----------------CC_File_Tools--------------\n");
    printf("1.打开(不存在则新建)       2.写文件       3.读文件  \n");
    printf("4.改权限     5.查权限       0.退出    \n");
    //printf("------------------------------------\n");

    int choice = -1;
    while (1)
    {
        printf("-------------请输入选择:-----------\n");
        scanf("%d", &choice);
        switch (choice)
        {
        case 0:
        {
            printf("\n\t感谢使用!\n\n");
            return 0;
        }
        case 1:
        {
            Open_Creat_file();
            break;
        }
        case 2:
        {
            write_file();
            break;
        }
        case 3:
        {
            read_file();
            break;
        }
        case 4:
        {
            change_file_mod();
            break;
        }
        case 5:
        {
            int p =fork();
            if(p==0)
                check_file_mod();
            else
                wait(NULL);            
            break;
        }
        default:
        {
            printf("您的输入有误,请重新输入!!!\n");
        }
        }
    }

    return 0;
}

运行结果:

在这里插入图片描述

  • 4
    点赞
  • 157
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cheney822

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值