deffront_recursion(root: Node): if root isNone: returnNone print(root.item) if root.lchild isnotNone: front_recursion(root.lchild) if root.rchild isnotNone: front_recursion(root.rchild)
中序遍历
1 2 3 4 5 6 7 8
defMiddle_recursion(root: Node): if root isNone: returnNone if root.lchild isnotNone: front_recursion(root.lchild) print(root.item) if root.rchild isnotNone: front_recursion(root.rchild)
后序遍历
1 2 3 4 5 6 7 8
defMiddle_recursion(root: Node): if root isNone: returnNone if root.lchild isnotNone: front_recursion(root.lchild) if root.rchild isnotNone: front_recursion(root.rchild) print(root.item)
''' 1. 同样先找到最左边的节点,父节点和左子节点入栈 2. 找到最后一个左子节点之后,判断栈顶的节点,出栈顺序是先左子后父节点,所以只需要判断右子节点的情况: 如果栈顶节点的右子节点为空,直接打印栈顶节点。 如果栈顶节点的右子节点是上一个出栈的节点,那么说明已经访问到了右子节点,可以继续打印父节点 如果栈顶的右子节点不为空也不是上一个访问的节点,所以要先去访问右子树, 将右子节点入栈,退出循环,执行第一步 ''' defback_stack(self, root): if root isNone: returnNone stack = [] Tag = None stack.append(root) while stack: Node = stack[-1] while Node.lchild: stack.append(Node.lchild) Node = Node.lchild
while stack: Node = stack[-1] if Tag == Node.rchild or Node.rchild isNone: Node = stack.pop() print(Node.item) Tag = Node elif Node.rchild isnotNone: stack.append(Node.rchild) break
ls 04ea1faa8074e5862f40eecdba968bd9b7f222cb30e5bf6a0b9a9c48be0940f2/ diff link lower merged work
手动mount的例子
原本目录,文件都分散在不同目录ABC
1 2 3 4 5 6 7 8 9 10 11
. ├── A │ ├── aa │ └── a.txt ├── B │ ├── a.txt │ └── b.txt ├── C │ └── c.txt └── worker └── work [error opening dir]
overlay 挂载到/tmp/test目录 sudo mount -t overlay overlay -o lowerdir=A:B,upperdir=C,workdir=worker /tmp/test/
查看test目录
1 2 3 4 5
/tmp/test/ ├── aa ├── a.txt ├── b.txt └── c.txt
1 2
mount | grep 'overlay' overlay on /tmp/test type overlay (rw,relatime,lowerdir=A:B,upperdir=C,workdir=worker)
overlay的增删改
当运行docker容器时查看挂载
1 2 3 4 5 6
overlay on /var/lib/docker/overlay2/04ea1faa8074e5862f40eecdba968bd9b7f222cb30e5bf6a0b9a9c48be0940f2/merged type overlay (rw,relatime, lowerdir=/var/lib/docker/overlay2/l/B74PWZCBMRCWXFH5UL2ZXB5WEU:/var/lib/docker/overlay2/l/WNHICVPVSDNUGSCZW435TPSMOK, upperdir=/var/lib/docker/overlay2/04ea1faa8074e5862f40eecdba968bd9b7f222cb30e5bf6a0b9a9c48be0940f2/diff, workdir=/var/lib/docker/overlay2/04ea1faa8074e5862f40eecdba968bd9b7f222cb30e5bf6a0b9a9c48be0940f2/work )
# 解析文本文件 #with pathlib.Path('requirements.txt').open() as requirements_txt: # install_requires = [str(requirement) for requirement in pkg_resources.parse_requirements(requirements_txt) ]
Collecting yarl<2.0,>=1.0 (from aiohttp==3.6.2) Downloading yarl-1.6.2.tar.gz (177kB) Installing build dependencies: started Installing build dependencies: finished with status 'done' Getting requirements to build wheel: started Getting requirements to build wheel: finished with status 'done' Preparing wheel metadata: started Preparing wheel metadata: finished with status 'done' ...
gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/opt/ha/include/python3.8 -c yarl/_quoting_c.c -o build/temp.linux-x86_64-3.8/yarl/_quoting_c.o error: command 'gcc' failed with exit status 1 ---------------------------------------- ERROR: Failed building wheel for yarl Running setup.py clean for yarl Failed to build yarl
Download the file for your platform. If you're not sure which to choose, learn more about installing packages. Files for yarl, version 1.6.2 Filename, size File type Python version Upload date Hashes yarl-1.6.2-cp36-cp36m-macosx_10_14_x86_64.whl (128.3 kB) Wheel cp36 Oct 13, 2020 View yarl-1.6.2-cp36-cp36m-manylinux1_i686.whl (293.5 kB) Wheel cp36 Oct 13, 2020 View yarl-1.6.2-cp36-cp36m-manylinux2014_aarch64.whl (294.5 kB) Wheel cp36 Oct 13, 2020 View
...
yarl-1.6.2.tar.gz (177.5 kB) Source None Oct 13, 2020 View
.data s: .ascii "hello world\n" len = . - s .text .global _start _start:
movl $4, %eax /* write system call number */ movl $1, %ebx /* stdout */ movl $s, %ecx /* the data to print */ movl $len, %edx /* length of the buffer */ int $0x80
movl $1, %eax /* 退出的系统调用编号 */ movl $0, %ebx /* exit status */ int $0x80
在 x86 保护模式中,处理 INT 中断指令时,CPU 首先从中断描述表 IDT 取出对应的门描述符,判断门描述符的种类,然后检查门描述符的级别 DPL 和 INT 指令调用者的级别 CPL,当 CPL<=DPL 也就是说 INT 调用者级别高于描述符指定级别时,才能成功调用,最后再根据描述符的内容,进行压栈、跳转、权限级别提升。内核代码执行完毕之后,调用 IRET 指令返回,IRET 指令恢复用户栈,并跳转会低级别的代码。
其实,在发生系统调用,由 Ring3 进入 Ring0 的这个过程浪费了不少的 CPU 周期,例如,系统调用必然需要由 Ring3 进入 Ring0(由内核调用 INT 指令的方式除外,这多半属于 Hacker 的内核模块所为),权限提升之前和之后的级别是固定的,CPL 肯定是 3,而 INT 80 的 DPL 肯定也是 3,这样 CPU 检查门描述符的 DPL 和调用者的 CPL 就是完全没必要。正是由于如此,Intel x86 CPU 从 PII 300(Family 6,Model 3,Stepping 3)之后,开始支持新的系统调用指令 sysenter/sysexit。sysenter 指令用于由 Ring3 进入 Ring0,SYSEXIT 指令用于由 Ring0 返回 Ring3。由于没有特权级别检查的处理,也没有压栈的操作,所以执行速度比 INT n/IRET 快了不少。
deb [trusted=yes] file:///mnt/iso/ juniper main multiverse restricted universe deb [trusted=yes] http://ftp.cn.debian.org/debian/ stretch main contrib non-free deb [trusted=yes] http://ftp.cn.debian.org/debian/ stretch-updates main contrib non-free deb [trusted=yes] http://mirrors.ustc.edu.cn/debian-security/ stretch/updates main contrib non-free deb [trusted=yes] http://ftp.cn.debian.org/debian/ stretch-backports main contrib non-free
安装虚拟工具
安装 qemu, libvirt, virt-manager
1
sudo apt install qemu libvirt virt-manager
libvirt 没有网络
执行virsh net-list -all 发现default 网络处于未激活状态, 于是执行 systemctl status libvirtd 发现
# # These can be used in cases when no URI is supplied by the application # (@uri_default also prevents probing of the hypervisor driver). # uri_default = "qemu:///system"
$ lvconvert --mergesnapshot /dev/centos/backup Delaying merge since origin is open. Merging of snapshot centos/backup will occur on next activation of centos/root.
IRQ vector, interrupt count per CPU (0 .. n), the hardware source, the hardware source's channel information, and the name of the device that caused the IRQ.