Linux中的File Descriptor共享:实现资源共享与程序优化 (linux fd共享)
在Linux操作系统中,File Descriptor是非常重要的概念和特性之一。File Descriptor是对于文件描述符的统称,它是一个非常重要的概念,它代表了Linux系统中的一个打开的文件句柄。这个句柄包含了文件的所有信息,包括文件的读写权限、文件的位置、文件的大小等等。在Linux操作系统中,任何的I/O操作都需要通过File Descriptor来完成,所以它是Linux系统中非常重要的资源之一。 在Linux系统中,每个进程都有其独立的File Descriptor表。每个表都由一系列整数值组成,这些整数值表示了进程访问的文件资源。这些整数值可以被认为是一种句柄,通过这些句柄,进程可以访问文件资源。在Linux系统中,进程可以共享相关的File Descriptor信息。这种共享机制可以用来实现资源的共享以及程序的优化。 资源共享是非常重要的,在多个进程之间,如果某些文件资源是重复利用的,那么就可以通过File Descriptor实现资源共享。这种方式可以避免系统资源的浪费。对于需要占用较大资源的进程,可以通过共享File Descriptor的方式实现资源效率的提升。例如在一些多线程应用中,多个线程可能需要同时访问相同的文件资源,这时可以通过共享File Descriptor来避免重复打开资源的情况,从而提升程序的效率和稳定性。 除了资源共享之外,File Descriptor还可以用于程序的优化。在Linux系统中,程序的优化非常重要,可以通过各种手段来提高程序的效率和稳定性。其中,File Descriptor的共享机制是一种非常有效的优化方式。在一些高并发和高负载的应用中,为了满足系统的要求,可能需要不断的打开和关闭文件,这会给系统带来不小的开销。为了避免这种情况,可以通过共享File Descriptor的方式来避免频繁的打开和关闭操作。这种方式可以避免文件句柄的重复创建和销毁,从而提高程序的效率和稳定性。 Linux中的File Descriptor共享是一个非常重要的特性和机制。它可以用来实现资源的共享以及程序的优化。在多线程、高并发和高负载的应用中,通过共享File Descriptor,可以有效地避免资源浪费和频繁的打开关闭操作,从而提高程序的效率和稳定性。因此,程序员和系统管理员必须深入了解File Descriptor的共享机制,才能更好的利用它来优化和提高程序和系统的性能。 相关问题拓展阅读: Linux下各种锁的理解和使用及总结解决epoll惊群问题(面试常考)- linux中的fd就绪时,会立即回调rollback,那么哪位大牛能帮忙解释下fd就绪的条件是什么 Linux下各种锁的理解和使用及总结解决epoll惊群问题(面试常考)- 锁出现的原因 临举态界资源是什么: 多线程执行流所共享的资源 锁的作用是什么, 可以做原子操作, 在多线程中针对临界资源的互斥访问… 保证一个时刻只有一个线程可以持有锁对于临界资源做修改操作… 任何一个线程如果需要修改,向临界资源做写入操作都必须持有锁,没有持有锁就不能对于临界资源做写入操作. 锁 : 保证同一时刻只能有一个线程对于临界资源做写入操作 (锁地功能) 再一个直观地代码引出问题,再从指令集的角度去看问题 上述一个及其奇怪的结果,这个结果每一次运行都可能是不一样的,Why ? 按照我们本来的想法是每一个线程 +结果肯定应该是呀,可以就是达不到这个值 为何? (深入汇编指令来看) 一定将过程放置到汇编指令上去看就可以理解这个过程了. a++; 或者 a += 1; 这些操作的汇编操作是几个步骤? 其实是三个步骤: 正常情况下,数据少,操作的线程少,问迹丛题倒是不大,想一想要是这样的情况下,操作次数大,对齐操作的线程多,有些线程从中间切入进来了,在运算之后还没写回内存就另外一个线程切入进来同时对于之前的数据进行++ 再写回内存, 啥效果,多次++ 操作之后结果确实一次加加操作后的结果。 这样的操作 (术语叫做函数的重入) 我觉得其实就是重入到了汇编指令中间了,还没将上一次运算的结果写回内存就重新对这个内存读取再运算写姿答樱入,结果肯定和正常的逻辑后的结果不一样呀 来一幅图片解释一下 咋办? 其实问题很清楚,我们只需要处理的是多条汇编指令不能让它中间入其他的线程运算. (要想自己在执行汇编指令的时候别人不插入进来) 将多条汇编指令绑定成为一条指令不就OK了嘛。 也就是原子操作!!! 不会原子操作?操作系统给咱提供了线程的 绑定方式工具呀:mutex 互斥锁(互斥量), 自旋锁(spinlock), 读写锁(readers-writer lock) 他们也称作悲观锁. 作用都是一个样,将多个汇编指令锁成为一条原子操作 (此处的汇编指令也相当于如下的临界资源) 悲观锁:锁如其名,每次都悲观地认为其他线程也会来修改数据,进行写入操作,所以会在取数据前先加锁保护,当其他线程想要访问数据时,被阻塞挂起 乐观锁:每次取数据的时候,总是乐观地认为数据不会被其他线程修改,因此不上锁。但是在更新数据前, 会判断其他数据在更新前有没有对数据进行修改。 互斥锁 最为常见使用地锁就是互斥锁, 也称互斥量. mutex 特征,当其他线程持有互斥锁对临界资源做写入操作地时候,当前线程只能挂起等待,让出CPU,存在线程间切换工作 解释一下存在线程间切换工作 : 当线程试图去获取锁对临界资源做写入操作时候,如果锁被别的线程正在持有,该线程会保存上下文直接挂起,让出CPU,等到锁被释放出来再进行线程间切换,从新持有CPU执行写入操作 互斥锁需要进行线程间切换,相比自旋锁而言性能会差上许多,因为自旋锁不会让出CPU, 也就不需要进行线程间切换的步骤,具体原理下一点详述 加互斥量(互斥锁)确实可以达到要求,但是会发现运行时间非常的长,因为线程间不断地切换也需要时间, 线程间切换的代价比较大. 相关视频推荐 你绕不开的组件—锁,4个方面手撕锁的多种实现 “惊群”原理、锁的设计方案及绕不开的“死锁”问题 学习视频教程-腾讯课堂 需要C/C++ Linux服务器架构师学习资料加qun获取(资料包括 C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg 等),免费分享 自旋锁 spinlock.自旋锁. 对比互斥量(互斥锁)而言,获取自旋锁不需要进行线程间切换,如果自旋锁正在被别的线程占用,该线程也不会放弃CPU进行挂起休眠,而是恰如其名的在哪里不断地循环地查看自旋锁保持者(持有者)是否将自旋锁资源释放出来… (自旋地原来就是如此) 口语解释自旋:持有自旋锁的线程不释放自旋锁,那也没有关系呀,我就在这里不断地一遍又一遍地查询自旋锁是否释放出来,一旦释放出来我立马就可以直接使用 (因为我并没有挂起等待,不需要像互斥锁还需要进行线程间切换,重新获取CPU,保存恢复上下文等等操作) 哪正是因为上述这些特点,线程尝试获取自旋锁,获取不到不会采取休眠挂起地方式,而是原地自旋(一遍又一遍查询自旋锁是否可以获取)效率是远高于互斥锁了. 那我们是不是所有情况都使用自旋锁就行了呢,互斥锁就可以放弃使用了吗???? 解释自旋锁地弊端:如果每一个线程都仅仅只是需要短时间获取这个锁,那我自旋占据CPU等待是没啥问题地。要是线程需要长时间地使用占据(锁)。。。 会造成过多地无端占据CPU资源,俗称站着茅坑不拉屎… 但是要是仅仅是短时间地自旋,平衡CPU利用率 + 程序运行效率 (自旋锁确实是在有些时候更加合适) 自旋锁需要场景:内核可抢占或者P(多处理器)情况下才真正需求 (避免死锁陷入死循环,疯狂地自旋,比如递归获取自旋锁. 你获取了还要获取,但是又没法释放) 自旋锁的使用函数其实和互斥锁几乎是一摸一样地,仅仅只是需要将所有的mutex换成spin即可 仅仅只是在init存在些许不同 何为惊群,池塘一堆, 我瞄准一条插过去,但是好似所有的都像是觉着自己正在一样的四处逃窜。 这个就是惊群的生活一点的理解 惊群现象其实一点也不少,比如说 accept pthread_cond_broadcast...