cgroup-v1在android中的應用實現淺析

来源:https://www.cnblogs.com/aosp/archive/2022/06/22/16399443.html
-Advertisement-
Play Games

本文檔內容主要是分析android設備中cgroup v1實現了哪些控制器,他們有哪些子控制器以及如何配置這些控制器的。 我是使用紅米Note4Plus的開發版本來調研分析的,手機已經解鎖並具有了root許可權,可以隨意操作修改手機內容。不涉及到源代碼層面的調查分析。 設備的基本配置信息:高通msm8 ...


目錄

本文檔內容主要是分析android設備中cgroup v1實現了哪些控制器,他們有哪些子控制器以及如何配置這些控制器的。

我是使用紅米Note4Plus的開發版本來調研分析的,手機已經解鎖並具有了root許可權,可以隨意操作修改手機內容。不涉及到源代碼層面的調查分析。

設備的基本配置信息:高通msm8953晶元、android7.0、8核CPU-arm64、3GB記憶體、內核版本3.18.31。

adb shell uname -a
Linux localhost 3.18.31-perf-g66052ad #1 SMP PREEMPT Thu Aug 29 23:06:40 CST 2019 aarch64
adb shell getprop |grep -iE "ro.build|ro.product|ro.board"
[ro.board.platform]: [msm8953]
[ro.build.date]: [Thu Aug 29 22:56:57 CST 2019]
[ro.build.software.version]: [Android7.0_10]
[ro.build.version.sdk]: [24]
[ro.product.board]: [msm8953]
[ro.product.cpu.abi]: [arm64-v8a]
[ro.product.model]: [Redmi Note 4X]

8核CPU, AArch64:

adb shell cat /proc/cpuinfo
Processor	: AArch64 Processor rev 4 (aarch64)
processor	: 0
BogoMIPS	: 38.40
Features	: fp asimd evtstrm aes pmull sha1 sha2 crc32
CPU implementer	: 0x41
CPU architecture: 8
CPU variant	: 0x0
CPU part	: 0xd03
CPU revision	: 4

processor	: 1  ...
processor	: 2  ...
processor	: 3  ...
processor	: 4  ...
processor	: 5  ...
processor	: 6  ...
processor	: 7  ...
Hardware	: Qualcomm Technologies, Inc MSM8953

記憶體總大小為3GB。

adb shell cat /proc/meminfo
MemTotal:        2914764 kB  ## 記憶體大小為3GB
MemFree:         1100080 kB
MemAvailable:    1306628 kB
Buffers:            9584 kB
Cached:           399040 kB
SwapCached:        72728 kB
Active:           598636 kB
Inactive:         411028 kB
Active(anon):     365696 kB
Inactive(anon):   391956 kB
Active(file):     232940 kB
Inactive(file):    19072 kB
Unevictable:      146796 kB
Mlocked:          146796 kB
SwapTotal:       1048572 kB
SwapFree:         669908 kB
Dirty:                60 kB
Writeback:             0 kB
AnonPages:        741228 kB
Mapped:           384520 kB
Shmem:             10056 kB
Slab:             133476 kB
SReclaimable:      36096 kB
SUnreclaim:        97380 kB
KernelStack:       38976 kB
PageTables:        38472 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     2505952 kB
Committed_AS:   70269080 kB
VmallocTotal:   258998208 kB
VmallocUsed:      126804 kB
VmallocChunk:   258746676 kB

1 開機初始化

開機初始化部分,主要分析cgroup文件系統是如何初始化的。我們重點關註init.xxx.rc文件中的初始化配置。

1.1 init.miui.rc

# 創建和掛載memory、freezer控制組。
on init
    # Create cgroup mount point for memory and freezer
    mount tmpfs none /sys/fs/cgroup mode=0750,uid=0,gid=1000
    mkdir /sys/fs/cgroup/memory 0750 root system
    mount cgroup none /sys/fs/cgroup/memory memory
    mkdir /sys/fs/cgroup/freezer 0750 root system
    mount cgroup none /sys/fs/cgroup/freezer freezer

# 創建cpuset的子控制器:vr、foreground、top-app、boost等
# 設置預設許可權
on late-init
    # set vr related cpuset
    mkdir /dev/cpuset/vr
    write /dev/cpuset/vr/mems 0

    # change permissions for vr cpusets as we'll touch at runtime
    chown system system /dev/cpuset/foreground/boost/cpus
    chmod 0664 /dev/cpuset/foreground/cpus
    chown root system /dev/cpuset/foreground/cpus
    chown system system /dev/cpuset/vr
    chown system system /dev/cpuset/vr/cpu_exclusive
    chown system system /dev/cpuset/vr/cpus
    chown system system /dev/cpuset/vr/tasks
    chmod 0664 /dev/cpuset/top-app/cpus
    chown root system /dev/cpuset/top-app/cpus
    chown system system /dev/cpuset/top-app/boost
    chown system system /dev/cpuset/top-app/boost/tasks
    chown system system /dev/cpuset/top-app/boost/cpus
    chmod 0664 /dev/cpuset/vr/cpu_exclusive
    chmod 0664 /dev/cpuset/vr/cpus
    chmod 0664 /dev/cpuset/vr/tasks
    chmod 0664 /dev/cpuset/top-app/boost/tasks

# 創建cpuset子控制器game、gamelite,並設置許可權。
on late-init
    # put some heavy-load thread into this cpuset for performance
    mkdir /dev/cpuset/game
    write /dev/cpuset/game/mems 0
    chown system system /dev/cpuset/game
    chown system system /dev/cpuset/game/tasks
    chown system system /dev/cpuset/game/cgroup.procs
    chmod 0660 /dev/cpuset/game/tasks
    chmod 0660 /dev/cpuset/game/cgroup.procs
    # put some light-load thread into this cpuset for battery life
    mkdir /dev/cpuset/gamelite
    write /dev/cpuset/gamelite/mems 0
    chown system system /dev/cpuset/gamelite
    chown system system /dev/cpuset/gamelite/tasks
    chown system system /dev/cpuset/gamelite/cgroup.procs
    chmod 0660 /dev/cpuset/gamelite/tasks
    chmod 0660 /dev/cpuset/gamelite/cgroup.procs

on boot
    # 壓力時速監視器
    # psi
    chmod 0660 /proc/pressure/io
    chmod 0660 /proc/pressure/memory
    chmod 0660 /proc/pressure/cpu

    # 創建cpuctl下的子控制器fg_service、fg_limited
    # 初始化子控制器配置
    mkdir /dev/cpuctl/fg_service
    chown system system /dev/cpuctl/fg_service/tasks
    chmod 0666 /dev/cpuctl/fg_service/tasks
    write /dev/cpuctl/bg_non_interactive/cpu.rt_runtime_us 300000
    write /dev/cpuctl/fg_service/cpu.shares 256
    write /dev/cpuctl/fg_service/cpu.rt_runtime_us 400000
    write /dev/cpuctl/fg_service/cpu.rt_period_us 1000000

    mkdir /dev/cpuctl/fg_service/fg_limited
    chown system system /dev/cpuctl/fg_service/fg_limited/tasks
    chmod 0666 /dev/cpuctl/fg_service/fg_limited/tasks
    write /dev/cpuctl/fg_service/fg_limited/cpu.shares 256
    write /dev/cpuctl/fg_service/fg_limited/cpu.rt_runtime_us 400000
    write /dev/cpuctl/fg_service/fg_limited/cpu.rt_period_us 1000000

1.2 init.qcom.rc

on init
    # 創建記憶體控制器
    # 設置基本配置
    # Create cgroup mount point for memory
    mkdir /sys/fs/cgroup/memory/bg 0750 root system
    write /sys/fs/cgroup/memory/bg/memory.swappiness 140
    write /sys/fs/cgroup/memory/bg/memory.move_charge_at_immigrate 1
    chown root system /sys/fs/cgroup/memory/bg/tasks
    chmod 0660 /sys/fs/cgroup/memory/bg/tasks

# 把日誌服務進程ID寫入到cpuset/system-background/tasks
# Logcat dump daemon, dumps logs to logdump partition
service logdumpd /system/bin/logcat -b all -v threadtime -D -w /dev/block/bootdevice/by-name/logdump
    class core
    writepid /dev/cpuset/system-background/tasks
    seclabel u:r:logdumpd:s0
    disabled

1.3 init.miui.early_boot.sh

配置了dex2oat線程的cpuset。詳情忽略。

1.4 init.zygote64_32.rc

# 把zygote服務放入cpuset/foreground控制組
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
    class main
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart netd
    writepid /dev/cpuset/foreground/tasks /sys/fs/cgroup/stune/foreground/tasks
    writepid /d/ktrace/sched/zygote64_pid

service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
    class main
    socket zygote_secondary stream 660 root system
    onrestart restart zygote
    writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
    writepid /d/ktrace/sched/zygote_pid

1.5 init.target.rc

在這個文件中設置各種子控制組的預設的CPU親和性。

# 配置了cpuset的各組cpu分配
on boot
    write /dev/cpuset/top-app/cpus 0-7
    # 頂層app中的boost任務限制在4-7
    write /dev/cpuset/top-app/boost/cpus 4-7
    # 前臺任務限制在0-6
    write /dev/cpuset/foreground/cpus 0-6
    write /dev/cpuset/foreground/boost/cpus 0-6
    # 後臺任務限制到 0-1
    write /dev/cpuset/background/cpus 0-1
    # 系統後臺限制到 0-3
    write /dev/cpuset/system-background/cpus 0-3

總而言之,在開機初始化init.xx.rc中完成的任務主要是:

  • 創建和掛載控制組文件系統。
  • 寫入初始的基礎配置信息。
  • 寫入某些關鍵進程到預設的控制組。

2 控制組概覽

2.1 控制器信息

cat /proc/cgroups                                                                            
#subsys_name	 hierarchy	num_cgroups	enabled
cpuset	         4	10	1
cpu	         3	3	1
cpuacct	         1	108	1
memory	         2	3	1
freezer	         5	65	1

這裡會列舉出每個控制器的名稱、分層的層級數、子控制組數量、是否已經使能。

2.2 控制組文件系統

查看每種控制組文件系統的掛載位置和掛載類型。

mount |grep cgroup
none on /acct type cgroup (rw,relatime,cpuacct)
none on /dev/memcg type cgroup (rw,relatime,memory)
none on /dev/cpuctl type cgroup (rw,relatime,cpu)
none on /dev/cpuset type cgroup (rw,relatime,cpuset,noprefix,release_agent=/sbin/cpuset_release_agent)
none on /sys/fs/cgroup type tmpfs (rw,seclabel,relatime,size=1436904k,nr_inodes=359226,mode=750,gid=1000)
none on /sys/fs/cgroup/memory type cgroup (rw,relatime,memory)
none on /sys/fs/cgroup/freezer type cgroup (rw,relatime,freezer)

說明:
掛載的文件系統類型是cgroup,是cgroup v1版本。cgroup v2版本的文件系統類型是cgroup2。
發現有兩個memory的節點:/dev/memcg,/sys/fs/cgroup/memory。查看對比了文件內容完全一致。沒有代碼來驗證他們是否是一個鏈接關係。

接下來我們就依次查看一下每種控制器的分層結構和配置信息。

3 cpuacct

從#2.1章節我們可以看到cpuacct有1個分層,108個控制組。這些子控制器是預設劃分的,以用戶id為單位。

ls -l
-rw-r--r--  1 root   root   0 2022-06-16 14:20 cgroup.clone_children
-rw-r--r--  1 root   root   0 2022-06-16 14:20 cgroup.procs
-r--r--r--  1 root   root   0 2022-06-16 14:20 cgroup.sane_behavior
-r--r--r--  1 root   root   0 2022-06-16 14:20 cpuacct.stat
-rw-r--r--  1 root   root   0 2022-06-16 14:20 cpuacct.usage
-r--r--r--  1 root   root   0 2022-06-16 14:20 cpuacct.usage_percpu
-rw-r--r--  1 root   root   0 2022-06-16 14:20 notify_on_release
-rw-r--r--  1 root   root   0 2022-06-16 14:20 release_agent
-rw-r--r--  1 root   root   0 2022-06-16 14:20 tasks
drwxr-xr-x  2 root   root   0 2022-06-16 14:20 uid
drwx------ 20 system system 0 2022-06-16 13:57 uid_1000
drwx------  5 system system 0 2022-06-16 10:28 uid_1001
drwx------  6 system system 0 2022-06-16 10:27 uid_......
drwx------  2 system system 0 2022-06-16 10:27 uid_10125
drwx------  2 system system 0 2022-06-16 10:27 uid_10127
drwx------  2 system system 0 2022-06-16 10:27 uid_10137

cat命令查看根目錄下的配置後做個簡單彙總:

配置 說明
cgroup.clone_children 0 子控制組不克隆配置
cgroup.procs ... 進程id列表
cgroup.sane_behavior 0 不啟用blkio統計
cpuacct.stat user 46994,system 72578 用戶空間和內核空間消耗的USER_HZ
cpuacct.usage 1317380348219 所有任務的累加CPU時間
cpuacct.usage_percpu 。。。 每個CPU的累加時間(共8個CPU)
notify_on_release 0 沒有啟用控制組釋放的通知
release_agent - 沒有指定命令
tasks ... 線程id列表

任意選擇一個子控制器uid_10110來看一下:

ls
cgroup.clone_children cpuacct.stat  cpuacct.usage_percpu tasks
cgroup.procs          cpuacct.usage notify_on_release

cat cpuacct.usage
564932354
cat cpuacct.usage_percpu
165586827 221125369 52289165 26123542 18939792 24406827 49224999 7235833 
cat cpuacct.stat
user 50
system 16

4 cpuset

4.1 cpuset分層結構

從#2.1章節我們可以看到cpuset有4個分層,10個控制組。

通過直觀的查看目錄樹,我們看到CPUSET控制組的樹形目錄:

/dev/cpuset
├── top-app
│   └── boost
├── foreground
│   └── boost               
├── foreground           
├── background                  
├── system-background               
├── game                
├── gamelite
└── vr

4.2 cpuset根控制組

看一下根目錄結構:

adb shell ls -l /dev/cpuset
total 0
drwxr-xr-x 2 system system 0 1974-11-23 05:28 background
-rw-r--r-- 1 root   root   0 2022-06-17 08:58 cgroup.clone_children
-rw-r--r-- 1 root   root   0 2022-06-17 08:58 cgroup.procs
-r--r--r-- 1 root   root   0 2022-06-17 08:58 cgroup.sane_behavior
-rw-r--r-- 1 root   root   0 2022-06-17 08:58 cpu_exclusive
-rw-r--r-- 1 root   root   0 2022-06-17 08:58 cpus
-r--r--r-- 1 root   root   0 2022-06-17 08:58 effective_cpus
-r--r--r-- 1 root   root   0 2022-06-17 08:58 effective_mems
drwxr-xr-x 3 system system 0 1974-11-23 05:28 foreground
drwxr-xr-x 2 system system 0 1974-11-23 05:28 game
drwxr-xr-x 2 system system 0 1974-11-23 05:28 gamelite
-rw-r--r-- 1 root   root   0 2022-06-17 08:58 mem_exclusive
-rw-r--r-- 1 root   root   0 2022-06-17 08:58 mem_hardwall
-rw-r--r-- 1 root   root   0 2022-06-17 08:58 memory_migrate
-r--r--r-- 1 root   root   0 2022-06-17 08:58 memory_pressure
-rw-r--r-- 1 root   root   0 2022-06-17 08:58 memory_pressure_enabled
-rw-r--r-- 1 root   root   0 2022-06-17 08:58 memory_spread_page
-rw-r--r-- 1 root   root   0 2022-06-17 08:58 memory_spread_slab
-rw-r--r-- 1 root   root   0 2022-06-17 08:58 mems
-rw-r--r-- 1 root   root   0 2022-06-17 08:58 notify_on_release
-rw-r--r-- 1 root   root   0 2022-06-17 08:58 release_agent
-rw-r--r-- 1 root   root   0 2022-06-17 08:58 sched_load_balance
-rw-r--r-- 1 root   root   0 2022-06-17 08:58 sched_relax_domain_level
drwxrwxr-x 2 system system 0 1974-11-23 05:28 system-background
-rw-rw-r-- 1 system system 0 1974-11-23 05:28 tasks
drwxr-xr-x 3 system system 0 1974-11-23 05:28 top-app
drwxr-xr-x 2 system system 0 1974-11-23 05:28 vr

cat命令查看根目錄下的配置後做個簡單彙總:

配置 說明
cgroup.clone_children 0 子控制組不克隆配置
cgroup.procs ... 進程id列表
cgroup.sane_behavior 0 不啟用blkio統計
cpus 0-7 cpu id列表
mems 0 mem節點id列表
effective_cpus 0-7 有效cpu id列表
effective_mems 0 有效mem節點id列表
cpu_exclusive 1 cpu獨占
mem_exclusive 1 mem獨占
mem_hardwall 0 頁面限制沒有啟用
memory_migrate 0 記憶體移動沒有啟用
memory_pressure_enabled 0 記憶體壓力監測沒有使能
memory_pressure 0 記憶體壓力監測為空
memory_spread_page 0 page擴展沒有使能
memory_spread_slab 0 slab擴展沒有使能
sched_load_balance 1 開啟負載均衡
sched_relax_domain_level -1 調度搜索範圍設為不限制
notify_on_release 0 沒有啟用控制組釋放的通知
release_agent /sbin/cpuset_release_agent 指定了命令
tasks ... 線程id列表

4.3 cpuset子控制組

關鍵是要看系統的子控制組如何配置的。這些控制組的預設設置在初始化init.xxx.rc時已經寫入了。我這裡彙總一下cpuset中cpu和mem相關的配置信息。

控制組 cpus mems sched_load_balance
top-app 0-7 0 1
top-app/boost 4-7 0 1
foreground 0-6 0 1
foreground/boost 4-7 0 1
background 0-1 0 1
system-background 0-3 0 1
game - 0 1
gamelite - 0 1
vr - 0 1

對看到的結果做個彙總:

  • 只有一個mem節點,所以記憶體節點id列表肯定是0。
  • miui配置的三個子控制組cpus為空,會使用父目錄下的配置。
  • boost性能要求的控制組都配置在CPU4-7
  • 後臺限制在0-1
  • 系統後臺限制在0-3
  • top應用全開放cpu0-7

5 cpuctl

5.1 cpuctl分層結構

從#2.1章節我們可以看到cpuctl有3個分層和3個控制組。

通過查看/dev/cpuctl下的目錄結構,我們可以看到控制組的分層結構:

/dev/cpuctl
└── fg_service
    └──  fg_limited

5.2 cpuctl配置和屬性

控制組根目錄:

adb shell ls -l /dev/cpuctl
-rw-r--r-- 1 root   root   0 2022-06-17 10:42 cgroup.clone_children
-rw-r--r-- 1 root   root   0 2022-06-17 10:42 cgroup.procs
-r--r--r-- 1 root   root   0 2022-06-17 10:42 cgroup.sane_behavior
-rw-r--r-- 1 root   root   0 2022-06-17 10:42 cpu.cfs_period_us
-rw-r--r-- 1 root   root   0 2022-06-17 10:42 cpu.cfs_quota_us
-rw-r--r-- 1 root   root   0 2022-06-17 10:42 cpu.notify_on_migrate
-rw-r--r-- 1 root   root   0 2022-06-17 10:42 cpu.rt_period_us
-rw-r--r-- 1 root   root   0 2022-06-17 10:42 cpu.rt_runtime_us
-rw-r--r-- 1 root   root   0 2022-06-17 10:42 cpu.shares
-r--r--r-- 1 root   root   0 2022-06-17 10:42 cpu.stat
-rw-r--r-- 1 root   root   0 2022-06-17 10:42 cpu.upmigrate_discourage
drwxr-xr-x 3 root   root   0 1974-11-23 05:28 fg_service
-rw-r--r-- 1 root   root   0 2022-06-17 10:42 notify_on_release
-rw-r--r-- 1 root   root   0 2022-06-17 10:42 release_agent
-rw-rw-rw- 1 system system 0 1974-11-23 05:28 tasks

通過cat命令,我們可以查看到幾個關鍵的cpu時間片分配信息:

配置 root fg_service fg_limited 說明
cfs_period_us 100000 100000 100000 100ms調度周期
cfs_quota_us -1 -1 80000 fg_limited的時間片限定為80ms,即80%比例
shares 1024 256 256 fg_service和fg_limited的時間調度比分別設為1/4
rt_period_us 1000000 1000000 1000000 CPU運行周期1秒
rt_runtime_us 950000 400000 400000 允許運行的CPU時間為950ms、400ms、400ms

6 memory

6.1 mem控制組分層結構

查看控制組信息:

adb shell cat /proc/cgroups
#subsys_name	hierarchy	num_cgroups	enabled
cpuset	4	10	1
cpu	3	3	1
cpuacct	1	103	1
memory	2	3	1
freezer	5	65	1

控制組有2層,3個控制組。通過查看/sys/fs/cgroup/memory目錄,我們可以看到memory的控制組結構如下:

/sys/fs/cgroup/memory
├── apps
└── sys_critical

6.2 控制組配置

通過cat命令,我們可以查看個控制組下的配置信息。在此我們跟控制組和2個子控制組的配置收集在這個表格中:

配置 root apps sys_critical 說明
cgroup.clone_children 0 0
cgroup.event_control - - -
cgroup.procs 列表省略... ...
cgroup.sane_behavior 0 無此文件
notify_on_release 0 0
release_agent 無此文件
tasks 列表省略... ...
memory.failcnt 0 0 0
memory.force_empty - - -
memory.limit_in_bytes 18446744073709551615 18446744073709551615 18446744073709551615
memory.max_usage_in_bytes 0 0 2793472
memory.memsw.failcnt 0 0 0
memory.memsw.limit_in_bytes 18446744073709551615 18446744073709551615 18446744073709551615
memory.memsw.max_usage_in_bytes 0 0 2797568
memory.memsw.usage_in_bytes 2329587712 0 2666496
memory.move_charge_at_immigrate 0 0 0
memory.oom_control oom_kill_disable 0 under_oom 0 oom_kill_disable 0 under_oom 0 oom_kill_disable 0 under_oom 0
memory.pressure_level - - -
memory.soft_limit_in_bytes 18446744073709551615 18446744073709551615 18446744073709551615
memory.stat 內容太長,省略 內容太長,省略 內容太長,省略
memory.swappiness 60 0 0
memory.usage_in_bytes 1964482560 0 2662400
memory.use_hierarchy 0 0 0 0

針對上表信息對記憶體配置作個總結說明:

  • apps控制組沒有寫入任務進程和線程,實際上沒有啟用。
  • 內容用量還沒有觸達上限閾值,沒有相關的記憶體不夠用情況
  • 記憶體軟限制跟硬限制閾值大小一樣。

7 freezer

7.1 freezer分層結構

查看控制組信息:

adb shell cat /proc/cgroups
#subsys_name	hierarchy	num_cgroups	enabled
cpuset	4	10	1
cpu	3	3	1
cpuacct	1	103	1
memory	2	3	1
freezer	5	65	1

freezer控制組有5個層次,65個控制組。

我們看一下/sys/fs/cgroup/freezer的目錄結構,大概看一下控制的分層結構(一個root加上64個子控制組):

/sys/fs/cgroup/freezer
├── miui0
├── miui1
├── miui2
├── miuiXXX ...
├── miui61
├── miui62
└── miui63

從這裡可以看出,miui預設劃分了64個子控制組,如果需要批量操作進程線程,只需要寫入到相應的控制組即可。

7.2 freezer控制組配置

根目錄下除了cgroup全局控制之外,沒有其他內容。
muiui0~miui63子控制組只是預先劃分好的,裡面並沒有填充任何進程和線程,實際上是沒有有效工作的。

我們隨便看一下miui11子控制組下的配置文件:

cat cgroup.clone_children
0
# 沒有配置進程列表
cat cgroup.procs
空      
# 父狀態
cat freezer.parent_freezing
0
# 自狀態
cat freezer.self_freezing
0
# 狀態:未凍結
cat freezer.state
THAWED

# 釋放通知未啟用
cat notify_on_release
0

# 線程列表為空
cat tasks
空

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

-Advertisement-
Play Games
更多相關文章
  • 前言 當我們開始學習Python時,我們會養成一些不良編碼習慣,而更可怕的是我們連自己也不知道。 我們學習變成的過程中,大概有會這樣的經歷: 寫的代碼只能完成了一次工作,但後來再執行就會報錯或者失敗,令人感到懊惱, 或者偶然發現一個內置函數可以讓你的工作更輕鬆時,瞬間豁然開朗。 我們中的大多數人仍然 ...
  • 1. 前言 距離上次發《MAUI初體驗:爽》一文已經過去2個月了,本計劃是下半年或者明年再研究MAUI的,現在計劃提前啦,因為我覺得MAUI Blazor挺有意思的:在Android、iOS、macOS、Windows之間共用UI,一處UI增加或者修改,就能得到一致的UI體驗。 看看這篇文章《Bla ...
  • 一:背景 1. 一個有趣的話題 最近在看 硬體異常 相關知識,發現一個有意思的空引用異常問題,拿出來和大家分享一下,為了方便講述,先上一段有問題的代碼。 namespace ConsoleApp2 { internal class Program { static Person person = n ...
  • 為什麼要使用Gridsome Gridsome 通過使用PRPL模式將超高性能構建到每個頁面中。您可以獲得開箱即用的代碼拆分、資產優化、漸進式圖像和鏈接預取。Gridsome 網站預設獲得幾乎完美的頁面速度分數。 Gridsome 生成靜態 PWA。只有關鍵的 HTML、CSS 和 JavaScri ...
  • 轉載自:https://blog.csdn.net/u013685264/article/details/121903540?spm=1001.2101.3001.6650.8&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault% ...
  • 記錄windows11系統,按shift鍵中英文切換未生效解決辦法 問題由來:中英文切換不順暢 問題搜索思路: shift鍵跟粘滯鍵有關,博主顯示直接去搜Windows shift鍵切換中英文不順暢。看到有人說從Windows 10後shift鍵就有了該特性,有些大佬描述是跟粘滯鍵有關,shift按 ...
  • 一 、通過雲開發平臺快速創建初始化應用 1.創建相關應用模版請參考鏈接:嘗鮮少代碼高性能的Svelte框架 2.完成創建後就可以在github中查看到新增的Vite倉庫 二 、 本地編寫 Svelte3聊天室 1.將應用模版克隆到本地 首先假定你已經安裝了Git、node,沒有安裝請移步node官網 ...
  • E-R圖也稱實體-聯繫圖(Entity Relationship Diagram),它提供了表示實體類型、屬性和聯繫的方法,用來描述現實世界的概念模型。 ...
一周排行
    -Advertisement-
    Play Games
  • 1、預覽地址:http://139.155.137.144:9012 2、qq群:801913255 一、前言 隨著網路的發展,企業對於信息系統數據的保密工作愈發重視,不同身份、角色對於數據的訪問許可權都應該大相徑庭。 列如 1、不同登錄人員對一個數據列表的可見度是不一樣的,如數據列、數據行、數據按鈕 ...
  • 前言 上一篇文章寫瞭如何使用RabbitMQ做個簡單的發送郵件項目,然後評論也是比較多,也是準備去學習一下如何確保RabbitMQ的消息可靠性,但是由於時間原因,先來說說設計模式中的簡單工廠模式吧! 在瞭解簡單工廠模式之前,我們要知道C#是一款面向對象的高級程式語言。它有3大特性,封裝、繼承、多態。 ...
  • Nodify學習 一:介紹與使用 - 可樂_加冰 - 博客園 (cnblogs.com) Nodify學習 二:添加節點 - 可樂_加冰 - 博客園 (cnblogs.com) 介紹 Nodify是一個WPF基於節點的編輯器控制項,其中包含一系列節點、連接和連接器組件,旨在簡化構建基於節點的工具的過程 ...
  • 創建一個webapi項目做測試使用。 創建新控制器,搭建一個基礎框架,包括獲取當天日期、wiki的請求地址等 創建一個Http請求幫助類以及方法,用於獲取指定URL的信息 使用http請求訪問指定url,先運行一下,看看返回的內容。內容如圖右邊所示,實際上是一個Json數據。我們主要解析 大事記 部 ...
  • 最近在不少自媒體上看到有關.NET與C#的資訊與評價,感覺大家對.NET與C#還是不太瞭解,尤其是對2016年6月發佈的跨平臺.NET Core 1.0,更是知之甚少。在考慮一番之後,還是決定寫點東西總結一下,也回顧一下.NET的發展歷史。 首先,你沒看錯,.NET是跨平臺的,可以在Windows、 ...
  • Nodify學習 一:介紹與使用 - 可樂_加冰 - 博客園 (cnblogs.com) Nodify學習 二:添加節點 - 可樂_加冰 - 博客園 (cnblogs.com) 添加節點(nodes) 通過上一篇我們已經創建好了編輯器實例現在我們為編輯器添加一個節點 添加model和viewmode ...
  • 前言 資料庫併發,數據審計和軟刪除一直是數據持久化方面的經典問題。早些時候,這些工作需要手寫複雜的SQL或者通過存儲過程和觸發器實現。手寫複雜SQL對軟體可維護性構成了相當大的挑戰,隨著SQL字數的變多,用到的嵌套和複雜語法增加,可讀性和可維護性的難度是幾何級暴漲。因此如何在實現功能的同時控制這些S ...
  • 類型檢查和轉換:當你需要檢查對象是否為特定類型,並且希望在同一時間內將其轉換為那個類型時,模式匹配提供了一種更簡潔的方式來完成這一任務,避免了使用傳統的as和is操作符後還需要進行額外的null檢查。 複雜條件邏輯:在處理複雜的條件邏輯時,特別是涉及到多個條件和類型的情況下,使用模式匹配可以使代碼更 ...
  • 在日常開發中,我們經常需要和文件打交道,特別是桌面開發,有時候就會需要載入大批量的文件,而且可能還會存在部分文件缺失的情況,那麼如何才能快速的判斷文件是否存在呢?如果處理不當的,且文件數量比較多的時候,可能會造成卡頓等情況,進而影響程式的使用體驗。今天就以一個簡單的小例子,簡述兩種不同的判斷文件是否... ...
  • 前言 資料庫併發,數據審計和軟刪除一直是數據持久化方面的經典問題。早些時候,這些工作需要手寫複雜的SQL或者通過存儲過程和觸發器實現。手寫複雜SQL對軟體可維護性構成了相當大的挑戰,隨著SQL字數的變多,用到的嵌套和複雜語法增加,可讀性和可維護性的難度是幾何級暴漲。因此如何在實現功能的同時控制這些S ...