centos系統啟動流程

来源:https://www.cnblogs.com/xiaoshiwang/archive/2020/02/21/12343134.html
-Advertisement-
Play Games

linux內核特點: 支持模塊化:模塊文件的名字以.ko(kernel object)結尾 支持內核運行時,動態載入和卸載模塊文件。 linux內核組成部分: 核心文件:/boot/vmlinuz VERSION release 模塊文件:/lib/modules/VERSION release 如 ...


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 ([email protected]) #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:引導程式

    • 功能:

      • 提供一個可以讓用戶選擇的菜單,上面寫著,可以選擇運行的內核列表
      • 把用戶選定的內核程式從磁碟載入到記憶體的特定空間中,然後解壓,展開,此後,內核就開始真正運行起來了,然後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

本人微信:xiaoshitou5854


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • ​ 在C#8.0中,針對介面引入了一項新特性,就是可以指定預設實現,方便對已有實現進行擴展,也對面向Android和Swift的Api進行互操作提供了可能性。下麵我們來看看該特性的具體規則與實現。 一、主要應用場景: 在不破壞影響已有實現的情況下,可以添加新成員。這解決了在第三方已經大量使用了的介面 ...
  • 一文帶你瞭解 C DLR 的世界 在很久之前,我寫了一片文章 "dynamic結合匿名類型 匿名對象傳參" ,裡面我以為DLR內部是用反射實現的。因為那時候是心中想當然的認為只有反射能夠在運行時解析對象的成員信息並調用成員方法。後來也是因為其他的事一直都沒有回過頭來把這一節知識給補上,正所謂亡羊補牢 ...
  • 首先新建一個項目,名稱叫Caliburn.Micro.ActionConvertions 然後刪掉MainWindow.xaml 然後去app.xaml刪掉StartupUri這行代碼 其次,安裝Caliburn.Micro,Caliburn.Micro.Core,這兩個Nuget包,如下圖 然後新 ...
  • 先看核心代碼: public List<DataEntity> SearchShopSalesReport(DateTimeOffset? dateFrom, DateTimeOffset? dateTo,string groupBy) { var query = data.DataEntity / ...
  • 本筆記摘抄自:https://www.cnblogs.com/PatrickLiu/p/7928521.html,記錄一下學習過程以備後續查用。 一、引言 今天我們要講行為型設計模式的第四個模式--觀察者模式,先從名字上來看。觀察者模式可以理解為既然有“觀察者”,那肯定就有“被觀察者”了。“觀察者” ...
  • 本筆記摘抄自:https://www.cnblogs.com/PatrickLiu/p/7903617.html,記錄一下學習過程以備後續查用。 一、引言 今天我們要講行為型設計模式的第三個模式--迭代器模式,先從名字上來看。迭代是遍歷的意思,迭代器可以理解為是遍歷某某的工具,遍歷什麼呢?在軟 件設 ...
  • 1. 泛型Generic 1.1 引入泛型:延遲聲明 泛型方法聲明時,並未寫死類型,在調用的時候再指定類型。 延遲聲明:推遲一切可以推遲的。 1.2 如何聲明和使用泛型 泛型方法:方法名稱後面加上尖括弧,裡面是類型參數 類型參數實際上就是一個類型T聲明,方法就可以用這個類型T了。 如下所示: pub ...
  • 安裝Debian的磨磨唧唧 唆使VMware罷工的微軟 這兩天心血來潮想折騰,拆了我親愛的Ubuntu、裝個Debian 不過因為加入了~~微軟的insider版本~~ 就很尷尬的發現當我打開我的VMware workstation pro 15的時候 看臉 綠屏 TAT, 綠屏 你懂吧Orz 每每 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...