Linux文件编程(进阶)

news2024/9/19 14:18:19

文章目录

  • Linux文件编程
    • 文件操作的基本元素(文件在磁盘上的操作)
    • 软链接和硬链接
      • 原理
      • 文件系统范围
      • 创建方式
      • 示例:在终端使用指令创建软硬链接
        • 软链接
        • 硬链接
      • 删除源文件影响
      • 软链接和硬链接实现的具体原理
      • link函数
      • unlink函数
        • 代码示例:使用`link`创建硬链接
        • 代码示例:使用`unlink`删除硬链接
      • remove函数
      • rename函数
        • 代码示例--使用`remove`解除对文件或者目录的连接
        • 代码示例--使用`rename`函数给文件重命名
      • symlink函数
      • readlink函数
        • 代码示例--使用`symlink`和`readlink`函数创建软链接和查找源文件

Linux文件编程

文件操作的基本元素(文件在磁盘上的操作)

文件操作最基本的元素是:目录结构、索引节点和文件数据的本身

  • 目录结构(目录项 用来存放文件路径和文件的索引节点)
  • 索引节点(i节点 用来存放数据块的块号)
  • 文件的数据

image-20240825180830498

在磁盘上操作文件的流程

image-20240825180938061

在Linux文件系统结构中有一个目录项,这个目录项存放了文件的路径和文件的i节点。当我们使用指令去操作一个文件的时候,首先会获取到文件的路径,然后根据目录项来获取到i节点i节点中存放的文件的数据块号,根据这个数据块号就能访问到对应的数据区。同时在Linux磁盘中的i节点和内核中的i节点是同步的,所以对文件的读写操作可以通过内核中的i节点同步磁盘中的i节点。

软链接和硬链接

原理

  • 软连接:软连接实际上是一个独立的特殊类型的文件,它存储的是目标文件或目录的路径。当你访问软链接时,系统会跟踪这个路径并解析到真正的目标文件。因此,软链接更像是一个指向目标文件的指针或快捷方式。
  • 硬链接:硬链接实际上是同一文件系统中同一个文件的多个“入口”。每个硬链接指向的是同一个文件的inode(索引节点),所有硬链接共享相同的inode和数据块。这意味着,无论你通过哪个硬链接访问文件,实际上看到的都是同一份数据。

文件系统范围

  • 软链接:可跨越不同的文件系统进行创建,而且能够对文件、目录进行创建软链接,同时也能够对不存在的文件创建软链接,只不过由于没有源文件是一个无效的符号链接文件;
  • 硬链接:不能跨系统操作,只能对文件创建硬链接,且必须是在同一个分区。

创建方式

  • 软链接:在Linux中使用ln -s来创建软链接;

  • 硬链接:使用ln创建,无需指定参数;

示例:在终端使用指令创建软硬链接

软链接
  • 给普通文件创建软链接:

image-20240826073925650

ln -s 源文件或目录 目标文件或目录

使用ls -l指令查看创建的文件可以发现,它的文件类型是一个符号链接文件,而且它所引用的源文件是temp.c

  • 给目录创建软链接

image-20240826075339002

首先在当前目录下创建一个目录,然后在此目录下创建一个文件进行编辑,然后给此目录创建软链接。可以发现通过软链接文件ld_test可以访问到test目录下的文件并进行修改。所以软链接文件是可以进行跨分区、跨系统进行操作的,并且使用方法和源文件或者目录没有区别,就像是创建了一个快捷方式。

硬链接
  • 给普通文件创建硬链接:

    image-20240826080454429

    上边使用ln指令给temp.c创建了一个硬链接,然后使用ls -l指令查看硬链接的文件类型,可以发现它是一个普通类型的文件。而且这里的2代表硬链接数,如果只有源文件的话,它的硬链接数是1,每创建一个硬连接,硬连接数就会加1。并且通过硬链接文件也能够访问到源文件里边的内容。

  • 给目录创建硬链接:

    image-20240826081130065

    通过尝试发现并不能给目录创建硬链接,之前在网上看到过说超级用户可以对目录创建硬链接,但实际测试好像并不可以。(具体原因下边会详细介绍)

删除源文件影响

  • 软链接:由于源文件被删除,所以软链接文件就失去了它的指向。因此当尝试通过软链接去访问之前的文件或者目录的时候,就会显示没有此文件。

  • 硬链接:即使是源文件被删除,但是还是能通过硬链接访问源文件里边的内容。

如下图:

image-20240826081744309

首先,通过cat指令来通过软链接和硬链接都能够访问到源文件里边的内容,当把源文件删除以后,通过ls -l指令查看软链接,发现它的文件名变成红色了,这就是我们通常说的软连接失效了。然后通过ls -l指令来查看硬链接发现它的硬链接数减1。通过cat指令发现软链接不能进行访问了,但是硬链接仍旧可以访问。

软链接和硬链接实现的具体原理

  • 硬链接

    image-20240826090418411

    如图所示:当创建一个文件的时候,通过目录项可以得知文件的i节点,通过i节点就能找到它对应的数据块号,也就能访问到它所指向的数据区当创建一个硬链接指向源文件的时候,它只创建一个目录项并且硬连接数做加1操作,并不会创建新的i节点和数据块,所以源文件和硬链接文件它们访问的是同一块数据区域,这也就解释了为什么当源文件删除以后硬链接还能够访问到源文件的内容,因为它所指向的这片数据区域没有被释放掉。所以当删除一个文件的时候,想要将内容清空,然后将这片数据区域释放,只有当它的硬连接数减为0的时候才说明它的源文件和硬链接文件全部删除了,也就意味这这片数据区域被释放掉了。不能对目录创建硬链接的原因是:如果想要删除这个目录,那么指向这个目录的硬链接的内容就不能同步了。这回破坏文件系统结构并且会造成数据的丢失。

  • 软链接

    image-20240826092716058

    如图所示:当创建一个软连接的时候,会创建一个新的目录项和i节点,而软链接文件的数据块所指向的内容是源文件的路径,所以当把源文件删除的时候,它数据块所引用的内容没有了,所以此时它找不到对应的文件或者目录。

示例–创建硬链接

link函数

#include <unistd.h>

int link(const char *path1, const char *path2);

//功能:创建一个指向现存文件链接(硬链接)
//参数1:源文件的路径
//参数2:目标文件的路径
//返回值:如果成功执行返回0,反之返回-1

unlink函数

#include <unistd.h>

int unlink(const char *path);

//功能:删除pathname指定的硬链接,并将由pathname所引用的文件链接计数减1
//参数:要删除的硬连接的路径
//返回值:成功执行返回0,反之返回-1
代码示例:使用link创建硬链接
#include "header.h"

int main(int argc, char **argv)
{
	if(argc < 3)
	{
		fprintf(stderr,"usage: %s [srcfile] [linkfile]\n",argv[0]);
		exit(EXIT_FAILURE);
	}

	int i;

	for(i=2;i<argc;i++)
	{
		if(link(argv[1],argv[i]) < 0)
		{
			perror("link error");
			continue;
		}
	}

	printf("link finished\n");

	return 0;
}

image-20240826110605377

经过编译执行后生成两个硬链接文件,而且它们的执行结果和源文件一样,并且硬连接数变为了3

代码示例:使用unlink删除硬链接
#include "header.h"

int main(int argc, char **argv)
{
	if(argc < 3)
	{
		fprintf(stderr,"usage: %s [srcfile] [linkfile]\n",argv[0]);
		exit(EXIT_FAILURE);
	}

	int i;

	for(i=1;i<argc;i++)
	{
		if(unlink(argv[i]) < 0)
		{
			perror("unlink error");
			continue;
		}
	}

	printf("unlink finished\n");

	return 0;
}

image-20240826111006914

通过编译执行,可以发现unlink函数可以删除硬链接文件

remove函数

#include <stdio.h>

int remove(const char *path);

//功能:解除对一个文件或者目录的连接(对与文件,remove的功能与unlink相同;对于目录,remove的功能与rmdir相同)
//参数:要解除的文件的路径
//返回值:成功返回0,出错返回-1

rename函数

#include <stdio.h>

int rename(const char *old, const char *new);

//功能:文件或者目录重命名
//参数1:旧的文件名字或者目录名
//参数2:新的文件名或者路径名
//返回值:成功返回0,出错返回-1
代码示例–使用remove解除对文件或者目录的连接
#include "header.h"

int main(int argc, char **argv)
{
	if(argc < 2)
	{
		fprintf(stderr,"usage: %s [srcfile] [linkfile]\n",argv[0]);
		exit(EXIT_FAILURE);
	}

	int i;

	for(i=1;i<argc;i++)
	{
		if(remove(argv[i]) < 0)
		{
			perror("remove error");
			continue;
		}
	}

	printf("remove finished\n");

	return 0;
}

image-20240826113023904

remove函数其实就是Linux中的指令rm,所以它的用法也比较熟悉了

代码示例–使用rename函数给文件重命名
#include "header.h"

int main(int argc, char **argv)
{
	if(argc < 3)
	{
		fprintf(stderr,"usage: %s [srcfile] [renamefile]\n",argv[0]);
		exit(EXIT_FAILURE);
	}

	int i;

	for(i=2;i<argc;i++)
	{
		if(rename(argv[1],argv[i]) < 0)
		{
			perror("rename error");
			continue;
		}
	}

	printf("rename finished\n");

	return 0;
}

image-20240826113422753

这个函数的用法也比较简单,就像Linux指令中的mv指令的重命名

示例–创建软链接

symlink函数

#include <unistd.h>

int symlink(const char *path1, const char *path2);

//功能:创建一个符号链接(软链接)
//参数1:源文件的路径
//参数2:要创建的那个文件的路径
//返回值:成功执行返回0,反之返回-1

readlink函数

#include <unistd.h>

ssize_t readlink(const char *restrict path, char *restrict buf,
           size_t bufsize);

//功能:打开该链接本身,并读取到该链接所引用的源文件名字
//参数1:链接文件的路径
//参数2:用来存放读取到的内容的缓存
//参数3:缓存的大小
//返回值:成功返回独到的字节数,出错返回-1
代码示例–使用symlinkreadlink函数创建软链接和查找源文件
#include "header.h"

int main(int argc, char **argv)
{
	if(argc < 3)
	{
		fprintf(stderr,"usage: %s [srcfile] [linkfile]\n",argv[0]);
		exit(EXIT_FAILURE);
	}
	
	int i;
	char buffer[4096];
	int fd;
	ssize_t nbytes;

	for(i=2;i<argc;i++)
	{
		if(symlink(argv[1],argv[i]) < 0)
		{
			perror("symlink error");
			exit(EXIT_FAILURE);
		}
	}
	printf("symlink finished\n");

	fd = open(argv[2],O_RDONLY);
	if(fd < 0)
	{
		perror("open file error");
		exit(EXIT_FAILURE);
	}

	memset(buffer,'\0',sizeof(buffer));

	//将符号链接文件里边的内容输出到屏幕上
	if((nbytes = read(fd, buffer, sizeof(buffer))) < 0)
	{
		perror("read error");
		exit(EXIT_FAILURE);
	}
	else
	{
		if(write(STDOUT_FILENO,buffer,nbytes) != nbytes)
		{
			perror("write error");
			exit(EXIT_FAILURE);
		}
	}
	
	memset(buffer,'\0',sizeof(buffer));
	if((nbytes = readlink(argv[2], buffer, sizeof(buffer))) < 0)
	{
		perror("readlink error");
		exit(EXIT_FAILURE);
	}
	else
	{
		fprintf(stdout,"readlink: \n%s\n",buffer);
	}

	return 0;
}

image-20240826120316025

通过编译执行可以看到成功创建了软链接文件,而且也能够通过软链接文件访问到源文件的内容,也能够获取符号链接引用的文件。通过ls -l指令验证也是一样的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2077145.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【链栈的实现】--------本质为不带头结点的 头插法建立起来的单链表

1.链栈的基本属性与特征&#xff1a; 链栈是运算受限的单链表&#xff0c;只能在链表头部进行操作 2.链栈的相关基础操作汇总 初始化操作&#xff1a;操作结果:构造一个空栈 S。 InitStack(LinkStack *s)判定S是否为空栈&#xff1a; 初始条件:栈S 已存在 操作结果:若栈S为…

【Linux】全面解析进程:优先级、环境变量与地址空间

文章目录 1. 进程概念1.1 什么叫做进程&#xff1f;1.2 进程和程序的区别 2. linux下的进程2.1 task_struct 包含哪些内容2.2 访问&#xff08;查看&#xff09;进程信息2.3 通过系统调用获取进程标示符2.4 通过系统调用创建进程2.5 进程状态2.6 如何查看进程状态&#xff08;指…

鸿蒙开发5.0【基于CameraKit,通过avrecorder进行录像】

1 场景描述 录像是相机应用的最重要功能之一&#xff0c;录像是循环帧的捕获。本文通过CameraKit自定义相机并通过avrecorder进行录像。 2 效果图 3 自定义相机录像流程图 4 方案描述 4.1 整体描述&#xff1a; 总体可分为:1、相机输入&#xff0c;2、同时输出预览流录像流…

【Python机器学习】NLP分词——利用分词器构建词汇表(三)——度量词袋之间的重合度

如果能够度量两个向量词袋之间的重合度&#xff0c;就可以很好地估计他们所用词的相似程度&#xff0c;而这也是它们语义上重合度的一个很好的估计。因此&#xff0c;下面用点积来估计一些新句子和原始的Jefferson句子之间的词袋向量重合度&#xff1a; import pandas as pdse…

win10配置安装apache服务

Welcome! - The Apache HTTP Server Project

redisson watchdog 原理

目录 1、使用2、加锁解析1、getLock2、tryLock2.1、当ttl为null时为加锁成功&#xff0c;返回true,否则继续往下执行&#xff0c;判断是否超过等待时间&#xff0c;当前时间减去获取锁前时间就是获取锁花费时间。2.2、tryAcquire(leaseTime, unit, threadId)2.3 、renewExpirat…

黑悟空!一区预定!原创首发!SLWCHOA-Transformer-LSTM混合改进策略的黑猩猩优化算法多变量时间序列预测

黑悟空&#xff01;一区预定&#xff01;原创首发&#xff01;SLWCHOA-Transformer-LSTM混合改进策略的黑猩猩优化算法多变量时间序列预测 目录 黑悟空&#xff01;一区预定&#xff01;原创首发&#xff01;SLWCHOA-Transformer-LSTM混合改进策略的黑猩猩优化算法多变量时间序…

帮助检测SQL注入漏洞的工具

目录 SQLMap与Burp Suite相比&#xff0c;哪个更适合进行大规模的SQL注入检测&#xff1f; OWASP ZAP在检测SQL注入时的优势体现在哪些方面&#xff1f; 对于SQL注入漏洞检测&#xff0c;Havij和acunetix有什么区别&#xff1f; 在检测SQL注入漏洞方面&#xff0c;有几款工具…

shell脚本-采集容器内自定义端口tcp连接数并通过http接口推送到Prometheus

目录 1、脚本编写 2、脚本说明 3、运行脚本 1、脚本编写 脚本监控服务器 5000 端口的 TCP 连接数。使用 netstat 工具获取连接数&#xff0c;并通过一个简单的 shell 服务器提供 /connect 接口。具体功能如下&#xff1a; vim prometheus_tcp_monitor.sh 编写脚本&#…

Docker 安装消息队列RabbitMQ

拉取镜像 docker pull rabbitmq拉取最新镜像 创建并运行 docker run -d --hostname my-rabbit --name rabbit-p 15672:15672 -p 5673:5672rabbitmq开启Web管理 进入容器 docker exec -it rabbitmq /bin/bash开启web管理 rabbitmq-plugins enable rabbitmq_managementhttp:…

一文通透DeepSeek-V2(改造Transformer的中文模型):从DeepSeek LLM到DeepSeek-V2的MLA与MoE

前言 成就本文有以下三个因素 24年5.17日&#xff0c;我在我司一课程「大模型与多模态论文100篇」里问道&#xff1a;大家希望我们还讲哪些论文 一学员朋友小栗说&#xff1a;幻方发布的deepseek-v224年5.24日&#xff0c;我司一课程「大模型项目开发线上营1」里的一学员朋友…

Typora + PicGo + SMMS 实现markdown格式文档图片上传

Typora PicGo SMMS 实现图片自动上传 1. Typora 软件安装2. PicGo 的安装2.1 下载 PicGo 3. 配置 SMMS 图床服务3.1 注册并登录 SMMS3.2 获取 API Token 4. 软件配置4.1 Typora 图床设置4.2 PicGo 配置 5. 使用 Typora 实现图片自动上传 1. Typora 软件安装 Typora中文版是一…

排序1

一、概述 直接插入排序 是稳定排序 二、插入排序 1&#xff09;直接插入排序 2&#xff09;折半插入排序 3)希尔排序 、 三、交换排序 1&#xff09;冒泡排序 2&#xff09;快速排序

three.js 着色器学习 聚集地

预览地址&#xff1a;https://z2586300277.github.io/three-cesium-examples 国内站点预览&#xff1a;http://threehub.cn github: https://github.com/z2586300277/three-cesium-examples

swift微调Qwen-7B大模型

环境说明&#xff1a; CUDA相关环境已搭建完成&#xff0c;不会装CUDA环境可参照我的其它文章&#xff1b; 显卡&#xff1a;4张3090 1、安装swift环境 #从源码安装 git clone https://github.com/modelscope/swift.git cd swift pip install -e .[llm] pip install -e .[e…

文件读写与缓存机制

文件读写与缓存机制 写文件&#xff1a; 1&#xff1a;stdio函数库 fopen/fwrite/fflush/fclose File* fp2: POSIX系统级别函数 open/write/close fd3&#xff1a;Windows系统级别函数 CreateFile/WriteFile/CloseHandle**同步数据到磁盘&#xff1a;**FlushFileBuffers、f…

永磁同步电机高性能控制算法(13)后续篇—— 基于高阶扩张状态观测器(ESO)的无模型预测控制(MFPC)

1.前言 前文已经介绍过了高阶ESO相对于传统ESO的优势。 https://zhuanlan.zhihu.com/p/703039702https://zhuanlan.zhihu.com/p/703039702 但是当时搭的ESO有点问题。把公式修正之后&#xff0c;发现前文用的改进四阶ESO无法使用。 今天来解释一下为什么改进4阶ESO无法使用…

SystemTap(stap)架构和原理介绍,以及脚本编写举例

1 SystemTap简介 SystemTap是一个诊断Linux系统性能或功能问题的开源工具。它允许开发人员和系统管理员深入研究内核甚至用户空间应用程序的行为&#xff0c;以便发现错误状态、性能问题&#xff0c;或者仅仅为了解系统是如何工作的。它使得对运行时的Linux系统进行诊断调式变…

递归算法及应用

一.简介 1.介绍 递归&#xff08;Recursion&#xff09;在计算机科学中是指一种通过重复将问题分解为同类的子问题而解决问题的方法&#xff0c;其核心思想是分治策略。 在日常开发中&#xff0c;我们使用循环语句远远大于递归&#xff0c;但这不能说明递归就没有用武之地&am…

服务器(百度云)部署项目(jar包)

java项目打包成jar包&#xff1a;clean------compile------install jar包上传到服务器上 和jar包相同的文件里&#xff0c;创建Dockerfile文件。 Dockerfile文件的内容informationerasure是jar包名&#xff0c;这里可根据自己定义的名字进行更换。 Dockerfile文件内容&#x…