C++ Linux Web Server 面试基础篇-操作系统(四、线程通信)

news2024/11/23 19:49:24

⭐️我叫忆_恒心,一名喜欢书写博客的在读研究生👨‍🎓。
如果觉得本文能帮到您,麻烦点个赞👍呗!

近期会不断在专栏里进行更新讲解博客~~~ 有什么问题的小伙伴 欢迎留言提问欧,喜欢的小伙伴给个三连支持一下呗。👍⭐️❤️
Qt5.9专栏定期更新Qt的一些项目Demo
项目与比赛专栏定期更新比赛的一些心得面试项目常被问到的知识点。

Linux Web Server项目虽然是现在C++求职者的人手一个的项目,但是想要吃透这个项目,还是需要一定的基础的,以项目为导向,进行基础的学习。

涵盖了计算机网络(网络编程)常见的知识点和常见的操作系统知识

博主参加过大大小小的互联网厂和银行的秋招和春招的笔试与面试,整理了下面的2万7千字的长文(😄都是干货,写作不易啊),喜欢,觉得有帮助的,欢迎订阅专栏,后续有很多优质的文章进行更新,有任何疑问,欢迎留言!
在这里插入图片描述

C++ Linux Web Server 面试基础篇-操作系统(四、线程通信)

目录

    • C++ Linux Web Server 面试基础篇-操作系统(四、线程通信)
      • 1、线程间的通信方式
      • 2、简述Linux零拷贝的原理?
      • 3、为什么要有DMA技术
      • 4、传统的文件拷贝的不足
      • 5、如何减少[数据拷贝]的次数?
      • 6、如何实现零拷贝
      • 7、大文件传输用什么方式实现?
      • 参考资料

1、线程间的通信方式

同个进程下的线程之间都是共享进程的资源,只要是共享变量都可以做到线程间通信,比如全局变量,所以对于线程间关注的不是通信方式,而是关注多线程竞争共享资源的问题,信号量也同样可以在线程间实现互斥与同步:

  • 互斥的方式,可保证任意时刻只有一个线程访问共享资源;
  • 同步的方式,可保证线程 A 应在线程 B 之前执行;

2、简述Linux零拷贝的原理?

  1. 什么是零拷贝

    所谓「零拷贝」描述的是计算机操作系统当中,CPU不执行将数据从一个内存区域,拷贝到另外一个内存区域的任务。通过网络传输文件时,这样通常可以节省 CPU 周期和内存带宽。

  2. 零拷贝的好处

    (1)节省了 CPU 周期,空出的 CPU 可以完成更多其他的任务

    (2)减少了内存区域之间数据拷贝,节省内存带宽

    (3)减少用户态和内核态之间数据拷贝,提升数据传输效率

    (4)应用零拷贝技术,减少用户态和内核态之间的上下文切换

3、为什么要有DMA技术

如果没有直接内存访问DMA 则CPU 一直参与搬运

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9xX2HkMp-1682155578421)(https://cdn.xiaolincoding.com/gh/xiaolincoder/ImageHost2/操作系统/零拷贝/DRM I_O 过程.png)]

  • DMA 收到磁盘的信号,将磁盘控制器缓冲区中的数据拷贝到内核缓冲区中,此时不占用 CPU,CPU 可以执行其他任务

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5fize5Rf-1682155578422)(https://cdn.xiaolincoding.com/gh/xiaolincoder/ImageHost2/操作系统/零拷贝/DRM I_O 过程.png)]

4、传统的文件拷贝的不足

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WQWFItcS-1682155578423)(https://cdn.xiaolincoding.com/gh/xiaolincoder/ImageHost2/操作系统/零拷贝/传统文件传输.png)]

要想提高文件传输的性能,就需要减少「用户态与内核态的上下文切换」和「内存拷贝」的次数

5、如何减少[数据拷贝]的次数?

从上图中国可以看到,内核区的缓存是没有必要的,通过避免这一缓存可以减少数据拷贝的次数。

在操作系统中,减少数据拷贝的次数是提高性能和效率的重要手段之一。以下是一些常见的减少数据拷贝次数的方法:

  1. 零拷贝(Zero-copy):零拷贝技术是一种可以在不拷贝数据的情况下进行数据传输的技术。在使用零拷贝技术时,内核将应用程序的缓冲区映射到系统内核空间的缓冲区中,然后直接将数据传输到目标设备或缓冲区中,从而避免了多次数据拷贝的操作。
  2. 内核缓冲区复制:在某些情况下,如果应用程序需要在进程间传输数据,可以使用内核缓冲区复制技术,这种技术将数据从一个进程的用户空间缓冲区复制到内核空间的缓冲区,然后再将数据从内核空间的缓冲区复制到另一个进程的用户空间缓冲区,避免了不必要的用户空间和内核空间的切换。
  3. 分页技术:分页技术可以将数据拆分成多个小块,每个小块都有自己的页表。这样在进行数据传输时,只需要传输需要的页,而不需要拷贝整个数据,从而避免了不必要的数据拷贝。
  4. 预先分配空间:预先分配空间可以避免在传输数据时动态分配内存的开销。如果应用程序需要传输大量数据,可以在传输之前预先分配足够的空间,这样在传输时就不需要动态分配内存,从而减少数据拷贝的次数。
  5. 操作系统缓存:一些操作系统提供了数据缓存功能,可以缓存数据以避免重复的拷贝。在数据传输时,如果数据已经被缓存,可以直接使用缓存中的数据,避免了不必要的数据拷贝。

这些技术都可以在不同的场景中使用,以提高操作系统的性能和效率。

6、如何实现零拷贝

零拷贝技术实现的方式:

  • mmap + write
  • sendfile

mmap + write

mmap() 替换 read() 系统调用函数

buf = mmap(file, len);
write(sockfd, buf, len);

系统调用函数会直接把内核缓冲区里的数据「映射」到用户空间.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1kyrL306-1682155578424)(https://cdn.xiaolincoding.com/gh/xiaolincoder/ImageHost2/操作系统/零拷贝/mmap %2B write 零拷贝.png)]

零拷贝(*Zero-copy*)技术,因为我们没有在内存层面去拷贝数据,也就是说全程没有通过 CPU 来搬运数据,所有的数据都是通过 DMA 来进行传输的。

在 Linux 中,可以通过使用零拷贝技术来减少数据拷贝的次数,从而提高数据传输的效率。零拷贝技术是指在数据传输的过程中,尽可能地减少 CPU 和内存的拷贝操作,从而降低数据传输的延迟和 CPU 占用率。

下面给出两个示例代码,分别演示了如何在 Linux 中使用零拷贝技术进行文件传输和网络传输。

  1. 文件传输

使用 mmap 系统调用将文件映射到内存中,然后使用 sendfile 系统调用将文件从内存中传输到网络中,从而避免了数据在用户空间和内核空间之间的拷贝。

#include <sys/sendfile.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int sendfile(int out_fd, int in_fd, off_t *offset, size_t count);

int main()
{
    int in_fd = open("file.txt", O_RDONLY);
    struct stat stat_buf;
    fstat(in_fd, &stat_buf);
    off_t offset = 0;
    sendfile(STDOUT_FILENO, in_fd, &offset, stat_buf.st_size);
    close(in_fd);
    return 0;
}

  1. 网络传输

    使用 splice 系统调用将数据从一个文件描述符传输到另一个文件描述符,从而避免了数据在用户空间和内核空间之间的拷贝。

#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <unistd.h>

int splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags);

int main()
{
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in servaddr = {0};
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(8080);
    bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
    listen(sockfd, 10);
    int connfd = accept(sockfd, NULL, NULL);
    int filefd = open("file.txt", O_RDONLY);
    int flags = SPLICE_F_MOVE | SPLICE_F_NONBLOCK;
    splice(filefd, NULL, connfd, NULL, 4096, flags);
    close(filefd);
    close(connfd);
    close(sockfd);
    return 0;
}

需要注意的是,零拷贝技术的使用需要考虑诸多因素,如硬件支持、内核版本等,同时也需要谨慎使用,避免出现数据丢失或破坏等问题。

7、大文件传输用什么方式实现?

那针对大文件的传输,我们应该使用什么方式呢?

我们先来看看最初的例子,当调用 read 方法读取文件时,进程实际上会阻塞在 read 方法调用,因为要等待磁盘数据的返回,如下图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LbVzfAxc-1682155918503)(https://cdn.xiaolincoding.com/gh/xiaolincoder/ImageHost2/操作系统/零拷贝/阻塞 IO 的过程.png)]

具体过程:

  • 当调用 read 方法时,会阻塞着,此时内核会向磁盘发起 I/O 请求,磁盘收到请求后,便会寻址,当磁盘数据准备好后,就会向内核发起 I/O 中断,告知内核磁盘数据已经准备好;
  • 内核收到 I/O 中断后,就将数据从磁盘控制器缓冲区拷贝到 PageCache 里;
  • 最后,内核再把 PageCache 中的数据拷贝到用户缓冲区,于是 read 调用就正常返回了。

对于阻塞的问题,可以用异步 I/O 来解决

它把读操作分为两部分:

  • 前半部分,内核向磁盘发起读请求,但是可以不等待数据就位就可以返回,于是进程此时可以处理其他任务;
  • 后半部分,当内核将磁盘中的数据拷贝到进程缓冲区后,进程将接收到内核的通知,再去处理数据;

而且,我们可以发现,异步 I/O 并没有涉及到 PageCache,所以使用异步 I/O 就意味着要绕开 PageCache。

绕开 PageCache 的 I/O 叫直接 I/O,使用 PageCache 的 I/O 则叫缓存 I/O。通常,对于磁盘,异步 I/O 只支持直接 I/O。

前面也提到,大文件的传输不应该使用 PageCache,因为可能由于 PageCache 被大文件占据,而导致「热点」小文件无法利用到 PageCache。

于是,在高并发的场景下,针对大文件的传输的方式,应该使用「异步 I/O + 直接 I/O」来替代零拷贝技术

直接 I/O 应用场景常见的两种:

  • 应用程序已经实现了磁盘数据的缓存,那么可以不需要 PageCache 再次缓存,减少额外的性能损耗。在 MySQL 数据库中,可以通过参数设置开启直接 I/O,默认是不开启;
  • 传输大文件的时候,由于大文件难以命中 PageCache 缓存,而且会占满 PageCache 导致「热点」文件无法充分利用缓存,从而增大了性能开销,因此,这时应该使用直接 I/O。

另外,由于直接 I/O 绕过了 PageCache,就无法享受内核的这两点的优化:

  • 内核的 I/O 调度算法会缓存尽可能多的 I/O 请求在 PageCache 中,最后「合并」成一个更大的 I/O 请求再发给磁盘,这样做是为了减少磁盘的寻址操作;
  • 内核也会「预读」后续的 I/O 请求放在 PageCache 中,一样是为了减少对磁盘的操作;

于是,传输大文件的时候,使用「异步 I/O + 直接 I/O」了,就可以无阻塞地读取文件了。

所以,传输文件的时候,我们要根据文件的大小来使用不同的方式:

  • 传输大文件的时候,使用「异步 I/O + 直接 I/O」;

  • 传输小文件的时候,则使用「零拷贝技术」;

参考资料

图片部分来源于小林Coding图解操作系统(非常推荐!!!)小林coding

最后,最后
如果觉得有用,麻烦三连👍⭐️❤️支持一下呀,希望这篇文章可以帮到你,你的点赞是我持续更新的动力

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

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

相关文章

TiDB实战篇-Data Migration (DM) 同步数据

目录 简介 原理 任务管理 ​编辑同步拓扑示例 使用场景 限制 硬件配置 安装&升级 部署 生成配置文件 生成配置文件模板 更具自身的机器修改 部署 启动集群&查看集群 实战 上游数据库前提 配置mysql的相关配置 编写DM的MySQL相关配置 把MySQL和DM …

【JavaEE】Bean的作用域和生命周期

目录 Bean的作用域 作用域分类 设置作用域 通过注解设置 通过配置文件设置 Bean的生命周期 Bean的作用域 Bean的作用域是指&#xff1a;在整个Spring容器中Bean的行为模式。这个模式有六种。 作用域分类 singleton&#xff1a;单例作用域。 在这个模式下&#xff0c;容器…

网络地址转换应用

如图所示,企业使用一台AR 路由器作为出口设备,路由器配置NAT Outbound为私网用户提供访问Internet服务,同时配置NAT Server将私网WEB服务器发布到公网上,对外网用户提供服务。运营商仅为该单位分配了一个公网IP,此地址既作为AR出接口的IP地址,也作为NAT Outbound和NAT Se…

【Atlas500】华为Atals MindStudio配置指南

目录 安装推理用ubuntu版docker配置docker内的ssh服务安装ubuntu系统中的依赖项&#xff1a;检查root用户的umask安装依赖项安装CANN连接到CANN Setting 安装推理用ubuntu版docker 华为的atlas500自带的欧拉系统是一个裁剪系统&#xff0c;一般通过在其上运行官方的ubuntu dock…

【消息队列】Kafka高水位和Leader Epoch原理

什么是高水位 首先高水位也就是HW&#xff0c;而对应的有LEO&#xff0c;其实这都是Kafka副本中针对位移的概念&#xff0c;其目的就是为了保证多副本间数据的一致性。 LEO &#xff08;Log End Offet&#xff09;&#xff1a;每个副本的最后一个offset&#xff0c;LEO其实就是…

你猜我猜不猜 (猜数字游戏) 快来小玩一把叭

&#x1f929;本文作者&#xff1a;大家好&#xff0c;我是paperjie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 &#x1f970;内容专栏&#xff1a;这里是《C语言》专栏&#xff0c;笔者用重金(时间和精力)打造&#xff0c;将C语言知识一网打尽&#xff0c;希望可…

解决Vue热更新失效问题

解决Vue热更新失效 一、问题描述二、出现原因三、解决方案四、总结 &#x1f680; 欢迎访问我的个人博客&#xff1a;https://wk-blog.vip 一、问题描述 之前在本地测试Vue项目时&#xff0c;是可以热更新的&#xff0c;但是最近一段时间发现Vue的热更新失效了。然后通过vs co…

【大厂直通车】美团_测开面经

哈喽,大家好,我是小浪;那么最近暑假实习,日常实习是卷的飞起,无论是开发岗,测试岗,算法岗,都一片死寂;不过还是有很多大佬,成功绞杀很多大厂,offer也是拿到手软; 团子暑期实习offer: 📱本专栏致力于持续更新最新各大厂面经,实习消息,招聘要求; 那么目前价格…

ISCSI个人理解与简要说明

ISCSI个人理解与简要说明 一、如何理解ISCSI二、iscsi 命令iscsiadm&#xff08;管理客户端&#xff09;tgtadm&#xff08;管理服务端&#xff09; 三、ISCSI中的概念四、从DAS&#xff0c;NAS&#xff0c;SAN的角度扩展理解ISCSI 一、如何理解ISCSI 理解一个东西&#xff0c…

Niginx的rewrite

常用的Nginx正则表达式 ^匹配输入字符串的起始位置 $匹配输入字符串的结束位置 *匹配前面的字符零次或多次。如“ol*" 能匹配"o”及“ol”、“oll” 匹配前面的字符一次或多次。如“ol" 能匹配“ol"及“ol1”、“olll"&#xff0c; 但不能匹配“o” ?…

服务器版本的表白墙

目录 1.步骤 2.提供两个接口: 3.流程 4.代码 1.前端代码 2.sql创建表 3.后端代码 MessageServlet.java DBUtil.java 1.步骤 1.约定前后端交互的接口 2.开发服务器代码 a.编写servlet处理前端发来的请求 b.编写数据库代码,存储获取关键的数据 3.开发客户端代码 a.基于…

java学习中遇到的问题及解答

你好&#xff0c;我想问一下&#xff0c;为什么在idea编译环境下&#xff0c;有异常的地方它会报错&#xff0c;让你主动添加抛出错误代码呢&#xff1f; 在Java中&#xff0c;有两种类型的异常&#xff0c;一种是受检异常&#xff08;checked exception&#xff09;&#xff0…

一级结构规范 合集

极限状态设计原则4.1限态4.11 极限状态可分为承载能力极限状态、正常使用极限状态和耐久性极限状态。极限状态应符合下列规定:1当结构或结构构件出现下列状态之一时&#xff0c;应认定为超过了承载能力极限状态;1) 结构构件或连接因超过材料强度而破坏&#xff0c;或因过度变形…

安捷伦E4433B信号发生器

E4433B Agilent E4433B ESG-D系列 4G信号发生器安捷伦250kHz-4GHz 品  牌&#xff1a; Agilent 简单介绍 频率范围&#xff1a; E4430B 250K-1GHz E4431B 250K-2GHz E4432B 250K-3GHz E4433B 250K-4GHz 18320918653 供单信道和多信道CDMA用的测量卡用于I和Q的20 MH…

第六章 建造者模式

文章目录 前言一、传统方式解决盖房子需求完整代码抽象房子类 AbstractHouse实现子类 普通房子实现子类 高楼大厦客户端盖房子 二、引入建造者模式建造者模式的四个角色&#xff1a; 产品、抽象建造者、具体建造者、指挥者完整代码House类 (产品角色)抽象父类&#xff08;抽象建…

Node内置模块 【Event事件模块】

文章目录 &#x1f31f;前言&#x1f31f;Event事件模块&#x1f31f;EventEmitter类&#x1f31f;加载events模块&#x1f31f;实例化eventEmitter对象 &#x1f31f;事件方法列表&#x1f31f;使用事件&#x1f31f;异步与同步 &#x1f31f;写在最后 &#x1f31f;前言 哈喽…

ZLMeidiaKit实现推流时(FFmpeg推rtmp流)时非127.0.0.1被拒绝需要鉴权的解决方式

场景 开源流媒体服务器ZLMediaKit在Windows上运行、配置、按需拉流拉取摄像头rtsp视频流)并使用http-flv网页播放: 开源流媒体服务器ZLMediaKit在Windows上运行、配置、按需拉流拉取摄像头rtsp视频流)并使用http-flv网页播放_霸道流氓气质的博客-CSDN博客 在上面搭建ZLMedia…

CE作业(3)

1.基于域名[www.openlab.com](http://www.openlab.com)可以访问网站内容为 welcome to openlab!!! ​ 2.给该公司创建三个子界面分别显示学生信息&#xff0c;教学资料和缴费网站&#xff0c;基于[www.openlab.com/student](http://www.openlab.com/student) 网站访问学生信息&…

windows和linux上证书的增删查

文章目录 引言windows上对个人证书的增删查创建证书证书的查找证书的删除证书的安装 Linux上对个人证书的增删查创建证书证书的安装证书的查看证书的删除 Linux上对系统证书的增删查 引言 PS: 我之前看过《图解密码技术》&#xff0c;已经对证书这些概念有基本的了解&#xff…

Docker容器---dockerfile简介

Docker容器---dockerfile简介 一、dockerfile概念1、dockerfile介绍2、基于dockerfile创建3、docker镜像加载原理 二、镜像的创建1、基于现有镜像创建2、基于本地模板创建3、基于dockerfile创建 三、Dockerfile编写1、dockerfile操作指令&#xff08;1&#xff09;FROM 镜像&am…