flock使用文件描述符和使用文件的区别

2023-11-22 14:20
文章标签 使用 区别 flock 描述符

本文主要是介绍flock使用文件描述符和使用文件的区别,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

使用带文件描述符的方法可以让你更好地控制和管理 flock 以及与锁相关的行为。当你在子进程或子shell中使用文件描述符时,文件锁可以跨越这些范围,并且只有在你显式地释放它时,锁才会被释放。

让我们看一个例子,更好地理解这一点。

假设我们有一个脚本 script_a.sh:

#!/bin/shlock_file="/tmp/script_b.lock"touch "$lock_file"# 使用带文件描述符的方法(flock -n 9 || { echo "Script B is locked, could not acquire lock."; exit 1; }# 在子进程中执行脚本b( ./script_b.sh ) &) 9>"$lock_file"

在这段代码中,主 shell 脚本使用文件描述符 9 来创建并获取锁。当主脚本退出时,由于 script_b.sh 在子进程运行(使用 & 符号),script_b.sh 可以继承父进程(即主 shell 脚本)的文件描述符。

关键在于,script_b.sh 继承了文件描述符 9,而该描述符具有在退出时继续保持文件锁的特性。这意味着,即使主脚本已经退出,script_b.sh 仍然可以继续持有文件锁,直至其运行结束。

这里的一个重要概念是:锁是与文件描述符绑定的,而文件描述符可以在进程之间传递(例如从父进程传递给子进程)。因此,在这个例子中,锁的生命周期取决于文件描述符 9 何时被关闭。而由于 script_b.sh 继承了该文件描述符并一直保持打开状态,因此它可以在主进程退出后继续持有文件锁。

flock 命令会将锁状态与文件描述符状态联系起来。因此,在文件描述符关闭时,操作系统也会自动清理与该描述符相关的状态,从而释放文件锁。

这种设计有助于防止资源泄漏,确保文件锁在描述符关闭、进程退出或异常终止时被释放。当文件描述符关闭时,操作系统知道不再有进程可以访问该文件或其他资源。因此,释放与文件描述符关联的文件锁是一种自动清理资源的机制,用于确保锁不会因为进程退出或崩溃而永久保持。

相反,如果我们不使用文件描述符,脚本将如下所示:

#!/bin/shlock_file="/tmp/script_b.lock"touch "$lock_file"# 不使用文件描述符的方法if flock -n "$lock_file" -c "true"; then# 在子进程中执行脚本b( ./script_b.sh ) &elseecho "Script B is locked, could not acquire lock."fi

在这种情况下,flock 使用 -c 参数来指定一个命令作为子进程执行。flock 会在获得锁之后执行这个命令,并在该命令运行完成之后自动释放锁。

这行代码将 flock 与文件名一起使用。当使用 -c 参数时,flock 会创建一个临时文件描述符,用于在内部锁定文件。这个临时文件描述符对用户是不可见的。

锁的状态如下:

  1. 执行 flock 时,创建一个临时文件描述符,锁定对应的文件。
  2. flock 执行子进程(这里是 true),子进程运行期间锁保持。
  3. 子进程执行完成后,flock 释放锁。
  4. 整个过程中,文件锁对于脚本来说是不可见和不可访问的,因为文件描述符是在 flock 内部创建的。

这种锁的状态类似于使用文件描述符的情况,但是更封装且适用于单个命令的执行。当在脚本中有多个命令需要在获得锁后顺序执行时,这种方法可能不太适用。在这种情况下,使用文件描述符将更合适,因为它允许您在脚本中自由地写入多个命令,而无需将它们包装在 -c 参数中。

所以,使用带文件描述符的方法可以让你更好地在子进程或子shell中保持和管理文件锁。

---------------------------------------------------------------------------------------------------------------------------------

在 UNIX 和 Linux 系统中,文件锁通常是与文件描述符绑定的。文件描述符是操作系统分配的唯一标识符,代表打开的文件、设备、网络套接字等资源。文件锁实际上是操作系统内核提供的一种同步和协调机制,管理对共享文件或资源的访问。文件锁依赖于文件描述符,以便操作系统追踪哪个进程手中持有哪个锁。

当一个进程想要锁定一个文件时,它需要首先打开该文件并获得一个文件描述符。然后,这个进程可以使用系统调用(例如 fcntl 或 flock)操作文件描述符,请求操作系统将锁应用于该文件。操作系统会根据文件描述符的状态,来决定是否授予文件锁。

当文件描述符关闭时,与它关联的文件锁会被自动释放。这是因为文件锁的生命周期与文件描述符有关。这种设计确保了文件锁在进程退出、崩溃或正常关闭文件描述符时自动释放,从而防止了资源泄露和死锁。

在某些情况下,如使用 flock 命令时,您可以看到文件锁与文件名一起使用,而不是与文件描述符一起使用。然而,在这些情况下,flock 内部依然会创建和管理临时的文件描述符,以确保文件锁与文件描述符之间的关联。所以,最终文件锁还是与文件描述符绑定的。

总之,文件锁是与文件描述符紧密相关的,并通过操作系统内核进行管理。使用文件描述符允许操作系统有效地跟踪和控制对共享资源的访问。

父进程和子进程共享文件描述符的情况下,对文件锁的操作实际上是共享的,而不是独立的。这是因为文件锁是与文件描述符关联的,而文件描述符在父子进程之间共享。因此,如果子进程解锁文件描述符,父进程的锁定状态也会受到影响。

这是一个示例,说明当子进程解锁文件描述符时,父进程的锁定状态会受到影响:

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>int main() {int fd = open("testfile.txt", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);if (fd == -1) {perror("open failed");exit(1);}struct flock lock;lock.l_type = F_WRLCK;lock.l_whence = SEEK_SET;lock.l_start = 0;lock.l_len = 0;if (fcntl(fd, F_SETLK, &lock) == -1) {perror("fcntl lock failed");exit(1);}printf("Parent process (%d) locked the file\n", getpid());pid_t pid = fork();if (pid < 0) {perror("fork failed");exit(1);} else if (pid == 0) {// 子进程lock.l_type = F_UNLCK;if (fcntl(fd, F_SETLK, &lock) == -1) {perror("Child process fcntl unlock failed");}printf("Child process (%d) released the file lock\n", getpid());} else {// 父进程sleep(3);lock.l_type = F_WRLCK; // 尝试重新对文件上锁if (fcntl(fd, F_SETLK, &lock) == -1) {perror("Parent process fcntl lock failed");} else {printf("Parent process (%d) locked the file again\n", getpid());}lock.l_type = F_UNLCK;fcntl(fd, F_SETLK, &lock);close(fd);}return 0;
}

运行结果:

父进程锁定文件描述符 fd,然后创建子进程。子进程解锁文件描述符,父进程在3秒后尝试重新锁定。这时,由于子进程已经解锁,父进程能够成功重新锁定文件。这表明子进程解锁文件描述符时,确实影响了父进程的锁定状态。

这篇关于flock使用文件描述符和使用文件的区别的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/410742

相关文章

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

pdfmake生成pdf的使用

实际项目中有时会有根据填写的表单数据或者其他格式的数据,将数据自动填充到pdf文件中根据固定模板生成pdf文件的需求 文章目录 利用pdfmake生成pdf文件1.下载安装pdfmake第三方包2.封装生成pdf文件的共用配置3.生成pdf文件的文件模板内容4.调用方法生成pdf 利用pdfmake生成pdf文件 1.下载安装pdfmake第三方包 npm i pdfma

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

git使用的说明总结

Git使用说明 下载安装(下载地址) macOS: Git - Downloading macOS Windows: Git - Downloading Windows Linux/Unix: Git (git-scm.com) 创建新仓库 本地创建新仓库:创建新文件夹,进入文件夹目录,执行指令 git init ,用以创建新的git 克隆仓库 执行指令用以创建一个本地仓库的

【北交大信息所AI-Max2】使用方法

BJTU信息所集群AI_MAX2使用方法 使用的前提是预约到相应的算力卡,拥有登录权限的账号密码,一般为导师组共用一个。 有浏览器、ssh工具就可以。 1.新建集群Terminal 浏览器登陆10.126.62.75 (如果是1集群把75改成66) 交互式开发 执行器选Terminal 密码随便设一个(需记住) 工作空间:私有数据、全部文件 加速器选GeForce_RTX_2080_Ti

native和static native区别

本文基于Hello JNI  如有疑惑,请看之前几篇文章。 native 与 static native java中 public native String helloJni();public native static String helloJniStatic();1212 JNI中 JNIEXPORT jstring JNICALL Java_com_test_g