首页 > 其他分享 >06 运行Lib-OS

06 运行Lib-OS

时间:2024-07-09 19:51:55浏览次数:4  
标签:MAP 06 Lib READ unknown PROT mmap NULL OS

QEMU运行第一章代码

切换分支

git checkout ch1

detail

git checkout ch1 命令是用来切换到名为 ch1 的分支或者恢复工作目录中的文件到 ch1 提交的状态

运行代码

cd os
LOG=TRACE make run

detail

LOG=TRACE 是指定 LOG 的级别为 TRACE,可以查看重要程度不低于 TRACE 的输出日志。目前 TRACE 的重要程度最低,因此这样能够看到全部日志

学习Lib-OS的宗旨

引言 - rCore-Tutorial-Book-v3 3.6.0-alpha.1 文档 (rcore-os.cn)

要仔细看最后一段.

创建一个Rust工程

使用Cargo创建Rust工程

cargo new os --bin

detail

os/Cargo.toml 里的内容,记录着这个项目的信息.

[package]
name = "os"
version = "0.1.0"
edition = "2021"

[dependencies]

运行Rust工程

cd os 
cargo run

用strace观察应用程序层是怎么调用标准库的

strace target/debug/os

log

所有的log

execve("target/debug/os", ["target/debug/os"], 0x7ffc9e2f62e0 /* 46 vars */) = 0
brk(NULL)                               = 0x653c719dd000
arch_prctl(0x3001 /* ARCH_??? */, 0x7ffed7691920) = -1 EINVAL (Invalid argument)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7913b1fc9000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=63807, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 63807, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7913b1fb9000
close(3)                                = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\0\0\0\0\0\0\0"..., 832) = 832
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=125488, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 127720, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7913b1f99000
mmap(0x7913b1f9c000, 94208, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x3000) = 0x7913b1f9c000
mmap(0x7913b1fb3000, 16384, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1a000) = 0x7913b1fb3000
mmap(0x7913b1fb7000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1d000) = 0x7913b1fb7000
close(3)                                = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0P\237\2\0\0\0\0\0"..., 832) = 832
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
pread64(3, "\4\0\0\0 \0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0"..., 48, 848) = 48
pread64(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0I\17\357\204\3$\f\221\2039x\324\224\323\236S"..., 68, 896) = 68
newfstatat(3, "", {st_mode=S_IFREG|0755, st_size=2220400, ...}, AT_EMPTY_PATH) = 0
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
mmap(NULL, 2264656, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7913b1c00000
mprotect(0x7913b1c28000, 2023424, PROT_NONE) = 0
mmap(0x7913b1c28000, 1658880, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x28000) = 0x7913b1c28000
mmap(0x7913b1dbd000, 360448, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1bd000) = 0x7913b1dbd000
mmap(0x7913b1e16000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x215000) = 0x7913b1e16000
mmap(0x7913b1e1c000, 52816, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7913b1e1c000
close(3)                                = 0
mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7913b1f96000
arch_prctl(ARCH_SET_FS, 0x7913b1f96780) = 0
set_tid_address(0x7913b1f96a50)         = 4628
set_robust_list(0x7913b1f96a60, 24)     = 0
rseq(0x7913b1f97120, 0x20, 0, 0x53053053) = 0
mprotect(0x7913b1e16000, 16384, PROT_READ) = 0
mprotect(0x7913b1fb7000, 4096, PROT_READ) = 0
mprotect(0x653c70293000, 12288, PROT_READ) = 0
mprotect(0x7913b2003000, 8192, PROT_READ) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
munmap(0x7913b1fb9000, 63807)           = 0
poll([{fd=0, events=0}, {fd=1, events=0}, {fd=2, events=0}], 3, 0) = 0 (Timeout)
rt_sigaction(SIGPIPE, {sa_handler=SIG_IGN, sa_mask=[PIPE], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7913b1c42520}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
getrandom("\xbd\x19\x85\x71\xcb\xc5\x6b\x55", 8, GRND_NONBLOCK) = 8
brk(NULL)                               = 0x653c719dd000
brk(0x653c719fe000)                     = 0x653c719fe000
openat(AT_FDCWD, "/proc/self/maps", O_RDONLY|O_CLOEXEC) = 3
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
newfstatat(3, "", {st_mode=S_IFREG|0444, st_size=0, ...}, AT_EMPTY_PATH) = 0
read(3, "653c70241000-653c70247000 r--p 0"..., 1024) = 1024
read(3, "--p 00215000 08:03 133853       "..., 1024) = 1024
read(3, "-7913b1fcd000 r--p 00000000 08:0"..., 1024) = 913
close(3)                                = 0
sched_getaffinity(4628, 32, [0, 1])     = 16
rt_sigaction(SIGSEGV, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGSEGV, {sa_handler=0x653c70265f30, sa_mask=[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_SIGINFO, sa_restorer=0x7913b1c42520}, NULL, 8) = 0
rt_sigaction(SIGBUS, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGBUS, {sa_handler=0x653c70265f30, sa_mask=[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_SIGINFO, sa_restorer=0x7913b1c42520}, NULL, 8) = 0
sigaltstack(NULL, {ss_sp=NULL, ss_flags=SS_DISABLE, ss_size=0}) = 0
mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7913b1fc6000
mprotect(0x7913b1fc6000, 4096, PROT_NONE) = 0
sigaltstack({ss_sp=0x7913b1fc7000, ss_flags=0, ss_size=8192}, NULL) = 0
write(1, "Hello, world!\n", 14Hello, world!
)         = 14
sigaltstack({ss_sp=NULL, ss_flags=SS_DISABLE, ss_size=8192}, NULL) = 0
munmap(0x7913b1fc6000, 12288)           = 0
exit_group(0)                           = ?
+++ exited with 0 +++

这段输出是Linux系统中通过strace命令跟踪一个程序执行时的系统调用序列。strace是一个强大的诊断、调试和故障排查工具,能够展示一个程序及其子进程所执行的系统调用,以及这些调用的返回值。下面是对输出中一些关键步骤的简要解析:

  1. execve: 程序启动,执行target/debug/os可执行文件,并传递["target/debug/os"]作为命令行参数,以及环境变量。
  2. 内存管理: 包括brk, mmap, mprotect等调用,用于分配、映射和调整进程的内存布局。例如,mmap用于映射匿名内存、加载共享库如libgcc_s.so.1libc.so.6到进程地址空间。
  3. 动态链接: 通过打开和读取/etc/ld.so.cache和相关共享库文件(如libgcc_s.so.1libc.so.6),进行动态链接库的加载准备。
  4. 权限与安全: 如arch_prctl调用用来设置进程的架构特定寄存器,可能涉及到栈保护或其他安全措施。
  5. 文件访问: 例如尝试访问/etc/ld.so.preload来检查是否有额外的动态链接库需要预先加载,以及读取映射共享库内容。
  6. 信号处理: 如rt_sigaction调用,用于设置对特定信号(如SIGPIPE, SIGSEGV, SIGBUS)的处理方式,确保程序能响应这些信号并采取适当行动。
  7. 资源限制与管理: 通过prlimit64调用来获取或设置进程资源限制,比如堆栈大小。
  8. I/O操作: 如openat, read, write等,涉及到文件或标准输入输出的读写操作。此处包括读取自身内存映射信息和最终向标准输出写入"Hello, world!\n"。
  9. 进程终止: 最后,通过exit_group(0)调用,程序正常结束,退出状态码为0,表示成功执行。
    这段跟踪记录详细展示了程序从启动到执行完毕的底层系统活动,对于理解程序运行时的行为、性能分析或问题排查非常有用。

detail

与 Hello, world! 应用实际执行相关的只有两个系统调用

# 输出字符串
write(1, "Hello, world!\n", 14)         = 14
# 程序退出执行
exit_group(0)

观察"被隐藏"的操作系统

strace一个空的程序

mkdir ./empty_c_project
cd ./empty_c_project
gcc -o empty empty.c
strace ./empty

程序内容

int main()
{
    return 0;
}

log

execve("./empty", ["./empty"], 0x7ffc5012dd30 /* 46 vars */) = 0
brk(NULL)                               = 0x57b5ec70b000
arch_prctl(0x3001 /* ARCH_??? */, 0x7ffe40adc1c0) = -1 EINVAL (Invalid argument)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7009833a7000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=63807, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 63807, PROT_READ, MAP_PRIVATE, 3, 0) = 0x700983397000
close(3)                                = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0P\237\2\0\0\0\0\0"..., 832) = 832
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
pread64(3, "\4\0\0\0 \0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0"..., 48, 848) = 48
pread64(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0I\17\357\204\3$\f\221\2039x\324\224\323\236S"..., 68, 896) = 68
newfstatat(3, "", {st_mode=S_IFREG|0755, st_size=2220400, ...}, AT_EMPTY_PATH) = 0
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
mmap(NULL, 2264656, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x700983000000
mprotect(0x700983028000, 2023424, PROT_NONE) = 0
mmap(0x700983028000, 1658880, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x28000) = 0x700983028000
mmap(0x7009831bd000, 360448, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1bd000) = 0x7009831bd000
mmap(0x700983216000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x215000) = 0x700983216000
mmap(0x70098321c000, 52816, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x70098321c000
close(3)                                = 0
mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x700983394000
arch_prctl(ARCH_SET_FS, 0x700983394740) = 0
set_tid_address(0x700983394a10)         = 5271
set_robust_list(0x700983394a20, 24)     = 0
rseq(0x7009833950e0, 0x20, 0, 0x53053053) = 0
mprotect(0x700983216000, 16384, PROT_READ) = 0
mprotect(0x57b5ec153000, 4096, PROT_READ) = 0
mprotect(0x7009833e1000, 8192, PROT_READ) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
munmap(0x700983397000, 63807)           = 0
exit_group(0)                           = ?
+++ exited with 0 +++

查看rustc的运默认配置信息

rustc --version --verbose

从其中的 host 一项可以看出默认的目标平台是 x86_64-unknown-linux-gnu,其中 CPU 架构是 x86_64,CPU 厂商是 unknown,操作系统是 linux,运行时库是 GNU libc(封装了 Linux 系统调用,并提供 POSIX 接口为主的函数库)。

rustc 1.79.0 (129f3b996 2024-06-10)
binary: rustc
commit-hash: 129f3b9964af4d4a709d1383930ade12dfe7c081
commit-date: 2024-06-10
host: x86_64-unknown-linux-gnu
release: 1.79.0
LLVM version: 18.1.7

在另一个平台上运行rust

查看rustc支持的平台

rustc --print target-list | grep riscv

可以看到程序列出来的平台:

riscv32gc-unknown-linux-gnu
riscv32gc-unknown-linux-musl
riscv32i-unknown-none-elf
riscv32im-risc0-zkvm-elf
riscv32im-unknown-none-elf
riscv32ima-unknown-none-elf
riscv32imac-esp-espidf
riscv32imac-unknown-none-elf
riscv32imac-unknown-xous-elf
riscv32imafc-esp-espidf
riscv32imafc-unknown-none-elf
riscv32imc-esp-espidf
riscv32imc-unknown-none-elf
riscv64-linux-android
riscv64gc-unknown-freebsd
riscv64gc-unknown-fuchsia
riscv64gc-unknown-hermit
riscv64gc-unknown-linux-gnu
riscv64gc-unknown-linux-musl
riscv64gc-unknown-netbsd
riscv64gc-unknown-none-elf
riscv64gc-unknown-openbsd
riscv64imac-unknown-none-elf

这里我们选择 riscv64gc-unknown-none-elf 目标平台。这其中的 CPU 架构是 riscv64gc ,CPU厂商是 unknown ,操作系统是 none , elf 表示没有标准的运行时库(表明没有任何系统调用的封装支持),但可以生成 ELF 格式的执行程序。

detail

  1. rustc: 这是Rust编程语言的编译器命令行工具。它用于编译Rust源代码到各种不同的目标平台上,包括但不限于各种CPU架构和操作系统。
  2. --print target-list: 这是一个rustc的命令行选项,用来打印出rustc支持的所有编译目标(target triples)。Target triple是一种描述编译目标平台的字符串格式,通常包含架构、操作系统和环境信息,比如x86_64-unknown-linux-gnu表示64位x86架构、未知操作系统、GNU库环境。
  3. |(管道符号): 这是一个Unix/Linux shell命令,用于将前一个命令的输出作为后一个命令的输入。在这里,它把rustc --print target-list的输出作为下一个命令(grep riscv)的输入。
  4. grep riscv: grep是一个文本搜索工具,用于在输入数据中查找包含指定模式的行。这里使用grep riscv来过滤出那些包含“riscv”字符串的行。由于前面的命令列出了所有支持的编译目标,这一步就是从这些目标中筛选出与RISC-V架构相关的所有目标。

去掉操作系统支持,编译rust

cargo run --target riscv64gc-unknown-none-elf

log

这里重点关注关于 error[E0463]的表述,是编译器找不到rust的std库,

warning: `/home/winddevil/.cargo/config` is deprecated in favor of `config.toml`
note: if you need to support cargo 1.38 or earlier, you can symlink `config` to `config.toml`
warning: `/home/winddevil/.cargo/config` is deprecated in favor of `config.toml`
note: if you need to support cargo 1.38 or earlier, you can symlink `config` to `config.toml`
   Compiling os v0.1.0 (/home/winddevil/workspace/os)
error[E0463]: can't find crate for `std`
  |
  = note: the `riscv64gc-unknown-none-elf` target may not support the standard library
  = note: `std` is required by `os` because it does not declare `#![no_std]`

error: cannot find macro `println` in this scope
 --> src/main.rs:2:5
  |
2 |     println!("Hello, world!");
  |     ^^^^^^^

error: `#[panic_handler]` function required, but not found

error: requires `sized` lang_item

For more information about this error, try `rustc --explain E0463`.
error: could not compile `os` (bin "os") due to 4 previous errors

detail

当你运行 cargo run --target riscv64gc-unknown-none-elf 命令时,你是在使用Rust的包管理器Cargo来构建并运行一个Rust项目,但目标平台设定为了RISC-V 64位架构、具有GC(General Purpose,通用)扩展、面向一个未知且没有操作系统的环境(通常指嵌入式系统或微控制器)。下面是这个命令的几个关键点解析:

  • cargo run: 这个命令告诉Cargo构建当前包(默认是项目的根crate)并随后运行生成的可执行文件。它相当于先执行cargo build,然后执行生成的二进制文件。
    • --target: 这是一个选项,用于指定构建的目标架构和平台。这对于交叉编译特别重要,即在一种架构上编译代码,使其能在另一种架构上运行。
  • riscv64gc-unknown-none-elf: 这个目标三元组定义了编译的目标平台特征:
    • riscv64gc: 指定目标架构为RISC-V 64位版本,带GC(General Purpose)扩展,这通常意味着启用了像乘法和除法这样的基本指令集扩展。
    • unknown: 表示供应商或制造商未知,这在嵌入式开发中很常见,因为目标硬件可能不是由知名的商业公司生产。
    • none: 表明目标系统没有操作系统。这对于裸机编程(bare metal programming)、微控制器编程或自定义OS开发非常重要。
    • elf: 表明输出格式为ELF(Executable and Linkable Format),这是一种常用的可执行文件、目标文件和核心转储格式,适用于多种操作系统和体系结构。

使用rust core来代替std

Rust 有一个对 Rust 语言标准库–std 裁剪过后的 Rust 语言核心库 core。core库是不需要任何操作系统支持的,它的功能也比较受限,但是也包含了 Rust 语言相当一部分的核心机制,可以满足我们的大部分功能需求.

标签:MAP,06,Lib,READ,unknown,PROT,mmap,NULL,OS
From: https://www.cnblogs.com/chenhan-winddevil/p/18292649

相关文章

  • elementary os 8 2024年07月新动态
    具体信息请登录官网查询**OS7更新**Photos8已经作为Flatpak应用发布到AppCenter。这意味着你可以通过从AppCenter安装Flatpak版本来继续接收Photos的更新,即使在旧版本的elementaryOS上,而且Photos现在也很容易为那些运行除elementaryOS之外的Linux发行版的人提供。这个新......
  • Exam20240629 赛后结
    Exam20240629赛后结T1想法几乎是对的,结果两个不能直接乘起来就是如果你不太冷静的话就容易做出错误的判断,我考虑了这个问题,居然认为直接乘起来是可以的emmT2不太熟悉容斥,想到前缀和之后扔了结果它这个时候就已经变成slime和npc了这个时候就只需要钦定一段是大于k的其......
  • APICloud+ cosClient快速构建APP
    APICloud简介APICloud是一个移动低代码开发平台,对于不同的需求场景提供了不同的功能模块,并快速构建企业级应用。cosClient模块简介cosClient是腾讯云对象存储(COS)针对APICloud平台桥接原生SDK封装的模块,可以使用cosClient快速接入并使用COS的功能,目前支持Android、iOS。在APIC......
  • springboot煤炉网站代切系统-计算机毕业设计源码06656
    目  录摘要1绪论1.1课题目的与意义1.2国内外研究现状1.3论文结构与章节安排1.4Springboot框架介绍2 Springboot煤炉网站代切系统系统分析2.1可行性分析2.1.1技术可行性分析2.1.2经济可行性分析2.1.3操作可行性分析2.2 系统功能分析2.2.1......
  • CenterOs7安装redis
    CenterOs7安装redis1.redis的安装1.1下载redis从官网下载redis,并且上传到服务器的安装位置1.2安装redis①解压redis,执行tar-zxvf安装包名称②makeredis源码,make③makeinstallmakeinstall2.redis的配置2.1配置启动脚本配置redis的启动脚本,放置于/etc/init.d/......
  • 使用资源编排 ROS 轻松部署单点网站——以 WordPress 为例
    介绍WordPress是一款免费开源的网站内容管理系统(CMS),它可以帮助用户简单快捷地创建和管理自己的网站,包括博客、新闻网站、电子商务网站、社交网络等等。WordPress有丰富的主题和插件库,使得用户可以轻松地为网站定制外观和功能。WordPress的易用性和可扩展性使其成为世界上最受欢......
  • Nacos 爆重大 Bug!!不要升级,不要升级,不要升级
    大家好,我是R哥。最近我把我的《SpringCloudAlibaba微服务实战课》适配了SpringCloudAlibaba2023.0.1.0官方最新版本适配:SpringCloudAlibaba=>2023.0.1.0;SpringCloud=>2023.0.1;SpringBoot=>3.2.4;以下官方组件依赖需要升级:Nacos2.2.1=>2.3.2;RocketMQ......
  • 容器之docker compose
    DockerCompose是一个用于定义和运行多容器Docker应用的工具。通过一个YAML文件,您可以配置应用程序需要的所有服务,并使用单个命令来创建和启动这些服务。以下是对DockerCompose的详细介绍:核心概念服务(Services)服务是一个运行容器的抽象。每个服务都运行一个镜像,并且......
  • CentOs去除桌面上边栏、隐藏桌面图标、修改桌面背景
    1:去除CentOs桌面上边栏:  修改/usr/share/gnome-shell/theme目录下gnome-classic.css                 修改/usr/share/gnome-shell/modes/目录下classic.json2:隐藏桌面图标:应用程序-》工具-》优化工具-》桌面,取消勾选的图标3:去除下边栏:cd /usr/......
  • docker-compose创建haproxy教程
    本文主要讲解通过docker-compose创建haproxy并进行代理一、haproxy简介HAProxy是一款基于事件驱动、单进程模型设计的四层与七层负载均衡器,它能够在TCP/UDP层面以及HTTP(S)等应用层协议上实现高效的流量分发。HAProxy不仅适用于Web服务器负载均衡,还能应用于数据库、邮件服务器......