MTK系统启动流程

MTK系统启动流程

boot rom -> preloader ->lk ->kernel ->Native -> Android

1、Boot rom:系统开机,最先执行的是固化在芯片内部的bootrom,其作用主要有
a.初始化ISRAM和EMMC
b.当系统全擦后 ,也会配置USB,用来仿真USB端口下载镜像。
c.从EMMC中加载preloader到ISRAM中执行。

2、Preloader:主要完成平台基础设备的初始化,如DDR等硬件,下载握手连接,加载lk到DDR中,跳转到lk

3、Lk:打开MMU,加速lk执行,显示log、充电相关,从emmc中boot分区取出boot.img进行解压,将根文件系统,linux kernel加载到Dram,完成kernel前的准备工作并拉起kernel(start_kernel)。

4Kernel:初始化调度、内存管理、io、中断等linux操作系统基本功能、识别OTBO,创建init进程,完成模块的初始化,执行init主程序。

5Native:启动系统关键进程init、void、surfaceflinger等

init 进程的作用大致分为3部分:

1、创建备结点,挂载跟文件系统,

2、开启selinux安全策略,初始化资源文件,启动属性服务等;

3、解析initrc 文件;

6、Android:init fork zygote进程,再由zygote去创建所有安卓的应用进程

基本流程图如下:

属性查看是否第一次开机

persist.sys.device_provisioned开机向导是否完成

persist.sys.device_first_boot是否第一次开机

一、preloader(汇编/C)

1.1 作用

1、完成平台基础设备的初始,如DDR等硬件

2、与flashtoolUSB握手,download 相关检测 & sec boot检测;

3、将lk加载到DRAM

4、跳转到Ik

1.2 入口代码

/MTXXXX_13_Master/vnd/vendor/mediatek/proprietary/bootable/bootloader/preloader/platform/mtXXXX/src/init/init.s

init.s:初始化寄存器、清空bss段、初始化stack、设置CPSR、切换到SVC模式、禁止中断;完成以上基本初始化后jump to main

  setup_stk :/* setup stack */LDR r0, stackLDR r1, stacksz/* buffer overflow detect pattern */LDR r2, =0xDEADBEFFSTR r2, [r0]LDR r1, [r1]SUB r1, r1, #0x04ADD r1, r0, r1MOV sp, r1entry :LDR r0, =bldr_args_addrB   main.globl jump

/MTXXXX_13_Master/vnd/vendor/mediatek/proprietary/bootable/bootloader/preloader/platform/mtXXXX/src/core/main.c

static void bldr_pre_process(void)
{int isLocked = 0;int tempnoboot = 0;uint32_t ret = 0;......//初始化timer/pll/gpio/uart/WDT/storage/PMICplatform_pre_init();pal_log_info("\n%s Build Time: %s\n", MOD, BUILD_TIME);....../* hardware initialization *///初始化RTC/PM/batter/DDR/storageplatform_init();tempnoboot = oplus_bq28z610_temp();no_boot_log_to_storage(tempnoboot);......
}void main(u32 *arg){struct bldr_command_handler handler;u32 jump_addr, jump_arg;
......//初始化平台环境bldr_pre_process();.......BOOTING_TIME_PROFILING_LOG("before bldr_handshake");//与下载工具握手连接bldr_handshake(&handler);BOOTING_TIME_PROFILING_LOG("bldr_handshake");//初始化安全环境trustzone_pre_init();BOOTING_TIME_PROFILING_LOG("trustzone pre init");#endif#if !(CFG_BYPASS_LOAD_IMG_FORCE_ATF)/* Do not load ATF, lk, load by JTAG *///加载LK镜像到DRAMif (0 != bldr_load_images(&jump_addr)) {pal_log_err("%s Second Bootloader Load Failed\n", MOD);#if !CFG_BYPASS_EMIgoto error;#endif //SLT//完成preloader剩余的初始化,主要对电池的初始化bldr_post_process();.......//跳转到lkbldr_jump64(jump_addr, jump_arg, sizeof(boot_arg_t));.......}

bldr_pre_process 初始化平台环境

platform_pre_init:初始化timer/pll/gpio/uart/WDT/storage/PMIC

platform_init:初始化RTC/PM/batter/DDR/storage

bldr_handshake 与下载工具握手连接

trustzone_pre_init 安全环境初始化

bldr_load_images 加载LK镜像到DRAM

bldr_post_process 完成preloader剩余的初始化,主要对电池的初始化

bldr_jump64跳转到lk

二、LK(汇编/C)

2.1 作用

1、打开MMU,使能I/D-cache,加速lk执行,显示logo、充电相关

·2、从emmc中boot分区取出bootimg解压,将根文件系统(ramdisk)、linux kernel load到DRAM:

3、解析dtb,写入到DRAM指定区域:

4、关闭MMU、irg /fg,关闭ID-cache,拉起 kernel(startkemel);

2.2 入口代码:

/MTXXXX_13_Master/vnd/vendor/mediatek/proprietary/bootable/bootloader/lk/arch/arm/crt0.S

crt0.s:添加TZ symbol,执行abort stack等初始化操作。跳转到kmain

2.3 kmain

/MTXXXX_13_Master/vnd/vendor/mediatek/proprietary/bootable/bootloader/lk/kernel/main.c

void kmain(void)
{//初始化工作队列、线程表、创建bootstrap线程开始后面初始化thread_init_early();// 初始化MMU、cachearch_early_init();//平台初始化。如timmer、gpio、pmic等,建立lk基本运行环境platform_early_init();
.......#if (!ENABLE_NANDWRITE)// create a thread to complete system initializationdprintf(SPEW, "creating bootstrap completion thread\n");//thread_bs2:创建bootstrap2线程,用于完成后续的初始化并加载app bootstrap2thread_t *thread_bs2 = thread_create("bootstrap2", &bootstrap2, NULL,DEFAULT_PRIORITY, DEFAULT_STACK_SIZE);
......}

1. 初始化系统任务所需的线程、链表和相关队列。
2. 初始化硬件平台,搭建lk基本运行环境
3. 初始化定时器等
4. 创建一个新线程bootstrap2,并执行。当前线程置于空闲状态

2.4 bootstrap2

static int bootstrap2(void *arg)
{dprintf(SPEW, "top of bootstrap2()\n");print_stack_of_current_thread();arch_init();// XXX put this somewhere else
#if WITH_LIB_BIObio_init();
#endif
#if WITH_LIB_FSfs_init();
#endif// Allocate LK memory from mb, free before jump to kernelmboot_allocate_lk_scratch_from_mblock();// initialize the rest of the platformdprintf(SPEW, "initializing platform\n");platform_init();// initialize the targetdprintf(SPEW, "initializing target\n");target_init();dprintf(SPEW, "calling apps_init()\n");apps_init();return 0;
}

bootstrap2线程主函数:初始化bio、fs、platform、app

app_init 逐个app初始化并运行

mt_boot执行后续启动流程,最终加载kernel的app

三、Kernel(汇编/C)

3.1 作用

初始化调度、内存管理、io、中断等linux操作系统基本功能、识别DTBO、创建init进程、完成模块的初始化,执行init主程序

3.2 入口代码

/MTXXXX_13_Master/vnd/kernel/kernel-5.10/arch/arm64/kernel/head.S

MMU、CPU、页表、Cache等初始化,跳转到start_kernel

3.3 start_kernel

/MTXXXX_13_Master/vnd/kernel/kernel-5.10/init/main.c

在一系列基本初始化完成后,rest_init->kernel_init 创建init进程,并在/sbin/etc/bin依次寻找init可执行文件

3.4 DTBO识别流程

start_kernel->setup_arch->unflatten_device_tree->unflatten_device_tree->unflatten_dt_nodes

在unflatten_dt_nodes中遍历每个节点,对每个节点调用populate_node,将每个节点的信息转化为device_node结构;

unflatten_dt_alloc创建device_node结构

populate_propertites创建property结构,并将device_node属性添加进去

3.5 platform bus初始化流程

do_basic_setup->driver_init

devices_init:创建/sys/devices /sys/dev两个设备根节点,创建/sys/dev/block /sys/dev/char

buses_init:创建/sys/bus bus根节点

platform_bus_init

注册platform_bus设备,创建/sys/devices/plaform节点,此节点是所有platform设备的根节点

注册platform_bus_type总线类型,创建/sys/bus/platfrom节点,此节点是所有platform设备的总线类型根节点

3.6 将设备树种的设备加入platform devices:

入口函数

/MTXXXX_13_Master/vnd/kernel-5.10/drivers/of/platform.c

通过arch_initcall_sync将此函数加入kernel初始化函数集

通过of_platform_default_populate->of_plattform_populate->platform_bus_create此调用流程挑选合适的设备加入platform bus

最后通过of_plaform_device_create_pdata->of_device_add将设备添加到platform devices

四、Native(C/C++)

4.1 作用

启动系统关键进程init、void、surfaceflinger

4.2 init入口代码

/MTXXXX_13_Master/sys/system/core/init/main.cpp

int main(int argc, char** argv) {
......if (argc > 1) {if (!strcmp(argv[1], "subcontext")) {android::base::InitLogging(argv, &android::base::KernelLogger);const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();return SubcontextMain(argc, argv, &function_map);}if (!strcmp(argv[1], "selinux_setup")) {return SetupSelinux(argv);}if (!strcmp(argv[1], "second_stage")) {return SecondStageMain(argc, argv);}}//init第一阶段return FirstStageMain(argc, argv);
}

4.3 init第一阶段 FirstStageMain

/MTXXXX_13_Master/sys/system/core/init/first_stage_main.cpp

1、创建系统目录、挂载对应分区

2、初始化init阶段log到kernel log

3、加载SElinux安全策略

4.4 init第二阶段 SecondStageMain

/MTXXXX_13_Master/sys/system/core/init/init.cpp

1、初始化属性系统,从指定位置读取属性设置:-->Propertyinit()

2、挂载apex/分区-->MountExtraFilesystem s ()

3、SElinux第二阶段-->SelinuxRestoreContext() :

4、启动属性服务,以便增加、修改、获取属性-->StartPropertyService ()

5、初始化文件上下文-->InitializeSubcontext()

6、将am、sm添加到集合中,以便后续按顺序执行-->LoadBootscripts (am , sm )

7、执行init.rc

4.5 initrc语法:安卓启动脚本专用语法

四要素:Action、Command、Service、Option

4.5.1 Action

由一组命令和一个触发器组成,触发器语句以on开头,on后的条件决定执行的时机,当一些条件满足触发器的条件时,该Action中定义的命令会被添加到要执行命令队列的尾部(如果这组命令已经在队列中,则不会再次添加)。

常用的triggers如下:

  1. early-init 在初始化早期阶段触发
  2. late-init 在初始化晚期阶段触发
  3. init 在初始化阶段触发
  4. late-init 在初始化晚期阶段触发
  5. boot/charger 当系统启动/充电时触发
  6. property:<key>=<value> 当属性值满足条件时触发 如:on property:ro.debuggable=1
  7. fs 挂载mtd分区时触发
  8. boot 基本网络的初始化,内存管理等时触发
  9. post-fs 改变系统目录的访问权限时触发
  10. device-added-<path> 设备节点添加时触发
  11. device-removed-<path> 设备节点删除时触发
  12. service-exited-<name> 在特定服务(service)退出时触发

on earty-init创建文件目录,给进程设置限制(nice、fd)启动 ueventd

on init创建文件目录,给各节点分用户组,启动logd、Imkd、servicemanager等服务

on late-init

on early-fs:启动voId

on fs:挂载文件目录

on postfs:挂载文件系统 rootfs(remount)。

on late-fs:存储加密解锁前所需的 HALs如(keyasten)

on post-fs-data:挂载data,启动apexd,初始化第一个用户,启动fuse,

zygote-start:需和加密状态一起,启动zygote.netdzygote-secondnary

on boot:启动 hal,启动core service

4.5.2 command

常用命令:

1).import <filename>          导入init.XX.rc、xxx.conf等文件  Parse an init config file, extending the current configuration.2).chmod <octal-mode> <path>  Change file access permissions.3).chown <owner> <group> <path>  Change file owner and group.  4).chdir <directory>  Change working directory.  5).chroot <directory>   改变进程根目录  6).insmod <path>     加载XX.ko驱动模块7).start <service>  Start a service running if it is not already running.8).stop <service>  Stop a service from running if it is currently running.9).class_start <serviceclass>  Start all services of the specified class if they are not already running.10).class_stop <serviceclass>  Stop all services of the specified class if they are currently running.  class_reset <serviceclass>   //重启class下面所有的服务  11).setprop <name> <value>    Set system property <name> to <value>.  通过getprop命令可以查看当前系统的属性值  12).export <name> <value>         设置全局环境变量,这个变量值可以被所有进程访问(全局的,一直存在)  在代码中通过value = getenv("name")接口可以获取这个环境变量的值  13).mkdir <path> [mode] [owner] [group]  创建目录,后面项缺省值为 mode,owner,group: 0755 root root14).trigger <event>  Trigger an action.  Used to queue an action from another action.  例:trigger post-fs-data15).exec <path> [ <argument> ]*       执行<path>指定的Program,并可以带有执行参数。  exec在调用进程内部执行一个可执行文件,并会阻塞当前进程,直到运行完成。  最好避免和那些builtin commands一样使用exec命令,否则容易造成阻塞 or stuck ( maybe there should be a timeout?)16).ifup <interface>  启动某个网络接口,使其为up状态,通过netcfg可以查看,ifup eth0  等价于 netcfg eth0 up 功能一样  17).hostname <name>  设置设备的主机名,一般默认设置为localhost,可以在终端通过hostname new_name进行修改18).domainname <name>  设置网络域名localdomain19).mount <type> <device> <dir> [ <mountoption> ]* 把device挂接到dir目录下面,文件系统类型为type。  <mountoption>s include "ro", "rw", "remount", "noatime", “nosuid”......,具体可查看[linux](http://lib.csdn.net/base/linux "Linux知识库")的mount命令说明  20).setkey  TBD  == to be determined 暂时没有使用21).setrlimit <resource> <cur> <max>  设置本服务进程的资源上限值。(使用例子??)22).symlink <target> <path>     path 链接到 ---》target ;创建符号链接23).sysclktz <mins_west_of_gmt>    设置系统时区(0 if system clock ticks in GMT)24).wait <path> [ <timeout> ]  轮询查找给定的文件path是否存在,如果找到或者超时则返回默认超时为5秒。(使用实例???)25).write <path> <string> [ <string> ]*  打开一个文件,利用write命令写入一个或多个字符串

4.5.3 service

Services(服务)是一个程序,以 service开头,由init进程启动,一般运行于另外一个init的子进程,所以启动service前需要判断对应的可执行文件是否存在。init生成的子进程,定义在rc文件,其中每一个service,在启动时会通过fork方式生成子进程。Services(服务)的形式如下:

服务(services)是指那些须要在系统初始化时就启动或退出时自己主动重新启动的程序.

它的语法结构例如以下:

1.  service <name> <pathname> [ <argument> ]* 
2.   <option> 
3.   <option> 
4.   ...

pathname: 必须要有可执行的权限 service的name: 在所有rc文件中不能重复

4.5.4 option 选项

  • class <class_name>
    说明服务属于class_name这个类。缺省值service属于 “default” 类。同一个class下面的服务可以一起启动或停止。
  • disabled
    表示当这个服务所在的class启动的时候,服务不会自动启动,
    要用start server_name 或 property_set("ctl.start", server_name);才能启动。
  • oneshot
    当服务退出后,不会再重新启动,如果没有加这个option,则服务默认退出后又会重新重启
  • user <username>
    执行服务之前,先声明服务的用户名,缺省值应该为root用户.
  • group <groupname> [ <groupname> ]*
    执行服务之前,先声明服务所属组名,可以一次声明属于多个组。
    声明多个组时,除第一个组名外,其他的为服务的补充组名(调用接口 setgroups()).
  • onrestart + command
    服务重启的时,会执行onrestart后面的command.
    eg:onrestart restart media 重启名为media的服务
  • setenv <name> <value>
    在当前服务进程中设置环境变量name的值为value。
    注意:setenv定义的环境变量仅在本进程内生效,退出该进程,或者关闭相应的程序运行窗口,该环境变量即无效)
    程序中可通过getenv("name")接口获取这个环境变量的值
    setenv和export 的区别:
    setenv csh ,本进程生效,退出后,变量无效
    export bash ,全局生效,一直存在
    格式:
    export key=value
    setenv key value
  • critical
    声明为关键服务。如果服务在四分钟内退出了四次,则设备会进入recovery模式
  • socket <name> <type> <perm> [ <user> [ <group> ] ]
    创建名为/dev/socket/<name>的unix domain socket ,并把它的句柄fd传给本服务进程
    <type> 必须为 "dgram", "stream" or "seqpacket".User and group default to 0 ,也就是root.
  • seclablel 执行服务之前改变安全上下文

五、Android(JAVA)

init fork zygote进程,再由zygote去创建所有安卓的应用进程。

5.1 ZygoteInit

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

    public static void main(String argv[]) {//1、创建ZygoteServerZygoteServer zygoteServer = new ZygoteServer();.......try {.......boolean startSystemServer = false;String socketName = "zygote";String abiList = null;boolean enableLazyPreload = false;// 2、解析app_main.cpp传来的参数for (int i = 1; i < argv.length; i++) {if ("start-system-server".equals(argv[i])) {startSystemServer = true;} else if ("--enable-lazy-preload".equals(argv[i])) {enableLazyPreload = true;} else if (argv[i].startsWith(ABI_LIST_ARG)) {abiList = argv[i].substring(ABI_LIST_ARG.length());} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {socketName = argv[i].substring(SOCKET_NAME_ARG.length());} else {throw new RuntimeException("Unknown command line argument: " + argv[I]);}}if (abiList == null) {throw new RuntimeException("No ABI list supplied.");}//3、创建一个Server端的SocketzygoteServer.registerServerSocket(socketName);// In some configurations, we avoid preloading resources and classes eagerly.// In such cases, we will preload things prior to our first fork.if (!enableLazyPreload) {bootTimingsTraceLog.traceBegin("ZygotePreload");EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,SystemClock.uptimeMillis());//4、加载进程的资源和类preload(bootTimingsTraceLog);EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,SystemClock.uptimeMillis());bootTimingsTraceLog.traceEnd(); // ZygotePreload} else {Zygote.resetNicePriority();}........if (startSystemServer) {//5、开启SystemServer进程startSystemServer(abiList, socketName, zygoteServer);}Log.i(TAG, "Accepting command socket connections");//6、启动一个死循环监听来自Client端的消息zygoteServer.runSelectLoop(abiList);//7、关闭SystemServer的SocketzygoteServer.closeServerSocket();} catch (Zygote.MethodAndArgsCaller caller) {//8、这里捕获这个异常调用MethodAndArgsCaller的run方法。caller.run();} catch (Throwable ex) {Log.e(TAG, "System zygote died with exception", ex);zygoteServer.closeServerSocket();throw ex;}}

5.2 Zygote流程

1、创建java虚拟机

2、为java虚拟机注册native方法

3、在com.android.initernal.os.ZygoteInit中调用java类的主要方法

4、加载Zygotelnit class

5、注册Zygote socker

6、加载preload class

7、加载preload资源文件

8、调用Zygote::forkSystemServer、fork一个新的进程,调用SystemSercer的main方法,启动SystemServer进程

1.解析init.zygote.rc中的参数,创建AppRuntime并调用AppRuntime.start()万法

2.调用AndroidRuntime的startVM()方法创建虚拟机,再调用startReg()注册JNI函数

3.通过JNI方式调用Zygotelnitmain0),第一次进入Java世界

4.registerZygoteSocket()建立socket通道,zygote作为通信的服务端用于响应客户端请求

5.preload()预加载通用类、drawable和color资源、openGL以及共享库以及WebView,用于提高app启动效率

6.通过startSystemServer(),fork得力帮手system_server进程

7.调用runSelectLoop0(),当接收到请求创建新进程请求时立即唤醒并执行相应工作

5.3 Zygote作用

创建SystemServer

孵化应用进程

5.3 相关进程

init 进程:当内梭创建了 init 进程之后便去执行 init,init 进程的最后阶段对 init,rc脚本进行解析,启动各种进程服务,其中最重要的是启动了 zygote 进程。

zygote 进程: zygote 进程承上启下,是系统开启的第一个 java 进程,运行在 framework层;该进程主要负责创建包括 systemserver 在内的所有应用程序,以及创建虚拟机运行环境。

systemserver 进程: 启动 Binder 线程池和 SystemServiceNanager;

systemServiceManager 主要是对系统服进行创建、启动和生命局期管理,就会启动各种系统服。(android中最核心的服务 AMS 就是在 SystemServer 进程中启动的)

Launcher 进程: launcher 进程是android 系统启动的最后一步,主要负责将已经安装好的应用程序显示到界面上。

5.4 谷歌官方开机优化资料

https://source.android.com/devices/tech/perf/boot-times

 

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

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

相关文章

CSS 瀑布流效果效果

示例 <!DOCTYPE html> <html lang="cn"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>瀑布流效果</title><style>…

IMU和视觉融合学习笔记

利用纯视觉信息进行位姿估计&#xff0c;对运动物体、光照干扰、场景纹理缺失等情况&#xff0c;定位效果不够鲁棒。当下&#xff0c;视觉与IMU融合(VI-SLAM&#xff09;逐渐成为常见的多传感器融合方式。视觉信息与IMU 数据进行融合&#xff0c;根据融合方式同样可分为基于滤波…

Rust vs Go:常用语法对比(八)

题目来自 Golang vs. Rust: Which Programming Language To Choose in 2023?[1] 141. Iterate in sequence over two lists Iterate in sequence over the elements of the list items1 then items2. For each iteration print the element. 依次迭代两个列表 依次迭代列表项1…

聊天机器人如何增加电子商务销售额

聊天机器人和自动化对企业和客户来说都是福音。自动对话和聊天机器人&#xff08;以下统称为“自动化”&#xff09;通过自动回答问题或分配会话信息来帮助用户浏览品牌网站或电商商店。即时答案对客户来说非常有用&#xff0c;使用自动化也可以让原本与客户聊天的客服员工专注…

MacDroid for Mac:在Mac上访问和传输Android文件的最简单方式

MacDroid for Mac是一款帮助用户在Mac和Android设备之间传输文件的软件。由于Mac OS X本身并不支持MTP协议&#xff0c;所以透过USB将Android设备连接到Mac电脑上是无法识别的&#xff0c;更别说读取里面的文件了。 MacDroid可以帮助您轻松搞定这个问题&#xff0c;您可以将An…

产业大数据应用:洞察企业全维数据,提升企业监、管、服水平

​在数字经济时代&#xff0c;数据已经成为重要的生产要素&#xff0c;数字化改革风生水起&#xff0c;在新一代科技革命、产业革命的背景下&#xff0c;产业大数据服务应运而生&#xff0c;为区域产业发展主导部门提供了企业洞察、监测、评估工具。能够助力区域全面了解企业经…

output delay 约束

output delay 约束 一、output delay约束概述二、output delay约束系统同步三、output delay约束源同步 一、output delay约束概述 特别注意&#xff1a;在源同步接口中&#xff0c;定义接口约束之前&#xff0c;需要用create_generated_clock 先定义送出的随路时钟。 二、out…

【优选算法题练习】day9

文章目录 一、DP35 【模板】二维前缀和1.题目简介2.解题思路3.代码4.运行结果 二、面试题 01.01. 判定字符是否唯一1.题目简介2.解题思路3.代码4.运行结果 三、724. 寻找数组的中心下标1.题目简介2.解题思路3.代码4.运行结果 总结 一、DP35 【模板】二维前缀和 1.题目简介 DP…

百度智能云连拿四年第一,为什么要深耕AI公有云市场

AI是过去几年云计算市场中的最大变量&#xff0c;而大模型的成熟&#xff0c;毫无疑问将指数级增强这个变量。 记得在2022年年底&#xff0c;生成式AI与大模型开始爆火的时候&#xff0c;我们就曾讨论过一个问题&#xff1a;这轮AI浪潮中&#xff0c;最先受到深刻影响的将是云计…

Oracle 多条记录根据某个字段获取相邻两条数据间的间隔天数,小于31天的记录都筛选出来

需求描述&#xff1a;在Oracle中 住院记录记录表为v_hospitalRecords&#xff0c;表中FIHDATE入院时间&#xff0c;FBIHID是住院号&#xff0c; 我想查询出每个患者在他们的所有住院记录中是否在一个月内再次入院(相邻的两条记录进行比较)&#xff0c;并且住院记录大于一的患者…

qsort的使用及模拟实现

qsort函数是C语言库中提供的一种快速排序&#xff0c;头文件是stdlib.h qsort的使用 qsort函数需要四个参数&#xff1a; 1.排序的起始位置的地址&#xff08;数组名&#xff09;: arr 2.排序元素的个数&#xff1a; sizeof&#xff08;arr)/sizeof(arr[0]) 3.排序元素…

echarts 饼图中间添加文字

需求&#xff1a;饼图中间展示总量数据 方法一、设置series对应饼图的label属性 series: [{type: "pie",radius: [55%, 62%],center: ["67%", "50%"],itemStyle: {borderRadius: 10,borderColor: #fff,borderWidth: 2},// 主要代码在这里label: …

protobuf入门实践1

protobuf入门实践1 下载和安装 protobuf&#xff1a;https://github.com/google/protobuf 解压压缩包&#xff1a;unzip protobuf-master.zip 2、进入解压后的文件夹&#xff1a;cd protobuf-master 3、安装所需工具&#xff1a;sudo apt-get install autoconf automake libt…

PostgreSQL数据库动态共享内存管理器——Dynamic shared memory areas

dsm.c提供的功能允许创建后端进程间共享的共享内存段。DSA利用多个DSM段提供共享内存heap&#xff1b;DSA可以利用已经存在的共享内存&#xff08;DSM段&#xff09;也可以创建额外的DSM段。和系统heap使用指针不同的是&#xff0c;DSA提供伪指针&#xff0c;可以转换为backend…

python与深度学习(六):CNN和手写数字识别二

目录 1. 说明2. 手写数字识别的CNN模型测试2.1 导入相关库2.2 加载数据和模型2.3 设置保存图片的路径2.4 加载图片2.5 图片预处理2.6 对图片进行预测2.7 显示图片 3. 完整代码和显示结果4. 多张图片进行测试的完整代码以及结果 1. 说明 本篇文章是对上篇文章训练的模型进行测试…

工具推荐:Linux Busybox

文章首发地址 BusyBox是一个开源的、轻量级的、可嵌入式的、多个Unix工具的集合。BusyBox提供了各种Unix工具的实现&#xff0c;包括文件处理工具、网络工具、shell工具、系统管理工具、进程管理工具等等。它被设计为一个小巧、高效、可靠、易于维护的工具&#xff0c;适用于嵌…

微服务——服务异步通讯RabbitMQ

前置文章 消息队列——RabbitMQ基本概念容器化部署和简单工作模式程序_北岭山脚鼠鼠的博客-CSDN博客 消息队列——rabbitmq的不同工作模式_北岭山脚鼠鼠的博客-CSDN博客 消息队列——spring和springboot整合rabbitmq_北岭山脚鼠鼠的博客-CSDN博客 目录 Work queues 工作队列…

设计模式 - 工厂模式

一、 简单工厂&#xff08;Simple Factory Pattern&#xff09; 1、概念 一个工厂对象决定创建出哪一种产品类的实力&#xff0c;但不属于GOF23种设计模式。 简单工厂适用于工厂类负责创建的对象较少的场景&#xff0c;且客户端只需要传入工厂类的参数&#xff0c;对于如何创…

Andrew算法求凸包模板

前置知识 向量的叉乘: 设 a ⃗ ( x a , y a , z a ) , b ⃗ ( x b , y b , z b ) \vec a(x_a,y_a,z_a), \vec b(x_b, y_b,z_b) a (xa​,ya​,za​),b (xb​,yb​,zb​), 令 a ⃗ \vec a a 和 b ⃗ \vec b b 的叉乘为 c ⃗ \vec c c , 有: c ⃗ ∣ i j k x a y a z a x b y…

【深度学习】GPT-3

2020年5月&#xff0c;OpenAI在长达72页的论文《https://arxiv.org/pdf/2005.14165Language Models are Few-Shot Learners》中发布了GPT-3&#xff0c;共有1750亿参数量&#xff0c;需要700G的硬盘存储&#xff0c;(GPT-2有15亿个参数)&#xff0c;它比GPT-2有了极大的改进。根…