【Linux C | 文件I/O】fcntl函数详解 | 设置描述符非阻塞、文件(记录)锁

😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
🤣本文内容🤣:🍭介绍🍭
😎金句分享😎:🍭你不能选择最好的,但最好的会来选择你——泰戈尔🍭

本文未经允许,不得转发!!!

目录

  • 🎄一、fcntl 函数介绍
  • 🎄二、复制文件描述符(F_DUPFD、F_DUPFD_CLOEXEC)
    • ✨2.1 F_DUPFD(int)
    • ✨2.2 F_DUPFD_CLOEXEC(int)
  • 🎄三、获取/设置文件描述符标志(F_GETFD、F_SETFD)
  • 🎄四、获取/设置文件状态标志(F_GETFL、F_SETFL)
  • 🎄五、获取/设置记录锁(F_GETLK、F_SETLK、F_SETLKW)
  • 🎄六、总结


在这里插入图片描述

🎄一、fcntl 函数介绍

函数原型:

#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );
// arg表示可变参数,由cmd决定

fcntl()对打开的文件描述符fd执行下面描述的操作之一。操作由cmd决定。

fcntl()的第三个参数是可选。是否需要此参数由cmd决定。所需的参数类型在每个cmd名称后面的括号中指示(在大多数情况下,所需的类型是int,我们使用名称arg来标识参数),如果不需要参数,则指定void。

以下某些操作仅在特定的Linux内核版本之后才受支持。检查主机内核是否支持特定操作的首选方法是使用所需的cmd值调用fcntl(),然后使用EINVAL测试调用是否失败,这表明内核无法识别该值。

本文主要介绍下面4个功能:

  • 1、复制文件描述符(F_DUPFD、F_DUPFD_CLOEXEC);
  • 2、获取/设置文件描述符标志(F_GETFD、F_SETFD);
  • 3、获取/设置文件状态标志(F_GETFL、F_SETFL);
  • 4、获取/设置记录锁(F_GETLK、F_SETLK、F_SETLKW);

在这里插入图片描述

🎄二、复制文件描述符(F_DUPFD、F_DUPFD_CLOEXEC)

✨2.1 F_DUPFD(int)

F_DUPFD(int) 表示使用 F_DUPFD 作为cmd时,第三个参数需要传入int型数据。

cmd为F_DUPFD表示复制文件描述符fd。调用成功会返回新的描述符。新描述符使用大于或等于arg参数的编号最低的可用文件描述符复制文件描述符fd。新描述符与f似共享同一文件表项。但是,新描述符有它自己的一套文件描述符标志,其FD_CLOEXEC文件描述符标志被清除〈这表示该描述符在 exec 时仍保持打开状态)。

// fcntl_F_DUPFD.c
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
int main()
{
	int fd = open("./fcntl_F_DUPFD", O_RDWR | O_CREAT | O_TRUNC, 0775);
	int fcntlFd = fcntl(fd, F_DUPFD, 0); // 指定从 0 开始分配最小的可用描述符作为新描述符
	int dupFd = dup(fd); // 等效于 fcntl(fd, F_DUPFD, 0);
	
	close(fd);
	close(fcntlFd);
	close(dupFd);
	return 0;
}

✨2.2 F_DUPFD_CLOEXEC(int)

F_DUPFD_CLOEXEC(int) 表示使用 F_DUPFD_CLOEXEC 作为cmd时,第三个参数需要传入int型数据。

cmd为F_DUPFD_CLOEXEC的功能与F_DUPFD类似,区别在于F_DUPFD_CLOEXEC在复制的同时会设置文件描述符标志FD_CLOEXEC,表示在执行exec系列函数后,该描述符会关闭。

看例子:F_GETFDdup函数都会清除新描述符的FD_CLOEXEC标志,F_DUPFD_CLOEXEC会复制并设置FD_CLOEXEC标志。

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
int main()
{
	int fd = open("./fcntl_F_DUPFD_CLOEXEC", O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0775);
	int fcntlFd = fcntl(fd, F_DUPFD, 0);
	int fcntlCloFd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
	int dupFd = dup(fd);
	
	int fdFlag = fcntl(fd, F_GETFD, 0);
	int fcntlFdFlag = fcntl(fcntlFd, F_GETFD, 0);
	int fcntlCloFdFlag = fcntl(fcntlCloFd, F_GETFD, 0);
	int dupFdFlag = fcntl(dupFd, F_GETFD, 0);
	
	// 结果是:fdFlag=1, fcntlFdFlag=0, fcntlCloFdFlag=1, dupFdFlag=0
	printf("fdFlag=%d, fcntlFdFlag=%d, fcntlCloFdFlag=%d, dupFdFlag=%d\n",
		fdFlag,fcntlFdFlag,fcntlCloFdFlag,dupFdFlag);
	
	close(fd);
	close(fcntlFd);
	close(fcntlCloFd);
	close(dupFd);
	return 0;
}

运行结果:
在这里插入图片描述

在这里插入图片描述

🎄三、获取/设置文件描述符标志(F_GETFD、F_SETFD)

当前只定义了一个文件描述符标志FD_CLOEXEC。用来表示该描述符在执行完fork+exec系列函数创建子进程时会自动关闭,以防止它们被传递给子进程。为什么要这样做呢?

因为当一个进程调用exec系列函数(比如execve)来创建子进程时,所有打开的文件描述符都会被传递给子进程。如果文件描述符没有设置FD_CLOEXEC标志,这些文件将保持打开状态并继续对子进程可见。这可能导致潜在的安全风险或者意外行为。

F_GETFD(void) :表示使用 F_GETFD 作为cmd时,不需要传入第三个参数。
功能:获取文件描述符标志。
返回值:

  • 成功返回文件描述符标志
  • 失败返回 -1.

F_SETFD(int):表示使用 F_SETFD 作为cmd时,传入第三个参数是int型的。
功能:设置文件描述符标志,第三个参数传入新的标志值。
返回值:

  • 成功返回 0
  • 失败返回 -1.

文件描述符的FD_CLOEXEC标志可以通过三个方法得到:

  • 1、调用open函数是,指定 O_CLOEXEC
  • 2、通过fcntl函数使用F_DUPFD_CLOEXEC复制文件描述符,新的描述符就是FD_CLOEXEC
  • 3、通过fcntl函数使用F_SETFD直接设置FD_CLOEXEC

看例子:

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
int main()
{
	int fd = open("./fcntl_F_GETFD", O_RDWR | O_CREAT | O_TRUNC, 0775);
	int fdCloExec = open("./fcntl_F_GETFD2", O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0775);
	int fdCloExecDup = fcntl(fd, F_DUPFD_CLOEXEC, 0);
	int fdSetFd = dup(fd);
	fcntl(fdSetFd, F_SETFD, FD_CLOEXEC);
	
	int flagFd = fcntl(fd, F_GETFD);
	int flagFdCloExec = fcntl(fdCloExec, F_GETFD);
	int flagFdCloExecDup = fcntl(fdCloExecDup, F_GETFD);
	int flagFdSetFd = fcntl(fdSetFd, F_GETFD);
	// 打印结果:flagFd=0, flagFdCloExec=1, flagFdCloExecDup=1 flagFdSetFd=1
	printf("flagFd=%d, flagFdCloExec=%d, flagFdCloExecDup=%d flagFdSetFd=%d\n", 
		flagFd,flagFdCloExec,flagFdCloExecDup,flagFdSetFd);

	close(fd);
	close(fdCloExec);
	close(fdCloExecDup);
	close(fdSetFd);
	return 0;
}

在这里插入图片描述

🎄四、获取/设置文件状态标志(F_GETFL、F_SETFL)

文件状态标志如下表:

文件状态标志说明十六进制值
O_RDONLY只读打开0x0
O_WRONLY只写打开0x1
O_RDWR读、写打开0x2
O_APPEND追加写0x400
O_NONBLOCK非阻塞模式0x800
O_SYNC等待写完成(数据和属性)0x
O_DSYNC等待写完成(仅数据)
O_RSYNC同步读和写
O_FSYNC等待写完成
O_ASYNC异步IO0x2000

F_GETFL(void) :表示使用 F_GETFL 作为cmd时,不需要传入第三个参数。
功能:获取文件状态标志。
返回值:

  • 成功返回文件状态标志
  • 失败返回 -1.

访问方式标志:O_RDONLY 、O_WRONLY、O_RDWR。这3个值是互斥的,因此首先必须用屏蔽O_ACCMODE取得访问方式位,然后将结果与这3个值中的每一个相比较。

F_SETFL(int):表示使用 F_SETFL 作为cmd时,传入第三个参数是int型的。
功能:设置文件状态标志,第三个参数传入新的文件状态标志值。
返回值:

  • 成功返回 0
  • 失败返回 -1.

在Linux上,只能设置这5个文件状态标志:O_APPEND、 O_ASYNC、 O_DIRECT、 O_NOATIME、O_NONBLOCK,其中最常用的是将文件描述符设置成非阻塞(O_NONBLOCK),特别是在网络编程中很常见。

看例子,设置文件状态标志在日常使用中,就用来设置非阻塞,其他的可以先不关注。

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
int main()
{
	int fd = open("./fcntl_F_GETFL", O_RDWR | O_CREAT | O_TRUNC | O_NONBLOCK, 0775);
	int flag = fcntl(fd, F_GETFL);
	if(flag<0)
		return ;
	
	printf("flag=%x, O_ACCMODE=%x [%x %x %x] [%x %x %x %x %x %x %x][%x %x]\n", 
		flag & O_ACCMODE,O_ACCMODE,O_RDONLY,O_WRONLY,O_RDWR,O_APPEND,O_NONBLOCK,O_ASYNC,O_DSYNC,O_RSYNC,O_FSYNC,O_SYNC,__O_DIRECT,__O_NOATIME);

	fcntl(fd, F_SETFL, flag | O_NONBLOCK);
	close(fd);
	return 0;
}

在这里插入图片描述

🎄五、获取/设置记录锁(F_GETLK、F_SETLK、F_SETLKW)

Linux实现了POSIX标准化的传统(“进程相关”)UNIX记录锁。
记录锁(record locking)的功能是:当一个进程正在读或修改文件的某个部分时,它可以阻止其他进程修改同一文件区。对于UNIX系统而言,“记录”这个词是一种误用,因为UNIX系统内核根本没有使用文件记录这种概念。更适合的术语可能是字节范围锁(byte-rangelocking),因为它锁定的只是文件中的一个区域(也可能是整个文件)。

F_SETLK、F_SETLKW和F_GETLK用于获取、释放和测试记录锁(也称为字节范围、文件段或文件区域锁)的存在。使用记录锁时,第三个参数是指向struct flock结构的指针。

struct flock
{
	...
	short l_type;//锁的类型:F_RDLCK(读锁)、F_WRLCK(写锁)、F_UNLCK(解锁)
	short l_whence;//偏移的起点:SEEK_SET、SEEK_CUR、SEEK_END 
	off_t l_start; //锁区偏移,从l_whence
	off_t l_len;  //锁区长度(字节)
	pid_t l_pid; //阻塞我们加锁的进程ID
	...
}

F_SETLK(struct flock *):表示使用 F_SETLK 作为cmd时,传入第三个参数是struct flock *型的。
在锁的l_where、l_start和l_len字段指定的字节上设置锁(当l_type为F_RDLCK或F_WRLCK时)或释放锁(当l_type为F_UNLOCK时)。如果另一个进程持有冲突锁,则此调用返回-1并将errno设置为EACCES或EAGAIN。(本例中返回的错误因实现而异,因此POSIX需要一个可移植的应用程序来检查这两个错误。)

F_SETLKW(struct flock *):表示使用 F_SETLKW 作为cmd时,传入第三个参数是struct flock *型的。
类似于F_SETLK(命名中的W表示等待(wait)),但如果文件上持有冲突的锁,则等待该锁释放。如果在等待时捕获到信号,则调用将中断,并且(在信号处理程序返回后)立即返回(返回值为-1,errno设置为EINTR;)。

F_GETLK(struct flock *):表示使用 F_GETLK 作为cmd时,传入第三个参数是struct flock *型的。
判断由struct flock *(第三个参数)所描述的锁是否会被另外一把锁所排斥(阻塞)。如果存在一把锁,它阻止创建由第三个参数(struct flock *)所描述的锁,则把该现存锁的信息写到第三个参数(struct flock *)指向的结构中。如果不存在这种情况,则除了将l_type设置为F_UNLCK之外,第三个参数所指向结构中的其他信息保持不变。

读锁(F_RDLCK):允许其他进程读该文件,但不允许其他进程写该文件;
写锁(F_WRLCK):不允许其他进程读、写该文件;
看例子,下面两个.c保存后编译成2个执行文件,分别在两个窗口允许:
fcntl_lock1.c:

// 进程1,加了读锁,允许其他进程读该文件,但不允许其他进程写该文件;
// gcc fcntl_lock1.c -o fcntl_lock1
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

int makeFlock(struct flock* pLock,int type, int whence, off_t start, off_t len)
{
	if (pLock == NULL)
		return -1;
	pLock->l_type=type;
	pLock->l_whence=whence;
	pLock->l_start=start;
	pLock->l_len=len;
	pLock->l_pid = -1;
	return 0;
}

int main()
{
	int fd = open("./fcntl_lock", O_RDWR | O_CREAT | O_TRUNC, 0664);
	
	int i=0;
	for(i=0; i<30; i++)
	{
		char num = i+1;
		write(fd, &num, 1);
	}
	
	// 加读锁
	struct flock rlock;
	makeFlock(&rlock, F_RDLCK, SEEK_SET, 11, 10); // 读锁,锁第11~20个字节
	int ret = fcntl(fd, F_SETLK, &rlock);
	if(ret<0)
	{
		return -1;
	}
	
	// 读取数据
	printf("reading 11~20 byte:\n");
	lseek(fd, 10, SEEK_SET);
	for(i=0; i<10; i++)
	{
		char num;
		read(fd, &num, 1);
		printf("reading byte: %d\n",num);
		sleep(1);
	}
	sleep(30);
	
	// 释放锁
	rlock.l_type = F_UNLCK;
    ret = fcntl(fd, F_SETLK, &rlock);
    if(ret == -1)
    {
        perror("rlock release failed");
        return -1;
    }
    sleep(30);
    close(fd);
	return 0;
}

fcntl_lock2.c

// 进程2,加了读锁,允许其他进程读该文件,但不允许其他进程写该文件;
// gcc fcntl_lock2.c -o fcntl_lock2
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

int makeFlock(struct flock* pLock,int type, int whence, off_t start, off_t len)
{
	if (pLock == NULL)
		return -1;
	pLock->l_type=type;
	pLock->l_whence=whence;
	pLock->l_start=start;
	pLock->l_len=len;
	pLock->l_pid = -1;
	return 0;
}

int main()
{
	int i=0;
	int fd = open("./fcntl_lock", O_RDWR);	
	// 加读锁,与进程1重叠,仍然可以读
	struct flock rlock;
	makeFlock(&rlock, F_RDLCK, SEEK_SET, 6, 10); // 读锁,锁第6~15个字节,与进程1的11~20有重叠
	int ret = fcntl(fd, F_SETLK, &rlock);
	if(ret == -1)
	{
		return -1;
	}
	// 读取数据
	printf("reading 6~15 byte:\n");
	lseek(fd, 5, SEEK_SET);
	for(i=0; i<10; i++)
	{
		char num;
		read(fd, &num, 1);
		printf("reading byte: %d\n",num);
	}
	// 释放读锁
	rlock.l_type = F_UNLCK;
    ret = fcntl(fd, F_SETLK, &rlock);
    if(ret == -1)
    {
        perror("rlock release failed");
        return -1;
    }	
	// 加写锁,此时会失败,因为进程1加了读锁没释放
	struct flock wlock;
	makeFlock(&wlock, F_WRLCK, SEEK_SET, 6, 10); // 写锁,锁第6~15个字节,与进程1的11~20有重叠
    ret = fcntl(fd, F_SETLK, &wlock);
    if(ret == -1)
    {
        perror("rlock release failed");
    }
    sleep(30);
    close(fd);
	return 0;
}

运行结果如下:
在这里插入图片描述

在这里插入图片描述

🎄六、总结

本文详细介绍fcntl函数,并举例介绍常用功能如:设置非阻塞文件描述符、文件锁等

在这里插入图片描述
如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁

参考资料:
《Unix环境高级编程》
Linux系统调用–fcntl函数详解:https://blog.csdn.net/bailyzheng/article/details/7463775

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

什么情况下不应该使用 LockWindowUpdate ?

在之前的文章中&#xff0c;我们将了解了 LockWindowUpdate 应该在什么场景下使用&#xff0c;也就是拖动的场景。 今天&#xff0c;我们来看看 LockWindowUpdate 被误用的一些场景。 人们看到 LockWindowUpdate 的“您锁定的窗口将无法重新绘制自身”行为&#xff0c;并将其…

ToDesk Linux 客户端安装(欧拉系统)

下载链接 下载链接 https://newdl.todesk.com/linux/todesk-v4.3.1.0-x86_64.rpm &#xff08;使用4.3.1.0覆盖安装后&#xff0c;临时密码将会变更&#xff09; 安装命令&#xff1a; sudo rpm -Uvh todesk-v4.3.1.0-x86_64.rpm启动命令&#xff1a; todesk启动命令只能在桌…

Spring通信传参的方法

Spring通信传参的方法 目录概述需求&#xff1a; 设计思路实现思路分析1.简单参数传递2.复合参数3.动态参数 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a better resul…

typescript,eslint,prettier的引入

typescript 首先用npm安装typescript&#xff0c;cnpm i typescript 然后再tsc --init生成tsconfig.json配置文件&#xff0c;这个文件在package.json同级目录下 最后在tsconfig.json添加includes配置项&#xff0c;在该配置项中的目录下&#xff0c;所有的d.ts中的类型可以在…

[新版Hi3531DV200 性能强悍]

新版Hi3531DV200 性能强悍 Hi3531DV200是针对多路高清/超高清&#xff08;1080p/4M/5M/4K&#xff09;DVR产品应用开发的新一代专业SoC芯片。Hi3531DV200集成了ARM A53四核处理器和性能强大的神经网络推理引擎&#xff0c;支持多种智能算法应用。同时&#xff0c;Hi3531DV200还…

听GPT 讲Rust源代码--library/alloc

File: rust/library/alloc/benches/slice.rs 在Rust源代码中&#xff0c;rust/library/alloc/benches/slice.rs文件的作用是对&[T]类型&#xff08;切片类型&#xff09;进行性能基准测试。该文件包含了对切片类型的一系列操作的基准测试&#xff0c;例如切片迭代、切片排序…

面试高频算法专题:数组的双指针思想及应用(算法村第三关白银挑战)

所谓的双指针其实就是两个变量&#xff0c;不一定真的是指针。 快慢指针&#xff1a;一起向前走对撞指针、相向指针&#xff1a;从两头向中间走背向指针&#xff1a;从中间向两头走 移除值为val的元素 题目描述 27. 移除元素 - 力扣&#xff08;LeetCode&#xff09; 给你…

Spring Boot案例-员工分页查询

准备工作: 数据库的连接: #驱动类名称 spring.datasource.driver-class-namecom.mysql.cj.jdbc.Driver #数据库连接的url spring.datasource.urljdbc:mysql://localhost:3306/tlias #连接数据库的用户名 spring.datasource.usernameroot #连接数据库的密码 spring.datasource.p…

SpringBoot 医药咨询系统

概述 智慧医药系统&#xff08;smart-medicine&#xff09;是一个基于 SpringBoot 开发的Web 项目。整体页面简约大气&#xff0c;增加了AI医生问诊功能&#xff0c;功能设计的较为简单。 开源地址 https://gitcode.net/NVG_Haru/Java_04 界面预览 功能介绍 游客功能介绍 …

Java多线程之线程池,volatile,悲观锁,乐观锁,并发工具类

目录 1.线程池核心原理1.创建线程池2.任务拒绝策略3.自定义线程池 2.线程池的大小1.最大并行数2.影响线程池大小的因素 3.多线程常见考点&#xff08;volatile&#xff0c;悲观锁&#xff0c;乐观锁&#xff09;4.并发工具类 1.线程池核心原理 ①创建一个空的池子 ②提交任务时…

c++写入数据到文件中

假设你想编写一个C程序&#xff1a;当你在调试控制台输入一些数据时&#xff0c;系统会自动存入到指定的文件中&#xff0c;该如何操作呢&#xff1f; 具体操作代码如下&#xff1a; #include<iostream> #include<string> #include<fstream> using namespa…

Spring Boot日志:从Logger到@Slf4j的探秘

写在前面 Hello大家好&#xff0c;今日是2024年的第一天&#xff0c;祝大家元旦快乐&#x1f389; 2024第一篇文章从SpringBoot日志开始 文章目录 一、前言二、日志有什么用&#xff1f;三、日志怎么用&#xff1f;四、自定义日志打印&#x1f4ac; 常见日志框架说明4.1 在程序…

【教3妹学编程-算法题】一年中的第几天

3妹&#xff1a;“太阳当空照&#xff0c;花儿对我笑&#xff0c;小鸟说早早早&#xff0c;你为什么背上炸药包” 2哥 :3妹&#xff0c;什么事呀这么开森。 3妹&#xff1a;2哥你看今天的天气多好啊&#xff0c;经过了一周多的寒潮&#xff0c;天气总算暖和些了。 2哥&#xff…

VUE——IDEA 启动前端工程VS文件启动前端工程

IDEA 启动前端 目录 前言一、打开控制台二、输入npm install三、依赖下载完之后&#xff0c;输入npm run dev&#xff0c;运行前端项目1、IDEA启动前端工程2、文件目录启动前端工程 四、点击http://localhost:8080后续敬请期待 前言 启动已有的vue前端项目 一、打开控制台 选…

服务器硬件及RAID配置实战

目录 1、RAID的概念 2、RAID的实现方式 3、标准的RAID 3.1 RAID 0 3.2 RAID 1 3.3 RAID 5 3.4 RAID 10 4、建立硬件 RAID的过程步骤 1、进入RAID 1.1 重启服务器 1.2 进入RAID界面 1.3 在RAID界面切换目录 2、创建RAID 2.1 移动到RAID卡 2.2 按F2&#xff0c;选择…

NullByte

信息收集 # nmap -sn 192.168.1.0/24 -oN live.nmap Starting Nmap 7.94 ( https://nmap.org ) at 2023-12-29 09:23 CST Nmap scan report for 192.168.1.1 Host is up (0.00038s latency). MAC Address: 00:50:56:C0:00:08 (VMware) Nmap scan report for …

Rust学习笔记006:代码组织

Crate 在Rust中&#xff0c;“crate” 是指 Rust 的代码单元&#xff0c;它可以包含一个或多个模块&#xff08;modules&#xff09;。Rust 的 crate 分类主要有两个方面&#xff1a;库&#xff08;Library Crates&#xff09;和二进制&#xff08;Binary Crates&#xff09;。…

UE4运用C++和框架开发坦克大战教程笔记(十三)(第40~42集)

UE4运用C和框架开发坦克大战教程笔记&#xff08;十三&#xff09;&#xff08;第40~42集&#xff09; 40. 多按键绑定41. 自动生成对象42. 资源模块数据结构测试自动生成对象按资源类型生成对象 40. 多按键绑定 上节课实现了按键绑定系统的 4 种基础绑定&#xff0c;这节课来…

【大数据面试知识点】Spark的DAGScheduler

Spark数据本地化是在哪个阶段计算首选位置的&#xff1f; 先看一下DAGScheduler的注释&#xff0c;可以看到DAGScheduler除了Stage和Task的划分外&#xff0c;还做了缓存的跟踪和首选运行位置的计算。 DAGScheduler注释&#xff1a; The high-level scheduling layer that i…

畅捷通的 Serverless 探索实践之路

作者&#xff1a;计缘&#xff0c;阿里云云原生架构师 畅捷通介绍 畅捷通是中国领先的小微企业财税及业务云服务提供商&#xff0c;成立于 2010 年。畅捷通在 2021 年中国小微企业云财税市场份额排名第一&#xff0c;在产品前瞻性及行业全覆盖方面领跑市场&#xff0c;位居中…