首页 > 系统相关 >Linux环境编程day03--文件管理

Linux环境编程day03--文件管理

时间:2023-08-05 09:35:09浏览次数:48  
标签:文件 const day03 st char -- int Linux 链接

分别使用标准IO和系统IO写入一百万个整数到文件,测试谁的时间更短?为什么?
结论:在同等数据的写入下,使用标准IO要比直接使用系统IO更快
原因:标准IO有缓冲区机制,在执行fwrite写文件时,数据不是直接调用系统IO写入磁盘,而是先存放在内存的缓冲区中,直到缓冲区满后才会调用一次系统IO全部写入到磁盘,因此对系统IO的调用次数、用户态内核态的转换次数都大大降低
而直接使用系统IO是没有缓冲区机制,因此耗时增加
解决:如果给系统IO也加上缓冲区机制,那么它的速度要比标准IO更快

随机读写:

每个打开的文件都有一个记录读写位置的指针,也称文件位置指针,对文件的读写时该指针会自动往后移动,因此顺序读写时无需操作
当需要去文件的任意位置进行读写时,才需要调整该指针的位置
标准IO:
int fseek(FILE *stream, long offset, int whence);
返回值:成功0 失败-1
系统IO:
off_t lseek(int fd, off_t offset, int whence);
返回值:成功返回调整后位置指针的位置 失败-1

系统IO中的文本文件的读写:

在系统IO中没有类似fprintf\fscanf函数,因此没有直接对文本文件读写的操作
但是可以通过把数据转换成字符串进行间接的文本文件读写
写文本文件
任意类型数据对象 sprintf 转换成字符串 write写入
读文本文件
按字符串格式读取到内存 sscanf 解析到任意类型数据中

文件描述符(fd):

1、非负整数,代表了一个打开的文件
2、通过系统调用(open\creat)返回,该数值是被内核使用的
3、它在内核中对应一个内核对象,因为内核不能暴露它真实的地址,因此不能直接返回真实的文件地址,而是使用文件描述符来表示
4、内核中有一张记录了所有已打开的文件的二维表,文件描述符就是访问该表每行的下标,文件描述符也称为句柄,就是访问文件的凭证
5、内核中有三个默认长期打开的文件描述符
0 标准输入 宏STDIN_FILENO FILE* stdin
1 标准输出 STDOUT_FILENO stdout
2 标准错误 STDERR_FILENO stderr

文件描述符的重定向:

int dup(int oldfd);
功能:复制一个已经打开的文件描述符
返回值:返回一个当前进程没有使用的最小的文件描述符,该描述符与oldfd对应一个文件
int dup2(int oldfd, int newfd);
功能:复制oldfd文件描述符为newfd
如果newfd已经被打开,那么会先关闭newfd再复制
相当于newfd\oldfd同时对应原oldfd对应的文件

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc,const char* argv[])
{
    int oldfd = dup(1);
    int fd = open("hehe.txt",O_RDWR|O_TRUNC);
    if(0 > fd)
    {
        perror("open");
        return -1;
    }
    dup2(fd,1);//复制oldfd文件描述符为 1 标准输出 STDOUT_FILENO stdout
    printf("hehehxixixixix\n");//在hehe.txt中显示
    fflush(stdout);//清理缓冲区
    dup2(oldfd,1);
    printf("xixi\n");
    close(fd);
    close(oldfd);
}

重定向的作用:
把一个已经打开的文件描述符fd 经过dup2指定复制为标准输入0\标准输出1\标准错误2,则会先关闭已经打开的0\1\2,然后0\1\2重定向指向fd对应的文件
就可以通过printf\scanf函数就可以直接往fd对应的文件进行读写,相当于write\read
但是在当前进程中会导致后续无法使用标准输入、输出、错误文件,因此可以在开始前通过dup先备份这些文件,结束后通过dup2重新指向标准文件

文件同步:
1、在写入数据时,内存与磁盘之间有一块缓冲区,目的是为了降低磁盘的读写次数、提高读写效率
2、但是这种机制带来的后果是磁盘中的数据与实际写入的数据可能不符合,系统提供了三个函数让缓冲区中的数据立即写入磁盘,称为文件同步
fsync\sync\fdataync

文件属性:

int stat(const char * pathname, struct stat * buf);
功能:根据文件路径获取文件的属性
buf:输出型参数
int fstat(int fd, struct stat * buf);
功能:根据文件描述符获取文件的属性
int lstat(const char * pathname, struct stat * buf);
功能:根据文件路径获取软链接文件的属性

struct stat {
    dev_t     st_dev;         // 设备ID
    ino_t     st_ino;         // inode节点号
    mode_t    st_mode;        // 文件的类型和权限
    nlink_t   st_nlink;       // 硬链接数
    uid_t     st_uid;         // 用户ID
    gid_t     st_gid;         // 组ID
    dev_t     st_rdev;        // 特殊设备ID
    off_t     st_size;        // 总字节数
    blksize_t st_blksize;     // IO块总字节数
    blkcnt_t  st_blocks;      // 占用大小512字节的内存块数量
    struct timespec st_atim;  // 最后访问时间
    struct timespec st_mtim;  // 最后修改时间
    struct timespec st_ctim;  // 最后状态修改时间
#define st_atime st_atim.tv_sec /* Backward compatibility */ 
#define st_mtime st_mtim.tv_sec #define st_ctime st_ctim.tv_sec 
};
文件的权限:

int access(const char *pathname, int mode);
功能:测试当前用户对文件的权限
pathname:想要测试的文件路径
mode:想要测试的权限
F_OK 测试文件是否存在
R_OK 测试文件是否有读权限
W_OK 测试文件是否有写权限
X_OK 测试文件是否有执行权限
返回值:存在返回0 不存在返回-1
int chmod(const char *pathname, mode_t mode);
功能:根据文件路径修改文件权限
mode:由三个八进制数组成的权限掩码
0xxx
0644 0666 普通文件
0755 可执行文件

int fchmod(int fd, mode_t mode);
功能:根据文件描述符修改文件权限

权限屏蔽码:
如果想让新创建(open\creat)的文件不具备某些权限,可以通过设置权限屏蔽码进行屏蔽权限
查看命令 umask 查看当前终端的权限屏蔽码
注意:可以通过chmod命令、函数可以无视权限屏蔽码
修改权限屏蔽码:
命令:umask 0xxx 修改成0xxx
注意:只是当前终端临时有效,如果想要长期有效需要修改配置文件
函数:mode_t umask(mode_t mask);
mask:新的屏蔽码
返回值:原来的屏蔽码
注意:该函数只是当前进程中生效,进程结束后就失效了

修改文件的大小:
int truncate(const char *path, off_t length);
功能:根据文件路径截取文件长度
length:截取后文件的长度(字节)
int ftruncate(int fd, off_t length);
功能:根据文件描述符截取文件长度

文件删除、重命名:

int remove(const char *pathname);
功能:由C标准库提供的删除文件函数
int unlink(const char *pathname);
功能:操作系统提供的删除文件函数

remove底层调用unlink、rmdir函数
1、如果删除的是硬链接文件或者原文件本身且文件是关闭的,则是把该文件的硬链接数减1,然后清除该文件的inode信息
2、当文件的硬链接数减为0时,系统就把该文件的block权限释放,可以用于存储其它文件的数据
3、如果删除软链接文件,则删除的是软链接文件的inode信息,而不会删除原文件的数据,没有任何一个函数可以通过软链接文件删除源文件

int rename(const char *oldpath, const char *newpath);
功能:重命名文件

Linux文件系统会把分区分为两大部分:
inode信息块区:
每块默认128B,记录某个文件的文件权限、大小、所有者、修改时间等属性信息以及该文件的block信息
block数据块区:
每块默认4Kb,记录了文件的真正内容数据、文件名
每个文件有且只有一个inode信息块以及若干个block数据块,读取文件file需要借助所在目录文件的block中记录的file文件的inode号和文件名,来找到file的inode信息块,从而读取file文件的block数据块
硬链接文件:
没有属于自己的inode和block,只是在不同的目录下复制链接的源文件的inode信息块,通过该复制的inode信息块访问源文件的block数据块
软链接文件:
软链接文件会创建自己的新的inode和block块,在软链接文件的block中不存储源文件的数据,而是存储源文件的inode号,从而借助源文件的inode来访问源文件的block
区别:
1、删除源文件,只是删除源文件的inode信息块中的内容,对应的block的数据不会清理,所以硬链接文件依然可以访问,但是软链接文件就无法访问了
2、当文件的硬链接数删除到0时,文件才算被真正的删除了
3、修改硬链接文件的内容,源文件也会随之修改
4、硬链接不能链接目录、软链接可以
5、硬链接不能跨文件系统使用,而软链接可以

int link(const char *oldpath, const char *newpath);
功能:创建硬链接文件

int symlink(const char *target, const char *linkpath);
功能:创建软链接文件 文件类型 l

目录操作:
int mkdir(const char *pathname, mode_t mode);
功能:创建空目录
mode:目录的权限,必须有执行权限才能进入目录
返回值:成功0 失败-1

int rmdir(const char *pathname);
功能:删除空目录


int chdir(const char *path);
功能:修改当前的工作路径为path 相当于cd


char *getcwd(char *buf, size_t size);
功能:获取当前进程的工作路径 相当于pwd


DIR *opendir(const char *name);
功能:根据目录路径打开目录
返回值:成功返回一个目录流对象


DIR *fdopendir(int fd);
功能:根据目录文件描述符打开目录
返回值:成功返回一个目录流对象

注意:DIR目录流对象中记录了该目录中所有文件的信息
struct dirent *readdir(DIR *dirp);
功能:从目录流dirp中读取一条文件信息并返回
struct dirent {
    ino_t  d_ino;       // inode号
    off_t  d_off;       // 距离下一条信息的字节数
    unsigned short d_reclen;  // 当前信息的字节数
    unsigned char  d_type;   // 文件类型
    char           d_name[256]; // 文件名
};

注意:readdir读取完一条信息后,会自动的指向下一条信息,只需要继续执行readdir即可读取下一条,直到返回值为NULL读取完毕

标签:文件,const,day03,st,char,--,int,Linux,链接
From: https://www.cnblogs.com/bigflyny/p/17607492.html

相关文章

  • C#获取文件信息大全
    C#获取文件信息大全 转自:   https://mp.weixin.qq.com/s/HYUJAvXchZywWQRtr_Aj9g在.NET开发中,用C#获取文件信息是比较常见的操作。通过获取文件信息,我们可以了解文件的属性、大小、创建日期、修改日期等各种元数据信息。比如我们网站需要上传文件,可以用扩展名称控......
  • 凸优化8——线性规划、二次规划
    线性规划以及等价变换中科大-凸优化笔记(lec25)-等价变换_凸优化等价_及时行樂_的博客-CSDN博客二次规划QP 二次约束二次规划QCQP中科大-凸优化笔记(lec26)-二次规划_二次约束二次规划_及时行樂_的博客-CSDN博客引入了lasso回归和岭回归......
  • sql 中延迟执行
    SQL有定时执行的语句WaitFor。语法格式:waitfor{delay'time'|time'time'}delay后面的时间是需要延迟多长时间后执行。time后面的时间是指定何时执行,格式为'HH:MM:SS',不支持日期例:``--指定10:00执行Beginwaitfortime'10:00'select*fromtablenameend--指定等待1......
  • Linux环境编程day04--信号产生与处理
    信号管理基本概念1、中断当进程接收到消息后中止当前正在进行进程,转而去执行其它任务,等其它任务执行结束后再返回刚刚中止的位置,可以继续往下运行这种执行模式称为中断中断分为硬件中断、软件中断,硬件中断是由硬件设备引发的、软件中断是执行了中断指令引发2、信号信号是一......
  • 前后端联调步骤
    确定接口:前后端需要确定接口的格式和参数。可以使用RESTfulAPI或其他协议来定义接口。模拟数据:前端可以使用mock数据来模拟后端接口的数据,以便在没有实际数据的情况下进行测试。联调接口:前后端开始通过接口协作来实现整个应用的功能。后端提供接口,前端调用接口获取数据。......
  • yapi安装及使用
    yapi介绍YApi是一款高效、易用、功能非常强大的api可视化接口管理平台,旨在为互联网公司的技术人员提供更优雅的接口管理服务系统。它可以帮助开发者快速创建、发布、维护API接口,并且YApi为用户提供了优秀的交互体验,技术人员只需利用平台提供的接口数据写入工具以及很少的点击......
  • 应用不停服,平滑升级分库分表还能这样做
    背景分库分表是大型互联网应用经常采用的一种数据层优化方案,常见的分库分表中间件如sharding-jdbc、mycat都已经比较成熟,基本上可以应对我们一般的分库分表需求。做过分库分表的同学应该知道,在给业务系统做分库分表改造过程中,难的不是如何使用这些组件进行分库分表,......
  • sql注入发现
    1、异常YouhaveanerrorinyourSQLsyntax;checkthemanualthatcorrespondstoyourMySQLserverversionfortherightsyntaxtousenear''1'''atline1一般适用于查询输出的场景,而对于盲注场景和其它sql语句类型,基本不会输出sql异常。......
  • nflsoj 1351 抓住奶牛
    这题类似走迷宫,走迷宫是向四个方向进行拓展,而这道题好比是向三个方向拓展,分别是:\(x+1,x-1,x×2\)在这里拓展的时候我写了一个函数operation来计算拓展后的坐标这里判断坐标是否合法的时候我取了最大值的两倍加5,因为坐标不一定在\(k\)的左边,有可能超出去了再往回走,不过超出一......
  • P4850 [IOI2009] Raisins 题解
    前言:IOI还出这样水的纯记忆化搜索题?还是T4?真令人难以置信。题意:题目传送门一个N×M的矩阵,对于任意一个子矩阵,只能横着或竖着分割,并且分割一次的价值为改子矩阵的元素之和,现要将该矩阵分割成1×1的方格,求最小的分割总价值之和。思路:看到这是个最优化的题,且数据范围很......