深入剖析怎么分析进程crash问题(上)

【内核崩溃kdump(sysdump)和crash分析】 kdump实现了"双内核"布局,Kdump 在内核在内核panic后,立即调用kexec 引导到转储捕获内核(capture kernel),使用 kexec 引导 “覆盖” 当前运行的内核。该“转储捕获内核”的内存区域由主内核的bootargs参数 crashkernel 或dts指定。“转储捕获内核”可以是专门build的单独 Linux 内核image,也可以在支持可重定位内核的系统架构上重用主内核映像。 阅读详情

1. 概述

        平台:linux/armv7

2.问题

        以编程中经常发生程序段错误为例,要全方面理解段错误发生时候硬件和操作系统背后的逻辑,我们尝试思考如下几个核心问题:

  • cpu怎么知道段错误,段错误之后cpu做了哪些逻辑?
  • 异常发生后,怎么保存硬件上下文?
  • 异常发生后,怎么跳转到对应的处理程序?
  • 如果注册了signal handler发生段错误后打印crash现场的寄存器,从发生到段错误,到回调到应用进程的signal handler中间流程怎样的?这其中涉及一个有趣的问题就是怎么从内核态调用了用户态的signal handler,又自动跳转回内核执行的?

3. 段错误的本质

  对于arm linux内核来讲,应用程序的段错误核心是一种“异常”,ARM平台定义了如下几种异常,异常向量表中定义每种异常的处理程序,如下:

        段错误发生的时候最终会调用到异常向量表中data abort对应的处理程序。

4. 段错误发生时的硬件逻辑

     arm异常发生时硬件的动作在armv7 B1.8.3 章节有详细的描述,总结如下:

  1. 根据异常类型决定需要进入的mode。
  2. CPSR寄存器保存到相应mode对应的SPSR寄存器。
  3. 更新CPSR进入特定的模式(mode),注意:切入特定模式之后,像sp寄存器就会切入到特定模式的sp寄存器(banking register概念)。
  4. 将返回地址(PC)自动保存到对应模式的LR寄存器中。
  5. PC寄存器设置成相应的异常向量表中的对应的代码,跳转到相应的异常处理程序执行,进入到软件(OS)控制流程中。
  6. 处理完异常后,恢复异常发生前的处理器状态,即将对应模式SPSR寄存器中的数据复制到CPSR寄存器中。
  7. 设置程序计数器PC,使其指向中断发生前要执行的指令,即将对应模式的LR寄存器中的数据复制到PC寄存器中。

 细节:CPU怎么跳转到异常处理程序?

        核心cpu需要知道异常向量表的地址,这个不同的芯片平台可以有不同配置,针对arm linux一般配置在0xFFFF0000地址处,这个可以参考armv7芯片手册的B1.8.1,CP15协处理器的SCTLR寄存器可以控制具体的地址。

5. 段错误发生时的软件(OS)逻辑

        上面"段错误发生时的硬件逻辑"第5步开始跳转到OS软件的逻辑,对于os有了解的都知道,异常发生时最重要的步骤是保存硬件上下文。这点arm和x86逻辑并不相同,x86硬件做了更多的逻辑,arm可能基于功耗的考虑,没有设计那么复杂的硬件逻辑,保存上下文完全通过软件实现。硬件上下文(即各种寄存器)保存在内核栈中(arm芯片有要求不同mode使用不同的stack,linux也遵循了这个逻辑)。

5.1 中断向量表

arch/arm/kernel/entry-armv.S

.L__vectors_start:                                                                                                                                         
    W(b)    vector_rst
    W(b)    vector_und
    W(ldr)  pc, .L__vectors_start + 0x1000
    W(b)    vector_pabt
    W(b)    vector_dabt
    W(b)    vector_addrexcptn
    W(b)    vector_irq
    W(b)    vector_fiq

可以看到汇编代码中定义了armv7芯片手册中定义的各种异常处理函数,本文的段错误发生会跳转到vector_dabt函数,这个函数定义是通过vector_stub宏定义:

/*
 * Data abort dispatcher
 * Enter in ABT mode, spsr = USR CPSR, lr = USR PC
 */
    vector_stub dabt, ABT_MODE, 8

    .long   __dabt_usr          @  0  (USR_26 / USR_32)
    .long   __dabt_invalid          @  1  (FIQ_26 / FIQ_32)
    .long   __dabt_invalid          @  2  (IRQ_26 / IRQ_32)
    .long   __dabt_svc          @  3  (SVC_26 / SVC_32)
    .long   __dabt_invalid          @  4
    .long   __dabt_invalid          @  5
    .long   __dabt_invalid          @  6
    .long   __dabt_invalid          @  7
    .long   __dabt_invalid          @  8
    .long   __dabt_invalid          @  9
    .long   __dabt_invalid          @  a
    .long   __dabt_invalid          @  b
    .long   __dabt_invalid          @  c
    .long   __dabt_invalid          @  d
    .long   __dabt_invalid          @  e
    .long   __dabt_invalid          @  f

vector_stub宏定义了vector_dabt函数,函数体后面定义了16个入口,有效的入口是0和3索引处的__dabt_usr和__dabt_svc,用户空间发生dabt异常跳转到__dabt_usr函数,内核空间发生dabt异常跳转到__dabt_svc,如何实现这种跳转要需要分析vector_stub宏实现代码:

/*
 * Vector stubs.
 *
 * This code is copied to 0xffff1000 so we can use branches in the
 * vectors, rather than ldr's.  Note that this code must not exceed
 * a page size.
 *
 * Common stub entry macro:
 *   Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
 *
 * SP points to a minimal amount of processor-private memory, the address
 * of which is copied into r0 for the mode specific abort handler.
 */
    .macro  vector_stub, name, mode, correction=0
    .align  5

vector_\name:
    .if \correction
    sub lr, lr, #\correction
    .endif

    @
    @ Save r0, lr_<exception> (parent PC) and spsr_<exception>
    @ (parent CPSR)
    @
    stmia   sp, {r0, lr}        @ save r0, lr
    mrs lr, spsr
    str lr, [sp, #8]        @ save spsr

    @
    @ Prepare for SVC32 mode.  IRQs remain disabled.
    @
    mrs r0, cpsr
    eor r0, r0, #(\mode ^ SVC_MODE | PSR_ISETSTATE)
    msr spsr_cxsf, r0

    @
    @ the branch table must immediately follow this code
    @

    //获取异常之前处于哪个模式mode. 0:user 3: svc
    and lr, lr, #0x0f
 THUMB( adr r0, 1f          )
 THUMB( ldr lr, [r0, lr, lsl #2]    )

    //内核栈sp赋值给r0
    mov r0, sp

 //lr = pc + lr * 4,根据mode值算出来要跳转的入口,比如用户空间跳转到__dabt_usr
 ARM(   ldr lr, [pc, lr, lsl #2]    )
    movs    pc, lr          @ branch to handler in SVC mode
ENDPROC(vector_\name)

    .align  2
    @ handler addresses follow this label
1:
    .endm

 5.2 __dabt_user

__dabt_usr:    

    //保存硬件上下文,即各种寄存器                                                                                                                                            
    usr_entry uaccess=0
    kuser_cmpxchg_check

    sp赋值给r2,即给do_DataAbort第三个参数pt_regs传参
    mov r2, sp

    //内部实现跳转到CPU_DABORT_HANDLER,即v7_early_abort
    dabt_helper
    b   ret_from_exception
 UNWIND(.fnend      )
ENDPROC(__dabt_usr)

 5.3 v7_early_abort

#include <linux/linkage.h>
#include <asm/assembler.h>
/*
 * Function: v7_early_abort
 *
 * Params  : r2 = pt_regs
 *     : r4 = aborted context pc
 *     : r5 = aborted context psr
 *
 * Returns : r4 - r11, r13 preserved
 *
 * Purpose : obtain information about current aborted instruction.
 */
    .align  5
ENTRY(v7_early_abort)

    //armv7架构中cp15写处理的c5和c6寄存器保存了fsr和far
    mrc p15, 0, r1, c5, c0, 0       @ get FSR
    mrc p15, 0, r0, c6, c0, 0       @ get FAR
    uaccess_disable ip          @ disable userspace access

    b   do_DataAbort
ENDPROC(v7_early_abort) 
  • FSR : 失效状态寄存器(Data Fault Status Register)
  • FAR:失效地址寄存器(Data Fault Address Register)

    FSR寄存器记录发生存储失效的相关信息,包括存储访问所属域和存储访问类型,FAR记录访存失效的虚拟地址。参数r0 r1 r2准备好之后跳转到do_DataAbort执行。

5.4 do_DataAbort

/*
 * Dispatch a data abort to the relevant handler.
 */
asmlinkage void __exception
do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
{
    struct thread_info *thread = current_thread_info();
    const struct fsr_info *inf = fsr_info + fsr_fs(fsr);
    struct siginfo info;

    if (!user_mode(regs)) {
        thread->cpu_excp++;
        if (thread->cpu_excp == 1) {
            thread->regs_on_excp = (void *)regs;
            aee_excp_regs = (void *)regs;
        }
        /*
         * NoteXXX: The data abort exception may happen twice
         *          when calling probe_kernel_address() in which.
         *          __copy_from_user_inatomic() is used and the
         *          fixup table lookup may be performed.
         *          Check if the nested panic happens via
         *          (cpu_excp >= 3).
         */
        if (thread->cpu_excp >= 3)
            aee_stop_nested_panic(regs);
    }

    if (!inf->fn(addr, fsr & ~FSR_LNX_PF, regs)) {
        if (!user_mode(regs))
            thread->cpu_excp--;
        return;
    }

    pr_alert("Unhandled fault: %s (0x%03x) at 0x%08lx\n",
        inf->name, fsr, addr);
    show_pte(current->mm, addr);

    info.si_signo = inf->sig;
    info.si_errno = 0;
    info.si_code  = inf->code;
    info.si_addr  = (void __user *)addr;
    arm_notify_die("", regs, &info, fsr, 0);
}

根据fsr寄存器信息得到fsr_info结构体,该结构体描述一个异常状态对应的处理逻辑,结构体定义如下:

struct fsr_info {                                                                                                                                          
    int (*fn)(unsigned long addr, unsigned int fsr, struct pt_regs *regs);
    int sig;
    int code;
    const char *name;
};

name是失效状态的名称,sig是处理失效时Linux内核发送的信号,fn表示修复失效状态的处理函数。结构体的具体实现如下:

static struct fsr_info fsr_info[] = {
    /*
     * The following are the standard ARMv3 and ARMv4 aborts.  ARMv5
     * defines these to be "precise" aborts.
     */
    { do_bad,       SIGSEGV, 0,     "vector exception"         },
    { do_bad,       SIGBUS,  BUS_ADRALN,    "alignment exception"          },
    { do_bad,       SIGKILL, 0,     "terminal exception"           },
    { do_bad,       SIGBUS,  BUS_ADRALN,    "alignment exception"          },
    { do_bad,       SIGBUS,  0,     "external abort on linefetch"      },
    { do_translation_fault, SIGSEGV, SEGV_MAPERR,   "section translation fault"    },
    { do_bad,       SIGBUS,  0,     "external abort on linefetch"      },
    { do_page_fault,    SIGSEGV, SEGV_MAPERR,   "page translation fault"       },
    { do_bad,       SIGBUS,  0,     "external abort on non-linefetch"  },
    { do_bad,       SIGSEGV, SEGV_ACCERR,   "section domain fault"         },                                                                              
    { do_bad,       SIGBUS,  0,     "external abort on non-linefetch"  },
    { do_bad,       SIGSEGV, SEGV_ACCERR,   "page domain fault"        },
    { do_bad,       SIGBUS,  0,     "external abort on translation"    },
    { do_sect_fault,    SIGSEGV, SEGV_ACCERR,   "section permission fault"     },
    { do_bad,       SIGBUS,  0,     "external abort on translation"    },
    { do_page_fault,    SIGSEGV, SEGV_ACCERR,   "page permission fault"        },
    ...
    /*

 针对本文举例的段错误,对应的处理函数是do_translation_fault函数。该函数中最后会给进程发送段错误信号。

参考文章:

linux arm内核栈切换,(转)ARM Linux中断发生时内核堆栈切换 - CodeAntenna   

crash分析工具 什么是Crash? 当linux系统内核发生崩溃的时候,可以通过KEXEC+KDUMP等方式收集内核崩溃之前的内存,生成一个转储文件vmcore。内核开发者通过分析该vmcore文件就可以诊断出内核崩溃的原因,从而进行操作系统的代码改进。那么Crash就是一个被广泛使用的内核崩溃转储文件分析工具。 对调试来讲,gdb是非常适合的,但gdb始终是调试native的工具,不支持kernel信息显示,比如task信息之类的。crash补足了这个短板,由Dave Anderson开发和维护的一个内存转储分 阅读详情

相关推荐

arm linux应用程序crash分析一般方法

linux的应用程序app开发过程中,出现一些应用程序的崩溃是比较常见的事情,根据不同的场景,往往有可以分成两类:1.开发环境下,解决应用程序的崩溃往往有很多的方法,常规的例如:上下文看代码逻辑,版本回退缩代码bug范围,不同版本横向对比,printf打印跟踪代码运行,debug工具上,配置内核show出来kallsyms,配置coredump抓应用崩溃日志等等,方式方法有很多种,分析问题手段也比较多一些,相对难度小一些。

开发者 1804

Crash分析

先找9a7bef6c.这个是用户堆栈的排布规则,规则就是这样的。2. gdb(gdb) x /2000a $sp //arm 下是寄存器名sp, x86下是寄存器名rsp...这个会把 dump user stack(用户堆栈信息)里面所有的 函数地址 转化为 函数名,根据这么函数名推测哪里crash了。

gezi322的专栏 1198

Linux内核崩溃分析实战:从Crash工具入门到高级调试技巧

在Linux系统运维和内核开发中,系统崩溃是常见且棘手的问题。当系统发生严重错误时,传统的日志调试方法往往失效,此时需要借助Crash工具进行事后调试。Crash工具通过分析内核内存转储文件,能够深入系统底层,定位崩溃根源。其核心原理在于利用调试符号文件解析内存数据结构,结合系统快照还原崩溃现场。这项技术对于诊断内存越界、空指针解引用、死锁等复杂内核问题具有极高价值,是运维工程师和内核开发者必须掌握的技能。在实际应用场景中,Crash工具常用于生产环境故障分析、内核问题排查和系统稳定性优化。本文将以实战为导

weixin_30719711的博客 367

crash实战:手把手教你使用crash分析内核dump

Kdump是Linux的一种内核崩溃捕获机制,Linux内核遇到致命错误崩溃时会触发Kdump机制将崩溃时的现场保存下来,以便后续分析和故障排查。目前市面上有很多分析Kdump的工具,例如trace32, crash tool,本文介绍crash tool在手机领域的应用,并重点介绍一些实用的技巧。然而,本文的重点并不是介绍crash tool的工作原理和基础命令,也不是为了介绍Kdump转储的原理以及其他Kdump解析工具,如果你对这些内容感兴趣,请参考本文末尾提供的参考文档。 一、为什么要用crash

Elvis Hu的博客 5494

从宕机到洞察:掌握Linux内核调试与Crash工具实战分析

在Linux系统运维与开发中,系统稳定性是核心诉求。当发生内核崩溃(Kernel Crash)时,常规的日志和用户态coredump往往失效,导致根因定位困难。其原理在于内核崩溃意味着系统控制权丢失,无法记录现场。为此,Linux提供了内核崩溃转储机制,通过Kdump在系统崩溃瞬间捕获完整物理内存的快照(vmcore),再使用专门的Crash工具进行离线分析,这构成了事后调试(Post-mortem Analysis)的技术基础。这项技术的核心价值在于能将黑盒般的系统宕机转化为可追溯、可分析的现场,实现从故

weixin_33841722的博客 450

Android 9.0 Crash机制深度解析:从异常捕获到进程终止的完整调用链

在移动应用开发中,异常处理是保障应用稳定性的核心技术。其原理基于运行时环境对程序执行错误的监控与响应机制,当代码执行出现无法处理的错误时,系统会触发一系列预定义的错误处理流程。这项技术的核心价值在于,它不仅能帮助开发者快速定位和修复问题,更能为构建高可用的应用提供底层支持,广泛应用于性能监控、崩溃分析和用户体验优化等场景。以Android系统为例,其异常处理机制构建了从Java运行时到Linux内核的完整调用链。在Android 9.0版本中,系统引入了独立的crash_dump守护进程,将崩溃信息收集逻辑

weixin_30902251的博客 260

C++线上Crash排查:5个真实案例解析与防御性编程实践

在C++后端开发中,线上进程崩溃是开发者常面临的棘手问题。这类问题通常源于内存管理、多线程同步、异常处理等核心概念的理解偏差。从原理上看,C++程序的稳定性依赖于对对象生命周期、内存对齐、信号处理等底层机制的准确把握。其技术价值在于,通过深入理解这些机制,可以构建出高性能且高可用的系统。在实际应用场景中,高并发服务、实时数据处理、系统级编程等领域尤为常见。本文聚焦于多线程环境下的静态初始化顺序、STL容器迭代器失效、跨语言异常处理、内存对齐要求以及信号处理安全等典型问题,通过具体案例剖析其根源,并提供工程实

weixin_31188927的博客 309

深入解析Android Native Crash信号处理与debuggerd守护机制

本文深入解析Android Native Crash的信号处理机制与debuggerd守护进程的工作原理。详细介绍了Linux信号机制如何触发崩溃,debuggerd如何通过生成tombstone文件记录崩溃信息,并提供了源码级分析和实战调试技巧,帮助开发者快速定位和解决Native层崩溃问题。

weixin_29196613的博客 692

Android 12 进程native crash流程分析

在Android中,crash大致可以做如下分类:本篇主要是看 Native crash 抓log流程。实现机制主要是基于信号机制和ptrace机制,如下:流程大致如下图所示: 接下来,从 linker 的入口_start开始看起。如何分析入口可见参考。 __linker_init __linker_init_post_relocation linker的一些初始化,主要看linker_main函数 linker_main linker_debuggerd_init debuggerd_init d

pecuyu 4828

Google Cameraserver看门狗CameraServiceWatchdog disconnectImpl超时crash分析一:reconfigureCamera重新配流超时crash

本文分析了Google CameraServer中CameraServiceWatchdog看门狗超时crash问题。该问题由reconfigureCamera重新配流超时触发,具体表现为Session_parameters的FPS range参数变化导致不必要的重新配流请求,最终因OPERATION_NOT_SUPPORTED而失败。解决方案是针对特定相机APP禁用重新配流权限,在configureStreamsLocked调用前添加APP判断逻辑,跳过不必要的重新配流操作,从而避免看门狗超时crash。

1395

Android crash 流程详解(二):NE

在上一篇博文剖析了java layer exception 的处理流程,本文将继续剖析 Android crash 的另一部分,即 native 端的 crash,又称 native layer exception (NE。

私房菜 1万+

简单分析 App 进程 Crash 机制

code小生 一个专注大前端领域的技术平台公众号回复Android加入安卓技术群作者:杰杰_88链接:https://www.jianshu.com/p/ecd52cd90a4b声明:本...

weixin_38754349的博客 753

01-SA8155 QNX 虚拟机Hypervisor

Hypervisor运行在Host OS操作系统上,其他操作系统均在Hypervisor上运行。:Hypervisor直接运行在硬件上,操作系统在Hypervisor之上运行。终止(关闭):echo control 0 dev/vmm。路径:qnx_ap/AMSS/platform/vm/resources/关闭/终止 qvm(GVM):slay -s SIGQUIT qvm。", //host PVM --- 主机。不直接操作/dev/vmm 实现关闭,启动vm。

静虚待令,有物混成 1万+

疑难ANR面试题:crash导致ANR深入剖析

只要有异常抛出,那么主线就直接无法再继续运行,所以哪怕加上原来的skipCallbacks为true时候进行sendFinishedSignal,确实当前这个事件正常finish了,不会当场anr,但是主线程已经停止运行了,如果有新事件过来无法接受也会ANR。可以看到默认的直接会执行finishInputEvent方法,这个finishInputEvent最后会调用到InputConsumer::sendFinishedSignal方法传递finish到InputDispatcher中。

learnframework的博客 960

从实验室到晶圆厂:一文看懂二维半导体(如MoS2)的CVD生长与晶体管制造挑战

本文深入探讨了二维半导体(如MoS2)从实验室研究到晶圆厂量产的CVD生长与晶体管制造关键技术挑战。重点分析了晶圆级二维半导体的CVD生长工艺优化、晶体管制造的四大界面工程难题,以及掺杂与集成的产业化解决方案,为二维半导体在集成电路领域的应用提供技术参考。

weixin_42651748的博客 471

四大AI编程工具深度对比:Claude Code、Codex、OpenCode与WorkBuddy选型指南

AI编程助手正从代码补全走向自主执行的智能体形态,其核心原理是通过“规划-执行-观察”循环让模型自主完成文件修改、命令运行与错误修复。这类工具的技术价值在于提升长任务连续性与上下文理解能力,同时通过自定义指令与技能机制沉淀团队规范,适应不同工程场景。在实际选型中,开发者常面临终端CLI与图形化工作台、模型开放程度与绑定生态之间的权衡:Claude Code强调深度Agent体验,Codex支持灵活接入OpenAI兼容模型,OpenCode以开源多模型见长,WorkBuddy则提供全流程集成环境。本文基于真实

weixin_42526166的博客 135

嵌入式系统中crash的底层驱动成因深度剖析

深入探讨嵌入式系统中导致crash的底层驱动问题,从内存访问错误到中断处理异常,剖析典型故障场景。结合实际案例,揭示crash背后的关键驱动逻辑缺陷,帮助开发者提升系统稳定性与容错能力。

weixin_42604188的博客 481

linux下autocad完美替代品bricscad的安装运行

前言 在Linux平台下,能完美兼容.dwg文件的软件并不多。 虽然国产的中望和浩辰为适配uos操作系统,近期都推出了linux版本,但目前好像还没有对应的破姐流出。(如果有的话请私信我或留下评论) 然而有了这一款源自比利时的软件——bricscad,linux下查看和编辑.dwg文件再也不是噩梦了! 安装pj 资源链接:https://pan.baidu.com/s/1dC7zarlqwuO5fa4CBL_KGQ 提取码:24j6 1.下载对应的压缩包,解压并安装其中对应的deb或rpm软件包。 2.在C

weixin_35259117的博客 4481

实例分析:android.process.media由于调用进程crash而退出

Log: 09-13 11:46:42.093 14778 17309 I dalvikvm: Ljava/lang/RuntimeException;: No memory in memObj 09-13 11:46:42.093 14778 17309 I dalv

cloudwu007的专栏 3868

SAP数据导入工具(LSMW) 超级详细教程(批量导入内部订单)

用户提了个需求,让我批量导入内部订单几百个内部订单。我本打算用写段ABAP 代码来调用 BAPI (BAPI_INTERNALORDER_CREATE)就可以了。但想到我很久没有用过LSMW 了,都快要忘记了。于是我采用LSMW的方式,完成了任务。并把过程记录下来,形成教程方便我以后回头查看,分享出来也希望对大家有帮助。

IT小职员 2万+

linux 基于debian/ubuntu AB系统适配(二)-updateEngine移植

其实A/B系统的原理很简单,大部分的工作都集中在uboot上,rootfs只是起到一个辅助的作用,但这个作用也就必不可少的。你会发现在这个其中并没有kernel的参与。

badbayyj的博客 1033

内存越界导致crash:实战案例与规避策略

通过真实案例解析内存越界如何导致程序crash,深入探讨常见触发场景和调试技巧,结合crash日志定位问题根源,提供有效的编码规范与检测工具建议,帮助开发者规避此类顽固问题。

weixin_28793831的博客 962

【QT开发教程】使用Qt进行蓝牙低功耗(BLE)编程

蓝牙低功耗(BLE,Bluetooth Low Energy)技术广泛应用于现代设备中,例如智能手表、健身追踪器和物联网设备。Qt提供了一套完整的Bluetooth模块,使开发者可以轻松地在应用程序中实现BLE通信功能。本文将介绍如何在Qt中进行BLE编程,包括基本概念、使用方法以及一些实际的示例。

科技改变人类,技术成就未来 2868

CRASH工具介绍

转自: http://yalung929.blog.163.com/blog/static/2038982252013216102949487/ 学习 crash命令和其他命令的结合使用方法。 crash是和kdump工具配套使用,用于解析kdump生成的vmcore文件。vmcore是内核的映像(实际上是整个内存的映像,一般来说我们会开启过滤功能,只记录内核页)。内核全部的数据结构

u011279649的专栏 9780

vue2/3 - 详细对接海康监控实时视频预览和录像回放功能,vue接入使用海康视频监控播放器实时推流等功能,支持hik/rtsp/rtmp/hls/ws取流协议(详细教程与示例代码,一键复制开箱即用

vue2,vue3,海康,vue海康视频监控,海康开放平台,如何接入海康的实时监控,海康威视,Vue实现海康监控视频播放,vue3对接海康视频监控播放、回放的方法流程,实现海康H5视频插件播放视频的实例,web网页接入海康,海康威视的视频vue的录像回放和实时预览,前端vue3项目接入海康威视h5player.js播放器,vue2接入海康威视视频监控平台,使用海康监控H5视频播放,对接海康视频监控,海康视频web插件,web前端在vue中通过海康插件嵌入视频,实现实时预览,vue3海康监控播放器组件,vue

✅ 精选推荐文章 1万+

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

上一篇: 彻底搞懂内存屏障(下)
下一篇: Linux进程内核栈
OS技术解密
博客等级 码龄16年 3760粉丝 189原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值