linux内核特点:

  • 支持模块化:模块文件的名字以.ko(kernel object)结尾
  • 支持内核运行时,动态加载和卸载模块文件。

linux内核组成部分:

  • 核心文件:/boot/vmlinuz-VERSION-release

    # ll /boot/vmlinuz-3.10.0-957.el7.x86_64
    -rwxr-xr-x. 1 root root 6639904 Nov 9 2018 /boot/vmlinuz-3.10.0-957.el7.x86_64
    # file /boot/vmlinuz-3.10.0-957.el7.x86_64
    /boot/vmlinuz-3.10.0-957.el7.x86_64: Linux kernel x86 boot executable bzImage, version 3.10.0-957.el7.x86_64 (mockbuild@kbuilder.bsys.centos.org) #1 S, RO-rootFS, swap_dev 0x6, Normal VGA
  • 模块文件:/lib/modules/VERSION-release

    如果按照了多个内核版本,则/lib/modules下,有多个目录

    # ll /lib/modules
    drwxr-xr-x. 8 root root 4096 Feb 20 10:03 3.10.0-957.el7.x86_64

    3.10.0-957.el7.x86_64目录下的文件:

    # ls /lib/modules/3.10.0-957.el7.x86_64/
    build modules.alias modules.builtin.bin modules.drm modules.softdep updates
    extra modules.alias.bin modules.dep modules.modesetting modules.symbols vdso
    kernel modules.block modules.dep.bin modules.networking modules.symbols.bin weak-updates
    misc modules.builtin modules.devname modules.order source

    其中有:kernel目录

    # ls /lib/modules/3.10.0-957.el7.x86_64/kernel/
    arch crypto drivers fs kernel lib mm net sound virt

    arch:平台特有;crypto:加密/解密;drivers:驱动管理;mm:内存管理。fs:文件系统;net:网络管理;sound:声卡驱动

  • ramdisk:

    ramdisk的由来:操作系统不知道用户的电脑上的磁盘设备是什么型号的,访问特定磁盘是要使用特定的磁盘驱动程序的,所以操作系统可能就要把市面上主流的磁盘驱动程序都准备好,放入安装盘中,这样一来安装盘太臃肿。为了解决这个问题,操作系统不准备任何磁盘驱动程序,而是在安装操作系统的过程中,扫描用户的硬件,根据硬件自动生成磁盘驱动程序,并把这个驱动程序存放入磁盘中。

    开机后,内核被装载到内存后,就要去从磁盘找根文件系统。内核要想访问磁盘,必须需要访问磁盘的驱动程序,可是磁盘的驱动程序又在根文件系统里,所以内核就无法找到磁盘的驱动程序,也就无法访问磁盘。所以需要一个临时的根文件系统,在里面放磁盘的驱动程序。这个临时的驱动程序和根文件系统,是在安装操作系统时,由安装程序扫描机器的硬件后,根据硬件的型号自动生成的。有了这个东西后,内核就先把一段内存模拟成磁盘,把这个东西放到内存中,从它的里面取得到磁盘驱动,然后使用好不容易得到的驱动程序,去访问真的磁盘,得到真的根文件系统。然后真的根文件系统,取代这个东西。

    这个东西叫:ramdisk。

    我们使用free命令,可以看到buff和cache。为什么有buff和cache呢?因为磁盘IO太慢,所以把经常访问的磁盘上的数据,载入内存的buff和cache区域。

    # free
    total used free shared buff/cache available
    Mem: 3880164 459420 2525300 12596 895444 3076684
    Swap: 4063228 0 4063228

    centos5:/boot/initrd-VERSION-release.img

    由于是用内存模拟磁盘,所以内存又使用buff和cache机制,缓存了磁盘的内容,造成了双重buff和cache。

    centos6,7:/boot/initramfsVERSION-release.img

    为了防止双重buffer和cache,centos6和7使用ramfs,ramfs是文件系统,就防止了双重buff和cache。

    # ll /boot/initramfs-3.10.0-957.el7.x86_64.img
    -rw-------. 1 root root 31489644 Nov 29 17:11 /boot/initramfs-3.10.0-957.el7.x86_64.img

    ramdisk的做成工具程序:

    • centos5:mkinitrd
    • centos6,7:dracut。为了兼容centos5,也可以使用mkinitrd

centos5系统启动流程

前提pc主机,MBR架构

  • 第一步:post(power on system test)加电自检。

    pc机的主板上有个rom芯片(CMOS),加电后,cpu去找这个raw,然后读取里面的指令,检测机器上是否有:内存,硬盘,显示设备等。

    CMOS里有个bios(basic input output system)程序

  • 第二步:boot sequence(bios里设置是用光盘启动,还是硬盘启动等)

    按次序查找引导设备,第一个有引导程序(bootloader)的设备即为本次启动要用到的设备。

    bootloader:

    • 功能:

      • 找到磁盘上的grub程序,并加载运行之。
      • grub提供一个可以让用户选择的菜单,上面写着,可以选择运行的内核列表
      • 把用户选定的内核程序从磁盘加载到内存的特定空间中,然后解压,展开,此后,内核就开始真正运行起来了,然后bootloader退出,由内核接管一切。

      注意:由于bootloader仅有446字节,它无法读取LVM,软RAID的逻辑分区,只能读取物理分区,所以内核程序只能存放在物理分区上。

    • 种类:

      • LILO:linux loader。它有个致命弱点,如果内核在磁盘的1024以后的柱面上存储着的话,它无法加载内核。安卓手机用的是LILO。

      • GRUB:Grand Uniform Bootloader

        centos5,6用的版本是:grub 0.x(别名:grub legacy)

        cengtos7用的版本是:grub 1.x(别名:grub2)

    bootloader程序放在哪里了?

    如果是MBR架构,则放在了在0号track(磁道),0号sector(扇区)里 的前446bytes 。

    由于只有446字节,空间太小了,能写的程序实在有限,所以linux使用GRUB机制。

    GRUB机制:不让bootloader直接加载内核,而是让bootloader加载磁盘上的另外一个程序/boot/grub。由于/boot/grub是放在磁盘上的,所以突破了446字节的约束。

    • 第一阶段:bootloader加载/boot/grub程序
    • 第1.5阶段:filesystem driver?
    • 第二阶段:/boot/grub程序加载内核。
  • 第三步:kernel自身初始化

    • 探测所以硬件设备

    • 为了加载磁盘上的根文件系统,所以先加载ramdisk上的文件系统,找到里面的磁盘驱动程序。

      注意:也有可能不使用ramdisk。当自己在自己的机器上编译内核时,编译程序就探测到了本地磁盘类型,所以在编译的时候,就可以把磁盘的驱动,编译到内核里,所以内核就不需要再去找ramdisk了。

    • 使用磁盘驱动,以只读方式,加载根文件系统。只读的目的:防止内核有bug,把根文件系统里面的东西删除了。没问题后,再改为读写方式。

    • 运行用户空间的第一个应用程序:/sbin/init

      centos5之前的init程序:SysV init

      ​ 使用的配置文件:/etc/inittab

      centos6的init程序:Upstart

      ​ 使用的配置文件:/etc/init/*.conf

      centos7的init程序:Systemd

      ​ 使用的配置文件: /usr/lib/systemd/system目录下的文件,和/etc/systemd/system目录下的文件

  • 第四步:/sbin/init会启动/sbin/mingetty程序,显示可以登录的文本界面。

Linux的运行级别

为了系统的维护等目的设定了7个级别(0~6)

  • 级别0:关机 shutdown
  • 级别1:单用户模式(single user),以root用户登录,无需输入root密码。root密码忘记了,使用级别1。输入维护模式。
  • 级别2:多用户模式(multi user),会启动网络功能,但不会启动NFS。属于维护模式。
  • 级别3:多用户模式(multi user),完全功能模式,但不启动图形界面。
  • 级别4:预留级别,没有被使用,但习惯以同3级别功能使用。
  • 级别5:多用户模式(multi user),完全功能模式,开机自动启动图形界面。
  • 级别6:重启 reboot

默认级别是3或5,server用级别3;个人主机用级别5.

切换级别的命令:init 级别

查看当前的级别:who -r或者runlevel

run命令的结果里的N:上一次的级别。由于没切换过级别,所以上一次就是N。

# who -r
run-level 5 2020-02-20 10:03
# runlevel
N 5

init程序的配置文件说明

1,centos5,6:/etc/inittab

每行定义一种action,以及与之对应的process

每一行的格式:id:runlevel:action:process

id:标识

runlevel:运行级别

action:指明启动process的条件

  • wait:当运行级别切换至此行的级别时,执行一次process
  • respawn:一旦此行的process终止,就自动重新启动它
  • initdefault:设定系统开机时默认的运行级别,所以此行的process省略
  • sysinit:设定系统初始化的方式,所以runlevel省略,process一般为/etc/rc.d/rc.sysinit脚本

process:程序

例子:

  • id01:3:initdefault:

    系统开机时,以级别3运行。

  • id02::sysinit:/etc/rc.d/rc.sysinit

    不管以哪个级别运行,都使用/etc/rc.d/rc.sysinit脚本完成系统初始化。

  • id03:3:wait:/etc/rc.d/rc 0

    当切换到级别3后,运行脚本:/etc/rc.d/rc 0一次。

脚本/etc/rc.d/rc的作用:当切换运行级别时,定义先kill哪些进程,然后再启动哪些进程。

  • 脚本参数:运行级别

解释脚本/etc/rc.d/rc之前,先看看目录/etc/rc.d/下的构成。

下面有rc0.d,rc1.d,rc2.d,rc3.d,rc4.d,rc5.d,rc6.d目录

# ll /etc/rc.d/
drwxr-xr-x. 2 root root 4096 Feb 21 09:19 init.d
-rwxr-xr-x. 1 root root 2617 Jun 19 2018 rc
drwxr-xr-x. 2 root root 4096 Feb 21 09:19 rc0.d
drwxr-xr-x. 2 root root 4096 Feb 21 09:19 rc1.d
drwxr-xr-x. 2 root root 4096 Feb 21 09:19 rc2.d
drwxr-xr-x. 2 root root 4096 Feb 21 09:19 rc3.d
drwxr-xr-x. 2 root root 4096 Feb 21 09:19 rc4.d
drwxr-xr-x. 2 root root 4096 Feb 21 09:19 rc5.d
drwxr-xr-x. 2 root root 4096 Feb 21 09:19 rc6.d
-rwxr-xr-x. 1 root root 220 Jun 19 2018 rc.local
-rwxr-xr-x. 1 root root 20199 Jun 19 2018 rc.sysinit

/etc/rc.d/rc的脚本内容摘要:

变量$runlevel,就是执行此脚本时,传进来的参数,也就是运行级别。

# First, run the KILL scripts.
for i in /etc/rc$runlevel.d/K* ; do
#省略
$i stop
#省略
done
# Now run the START scripts.
for i in /etc/rc$runlevel.d/S* ; do
#省略
$i start
#省略
done

所以当运行/etc/rc.d/rc 3的时候,实际运行的脚本的就/etc/rc3.d/目录下的:K*和S*的所有脚本。

查看一下ls /etc/rc.d/rc3.d的目录,发现都是符号链接文件,指向的是/etc/init.d目录下的相应的脚本。其他的rc1.d等目录下也都是符号链接,而且指向的也是/etc/init.d目录下的相应的脚本。所有不管传的运行级别参数是什么,实际运行的脚本都是/etc/init.d下的相应的脚本。

# ll /etc/rc.d/rc3.d/K*
lrwxrwxrwx. 1 root root 15 Jan 31 14:09 /etc/rc.d/rc3.d/K01numad -> ../init.d/numad
lrwxrwxrwx. 1 root root 16 Jan 31 14:09 /etc/rc.d/rc3.d/K01smartd -> ../init.d/smartd
# ll /etc/rc.d/rc3.d/S*
lrwxrwxrwx. 1 root root 17 Jan 31 14:09 /etc/rc.d/rc3.d/S01sysstat -> ../init.d/sysstat
lrwxrwxrwx. 1 root root 22 Jan 31 14:09 /etc/rc.d/rc3.d/S02lvm2-monitor -> ../init.d/lvm2-monitor
lrwxrwxrwx. 1 root root 14 Jan 31 14:09 /etc/rc.d/rc3.d/S05rdma -> ../init.d/rdma

那么,为什么弄出这么多符号链接呢?

观察这些符号链接,发现:K和S的后面都有2位数字。

这2位数字是为了排序用的,/etc/rc.d/rc脚本的for i in /etc/rc$runlevel.d/K* ; do语句,就把以K后S开头的按后面的数字排序了。

  • K##:要被结束的进程。##数字越小,先被结束。所以不被别的进程依赖的进程,数字小。
  • S##:要被启动的进程。##数字越小,先被启动。所以被别的进程依赖的进程,数字小。

启动服务时,都是使用service 服务程序名 start,其实service命令,调用的是就是/etc/init.d目录下的脚本,所以直接运行脚本和使用service命令的效果是一样的,试验如下:

# /etc/init.d/crond stop
Stopping crond: [ OK ]
# /etc/init.d/crond start
Starting crond: [ OK ]
# /etc/init.d/crond status
crond (pid 4822) is running...
# /etc/init.d/crond restart
Stopping crond: [ OK ]
Starting crond: [ OK ]
# service crond status
crond (pid 4850) is running...
# service crond restart
Stopping crond: [ OK ]
Starting crond: [ OK ]
# service crond stop
Stopping crond: [ OK ]
# service crond start
Starting crond: [ OK ]

当想让某个服务进程开机就自动运行的话,在目录/etc/init.d下创建自己的脚本文件:

#!/bin/bash
#
# test servvice
#
# chkconfig: 2345 90 60
# description: test service prog=$(basename $0) if [ $# -lt 1 ]; then
echo "Usage:$prog {start|stop|status|restart}"
exit 1
fi if [ "$1" == "start" ]; then
echo "start $prog done"
elif [ "$1" == "stop" ]; then
echo "stop $prog done"
elif [ "$1" == "restart" ]; then
echo "restart $prog done"
elif [ "$1" == "status" ]; then
if [ pidof $prog &> /dev/null ]; then
echo "$prog is running"
else
echo "$prog is stopped"
fi
else
echo "Usage:$prog {start|stop|status|restart}"
exit 2
fi

注意:chkconfig: 2345 90 60

2345:级别

90:启动优先级

60:终止优先级

有个命令chkconfig可以帮助我们,在rc0.d,rc1.d,rc2.d,rc3.d,rc4.d,rc5.d,rc6.d目录下自动创建符号链接,符号链接的名字:S90mySer.sh和K60mySer.sh。但不是在所以目录都创建,根据写的级别创建,这里写的是2345,所以在rc2.d,rc3.d,rc4.d,rc5.d目录下创建S90mySer.sh和K60mySer.sh

虽然【# chkconfig: 2345 90 60】是注释,但必须有这行。否则,执行chkconfig命令出下面的错误:

# chkconfig mySer.sh on
service mySer.sh does not support chkconfig

使用chkconfig mySer.sh on就是在2345目录下创建S90mySer.sh文件

使用chkconfig mySer.sh off就是在2345目录下创建K90mySer.sh文件

# chkconfig mySer.sh on
# ls /etc/rc.d/rc0.d/ | grep mySer
# ls /etc/rc.d/rc1.d/ | grep mySer
# ls /etc/rc.d/rc2.d/ | grep mySer
S90mySer.sh
# ls /etc/rc.d/rc3.d/ | grep mySer
S90mySer.sh
# ls /etc/rc.d/rc4.d/ | grep mySer
S90mySer.sh
# ls /etc/rc.d/rc5.d/ | grep mySer
S90mySer.sh
# ls /etc/rc.d/rc6.d/ | grep mySer
# chkconfig mySer.sh off
# ls /etc/rc.d/rc0.d/ | grep mySer
# ls /etc/rc.d/rc1.d/ | grep mySer
# ls /etc/rc.d/rc2.d/ | grep mySer
K60mySer.sh
# ls /etc/rc.d/rc3.d/ | grep mySer
K60mySer.sh
# ls /etc/rc.d/rc4.d/ | grep mySer
K60mySer.sh
# ls /etc/rc.d/rc5.d/ | grep mySer
K60mySer.sh
# ls /etc/rc.d/rc6.d/ | grep mySer

有了这些链接文件后,就可以使用service命令,来启动我们的服务了。

# service mySer.sh start
start mySer.sh done
# service mySer.sh stop
stop mySer.sh done
# service mySer.sh restart
restart mySer.sh done

chkconfig选项:

  • 查看:--list [scriptname]

    # chkconfig  --list
    abrt-ccpp 0:off 1:off 2:off 3:on 4:off 5:on 6:off
    abrtd 0:off 1:off 2:off 3:on 4:off 5:on 6:off
    acpid 0:off 1:off 2:on 3:on 4:on 5:on 6:off
    atd 0:off 1:off 2:off 3:on 4:on 5:on 6:off
    auditd 0:off 1:off 2:on 3:on 4:on 5:on 6:off
    autofs 0:off 1:off 2:off 3:on 4:on 5:on 6:off
    # chkconfig --list mySer.sh
    mySer.sh 0:off 1:off 2:on 3:on 4:on 5:on 6:off
  • 指定运行级别:--level LEAVES

    # chkconfig  --list mySer.sh
    mySer.sh 0:off 1:off 2:on 3:on 4:on 5:on 6:off
    # chkconfig --level 35 mySer.sh off
    # chkconfig --list mySer.sh
    mySer.sh 0:off 1:off 2:on 3:off 4:on 5:off 6:off

当只是单纯开机运行某个进程,而不需要额外的脚本的话,直接修改/etc/rc.d/rc.local文件即可。

下面添加了touch /tmp/welcome,所以开机后,就会创建这个文件;

添加了/usr/sbin/httpd,所以开机后,就会启动httpd进程。

#!/bin/sh
#
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init stuff. touch /var/lock/subsys/local
touch /tmp/welcome
/usr/sbin/httpd

为什么编辑/etc/rc.d/rc.local文件就好用呢?

因为这个文件被rc2.d,rc3.d,rc4.d,rc5.d目录里的最后一个文件S99local链接了

# ll /etc/rc.d/rc2.d/ | tail -1
lrwxrwxrwx. 1 root root 11 Jan 31 14:08 S99local -> ../rc.local
# ll /etc/rc.d/rc3.d/ | tail -1
lrwxrwxrwx. 1 root root 11 Jan 31 14:08 S99local -> ../rc.local
# ll /etc/rc.d/rc4.d/ | tail -1
lrwxrwxrwx. 1 root root 11 Jan 31 14:08 S99local -> ../rc.local
# ll /etc/rc.d/rc5.d/ | tail -1
lrwxrwxrwx. 1 root root 11 Jan 31 14:08 S99local -> ../rc.local

系统初始化脚本/etc/rc.d/rc.sysinit的作用:

  • 设置主机名

  • 设置欢迎信息

  • 激活udev(创建设备文件用的)和selinux

  • 挂载/etc/fstab文件中定义的所以文件系统

  • 检测根文件系统,没有问题后,以读写方式重新挂载根文件系统。

  • 读取硬件时钟,设置系统时钟

  • 读取配置文件/etc/sysctl.conf里的内核参数,修改内核的行为。

  • 激活lvm及软raid设备

  • 激活swap设备

  • 从根文件系统,加载硬件的驱动程序

  • 清理操作

总结:/sbin/init的启动流程

1,通过读取配置文件/etc/inittab,获得运行级别

2,执行脚本/etc/rc.d/rc.sysinit,完成系统初始化

3,根据取得的运行级别,先停止这个级别不需要运行的进程(K##),再启动这个级别需要运行的进程(S##)

4,设置登录终端。如果是级别3则登录终端是文本界面

5,如果是级别5,则需要启动图形界面服务,显示图形登录界面;

centos6系统启动流程

基本和centos5相同,只列出不同点

1,init程序:upstart,但依然为/sbin/init。其配置文件不是/etc/inittab了,而是/etc/init/*.conf。但/etc/inittab里也有用,只放默认运行级别一行(id:3:initdefault:)。

2,系统初始化脚本是/etc/init/rcS.conf,但里面运行的是/etc/rc.d/rc.sysinit

3,脚本/etc/init/rc.conf里面,调用/etc/rc.d/rc $RUNLEVEL

centos7系统启动流程

启动流程是一样的,实现的细节不一样。

兼容centos5和6,所以也可以使用service命令。

# service crond start
Redirecting to /bin/systemctl start crond.service
# service crond status
Redirecting to /bin/systemctl status crond.service

centos7使用systemctl命令。

centos7没有了运行级别的概念,改用target概念

  • graphical.target对应运行级别5
  • multi-user.target对应运行级别3

systemctl get-default

# systemctl get-default
graphical.target

centos7的init程序:Systemd

​ 使用的配置文件: /usr/lib/systemd/system目录下的文件,和/etc/systemd/system目录下的文件

# c/c++ 学习互助QQ群:877684253
![](https://img2018.cnblogs.com/blog/1414315/201811/1414315-20181106214320230-961379709.jpg)
# 本人微信:xiaoshitou5854

centos5,6 系统启动流程的更多相关文章

  1. CentOS系统启动流程

    CentOS系统启动流程 POST --> Boot Sequence(BIOS) --> Boot Loader(MBR) --> kernel(ramdisk) --> r ...

  2. CentOS系统启动流程你懂否

    一.Linux内核的组成 相关概念: Linux系统的组成部分:内核+根文件系统 内核:进程管理.内存管理.网络协议栈.文件系统.驱动程序. IPC(Inter-Process Communicati ...

  3. 20190411RAID磁盘阵列及CentOS7系统启动流程

    RAID磁盘阵列及CentOS7系统启动流程(week2_day3)   RAID概念 磁盘阵列(Redundant Arrays of Independent Disks,RAID),有“独立磁盘构 ...

  4. Centos6系统启动流程

    Centos6系统启动流程   一.CentOS 5和6的启动流程 Linux内核:存在于/boot分区,是整个操作系统的最底层,它负责整个硬件的驱动,以及提供各种系统所需的核心功能,包括防火墙机制. ...

  5. Linux操作系统启动流程梳理

    接触linux系统运维已经好几年了,常常被问到linux系统启动流程问题,刚好今天有空来梳理下这个过程:一般来说,所有的操作系统的启动流程基本就是: 总的来说,linux系统启动流程可以简单总结为以下 ...

  6. linux基础-附件1 linux系统启动流程

    附件1 linux系统启动流程 最初始阶段当我们打开计算机电源,计算机会自动从主板的BIOS(Basic Input/Output System)读取其中所存储的程序.这一程序通常知道一些直接连接在主 ...

  7. Linux系统启动流程及安装命令行版本

    Debian安装 之前也安装过很多次linux不同版本的系统,但安装后都是直接带有桌面开发环境的版本,直接可以使用,正好最近项目不是很忙,想一直了解下Linux的整个启动流程,以及如何从命令行模式系统 ...

  8. 【转载】Linux系统启动流程

    原文:Linux系统启动流程 POST(Power On Self Test/上电自检)-->BootLoader(MBR)-->Kernel(硬件探测.加载驱动.挂载根文件系统./sbi ...

  9. Linux系统启动流程及grub重建(1)

    日志系统 Linux系统启动流程 PC: OS(Linux) POST-->BIOS(Boot Sequence)-->MBR(bootloader,446)-->Kernel--& ...

随机推荐

  1. FileNotFoundError: [WinError 2] 系统找不到指定的文件

    用Idle运行Python脚本的时候发现如下错误: Traceback (most recent call last):  File "D:\Python\Python36-32\lib\s ...

  2. nginx白名单黑名单设置

    nginx白名单黑名单设置 白名单设置,访问根目录 location / { allow 123.34.22.155; allow 33.56.32.1/100; deny all; } 黑名单设置, ...

  3. win10搭建本地服务器(IIS)

    若想外网也可以访问使用NATAPP:https://natapp.cn/article/natapp_newbie 参考文章: https://segmentfault.com/a/119000001 ...

  4. Mybatis框架配置讲解以及使用

    1.什么是Mybatis MyBatis 是一款优秀的持久层框架, 它支持定制化 SQL.存储过程以及高级映射. MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.·MyB ...

  5. 安卓开发实战-记账本APP(六)

    记账本APP开发---终结篇 昨天的动态数字录屏奉上:在抖音上拍了一个(ps:欢迎点赞) https://v.douyin.com/poEjmG/ 今天将图表的内容进行了制作,我用的是MPChart的 ...

  6. 制作ASCII字符动画

    看过Matrix的同学应该还记得,在母舰上一直在计算的电脑屏幕在Neo觉醒的时候,不停的下落的杂乱无章的字符组成了Neo当时所处的场景.其实利用开源和免费的工具,我们可以将现有的视频转换为ASCII字 ...

  7. 使用MS Devops 来部署CRM Solution

    在D365 CE开发当中,有一个非常痛苦的问题就是开发,测试环境中的export import solution 部署问题. Devops中能很好的解决这个问题. 工作原理: 在Azure Devop ...

  8. Codeforces gym101755H Safe Path(bfs)

    题意: 给以一个网格图,有起点终点和一些怪兽,可以上下左右走,不能走到距离怪兽曼哈顿距离为d以内的地方,问到终点最短路径 n*m<=2e5,d<=2e5 思路: 因为n*m的范围,不能直接 ...

  9. 《Python学习手册 第五版》 -第6章 动态类型

    本章主要讲述变量.对象.引用三者直接的关联及区别,详细说明了在变量赋值的操作中,计算机内部到底发生了什么,有哪些是不被人察觉和需要明确了解的 1.先从最简单的赋值语句开始 a=3 这一句,基本就能涵盖 ...

  10. 9.3.1 map端连接- DistributedCache分布式缓存小数据集

    1.1.1         map端连接- DistributedCache分布式缓存小数据集 当一个数据集非常小时,可以将小数据集发送到每个节点,节点缓存到内存中,这个数据集称为边数据.用map函数 ...