ais_server 学习笔记

ais_server 学习笔记

  • 一前序
  • 二、ais init
    • 1、时序图如下
    • 2. 初始化一共分为以下几个重要步骤:
      • 2.1.1、在ais_server中启动main函数,然后创建AisEngine,接着初始化AisEngine
      • 2.1.2、解析/var/camera_config.xml 文件,获取相关配置参数。这个camera_config.xml 后面会细聊
      • 2.1.3、启动EventHandler线程,会启动四个EventHandler,来承接外面调回来的通知,比如FRAME_DONE、FATAL_ERROR等等, 至于为什么是四个EventHandler,我猜测可能是一个CSIPHY 对应一个 Thread handler吧。
      • 2.1.4、"加载" sensor so、CSIPHY 、IFE
      • 2.1.5、接着会根据前面解析的camera_config.xml 里面的配置来给input、ife、csiphy 里面的参数进行配置,在csiphy里面会进行mipi协议的一些配置, 配置好mipiconfig 后就会去 start mipi
      • 2.1.6、启动平台图像处理等功能
  • 三、amera_client -> qcarcam_initialize
  • 四、camera_client -> qcarcam_open
  • 五、camera_client -> qcarcam_s_param
  • 六、camera_client -> qcarcam_start
  • 七、camera_client -> qcarcam_get_frame

一前序

ais server 的主要功能,简单理解就是高通平台用于使能相机模块,处理camera 数据,并在camera client连接的时候将camera数据顺利给到client。

我们还是从ais的init,然后client调用接口,init、open、s_param、start、get_frame、release_frame、stop、close、deinit聊起, 每个调用都会有对应的时序图。

二、ais init

1、时序图如下

在这里插入图片描述

2. 初始化一共分为以下几个重要步骤:

2.1.1、在ais_server中启动main函数,然后创建AisEngine,接着初始化AisEngine

2.1.2、解析/var/camera_config.xml 文件,获取相关配置参数。这个camera_config.xml 后面会细聊

<?xml version="1.0" encoding="UTF-8"?><!--Copyright (c) 2020 Qualcomm Technologies, Inc.All Rights Reserved.Confidential and Proprietary - Qualcomm Technologies, Inc.--><!-- THIS IS A SAMPLE CAMERA CONFIG XML TO ILLUSTRATE HOW IT CAN BE USED --><!--SA8155 SAMPLE
=========================================================================== */
/*              CSI     lanes   IFEs   I2C Port    Sensors* max96716    2        4      2    /dev/cci1    2 x 96717 YUV SENSORS
*/
--><CameraConfig version="0x403"><board name="SA8155_ADP" boardType="CAMERA_HW_BOARD_ADPAIR_V2_PL195" multiSocEnable="0"><i2cDevs><i2cDev name="cci0"><properties i2ctype = "CAMERA_I2C_TYPE_CCI" device_id = "0" port_id = "0"/><sda_pin gpio = "17" function = "1"/><scl_pin gpio = "18" function = "1"/></i2cDev><i2cDev name="cci1"><properties i2ctype = "CAMERA_I2C_TYPE_CCI" device_id = "0" port_id = "1"/><sda_pin gpio = "19" function = "1"/><scl_pin gpio = "20" function = "1"/></i2cDev><i2cDev name="cci2"><properties i2ctype = "CAMERA_I2C_TYPE_CCI" device_id = "1" port_id = "0"/><sda_pin gpio = "31" function = "1"/><scl_pin gpio = "32" function = "1"/></i2cDev></i2cDevs><inputDevs><inputDev devId = "0"><properties><!-- 2 AR0231 Bayer Sensor --><config subdevId = "0" type="1" numSensors="1" pmasterSocId="0" socMap="1" opMode="0" /><sensor link="0" type="1" /></properties><driverInfo devCategory = "CAMERA_DEVICE_CATEGORY_SENSOR" libName="ais_nio_max96716f" openFcn="CameraSensorDevice_Open_max96716"/><i2cPort soc_id = "0" i2ctype = "CAMERA_I2C_TYPE_CCI" device_id = "0" port_id = "1" /><csiInfo csiId = "0" numLanes = "2" laneAssign = "0x10" numIfeMap="1" ifeMap="0x0" /><gpio id = "CAMERA_GPIO_RESET" num = "22" config = "0x31"/><intr id = "CAMERA_GPIO_INTR" pin_id = "106" intr_type = "CAMERA_GPIO_INTR_TLMM" trigger = "CAMERA_GPIO_TRIGGER_FALLING" gpio_cfg = "0x30"/></inputDev><inputDev devId = "1"><properties><!-- 2 AR0231 Bayer Sensor --><config subdevId = "1" type="1" numSensors="4" pmasterSocId="0" socMap="1" opMode="0" /><sensor link="0" type="1" /><sensor link="1" type="1" /><sensor link="2" type="1" /><sensor link="3" type="1" /></properties><driverInfo devCategory = "CAMERA_DEVICE_CATEGORY_SENSOR" libName="ais_nio_max96722" openFcn="CameraSensorDevice_Open_max96722"/><i2cPort soc_id = "0" i2ctype = "CAMERA_I2C_TYPE_CCI" device_id = "1" port_id = "0" /><csiInfo csiId = "3" numLanes = "4" laneAssign = "0x3210" ifeMap="0x32" numIfeMap="2"/><gpio id = "CAMERA_GPIO_RESET" num = "25" config = "0x31"/><intr id = "CAMERA_GPIO_INTR" pin_id = "13" intr_type = "CAMERA_GPIO_INTR_TLMM" trigger = "CAMERA_GPIO_TRIGGER_FALLING" gpio_cfg = "0x30"/><intr id = "CAMERA_GPIO_LOCK" pin_id = "15" intr_type = "CAMERA_GPIO_INTR_TLMM" trigger = "CAMERA_GPIO_TRIGGER_FALLING" gpio_cfg = "0x30"/><intr id = "CAMERA_GPIO_PASS" pin_id = "90" intr_type = "CAMERA_GPIO_INTR_TLMM" trigger = "CAMERA_GPIO_TRIGGER_EDGE" gpio_cfg = "0x10"/><intr id = "CAMERA_GPIO_CUSTOM1" pin_id = "149" intr_type = "CAMERA_GPIO_INTR_TLMM" trigger = "CAMERA_GPIO_TRIGGER_FALLING" gpio_cfg = "0x30"/><intr id = "CAMERA_GPIO_CUSTOM2" pin_id = "150" intr_type = "CAMERA_GPIO_INTR_TLMM" trigger = "CAMERA_GPIO_TRIGGER_FALLING" gpio_cfg = "0x30"/><intr id = "CAMERA_GPIO_CUSTOM_REG1" pin_id = "151" intr_type = "CAMERA_GPIO_INTR_TLMM" trigger = "CAMERA_GPIO_TRIGGER_FALLING" gpio_cfg = "0x30"/><intr id = "CAMERA_GPIO_CUSTOM_REG2" pin_id = "152" intr_type = "CAMERA_GPIO_INTR_TLMM" trigger = "CAMERA_GPIO_TRIGGER_FALLING" gpio_cfg = "0x30"/></inputDev><inputDev devId = "2"><properties><!-- 2 AR0231 Bayer Sensor --><config subdevId = "0" type="1" numSensors="3" pmasterSocId="0" socMap="1" opMode="0" /><sensor link="0" type="1" /><sensor link="1" type="1" /><sensor link="2" type="1" /></properties><driverInfo devCategory = "CAMERA_DEVICE_CATEGORY_SENSOR" libName="ais_nio_svc_fy" openFcn="CameraSensorDevice_Open_max96712"/><i2cPort soc_id = "0" i2ctype = "CAMERA_I2C_TYPE_CCI" device_id = "0" port_id = "0" /><csiInfo csiId = "2" numLanes = "4" laneAssign = "0x3210" ifeMap="0x1" numIfeMap="1"/></inputDev></inputDevs><engineSettings numBufMax="12" powerManagementPolicy="CAMERA_PM_POLICY_LPM_EVENT_ALL" latencyMeasurementMode="CAMERA_LM_MODE_DISABLE"recoveryRestartDelay="33"  recoveryTimeoutAfterUsrCtxtRestart="500" recoveryRetryDelay="300" recoveryMaxNumAttempts="1"><inputFatalError type="MATCH_INPUT_DEVICE" severity="0"/><csidFatalError type="MATCH_IFE_DEVICE" severity="0"/><ifeOutputError type="MATCH_IFE_DEVICE" severity="0"/></engineSettings></board><inputMapping><inputMap qcarcamId = "1" opMode = "QCARCAM_OPMODE_RAW_DUMP"><inputSrc devId = "0" srcId = "0"/></inputMap><inputMap qcarcamId = "2" opMode = "QCARCAM_OPMODE_RAW_DUMP"><inputSrc devId = "2" srcId = "2"/></inputMap><inputMap qcarcamId = "3" opMode = "QCARCAM_OPMODE_RAW_DUMP"><inputSrc devId = "2" srcId = "0"/></inputMap><inputMap qcarcamId = "4" opMode = "QCARCAM_OPMODE_RAW_DUMP"><inputSrc devId = "2" srcId = "1"/></inputMap><inputMap qcarcamId = "5" opMode = "QCARCAM_OPMODE_RAW_DUMP"><inputSrc devId = "1" srcId = "0"/></inputMap><inputMap qcarcamId = "6" opMode = "QCARCAM_OPMODE_RAW_DUMP"><inputSrc devId = "1" srcId = "1"/></inputMap><inputMap qcarcamId = "7" opMode = "QCARCAM_OPMODE_RAW_DUMP"><inputSrc devId = "1" srcId = "2"/></inputMap><inputMap qcarcamId = "8" opMode = "QCARCAM_OPMODE_RAW_DUMP"><inputSrc devId = "1" srcId = "3"/></inputMap></inputMapping>
</CameraConfig>

2.1.3、启动EventHandler线程,会启动四个EventHandler,来承接外面调回来的通知,比如FRAME_DONE、FATAL_ERROR等等, 至于为什么是四个EventHandler,我猜测可能是一个CSIPHY 对应一个 Thread handler吧。

在这里插入图片描述在这里插入图片描述

2.1.4、“加载” sensor so、CSIPHY 、IFE

分别会调用RegisterDeviceFromLib()、RegisterDevice()将libais_nio_*.so 和 IFE 、CSIPHY open

static CameraDeviceManagerRegisteredType sStaticDevicesSA8155[] =
{
#ifndef AIS_WITH_HAL_CAMERA{{CAMERADEVICEID_IFE_0, CAMERA_DEVICE_CATEGORY_IFE}, ife_device_open},{{CAMERADEVICEID_IFELITE_1, CAMERA_DEVICE_CATEGORY_IFE}, ifelite_device_open},
#endif{{CAMERADEVICEID_IFE_1, CAMERA_DEVICE_CATEGORY_IFE}, ife_device_open},{{CAMERADEVICEID_IFELITE_0, CAMERA_DEVICE_CATEGORY_IFE}, ifelite_device_open},{{CAMERADEVICEID_CSIPHY_0, CAMERA_DEVICE_CATEGORY_CSIPHY}, csiphy_device_open},{{CAMERADEVICEID_CSIPHY_1, CAMERA_DEVICE_CATEGORY_CSIPHY}, csiphy_device_open},{{CAMERADEVICEID_CSIPHY_2, CAMERA_DEVICE_CATEGORY_CSIPHY}, csiphy_device_open},{{CAMERADEVICEID_CSIPHY_3, CAMERA_DEVICE_CATEGORY_CSIPHY}, csiphy_device_open},
};
这里继续调用到RegisterDevice,将
libais_nio_max96722.so -> CameraSensorDevice_Open_max96722
libais_nio_svc_fy.so -> CameraSensorDevice_Open_max96712
libais_nio_max96716f.so -> CameraSensorDevice_Open_max96716
保存在registeredDevices中
CameraSensorDevice_Open_max96722 -> max96722_sensor_open_lib()
CameraSensorDevice_Open_max96712 -> max96712_sensor_open_lib()
CameraSensorDevice_Open_max96716 -> max96716_sensor_open_lib()

创建AisInputConfigurer、AisIFEConfigurer、AisCSIConfigurer,然后init他们三个,在init中分别调用DeviceOpen方法,最终会调用到CameraSensorDevice_Open_max967*、 ife_device_open、csiphy_device_open。
ife_device_open 和 ifelite_device_open 分别会被调用两次,每次都会创建一个VFE/CSID(IFE持有VFE和CSID) 对象,ife_device_open 和 ifelite_device_open的取别主要在于RDI的个数,前者会有四个RDI通道,后者会有三个RDI通道。
在这里插入图片描述
CSID和IFE分别在创建的时候对应一个线程,分别open四次就会有四个线程,这个四个线程用于监听中断和其他消息通知,后面会用到
在这里插入图片描述

2.1.5、接着会根据前面解析的camera_config.xml 里面的配置来给input、ife、csiphy 里面的参数进行配置,在csiphy里面会进行mipi协议的一些配置, 配置好mipiconfig 后就会去 start mipi

在这里插入图片描述

2.1.6、启动平台图像处理等功能

在这里插入图片描述当ais完全启动后,后续将从client端使用的角度来分析,ais_server对应的每一步处理

三、amera_client -> qcarcam_initialize

Camera client和ais_server是通过libais_client进行通信的,如果是client是在qnx 则通过socket,如果client是在

android侧,则通过hab(也是基于共享内存封装的类socket机制)
Camera client 开始使用的时候首先要调用接口qcarcam_initialize, 首先会调用到ais_client中,会为这个camera分配一个s_ais_client变量,然后再建立该camera client和ais_server(ais_client 是camera client和ais_server之间的桥梁)之间的心跳机制

这里注意sgs_ais_client数组最大值是64,意味着最多同时可以连接64个client,但是这里有个奇怪的点,就是我们可以open的camera个数其实和rdi有关系?

–> 所以答案是:
### 三级目录
每个camera client qcarcam_initialize之后都会有个心跳线程
在这里插入图片描述

四、camera_client -> qcarcam_open

camera_client 调用qcarcam_open到AisEngine 中这里并没有对IFE、INPUT、CSI做什么操作,只是为这个open的camera分配了一个属于,camera_client和ais_server 识别这个camera的唯一标识句柄qcarcam_hndl
在这里插入图片描述

五、camera_client -> qcarcam_s_param

这里client会为每个camera申请5个buffer(MIN_USR_NUMBER_OF_BUFFERS 3 <buffer < QCARCAM_MAX_NUM_BUFFERS 12)

在这里插入图片描述
将client传过来的buffer地址和ais_server中的buffer做内存映射

smmu_map_pt_v2 函数可能用于将物理地址(DA, Device Address)映射到虚拟地址空间,具体是通过系统的 SMMU(System Memory Management Unit,系统内存管理单元)进行的,这里就简单理解camera_client buffer和ais_server的buffer做了映射,然后ais_server的buffer又绑定了一块专门用于camera data传输的内存。
在这里插入图片描述
在这里插入图片描述
如上log分析,handle 就是camera_client buffer的地址,DA就是做完映射后,ais_server使用的buffer地址,我们打开了四个camera,每个camera申请了5个buffer。

根据环视的camera_config.xml 配置,当有camera_client连接ais_server的时候,会优先给该camera分配IFE2,然后当IFE2的四个RDI都占用后,再连接的时候就分配IFE3的RDI

在这里插入图片描述如下图,CSID2 对应的 IFE就可以理解为IFE2、CSID3 对应的IFE就可以理解为IFE3,他们IFE都是Lite模式四路数据传输线。

在这里插入图片描述
这个后面camera data传递的时候会深入讨论

六、camera_client -> qcarcam_start

在这里插入图片描述
如上时序图,camera_client的start操作,其实主要针对的就是ais_input_configurer, CISPHY已经在ais_server初始化的时候已经start过了,然后根据先后顺序会start IFE 中的VFE/CISD,然后会start camera sensor, 这里我们用的摄像头加串器是96716/解串器是96722。

在96722sensor中 ,max96722_sensor_open_lib的时候,

    memcpy(&pCtxt->sensor_lib, &sensor_lib_ptr, sizeof(pCtxt->sensor_lib));memcpy(&pCtxt->max96722_sensors, max96722_sensors_init_table, sizeof(pCtxt->max96722_sensors));
static max96722_sensor_info_t max96722_sensors_init_table[] =
{{.state = SENSOR_STATE_INVALID,.serializer_addr = MSM_DES_0_ADDR_CAM_SER_0,.sensor_addr = MSM_DES_0_ADDR_CAM_SNSR_0,},{.state = SENSOR_STATE_INVALID,.serializer_addr = MSM_DES_0_ADDR_CAM_SER_1,.sensor_addr = MSM_DES_0_ADDR_CAM_SNSR_1,},{.state = SENSOR_STATE_INVALID,.serializer_addr = MSM_DES_0_ADDR_CAM_SER_2,.sensor_addr = MSM_DES_0_ADDR_CAM_SNSR_2,},{.state = SENSOR_STATE_INVALID,.serializer_addr = MSM_DES_0_ADDR_CAM_SER_3,.sensor_addr = MSM_DES_0_ADDR_CAM_SNSR_3,},
};
static sensor_lib_t sensor_lib_ptr =
{.sensor_slave_info ={.sensor_name = SENSOR_MODEL,.slave_addr = MSM_DES_0_SLAVEADDR,.i2c_freq_mode = SENSOR_I2C_MODE_CUSTOM,.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_BYTE_DATA,.sensor_id_info ={.sensor_id_reg_addr = 0x00,.sensor_id = MSM_DES_0_SLAVEADDR,.sensor_id_mask = 0xff00,},.power_setting_array ={.power_up_setting_a ={{.seq_type = CAMERA_POW_SEQ_VREG,.seq_val = CAMERA_VDIG,.config_val = 0,.delay = 1,},{.seq_type = CAMERA_POW_SEQ_GPIO,.seq_val = CAMERA_GPIO_RESET,.config_val = GPIO_OUT_LOW,.delay = 10,},{.seq_type = CAMERA_POW_SEQ_GPIO,.seq_val = CAMERA_GPIO_RESET,.config_val = GPIO_OUT_HIGH,.delay = 100,},},.size_up = 3,.power_down_setting_a ={{.seq_type = CAMERA_POW_SEQ_GPIO,.seq_val = CAMERA_GPIO_RESET,.config_val = GPIO_OUT_LOW,.delay = 0,},},.size_down = 1,},.is_init_params_valid = 1,},.csi_params ={{.lane_cnt = 4, /*4 lane mode is selected */.settle_cnt = 0xE,.lane_mask = 0x1F,.combo_mode = 0,.is_csi_3phase = 0,}},.sensor_close_lib = max96722_sensor_close_lib,.sensor_capability = 0,/*custom functions that were defined in the driver */.sensor_custom_func ={.sensor_set_platform_func_table = &max96722_sensor_set_platform_func_table,.sensor_power_suspend = &max96722_sensor_power_suspend,.sensor_power_resume = &max96722_sensor_power_resume,.sensor_detect_device = &max96722_sensor_detect_device,.sensor_detect_device_channels = &max96722_sensor_detect_device_channels,.sensor_init_setting = &max96722_sensor_init_setting,.sensor_set_channel_mode = &max96722_sensor_set_channel_mode,.sensor_start_stream = &max96722_sensor_start_stream,.sensor_stop_stream = &max96722_sensor_stop_stream,.sensor_s_param = &max96722_des_sensor_s_param,.sensor_g_param = &max96722_des_sensor_g_param,//.sensor_power_on = &max96722_sensor_power_on,},.use_sensor_custom_func = TRUE,
};

如上代码所示,在open的时候就将sensor_lib_ptr和max96722_sensors_init_table copy给了sensor_lib和max96722_sensors,后面对于camera寄存器的读写都操作sensor_lib_ptr,对于加/解串操作max96722_sensors,
max96722_sensor_start_stream() -> ser96717_start_link() -> i2c_slave_write_array(max96722_sensors->serializer_addr, cam_ser_reg_setting), 这里96722/96716对应的解串器都是96717,这里做了统一化处理,包括来自J5的摄像头也是定义了一个96717的解串器名字
在这里插入图片描述

七、camera_client -> qcarcam_get_frame

当ais_server 准备好camera data后就会通知camera_client去使用camera data,大致时序如下:
在这里插入图片描述
在这里插入图片描述
如上时序图,VFE中的camera data流转过程:
1、在VEF模块初始化的时候,会注册函数ifeIST()到CameraPlatformISTInit中,在CameraPlatformISTInit中会启动一个线程CameraIST,会专门用于监听中断, 然后回调ifeIST().
2、ifeIST() -> ProcessIST() -> CameraSetSignal(m_ifeIstProcThreadContext.evIfeIstNotification) -> ISTWorkerThread(), 回调到 ifeIST() 之后会间接的唤醒等待的函数ISTWorkerThread ->
CameraWaitOnSignal(pIfeCtx->m_ifeIstProcThreadContext.evIfeIstNotification), 然后会紧接着调用
ProcessISTQueueItem(), 将填充好sQueueItem的根据中断类型执行相应的操作:
ProcessResetIRQ(): 触发重启VFE中断
ProcessSofIRQ(): camera data从硬件缓冲区到内存,将client申请的buffer映射出来的软件缓冲区提交到硬件缓冲区,去填充camera data
ProcessWrBusIRQ(): 软件缓冲区数据填满后就会触发中断,通知去消费数据
ProcessOverflowIRQ(): 将IFE、MIPI相关的error, waring 通知到camera client端。

如上都是基于学习的精神做的笔记,若有错误的地方请大佬们多多指正。

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

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

相关文章

L1G3000 任务-浦语提示词工程

基础任务 (完成此任务即完成闯关) 背景问题&#xff1a;近期相关研究指出&#xff0c;在处理特定文本分析任务时&#xff0c;语言模型的表现有时会遇到挑战&#xff0c;例如在分析单词内部的具体字母数量时可能会出现错误。任务要求&#xff1a;利用对提示词的精确设计&#xf…

Unity之一键创建自定义Package包

内容将会持续更新&#xff0c;有错误的地方欢迎指正&#xff0c;谢谢! Unity之一键创建自定义Package包 TechX 坚持将创新的科技带给世界&#xff01; 拥有更好的学习体验 —— 不断努力&#xff0c;不断进步&#xff0c;不断探索 TechX —— 心探索、心进取&#xff01; …

Redis开发04:Redis的INFO信息解析

命令解释redis_versionRedis 的版本号&#xff0c;这里是 3.2.100。redis_git_sha1Redis 使用的 Git SHA1 校验值&#xff0c;表示当前代码的版本。redis_git_dirty如果 Redis 当前运行的代码是脏版本&#xff08;未提交的修改&#xff09;&#xff0c;该值为 1&#xff0c;否则…

python的Flask框架使用

python的Flask框架使用 python环境搭建conda安装python自带的虚拟环境&#xff1a;venv python环境搭建 官网地址 点击downloads 选择你需要的版本&#xff0c;我这里使用的3.12.6 选择Windows installer (64-bit) 选择自定义安装&#xff0c;勾选以管理员权限安装&#xff0…

网络原理(一)—— http

什么是 http http 是一个应用层协议&#xff0c;全称为“超文本传输协议”。 http 自 1991 年诞生&#xff0c;目前已经发展为最主流使用的一种应用层协议。 HTTP 往往基于传输层的 TCP 协议实现的&#xff0c;例如 http1.0&#xff0c;http1.0&#xff0c;http2.0 http3 是…

CTF之密码学(Polybius密码)

棋盘密码&#xff0c;也称为Polybius密码或方格密码&#xff0c;是一种基于替换的加密方法。以下是对棋盘密码的详细解析&#xff1a; 一、加密原理 棋盘密码使用一个5x5的方格棋盘&#xff0c;其中填充了26个英文字母&#xff08;通常i和j被视为同一个字母并放在同一个格子中…

二刷代码随想录第16天

513. 找树左下角的值 找到深度最大的点&#xff0c;遍历方式左边节点在右边节点前面&#xff0c;找到就返回&#xff0c;一定就是最左下角的值了 class Solution { public:int max_depth -1;int result 0;int findBottomLeftValue(TreeNode* root) {traversal(root, 0);ret…

Dockerfile docker-compose

1、Dockerfile # 使用官方的Python作为基础镜像 FROM python:3.9 # 设置工作目录 WORKDIR /app # 复制当前目录下的所有文件到容器的工作目录中 COPY . /app # 安装所需的Python库 #RUN pip install --no-cache-dir -r requirements.txt # 复制 requirements.txt 并安装依赖…

103.【C语言】数据结构之建堆的时间复杂度分析

1.向下调整的时间复杂度 推导 设树高为h 发现如下规律 按最坏的情况考虑(即调整次数最多) 第1层,有个节点,最多向上调整h-1次 第2层,有个节点,最多向上调整h-2次 第3层,有个节点,最多向上调整h-3次 第4层,有个节点,最多向上调整h-4次 ... 第h-1层,有个节点,最多向上调整1次 第…

用Python爬虫“偷窥”1688商品详情:一场数据的奇妙冒险

引言&#xff1a;数据的宝藏 在这个信息爆炸的时代&#xff0c;数据就像是一座座等待挖掘的宝藏。而对于我们这些电商界的探险家来说&#xff0c;1688上的商品详情就是那些闪闪发光的金子。今天&#xff0c;我们将化身为数据的海盗&#xff0c;用Python这把锋利的剑&#xff0…

Python基础学习-12匿名函数lambda和map、filter

目录 1、匿名函数&#xff1a; lambda 2、Lambda的参数类型 3、map、 filter 4、本节总结 1、匿名函数&#xff1a; lambda 1&#xff09;语法&#xff1a; lambda arg1, arg2, …, argN : expression using arg 2&#xff09; lambda是一个表达式&#xff0c;而不是一个语…

速盾高防cdn支持移动端独立缓存

随着移动互联网的快速发展&#xff0c;移动端网页访问量也越来越大。然而&#xff0c;移动端的网络环境相对不稳定&#xff0c;用户体验可能会受到影响。因此&#xff0c;使用高防CDN来加速移动端网页访问&#xff0c;成为越来越多网站运营者的首选。 速盾高防CDN是一种分布式…

【JavaEE初阶 — 网络编程】TCP流套接字编程

TCP流套接字编程 1. TCP &#xff06; UDP 的区别 TCP 的核心特点是面向字节流&#xff0c;读写数据的基本单位是字节 byte 2 API介绍 2.1 ServerSocket 定义 ServerSocket 是创建 TCP 服务端 Socket 的API。 构造方法 方法签名 方法说明 ServerS…

idea新建springboot web项目

idea新建springboot web项目 写在前面开始项目结构定义依赖初始化创建完成修复配置文件内容乱码修改配置文件名称更新配置文件内容为yml格式 配置项目启动项启动项目 写在前面 以下操作以IntelliJ IDEA 2022.3.3版本为例&#xff0c;其他版本应该大体相似。 开始 项目结构定义…

Docker 容器网络创建网桥链接

一、网络:默认情况下,所有的容器都以bridge方式链接到docker的一个虚拟网桥上; 注意:“172.17.0.0/16”中的“/16”表示子网掩码的长度为16位,它表示子网掩码中有16个连续的1,后面跟着16个连续的0。用于区分IP地址中的网络部分和主机部分; 二、为何自定义网络? 加入自…

智能产品综合开发 - 温湿度检测

1 实训选题目的 本次实训选择的题目是“温湿度检测系统”&#xff0c;旨在提升我们对日常生活中实际应用场景的观察力、问题描述能力、分析力和产品设计能力。通过本项目&#xff0c;我们将能够将所学的人工智能专业知识进行综合应用&#xff0c;包括但不限于Linux操作系统、Py…

人工智能如何改变你的生活?

在我们所处的这个快节奏的世界里&#xff0c;科技融入日常生活已然成为司空见惯的事&#xff0c;并且切实成为了我们生活的一部分。在这场科技变革中&#xff0c;最具变革性的角色之一便是人工智能&#xff08;AI&#xff09;。从我们清晨醒来直至夜晚入睡&#xff0c;人工智能…

vue3 ajax获取json数组排序举例

使用axios获取接口数据 可以在代码中安装axios包&#xff0c;并写入到package.json文件&#xff1a; npm install axios -S接口调用代码举例如下&#xff1a; const fetchScore async () > {try {const res await axios.get(http://127.0.0.1:8000/score/${userInput.v…

How to use the ‘git log‘ command to get change log for each file?

1. Using git log command #!/bin/bash# 目标文件名 output_file"git_log.csv"# 打印 CSV 文件的标题行 echo "CommitID,Author,Author Email,Date,Added-Lines Removed-Lines File" > $output_file echo "CommitID,Author,Author Email,Date,Add…

Vue前端开发-动态插槽

不仅父组件可以通过插槽方式访问并控制子组件传入的数据&#xff0c;而且可以控制传入父组件时插槽的名称&#xff0c;从而使不同的插槽根据名称的不同&#xff0c;使用场景也不同&#xff0c;例如在一个小区详细页中&#xff0c;可以根据小区类型&#xff0c;调用不同名称的详…