目录
谢谢帅气美丽且优秀的你看完我的文章还要点赞、收藏加关注
没错,说的就是你,不用再怀疑!!!
希望我的文章内容能对你有帮助,一起努力吧!!!
1、文件系统
1.1“裸奔”层次:不带操作系统的编程
APP 应用层
-----------------
HardWare 硬件层
特点:
- 简单,粗暴应用层直接操作硬件(寄存器、IO口...)
缺点:
- 开发应用、要能搞懂原理图
- 了解硬件的细节
- 不能同时运行多个任务:单任务运行
1.2带“OS”的编程
APP 应用层
-----------------
OS 操作系统
-----------------
Hardware 硬件层
特点:
- 开发应用、主要实现应用的逻辑实现
- 不需要关心底层硬件的实现细节
- 可以支持多任务运行、并发
缺点:
- API(application interface) 太多了
- API的实现(功能)可能不是我们想要的
OS:Operating System 操作系统。是直接运行在“裸机”的最基本的系统软件,任何软件/应用程序都必 须要在操作系统的支持下才能正常运行。
操作系统:
- windows x86/xp/win8/win10/win11
- linux ubuntu/centos/redhat/kali
- mac
- IOS
- Android
- 鸿蒙
- uinx
Linux操作系统下进行开发应用软件,就是调用Linux操作系统为我们提供的系统的API函数接口去操作硬 件。或者是说用Linux提供的服务来完成linux下的一些开发。
1.3Linux文件系统
在linux下面,一切皆文件。在linux 下面操作任何东西,其实都是通过操作文件来实现的,通过文件的 接口实现。
文件系统
用来存储、组织、管理文件的一套方式、方法、协议以及软件的实现...
文件:
- 文件属性:inode(编号),inode----> 文件内容...
- 文件内容:文件的实际存储的内容
文件在Linux下的操作过程:
- 硬链接(找文件名)---->inode
- linux内核
// 是用来描述一个文件的物理的inode信息
系统如果识别到了一个文件的存在,就会问他在linux内核里面创建一个struct inode的一个文 件对应的inode。
struct inode{};
/*
用来描述一个已经打开了的文件信息的。
文件状态便宜了(类似于文本光标)
每个打开的文件都会对应一个struct file
一个文件是可以被多个不同应用打开
*/
struct file{}
操作过程:struct file ---> struct inode ---> 硬件上的inode ---> 文件内容
linux为了屏蔽文件操作的具体实现细节,它会为进程创建一个“进程文件表项"
1.4进程文件表项
每一个应用都会有一个进程文件表项,保存进程打开的文件的sturct file结构体指针,相当于是一个 struct file *的数组(集合),打开一个文件,只需要返回一个下标给我使用就可以了
struct file* [ ]
打开一个文件,文件的struct file指针被分配到0下标,就可以使用0下标在进程文件表项中获取文件的 struct file指针使用了。
open 打开一个文件
返回值就是打开的文件在进程文件表项中的下标
linux提供系统操作函数:open、write、read、close...以上这些函数都是称为:“系统IO”
系统IO:操作系统所提供的对于文件的输入输出的函数接口
2、系统IO
2.1Linux系统IO应用
2.1.1umask
umask:用来设置一个文件的创建的掩码(掩盖部分功能)的。
mask掩码中为1的bit位,在文件创建的时候,不能指定这个bit位所对应的权限
0111 0111 0111 ---> 777 ---> rwx rwx rwx 权限全部没有
通过open创建一个文件的时候如果指定了文件的权限:0777,但是umask值为:0022的时候
实际文件被创建之后的权限为:0777 & ~umask
0777 & ~ 0022
0777 & 0755、
0755
#include <sys/types.h>
#include <sys/stat.h>
#include <iostream>
int main()
{
// 掩码值
int mask = 0222;
int old_mask = umask(mask);
std::cout << old_mask << std::endl;
return 0;
}
每一个进程都会自己的工作(目录)路径,指定文件名要么是绝对路径要么是相对路径,相对路径其实 就是相对于当前程序的工作路径而言。
2.1.2获取进程(程序)的当前工作路径
获取进程当前的工作目录(路径)的绝对路径
/*
获取进程的当前工作路径的API
*/
#include <iostream>
#include <unistd.h>
int main()
{
// 1种 第一种一般不使用
char wd_array[200];
if(NULL == getwd(wd_array))
perror("第一种获取错误");
// 2种
char cwd_array[200];
if(getcwd(cwd_array,200) == NULL)
perror("第二种获取错误");
// 3种
char *current_dir = get_current_dir_name();
if(current_dir == NULL)
perror("第二种获取错误");
std::cout << wd_array << std::endl;
std::cout << cwd_array << std::endl;
std::cout << current_dir << std::endl;
free(current_dir);
return 0;
}
2.1.3改变进程的工作路径
改变进程的当前工作路径
/*
改变进程的当前工作的路径
*/
#include <iostream>
#include <unistd.h>
int main()
{
char *cut_dir = get_current_dir_name();
std::cout << "当前工作路径:" << cut_dir << std::endl;
free(cut_dir);
std::cout << "修改当前工作路径:" << std::endl;
chdir("/");
cut_dir = get_current_dir_name();
std::cout << "当前工作路径:" << cut_dir << std::endl;
free(cut_dir);
return 0;
}
2.1.4文件截短
用来给一个文件截短内容至指定的长度
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
int main()
{
// 1
truncate("./1.txt",5);
// 2
int fd = open("./1.txt",O_RDWR);
ftruncate(fd,10);
close(fd);
}
注意:
- length < 源文件长度的时候
- 源文件中后面的内容看不到了
- length > 源文件长度的时候
- undefined,空洞的内容是随机被填充的。一直要扩展到length个字节。
2.1.5删除文件
删除文件
#include <iostream>
#include <unistd.h>
int main()
{
unlink("1.txt");
return 0;
}
删除一个目录
#include <unistd.h>
int main()
{
rmdir("./1");
return 0;
}
删除文件/目录
- remove 删除文件 等价 unlink 删除文件
- remove 删除目录 等价 rmdir 删除目录
2.1.6文件属性的获取
获取文件属性
2.2文件的操作步骤
2.2.1打开文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <iostream>
int main()
{
int fd = open("./open1.cpp",O_RDONLY);
if(fd == -1)
{
std::cout << "文件打开失败" << std::endl;
perror("错误:"); // 打印错误 ,如果文件不存在:No suck file or directory 没有哪个文件或者目录
return -1;
}
std::cout << "文件打开成功" << std::endl;
close(fd);
return 0;
}
2.2.2读文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <iostream>
#include <unistd.h>
int main()
{
int fd = open("./1.txt",O_RDONLY);
if(fd == -1)
{
perror("文件打开失败");
return -1;
}
// 需要有一个空间来存储读取到的数据
unsigned char data[1000]={0};
int ret = read(fd,data,500);
if(ret == -1)
{
perror("文件读取失败");
return -1;
}
std::cout << "成功读取到:" << ret << "个字节" << "内容:" << data << std::endl;
close(fd);
return 0;
}
2.2.3写文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <iostream>
#include <unistd.h>
#include <cstring>
int main()
{ // 追加内容
int fd = open("./1.txt",O_RDWR|O_APPEND);
if(fd == -1)
{
perror("文件打开失败");
return -1;
}
// 需要有一个空间来存储读取到的数据
unsigned char data[1000]={"ABCDEFG"};
int ret = write(fd,data,strlen((const char*)data));
if(ret == -1)
{
perror("文件写入失败");
return -1;
}
std::cout << "成功写入:" << ret << "个字节" << std::endl;
close(fd);
return 0;
}
2.2.4关闭文件
2.2.5设置偏移量
有时候咱们想在文件中间某个指定的文件插入内容
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <iostream>
#include <unistd.h>
#include <cstring>
int main()
{ // 追加内容
int fd = open("./1.txt",O_RDWR|O_APPEND);
if(fd == -1)
{
perror("文件打开失败");
return -1;
}
// 需要有一个空间来存储读取到的数据
unsigned char data[1000]={"ABCDEFG"};
int ret = write(fd,data,strlen((const char*)data));
if(ret == -1)
{
perror("文件写入失败");
return -1;
}
std::cout << "成功写入:" << ret << "个字节" << std::endl;
lseek(fd,9,SEEK_SET);
char buf[100]={0};
read(fd,buf,50);
std::cout << buf << std::endl;
close(fd);
return 0;
}
注意:当一个文件被成功打开之后,光标所属位置,在最开始的位置。除非打开的时候使用了 O_APPEND,那么光标就会移动到文件内容的最末尾
注意:当文件没有被关闭,那么进行write/read操作会改变光标位置,光标的偏移会被read/write的 返回值影响。
2.3目录操作
2.3.1打开目录
2.3.2操作目录
创建一个目录
读取目录的内容
注意:该结构体成员变量:d_ino、d_name是所有linux系统都支持的。如果想让代码具有更好的可移 植性,该结构体代码中,只能用d_ino、d_name这两个成员变量。