diff --git a/Hardware/8259A_pic.md b/Hardware/8259A_pic.md deleted file mode 100644 index 19e469b..0000000 --- a/Hardware/8259A_pic.md +++ /dev/null @@ -1,37 +0,0 @@ -#### 8259A概述 - -![8259A引脚](_img/8259A_pin.jpg "8259A引脚") - -8259A芯片是一个中断管理芯片,中断的来源除了来自于硬件自身的NMI中断和来自于软件的`INT n`指令造成的软件中断之外,还有来自于外部硬件设备的中断,这些中断是可屏蔽的。这些中断也都通过**PIC**(Programmable Interrupt Controller)进行控制,并传递给CPU。 - -一个8259A芯片的可以接最多8个中断源,但由于可以将2个或多个8259A芯片级连(cascade),并且最多可以级连到9个,所以最多可以接64个中断源。如今绝大多数的PC都拥有两个8259A,这样 最多可以接收15个中断源。 - -8259提供了两种屏蔽方式:1,简单方式,提供8位屏蔽字对应各个IR。2,特殊方式,允许CPU让低优先级的外设去中断高优先级的服务程序。 - -#### 内部结构 - -![8259A内部结构](_img/8259A_structure.jpg) - -- IRR:中断请求寄存器8位,IR0~IR7每一位对应一个设备,共可接收8个设备的中断请求。 -- IMR:中断屏蔽寄存器为8位,设置需要屏蔽的中断请求 -- ISR:中断服务寄存器为8位,保存当前正在处理的中断请求 -- PR:优先权判别器。当多个中断同时发生时,将高优先级者优先传递给CPU。优先级选择方式有4种:1,完全嵌套方式,优先级从IR0到IR7依次降低。2,轮换方式A,一个中断完成后立即把它放到最低优先级的位置上。3,轮换方式B,CPU可以在任何时间规定最优优先级。4,查询方式,CPU访问中断状态寄存器。 -- 控制逻辑:向CPU发出中断请求信号INT,并接受CPU的中断响应信号INTA。 -- 数据总线缓冲器:保存数据总线的数据,传输命令控制字、状态字和中断类型码。 -- 读/写逻辑:确定数据总线缓冲器中数据的传输方向,选择内部的各命令字寄存器。RD为读,WR为写,AO为I/O端口识别,CS为设备选择。 -- 级联缓冲/比较器:主从控制器的级联是由级联总线CAS0,CAS1,CAS2实现的。 - -#### 工作原理 - -![8259A级联](_img/8259A_link.jpg) - -#### 实例:两个中断控制器连接 - -![8259A级联](_img/8259A_link2.gif) - -​ Master 8259A: - 0x20: ICW1,OCW2,OCW3,IRR,ISR - 0x21: ICW2,ICW3,ICW4,IMR, address registers - Slave 8259A: - 0xA0: ICW1,OCW2,OCW3,IRR,ISR - 0xA1: ICW2,ICW3,ICW4,IMR, address registers \ No newline at end of file diff --git a/Hardware/hikey970.md b/Hardware/ARM/hikey970.md similarity index 100% rename from Hardware/hikey970.md rename to Hardware/ARM/hikey970.md diff --git a/Hardware/zedboard.md b/Hardware/FPGA/zedboard.md similarity index 100% rename from Hardware/zedboard.md rename to Hardware/FPGA/zedboard.md diff --git a/Hardware/8251PCI.md b/Hardware/Intel/8251PCI.md similarity index 100% rename from Hardware/8251PCI.md rename to Hardware/Intel/8251PCI.md diff --git a/Hardware/A20.md b/Hardware/Intel/A20.md similarity index 100% rename from Hardware/A20.md rename to Hardware/Intel/A20.md diff --git a/Hardware/ACPI.md b/Hardware/Intel/ACPI.md similarity index 100% rename from Hardware/ACPI.md rename to Hardware/Intel/ACPI.md diff --git a/Hardware/Intel/Interrupt/8259A_pic.md b/Hardware/Intel/Interrupt/8259A_pic.md new file mode 100644 index 0000000..a8ab9af --- /dev/null +++ b/Hardware/Intel/Interrupt/8259A_pic.md @@ -0,0 +1,57 @@ +#### 中断概述 + +中断是由硬件设备产生的电信号,它首先被中断控制器处理,中断控制器再把与它唯一对应的数据发送到处理器的数据总线。之所以要唯一对应,是因为处理器只有1个输入来接收设备中断,它没法分清是哪个设备需要服务。英特尔32位处理器一般有2个中断控制器,每个中断控制器可以处理8个输入,由于一个从控制器的输出连到主控制器的输入,所以2个中断控制器组合起来一共可以处理15个外设的中断。中断控制器里的0号插座是专有的,只能接时钟输入;其它插座则可以接任意设备。 + +主中断控制器的INT引脚连接CPU的INT引脚,从中断控制器的INT引脚则连到主中断控制器的输入插座上。中断控制器就是通过这个INT引脚告诉CPU中断来了。CPU的INTA引脚和中断控制器的INTA引脚相连,它通过向中断控制器的INTA引脚发信号使得中断控制器把数据发到系统数据总线上,这样处理器就知道该执行哪个服务例程了。 + +##### CPU如何处理中断 + +当一个进行着的进程收到中断时,处理器会为中断服务设置一个新栈。这个栈的位置由**任务状态段**(TSS)里的一个入口决定。处理器会自动把若干重要的寄存器压到这个栈上,包括恢复被中断进程自已的栈和程序计数器所必须的那些寄存器。 + +当从中断返回被中断的进程时,会执行`iretd`指令。`iretd`恢复中断前的状态,恢复被硬件压入的寄存器,并切换回中断发生之前的栈。 + +当CPU收到一个中断后,会关闭所有的中断。这样就可以保证进程的栈桢不会溢出。当进程表之外的内核栈被使用时,中断始终处于关闭的状态。当内核栈被使用时,也有机制可以保证异常处理例程可以运行。可以把异常理解为不能关闭的中断。当异常发生时,CPU把必要的寄存器压入当前的栈里。当内核运行时不应发生异常,否则将产生panic。 + +`iretd`返回内核进程和返回用户进程的机制是类似的,处理器通过检查代码段选择器来决定如何处理`iretd`。 + +#### 8259A概述 + +![8259A引脚](../../_img/8259A_pin.jpg "8259A引脚") + +8259A芯片是一个中断管理芯片,中断的来源除了来自于硬件自身的NMI中断和来自于软件的`INT n`指令造成的软件中断之外,还有来自于外部硬件设备的中断,这些中断是可屏蔽的。这些中断也都通过**PIC**(Programmable Interrupt Controller)进行控制,并传递给CPU。 + +一个8259A芯片的可以接最多8个中断源,但由于可以将2个或多个8259A芯片级连(cascade),并且最多可以级连到9个,所以最多可以接64个中断源。如今绝大多数的PC都拥有两个8259A,这样 最多可以接收15个中断源。 + +8259提供了两种屏蔽方式:1,简单方式,提供8位屏蔽字对应各个IR。2,特殊方式,允许CPU让低优先级的外设去中断高优先级的服务程序。 + +8259芯片里保存了一个表,这个表会生成一个8位的索引,CPU使用它来为每个可能的中断输入找到正确的中断门描述符。这个表是由BIOS初始化的。当使用了中断的驱动程序启动的时候,可以根据需要进行修改。驱动程序可以请求对相应的位进行重置来开启它需要的中断。 + + + +#### 内部结构 + +![8259A内部结构](../../_img/8259A_structure.jpg) + +- IRR:中断请求寄存器8位,IR0~IR7每一位对应一个设备,共可接收8个设备的中断请求。 +- IMR:中断屏蔽寄存器为8位,设置需要屏蔽的中断请求 +- ISR:中断服务寄存器为8位,保存当前正在处理的中断请求 +- PR:优先权判别器。当多个中断同时发生时,将高优先级者优先传递给CPU。优先级选择方式有4种:1,完全嵌套方式,优先级从IR0到IR7依次降低。2,轮换方式A,一个中断完成后立即把它放到最低优先级的位置上。3,轮换方式B,CPU可以在任何时间规定最优优先级。4,查询方式,CPU访问中断状态寄存器。 +- 控制逻辑:向CPU发出中断请求信号INT,并接受CPU的中断响应信号INTA。 +- 数据总线缓冲器:保存数据总线的数据,传输命令控制字、状态字和中断类型码。 +- 读/写逻辑:确定数据总线缓冲器中数据的传输方向,选择内部的各命令字寄存器。RD为读,WR为写,AO为I/O端口识别,CS为设备选择。 +- 级联缓冲/比较器:主从控制器的级联是由级联总线CAS0,CAS1,CAS2实现的。 + +#### 工作原理 + +![8259A级联](../../_img/8259A_link.jpg) + +#### 实例:两个中断控制器连接 + +![8259A级联](../../_img/8259A_link2.gif) + +​ Master 8259A: +​ 0x20: ICW1,OCW2,OCW3,IRR,ISR +​ 0x21: ICW2,ICW3,ICW4,IMR, address registers +​ Slave 8259A: +​ 0xA0: ICW1,OCW2,OCW3,IRR,ISR +​ 0xA1: ICW2,ICW3,ICW4,IMR, address registers \ No newline at end of file diff --git a/Hardware/APIC.md b/Hardware/Intel/Interrupt/APIC.md similarity index 66% rename from Hardware/APIC.md rename to Hardware/Intel/Interrupt/APIC.md index 391cf79..1d9e100 100644 --- a/Hardware/APIC.md +++ b/Hardware/Intel/Interrupt/APIC.md @@ -1,18 +1,4 @@ -#### 中断概述 -中断是由硬件设备产生的电信号,它首先被中断控制器处理,中断控制器再把与它唯一对应的数据发送到处理器的数据总线。之所以要唯一对应,是因为处理器只有1个输入来接收设备中断,它没法分清是哪个设备需要服务。英特尔32位处理器一般有2个中断控制器,每个中断控制器可以处理8个输入,由于一个从控制器的输出连到主控制器的输入,所以2个中断控制器组合起来一共可以处理15个外设的中断。中断控制器里的0号插座是专有的,只能接时钟输入;其它插座则可以接任意设备。 - -主中断控制器的INT引脚连接CPU的INT引脚,从中断控制器的INT引脚则连到主中断控制器的输入插座上。中断控制器就是通过这个INT引脚告诉CPU中断来了。CPU的INTA引脚和中断控制器的INTA引脚相连,它通过向中断控制器的INTA引脚发信号使得中断控制器把数据发到系统数据总线上,这样处理器就知道该执行哪个服务例程了。 - -##### CPU如何处理中断 - -当一个进行着的进程收到中断时,处理器会为中断服务设置一个新栈。这个栈的位置由**任务状态段**(TSS)里的一个入口决定。处理器会自动把若干重要的寄存器压到这个栈上,包括恢复被中断进程自已的栈和程序计数器所必须的那些寄存器。 - -当从中断返回被中断的进程时,会执行`iretd`指令。`iretd`恢复中断前的状态,恢复被硬件压入的寄存器,并切换回中断发生之前的栈。 - -当CPU收到一个中断后,会关闭所有的中断。这样就可以保证进程的栈桢不会溢出。当进程表之外的内核栈被使用时,中断始终处于关闭的状态。当内核栈被使用时,也有机制可以保证异常处理例程可以运行。可以把异常理解为不能关闭的中断。当异常发生时,CPU把必要的寄存器压入当前的栈里。当内核运行时不应发生异常,否则将产生panic。 - -`iretd`返回内核进程和返回用户进程的机制是类似的,处理器通过检查代码段选择器来决定如何处理`iretd`。 #### APIC简介 diff --git a/Hardware/NUMA.md b/Hardware/Intel/NUMA.md similarity index 100% rename from Hardware/NUMA.md rename to Hardware/Intel/NUMA.md diff --git a/Hardware/VT-x.md b/Hardware/Intel/VT-x.md similarity index 100% rename from Hardware/VT-x.md rename to Hardware/Intel/VT-x.md diff --git a/Hardware/cpu_x86.md b/Hardware/Intel/cpu_x86.md similarity index 100% rename from Hardware/cpu_x86.md rename to Hardware/Intel/cpu_x86.md diff --git a/Hardware/Intel/proctect.md b/Hardware/Intel/proctect.md new file mode 100644 index 0000000..a4fdb69 --- /dev/null +++ b/Hardware/Intel/proctect.md @@ -0,0 +1,31 @@ +#### 帮助 + +- 可参考[语言->汇编->i386.md]里与保护模式相关的内容 + +### 保护模式下访问系统资源 + +之所以用描述符的形式来组织数据,是有两个原因:硬件细节、与16位286处理器兼容。 + +#### GDT + +全局描述符表,通过`GDTR`寄存器来找到它。 + +GDT中放的是段描述符,GDT的段描述符里记录了操作系统所使用的内存区域。GDT对所有进程可见。 + +> GDT里所说的段是硬件定义的段,它和操作系统所管理的段是不一样的。操作系统把硬件定义的数据段再分为数据段和栈段。 + +段描述符是8字节的结构体,包含了许多内容,但最重要的部分是描述基址的字段和描述内存限长的字段。 + +#### LDT + +局部描述符表,通过`LDTR`寄存器来找到它。 + +LDT中放的是段描述符,LDT的段描述符里记录了进程所使用的内存区域。一般一个进程对应一个LDT。 + +#### IDT + +中断门描述符表,通过`IDTR`寄存器来找到它。通过中断门描述符表,那些为异常、硬件中断或软件中断服务的代码片断可以得以执行。 + +IDT中放的是中断门描述符,即中断处理程序的入口。 + +门描述符也是8字节的结构体,最重要的部分是当对应中断激活时要执行的代码的地址。 \ No newline at end of file diff --git a/Hardware/FU540-C000.md b/Hardware/RISC-V/FU540-C000.md similarity index 100% rename from Hardware/FU540-C000.md rename to Hardware/RISC-V/FU540-C000.md diff --git a/Hardware/cpu_rocket.md b/Hardware/RISC-V/cpu_rocket.md similarity index 100% rename from Hardware/cpu_rocket.md rename to Hardware/RISC-V/cpu_rocket.md diff --git a/Hardware/k210/clint.md b/Hardware/RISC-V/k210/clint.md similarity index 100% rename from Hardware/k210/clint.md rename to Hardware/RISC-V/k210/clint.md diff --git a/Hardware/k210/plic.md b/Hardware/RISC-V/k210/plic.md similarity index 100% rename from Hardware/k210/plic.md rename to Hardware/RISC-V/k210/plic.md diff --git a/Hardware/k210/uarths.md b/Hardware/RISC-V/k210/uarths.md similarity index 100% rename from Hardware/k210/uarths.md rename to Hardware/RISC-V/k210/uarths.md diff --git a/Hardware/k210/系统控制器.md b/Hardware/RISC-V/k210/系统控制器.md similarity index 100% rename from Hardware/k210/系统控制器.md rename to Hardware/RISC-V/k210/系统控制器.md diff --git a/Languages/CLang/libraries/sys/socket.md b/Languages/CLang/libraries/sys/socket.md index e0041f6..887aa18 100644 --- a/Languages/CLang/libraries/sys/socket.md +++ b/Languages/CLang/libraries/sys/socket.md @@ -56,6 +56,10 @@ int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); */ int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen); +/* 获取网络插座sockfd的状态 + */ +int getsockopt(int sockfd, int level, int optname, void *restrict optval, socklen_t *restrict optlen); + /* 让服务端的网络插座sockfd变成被动网络插座。(网络插座默认是主动) */ int listen(int sockfd, int backlog); @@ -98,6 +102,11 @@ ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags); // SOCK_STREAM - 提供顺序的、可靠的、双向的、基于连接的字节流。 // SOCK_DGRAM - 支持数据报(无连接的,不可靠的,消息有最大长度)。 // protocol:指定网络插座要用的协议。通常一个网络插座的类型对应唯一的协议,此时此参数可指定为0;但若存在对应多个协议的情况,此时必须指定协议号。(详见/etc/protocols) + +/* 设置网络插座sockfd的状态 + */ +int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen); + int socket(int domain, int type, int protocol); /* 作用:创建两个网络插座,并使它们之间互相连接。 diff --git a/Languages/LinuxShell/0shell-programming.md b/Languages/LinuxShell/0shell-programming.md index 772ce21..438b0a8 100644 --- a/Languages/LinuxShell/0shell-programming.md +++ b/Languages/LinuxShell/0shell-programming.md @@ -43,6 +43,16 @@ +### 函数 + +```bash +function help(){ + echo "help" +} +``` + + + # -------------------- #### 基本格式 diff --git a/Languages/Python3/错误记录.md b/Languages/Python3/错误记录.md index c6873d4..22f4e74 100644 --- a/Languages/Python3/错误记录.md +++ b/Languages/Python3/错误记录.md @@ -1,14 +1,51 @@ #### 1 BlockingIOError -##### 错误描述: +错误描述: ``` BlockingIOError: [Errno 11] write could not complete without blocking ``` -##### 原因分析: +原因分析: 我面临的情况是子进程写管道,当前进程读管道,当前进程把子进程输出的信息打印出来。当子进程向管道写入信息太多时,管道阻塞,于是抛出此错误。 -##### 解决方法: +解决方法: +方法一:当产生此异常时执行`pass`,不管它。 + +方法二:减少要输出的信息。 + +方法三:将管道设置为非阻塞 + +#### 2 UnicodeDecodeError + +错误描述: + +``` +UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8e in position 2816: invalid start byte +``` + +原因分析: + +这应该是文本里混入了非utf-8编码,然而我用xxd命令却没查到0x8e这个数字。 + +解决方法: + +应该是把非utf-8编码改为utf-8编码。 + +#### 3 + +错误描述: + +``` +Exception ignored in: <_io.TextIOWrapper name='' mode='w' encoding='utf-8'> +``` + +原因分析: + +应该还是输出信息太多引起的 + +解决方法: + +当出现异常`BrokenPipeError`和`IOError`的时候执行`pass`。 diff --git a/Languages/Rust/lib_std/macro.md b/Languages/Rust/lib_std/macro.md new file mode 100644 index 0000000..9f1decb --- /dev/null +++ b/Languages/Rust/lib_std/macro.md @@ -0,0 +1,3 @@ +#### format + +使用运行时表达式来创建`String`。`format!`常用来连接字符串。 \ No newline at end of file diff --git a/Languages/Rust/lib_std/macro_vec.md b/Languages/Rust/lib_std/macro_vec.md deleted file mode 100644 index e69de29..0000000 diff --git a/Languages/Rust/lib_std/mod_env.md b/Languages/Rust/lib_std/mod_env.md index 7033219..f4ed918 100644 --- a/Languages/Rust/lib_std/mod_env.md +++ b/Languages/Rust/lib_std/mod_env.md @@ -4,6 +4,8 @@ #### 模块 +- consts - 与当前目标相关的常数 + #### 结构体 - Args - 进程参数的迭代器,为每个参数都生成一个`String`类型的值。 @@ -12,10 +14,20 @@ pub struct Args { /* fields omitted */ } ``` - +- ArgsOs + +- JoinPathsError + +- SplitPaths + +- Vars + +- VarsOs #### 枚举类型 +- VarError + #### 函数 - args - 返回传递给本程序的命令行参数。 @@ -24,4 +36,30 @@ pub fn args() -> Args ``` - \ No newline at end of file +- args_os + +- current_dir + +- current_exe + +- home_dir + +- join_paths + +- remove_var + +- set_current_dir + +- set_var + +- split_paths + +- temp_dir + +- var + +- var_os + +- vars + +- vars_os \ No newline at end of file diff --git a/OS/Fuchsia/readme.md b/OS/Fuchsia/readme.md new file mode 100644 index 0000000..94a8986 --- /dev/null +++ b/OS/Fuchsia/readme.md @@ -0,0 +1,11 @@ +#### 参考资料 + +- [pwn-fuchsia](https://a13xp0p0v.github.io/2022/05/24/pwn-fuchsia.html) + +#### 概述 + +- 没有属主的概述,而是基于访问能力的。 +- 基于微内核,这使内核被攻击面变小了。 +- 所有的用户态程序都是在各自的沙箱中运行的。 +- 用户态程序由URL标识,可以按需解析、下载和执行。 + diff --git a/OS/Minix/readme.md b/OS/Minix/readme.md new file mode 100644 index 0000000..1688c4e --- /dev/null +++ b/OS/Minix/readme.md @@ -0,0 +1,117 @@ +#### 设计目标 + +- 可以在运行时配置I/O设备 +- 让主要的系统组件成为与内核分开的独立进程 + +#### 重要概念 + +##### minix3的四层结构 + +| 层级 | 进程类型 | 包含的进程 | +| ------------ | -------- | -------------------------------------------------- | +| 4 (用户模式) | 用户进程 | init进程, 若干用户进程 | +| 3 (用户模式) | 服务进程 | 进程管理器,文件系统,信息服务程序,网络服务程序等 | +| 2 (用户模式) | 设备驱动 | TTY驱动程序,以太网驱动程序等 | +| 1 (内核模式) | 内核进程 | 内核,时钟任务,系统任务 | + +##### 各种调用 + +- 系统调用 + + 在宏内核里,系统调用指内核提供的所有调用。 + + 在Minix3里,系统调用在形式上和宏内核是一样的,但它不直接向内核请求服务,而是向服务进程发消息。服务进程之间,服务进程与驱动、内核之间也是通过消息来通信的。 + +- 内核调用 + + 直接向内核请求服务的调用。用户进程无法进行内核调用,服务进程和驱动程序才能进行内核调用。内核调用和系统调用常有类似的名字,因为有些操作只能在内核里进行。 + +- 消息原语 + + 用于进程间通信,如send、receive、notify等。有时也被叫**IPC原语**或**自陷**。它们确实调用了系统,但即不应称为系统调用也不应称为内核调用。 + +##### 系统任务接收的消息 + +其实就是内核调用,共有28个。 + +- 进程管理 + + sys_fork, sys_exec, sys_exit, sys_trace : 与POSIX系统调用相关的内核调用 + + sys_nice:设置进程的调度优先级 + + sys_privctl : 再生服务程序RS用它来改变进程的特权。驱动程序和不在启动镜像里的服务程序通过`/etc/rc`脚本启动时,将会需要特权转换。 + +- 信号 + + sys_kill : 与系统调用`kill`相关 + + sys_getksig, sys_endksig, sys_sigsend, sys_sigreturn : 进程管理器用它们来操作信号 + +- 设备驱动的支持 + + sys_irqctl : 开启、关闭或配置中断 + + sys_devio :读写I/O端口 + + sys_sdevio:从I/O端口读写字符串。例如访问串口时会用到它。 + + sys_vdevio:执行一个I/O所请求的向量。向量指的是一串(port, value)对。 + +- 关于内存 + + sys_newmap:当进程的内存发生改变时,进程管理器调用它来更新内核里的进程表。 + + sys_regctl:设备驱动用它来获取一个段选择子,这样就可以访问I/O设备占用的内存区域了(0xa0000~0xfffff)。 + + sys_memset:服务进程用它来写数据到不属于自己的内存里。当新进程创建时,进程管理器用它来为新进程清空内存。 + +- 复制内存 + + sys_umap:把虚拟地址转换为物理地址。 + + sys_vircopy, sys_physcopy:使用虚拟或物理地址复制内存。 + + sys_virvcopy, sys_physcopy:使用向量化的I/O请求,它们可以向系统任务请求一系统的内存复制操作。 + +- 其它 + + sys_times:对应了`times`系统调用。 + + sys_setalarm:与`alarm`系统调用相关。 + + sys_abort:当要求关闭系统或产生panic之后,进程管理器会产生此内核调用;当用户按下`Ctrl-Alt_Del`组合键后,tty设备驱动也会产生此内核调用。 + + sys_getinfo:获取内核的信息。在`include/minix/syslib.h`里定义了获取内核信息的各种宏,它们都是使用的此内核调用。 + +#### 进程调度 + +Minix3使用的多级调度算法。具体过程是:先找到优先级最高的非空的队列,然后选择顶头的进程开始执行。`IDLE`进程在最低优先级队列里,且始终是处于就绪的状态,这就保证没有其它进程时至少还有一个进程可以跑。 + +初始状态下,时钟和系统任务在第1级,拥有最高的权限。设备驱动在第2级。服务进程在第3级。用户进程在更低的层级,但可以通过`nice`命令来调整。 + +时钟任务用于监控所有进程的时间。 + +任务、驱动程序和服务程序除非被阻塞,否则应该是一直运行的,它们会有大的时间片。它们如果运行的太久,也是可能被抢占的,这种机制可以防止有问题的高优先级进程锁死系统。 + +调度器管理着16个就绪队列。数组`rdy_head`保存了每个就绪队列的头,而数组`rdy_tail`保存了每个就绪队列的尾。 + +每个队列上使用的是轮转调度算法。时间片用完的进程会调度到队列的末尾,时间片没用完但被阻塞的进程再唤醒时会放在队列的顶头。 + +#### 驱动程序注册中断的过程 + +1. 一个用户态的、由中断驱动的设备驱动程序,当它需要注册一个中断处理例程时,会向系统任务发出`sys_irqctl`调用。 +2. 系统任务再调用`put_irq_handler`。但是在中断例程的字段里保存的将是系统任务所在内核空间的`generic_handler`的地址,而不是驱动程序所在用户空间的中断处理例程的地址。 +3. `generic_handler`用钩子结构体里的进程号字段定位此驱动程序在`priv`表里的入口,此中断在驱动程序的挂起中断位图里的对应位会置1。 +4. `generic_handler`向驱动程序发一个通知。此通知被识别为来自HARDWARE,驱动程序的挂起中断位图也包含在此消息里。 +5. 钩子结构体里的policy字段决定中断是立即打开还是保持关闭。如果是保持关闭,则驱动程序还需要发出一个内核调用`sys_irqenable`来开打中断。 + +#### 系统任务 + +系统任务是从内核中独立出来的进程,它不能像内核函数那样自由,不能进行实际的I/O,也不能操作内核表。 + +那么系统任务(驱动和服务程序)怎么和内核交互呢?答案是内核向它们提供一组服务。这些服务对普通用户是不可见的,系统任务通过这些服务进行实际的I/O,操作内核表等。 + +系统任务的工作就是就是接收上层对内核服务的请求并执行它们。上层的进程由于在用户态,无法访问内核里的数据结构,但系统任务可以。 + +系统任务的主程序在做完必要的初始化后就会进入一个循环。获取消息,发给合适的服务例程,然后发送一个回复。主文件`system.c`里有一些的通用支持函数,但处理内核调用是在`kernel/system`目录下进行的。 \ No newline at end of file diff --git a/Software/Linux分发版/Distr_Debian.md b/Software/Linux分发版/Distr_Debian.md index f78fd6b..1a86f3a 100644 --- a/Software/Linux分发版/Distr_Debian.md +++ b/Software/Linux分发版/Distr_Debian.md @@ -120,3 +120,10 @@ make menuconfig # 调整.config make CROSS_COMPILE=riscv64-linux-gnu- ARCH=riscv -j8 install ``` +#### 问题解决 + +1. 问题描述:libwacom9 : Depends: libwacom-common (= 2.2.0-1) but 1.12-1 is to be installed + + 原因分析:依赖冲突? + + 解决方法:`apt install libwacom9 libwacom2-` diff --git a/Software/Linux分发版/Distr_archLinux.md b/Software/Linux分发版/Distr_archLinux.md index 54094b0..35232a5 100644 --- a/Software/Linux分发版/Distr_archLinux.md +++ b/Software/Linux分发版/Distr_archLinux.md @@ -1,4 +1,4 @@ -#### archLinux安装过程分析 +#### 安装过程分析 本文是对archlinux安装过程原理的分析,而不是安装引导,具体的安装步骤请参照wiki.archlinux.org。 @@ -33,7 +33,7 @@ -#### 在qemu上安装archLinux +#### 在qemu上安装 1. qemu的网络采用tun/tap方式,这是最好连网方式 ``` @@ -106,7 +106,7 @@ pacman -S net-tools //这样才可以使用ifconfig等工具 ``` -#### U盘安装 +#### 在物理机上安装 ##### 1. 制作启动盘 @@ -200,3 +200,11 @@ vim /etc/asound.conf pacman -S gst-plugins-base gst-plugins-bad gst-plugins-good gst-plugins-ugly gst-libav ``` +#### 使用AUR + +``` +git clone # 下载 +makepkg -si # 安装或更新包,并使用pacman安装缺失的依赖 +pacman -Rs # 卸载包 +``` + diff --git a/Software/_git命令/github.md b/Software/_git命令/github.md index 56b8132..e10b956 100644 --- a/Software/_git命令/github.md +++ b/Software/_git命令/github.md @@ -61,9 +61,33 @@ - Job matrix:一个matrix生成的job数不得超过256个。 - Workflow运行队列:每个仓库10秒内的的wrokflow队列不得超过500个 +##### 编写action + +- Dockerfile : 用于创建Docker容器action +- action.yml:action的配置 + - `input:`定义接收的参数,其中`required`为true则必须传递此参数。 + - `runs:`定义运行环境,比如docker。 +- entrypoint.sh:执行脚本。 + ##### 例子:代码同步 -1. `ssh-keygen`生成一个密钥对,私钥放github,公钥放gitlink。 +1. `ssh-keygen`生成一个密钥对,私钥放github的`仓库设置->Secrets`下,公钥放gitee的`个人设置->SSH公钥`下。 +2. gitee的个人设置下新建一个私人令牌,保存到github仓库设置的`secrets`下。 +3. 在github仓库里`.github/workflow/`目录下新建一个yml文件,使用第三方action实现推送。 + +##### 例子:缓存文件 + +- 输入: + + `path` - 要缓存的文件和目录 + + `key` - 为保存文件而设置的键 + + `restore-keys` - 键的列表,如果缓存没有命中用来恢复缓存 + +- 输出: + + `cache-hit` - 一个布尔值,表示是否为键找到了确切的匹配。 #### 免密登陆 diff --git a/Software/_下载工具/curl.md b/Software/_下载工具/curl.md index 9ee8c6f..61b3501 100644 --- a/Software/_下载工具/curl.md +++ b/Software/_下载工具/curl.md @@ -22,6 +22,7 @@ Client URL,用来请求web服务器,是一个上传下载工具。 -S, --show-error # 与-s联用,当产生错误时会显示出错信息。 -v, --verbose # 显示一次http通信的整个过程。 -x, --proxy [protocol://][:port] # 指定代理。 +-X, --request # ``` diff --git a/Software/_压缩工具/tar.md b/Software/_压缩工具/tar.md index 7b71baf..8c76f79 100644 --- a/Software/_压缩工具/tar.md +++ b/Software/_压缩工具/tar.md @@ -106,6 +106,7 @@ tar {-x|--extract|--get} [-f ] [options] [member...]: 从归档文件中 ``` tar cf abc.tar ./abc # 给abc目录创建归档文件abc.tar +tar -cJf abc.tar.xz ./abc # 给abc目录创建归档文件并压缩 tar xf abc.tar -C ~/ # 将abc.tar解压到用户目录 tar tf abc.tar # 列出abc.tar里的文件 tar tf abc.tar | awk -F "/" '{print $2}' | uniq diff --git a/Software/_压缩工具/xz.md b/Software/_压缩工具/xz.md index 89afc0d..0c2fb3c 100644 --- a/Software/_压缩工具/xz.md +++ b/Software/_压缩工具/xz.md @@ -20,7 +20,7 @@ lzcat # 等价于xz -dc -F lzma,解压lzma文件并输出到stdout ##### 操作模式 ``` ---z, --compress # 压缩 +-z, --compress # 压缩 -d, --decompress, --uncompress # 解压 -t, --test -l, --list @@ -67,3 +67,22 @@ lzcat # 等价于xz -dc -F lzma,解压lzma文件并输出到stdout ##### 配置压缩过滤链 ##### 其它 + +#### 示例 + +##### 基本 + +``` +xz foo # 把文件foo压缩为foo.xz,并在压缩成功后删除foo +xz -dk bar.xz # 解压缩bar.xz为bar,且在解压成功后不删除bar.xz +tar cf - baz | xz -4e > baz.tar.xz + # 从文件baz创建baz.tar.xz,比默认的-6更慢但会需要更少的内存 +xz -dcf a.txt b.txt.xz c.txt d.txt.lzma > abcd.txt + # 只用一条命令就可以把压缩文件和非压缩文件合并为一个文件 +``` + +##### 并行压缩 + +##### 机器人模式 + +##### 配置压缩过滤链 diff --git a/Software/_文本编辑/sed.md b/Software/_文本编辑/sed.md index cf6d82f..d7c067c 100644 --- a/Software/_文本编辑/sed.md +++ b/Software/_文本编辑/sed.md @@ -58,6 +58,9 @@ sed -i "/abcd/d" input-file # 将指定目录path下的所有文件里的oldstr替换为newstr sed -i "s/oldstr/newstr/g" `grep oldstr -rl path` +# 删除每行里的前51个字符 +sed -i "s/.\{51\}//" file + # 把文件里从start到end之间的内容打印出来(包含start和end所在的行) sed -n '/start/,/end/p' file diff --git a/Software/_文本编辑/vim.md b/Software/_文本编辑/vim.md index 49d7e2f..7b91df8 100644 --- a/Software/_文本编辑/vim.md +++ b/Software/_文本编辑/vim.md @@ -12,8 +12,11 @@ vim [options] -q [errorfile] # 编辑首先出错的文件 #### 选项 ``` ++[num] # 打开文件后光标停留在num行 -b # 二进制模式。这样文件末尾就不会自动加上'0x0a'了。(0x0a即'\n') -d # 比较多个文件的差异。等价于vimdiff。 +-o[N] # 横向分屏打开文件。忽略N,则每个文件对应一个分屏。 +-O[N] # 纵向分屏打开文件。忽略N,则每个文件对应一个分屏。 -R # 只读模式。等价于view。 ``` @@ -142,7 +145,7 @@ V # 选择,以行为单位 -##### 打开多个文件 +##### 分割屏幕 ``` :vsp filename # 纵向分屏,并打开文件filename diff --git a/Software/_文本编辑/vscode.md b/Software/_文本编辑/vscode.md index 6ad5070..f4878a8 100644 --- a/Software/_文本编辑/vscode.md +++ b/Software/_文本编辑/vscode.md @@ -1,11 +1,20 @@ +#### 快捷操作 + - 自动换行:搜索"toggle word wrap"。在Ubuntu下为`alt+z`。或者`File > Preferences > Settings`打开用户设置,将`editor.wordWrap`改为`on`。 - - 向后跳转:在“Keyboard Shortcuts”搜索"Go Back"可得。在Ubuntu下为`Ctrl+Alt+-` - - 查找文件:搜索"Go to file"可得。在Ubuntu下为`Ctrl+P` +- 跳转到括号的另一边:搜索"go to bracket"可得。在Ubuntu下为`Ctrl+Shift+\` + +#### 配置 + +- rust支持:安装插件rust-analyzer即可。不要安装插件Rust,会冲突。 - 配置C语言的库 Ctrl+Shift+P调出配置窗口,输入edit,选择“C/CPP:Edit Configurations”,在打开的json文件中“includePath”下添加库文件的地址 -- 跳转到括号的另一边:搜索"go to bracket"可得。在Ubuntu下为`Ctrl+Shift+\` +#### 问题解决 + +1. 问题描述:终端中字体显示不正常,字符之间像隔着空格 + + 解决方法:打开设置-用户-功能-终端,向下翻找到Font Family,设置为"monospace" diff --git a/Software/_模拟器与容器/docker.md b/Software/_模拟器与容器/docker.md index 694be55..050d171 100644 --- a/Software/_模拟器与容器/docker.md +++ b/Software/_模拟器与容器/docker.md @@ -74,7 +74,9 @@ docker buildx [options] # 使用buildkit来构建 bake build [options] # 开始一个构建 -t, --tag # stringArry的格式是'name:tag',其中tag是可选的 - create + create # 创建一个builder实例 + --name # builder实例的名字 + --use # 设置当前的builder实例 du inspect ls @@ -349,6 +351,7 @@ docker run [options] [cmd] [args] --name # 指定容器名 --network # 把容器连接到一个network -p, --publish # 把容器的端口发布到主机 +--privileged # 为此容器提供扩展的权限(extended priviledges) --rm # 当exit的时候自动删除容器 -t, --tty # 分配一个伪TTY -v, --volume # 绑定并挂载一个卷 @@ -399,12 +402,42 @@ docker stop [options] # 停止一个或多个运行中的容器。 #### 配置 ``` -# 使用代理上网 +# 使用代理上网,方法一 vim /etc/default/docker # 修改http_proxy + +# 使用代理上网,方法二 +vim ~/.docker/config.json # 添加如下内容 +{ + "proxies": + { + "default": + { + "httpProxy":"http://proxy.example.com:8080", + "httpsProxy":"http://proxy.example.com:8080", + "noProxy":"localhost,127.0.0.1,.example.com" + } + } +} ``` +#### 多架构支持 + +##### 使用binfmt_misc + +binfmt_misc可以模拟执行异架构的二进制程序 + +``` +apt install binfmtc binfmt-support +docker run --rm --privileged multiarch/qemu-user-static --reset --persistent yes +docker run -it riscv64/alpine:edge +``` + +##### 使用buildx子命令 + +buildx是下一代标准构建命令的前端 + #### 使用示例 ``` @@ -430,14 +463,16 @@ docker cp alpine-3:root/abc . # 把容器alpine-3的abc文件传到当前目录 #### 错误分析 -1. 问题描述 +1. 问题描述:脚本script_file.sh在docker内手动运行正常,但使用`docker exec -d docker_name script_file.sh`运行出错。错误原因是:command not found。 - 脚本script_file.sh在docker内手动运行正常,但使用`docker exec -d docker_name script_file.sh`运行出错。错误原因是:command not found。 + 原因分析:因为在`.bashrc`文件里设置了额外的环境变量,而`docker exec`命令并不会设置额外的环境变量。 - 原因分析 + 解决方法:在脚本里使用`source`命令设置所需要的环境变量。 - 因为在`.bashrc`文件里设置了额外的环境变量,而`docker exec`命令并不会设置额外的环境变量。 +2. 问题描述:`Cannot connect to the Docker daemon` - 解决方法 - - 在脚本里使用`source`命令设置所需要的环境变量。 + 原因分析:docker的守护进程没有启动 + + 解决方法:要找到具体的原因,比如用`systemctl status docker`进一步排查。 + +3. 问题描述:`start request repeated too quickly for docker.service` diff --git a/Software/_系统工具/chroot.md b/Software/_系统工具/chroot.md index 2a581f7..0d35881 100644 --- a/Software/_系统工具/chroot.md +++ b/Software/_系统工具/chroot.md @@ -6,3 +6,12 @@ chroot [options] [ [args]] ``` +#### 问题解决 + +1 + +问题描述:`can't execute '/bin/sh': No such file or directory` + +原因分析:要切换过去的目录里没bin/sh + +解决方法:`cp /bin/bash bin/sh` diff --git a/Software/builtin命令/getopts.md b/Software/builtin命令/getopts.md new file mode 100644 index 0000000..ca475ec --- /dev/null +++ b/Software/builtin命令/getopts.md @@ -0,0 +1,7 @@ +快速版的`getopt`命令。 + +#### 示例 + +```bash +``` + diff --git a/Software/包管理/pacman.md b/Software/包管理/pacman.md index 5abf7a4..e5adf9e 100644 --- a/Software/包管理/pacman.md +++ b/Software/包管理/pacman.md @@ -144,11 +144,12 @@ pacman -S --help # 查询安装软件包的方法 ##### 1 -**错误提示**:error: failed to commit transaction (conflicting files)。 +- 错误提示:error: failed to commit transaction (conflicting files)。 -原因分析:这是文件冲突,pacman不会主动覆盖已经存在的文件。 +- 原因分析:这是文件冲突,pacman不会主动覆盖已经存在的文件。 + +- 解决方法:将冲突的文件删除,重命名或转移到其它文件夹。 -解决方法:将冲突的文件删除,重命名或转移到其它文件夹。 ##### 2 diff --git a/Software/文本转换/getopt.md b/Software/文本转换/getopt.md index e6cf198..578821c 100644 --- a/Software/文本转换/getopt.md +++ b/Software/文本转换/getopt.md @@ -21,7 +21,7 @@ ``` getopt [options] [--] getopt [options] <-o|--options> [options] [--] - # options和sptstring决定解析的方式 + # options和optstring决定解析的方式 # parameters是要解析的内容 ``` diff --git a/Software/设备管理/bluetoothctl.md b/Software/设备管理/bluetoothctl.md new file mode 100644 index 0000000..3151b06 --- /dev/null +++ b/Software/设备管理/bluetoothctl.md @@ -0,0 +1,12 @@ +#### 交互命令 + +``` +help # 获取可用的命令 +select # 选择默认控制器 +power on # 开启控制器。默认是关闭的。 +devices # 获取要配对的MAC地址 +scan on # 扫描设备 +pair # 配对 +connect # 完成连接 +``` + diff --git a/Software/进程管理/strace.md b/Software/进程管理/strace.md index e862e6d..aa52347 100644 --- a/Software/进程管理/strace.md +++ b/Software/进程管理/strace.md @@ -81,3 +81,16 @@ strace [options] [args] -V # 打印版本号。 ``` +#### 错误记录 + +##### 1 + +- 错误描述:docker里运行strace,提示`ptrace(PTRACE_TRACEME, ...): Function not implemented` +- 原因分析:请参考[why-strace-doesnt-work-in-docker](https://jvns.ca/blog/2020/04/29/why-strace-doesnt-work-in-docker/) +- 解决方法:`docker run --cap-add=SYS_PTRACE -it ubuntu:18.04 /bin/bash` + +##### 2 + +- 错误描述:shell脚本里运行strace,提示`strace: exec: Permission denied` +- 原因分析:不知道为什么 +- 解决方法:`bash ./script.sh`