Linux文件IO(五)-三种进程退出方法及空洞文件

server/2024/9/23 8:12:51/

1.三种进程退出方法

return

当程序在执行某个函数出错的时候,如果此函数执行失败会导致后面的步骤不能在进行下去时,应该在出错时终止程序运行,不应该让程序继续运行下去,那么如何退出程序、终止程序运行呢?有过编程经验的读者都知道使用 return,一般原则程序执行正常退出 return 0,而执行函数出错退出 return -1,前面我们所编写的示例代码也是如此。

在 Linux 系统下,进程(程序)退出可以分为正常退出和异常退出,注意这里说的异常并不是执行函数出现了错误这种情况,异常往往更多的是一种不可预料的系统异常,可能是执行了某个函数时发生的、也有可能是收到了某种信号等,这里我们只讨论正常退出的情况。

在 Linux 系统下,进程正常退出除了可以使用 return 之外,还可以使用 exit()、_exit()以及_Exit(),下面我们分别介绍。

_exit()

main 函数中使用 return 后返回,return 执行后把控制权交给调用函数,结束该进程。调用_exit()函数会清除其使用的内存空间,并销毁其在内核中的各种数据结构,关闭进程的所有文件描述符,并结束进程、将控制权交给操作系统。_exit()函数原型如下所示:

#include <unistd.h>

void _exit(int status);

调用函数需要传入 status 状态标志,0 表示正常结束、若为其它值则表示程序执行过程中检测到有错误

发生。使用示例如下:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>int main(void)
{int fd;/* 打开文件 */fd = open("./test_file", O_RDONLY);if (-1 == fd) {perror("open error");_exit(-1);}close(fd);_exit(0);
}

 用法很简单,大家可以自行测试!

Exit()函数

原型如下所示:

#include <stdlib.h>
void exit(int status);

_exit()和_Exit()两者等价,用法作用是一样的,这里就不再讲了,需要注意的是这 2 个函数都是系统调用。

exit()函数

exit()函数_exit()函数都是用来终止进程的,exit()是一个标准 C 库函数,而_exit()和_Exit()是系统调用。

执行 exit()会执行一些清理工作,最后调用_exit()函数。exit()函数原型如下:

#include <stdlib.h>
void exit(int status);

 

该函数是一个标准 C 库函数,使用该函数需要包含头文件<stdlib.h>,该函数的用法和_exit()/_Exit()是一样的,这里就不再多说了。

本小节就给大家介绍了 3 中终止进程的方法:

  • main 函数中运行 return;
  • 调用 Linux 系统调用_exit()或_Exit();
  • 调用 C 标准库函数 exit()。

2.空洞文件

2.1概念

 什么是空洞文件(hole file)?使用 lseek 可以修改文件的当前读写位置偏移量,此函数不但可以改变位置偏移量,并且还允许文件偏移量超出文件长度,这是什么意思呢?譬如有一个 test_file,该文件的大小是 4K(也就是 4096 个字节),如果通过 lseek 系统调用将该文件的读写偏移量移动到偏移文件头部 6000 个字节处,大家想一想会怎样?如果笔者没有提前告诉大家,大家觉得不能这样操作,但事实上 lseek 函数确实可以这样操作。

接下来使用 write()函数对文件进行写入操作,也就是说此时将是从偏移文件头部 6000 个字节处开始写入数据,也就意味着 4096~6000 字节之间出现了一个空洞,因为这部分空间并没有写入任何数据,所以形成了空洞,这部分区域就被称为文件空洞,那么相应的该文件也被称为空洞文件。

文件空洞部分实际上并不会占用任何物理空间,直到在某个时刻对空洞部分进行写入数据时才会为它分配对应的空间,但是空洞文件形成时,逻辑上该文件的大小是包含了空洞部分的大小的,这点需要注意。

那说了这么多,空洞文件有什么用呢?空洞文件对多线程共同操作文件是及其有用的,有时候我们创建一个很大的文件,如果单个线程从头开始依次构建该文件需要很长的时间,有一种思路就是将文件分为多段,然后使用多线程来操作,每个线程负责其中一段数据的写入;这个有点像我们现实生活当中施工队修路的感觉,比如说修建一条高速公路,单个施工队修筑会很慢,这个时候可以安排多个施工队,每一个施工队负责修建其中一段,最后将他们连接起来。

来看一下实际中空洞文件的两个应用场景:

  • 在使用迅雷下载文件时,还未下载完成,就发现该文件已经占据了全部文件大小的空间,这也是空洞文件;下载时如果没有空洞文件,多线程下载时文件就只能从一个地方写入,这就不能发挥多线程的作用了;如果有了空洞文件,可以从不同的地址同时写入,就达到了多线程的优势;
  • 在创建虚拟机时,你给虚拟机分配了 100G 的磁盘空间,但其实系统安装完成之后,开始也不过只用了 3、4G 的磁盘空间,如果一开始就把 100G 分配出去,资源是很大的浪费。

关于空洞文件,这里就介绍这么多,上述描述当中多次提到了线程这个概念,关于线程这是后面的内容,这里先不给大家讲。

2.2实验测试

这里我们进行相关的测试,新建一个文件把它做成空洞文件,示例代码如下所示:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{int fd;int ret;char buffer[1024];int i;/* 打开文件 */fd = open("./hole_file", O_WRONLY | O_CREAT | O_EXCL,	 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);if (-1 == fd) {perror("open error");exit(-1);}/* 将文件读写位置移动到偏移文件头 4096 个字节(4K)处 */ret = lseek(fd, 4096, SEEK_SET);if (-1 == ret) {perror("lseek error");goto err;}/* 初始化 buffer 为 0xFF */memset(buffer, 0xFF, sizeof(buffer));/* 循环写入 4 次,每次写入 1K */for (i = 0; i < 4; i++) {ret = write(fd, buffer, sizeof(buffer));if (-1 == ret) {perror("write error");goto err;}}ret = 0;
err:/* 关闭文件 */close(fd);exit(ret);
}

示例代码中,我们使用 open 函数新建了一个文件 hole_file,在 Linux 系统中,新建文件大小是 0,也就是没有任何数据写入,此时使用lseek函数将读写偏移量移动到4K字节处,再使用write函数写入数据0xFF,每次写入 1K,一共写入 4 次,也就是写入了 4K 数据,也就意味着该文件前 4K 是文件空洞部分,而后 4K数据才是真正写入的数据。

接下来进行编译测试,首先确保当前文件目录下不存在 hole_file 文件,测试结果如下

使用 ls 命令查看到空洞文件的大小是 8K,使用 ls 命令查看到的大小是文件的逻辑大小,自然是包括了空洞部分大小和真实数据部分大小;当使用 du 命令查看空洞文件时,其大小显示为 4K,du 命令查看到的大小是文件实际占用存储块的大小。


http://www.ppmy.cn/server/120701.html

相关文章

python新手的五个练习题

代码 # 1. 定义一个变量my_Number,将其设置为你的学号&#xff0c;然后输出到终端。 my_Number "20240001" # 假设你的学号是20240001 print("学号:", my_Number) # 2. 计算并输出到终端:两个数(例如3和5)的和、差、乘积和商。 num1 3 num2 5 print(&…

2024年最新前端工程师 TypeScript 基础知识点详细教程(更新中)

1. TypeScript 概述 TypeScript 是由微软开发的、基于 JavaScript 的一种强类型编程语言。它是在 JavaScript 的基础上添加了静态类型检查、面向对象编程等功能的超集&#xff0c;最终会被编译为纯 JavaScript 代码。由于其扩展了 JavaScript 的功能&#xff0c;TypeScript 特…

基于协同过滤算法+PHP的新闻推荐系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于协同过滤算法PHPMySQL的新…

html 几行的空间分成3个区域

1.代码 <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewport" content"widthdevice-width, initial-scale1.0"> <title>三个区域示例</title> …

一个基于 Tauri、Vite 5、Vue 3 和 TypeScript 构建的即时通讯系统,牛啊牛啊!(附源码)

这段时间正在学习桌面端开发&#xff0c;目前了解了Electron和Tauri,在搜索教程的时候发现了一位大佬用Tauri开发了个即时通讯的软件&#xff0c;并且技术栈用的也是VUE3和TypeScript&#xff0c;所以今天就给大家分享一下这个项目——HuLa HuLa HuLa 是一个基于 Tauri、Vite …

基于python+django+vue的图书管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于pythondjangovueMySQL的图…

【二等奖论文】2024年华为杯研究生数学建模F题成品论文(后续会更新)

您的点赞收藏是我继续更新的最大动力! 一定要点击如下的卡片&#xff0c;那是获取资料的入口&#xff01; 点击链接获取【2024华为杯研赛资料汇总】&#xff1a; https://qm.qq.com/q/alQjz21npu https://qm.qq.com/q/alQjz21npu X射线脉冲星光子到达时间建模 摘要 脉冲星是…

vim入门操作命令

目录 常用命令移动光标删除字符撤销和重做复制和粘贴搜索和替换保存和退出分屏 参考资料 常用命令 vim 工具本身提供了许多常用快捷键&#xff0c;以下是一些常用的命令&#xff1a; 移动光标 h&#xff1a;向左移动一个字符j&#xff1a;向下移动一行k&#xff1a;向上移动…