当前位置: 首页 > news >正文

linux的mmc子系统与块设备关联

1.前言

本文主要block组件的主要流程,在介绍的过程中,将详细说明和block相关的流程,涉及到其它组件的详细流程再在相关文章中说明。

2.主要数据结构和API

2.1 struct mmc_card

Elemete Namestruct mmc_card
Pathinclude/linux/mmc/card.h
Responsiblities

 是对mmc device的抽象,由于定义了mmc_bus_type类型的总线,此处mmc_card是与mmc_bus_type配套

Attributions
  • host:struct mmc_host *类型,这个mmc device属于哪个host管理;
  • dev:struct device类型,代表设备驱动模型中的一个 device
  • ocr:当前的操作电压设置
  • rca:device的relative card address
  • type:卡的类型,包括MMC/SD/SDIO/COMBO(SDIO+MEM)
  • state:卡的状态,在线、只读、是否使用block地址、是否是SDXC卡、卡被移除、卡在BKOPS、卡在suspend
  • quirks:卡的一些其它怪癖属性
  • erase_size:单位sectors
  • erase_shift:可以擦除的 sectors是2的多少次方
  • pref_erase:单位sectors
  • eg_boundary
  • erased_byte:擦除的字节数
  • raw_cid:原始的CID值
  • raw_csd:原始的CSD值
  • raw_scr:原始的raw_scr值
  • cid:struct mmc_cid类型,卡identification
  • csd:struct mmc_csd类型,保存从卡的CSD寄存器读取的内容
  • ext_csd:struct mmc_ext_csd类型,卡扩展信息
  • scr:其它的SD信息
  • ssr:更多的SD信息
  • sw_caps:swicth能力
  • sdio_funcs:SDIO功能的个数
  • cccr:struct sdio_cccr类型,卡的通常信息
  • cis:struct sdio_cis
  • sd_bus_speed:bus speed mode
  • mmc_avail_type:host和card都支持的设备类型
  • drive_strength:驱动能力,用于UHS-I, HS200 or HS400
  • debugfs_root:struct dentry *类型,用于debugfs显示根目录
  • part:struct mmc_part类型,物理分区
  • nr_parts:物理分区的个数
Operations

2.2 struct mmc_driver

Elemete Namestruct mmc_driver
Pathinclude/linux/mmc/card.h
Responsiblities

mmc driver,由于定义了mmc_bus_type类型的总线,此处mmc_driver是与mmc_bus_type配套

Attributions
  • drv:struct device_driver类型
  • probe,remove,shutdown:mmc driver相关函数
Operations
  •  int mmc_register_driver(struct mmc_driver *drv)

 设置总线类型,并将drv加入到设备驱动模型中

  • void mmc_unregister_driver(struct mmc_driver *drv)

将drv从设备驱动模型中移除

2.3 struct mmc_blk_data

Elemete Namestruct mmc_blk_data
Pathdrivers/mmc/card/block.c
Responsiblities

mmc_blk_data为block的核心结构体,用于存放mmc block的一些数据,与mmc slot对应

Attributions
  • lock:spinlock_t类型
  • disk:struct gendisk *类型,代表一个磁盘设备
  • queue:struct mmc_queue类型,请求队列
  • part:分区链表
  • flags:
  • usage:
  • read_only:
  • part_type:
  • name_idx:
  • reset_done:
  • part_curr:
  • force_ro:
  • power_ro_lock:
  • area_type:
Operations

3. 主要流程

3.1 mmc_blk_init

mmc_blk_init->

  初始化max_devices

  register_blkdev

  mmc_register_driver

module_init(mmc_blk_init)会执行到此函数

  • 初始化max_devices:设定最多支持多少个mmc块设备给max_devices
每类块设备支持256个次设备号,每个块设备有16个次设备号(16个分区),由此得出支持的最大的mmc块设备数max_devices为256/16=16,每个此设备号对应一个分区?
  • register_blkdev:向全局的struct blk_major_name类型的数组major_names注册本块设备的主设备号和设备名

mmc子系统对于上层block子系统来讲是首先抽象为一个普通的块设备。
通过register_blkdev向block子系统注册一个block设备,主设备号为MMC_BLOCK_MAJOR,设备名为“mmc”。
通过分配一个blk_major_name结构体,来保存主设备号和设备名,blk_major_name被保存到全局的blk_major_name数组中。
如果不指定主设备号,将查询全局的blk_major_name结构体找到一个未用的主设备号来使用,并将此主设备号作为返回值返回。
major_names中的信息会出现在/proc/devices中。
因此可以看出,注册做的事情实际上非常少。注册完成后,除了能够在/proce/devices中看到设备之外,不能对设备做任何事情,设备还无法使用,只有当block_device与gendisk建立关联用户空间才可以访问

  • mmc_register_driver(&mmc_driver)
设备驱动模型中通过driver_register将mmc_driver注册到mmc_bus_type上

3.2 mmc_blk_exit

mmc_blk_exit->

  mmc_unregister_driver

  unregister_blkdev

在退出的时候会执行mmc_blk_exit,与mmc_blk_init相反的动作,主要包括:

  • mmc_unregister_driver(&mmc_driver)
从mmc_bus_type上将mmc_driver注销
  •  unregister_blkdev(MMC_BLOCK_MAJOR, "mmc");
从全局的struct blk_major_name类型的数组major_names中注销主设备号为MMC_BLOCK_MAJOR名为mmc的blk_major_name结构体
释放对应的blk_major_name结构体

3.3 mmc_blk_probe

mmc_blk_probe->

       mmc_blk_alloc->

              mmc_blk_alloc_req->

        alloc_disk

                     mmc_init_queue->

          blk_queue_prep_rq

                            kthread_run(mmc_queue_thread, mq);

  mmc_blk_alloc_parts(card, md))

  mmc_add_disk->

      block_add_disk

初始化时mmc_blk_init中会执行mmc_register_driver,而前文所述执行mmc_attach_mmc时会通过mmc_add_card将mmc_card注册到mmc bus,这样就触发了执行前文所述的mmc_blk_probe函数,后面有详细解释mmc_blk_probe的执行过程

mmc_blk_probe最主要的是初始化了request queue;初始化disk,同时通过mmc_add_disk将磁盘添加到系统中,使之可用

  • mmc_blk_alloc_req

创建并初始化请求队列,启动线程循环抓取请求队列中的request,调用request处理函数进行处理

(1)分配mmc_blk_data结构体md并初始化,同时mmc_queue作为mmc_blk_data的成员也被创建
mmc_blk_data为block的核心结构体,与mmc_card关联,用于存放mmc_card相关数据,每个mmc slot即每个mmc设备对应一个mmc_blk_data结构体。
此处会分配mmc_blk_data结构体md,同时mmc_queue作为mmc_blk_data的成员也被创建。并标识dev_use的bitmap来记录已经分配的mmc device,
也就是说dev_use是与实际的物理设备相对应的,不是跟分区对应的,dev_use的index用dev_idx来记录
注意到此处MMC_BLK_DATA_AREA_MAIN表示主分区的区域(mmc_blk_data与设备对应,此处看又像是与分区对应??)。
MMC分区类型包括如下几种:
#define MMC_BLK_DATA_AREA_MAIN  (1<<0)
#define MMC_BLK_DATA_AREA_BOOT  (1<<1)
#define MMC_BLK_DATA_AREA_GP    (1<<2)
#define MMC_BLK_DATA_AREA_RPMB  (1<<3)(2) alloc_disk(perdev_minors):分配gendisk结构体保存到md中,gendisk与磁盘设备对应(3)mmc_init_queue(queue_c):创建并初始化请求队列
通过调用block子系统接口blk_init_queue来初始化请求队列,其中mmc_request_fn为处理请求的回调函数
blk_queue_prep_rq(mq->queue, mmc_prep_request)设定requet_queue的prep回调函数;
mmc_alloc_sg(host->max_segs, &ret)分配max_segs个scatterlist用于request请求(只是分配scatterlist,并未分配存放数据的内存),
返回分配的scatterlist个数
kthread_run(mmc_queue_thread, mq) 起一个kennel thread运行mmc_queue_thread来处理上层发送下来的request,对每个reqeust执行issue_fn回调注:issue_fn回调在下面指定为mmc_blk_issue_rq
(4)指定issue_fn回调为mmc_blk_issue_rq,mmc_blk_issue_rq是具体的mmc request处理函数

  • mmc_blk_alloc_parts(card, md))

  • mmc_add_disk
为了将一个磁盘添加到系统中,对系统可用,必须初始化磁盘数据结构并调用add_disk方法。
需要特别注意的是一旦调用了add_disk,磁盘就被“激活”了,系统随时都可能会调用该磁盘提供的各种方法,
甚至在该函数返回之前就会调用,因而在完成磁盘结构的初始化之前,不要调用add_disk。

3.4 mmc_add_disk

mmc_add_disk->

  device_add_disk

device_add_disk的原型为void device_add_disk(struct device *parent, struct gendisk *disk) 它完成的工作主要包括:

(1)根据磁盘的主次设备号信息为磁盘分配设备号;

(2)调用disk_alloc_events初始化磁盘的事件(alloc|add|del|release)处理机制。在最开始磁盘事件会被设置为被阻塞的。

(3)调用bdi_register_dev将磁盘注册到bdi_list,注:bdi用于将page_cache或buffer_cache中的脏数据刷新到磁盘

(4)调用blk_register_region将磁盘添加到bdev_map中(通过设备号可以获取kobject从而得到包含它的父对象进行操作)

(5)调用register_disk将磁盘添加到系统中。

(6)调用blk_register_queue注册磁盘的请求队列。主要是为队列和队列的调度器在设备的sys文件系统目录中创建相应的sys目录/文件,并且发出uevent事件。

(7)调用disk_add_events完成在/sys文件系统的设备目录下创建磁盘的事件属性文件,将磁盘事件添加到全局链表disk_events中,解除对磁盘事件的阻塞。

关于probe函数是如何被调用到的?

一般我们认为mmc_blk_probe的执行一定需要mmc_driver与mmc_device的匹配才可以,实际上没有mmc_device,  而是有mmc_card,mmc_blk_probe的执行经历如下历程:

(1)先来看mmc_register_driver的流程

       mmc_register_driver->

              driver_register->

                     driver_find//bus查看driver是否已经注册,如果已经注册则退出,否则bus add driver

                     bus_add_driver->

                            driver_attach->

                                   bus_for_each_dev//此处由于还没有device注册,因此会退出

显然mmc_blk_probe的执行不是在mmc_register_driver的时候,那么肯定是在device_register的时候,看看我们的假设是否正确,继续往下看

(2)mmc_alloc_card, mmc_add_card

通过浏览代码,我们发现在mmc/core/bus_c中有mmc_alloc_card和mmc_add_card

mmc_alloc_card:mmc_attach_mm->mmc_init_card初始化并分配一个新的mmc_card结构体,实际上是创建device设备;

mmc_add_card:mmc_attach_mmc->mmc_add_card时调用,通过调用device_add(&card->dev)来完成设备的注册,过程如下:

              mmc_add_card->

                            device_add->

                                   bus_probe_device->

                                          device_attach->

                                                 __device_attach->

                                                               driver_match_device->

                                                               mmc_bus_match//此函数的特殊之处在于总是返回值为1

                                                        driver_probe_device->

                                                               really_probe->

                                                                      mmc_bus_probe->

                                                                             mmc_blk_probe

mmc_blk_probe的执行不是靠device和driver的匹配,而是将匹配函数mmc_bus_match总是返回1,如下:

static int mmc_bus_match(struct device *dev, struct device_driver *drv)

{

       return 1;

}

这样就可以执行到mmc_bus_type的probe函数进而执行到mmc_blk_probe。

3.5 mmc_queue_thread

线程处理函数,用于循环抓取请求队列中的request并交给请求处理函数进行处理

mmc_queue_thread->

       blk_fetch_request

         issue_fn(mmc_blk_issue_rq)->

             mmc_blk_issue_rw_rq->

                 mmc_blk_rw_rq_prep

                 mmc_start_req –>

                     mmc_wait_for_data_req_done->

                         mmc_blk_err_check

                         host->ops->request

 mmc_queue_thread是在mmc_init_quene中起的线程,主要作用是完成上层发送的请求进行处理

  •  blk_fetch_request
从请求队列中取出一个request
  • issue_fn
由前面可知issue_fn在mmc_blk_probe->mmc_blk_alloc_req时将issue_rq初始化为mmc_blk_issue_rq,请求有几种包括:discard, flush, 以及rw
  • mmc_blk_issue_rw_rq
首先通过mmc_blk_rw_rq_prep来做一些准备工作,获取命令号、命令参数等,然后通过mmc_start_req发起请求
  • mmc_start_req
通过mmc_wait_for_data_req_done发起真正的请求,并等待请求结束。
mmc_wait_for_data_req_done会回调控制器的request函数发起请求,然后mmc_blk_err_check检查是否有错误发生,
如果有错误发生将尝试recovery进行修复开始新的传输

3.6 mmc_blk_issue_rq

mmc_blk_issue_rq->

   mmc_claim_host

  mmc_blk_part_switch

  mmc_blk_issue_rw_rq->

    mmc_blk_prep_packed_list

    mmc_blk_rw_rq_prep

    mmc_start_req->

      __mmc_start_data_req

    mmc_queue_bounce_post

    检查mmc_start_req返回的状态

mmc_blk_issue_rq对发送的mmc request进行具体的处理。

  • mmc_claim_host
实际上是声明当前进程占有host controller,如果有其它进程占有则需要等待,详细的可参考Linux mmc framework2:基本组件之core
  • mmc_blk_part_switch
通过MMC_SWITCH命令对EXT_CSD寄存器的PARTITION_CONFIG(bit[179])进行设置,主要包括boot是否使能、用哪个分区做boot分区、选择要访问的分区。
如果MMC_SWITCH命令出错,将通过blk_end_request_all终止request
  • mmc_blk_issue_rw_rq
根据req->cmd_flags的命令做不同的事情。REQ_SANITIZE、REQ_DISCARD、REQ_FLUSH分别为
. mmc_blk_issue_secdiscard_rq 和mmc_blk_issue_discard_rq
. mmc_blk_issue_flush
. mmc_blk_issue_rw_rq(这个是我们要分析的读写数据流程

1. mmc_blk_prep_packed_list尝试把当前request和队列中的其他request合并,以增强性能。是否可以合并,要依赖于:
控制器支持packed功能;
device的MAX_PACKED_WRITES 大于0;
只对写request进行packed2. mmc_blk_rw_rq_prep:正常情况下执行mmc_blk_rw_rq_prep函数,从request构造mmc_request,毕竟下发给host请求,是mmc_request,而不是block层通用的request。
如果支持packed功能,那么就用pack_list来构造mmc_request3. mmc_start_req:mmc_start_req 启动一个非阻塞的request,这个函数会等待前一个request完成,然后启动当前requeset,并立刻返回
如果mmc_start_req返回的areq不为空,说明完成了上一次的request

  • mmc_start_req
  • mmc_start_req 启动一个非阻塞的request,这个函数会等待前一个request完成,然后启动当前requeset,并立刻返回 如果mmc_start_req返回的areq不为空,说明完成了上一次的request

1. 首先它会执行到mmc_wait_for_data_req_done函数,等待上一次的命令的完成,如果上一次未完成就会将当前进程加入等待队列休眠,等待被唤醒。

   当上一次完成后会立即返回,并将上一次命令执行的状态返回给mmc_blk_issue_rw_rq。

2、if (host->areq) {

    err = mmc_wait_for_data_req_done(host, host->areq->mrq, areq);

host->areq不为空,说明有正在处理的reuqest,函数mmc_wait_for_data_req_done用来等待这个host->areq,有两个条件会唤醒该MMC上下文: is_done_rcv和is_new_req

3. if (!err && areq)      

   start_err = __mmc_start_data_req(host, areq->mrq);

进入__mmc_start_data_req(host, areq->mrq);

(1)首先会将函数指针mmc_wait_data_done赋给mrq->done.

mmc_wait_data_done会设置context_info->is_done_rcv=true,这正好是唤醒mmc_wait_for_data_req_done的条件之一,然后调wake_up_interruptible(&context_info->wait);唤醒之。

(2)然后会调用mmc_start_request(host, mrq);

 mmc_start_reuqest实际调用host->ops->request方法,进入了平台特定的request函数

进入特定的平台之后,会进入相应的中断对硬件进行读写的命令的执行,当命令执行完毕后,会进行函数回调调到刚才的mmc_wait_data_done唤醒等待的进程进行下一次命令的执行。

  •  mmc_queue_bounce_post
如果使用了bounce buffer,那么需要把传输结果从bounce buffer复制会sg buffer。
所谓bounce buffer是因为某些DMA控制器只能处理连续物理内存,此时需要通过bounce buffer来达到物理内存连续性。
  • 检查mmc_start_req返回的状态
1. 如果是MMC_BLK_SUCCESS或者MMC_BLK_PARTIAL,需要调用blk_end_request通知block设备层,完成了本次读写request。
2. 如果是MMC_BLK_CMD_ERR,那么调用mmc_blk_reset复位host。调用mmc_blk_cmd_err尝试blk_end_request,如果发现reuqest未完成,说明本次操作失败,反之成功start_new_req

相关文章:

linux的mmc子系统与块设备关联

1.前言 本文主要block组件的主要流程&#xff0c;在介绍的过程中&#xff0c;将详细说明和block相关的流程&#xff0c;涉及到其它组件的详细流程再在相关文章中说明。 2.主要数据结构和API 2.1 struct mmc_card Elemete Namestruct mmc_cardPathinclude/linux/mmc/card.hRe…...

【Spring MVC】

目录 &#x1f36e;1 什么是 MVC &#xff1f; &#x1f381;2 Spring MVC 的连接 &#x1f358;2.1 RequestMapping 实现 POST 和 GET 请求 &#x1f963;2.2 GetMapping 只支持 GET 请求 &#x1fad6;2.3 PostMapping 只支持 POST 请求 &#x1f36c;3 Spring MVC 获取参数的…...

【ES】笔记-生成器函数与调用

function* function* 这种声明方式 (function关键字后跟一个星号&#xff09;会定义一个生成器函数 (generator function)&#xff0c;它返回一个 Generator 对象。 function * gen(){console.log("heloo generator")}如何调用呢&#xff1f;先看下里面的内容 返回…...

将Spring Boot与Redis集成

一、引言 1、SpringBoot&#xff1a; Spring Boot是一个用于创建独立且可执行的Spring应用程序的框架。它简化了基于Spring框架的应用程序的开发过程&#xff0c;并提供了一种快速和简便的方式来构建Java应用程序。 Spring Boot提供了自动配置机制&#xff0c;通过引入适当的…...

vue echarts

安装 npm i -D echarts使用 <script setup lang"ts"> import * as echarts from echarts import { onMounted } from vueonMounted(() > {interface DataItem {value: [string, number]}let myChart echarts.init(document.getElementById(main))let dat…...

idea上利用JDBC连接MySQL数据库(8.1.0版)

1.了解jdbc概念 JDBC(Java DataBase Connectivity,java数据库连接)是一种用于执行SQL语句的Java API&#xff0c;可以为多种 关系数据库提供统一访问&#xff0c;它由一组用Java语言编写的类和接口组成。JDBC提供了一种基准&#xff0c;据此可以构建 更高级的工具和接口&#…...

【100天精通python】Day47:python网络编程_Web编程基础

目录 1 网络编程与web编程 1.1 网络编程 1.2 web编程 2 Web开发概述 3 Web开发基础 3.1 HTTP协议 3.2 Web服务器 3.3 前端基础 3.4 静态服务器 3.5 前后端交互的基本原理 4 WSGI接口 4.1 CGI 简介 4.2 WSGI 简介 4.3 定义 WSGI 接口 4.4 运行 WSGI 服务 4.5…...

DockerCompose介绍与使用

DockerCompose介绍与使用 1、DockerCompose介绍 DockerCompose用于定义和运行多容器 Docker 应用程序的工具。 通过 Compose可以使用 YAML 文件来配置应用程序需要的所有服务。一个使用Docker容器的应用&#xff0c;通常由多个容器组成&#xff0c;使用Docker Compose不再需要…...

Windows Qt 5.12.10下载与安装

Qt 入门实战教程&#xff08;目录&#xff09; C自学精简实践教程 目录(必读) 1 Qt5.12.10下载 qt-opensource-windows-x86-5.12.10.exe 官方离线安装包 Download Source Package Offline Installers | Qt 下载巨慢&#xff08;也可能很快&#xff09; 只能下载到最新的&…...

RustDesk最新版本编译与打包

本文环境 主要参考&#xff1a; https://www.yuque.com/shikangsi/efy0cp/wei3g1?https://blog.csdn.net/hualuohuakai2014/article/details/121605631 问题 flutter 生成 bridge 文件。 先安装工具&#xff0c;再生成ffi文件。 PS C:\Users\Administrator> cargo ins…...

Gin 框架入门实战系列(一)

GIN介绍 Gin是一个golang的微框架,封装比较优雅,API友好,源码注释比较明确,具有快速灵活,容错方便等特点 对于golang而言,web框架的依赖要远比Python,Java之类的要小。自身的net/http足够简单,性能也非常不错 借助框架开发,不仅可以省去很多常用的封装带来的时间,…...

【测试】pywinauto的简单使用(安装、常用对象、元素控件、鼠标操作、键盘操作)

1.说明 pywinauto是一个用于自动化Python 模块&#xff0c;适合Windows系统的软件&#xff08;GUI&#xff09;&#xff0c;可以通过Pywinauto遍历窗口&#xff08;对话框&#xff09;和窗口里的控件&#xff0c;也可以控制鼠标和键盘输入&#xff0c;所以它能做的事情比之前介…...

Java基础十八(正则表达式 + 日期时间)

1. 正则表达式 1.1 普通字符 字符描述示例[abc]匹配 […] 中所有字符[hlo] 匹配字符串 "hello world" 中所有的 h l o 字母[^ABC]匹配除了 […] 中所有字符[hlo] 匹配字符串 "hello world" 中除了 h l o 的所有字母[^a-z]匹配除了 […] 中所有字符[hlo] 匹…...

Linux C 多进程编程(面试考点)

嵌入式开发为什么要移植操作系统&#xff1f; 1.减小软硬件的耦合度&#xff0c;提高软件的移植性 2. 操作系统提供很多库和工具&#xff08;QT Open CV&#xff09;&#xff0c;提高开发效率 3.操作系统提供多任务机制&#xff0c;______________________? (提高C…...

c++一级

与7无关的数 #include<iostream> #include<iomanip> using namespace std; int main() {   int n,a,sum0,c0;   cin>>n;   for(int i1;i<n;i){     if(i%7!0){       ai;       c0; …...

Code Lab - 34

GAT里面有一些地方看的不是太懂&#xff08;GAT里Multi Attention的具体做法&#xff09;&#xff0c;暂时找了参考代码&#xff0c;留一个疑问 1. 一个通用的GNN Stack import torch_geometric import torch import torch_scatter import torch.nn as nn import torch.nn.fun…...

后端返回文件流,前端怎么导出、下载(8种方法可实现)

在前端导出和下载后端返回的文件流时&#xff0c;可以使用以下几种方法&#xff1a; 使用window.open()方法&#xff1a; 在前端使用window.open()方法打开一个新的窗口或标签页&#xff0c;并将后端返回的文件流作为URL传递给该方法。浏览器会自动下载该文件。例如&#xff1a…...

什么是 ThreadLocal?

ThreadLocal 是 Java 中的一个类,用于在多线程环境下,为每个线程提供独立的变量副本。每个线程可以通过 ThreadLocal 存储和获取数据,而不会影响其他线程的数据。这在某些情况下非常有用,特别是当多个线程需要访问共享数据,但又希望保持数据的隔离性时。 ThreadLocal 主要…...

CANOCO5.0实现冗余分析(RDA)最详细步骤

在地理及生态领域会常使用RDA分析&#xff0c;RDA的实现路径也有很多&#xff0c;今天介绍一下CANOCO软件的实现方法。 1.软件安装 时间调整到2010年 2.数据处理 得有不同的物种或者样点数值&#xff0c;再加上环境因子数据。 3.软件运行 4.结果解读 结果解读主要把握这几点…...

【tkinter 专栏】掷骰子游戏

文章目录 前言本章内容导图1. 需求分析2. 系统功能结构3. 设计流程4. 系统开发环境5. 系统预览6. 窗口布局7. 功能实现用户和电脑选择骰子的点数大小摇骰子过程实现判断游戏结果单击开始按钮进行游戏源代码汇总前言 本专栏将参考《Python GUI 设计 tkinter 从入门到实践》书籍…...

19 NAT穿透|python高级

文章目录 网络通信过程NAT穿透 python高级GIL锁深拷贝与浅拷贝私有化import导入模块工厂模式多继承以及 MRO 顺序烧脑题property属性property装饰器property类属性 魔法属性\_\_doc\_\_\_\_module\_\_ 和 \_\_class\_\_\_\_init\_\_\_\_del\_\_\_\_call\_\_\_\_dict\_\_\_\_str…...

2023常见前端面试题

以下是一些2023年秋招常见的前端面试题及其答案&#xff1a; 1. 请解释一下什么是前端开发&#xff1f; 前端开发是指使用HTML、CSS和JavaScript等技术来构建网页和用户界面的过程。前端开发人员负责将设计师提供的视觉设计转化为可交互的网页&#xff0c;并确保网页在不同设备…...

登录校验-JWT令牌-生成和校验

目录 JWT-生成 具体代码 运行结果如下 JWT-校验 具体代码 运行结果如下 小结 JWT-生成 具体代码 /*** 测试JWT令牌的生成*/Testpublic void TestJWT() {// 设置自定义内容Map<String, Object> claims new HashMap<>();claims.put("id", 1);claims…...

GIT 常用指令

基础指令 $ git init #初始化仓库&#xff0c;在该文件夹创建的为workspace$ git add . #已暂存 [.通配符&#xff0c;全部添加]$ git commit -m "log add file" #提交到仓库,并写了日志 ”log add file“$ git status #查看状态&#xff0c;可查看被修改的文件…...

多目标优化

https://zhuanlan.zhihu.com/p/158705342 概念 单目标优化只有一个优化目标&#xff0c;所以可以比较其好坏。 但是多目标优化&#xff0c;在需要优化多个目标时&#xff0c;容易存在目标之间的冲突&#xff0c;一个目标的优化是以其他目标劣化为代价的&#xff0c;所以我们要…...

odoo的优势

plus&#xff0c;主要是为了能尽早通过开发者审核&#xff0c;加入到chatgpt4 api的开发中去&#xff0c;接入到我们odoo aiCenter中。4的回答&#xff0c;明显比3.5的更聪明了。 可能是由于国内的特殊情况吧&#xff0c;我们的chatgpt模块很受欢迎&#xff0c;我也被问了不少…...

Spring Boot(Vue3+ElementPlus+Axios+MyBatisPlus+Spring Boot 前后端分离)【三】

&#x1f600;前言 本篇博文是关于Spring Boot(Vue3ElementPlusAxiosMyBatisPlusSpring Boot 前后端分离)【三】的分享&#xff0c;希望你能够喜欢 &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我…...

Kali 软件管理

kali 更新 1. 查看发行版本 ┌──(root㉿kali)-[~] └─# lsb_release -a No LSB modules are available. Distributor ID: Kali Description: Kali GNU/Linux Rolling Release: 2023.2 Codename: kali-rolling2. 查看内核版本 ┌──(root㉿kali)-[~] └─…...

加油站【贪心算法】

加油站 在一条环路上有 n 个加油站&#xff0c;其中第 i 个加油站有汽油 gas[i] 升。 你有一辆油箱容量无限的的汽车&#xff0c;从第 i 个加油站开往第 i1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发&#xff0c;开始时油箱为空。 给定两个整数数组 gas 和…...

java八股文面试[多线程]——死锁、活锁、饥饿

DCL双重锁&#xff1a;TODO 如何预防死锁&#xff1a; 如何查看线程死锁&#xff1a; 知识来源&#xff1a; 【2023年面试】描述一下线程安全活跃态问题&#xff0c;以及竞态条件_哔哩哔哩_bilibili 【2023年面试】如何预防死锁_哔哩哔哩_bilibili 【并发与线程】阿里一面&…...

设计模式——装饰器模式

装饰器模式 装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其结构。这种类型的设计模式属于结构型模式&#xff0c;它是作为现有的类的一个包装。 装饰器模式通过将对象包装在装饰器类中&#xff0c;以便动态…...

①matlab的命令掌握

目录 输入命令 命名变量 保存和加载变量 使用内置的函数和常量 输入命令 1.您可以通过在命令行窗口中 MATLAB 提示符 (>>) 后输入命令 任务 使用命令 3*5 将数值 3 和 5 相乘。 答案 3*5 2.除非另有指定&#xff0c;否则 MATLAB 会将计算结果存储在一个名为 ans…...

MySQL----索引

一、索引的概念 索引是一个排序的列表&#xff0c;在这个列表中存储着索引的值和包含这个值的数据所在行的物理地址&#xff08;类似于c语言的链表通过指针指向数据记录的内存地址&#xff09;。使用索引后可以不用扫描全表来定位某行的数据&#xff0c;而是先通过索引表找到该…...

秒杀系统的业务流程以及优化方案(实现异步秒杀)

先看基本的业务流程 那么我们可以看到整个流程都是一个线程来完成的&#xff0c;这样的话耗时还是很长的&#xff0c;那么可不可以采用多线程去实现呢&#xff1f; 首先我们要思考怎么对业务进行拆分&#xff0c;可以想象一个我们去饭店点餐&#xff0c;会有前台接待&#xff…...

Java实现根据商品ID获取1688商品详情跨境属性数据,1688商品重量数据接口,1688API接口封装方法

要通过1688的API获取商品详情跨境属性数据&#xff0c;您可以使用1688开放平台提供的接口来实现。以下是一种使用Java编程语言实现的示例&#xff0c;展示如何通过1688开放平台API获取商品详情属性数据接口&#xff1a; 首先&#xff0c;确保您已注册成为1688开放平台的开发者…...

前端面试的性能优化部分(14)每天10个小知识点

目录 系列文章目录前端面试的性能优化部分&#xff08;1&#xff09;每天10个小知识点前端面试的性能优化部分&#xff08;2&#xff09;每天10个小知识点前端面试的性能优化部分&#xff08;3&#xff09;每天10个小知识点前端面试的性能优化部分&#xff08;4&#xff09;每天…...

Uniapp笔记(六)uniapp基础

一、腾讯地图 1、uniapp地图渲染 <template><view><map class"map" :longitude"longitude" :latitude"latitude"></map></view> </template> <script>export default {data() {return {longitude:1…...

C++ sort函数用法

sort函数是C标准库中的一个排序算法&#xff0c;头文件是algorithm&#xff0c;用于对容器中的元素进行排序。它可以对任何可排序的容器&#xff08;如数组、向量、列表等&#xff09;进行排序。 有以下四个基本用法&#xff1a; 1. 自定义排序规则&#xff1a;可以通过提供自…...

电子仓库预测水浸事件,他怎么做到的?

仓库环境中水浸事件可能导致严重的损失&#xff0c;不仅对货物造成损害&#xff0c;还可能影响设备的正常运行甚至威胁安全。 因此&#xff0c;为了应对这一挑战&#xff0c;引入一套完善的仓库水浸监控系统成为了不可或缺的措施。 客户案例 广东某电子公司是一家领先的电子设…...

CMake调用第三方库的两种方法

为了让连接器搜索到库路径&#xff0c;一般有两种方法 link_directories命令 使用步骤## 在add_executable或add_library前引入第三方库 # 1.引入第三方库,${THIRD_PARTY_PREFIX}为用户定义的第三方库目录 link_directories(${THIRD_PARTY_PREFIX}/lib) # 2.增加第三方库头文…...

Django基础7——用户认证系统、Session管理、CSRF安全防护机制

文章目录 一、用户认证系统二、案例&#xff1a;登陆认证2.1 平台登入2.2 平台登出2.3 login_required装饰器 三、Django Session管理3.1 Django使用Session3.1.1 Cookie用法3.1.2 Session用法 3.2 案例&#xff1a;用户登录认证 四、Django CSRF安全防护机制 一、用户认证系统…...

基于流计算 Oceanus(Flink) CDC 做好数据集成场景

由于第一次做实时&#xff0c;所以踩坑比较多&#xff0c;见谅(测试环境用的flink),小公司没有用到hadoop组件 一、踩坑记录 1:本地代码的flink版本是flink1.15.4&#xff0c;生产环境是flink1.16.1&#xff0c;在使用侧输出流时报错&#xff0c;需要使用以下写法,需要使用Si…...

MySQL8.Xx安装控制台未生成随机密码解决方案

MySQL8.xx一主两从复制安装与配置 MySQL8.XX随未生成随机密码解决方案 MySQL8.0.30一主两从复制与配置(一) 一: Mysql 安装时控制台未生成密码 安装过程中解压或者安装时报错等,这种情况一般是因网络等其他原因导致下载的安装包不完整&#xff0c; 重新下载安装即可; 二:…...

安装VS2005时提示:请插入磁盘:visual studio 2005 DVD

安装VS2005时提示&#xff1a;请插入磁盘:visual studio 2005 DVD 修改卷标为 "DVD1"...

OpenVINO2023使用简介

1 下载安装 先在anaconda中创建一个虚拟环境&#xff0c;该环境的python版本为3.7&#xff0c;之所以使用python3.7&#xff0c;是因为我在3.9上安装过程中出现不少bug&#xff0c;后面新建了一个3.7的环境才解决&#xff0c;我不知道是否由于和我已有环境中某些包不兼容&…...

基于React实现无限滚动的日历详细教程,附源码【手写日历教程第二篇】

前言 最常见的日历大部分都是滚动去加载更多的月份&#xff0c;而不是让用户手动点击按钮切换日历月份。滚动加载的交互方式对于用户而言是更加丝滑和舒适的&#xff0c;没有明显的操作割裂感。 那么现在需要做一个这样的无限滚动的日历&#xff0c;前端开发者应该如何去思考…...

68、使用aws官方的demo和配置aws服务,进行视频流上传播放

基本思想:参考官方视频,进行了配置aws,测试了视频推流,rtsp和mp4格式的视频貌似有问题,待调研和解决 第一步:1) 进入aws的网站,然后进入ioT Core 2)先配置 Thing types & Thing,选择香港的节点,然后AWS ioT--->Manage---> Thing type 然后输入名字,创建Th…...

数据库

表 记录&#xff1a;行 字段&#xff08;属性&#xff09;: 列 以行列的形式就组成了表&#xff08;数据存储在表中&#xff09; 关系数据库的表由记录组成&#xff0c;记录由字段组成&#xff0c;字段由字符或数字组成。它可以供各种用户共享&#xff0c; 具有最小冗余度和较高…...

深入了解fcntl函数:Linux系统编程中的文件控制

文章目录 概述介绍函数原型与参数 拓展&#xff1a;fcntl改文件属性总结 概述 摘要: fcntl函数是Linux系统编程中一个重要的函数&#xff0c;用于对文件描述符进行各种控制操作。本文将详细介绍fcntl函数的原型、各个参数的用法&#xff0c;以及阻塞和非阻塞模式切换的方法&am…...

汇川技术内推码

[庆祝]不一样的内推码[庆祝]&#xff1a;IVSM2R 投递了可以评论下名字&#xff0c;我会帮忙留意进度。 汇尔成川&#xff0c;共赴星海&#xff0c;欢迎加入&#xff0c;职等你来。 嵌入式软硬件&#xff0c;机器人算法&#xff0c;电机控制&#xff0c;通信软件&#xff0c;PLC…...