首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

[rCore学习笔记 019]在main中测试本章实现

编程知识
2024年07月30日 15:25

写在前面

本随笔是非常菜的菜鸡写的。如有问题请及时提出。

可以联系:1160712160@qq.com

GitHhub:https://github.com/WindDevil (目前啥也没有

批处理操作系统的启动和运行流程

要想把本章实现的那些模块全部都串联在一起以实现运行一个批处理操作系统,回顾本章内容,思考批处理操作系统的运行流程.

可以看到本章完成的内容大概如图所示:

可以看到在内核层,最重要的就是实现了batch来加载程序和切换程序,以及trap用来处理用户层的请求.

因此,我们只需要在main.rs中添加这两个模块的初始化即可.

编写main.rs

主要是三部分:

  1. 引入上述编写模块
    1. 嵌入link_app.S
    2. 引入batch,trap,syscall
  2. 初始化模块
  3. 开始运行用户态APP

需要添加的内容就这么多:

pub mod batch;
pub mod syscall;
pub mod trap;

global_asm!(include_str!("link_app.S"));
pub fn rust_main() -> ! {
	trap::init();
    batch::init();
    batch::run_next_app();
}

最终实现的main.rs:

//! The main module and entrypoint
//!
//! Various facilities of the kernels are implemented as submodules. The most
//! important ones are:
//!
//! - [`trap`]: Handles all cases of switching from userspace to the kernel
//! - [`syscall`]: System call handling and implementation
//!
//! The operating system also starts in this module. Kernel code starts
//! executing from `entry.asm`, after which [`rust_main()`] is called to
//! initialize various pieces of functionality. (See its source code for
//! details.)
//!
//! We then call [`batch::run_next_app()`] and for the first time go to
//! userspace.

#![deny(missing_docs)]
#![deny(warnings)]
#![no_std]
#![no_main]
#![feature(panic_info_message)]

use core::arch::global_asm;

use log::*;
#[macro_use]
mod console;
pub mod batch;
mod lang_items;
mod logging;
mod sbi;
mod sync;
pub mod syscall;
pub mod trap;

global_asm!(include_str!("entry.asm"));
global_asm!(include_str!("link_app.S"));

/// clear BSS segment
fn clear_bss() {
    extern "C" {
        fn sbss();
        fn ebss();
    }
    unsafe {
        core::slice::from_raw_parts_mut(sbss as usize as *mut u8, ebss as usize - sbss as usize)
            .fill(0);
    }
}

/// the rust entry-point of os
#[no_mangle]
pub fn rust_main() -> ! {
    extern "C" {
        fn stext(); // begin addr of text segment
        fn etext(); // end addr of text segment
        fn srodata(); // start addr of Read-Only data segment
        fn erodata(); // end addr of Read-Only data ssegment
        fn sdata(); // start addr of data segment
        fn edata(); // end addr of data segment
        fn sbss(); // start addr of BSS segment
        fn ebss(); // end addr of BSS segment
        fn boot_stack_lower_bound(); // stack lower bound
        fn boot_stack_top(); // stack top
    }
    clear_bss();
    logging::init();
    println!("[kernel] Hello, world!");
    trace!(
        "[kernel] .text [{:#x}, {:#x})",
        stext as usize,
        etext as usize
    );
    debug!(
        "[kernel] .rodata [{:#x}, {:#x})",
        srodata as usize, erodata as usize
    );
    info!(
        "[kernel] .data [{:#x}, {:#x})",
        sdata as usize, edata as usize
    );
    warn!(
        "[kernel] boot_stack top=bottom={:#x}, lower_bound={:#x}",
        boot_stack_top as usize, boot_stack_lower_bound as usize
    );
    error!("[kernel] .bss [{:#x}, {:#x})", sbss as usize, ebss as usize);
    trap::init();
    batch::init();
    batch::run_next_app();
}

编译运行

使用第一章就编写好的Makefile文件实现一键编译运行:

cd os
make run

第一次编译运行:

error: expected expression, found keyword `extern`
  --> src/batch.rs:94:13
   |
94 |             extern "C" 
   |             ^^^^^^ expected expression

error: cannot find macro `asm` in this scope
  --> src/batch.rs:84:9
   |
84 |         asm!("fence.i")
   |         ^^^
   |
help: consider importing this macro
   |
1  + use core::arch::asm;
   |

error: cannot find macro `global_asm` in this scope
 --> src/trap/mod.rs:3:1
  |
3 | global_asm!(include_str!("trap.S"));
  | ^^^^^^^^^^
  |
help: consider importing one of these items
  |
3 + use core::arch::global_asm;
  |
3 + use crate::global_asm;
  |

error[E0412]: cannot find type `TrapContext` in this scope
  --> src/batch.rs:34:36
   |
34 |     pub fn push_context(&self, cx: TrapContext) -> &'static mut TrapContext {
   |                                    ^^^^^^^^^^^ not found in this scope

error[E0412]: cannot find type `TrapContext` in this scope
  --> src/batch.rs:34:65
   |
34 |     pub fn push_context(&self, cx: TrapContext) -> &'static mut TrapContext {
   |                                                                 ^^^^^^^^^^^ not found in this scope

error[E0412]: cannot find type `TrapContext` in this scope
  --> src/batch.rs:35:60
   |
35 |         let cx_ptr = (self.get_sp() - core::mem::size_of::<TrapContext>()) as *mut TrapContext;
   |                                                            ^^^^^^^^^^^ not found in this scope
   |
help: you might be missing a type parameter
   |
30 | impl<TrapContext> KernelStack {
   |     +++++++++++++

error[E0412]: cannot find type `TrapContext` in this scope
  --> src/batch.rs:35:84
   |
35 |         let cx_ptr = (self.get_sp() - core::mem::size_of::<TrapContext>()) as *mut TrapContext;
   |                                                                                    ^^^^^^^^^^^ not found in this scope

error[E0412]: cannot find type `RefCell` in this scope
 --> src/sync/up.rs:5:12
  |
5 |     inner: RefCell<T>,
  |            ^^^^^^^ not found in this scope
  |
help: consider importing this struct
  |
3 + use core::cell::RefCell;
  |

error[E0433]: failed to resolve: use of undeclared type `RefCell`
  --> src/sync/up.rs:14:23
   |
14 |         Self { inner: RefCell::new(value) }
   |                       ^^^^^^^ use of undeclared type `RefCell`
   |
help: consider importing this struct
   |
3  + use core::cell::RefCell;
   |

error[E0412]: cannot find type `RefMut` in this scope
  --> src/sync/up.rs:17:39
   |
17 |     pub fn exclusive_access(&self) -> RefMut<'_, T> {
   |                                       ^^^^^^ not found in this scope
   |
help: consider importing this struct
   |
3  + use core::cell::RefMut;
   |

error[E0412]: cannot find type `TrapContext` in this scope
  --> src/trap/mod.rs:13:30
   |
13 | pub fn trap_handler(cx: &mut TrapContext) -> &mut TrapContext {
   |                              ^^^^^^^^^^^ not found in this scope

error[E0412]: cannot find type `TrapContext` in this scope
  --> src/trap/mod.rs:13:51
   |
13 | pub fn trap_handler(cx: &mut TrapContext) -> &mut TrapContext {
   |                                                   ^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function `syscall` in this scope
  --> src/trap/mod.rs:19:24
   |
19 |             cx.x[10] = syscall(cx.x[17], [cx.x[10], cx.x[11], cx.x[12]]) as usize;
   |                        ^^^^^^^ not found in this scope
   |
help: consider importing this function
   |
3  + use crate::syscall::syscall;
   |

error[E0425]: cannot find function `run_next_app` in this scope
  --> src/trap/mod.rs:24:13
   |
24 |             run_next_app();
   |             ^^^^^^^^^^^^ not found in this scope
   |
help: consider importing this function
   |
3  + use crate::batch::run_next_app;
   |

error[E0425]: cannot find function `run_next_app` in this scope
  --> src/trap/mod.rs:28:13
   |
28 |             run_next_app();
   |             ^^^^^^^^^^^^ not found in this scope
   |
help: consider importing this function
   |
3  + use crate::batch::run_next_app;
   |

error[E0425]: cannot find function `init` in module `batch`
  --> src/main.rs:88:12
   |
88 |     batch::init();
   |            ^^^^ not found in `batch`
   |
help: consider importing one of these items
   |
23 + use crate::logging::init;
   |
23 + use crate::trap::init;
   |
help: if you import `init`, refer to it directly
   |
88 -     batch::init();
88 +     init();
   |

error[E0308]: mismatched types
   --> src/batch.rs:80:41
    |
80  |         core::slice::from_raw_parts_mut(APP_BASE_ADDRESS as *const u8, APP_SIZE_LIMIT).fill(0);
    |         ------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ in mutability
    |         |
    |         arguments to this function are incorrect
    |
    = note: expected raw pointer `*mut _`
               found raw pointer `*const u8`
note: function defined here
   --> /home/winddevil/.rustup/toolchains/nightly-2024-05-01-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/slice/raw.rs:147:21
    |
147 | pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] {
    |                     ^^^^^^^^^^^^^^^^^^

error[E0599]: the method `get` exists for struct `Lazy<UPSafeCell<AppManager>>`, but its trait bounds were not satisfied
   --> src/batch.rs:88:1
    |
88  | / lazy_static!
89  | | {
90  | |     static ref APP_MANAGER: UPSafeCell<AppManager> = unsafe 
91  | |     {
...   |
110 | |     };
111 | | }
    | |_^ method cannot be called on `Lazy<UPSafeCell<AppManager>>` due to unsatisfied trait bounds
    |
   ::: src/sync/up.rs:3:1
    |
3   |   pub struct UPSafeCell<T> {
    |   ------------------------ doesn't satisfy `UPSafeCell<AppManager>: Sized`
    |
    = note: the following trait bounds were not satisfied:
            `{type error}: Sized`
            which is required by `UPSafeCell<AppManager>: Sized`
    = note: this error originates in the macro `__lazy_static_internal` which comes from the expansion of the macro `lazy_static` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0433]: failed to resolve: use of undeclared type `TrapContext`
   --> src/batch.rs:126:13
    |
126 |             TrapContext::app_init_context(APP_BASE_ADDRESS, USER_STACK.get_sp())
    |             ^^^^^^^^^^^ use of undeclared type `TrapContext`

error[E0425]: cannot find function `sys_write` in this scope
 --> src/syscall/mod.rs:5:26
  |
5 |         SYSCALL_WRITE => sys_write(args[0], args[1] as *const u8, args[2]),
  |                          ^^^^^^^^^ not found in this scope

error[E0425]: cannot find function `sys_exit` in this scope
 --> src/syscall/mod.rs:6:25
  |
6 |         SYSCALL_EXIT => sys_exit(args[0] as i32),
  |                         ^^^^^^^^ not found in this scope

error[E0433]: failed to resolve: use of undeclared crate or module `stvec`
 --> src/trap/mod.rs:8:9
  |
8 |         stvec::write(__alltraps as usize, TrapMode::Direct);
  |         ^^^^^ use of undeclared crate or module `stvec`

error[E0433]: failed to resolve: use of undeclared type `TrapMode`
 --> src/trap/mod.rs:8:43
  |
8 |         stvec::write(__alltraps as usize, TrapMode::Direct);
  |                                           ^^^^^^^^ use of undeclared type `TrapMode`

error[E0433]: failed to resolve: use of undeclared crate or module `scause`
  --> src/trap/mod.rs:14:18
   |
14 |     let scause = scause::read();
   |                  ^^^^^^ use of undeclared crate or module `scause`

error[E0433]: failed to resolve: use of undeclared crate or module `stval`
  --> src/trap/mod.rs:15:17
   |
15 |     let stval = stval::read();
   |                 ^^^^^ use of undeclared crate or module `stval`

error: unused variable: `metadata`
  --> src/logging.rs:9:23
   |
9  |     fn enabled(&self, metadata: &Metadata) -> bool 
   |                       ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_metadata`
   |
note: the lint level is defined here
  --> src/main.rs:18:9
   |
18 | #![deny(warnings)]
   |         ^^^^^^^^
   = note: `#[deny(unused_variables)]` implied by `#[deny(warnings)]`

error[E0433]: failed to resolve: use of undeclared type `Exception`
  --> src/trap/mod.rs:26:25
   |
26 |         Trap::Exception(Exception::IllegalInstruction) => {
   |                         ^^^^^^^^^ use of undeclared type `Exception`

error[E0433]: failed to resolve: use of undeclared type `Trap`
  --> src/trap/mod.rs:26:9
   |
26 |         Trap::Exception(Exception::IllegalInstruction) => {
   |         ^^^^ use of undeclared type `Trap`

error[E0433]: failed to resolve: use of undeclared type `Exception`
  --> src/trap/mod.rs:22:25
   |
22 |         Trap::Exception(Exception::StorePageFault) => {
   |                         ^^^^^^^^^ use of undeclared type `Exception`

error[E0433]: failed to resolve: use of undeclared type `Trap`
  --> src/trap/mod.rs:22:9
   |
22 |         Trap::Exception(Exception::StorePageFault) => {
   |         ^^^^ use of undeclared type `Trap`

error[E0433]: failed to resolve: use of undeclared type `Exception`
  --> src/trap/mod.rs:21:25
   |
21 |         Trap::Exception(Exception::StoreFault) |
   |                         ^^^^^^^^^ use of undeclared type `Exception`

error[E0433]: failed to resolve: use of undeclared type `Trap`
  --> src/trap/mod.rs:17:9
   |
17 |         Trap::Exception(Exception::UserEnvCall) => {
   |         ^^^^ use of undeclared type `Trap`

error[E0433]: failed to resolve: use of undeclared type `Exception`
  --> src/trap/mod.rs:17:25
   |
17 |         Trap::Exception(Exception::UserEnvCall) => {
   |                         ^^^^^^^^^ use of undeclared type `Exception`

error[E0433]: failed to resolve: use of undeclared type `Trap`
  --> src/trap/mod.rs:21:9
   |
21 |         Trap::Exception(Exception::StoreFault) |
   |         ^^^^ use of undeclared type `Trap`

Some errors have detailed explanations: E0308, E0412, E0425, E0433, E0599.
For more information about an error, try `rustc --explain E0308`.
error: could not compile `os` (bin "os") due to 34 previous errors
make: *** [Makefile:42: kernel] Error 101

看到大段的报错不要着急,首先先看容易解决,能够解决的.

首先是在batch.rs里加入use core::arch::asm;:

error: cannot find macro `asm` in this scope
  --> src/batch.rs:84:9
   |
84 |         asm!("fence.i")
   |         ^^^
   |
help: consider importing this macro
   |
1  + use core::arch::asm;
   |

同样地,在src/trap/mod.rs里边加入use core::arch::global_asm;:

error: cannot find macro `global_asm` in this scope
 --> src/trap/mod.rs:3:1
  |
3 | global_asm!(include_str!("trap.S"));
  | ^^^^^^^^^^
  |
help: consider importing one of these items
  |
3 + use core::arch::global_asm;
  |
3 + use crate::global_asm;
  |

batch.rs加入use crate::trap::TrapContext;,这时候我们发现实际上在src/trap/mod.rs里也没有声明TrapContext则在里边声明mod context;:

error[E0412]: cannot find type `TrapContext` in this scope
  --> src/batch.rs:34:36
   |
34 |     pub fn push_context(&self, cx: TrapContext) -> &'static mut TrapContext {
   |                                    ^^^^^^^^^^^ not found in this scope

后续有很多找不到TrapContext的问题,可能都会解决.

src/sync/up.rs里加入use core::cell::{RefCell, RefMut};:

error[E0412]: cannot find type `RefCell` in this scope
 --> src/sync/up.rs:5:12
  |
5 |     inner: RefCell<T>,
  |            ^^^^^^^ not found in this scope
  |
help: consider importing this struct
  |
3 + use core::cell::RefCell;
  |
error[E0412]: cannot find type `RefMut` in this scope
  --> src/sync/up.rs:17:39
   |
17 |     pub fn exclusive_access(&self) -> RefMut<'_, T> {
   |                                       ^^^^^^ not found in this scope
   |
help: consider importing this struct
   |
3  + use core::cell::RefMut;
   |

这里还有一个比较难搞的依赖问题,如果这个module不是自己实现的,那么一般考虑外部依赖问题,

error[E0433]: failed to resolve: use of undeclared crate or module `riscv`
 --> src/trap/context.rs:2:5
  |
2 | use riscv::register::sstatus::{self, Sstatus, SPP};
  |     ^^^^^ use of undeclared crate or module `riscv`

Cargo.toml加入riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"] }

同理,把所有的这种依赖性问题都解决, 不一定 是对应着这个报错列表来,而是可以选择根据rust-analyzer自动报错的内容,顺便改一下.

再次编译一下,发现有很多类似的报错:

error: missing documentation for an associated function

这意味着你在编译一个 Rust 项目时启用了某个 lint (编译时检查规则),该 lint 要求所有关联函数都必须有文档注释.

那么我们只需要给这些函数加上注释就行了.

还有一个新的问题:

error: unused variable: `metadata`
  --> src/logging.rs:9:23
   |
9  |     fn enabled(&self, metadata: &Metadata) -> bool 
   |                       ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_metadata`
   |

因为这个metadataenbaled函数中没有被调用,因此需要在其前面加一个下划线_,从而声明这个参数是故意不被调用的.

另外.trap.S需要被链接到.text部分,并且需要声明__alltraps__restore,因此需要加入这个.

    .section .text
    .globl __alltraps
    .globl __restore

最终得到的trap.S为:

.altmacro
.macro SAVE_GP n
    sd x\n, \n*8(sp)
.endm
.macro LOAD_GP n
    ld x\n, \n*8(sp)
.endm
    .section .text
    .globl __alltraps
    .globl __restore
    .align 2
__alltraps:
    csrrw sp, sscratch, sp
    # now sp->kernel stack, sscratch->user stack
    # allocate a TrapContext on kernel stack
    addi sp, sp, -34*8
    # save general-purpose registers
    sd x1, 1*8(sp)
    # skip sp(x2), we will save it later
    sd x3, 3*8(sp)
    # skip tp(x4), application does not use it
    # save x5~x31
    .set n, 5
    .rept 27
        SAVE_GP %n
        .set n, n+1
    .endr
    # we can use t0/t1/t2 freely, because they were saved on kernel stack
    csrr t0, sstatus
    csrr t1, sepc
    sd t0, 32*8(sp)
    sd t1, 33*8(sp)
    # read user stack from sscratch and save it on the kernel stack
    csrr t2, sscratch
    sd t2, 2*8(sp)
    # set input argument of trap_handler(cx: &mut TrapContext)
    mv a0, sp
    call trap_handler

__restore:
    # case1: start running app by __restore
    # case2: back to U after handling trap
    mv sp, a0
    # now sp->kernel stack(after allocated), sscratch->user stack
    # restore sstatus/sepc
    ld t0, 32*8(sp)
    ld t1, 33*8(sp)
    ld t2, 2*8(sp)
    csrw sstatus, t0
    csrw sepc, t1
    csrw sscratch, t2
    # restore general-purpuse registers except sp/tp
    ld x1, 1*8(sp)
    ld x3, 3*8(sp)
    .set n, 5
    .rept 27
        LOAD_GP %n
        .set n, n+1
    .endr
    # release TrapContext on kernel stack
    addi sp, sp, 34*8
    # now sp->kernel stack, sscratch->user stack
    csrrw sp, sscratch, sp
    sret

最后运行结果是:

[rustsbi] RustSBI version 0.3.1, adapting to RISC-V SBI v1.0.0
.______       __    __      _______.___________.  _______..______   __
|   _  \     |  |  |  |    /       |           | /       ||   _  \ |  |
|  |_)  |    |  |  |  |   |   (----`---|  |----`|   (----`|  |_)  ||  |
|      /     |  |  |  |    \   \       |  |      \   \    |   _  < |  |
|  |\  \----.|  `--'  |.----)   |      |  |  .----)   |   |  |_)  ||  |
| _| `._____| \______/ |_______/       |__|  |_______/    |______/ |__|
[rustsbi] Implementation     : RustSBI-QEMU Version 0.2.0-alpha.2
[rustsbi] Platform Name      : riscv-virtio,qemu
[rustsbi] Platform SMP       : 1
[rustsbi] Platform Memory    : 0x80000000..0x88000000
[rustsbi] Boot HART          : 0
[rustsbi] Device Tree Region : 0x87000000..0x87000f02
[rustsbi] Firmware Address   : 0x80000000
[rustsbi] Supervisor Address : 0x80200000
[rustsbi] pmp01: 0x00000000..0x80000000 (-wr)
[rustsbi] pmp02: 0x80000000..0x80200000 (---)
[rustsbi] pmp03: 0x80200000..0x88000000 (xwr)
[rustsbi] pmp04: 0x88000000..0x00000000 (-wr)
[kernel] Hello, world!
[kernel] num_app = 5
[kernel] app_0 [0x8020a038, 0x8020b360)
[kernel] app_1 [0x8020b360, 0x8020c730)
[kernel] app_2 [0x8020c730, 0x8020dcd8)
[kernel] app_3 [0x8020dcd8, 0x8020f090)
[kernel] app_4 [0x8020f090, 0x80210440)
[kernel] Loading app_0
Hello, world!
[kernel] Application exited with code 0
[kernel] Loading app_1
Into Test store_fault, we will insert an invalid store operation...
Kernel should kill this application!
[kernel] PageFault in application, kernel killed it.
[kernel] Loading app_2
3^10000=5079(MOD 10007)
3^20000=8202(MOD 10007)
3^30000=8824(MOD 10007)
3^40000=5750(MOD 10007)
3^50000=3824(MOD 10007)
3^60000=8516(MOD 10007)
3^70000=2510(MOD 10007)
3^80000=9379(MOD 10007)
3^90000=2621(MOD 10007)
3^100000=2749(MOD 10007)
Test power OK!
[kernel] Application exited with code 0
[kernel] Loading app_3
Try to execute privileged instruction in U Mode
Kernel should kill this application!
[kernel] IllegalInstruction in application, kernel killed it.
[kernel] Loading app_4
Try to access privileged CSR in U Mode
Kernel should kill this application!
[kernel] IllegalInstruction in application, kernel killed it.
All applications completed!

可以看到启动了批处理系统之后,一个个APP运行,然后会想起用户层lib.rs中为每个app写得启动部分:

#[no_mangle]
#[link_section = ".text.entry"]
pub extern "C" fn _start() -> ! {
    clear_bss();
    exit(main());
    panic!("unreachable after sys_exit!");
}

每次运行之后,

  1. 因为触发了异常而退出
  2. 直接由exit(main());退出

都会陷入trap,然后在trap_handler里处理,只要不出现没有预期到的Expectation都会调用run_next_app,因此所有的app按顺序运行.

最后完美结束了这一章,我真是一条懒狗,怎么什么坑都要踩一遍.

From:https://www.cnblogs.com/chenhan-winddevil/p/18332741
本文地址: http://shuzixingkong.net/article/597
0评论
提交 加载更多评论
其他文章 Docker镜像构建:技术深度解析与实践指南
本文深入分析了Docker镜像构建的技术细节,从基础概念到高级技术,涵盖了多阶段构建、安全性优化、性能提升及实战案例。旨在为专业人士提供全面的技术洞察和实用指导,以提升Docker镜像构建的效率和安全性。 关注【TechLeadCloud】,分享互联网架构、云服务技术的全维度知识。作者拥有10+年互
Docker镜像构建:技术深度解析与实践指南 Docker镜像构建:技术深度解析与实践指南
从pytest源码的角度分析pytest工作原理
从pytest源码的角度分析pytest工作原理 从 pytest 源代码的角度来分析其工作原理,我们需要关注几个关键的部分,特别是 pytest 的启动过程以及测试的收集与执行。下面是基于 pytest 源代码的一个高层次的概述。 pytest 的启动过程 命令行解析: pytest&#160;的
从pytest源码的角度分析pytest工作原理
.NET 窗口/屏幕截图
图像采集源除了显示控件(上一篇《.NET 控件转图片》有介绍从界面控件转图片),更多的是窗口以及屏幕。 窗口截图最常用的方法是GDI,直接上Demo吧: 1 private void GdiCaptureButton_OnClick(object sender, RoutedEventArgs e)
.NET 窗口/屏幕截图 .NET 窗口/屏幕截图
EdgeOne安全专项实践:上传文件漏洞攻击详解与防范措施
通过本文,我们深入探讨了文件上传漏洞攻击的多种案例和防范措施,以及在搭建攻击靶场时的实际操作。从前端和后端的校验漏洞,到利用Apache配置文件和文件包含漏洞的攻击方式,每一步都展示了安全防护的重要性。
EdgeOne安全专项实践:上传文件漏洞攻击详解与防范措施 EdgeOne安全专项实践:上传文件漏洞攻击详解与防范措施 EdgeOne安全专项实践:上传文件漏洞攻击详解与防范措施
Known框架实战演练——进销存财务管理
本文介绍如何实现进销存管理系统的财务对账模块,财务对账模块包括供应商对账和客户对账2个菜单页面。供应商和客户对账字段相同,因此可共用一个页面组件类。 项目代码:JxcLite 开源地址: https://gitee.com/known/JxcLite 1. 配置模块 运行项目,在【系统管理-模块管理
使用Nginx Proxy Manager配置Halo的反向代理和申请 SSL 证书
本文介绍Nginx Proxy Manager配置Halo的反向代理和申请 SSL 证书,如需要了解Halo 2的安装,参考如何在Linux云服务器上通过Docker Compose部署安装Halo,搭建个人博客网站?。 目录安装Nginx Proxy ManagerNginx Proxy Mana
使用Nginx Proxy Manager配置Halo的反向代理和申请 SSL 证书 使用Nginx Proxy Manager配置Halo的反向代理和申请 SSL 证书 使用Nginx Proxy Manager配置Halo的反向代理和申请 SSL 证书
ComfyUI插件:ComfyUI Impact 节点(四)
前言: 学习ComfyUI是一场持久战,而 ComfyUI Impact 是一个庞大的模块节点库,内置许多非常实用且强大的功能节点 ,例如检测器、细节强化器、预览桥、通配符、Hook、图片发送器、图片接收器等等。通过这些节点的组合运用,我们可以实现的工作有很多,例如自动人脸检测和优化修复、区域增强、
ComfyUI插件:ComfyUI Impact 节点(四) ComfyUI插件:ComfyUI Impact 节点(四) ComfyUI插件:ComfyUI Impact 节点(四)
ambari2.8+ambari-metrics3.0+bigtop3.2编译、打包、安装
bigtop编译 资源说明: 软件及代码镜像 开发包镜像 github访问 编译相关知识 技术知识 bigtop编译流程及经验总结 各模块编译难度及大概耗时(纯编译耗时,不包含下载文件和排错时间) centos 真机编译branch-3.2 硬件说明: 编译步骤 下载代码并切换分支 国内镜像配置 基