首页 > 系统相关 >内存管理-19-vmlinux.lds.S分析

内存管理-19-vmlinux.lds.S分析

时间:2024-07-15 20:52:59浏览次数:12  
标签:__ vmlinux 19 text ALIGN lds -- init TEXT

基于msm-5.4

一、简介

链接器主要任务是将符号引用解析到符号定义上,将多个目标文件(.o)和库文件合并成为一个可执行文件或者动态链接库,生成符号表,并对程序代码做最后的检查和优化。这个链接脚本在Linux内核里就是 vmlinux.lds.S 文件。

vmlinux.lds.S 编译后会在 out/target 目录下生成一个 vmlinux.lds 文件,这个文件是各种宏展开后的。

 

二、文件分析

1. SECTIONS 

vmlinux.lds.S 文件是一个 "SECTIONS { }" 描述,它是链接脚本的关键命令,用以描述输出文件的内存布局。告诉链接文件如何把输入文件的段映射到输出文件的各个段中,如何将输入段整合为输出段,如何把输出段放入程序地址空间和进程地址空间中。

2. /DISCARD/ 段

这是一个特殊的输出段,被该段引用的任何输入段,将不会出现在输出文件中。

3. .head.text 段

    . = KIMAGE_VADDR + TEXT_OFFSET; //0xffffffc010000000 + 0x00080000 
    .head.text : {
        _text = .;
        HEAD_TEXT
    }

'.' 号是连接脚本中一个特殊的符号,用以表示当前位置计数器。######表示将当前位置的地址设置为等号右边的值,此处表示把代码段地址设置为 0xffffffc010080000。

.head.text 是输出段的名称,对应的输入段是 HEAD_TEXT, HEAD_TEXT 定义为 KEEP(*(.head.text))。意思是将所有输入目标文件(.o文件)中的 .head.text 都放入 .head.text 输出段中。

通过 readelf -S vmlinux 来看:

ubuntu:$ readelf -S vmlinux
Section Headers:
-------------------------------------------------------------------------------------------------------------------------
[Nr]   Name       Type      Address           Offset       Size              EntSize           Flags  Link  Info  Align
-------------------------------------------------------------------------------------------------------------------------
[ 1]  .head.text  PROGBITS  ffffffc010000000  00010000     0000000000001000  0000000000000000  AX     0     0     4096

可以看到每个段的起始地址和占用多大空间,对齐方式,可执行权限等。

4. text代码段

定义代码段,区间为 [_stext, _etext).

    .text : {
        _stext = .;
        ...
    }
    . = ALIGN(SEGMENT_ALIGN); //64k
    _etext = .;

5. rodata只读数据段

rodata段是一个非常大的段,里面又进行了很多细分。定义只读数据段内容,区间为 [__start_rodata, __end_rodata);
另外,ALIGN(PAGE_SIZE)表示只读数据段的起始地址、结束地址,都需要页对齐。

//vmlinux.lds.S 
RO_DATA(PAGE_SIZE)

//vmlinux.lds.h 
#define RO_DATA(align)  RO_DATA_SECTION(align) //传参align=4096
#define RO_DATA_SECTION(align) \
    /*
     * 1. PCI quirks
     * 2. Built-in firmware blobs
     * 3. Kernel symbol table: Normal symbols
     * 4. Kernel symbol table: GPL-only symbols
     * 5. Kernel symbol table: Normal unused symbols
     * 6. Kernel symbol table: GPL-only unused symbols
     * 7. Kernel symbol table: GPL-future-only symbols
     * 8. Kernel symbol table: Normal symbols
     * 9. Kernel symbol table: GPL-only symbols
     * 10. Kernel symbol table: Normal unused symbols
     * 11. Kernel symbol table: GPL-only unused symbols
     * 12. Kernel symbol table: GPL-future-only symbols
     * 13. Kernel symbol table: strings
     * 14. __*init sections
     * 15. Built-in module parameters. 
     * 16. Built-in module versions.
     */

9. __ex_table 扩展页表段

定义扩展页表段内容,区间为 [__start___ex_table, __stop___ex_table)

//vmlinux.lds.S 
EXCEPTION_TABLE(8)

//vmlinux.lds.h 
#define EXCEPTION_TABLE(align)                        \
    . = ALIGN(align);                        \
    __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) {        \
        __start___ex_table = .;                    \
        KEEP(*(__ex_table))                    \
        __stop___ex_table = .;                    \
    }

10. 页表地址段

    . = ALIGN(PAGE_SIZE);
    idmap_pg_dir = .;
    . += IDMAP_DIR_SIZE; //IDMAP_PGTABLE_LEVELS * PAGE_SIZE = 3*12K = 36K
    idmap_pg_end = .;

#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 //默认使能
    tramp_pg_dir = .;
    . += PAGE_SIZE; //4K
#endif

    reserved_pg_dir = .;
    . += PAGE_SIZE; //4K

    swapper_pg_dir = .;
    . += PAGE_SIZE; //4K

    INIT_TEXT_SECTION(8) //.init.text 段, 就是 __init 修饰的函数存放的段

在 .init.text 段之前,会预留一部分虚拟地址空间给一些页表初始化使用。例如,idmap_pg_dir、tramp_pg_dir、reserved_pg_dir、swapper_pg_dir 等。

idmap_pg_dir 是 identity mapping 使用到的页表。

11. init 段

初始化段范围是 [ __init_begin, __init_end),包括了这里的 inittext 段,以及后面 initdata 段,在 kernel_init() 中内核初始化完成,会将这部分内存释放掉,详细看 free_initmem() 函数。

也就是说 init初始化段,并不是Linux内核起始代码段的位置。

    . = ALIGN(SEGMENT_ALIGN); //16k
    __init_begin = .;
    __inittext_begin = .;

    INIT_TEXT_SECTION(8) //.init.text 段, 就是 __init 修饰的函数存放的段

    __exittext_begin = .;
    .exit.text : {
        ARM_EXIT_KEEP(EXIT_TEXT) //*(.exit.text)/*(.text.exit
    }
    __exittext_end = .;

    . = ALIGN(4);
    .altinstructions : {
        __alt_instructions = .;
        *(.altinstructions)
        __alt_instructions_end = .;
    }
    .altinstr_replacement : {
        *(.altinstr_replacement)
    }

    . = ALIGN(PAGE_SIZE);
    __inittext_end = .; //inittext结束

    __initdata_begin = .; initdata开始
    .init.data : {
        INIT_DATA
        INIT_SETUP(16)
        INIT_CALLS
        CON_INITCALL
        INIT_RAM_FS
        *(.init.rodata.* .init.bss)    /* from the EFI stub */
    }
    .exit.data : { //输出文件中段名
        ARM_EXIT_KEEP(EXIT_DATA) //输入目标.o文件中的段名
    }

    PERCPU_SECTION(L1_CACHE_BYTES)

    .rela.dyn : ALIGN(8) {
        *(.rela .rela*)
    }

    __rela_offset    = ABSOLUTE(ADDR(.rela.dyn) - KIMAGE_VADDR);
    __rela_size    = SIZEOF(.rela.dyn);

    . = ALIGN(SEGMENT_ALIGN);
    __initdata_end = .;
    __init_end = .;

释放init段的函数:

//arch/arm64/mm/init.c
void free_initmem(void)
{
    free_reserved_area(lm_alias(__init_begin), lm_alias(__init_end), 0, "unused kernel");
    unmap_kernel_range((u64)__init_begin, (u64)(__init_end - __init_begin));
}
11.2 inittext 段

链接脚本见"init 段"小节。注意,本小节分析的是 inittext段(自己起的名字),而不是 .init.text 段。

inittext段区间为:[__inittext_begin, __inittext_end),包括:

.init.text
*(.exit.text)
*(.text.exit)

percpu段竟然也在这个段中。

11.2.1 .init.text 段

通过宏 INIT_TEXT_SECTION() 指定,将目标文件中的 *.init.text, *.init.text.*, *.text.startup 段放入 .init.text 段中。

11.2.2 .exit.text 段

里面存放目标文件的 *(.exit.text), *(.text.exit) 段。


11.3 initdata 段

本节剖析的是 initdata 段(自己起的名字),而不仅仅是 .init.data,initdata 区间为 [__initdata_begin,__initdata_end), 其中包括:
.init.data 段,.exit.data 段,data..percpu 段,.rela.dyn 段。
.init.data 又包括:INIT_DATA, INIT_SETUP, INIT_CALLS, CON_INITCALL, INIT_RAM_FS, .init.rodata.*, .init.bss

注:
INIT_DATA 里面包含众多种类,包括 *.init.rodata, *.init.rodata.* 等等。
INIT_CALLS 区间[__initcall_start, __initcall_end),里面包含0-7的 INIT_CALLS_LEVEL()

initdata 中还有个重要的 .data.percpu 段,通过 PERCPU_SECTION 进行定义。

12. .bss 段

通过宏 BSS_SECTION(0, 0, 0) 定义bss段内容,区间为 [_bss_start, __bss_stop).

13. 镜像结尾段

    . = ALIGN(PAGE_SIZE);
    init_pg_dir = .;
    . += INIT_DIR_SIZE;
    init_pg_end = .;

    __pecoff_data_size = ABSOLUTE(. - __initdata_begin);
    _end = .;

定义了 init_pg_dir,这是临时页表初始化页表,对于三级页表,会占用 3 个pages 空间。在页表映射完成之后,这部分的内存会被释放掉,变成普通内存供 buddy 使用。

 

三、代码分析

1. 设置编译到哪个段中

//include/linux/init.h
#define __init    __section(.init.text)
#define __exit    __section(.exit.text)

static int __init led_init(void)
static void __exit led_exit(void)

 

四、readelf命令

readelf命令在主机和开发板上都存在。

ubuntu: $ readelf --help
Usage: readelf <option(s)> elf-file(s)
显示有关 ELF 格式文件内容的信息
选项为:
-a --all 相当于:-h -l -S -s -r -d -V -A -I
-h --file-header 显示 ELF 文件头
-l --program-headers 显示程序头
   --segments --program-headers 的别名
-S --section-headers 显示节的头
   --sections --section-headers 的别名
-g --section-groups 显示节组
-t --section-details 显示节详细信息
-e --headers 相当于:-h -l -S
-s --syms 显示符号表 ####### 可以对比机器运行状态和vmlinux文件里面的
   --symbols --syms 的别名
--dyn-syms 显示动态符号表
-n --notes 显示核心注释(如果存在)
-r --relocs 显示重定位(如果存在)
-u --unwind 显示展开信息(如果存在)
-d --dynamic 显示动态部分(如果存在)
-V --version-info 显示版本部分(如果存在)
-A --arch-specific 显示体系结构特定信息(如果有)
-c --archive-index 显示存档中的符号/文件索引
-D --use-dynamic 显示符号时使用动态部分信息
-x --hex-dump=<number|name> 将 section <number|name> 的内容转储为字节
-p --string-dump=<number|name> 将 section <number|name> 的内容转储为字符串
-R --relocated-dump=<number|name> 将 section <number|name> 的内容转储为重定位字节
-z --decompress 在转储之前解压缩section
-w[lLiaprmfFsoRt] 或 --debug-dump[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,
=frames-interp,=str,=loc,=Ranges,=pubtypes,=gdb_index,=trace_info,=trace_abbrev,=trace_aranges,=addr,=cu_index] 显示 DWARF2 调试sections的内容
--dwarf-depth=N 不显示深度为 N 或更大的 DIE
--dwarf-start=N 显示以 N 开头、深度相同或更深的 DIE
-I --histogram 显示 bucket list 长度的直方图
-W --wide 允许输出宽度超过 80 个字符
@<file> 从 <file> 读取选项
-H --help 显示此信息
-v --version 显示 readelf 的版本号

 

五、vmlinux.lds.S文件

/* SPDX-License-Identifier: GPL-2.0 */
/*
 * ld script to make ARM Linux kernel
 * taken from the i386 version by Russell King
 * Written by Martin Mares <[email protected]>
 */

#ifdef CONFIG_QCOM_RTIC
#define BSS_FIRST_SECTIONS                \
    . = ALIGN(PAGE_SIZE);                \
    KEEP(*(.bss.rtic))                \
    . = ALIGN(PAGE_SIZE);
#else
#define BSS_FIRST_SECTIONS
#endif

#include <asm-generic/vmlinux.lds.h>
#include <asm/cache.h>
#include <asm/kernel-pgtable.h>
#include <asm/thread_info.h>
#include <asm/memory.h>
#include <asm/page.h>
#include <asm/pgtable.h>

#include "image.h"

/* .exit.text needed in case of alternative patching */
#define ARM_EXIT_KEEP(x)    x
#define ARM_EXIT_DISCARD(x)

OUTPUT_ARCH(aarch64) //标识是Arm64平台
ENTRY(_text)         //指定程序的入口地址是 _text,代码段 _text -- _etext

jiffies = jiffies_64; //指定jiffies


#define HYPERVISOR_EXTABLE                    \
    . = ALIGN(SZ_8);                    \
    __start___kvm_ex_table = .;                \
    *(__kvm_ex_table)                    \
    __stop___kvm_ex_table = .;

#define HYPERVISOR_TEXT                    \
    /*                        \
     * Align to 4 KB so that            \
     * a) the HYP vector table is at its minimum    \
     *    alignment of 2048 bytes            \
     * b) the HYP init code will not cross a page    \
     *    boundary if its size does not exceed    \
     *    4 KB (see related ASSERT() below)        \
     */                        \
    . = ALIGN(SZ_4K);                \
    __hyp_idmap_text_start = .;            \
    *(.hyp.idmap.text)                \
    __hyp_idmap_text_end = .;            \
    __hyp_text_start = .;                \
    *(.hyp.text)                    \
    HYPERVISOR_EXTABLE                \
    __hyp_text_end = .;

#define IDMAP_TEXT                    \
    . = ALIGN(SZ_4K);                \
    __idmap_text_start = .;                \
    *(.idmap.text)                    \
    __idmap_text_end = .;

#ifdef CONFIG_HIBERNATION //默认不使能
#define HIBERNATE_TEXT                    \
    . = ALIGN(SZ_4K);                \
    __hibernate_exit_text_start = .;        \
    *(.hibernate_exit.text)                \
    __hibernate_exit_text_end = .;
#else
#define HIBERNATE_TEXT
#endif

#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
#define TRAMP_TEXT                    \
    . = ALIGN(PAGE_SIZE);                \
    __entry_tramp_text_start = .;            \
    *(.entry.tramp.text)                \
    . = ALIGN(PAGE_SIZE);                \
    __entry_tramp_text_end = .;
#else
#define TRAMP_TEXT
#endif

/*
 * The size of the PE/COFF section that covers the kernel image, which
 * runs from stext to _edata, must be a round multiple of the PE/COFF
 * FileAlignment, which we set to its minimum value of 0x200. 'stext'
 * itself is 4 KB aligned, so padding out _edata to a 0x200 aligned
 * boundary should be sufficient.
 */
PECOFF_FILE_ALIGNMENT = 0x200;

#ifdef CONFIG_EFI
#define PECOFF_EDATA_PADDING    \
    .pecoff_edata_padding : { BYTE(0); . = ALIGN(PECOFF_FILE_ALIGNMENT); }
#else
#define PECOFF_EDATA_PADDING
#endif

SECTIONS
{
    /*
     * XXX: The linker does not define how output sections are
     * assigned to input sections when there are multiple statements
     * matching the same input section name.  There is no documented
     * order of matching.
     */
    /DISCARD/ : {
        ARM_EXIT_DISCARD(EXIT_TEXT)
        ARM_EXIT_DISCARD(EXIT_DATA)
        EXIT_CALL
        *(.discard)
        *(.discard.*)
        *(.interp .dynamic)
        *(.dynsym .dynstr .hash .gnu.hash)
        *(.eh_frame)
    }

    . = KIMAGE_VADDR + TEXT_OFFSET; //0xffffffc010000000 + 0x00080000 内核起始虚拟地址+偏移32K的位置(内核镜像前16K预留出来给初始化页表使用)

    .head.text : {
        _text = .;
        HEAD_TEXT
    }
    .text : {            /* Real text segment        */
        _stext = .;        /* Text and read-only data    */
            __exception_text_start = .;
            *(.exception.text)
            __exception_text_end = .;
            IRQENTRY_TEXT  //定义在vmlinux.lds.h, 存放 *(.irqentry.text)
            SOFTIRQENTRY_TEXT //定义在vmlinux.lds.h, 存放 *(.softirqentry.text)
            ENTRY_TEXT //定义在vmlinux.lds.h, 存放 *(.entry.text)
            TEXT_TEXT //定义在vmlinux.lds.h, 存放 *(.test.*)
            SCHED_TEXT //定义在vmlinux.lds.h, 存放 *(.sched.text)
            CPUIDLE_TEXT //定义在vmlinux.lds.h, 存放 *(.cpuidle.text)
            LOCK_TEXT //定义在vmlinux.lds.h, 存放 *(.spinlock.text)
            KPROBES_TEXT //定义在vmlinux.lds.h, 存放 *(.kprobes.text)
            HYPERVISOR_TEXT //定义在本文件中,hypervisor相关
            IDMAP_TEXT //定义在本文件中,存放 *(.idmap.text)
            HIBERNATE_TEXT //默认空实现
            TRAMP_TEXT
            *(.fixup)
            *(.gnu.warning)
        . = ALIGN(16);
        *(.got)            /* Global offset table        */
    }

    . = ALIGN(SEGMENT_ALIGN);
    _etext = .;            /* End of text section */

    RO_DATA(PAGE_SIZE)        /* everything from this point to     */
    EXCEPTION_TABLE(8)        /* __init_begin will be marked RO NX */
    NOTES

    . = ALIGN(PAGE_SIZE);
    idmap_pg_dir = .;
    . += IDMAP_DIR_SIZE;
    idmap_pg_end = .;

#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
    tramp_pg_dir = .;
    . += PAGE_SIZE;
#endif

    reserved_pg_dir = .;
    . += PAGE_SIZE;

    swapper_pg_dir = .;
    . += PAGE_SIZE;

    . = ALIGN(SEGMENT_ALIGN); //16k
    __init_begin = .;
    __inittext_begin = .;

    INIT_TEXT_SECTION(8) //.init.text 段, 就是 __init 修饰的函数存放的段

    __exittext_begin = .;
    .exit.text : {
        ARM_EXIT_KEEP(EXIT_TEXT)
    }
    __exittext_end = .;

    . = ALIGN(4);
    .altinstructions : {
        __alt_instructions = .;
        *(.altinstructions)
        __alt_instructions_end = .;
    }
    .altinstr_replacement : {
        *(.altinstr_replacement)
    }

    . = ALIGN(PAGE_SIZE);
    __inittext_end = .;
    __initdata_begin = .;

    .init.data : {
        INIT_DATA
        INIT_SETUP(16)
        INIT_CALLS
        CON_INITCALL
        INIT_RAM_FS
        *(.init.rodata.* .init.bss)    /* from the EFI stub */
    }
    .exit.data : {
        ARM_EXIT_KEEP(EXIT_DATA)
    }

    PERCPU_SECTION(L1_CACHE_BYTES)

    .rela.dyn : ALIGN(8) {
        *(.rela .rela*)
    }

    __rela_offset    = ABSOLUTE(ADDR(.rela.dyn) - KIMAGE_VADDR);
    __rela_size    = SIZEOF(.rela.dyn);

#ifdef CONFIG_RELR //默认不使能
    .relr.dyn : ALIGN(8) {
        *(.relr.dyn)
    }

    __relr_offset    = ABSOLUTE(ADDR(.relr.dyn) - KIMAGE_VADDR);
    __relr_size    = SIZEOF(.relr.dyn);
#endif

    . = ALIGN(SEGMENT_ALIGN);
    __initdata_end = .;
    __init_end = .;

    _data = .;
    _sdata = .; //数据段,已初始化
    RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_ALIGN)

    /*
     * Data written with the MMU off but read with the MMU on requires
     * cache lines to be invalidated, discarding up to a Cache Writeback
     * Granule (CWG) of data from the cache. Keep the section that
     * requires this type of maintenance to be in its own Cache Writeback
     * Granule (CWG) area so the cache maintenance operations do not
     * interfere with adjacent data.
     */
    .mmuoff.data.write : ALIGN(SZ_2K) {
        __mmuoff_data_start = .;
        *(.mmuoff.data.write)
    }
    . = ALIGN(SZ_2K);
    .mmuoff.data.read : {
        *(.mmuoff.data.read)
        __mmuoff_data_end = .;
    }

    PECOFF_EDATA_PADDING
    __pecoff_data_rawsize = ABSOLUTE(. - __initdata_begin);
    _edata = .;

    BSS_SECTION(0, 0, 0) //bss段

    . = ALIGN(PAGE_SIZE);
    init_pg_dir = .;
    . += INIT_DIR_SIZE;
    init_pg_end = .;

    __pecoff_data_size = ABSOLUTE(. - __initdata_begin);
    _end = .;

    STABS_DEBUG

    HEAD_SYMBOLS
}

#include "image-vars.h"

/*
 * The HYP init code and ID map text can't be longer than a page each,
 * and should not cross a page boundary.
 */
ASSERT(__hyp_idmap_text_end - (__hyp_idmap_text_start & ~(SZ_4K - 1)) <= SZ_4K,
    "HYP init code too big or misaligned")
ASSERT(__idmap_text_end - (__idmap_text_start & ~(SZ_4K - 1)) <= SZ_4K,
    "ID map text too big or misaligned")
#ifdef CONFIG_HIBERNATION
ASSERT(__hibernate_exit_text_end - (__hibernate_exit_text_start & ~(SZ_4K - 1))
    <= SZ_4K, "Hibernate exit text too big or misaligned")
#endif
#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
ASSERT((__entry_tramp_text_end - __entry_tramp_text_start) <= 3*PAGE_SIZE,
    "Entry trampoline text too big")
#endif
/*
 * If padding is applied before .head.text, virt<->phys conversions will fail.
 */
ASSERT(_text == (KIMAGE_VADDR + TEXT_OFFSET), "HEAD is misaligned")

 

六、vmlinux.lds 文件

TODO

 

标签:__,vmlinux,19,text,ALIGN,lds,--,init,TEXT
From: https://www.cnblogs.com/hellokitty2/p/18303943

相关文章

  • 基于Go1.19的站点模板爬虫
    一、go语言简介Go(也被称为Golang)是一种开源的编程语言,由Google公司于2007年开始开发,并在2009年对外公开发布。Go语言的设计目标是提供一种简单、高效、安全的编程语言,适合并发编程和网络编程。以下是Go语言的一些特点和优势:简单易学:Go语言的语法简洁明了,只有25个关键字,......
  • CF1983E I Love Balls
    题意\(n\)个小球,有\(k\)个特殊小球,两个人轮流随机拿,每个小球有权值,如果拿到特殊球就再拿一个,问两个人的期望得分。题解关键1如果没有特殊小球,那么每个球是等价的,计算期望的时候可以直接用平均值作为一个小球的权值,把每个小球的权值都看成平均值关键2把拿取操作看成一个序......
  • 每日一题- CF1983F
    从未每日的每日一题E>F但是没时间了#include<bits/stdc++.h>usingnamespacestd;#definelllonglongintt,n,a[100005],p[100005];inttr[3200005][2],id[3200005],cnt;llk;voidinit(){ for(inti=1;i<=cnt;i++)tr[i][0]=tr[i][1]=0,id[i]=0; cnt=1;}intcalc(......
  • 折腾记:尝试Hyper-V Server2019 部署配置
    镜像下载(微软官方)下载地址使用rufus写入U盘https://rufus.ie/zh/正常安装系统下载配置脚本https://file.uhsea.com/2407/247fe11846307d5eacedeb96a94f39e5MF.ps1https://www.doracloud.cn/downloads/hypervps1-cn.html打开powershell命令行中输入startpowershell就可......
  • P2754 [CTSC1999] 家园 / 星际转移问题题解
    开始时,将源点连一条权值为\(k\)的边到地球。然后以时间分层,从上一层的点连接到下一层的点,权值为飞船载人数量,并将代表月球的点连接到汇点。每加一层,在上一层的基础上进行增广,看能不能增加流量,如果流量变为\(k\),那么证明运送完成。可以证明枚举时间最多到\(1500\),图的点数不......
  • codeforces 1980 E. Permutation of Rows and Columns
    题目链接https://codeforces.com/problemset/problem/1980/E题意共输入\(T\)组测试用例,每组测试用例第一行输入两个整数\(n,m\),分别代表输入的数据的行数和列数,其中\(n*m\leq2*10^5\)。接下来输入两个\(n\)行\(m\)列的矩阵\(a,b\),对于每个矩阵中的元素\(x_{i,j}\)都是......
  • 银河麒麟V10SP1搭建oracle19c(单库)
    遇到的坑:1.PRVG-0282问题解决:在先决条件检查步骤,PRVG-0282:无法检索操作系统分发ID的报错,该问题是由于字符集和环境变量问题,只需在执行安装前:使用oracle用户登录,不要root跳到oracle用户下exportCV_ASSUME_DISTID=RHEL7.6exportLANG=en_US然后刷新环境变量在执行./runInstal......
  • 题解:CodeForces 1019 A Elections[贪心/三分]
    CodeForces1019AA.Electionstimelimitpertest:2secondsmemorylimitpertest:256megabytesinput:standardinputoutput:standardoutputAsyouknow,majorityofstudentsandteachersofSummerInformaticsSchoolliveinBerlandforthemostparto......
  • [CF1941E] Rudolf and k Bridges 的题解
    题目大意在第\((i,j)\)个格子修建一个桥墩需要\(a_{i,j}+1\)的花费而且要求\((i,0)\)与\((i,m)\)必须修建桥墩并且桥墩之间的距离不得大于\(d\)。现在需要求见\(k\)个连续的桥,求最小代价。其中\(1\lek\len\le100,3\lem\le2\cdot10,1\led\lem\)。思路因为......
  • 旷野之间19 - Nvidia 首席执行官建议不要学习编码
    50年前出现的许多技术都遵循了两种轨迹之一:它们要么发展以跟上现代的步伐,要么消失得无影无踪。一个例子是1938年推出的第一台可编程机械计算机。由于内存限制,它的操作能力有限,而且重量很重,很难想象今天在我们的家中或工作场所放置这样的设备。确实,有许多技术远见者对计算......