Linux内核IO基础知识与概念

什么是 IO

在计算机操作系统中,所谓的I/O就是 输入(Input)和输出(Output),也可以理解为读(Read)和写(Write),针对不同的对象,I/O模式可以划分为磁盘IO模型和网络IO模型。

IO操作会涉及到用户空间内核空间的转换,先来理解以下规则:

  • 内存空间分为用户空间和内核空间,也称为用户缓冲区和内核缓冲区;

  • 用户的应用程序不能直接操作内核空间,需要将数据从内核空间拷贝到用户空间才能使用;

  • 无论是read操作,还是write操作,都只能在内核空间里执行;

  • 磁盘IO和网络IO请求加载到内存的数据都是先放在内核空间的;

再来看看所谓的读(Read)和写(Write)操作:

  • 读操作:操作系统检查内核缓冲区有没有需要的数据,如果内核缓冲区已经有需要的数据了,那么就直接把内核空间的数据copy到用户空间,供用户的应用程序使用。如果内核缓冲区没有需要的数据,对于磁盘IO,直接从磁盘中读取到内核缓冲区(这个过程可以不需要cpu参与)。而对于网络IO,应用程序需要等待客户端发送数据,如果客户端还没有发送数据,对应的应用程序将会被阻塞,直到客户端发送了数据,该应用程序才会被唤醒,从Socket协议找中读取客户端发送的数据到内核空间,然后把内核空间的数据copy到用户空间,供应用程序使用。

  • 写操作:用户的应用程序将数据从用户空间copy到内核空间的缓冲区中(如果用户空间没有相应的数据,则需要从磁盘—>内核缓冲区—>用户缓冲区依次读取),这时对用户程序来说写操作就已经完成,至于什么时候再写到磁盘或通过网络发送出去,由操作系统决定。除非应用程序显示地调用了sync 命令,立即把数据写入磁盘,或执行flush()方法,通过网络把数据发送出去。

  • 绝大多数磁盘IO和网络IO的读写操作都是上述过程,除了后面要讲到的零拷贝IO。

用户空间&内核空间

野生程序员对于这个概念可能比较陌生,这其实是 Linux 操作系统中的概念。虚拟内存(操作系统中的概念,和物理内存是对应的)被操作系统划分成两块:User Space(用户空间 和 Kernel Space(内核空间),本质上电脑的物理内存是不划分这些的,只是操作系统开机启动后在逻辑上虚拟划分了地址和空间范围。

操作系统会给每个进程分配一个独立的、连续的虚拟内存地址空间(物理上可能不连续),以32位操作系统为例,该大小一般是4G,即232 。其中将高地址值的内存空间分配给系统内核占用(网上查资料得知:Linux下占1G,Windows下占2G),其余的内存地址空间分配给用户进程使用。

因为我们不是要深入学习操作系统,所以这里以32位系统举例旨在帮助你理解原理。32 位的 LInux 操作系统下,0~3G为用户空间,3~4G为内核空间

那为什么要这样划分出空间范围呢?

也很好理解,毕竟操作系统身份高贵,太重要了,不能和用户应用程序在一起玩耍,各自的数据都要分开存储并且严格控制权限不能越界。这样才能保证操作系统的稳定运行,用户应用程序太不可控了,不同公司或者个人都可以开发,碰到坑爹的误操作或者恶意破坏系统数据直接宕机玩完了。隔离后应用程序要挂你就挂,操作系统可以正常运行。

简单说,内核空间 是操作系统 内核代码运行的地方用户空间用户程序代码运行的地方。当应用进程执行系统调用陷入内核代码中执行时就处于内核态,当应用进程在运行用户代码时就处于用户态

同时内核空间可以执行任意的命令,而用户空间只能执行简单的运算,不能直接调用系统资源和数据。必须通过操作系统提供接口,向系统内核发送指令。

一旦调用系统接口,应用进程就从用户空间切换到内核空间了,因为开始运行内核代码了。

简单看几行代码,分析下是应用程序在用户空间和内核空间之间的切换过程:

str = "i am qige" // 用户空间
x = x + 2
file.write(str) // 切换到内核空间
y = x + 4 // 切换回用户空间

上面代码中,第一行和第二行都是简单的赋值运算,在用户空间执行。第三行需要写入文件,就要切换到内核空间,因为用户不能直接写文件,必须通过内核安排。第四行又是赋值运算,就切换回用户空间

用户态切换到内核态的3种方式:

资料直通车:最新Linux内核源码资料文档+视频资料

内核学习地址:Linux内核源码/内存调优/文件系统/进程管理/设备驱动/网络协议栈

  • 系统调用。也称为 System Call,是说用户态进程主动要求切换到内核态的一种方式,用户态进程使用操作系统提供的服务程序完成工作,比如上面示例代码中的写文件调用,还有像 fork() 函数实际上就是执行了一个创建新进程的系统调用。而系统调用的机制其核心还是使用了操作系统为用户特别开放的一个中断来实现。

  • 异常。当CPU在用户空间执行程序代码时发生了不可预期的异常,这时会触发由当前运行进程切换到处理此异常的内核相关程序中,切换到内核态,比如缺页异常。

  • 外围设备的中断。 当外围设备完成用户请求的某些操作后,会向CPU发送相应的中断信号,这时CPU会暂停执行下一条即将执行的指令转而去执行与中断信号对应的处理程序,如果当前正在运行用户态下的程序指令,自然就发了由用户态到内核态的切换。比如硬盘数据读写完成,系统会切换到中断处理程序中执行后续操作等。

以上3种方式,除了系统调用是进程主动发起切换,异常和外围设备中断是被动切换的。

查看 CPU 时间在 User Space 与 Kernel Space 之间的分配情况,可以使用top命令。它的第三行输出就是 CPU 时间分配统计。

我们来看看图中圈出来的 CPU 使用率的三个指标:

其中,第一项 7.57% user 就是 CPU 消耗在 User Space 的时间百分比,第二项 7.0% sys是消耗在 Kernel Space 的时间百分比。第三项 85.4% idle 是 CPU 消耗在闲置进程的时间百分比,这个值越低,表示 CPU 越忙。

PIO&DMA

大家都知道一般我们的数据是存储在磁盘上的,应用程序想要读写这些数据肯定就需要加载到内存中。接下来给大家介绍下 PIODMA 这两种 IO 设备和内存之间的数据传输方式。

PIO 工作原理

  1. 用户进程通过read等系统调用接口向操作系统(即CPU)发出IO请求,请求读取数据到自己的用户内存缓冲区中,然后该进程进入阻塞状态。

  1. 操作系统收到用户进程的请求后,进一步将IO请求发送给磁盘。

  1. 磁盘驱动器收到内核的IO请求后,把数据读取到自己的缓冲区中,此时不占用CPU。当磁盘的缓冲区被读满之后,向内核发起中断信号告知自己缓冲区已满。

  1. 内核收到磁盘发来的中断信号,使用CPU将磁盘缓冲区中的数据copy到内核缓冲区中。

  1. 如果内核缓冲区的数据少于用户申请读的数据,则重复步骤2、3、4,直到内核缓冲区的数据符合用户的要求为止。

  1. 内核缓冲区的数据已经符合用户的要求,CPU停止向磁盘IO请求。

  1. CPU将数据从内核缓冲区拷贝到用户缓冲区,同时从系统调用中返回。

  1. 用户进程读取到数据后继续执行原来的任务。

PIO缺点:每次IO请求都需要CPU多次参与,效率很低。

DMA 工作原理

DMA(直接内存访问,Direct Memory Access)。

  1. 用户进程通过read等系统调用接口向操作系统(即CPU)发出IO请求,请求读取数据到自己的用户内存缓冲区中,然后该进程进入阻塞状态。

  1. 操作系统收到用户进程的请求后,进一步将IO请求发送给DMA,然后CPU就可以去干别的事了。

  1. DMA将IO请求转发给磁盘。

  1. 磁盘驱动器收到内核的IO请求后,把数据读取到自己的缓冲区中,当磁盘的缓冲区被读满后,向DMA发起中断信号告知自己缓冲区已满。

  1. DMA收到磁盘驱动器的信号,将磁盘缓冲区中的数据copy到内核缓冲区中,此时不占用CPU( PIO 这里是占用CPU的)。

  1. 如果内核缓冲区的数据少于用户申请读的数据,则重复步骤3、4、5,直到内核缓冲区的数据符合用户的要求为止。

  1. 内核缓冲区的数据已经符合用户的要求,DMA停止向磁盘发IO请求。

  1. DMA发送中断信号给CPU。

  1. CPU收到DMA的信号,知道数据已经准备好,于是将数据从内核空间copy到用户空间,系统调用返回。

  1. 用户进程读取到数据后继续执行原来的任务。

跟PIO模式相比,DMA就是CPU的一个代理,它负责了一部分的拷贝工作,从而减轻了CPU的负担。

需要注意的是,DMA承担的工作是从磁盘的缓冲区到内核缓冲区或网卡设备到内核的 soket buffer的拷贝工作,以及内核缓冲区到磁盘缓冲区或内核的 soket buffer 到网卡设备的拷贝工作,而内核缓冲区到用户缓冲区之间的拷贝工作仍然由CPU负责。

可以肯定的是,PIO模式的计算机我们现在已经很少见到了。

缓冲IO和直接IO

学习用户空间和内核空间的时候我们也说了,用户空间是不能直接访问内核空间的数据的,如果需要访问怎么办?很简单,就需要将数据从内核空间拷贝的用户空间。

  • 缓冲 IO:其实就是磁盘中的数据通过 DMA 先拷贝到内核空间,然后再从内核空间拷贝到用户空间。

  • 直接 IO:磁盘中的数据直接通过 DMA 拷贝到用户空间。

缓冲 IO

缓冲 IO 也被成为标准 IO,大多数的文件系统系统默认都是以缓冲 IO 的方式来工作的。在Linux的缓冲I/O机制中,数据先从磁盘复制到内核空间的缓冲区,然后从内核空间缓冲区复制到应用程序的地址空间。

接下来我们看看缓冲 IO 下读写操作是如何进行?

  • 读操作:

操作系统检查内核的缓冲区有没有需要的数据,如果已经缓冲了,那么就直接从缓冲中返回;否则从磁盘中读取到内核缓冲中,然后再复制到用户空间缓冲中。

  • 写操作:

将数据从用户空间复制到内核空间的缓冲中。这时对用户程序来说写操作就已经完成,至于什么时候再写到磁盘中由操作系统决定,除非显示地调用了sync同步命令。

缓冲I/O的优点:

  1. 在一定程度上分离了内核空间和用户空间,保护系统本身的运行安全;

  1. 因为内核中有缓冲,可以减少读盘的次数,从而提高性能。

缓冲I/O的缺点:

在缓冲 I/O 机制中,DMA 方式可以将数据直接从磁盘读到内核空间页缓冲中,或者将数据从内核空间页缓冲直接写回到磁盘上,而不能直接在用户地址空间和磁盘之间进行数据传输,这样数据在传输过程中需要在应用程序地址空间(用户空间)和内核缓冲(内核空间)之间进行多次数据拷贝操作,这些数据拷贝操作所带来的CPU以及内存开销是非常大的。

直接IO

顾名思义,直接IO就是应用程序直接访问磁盘数据,而不经过内核缓冲区,也就是绕过内核缓冲区,自己管理I/O缓冲区,这样做的目的是减少一次从内核缓冲区到用户程序缓冲的数据复制。

引入内核缓冲区这个主要是为了提升从磁盘读写数据文件的性能,这也是很多系统优化中常见的手段,多一层缓存可以有效减少很多磁盘 IO 操作;而当用户程序需要向磁盘文件中写入数据时,实际上只需要写入到内核缓冲区便可以返回了,而真正的落盘是有一定的延迟策略的,但这无疑提升了应用程序写入文件的响应速度。

在数据库管理系统这类应用中,它们更倾向于选择自己实现的缓存机制,因为数据库管理系统往往比操作系统更了解数据库中存放的数据,数据库管理系统可以提供一种更加有效的缓存机制来提高数据库中数据的存取性能。

直接I/O的优点:

应用程序直接访问磁盘数据,不经过操作系统内核数据缓冲区,这样做的最直观目的是减少一次从内核缓冲区到用户程序缓冲的数据复制。这种方式通常用在数据库、消息中间件中,由应用程序来实现数据的缓存管理。

直接I/O的缺点:

如果访问的数据不在应用程序缓冲中,那么每次数据都会直接从磁盘进行加载,这种直接加载会非常缓慢。通常 直接I/O 跟 异步I/O 结合使用会得到较好的性能。(异步IO:当访问数据的线程发出请求之后,线程会接着去处理其他事,而不是阻塞等待)

IO 访问方式

我们常说的 IO 操作,不仅仅是磁盘 IO,还有常见的网络数据传输即网络 IO。

磁盘 IO

读操作:

当应用程序调用read()方法时,操作系统检查内核高速缓冲区中是否存在需要的数据,如果存在,那么就直接把内核空间的数据copy到用户空间,供用户的应用程序使用。如果内核缓冲区没有需要的数据,通过通过DMA方式从磁盘中读取数据到内核缓冲区,然后由CPU控制,把内核空间的数据copy到用户空间。

这个过程会涉及到两次缓冲区copy,第一次是从磁盘到内核缓冲区,第二次是从内核缓冲区到用户缓冲区,第一次是DMA的copy,第二次是CPU的copy。

写操作:

当应用程序调用write()方法时,应用程序将数据从用户空间copy到内核空间的缓冲区中(如果用户空间没有相应的数据,则需要从磁盘—>内核缓冲区—>用户缓冲区),这时对用户程序来说写操作就已经完成,至于什么时候把数据再写到磁盘(从内核缓冲区到磁盘的写操作也由DMA控制,不需要cpu参与),由操作系统决定。除非应用程序显示地调用了sync命令,立即把数据写入磁盘。

如果应用程序没准备好写的数据,则必须先从磁盘读取数据才能执行写操作,这时会涉及到四次缓冲区的copy,第一次是从磁盘的缓冲区到内核缓冲区,第二次是从内核缓冲区到用户缓冲区,第三次是从用户缓冲区到内核缓冲区,第四次是从内核缓冲区写回到磁盘。前两次是为了读,后两次是为了写。这其中有两次 CPU 拷贝,两次DMA拷贝。

磁盘IO的延时:

为了读或写,磁头必须能移动到所指定的磁道上,并等待所指定的扇区的开始位置旋转到磁头下,然后再开始读或写数据。磁盘IO的延时分成以下三部分:

  • 寻道时间:把磁头移动到指定磁道上所经历的时间;

  • 旋转延迟时间 :指定扇区移动到磁头下面所经历的时间;

  • 传输时间 :数据的传输时间(数据读出或写入的时间);

网络 IO

读操作:

网络 IO 既可以从物理磁盘中读数据,也可以从Socket中读数据(从网卡中获取)。当从物理磁盘中读数据的时候,其流程和磁盘IO的读操作一样。当从Socket中读数据,应用程序需要等待客户端发送数据,如果客户端还没有发送数据,对应的应用程序将会被阻塞,直到客户端发送了数据,该应用程序才会被唤醒,从Socket协议栈(网卡)中读取客户端发送的数据到内核空间(这个过程也由DMA控制),然后把内核空间的数据 copy 到用户空间,供应用程序使用。

写操作:

为了简化描述,我们假设网络IO的数据从磁盘中获取,读写操作的流程如下:

  • 当应用程序调用read()方法时,通过DMA方式将数据从磁盘拷贝到内核缓冲区;

  • 由cpu控制,将内核缓冲区的数据拷贝到用户空间的缓冲区中,供应用程序使用;

  • 当应用程序调用 write() 方法时,CPU 会把用户缓冲区中的数据 copy 到内核缓冲区的 Socket Buffer 中;

  • 最后通过DMA方式将内核空间中的Socket Buffer拷贝到Socket协议栈(即网卡设备)中传输;

网络IO 的写操作也有四次缓冲区的copy,第一次是从磁盘缓冲区到内核缓冲区(由DMA控制),第二次是内核缓冲区到用户缓冲区(CPU控制),第三次是用户缓冲区到内核缓冲区的 Socket Buffer(由CPU控制),第四次是从内核缓冲区的 Socket Buffer 到网卡设备(由DMA控制)。四次缓冲区的copy工作两次由CPU控制,两次由DMA控制

网络IO的延时:

网络IO主要延时是由:服务器响应延时+带宽限制+网络延时+跳转路由延时+本地接收延时 决定。一般为几十到几千毫秒,受环境影响较大。所以,一般来说,网络IO延时要大于磁盘IO延时(不过同数据中心的交互除外,会比磁盘 IO 更快)。

零拷贝 IO

在上述IO中,一次读写操作要经过四次缓冲区的拷贝,并经历了四次内核态和用户态的切换零拷贝(zero copy)IO 技术减少不必要的内核缓冲区跟用户缓冲区之间的拷贝,从而减少CPU的开销和状态切换带来的开销,达到性能的提升。

我们还是对比上面不使用零拷贝时的网络 IO 传输过程来对比分析下:

和上图普通的网络 IO 传输过程对比,零拷贝的传输过程:硬盘 -> kernel buffer (快速拷贝到kernel socket buffer) -> Socket协议栈(网卡设备中)。

  • 当应用程序调用read()方法时,通过DMA方式将数据从磁盘拷贝到内核缓冲区;

  • 由CPU控制,将内核缓冲区的数据直接拷贝到另外一个与 Socket 相关的内核缓冲区,即kernel socket buffer;

  • 然后由 DMA 把数据从 kernel socket buffer 直接拷贝给 Socket 协议栈(网卡设备中);

这里,只经历了三次缓冲区的拷贝第一次是从磁盘缓冲区到内核缓冲区,第二次是从内核缓冲区到 kernel socket buffer,第三次是从 kernel socket buffer 到Socket 协议栈(网卡设备中)。只发生两次内核态和用户态的切换,第一次是当应用程序调用read方法时,用户态切换到内核态执行read系统调用,第二次是将数据从网络中发送出去后系统调用返回,从内核态切换到用户态。

零拷贝(zero copy)的应用:

  • Linux 下提供了zero copy的接口:sendfile和splice,用户可通过这两个接口实现零拷贝传输;

  • Nginx 可以通过sendfile配置开启零拷贝;

  • 在 Linux 系统中,Java NIO中 FileChannel.transferTo 的实现依赖于 sendfile()调用;

  • Apache 使用了 sendfile64() 来传送文件,sendfile64() 是 sendfile() 的扩展实现;

  • Kafka也用到了零拷贝的功能;

注意:零拷贝要求输入的fd必须是文件句柄,不能是socket,输出的fd必须是socket,也就是说,数据的来源必须是从本地的磁盘,而不能是从网络中,如果数据来源于socket,就不能使用零拷贝功能了。我们看一下sendfile接口就知道了:

#include <sys/sendfile.h>
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count)
  • out_fd:待写入文件描述符;

  • in_fd:待读出文件描述符;

  • offset:从读入文件流的哪个位置开始读,如果为空,则默认从起始位置开始;

  • count:指定在文件描述符in_fd 和out_fd之间传输的字节数;

  • 返回值:成功时,返回出传输的字节数,失败返回-1;

**in_fd 必须指向真实的文件,不能是socket和管道;而out_fd则必须是一个socket。由此可见,**sendfile 几乎是专门为在网络上传输文件而设计的。

在Linxu系统中,一切皆文件,因此socket也是一个文件,也有文件句柄(或文件描述符)。

同步&异步、阻塞&非阻塞

这两组概念,我接触编程以来,经过听到别人说服务端是 同步非阻塞模型 或者 异步阻塞的 IO 模型,也前后了解过几次,但是理解都不够透彻,特别是这个非阻塞和异步同步和阻塞的概念很容易懵逼,每个人的说法都不一样,最近我耐心看了几篇文章,这次我感觉我是顿悟了,这里分享下我的理解:

同步和异步是针对应用程序向内核发起任务后的状态而言的:如果发起调用后,在没有得到结果之前,当前调用就不返回,不能接着做后面的事情,一直等待就是同步异步就是发出调用后,虽然不能立即得到结果,但是可以继续执行后面的事情,等调用结果出来时,会通过状态、通知和回调来通知调用者。

举个例子加深下理解:

  1. 在互联网普及之前,我们去医院看病都是排队的模式,想看病就得排队等,直到轮到你,在此之前你必须一直排队等待,这个就是同步;

  1. 现在互联网普及了,都是直接大屏叫号,我们预约登记后,就可以去休息厅坐着,打游戏啥的都可以干,到自己看病的时候会有通知的,这就是异步;

阻塞blocking、非阻塞non-blocking,则聚焦的是CPU在等待结果的过程中的状态

阻塞调用是指调用结果返回之前,当前线程会被挂起,只有在得到结果之后才会返回。你可能会把阻塞调用和同步调用等同起来,实际上它们是不同的,同步只是说必须等到出结果才可以返回,但是等的过程中线程可以是激活的,阻塞是说线程被挂起了。

非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。

比如前面的例子,排队的过程中什么也不能做就是阻塞,CPU 执行权是交出去的;一边排队,一边看手机就是非阻塞,CPU 执行权还在自己手里,但是没看完病之前依旧是在排队死等,所以还是同步的。

总结

通过今天的学习,我们掌握了什么是 IO、常见的 IO 操作类型以及对应操作的原理,还有非常重要但是却很容易搞混的同步&异步、阻塞&非阻塞之间的区别,讲解的应该还是比较清楚的。

本文内容还是比较简单的,是一些基础知识,但是如果想深入学习网络编程这些基础是绕不开的,了解了操作系统对于 IO 操作的优化,才能搞明白各种高性能网络服务器的原理。

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

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

相关文章

<Linux>进程控制

进程控制 文章目录进程控制一、进程创建1.fork函数认识2.写时拷贝3.fork常规用法4.fork调用失败的原因二、进程终止1.进程退出场景2.进程退出码3.进程退出的方式三、进程等待1.进程等待是什么&#xff1f;2.进程等待的必要性3.进程等待的方法3.1.wait函数3.2.waitpid函数4.如何…

为什么 ChatGPT 输出时经常会中断,需要输入“继续” 才可以继续输出?

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;蚂蚁集团高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《EffectiveJava》独家解析》专栏作者。 热门文章推荐…

树莓派Pico开发板I2C OLED显示模块接口与MicroPython编程

首先简要介绍I2C接口及I2C接口OLED显示模块&#xff0c;然后讲述Pico开发板I2C总线引脚及其与I2C总线OLED SSD1306显示模块的接口原理&#xff0c;最后给出Pico开发板控制OLED屏显示文字/图形的MicroPython程序实例。 一、I2C接口简介 I2C/IIC/I2C&#xff08;Inter-Integrated…

Linux内核Socket通信原理和实例讲解

关于对 Socket 的认识&#xff0c;大致分为下面几个主题&#xff0c;Socket 是什么&#xff0c;Socket 是如何创建的&#xff0c;Socket 是如何连接并收发数据的&#xff0c;Socket 套接字的删除等。Socket 是什么以及创建过程一个数据包经由应用程序产生&#xff0c;进入到协议…

平板触控笔哪些品牌好?ipad触控笔推荐平价

苹果电容笔与平替电容笔两者需要根据我们的预算以及需求去选择&#xff0c;要是日常多用于用于绘画&#xff0c;建议可以用Apple Pencil&#xff0c;而对于日常仅仅用于学习与记笔记&#xff0c;可以用平替电容笔&#xff0c;由于平替电容笔的品质与表现都非常优秀。小编整理了…

初识进程

文章目录一、进程的概念1. 进程是什么及进程的管理2. Linux 下的 pcb3. 系统调用接口 getpid 和 getppid4. 系统调用接口 fork一、进程的概念 1. 进程是什么及进程的管理 在 Linux下 ./binaryfile 运行一个程序或者在 Windows下双击运行一个程序时&#xff0c;程序就变成了一个…

【百面成神】spring基础12问,你能坚持到第几问

前 言 &#x1f349; 作者简介&#xff1a;半旧518&#xff0c;长跑型选手&#xff0c;立志坚持写10年博客&#xff0c;专注于java后端 ☕专栏简介&#xff1a;java面试宝典&#xff0c;特点&#xff1a;全、精、深、简&#xff0c;力求每个核心知识点1分钟回答好。 &#x1f3…

RK3588平台开发系列讲解(视频篇)RTP H264 码流打包详解

平台内核版本安卓版本RK3588Linux 5.10Android 12文章目录 一、单 NALU 封包方式二、组合封包方式三、分片封包方式沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 H264 码流是放在 RTP 的有效载荷部分的。因此有效载荷前面的 RTP 头部跟码流本身是没有关系的,所以我…

Python|蓝桥杯进阶第六卷——搜索

欢迎交流学习~~ 专栏&#xff1a; 蓝桥杯Python组刷题日寄 蓝桥杯进阶系列&#xff1a; &#x1f3c6; Python | 蓝桥杯进阶第一卷——字符串 &#x1f50e; Python | 蓝桥杯进阶第二卷——贪心 &#x1f49d; Python | 蓝桥杯进阶第三卷——动态规划 ✈️ Python | 蓝桥杯进阶…

mysql数据库介绍

&#x1f49c;今天对mysql的一些基础概念进行讲诶横扫&#xff0c;如概念、特点、优势、发展历史等等。对之前内容感兴趣的同学可以参考&#x1f447;&#xff1a; 链接: mysql学习之数据系统概述 &#x1f3be;让我们开始今日份的学习吧&#xff01; 目录1. mysql的基本概念…

十七、网上商城项目(5)

本章概要 购物车 购物车状态管理配置购物车组件 结算页面用户管理 用户状态管理配置用户注册组件用户登录组件 17.8 购物车 在一个电商网站中&#xff0c;购物车在很多页面都需要用到&#xff0c;因此非常适合放在 Vuex 的 store 中进行集中管理。在本项目中&#xff0c;采…

【北大青鸟天府校区的Java专业怎么样?】

北大青鸟天府校区是北大青鸟总部在西南投资兴办的重点校区&#xff0c;拥有极为强大的外部教育资源和就业资源&#xff0c;使咱们的学员能够享受更好、更完善的教学资源。超过23年的办学经验&#xff0c;培养了超过10000位学员&#xff0c;保障就业&#xff0c;学员就业率达到9…

[入门必看]数据结构2.3:线性表的链式表示

[入门必看]数据结构2.3&#xff1a;线性表的链式表示第二章 线性表2.3 线性表的链式表示知识总览2.3.1 单链表的定义2.3.2_1 单链表的插入删除2.3.2_2 单链表的查找2.3.2_3 单链表的建立2.3.3 双链表2.3.4 循环链表2.3.5 静态链表2.3.6 顺序表和链表的比较2.3.1 单链表的定义单…

JUC高级四:Java内存模型之JMM

JUC高级四:Java内存模型之JMM 1. 计算机硬件存储体系(JMM为什么诞生) 因为有这么多级的缓存(cpu和物理主内存的速度不一致的)&#xff0c;CPU的运行并不是直接操作内存而是先把内存里边的数据读到缓存&#xff0c;而内存的读和写操作的时候就会造成不一致的问题 在我们cpu寄存…

WebRTC开源库内部调用abort函数引发程序发生闪退问题的排查

目录 1、初始问题描述 2、使用Process Explorer工具查看到处理音视频业务的rtcmpdll.dll模块没有加载起来 3、使用Dependency Walker工具查看到rtcmpdll.dll依赖的库有问题 4、更新库之后Debug程序启动时就发生异常&#xff0c;程序闪退 5、VS调试时看不到有效的函数调用堆…

十大Python可视化工具,太强了

今天介绍Python当中十大可视化工具&#xff0c;每一个都独具特色&#xff0c;惊艳一方。 Matplotlib Matplotlib 是 Python 的一个绘图库&#xff0c;可以绘制出高质量的折线图、散点图、柱状图、条形图等等。它也是许多其他可视化库的基础。 import matplotlib.pyplot as p…

OpenCV入门(二十)快速学会OpenCV 19 对象测量

OpenCV入门&#xff08;二十&#xff09;快速学会OpenCV 19 对象测量1.对象测量2.多边形拟合3.计算对象中心作者&#xff1a;Xiou 1.对象测量 opencv 中对象测量包括&#xff1a; 如面积&#xff0c;周长&#xff0c;质心&#xff0c;边界框等。 弧长与面积测量&#xff1b; …

《LKD3粗读笔记》(4)进程调度

1、多任务 什么是多任务操作系统&#xff1f; 能同时并发地交互执行多个进程。注意是并发而不是并行。特别地&#xff0c;在多处理机机器上可以实现真正意义上的并行&#xff0c;因为它长了多个脑子多任务操作系统有哪些分类&#xff1f; 非抢占式多任务&#xff08;cooperati…

【云原生】Kubernetes(k8s)部署 MySQL+Dubbo+Nacos服务

一、说明二、部署 MySQL三、部署 Nacos四、部署 Dubbo 服务4.1. 创建镜像仓库的密钥4.2. 部署 provider 服务4.3. 部署 consumer 服务五、测试一、说明 本文介绍基于 Kubernetes(k8s) 环境集成阿里云 私有镜像仓库 来部署一套 Dubbo Nacos 的微服务系统&#xff0c;并使用 Ku…

7个最好的PDF编辑器,帮你像编辑Word一样编辑PDF

PDF 是具有数字思维的组织的重要交流工具。提供高效的工作流程和更好的安全性&#xff0c;可以创建重要文档并与客户、同事和员工共享。文档的布局已锁定&#xff0c;因此无论在什么设备上查看&#xff0c;格式都保持不变。这是让每个人保持一致的好方法——尤其是那些使用Micr…
最新文章