Blog

Java Thread

java 的线程由 os scheduler 负责调度 Java thread scheduling is primarily managed by the operating system (OS) scheduler, but the Java Virtual Machine (JVM) and the application code can influence thread behavior in several ways. java 归根结底一个用户空间的程序而已。 实际的线程调度根本上还是由操作系统的调度器负责。 java 只是可以调整相应参数来影响线程的调度。 线程最终如何调度 java 无法决定。 OS Scheduler Dependency Native Threads: Modern JVMs use native threads (one-to-one mapping with OS threads). The OS scheduler is responsible for allocating CPU time to these threads based on its own algorithms (e.g., time-sharing, priority-based scheduling). Thread Lifecycle: The OS handles thread creation, scheduling, preemption, and termination. Even though Java provides abstractions like Thread and Runnable, the underlying OS controls execution. java 可以影响 Thread 行为 While the OS scheduler has ultimate authority, Java applications can influence thread behavior through:

Read more →

May 6, 2025

Syscall Futex

#syscall#futex

Futex (Fast Userspace Mutex) A futex is a Linux kernel system call that provides a fast and efficient mechanism for implementing user-space synchronization primitives, such as mutexes, semaphores, and condition variables. It minimizes kernel involvement in uncontended cases, reducing overhead by handling synchronization in userspace when possible. Futexes split synchronization into user-space atomics (fast) and kernel-assisted blocking (slow), optimizing for the common case. The boundary is enforced by hardware (CPU modes) and the need for kernel-managed resources (scheduling, interrupts).

Read more →

May 5, 2025

Asm Dynamic Linker

dynamic linker 简介 dynamic linker (also called the dynamic loader) is a shared object (*.so file) on Linux systems. It plays a critical role in the execution of dynamically linked programs. What Is the Dynamic Linker? The dynamic linker is a special shared library responsible for: Loading the program’s dependencies (shared libraries like libc.so.6). Resolving symbols (e.g., function addresses like printf). Performing relocations (adjusting addresses for shared libraries). Invoking constructors/destructors (via .init_array and .fini_array). On Linux, the dynamic linker is typically named:

Read more →

May 4, 2025

Master Elf Sections Dynamic Link

Dynamic Linking 涉及到的 section Section Type Purpose Example Command .dynamic DYNAMIC Contains metadata for the dynamic linker (e.g., needed libraries, symbol tables, relocations). readelf -d demo .plt PROGBITS Procedure Linkage Table: Stubs for external function calls (e.g., printf). objdump -d demo .got / .got.plt PROGBITS Global Offset Table: Stores resolved addresses for functions and variables. objdump -R demo .dynsym DYNSYM Dynamic symbol table (subset of .symtab) for runtime symbol resolution. readelf -s demo .dynstr STRTAB String table for symbol names in .dynsym. readelf -p .dynstr demo .gnu.hash GNU_HASH Optimized hash table for fast symbol lookup (replaces legacy .hash). readelf -p .gnu.hash demo .rela.dyn RELA Relocations for global variables (e.g., message). readelf -r demo .rela.plt RELA Relocations for function calls (e.g., printf). readelf -r demo .init_array INIT_ARRAY Array of constructor functions (marked with __attribute__((constructor))). readelf -s demo .fini_array FINI_ARRAY Array of destructor functions (marked with __attribute__((destructor))). readelf -s demo .interp PROGBITS Path to the dynamic linker (e.g., /lib64/ld-linux-x86-64.so.2). readelf -p .interp demo symbol table 符号表分析 The objdump -t demo command displays the symbol table of the ELF executable demo. This table lists all symbols (functions, variables, sections, etc.) defined or referenced in the binary.

Read more →

May 2, 2025

Master Elf Sections

分析环境 mint21 ELF (linking view) 分析 一个 ELF 文件有多种 view。 从 linking 视角来理解 sections 到底是如何工作的。 源代码的各个不同的部分编译后都被放到了哪个 section。 本文主要分析 rodata text data bss 这 4 个 section。 示例代码 gcc -g -o demo demo.c

Read more →

April 30, 2025

Gcc Compile C Prog

分析代码 os: Linux Mint 22.1 hello.c#include <stdio.h> int main(void){ printf("hello world"); } strace 追踪编译流程 strace -t -f -o hello.log -e trace=execve -s 2000 gcc -o hello hello.c All execve() system calls during compilation, showing how GCC orchestrates the build process.

Read more →

April 29, 2025

Master Elf

hello world #include <stdio.h> int main() { printf("hello world\n"); } gcc –save-temps -o hello hello.c What is ELF? ELF (Executable and Linkable Format) is a standardized binary format for storing compiled programs, libraries, and other binaries on Unix-like systems (e.g., Linux). It defines how machine code, data, symbols, relocation information, and metadata are organized in files like:

Read more →

April 28, 2025

Great Prompt

#llm#prompt

great prompt我在做 XX。如果你是一位专业人士,有更好的方法和建议吗?尽可能全面。

Read more →

April 28, 2025

Master Type System

#type#instruction

为啥需要 type system?type 就是契约 At the hardware level, the machine does not know types in the way humans or high-level programming languages do. 硬件级别就是电信号了。type 这种概念不存在。 Bits are just bits (0s and 1s), and the CPU/memory has no intrinsic understanding of “integers,” “strings,” or “objects.” But types exist in programming languages to impose structure on those raw bits, guiding both the programmer and the compiler/interpreter on how to interpret and manipulate data safely and meaningfully. Bridging Human Intent <-> Machine Execution Types act as a contract

Read more →

April 25, 2025

Linux Process State

#process#state#state machine

进程状态机最近在看南京大学蒋炎岩老师的 2025 操作系统课程。里面有一句话, 计算机中的一切程序可以视为 state machine。很有启发。进程有初始状态, CPU 这个无情的执行指令的机器执行一条指令后,程序的状态就发生了变化。

Read more →

April 22, 2025

Asm How Glibc Wrap Syscall

#syscall#glibc#asm

实验平台: x86_64 GNU/Linux mint22.1 使用 glibc 的函数write1.c #include <unistd.h> int main() { const char msg[] = "Hello, glibc!\n"; write(1, msg, sizeof(msg) - 1); // glibc's write() wrapper return 0; } gcc -o write1 write1.c 使用 ltrace ./write1 查看调用了 write 库函数 不使用 glibc 的函数write2.c

Read more →

April 21, 2025

Cmd Strace

#syscall#strace

syscall操作系统运行在 kernel space, 拥有整个系统的控制权。 应用程序运行在 user space, 拥有部分权限。 这就是隔离。 To prevent user applications from accessing or modifying critical operating system data. 想让操作系统做些事情怎么办?使用 syscall。

Read more →

April 19, 2025

Java String Concat in Loop

#string#java#bytecode

分析环境 jdk8 分析代码 public class StringConcat { public static void main(String[] args) { String s = "$"; for (int i = 0; i < 10; i++) { s += i; } System.out.println(s); } } main 字节码 public static void main(java.lang.String[]); Code: 0: ldc #2 // String $ 2: astore_1 3: iconst_0 4: istore_2 5: iload_2 6: bipush 10 8: if_icmpge 36 11: new #3 // class java/lang/StringBuilder 14: dup 15: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V 18: aload_1 19: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 22: iload_2 23: invokevirtual #6 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 26: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 29: astore_1 30: iinc 2, 1 33: goto 5 36: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream; 39: aload_1 40: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 43: return main 字节码执行图解分析

Read more →

April 9, 2025

Name Id Pairs

name id pairs 对于 OS 来说,id 更重要。 symbolic name(human readable name) number name(low level name) service name port user name user id process name process id host name ip address file name inode number signal name signal number syscall name syscall number

Read more →

April 9, 2025

Java Aqs

abstract queued synchronizer 是啥? AQS is an abstract class that provides a skeleton for managing thread contention, queuing, and state synchronization. It uses a FIFO wait(sync) queue to manage threads waiting for access to a shared resource and an atomic integer (state) to track the synchronizer’s status (e.g., locked/unlocked, available permits). AQS 数据结构 /** * Head of the wait queue, lazily initialized. Except for * initialization, it is modified only via method setHead. Note: * If head exists, its waitStatus is guaranteed not to be * CANCELLED. */ private transient volatile Node head; // 等待队列的 head /** * Tail of the wait queue, lazily initialized. Modified only via * method enq to add new wait node. */ private transient volatile Node tail; // 等待队列的 tail /** * The synchronization state. */ private volatile int state; // 同步状态, 这就是所谓的 lock /** * The current owner of exclusive mode synchronization. */ private transient Thread exclusiveOwnerThread;//继承自 AbstractOwnableSynchronizer Node 数据结构 组成双向链表,在之上构建等待队列

Read more →

March 21, 2025

Java User Space Schedule

A user-space scheduler manages tasks or “threads” entirely within an application, without relying on the operating system (OS) scheduler. This is different from kernel-level scheduling, where the OS manages threads. 什么是用户态调度?可以简单理解为自定义一堆任务, 由用户决定怎样执行这些任务。不涉及操作系统的进程/线程调度。

Read more →

March 10, 2025

Learn Llm

pre-traininghttps://huggingface.co/spaces/HuggingFaceFW/blogpost-fineweb-v1 100000 symbols(tokens) raw text —>tokenization —> token tokenization https://tiktokenizer.vercel.app/?model=cl100k_base statistic token simulator 这就是所谓的 prediction 参数 各个 token 的权重 模型有大量的知识,存储在上亿的参数之中。这些参数可以视为对超大规模的知识进行的一种有损压缩。超大规模知识的模糊记忆。 按照统计规律给出所谓的答案 模型需要中间结果 概率、统计 in-context learning

Read more →

February 17, 2025

Cache Miss Anomaly

缓存 miss 类型compulsory miss 一开始缓存里啥都没有,cold-start miss capacity miss 缓存容量有限,需要 evict 一些页 conflict miss cpu cache 的 set-associativity 的缓存行

Read more →

February 13, 2025

lsof examples

通用 ^ 表示非 多个值是 CSV 形式 lsof -i(internet) -i 后可以有空格 [46][protocol][@hostname|hostaddr][:service|port] 46 specifies the IP version, IPv4 or IPv6 that applies to the following address.‘6’ may be be specified only if the UNIX dialect supports IPv6. If neither ‘4’ nor ‘6’ is specified, the following address applies to all IP versions. protocol is a protocol name - TCP, UDP hostname is an Internet host name. Unless a specific IP version is specified, open network files associated with host names of all versions will be selected. hostaddr is a numeric Internet IPv4 address in dot form; or an IPv6 numeric address in colon form enclosed in brackets, if the UNIX dialect supports IPv6. When an IP version is selected, only its numeric addresses may be specified. service is an /etc/services name - e.g., smtp -or a list of them. port is a port number, or a list of them. lsof -i@10.10.129.99:8080 lsof -i4tcp all ipv4 tcp

Read more →

January 10, 2025

Master Iptables

数据包 接收 发送 转发 路由器 iptables 三要素table tables allow you to do very specific things with packets. 对数据包做特定的处理 filter table default mangle table nat table raw table chain each of these tables are composed of a few default chains. These chains allow you to filter packets at various points.

Read more →

January 7, 2025

My Source List

https://arthurchiao.art/ https://alexanderell.is/posts/ https://blog.ryanlevick.com/ https://brennan.io/blog/ https://bhoot.dev/ https://chsasank.com/ https://codewords.recurse.com/ https://crockford.com/blog.html https://devconnected.com/ https://joearms.github.io/ https://jitwxs.cn/ https://kiosk007.top/ https://kunststube.net/ https://linuxize.com/post/ https://matt.might.net/ https://www.marcobehler.com/ https://natanyellin.com/posts/ https://robertovitillo.com/blog https://research.swtch.com/ Russ Cox https://strikefreedom.top/ https://serhack.me/blog/ https://www.0xffffff.org/ https://www.booleanworld.com/ https://www.jmeiners.com/ https://www.timdbg.com/ https://www.taniarascia.com/ https://manybutfinite.com/archives/ 胡涂说 秋风的笔记 朱双印 陈树义

Read more →

January 6, 2025

Null Device

NULL device 是啥?The null device is a special file that discards all data written to it, but reports that the write operation succeeded. 用在何处? java 执行外部的命令, 但是不需要外部命令的执行结果. 直接丢弃 stdout, stderr. import java.io.*; public class DiscardProcessOutput { public static void main(String[] args) { try { // Create the ProcessBuilder with the command to run ProcessBuilder processBuilder = new ProcessBuilder("someCommand"); // Merge stdout and stderr and redirect them to /dev/null (or NUL in Windows) processBuilder.redirectErrorStream(true); if (System.getProperty("os.name").contains("Windows")) { processBuilder.redirectOutput(new File("NUL")); } else { processBuilder.redirectOutput(new File("/dev/null")); } // Start the process Process process = processBuilder.start(); // Wait for the process to finish int exitCode = process.waitFor(); System.out.println("Process exited with code: " + exitCode); } catch (IOException | InterruptedException e) { e.printStackTrace(); } } } References dev-null windows-NUL man7 /dev/null NUL in Windows seems to be actually a virtual path in any folder

Read more →

January 3, 2025

Ipc Unix Domain Socket

#ipc

unix domain socket 是啥? A Unix domain socket (UDS) or IPC socket (inter-process communication) is a data communications endpoint for exchanging data between processes executing on the same host operating system. 同一台机器两个不同的进程之间交换数据,优化过的 socket。 问题背景 java 写的程序需要和 c 写的程序交换数据,且两个程序运行在同一台机器上。

Read more →

July 23, 2024

My Tool Box

video & audio lux ttsmaker 表格 ascii-table 元素周期表 digital socpk 颜色 中国色 传统色 网络 WiFi 连接卡 海底电缆 工具集 油小猴 开发工具 神秘的热心网友 波特工具站 java JDK 启动盘制作 https://rufus.ie/zh/ https://ventoy.net/ windows sysinternals 编程 cron-expression crontab explainshell 隐私 Cover Your Tracks browserleaks explorer AST WASM compiler assembler brainfuck-visualizer

Read more →

April 19, 2024

Zookeeper Transaction Log

#zookeeper#log

分析的 zookeeper 代码版本为 3.9.1 。 zookeer 的 transaction log 为二进制文件,采用的是大端序。 zookeeper 数据持久化的功能在 zookeeper/server/persistence 下。 解析日志就可以获取 zookeeper 的数据。可以用来实现实时备份到另一个独立的 zookeeper 集群。

Read more →

October 21, 2023

Ipc Signal

#ipc

signal什么是 signal A signal can be thought of as a software interrupt. This means that a process that receives a signal stops the execution of the current program and makes the program respond to the signal. Signals are various notifications sent to a process in order to notify it of various “important” events. 信号是发送给进程的各种通知,以便通知它发生了各种“重要”的事件。

Read more →

April 11, 2023

Asm How Java Byte Code Execute

#asm#java#bytecode

jvm jvm 是一个栈式(stack-based)虚拟计算机。啥意思,就是大多数的 opcode 的操作数在 operand stack 上,执行的结果也放在 oprand stack 上。 有的 opcode 的操作数在 local variable table,如 iinc。

Read more →

April 5, 2023

Java Jdk Proxy

分析环境: jdk8 dynamic proxy 是啥? A dynamic proxy class is a class that implements a list of interfaces1 specified at runtime such that a method invocation through one of the interfaces on an instance of the class will be encoded and dispatched to another object through a uniform interface2. 动态代理类生成调用方法如下: Proxy.newProxyInstance(handler.getClass().getClassLoader(), new Class[]{Dynasty.class},handler); handler.getClass().getClassLoader() 运行时动态生成的代理类 load 到 jvm 使用的 class loader。 new Class[]{Dynasty.class} 运行时动态生成的代理类实现的一系列接口。 handler Invocation Handler 通过 invoke() 来分发方法,包含被实际代理的对象实例。 保存运行时生成的动态代理类ProxyGenerator.java /** debugging flag for saving generated class files */ private final static boolean saveGeneratedFiles = java.security.AccessController.doPrivileged( new GetBooleanAction( "sun.misc.ProxyGenerator.saveGeneratedFiles")).booleanValue(); 设置 sun.misc.ProxyGenerator.saveGeneratedFiles System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); 运行时生成的动态代理类($Proxy0)分析运行时生成的动态代理类实例化

Read more →

February 12, 2023

Algorithm Snowflake

分布式 ID 多个数据中心(一级),多个节点(一级),同一个时间点(一级),同时生成 ID(一级)。其实就是数字生成规则而已。没啥了不起的。 snowflake 算法使用一个 64bits 的正整数作为 ID。64bits 正整数 layout 如下:

Read more →

June 25, 2022

Master Pki

#pki#ssl

certificate 目标:绑定 public key 和 name。一切围绕着这个目标来展开。 图解 References 强烈推荐-everything-pki 翻译版-everything-pki ubuntu-trust-store-location decode-an-ssl-certificate csr-在线解析 github-public-key dns-caa-record X.509

Read more →

June 23, 2022

Java Thread Pool Params

基本策略 关注点分离,任务提交和执行分离。 延迟策略,延迟初始化。 图解 References 你管这破玩意叫线程池

Read more →

June 20, 2022

Virtual Memory Address Explore

#binary#linux

virtual memory 是啥? 本质是硬件支持。 virtual memory ===== MMU =====> physical memory OS + 硬件 共同为进程提供 virtual memory 功能。所有程序的内存布局一致。 为了安全。 virtual memory address space layout 代码测试 cargo new vas-explore main.rs

Read more →

May 22, 2022

Linux File Permissions

#linux#file

最近在使用 k8s 过程中,需要给 mount 的文件配置权限。 提起 file 的权限只想到 rwx,是不全面的,完整的权限是 rwxsStT。 权限列表 权限导图 特殊权限setuid Setuid is a Linux file permission setting that allows a user to execute that file or program with the permission of the owner of that file. 很明显,setuid 这个权限要和 execute 权限一起使用,作用于可执行文件。

Read more →

April 16, 2022

About

The pain you feel when you write is actually the pain of clarifying your thinking.(David Perell)

Read more →

March 27, 2022

Githubpage Hugo Website

#actions#hugo

步骤安装软件 git # 配置好 git git config --global user.name "your username" git config --global user.email "your email" hugo hugo 创建本地 website 参考:https://gohugo.io/getting-started/quick-start/

Read more →

March 19, 2022

2022-plan

#plan

https://www.bilibili.com/video/BV1Cx411S7HJ?p=2 https://see.stanford.edu/Course/CS107 ComputerSystem:A programer perspective Edtion3 English rust-lang kubernetes

Read more →

February 7, 2022

js-eventloop

#event-loop#call-stack#task-queue#timer

References understanding-the-event-loop-callbacks-promises-and-async-await-in-javascript learning-functional-programming-with-javascript what is event loop?js-conf what is event loop demo an-introduction-to-functional-programming how-javascript-works-in-browser-and-node 浏览器提供 Web Apis

Read more →

December 5, 2021

k8s-deploy-container-using-yaml

#katacoda#k8s#declarative#deploy

kubernetes 作为一个云上的操作系统,要想充分利用,就要了解 kubernetes 提供的功能。告诉系统要搞啥,k8s 帮你搞定这一切,归根结底,不开发 k8s 就是一个 k8s 的用户,知道 k8s 能具体做啥,写好 YAML 就可以。

Read more →

November 28, 2021

What-happens-type-url-into-browser-and-press-enter

#network#interrput#dns

dns query get the ip of the target domain browser cache firefox(about:networking#dns) /etc/hosts os cache macos 查看 dns 请求日志 sudo log stream –predicate ‘process == “mDNSResponder”’ –info dns resolver /etc/resolv.conf arp -a 查看有没有 dns 服务器的 mac 地址 ARP request for the nameserver send dns query to get the ip of the domain arp 获取 gateway 的 mac 地址 向 gateway 发送 ip packet References keyborad-interrput Chrome 是怎么判断地址栏输入的东西是不是网址? 这就是第一步😂-omnibox firefox dns ARP

Read more →

September 11, 2021

asm-java-jit

#java#jit

前言 无论多么花里胡哨的功能,最终落地到一台计算机上,都是二进制代码。虽然 java 代码跑在 jvm 平台之上,但是 jvm 只是负责执行 java 自定义的一套 bytecode 的工具,只要能解释字节码,这个工具用什么语言写都是可以的。主流的 HotSpot 虚拟机选择的 C++。

Read more →

July 18, 2021

java-keyword-volatile

#volatile#separate component#dependency#diagram

可见性问题 可见性问题思路 References von-neumann-harvard-architecture out-of-order-execution(dynamic execution) Instruction_scheduling X86/GCC memory fence的一些见解

Read more →

June 18, 2021

asm-pointers-and-memory

#pointers

Basic Pointer 为啥需要 Pointer? 更容易在不同代码段之间共享信息,在不同代码段之间来回复制也是可以的。但用指针的形式更好。 链式数据结构, 如链表和二叉树。 pointer dereference 指针必须要有指向的值,才可以 dereference。 没有指向的指针,dereference 时会 runtime error。

Read more →

April 28, 2021

cs-condition-variables

#condition variable#synchronization#queue#state

condition variable 是啥? condition variable 是啥?本质上就是一个状态变量 +队列。现实世界中,想要进行下一步的行动,往往需要满足一定的条件(condition)。如十字路口的交通信号灯,信号灯的颜色可以视为状态变量,根据不同的状态,汽车做出不同的选择。一条马路,可以视为队列。红灯时, 汽车就不能通过,排队等候。绿灯时,汽车才可以通过。在计算机中,同样存在这样的问题,如父进程需要等待子进程完成后(条件),才能继续运行。关键就是围绕状态变量来构建。

Read more →

April 18, 2021

cs-english-words

#words

a association a connection or cooperative link between people or organizations allot to assign as a share or portion ad-hoc An ad hoc activity or organization is done or formed only because a situation has made it necessary and is not planned in advance.Ad hoc is a word that originally comes from Latin and means “for this” or "for this situation." In current American English it is used to describe something that has been formed or used for a special and immediate purpose, without previous planning. 比如 shell 可以直接执行一次性的命令,这就是 ad-hoc,也可以提前写好 bash 脚本可以反复多次执行,这就是提前计划好的。Ad hoc can be used as an adjective or an adverb.

Read more →

December 28, 2020

cs-lock

#lock#synchronization

为啥需要 lock? 多处理器的存在 中断的存在 lock 是啥? lock 本质上是一个变量。变量本质上是一块内存。归根结底,lock 就是一块内存,用这块内存来保证线程的原子性。锁有两种状态:

Read more →

December 14, 2020

cs-cache

#notion#cache

There can be many caches stacked on top of each other. Cache 可以一层一层累积。 if you miss in one you try in the “lower level cache” Lower level, mean higher number. 在上层的 Cache miss 了,可以在下层的 Cache 去找。依次类推。 There can also be separate caches for data and instructions. Or the cache can be “unified”. 数据和指令的 Cache 可以独立,也可以混合。 to wit: the L1 data cache (d-cache) is the one nearest processor. It corresponds to the “data memory” block in our pipeline diagrams the L1 instruction cache (i-cache) corresponds to the “instruction memory” block in our pipeline diagrams. The L2 sits underneath the L1s. There is often an L3 in modern systems. cache 指导思想 局部性原理 temporal locality (时间局部性) Taking advantage of temporal locality:

Read more →

December 1, 2020

acknowledgement-timeout-retry-sequence-number

#notion#ack#timeout#retry#sequence-number

TCP 要解决的问题 references tcp-congestion-control tcp-congestion-control-ppt

Read more →

November 30, 2020

data_and_metadata

#notions

具体问题具体分析,确实非常重要。用正确的思想指导行动,才可事半功倍。 现实中的客观问题有意思的地方在于:无论你选择看得见,还是选择看不见,它都在那里,关键在于有没有人去解决,解决的人有多大的决心。

Read more →

November 26, 2020

notions_of_computer

#notions

指导思想 计算机是人发明的。由计算机组成的世界,其设计思想很明显要借鉴现实中的东西。正如一位伟人的著作开篇提出 “谁是我们的敌人?谁是我们的朋友?这个问题是革命的首要问题。中国过去一切革命斗争成效甚少,其基本原因就是因为不能团结真正的朋友,以攻击真正的敌人。”那么应对计算机,什么才是计算机组织背后的指导思想呢?个人认为有三个:1. hierarchy(层级)、2:group(分组)、3:order(有序)

Read more →

November 24, 2020

data-structure-btree

#data structure#BTree

B-tree 特性 所有的 leaves 都在同一层级。 B-Tree 被 minimum degree t 定义。t 依赖于 disk block size。 除了 root,其余节点必须至少有 t - 1 个 key。root 节点至少有 1 个 key。 所有的节点(包括 root)最多有 2t - 1 个 key。 某一个节点的子节点的个数 = 这个节点的 key 的个数 + 1。 一个节点的所有 key 从小到大排序。两个 key1 和 key2 之间的所有 child 都在 key1 和 key2 之间。 B-Tree 从 root 节点 grow(扩张) 和 shrink(收缩)。 search、insert、delete 时间复杂度是O(log n)。n 是 key 的总数。 t=3 为例来理解 B-tree 每一个节点(root 除外) 至少有 t - 1 = 2 个 key。 每一个节点最多有 2t - 1 = 5 个 key。节点 key 数量 = 5,称为节点满了。 问题来了,节点 key 个数大于 5 了咋办?拆分。什么时候来拆分呢?在向下遍历节点时发现满了,立即进行拆分。 B-Tree insert operation 拆分已满节点 #(btree-拆分已满节点)

Read more →

June 12, 2020

asm-how-computer-startup

#asm#x86

x86 架构计算机是如何启动的? 16-bit Processors and Segmentation (1978) The IA-32 architecture family was preceded by 16-bit processors, the 8086 and 8088. The 8086 has 16-bit registers and a 16-bit external data bus, with 20-bit addressing giving a 1-MByte address space. The 8088 is similar to the 8086 except it has an 8-bit external data bus. The 8086/8088 introduced segmentation to the IA-32 architecture. With segmentation, a 16-bit segment register contains a pointer to a memory segment of up to 64 KBytes. Using four segment registers at a time, 8086/8088 processors are able to address up to 256 KBytes without switching between segments. The 20-bit addresses that can be formed using a segment register and an additional 16-bit pointer provide a total address range of 1 MByte.

Read more →

June 8, 2020

data-structure-heap

#data structure#binary heap#priority queue#heap sort

线性 or 非线性 数据结构可以分为两大类:线性结构和非线性结构。线性结构典型的就是数组和链表,非线性典型就是树了。复杂的数据结构基本上都是两者的组合。

Read more →

May 18, 2020

os-banker's-algorithm

#os#dead lock#recource allocation

Banker’s Algorithm 银行家算法是什么 银行家主要就是通过放贷来赚钱的。那最重要的问题是啥?当然是把钱借给还得起的人咯。试想,银行把钱都借给了还不起的人,那银行就完蛋了。假设有一批人(多个进程)来借钱(将要申请资源),但是银行剩下的钱满足不了任何人,那就直接拒绝借贷。当然了,有一部分已经借出的钱回收之后(回收已经分配的资源),又可以满足一批人中某些人的借贷需求。依次类推,银行可以判定能不能按照某个顺序来给这批人放贷。类似的思路延伸到计算机世界,同理。操作系统给多个进程分配资源,能不能找到一个顺序给这些进程分配资源,并逐渐回收资源?从而满足多个进程的资源需求。采用银行家放贷和收贷的思路(这里排除利息,放多少贷,收多少钱。呵呵,哪有此种好事?)来分配和回收系统资源就是所谓的银行家算法。

Read more →

May 13, 2020

cache-replacement-policy-lru

#cache replacement#LRU

Cache cache 为啥要有 Cache 呢?根本原因是各种存储速度不匹配。或者为了加快某个过程,直接将多次转换的转换结果直接缓存起来,便于再次使用时直接绕开这些转换过程。典型的就是 MMU 的地址翻译过程,直接将虚拟地址多次转换的最后结果,也就是物理地址,直接缓存到 TLB 中,下次再次访问同一个虚拟地址,直接从虚拟地址拿到物理地址,绕开多次转换过程,这可不就提高了速度。CPU 的速度比 Memory 快得多,为了配上 CPU 超级快的速度,也就有了 L1,L2,L3 cache。还有就是存储器层次结构,速度快,容量小的存储作为速度慢,容量大的上级缓存。

Read more →

May 11, 2020

network-dhcp

#network#dhcp

DHCP 步骤 Discover Offer Request ACK References 127.0.0.1 和 0.0.0.0 DHCP-Basics full-packet-friday-dhcp dynamic-host-configuration-protocal dhcp-rfc

Read more →

May 9, 2020

data-structure-red-black-tree

#data structure#red-black-tree

References red-black-tree-visualization

Read more →

April 27, 2020

network-dns

#network#dns

怎样学习一个新的东西,也可以按照一定的套路的。这个东西解决什么问题?这个东西怎样解决问题? 还有没有其他方法? 三步走分析一下 DNS 解决什么问题 根据域名找到 IP。为啥要找到域名对应的 IP 呢?答案很简单,因为 TCP/IP 协议栈需要。 很常见的一个问题就是浏览器得到一个 web page 的流程是啥样的。

Read more →

April 23, 2020

algorithm-quick-sort

#algorithm#sort

quick sort C 代码 #include <stdio.h> int partition(int* array, int startIndex, int endIndex){ int left = startIndex; int right = endIndex; int pivot = array[startIndex]; int temp = 0; // 第一个 while 循环,其实就是从两个方向遍历一次数组,根据 pivot 进行分割。 while (left != right) { // 第二个 while 循环, 找一个 array[right] <= pivot,也就是找一个小于等于 pivot 的元素 while (left < right && array[right] > pivot) { right--; } // 第三个 while 循环, 找一个 array[left] > pivot,也就是找一个大于等于 pivot 的元素。 while (left < right && array[left] <= pivot) { left++; } // 交换找到的两个元素 if(left < right) { temp = array[left]; array[left] = array[right]; array[right] = temp; } } // pivot 归位, 左边都比 pivot 小, 右边都比 pivot 大 temp = array[left]; array[left] = pivot; array[startIndex] = temp; return left; } void quickSort(int* array, int startIndex, int endIndex){ // 只有一个元素,有序。直接返回 if(startIndex >= endIndex){ return; } // 一次 partition 有序一个元素。被 pivot 分割的两部分继续 quick sort int pivotIndex = partition(array, startIndex, endIndex); quickSort(array, startIndex, pivotIndex - 1); quickSort(array, pivotIndex + 1, endIndex); } int main(){ int array[8] = {4,7,6,5,3,2,8,1}; quickSort(array, 0, 7); for (int i = 0; i < 8; i++) { printf("%d ",array[i]); } return 0; } 汇编代码分析 quickSort: file format elf64-x86-64 Disassembly of section .init: 0000000000000548 <_init>: 548: 48 83 ec 08 sub $0x8,%rsp 54c: 48 8b 05 95 0a 20 00 mov 0x200a95(%rip),%rax # 200fe8 <__gmon_start__> 553: 48 85 c0 test %rax,%rax 556: 74 02 je 55a <_init+0x12> 558: ff d0 callq *%rax 55a: 48 83 c4 08 add $0x8,%rsp 55e: c3 retq Disassembly of section .plt: 0000000000000560 <.plt>: 560: ff 35 52 0a 20 00 pushq 0x200a52(%rip) # 200fb8 <_GLOBAL_OFFSET_TABLE_+0x8> 566: ff 25 54 0a 20 00 jmpq *0x200a54(%rip) # 200fc0 <_GLOBAL_OFFSET_TABLE_+0x10> 56c: 0f 1f 40 00 nopl 0x0(%rax) 0000000000000570 <__stack_chk_fail@plt>: 570: ff 25 52 0a 20 00 jmpq *0x200a52(%rip) # 200fc8 <__stack_chk_fail@GLIBC_2.4> 576: 68 00 00 00 00 pushq $0x0 57b: e9 e0 ff ff ff jmpq 560 <.plt> 0000000000000580 <printf@plt>: 580: ff 25 4a 0a 20 00 jmpq *0x200a4a(%rip) # 200fd0 <printf@GLIBC_2.2.5> 586: 68 01 00 00 00 pushq $0x1 58b: e9 d0 ff ff ff jmpq 560 <.plt> Disassembly of section .plt.got: 0000000000000590 <__cxa_finalize@plt>: 590: ff 25 62 0a 20 00 jmpq *0x200a62(%rip) # 200ff8 <__cxa_finalize@GLIBC_2.2.5> 596: 66 90 xchg %ax,%ax Disassembly of section .text: 00000000000005a0 <_start>: 5a0: 31 ed xor %ebp,%ebp ; ebp = 0 5a2: 49 89 d1 mov %rdx,%r9 ; r9 = rdx 5a5: 5e pop %rsi 5a6: 48 89 e2 mov %rsp,%rdx ; rdx = rsp 5a9: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp 5ad: 50 push %rax 5ae: 54 push %rsp 5af: 4c 8d 05 ca 03 00 00 lea 0x3ca(%rip),%r8 # 980 <__libc_csu_fini> 5b6: 48 8d 0d 53 03 00 00 lea 0x353(%rip),%rcx # 910 <__libc_csu_init> 5bd: 48 8d 3d 9c 02 00 00 lea 0x29c(%rip),%rdi # 860 <main> 5c4: ff 15 16 0a 20 00 callq *0x200a16(%rip) # 200fe0 <__libc_start_main@GLIBC_2.2.5> 5ca: f4 hlt 5cb: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) 00000000000005d0 <deregister_tm_clones>: 5d0: 48 8d 3d 39 0a 20 00 lea 0x200a39(%rip),%rdi # 201010 <__TMC_END__> 5d7: 55 push %rbp 5d8: 48 8d 05 31 0a 20 00 lea 0x200a31(%rip),%rax # 201010 <__TMC_END__> 5df: 48 39 f8 cmp %rdi,%rax 5e2: 48 89 e5 mov %rsp,%rbp 5e5: 74 19 je 600 <deregister_tm_clones+0x30> 5e7: 48 8b 05 ea 09 20 00 mov 0x2009ea(%rip),%rax # 200fd8 <_ITM_deregisterTMCloneTable> 5ee: 48 85 c0 test %rax,%rax 5f1: 74 0d je 600 <deregister_tm_clones+0x30> 5f3: 5d pop %rbp 5f4: ff e0 jmpq *%rax 5f6: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 5fd: 00 00 00 600: 5d pop %rbp 601: c3 retq 602: 0f 1f 40 00 nopl 0x0(%rax) 606: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 60d: 00 00 00 0000000000000610 <register_tm_clones>: 610: 48 8d 3d f9 09 20 00 lea 0x2009f9(%rip),%rdi # 201010 <__TMC_END__> 617: 48 8d 35 f2 09 20 00 lea 0x2009f2(%rip),%rsi # 201010 <__TMC_END__> 61e: 55 push %rbp 61f: 48 29 fe sub %rdi,%rsi 622: 48 89 e5 mov %rsp,%rbp 625: 48 c1 fe 03 sar $0x3,%rsi 629: 48 89 f0 mov %rsi,%rax 62c: 48 c1 e8 3f shr $0x3f,%rax 630: 48 01 c6 add %rax,%rsi 633: 48 d1 fe sar %rsi 636: 74 18 je 650 <register_tm_clones+0x40> 638: 48 8b 05 b1 09 20 00 mov 0x2009b1(%rip),%rax # 200ff0 <_ITM_registerTMCloneTable> 63f: 48 85 c0 test %rax,%rax 642: 74 0c je 650 <register_tm_clones+0x40> 644: 5d pop %rbp 645: ff e0 jmpq *%rax 647: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1) 64e: 00 00 650: 5d pop %rbp 651: c3 retq 652: 0f 1f 40 00 nopl 0x0(%rax) 656: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 65d: 00 00 00 0000000000000660 <__do_global_dtors_aux>: 660: 80 3d a9 09 20 00 00 cmpb $0x0,0x2009a9(%rip) # 201010 <__TMC_END__> 667: 75 2f jne 698 <__do_global_dtors_aux+0x38> 669: 48 83 3d 87 09 20 00 cmpq $0x0,0x200987(%rip) # 200ff8 <__cxa_finalize@GLIBC_2.2.5> 670: 00 671: 55 push %rbp 672: 48 89 e5 mov %rsp,%rbp 675: 74 0c je 683 <__do_global_dtors_aux+0x23> 677: 48 8b 3d 8a 09 20 00 mov 0x20098a(%rip),%rdi # 201008 <__dso_handle> 67e: e8 0d ff ff ff callq 590 <__cxa_finalize@plt> 683: e8 48 ff ff ff callq 5d0 <deregister_tm_clones> 688: c6 05 81 09 20 00 01 movb $0x1,0x200981(%rip) # 201010 <__TMC_END__> 68f: 5d pop %rbp 690: c3 retq 691: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) 698: f3 c3 repz retq 69a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1) 00000000000006a0 <frame_dummy>: 6a0: 55 push %rbp 6a1: 48 89 e5 mov %rsp,%rbp 6a4: 5d pop %rbp 6a5: e9 66 ff ff ff jmpq 610 <register_tm_clones> 00000000000006aa <partition>: 6aa: 55 push %rbp 6ab: 48 89 e5 mov %rsp,%rbp 6ae: 48 89 7d e8 mov %rdi,-0x18(%rbp) ; &array[0] 6b2: 89 75 e4 mov %esi,-0x1c(%rbp) ; startIndex 6b5: 89 55 e0 mov %edx,-0x20(%rbp) ; endIndex 6b8: 8b 45 e4 mov -0x1c(%rbp),%eax ; eax = startIndex 6bb: 89 45 f0 mov %eax,-0x10(%rbp) ; left = startIndex 6be: 8b 45 e0 mov -0x20(%rbp),%eax ; eax = endIndex 6c1: 89 45 f4 mov %eax,-0xc(%rbp) ; right = endIndex 6c4: 8b 45 e4 mov -0x1c(%rbp),%eax ; eax = startIndex 6c7: 48 98 cltq 6c9: 48 8d 14 85 00 00 00 lea 0x0(,%rax,4),%rdx ; rdx = 4 * startIndex 6d0: 00 6d1: 48 8b 45 e8 mov -0x18(%rbp),%rax ; rax = &array[0] 6d5: 48 01 d0 add %rdx,%rax ; rax = &array[0] + 4 * startIndex 6d8: 8b 00 mov (%rax),%eax ; eax = array[startIndex] 6da: 89 45 f8 mov %eax,-0x8(%rbp) ; pivot = array[startIndex] 6dd: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp) ; temp = 0; 6e4: e9 b7 00 00 00 jmpq 7a0 <partition+0xf6> ; 跳转到 while(left != right) 判断 left != right ; 第二个 while 循环的循环体 6e9: 83 6d f4 01 subl $0x1,-0xc(%rbp) ; right = right - 1 ; while(left != right) 的循环体 6ed: 8b 45 f0 mov -0x10(%rbp),%eax ; eax = left 6f0: 3b 45 f4 cmp -0xc(%rbp),%eax ; cmp right,left 6f3: 7d 21 jge 716 <partition+0x6c> ; left >= right,第二个 while 循环不满足,进入判断第三个 while 循环 6f5: 8b 45 f4 mov -0xc(%rbp),%eax ; eax = right 能执行到这,说明 left < right 6f8: 48 98 cltq ; convert eax to rax 6fa: 48 8d 14 85 00 00 00 lea 0x0(,%rax,4),%rdx; rdx = 4 * right 701: 00 702: 48 8b 45 e8 mov -0x18(%rbp),%rax ; rax = &array[0] 706: 48 01 d0 add %rdx,%rax ; rax = &array[0] + 4 * right 709: 8b 00 mov (%rax),%eax ; eax = array[right] 70b: 39 45 f8 cmp %eax,-0x8(%rbp) ; cmp array[right],pivot 70e: 7c d9 jl 6e9 <partition+0x3f> ; pivot < array[right] 执行跳转,执行循环体。 710: eb 04 jmp 716 <partition+0x6c> ; ; 第三个 while 循环的循环体 712: 83 45 f0 01 addl $0x1,-0x10(%rbp) ; left = left + 1 ; 第三个 while 循环 716: 8b 45 f0 mov -0x10(%rbp),%eax ; eax = left 719: 3b 45 f4 cmp -0xc(%rbp),%eax ; cmp,right,left 71c: 7d 1b jge 739 <partition+0x8f> ; left >= right,第三个 while 循环 条件 1 不满足,短路。进入 if 语句。 71e: 8b 45 f0 mov -0x10(%rbp),%eax ; eax = left 721: 48 98 cltq 723: 48 8d 14 85 00 00 00 lea 0x0(,%rax,4),%rdx ; rdx = 4 * left 72a: 00 72b: 48 8b 45 e8 mov -0x18(%rbp),%rax ; rax = &array[0] 72f: 48 01 d0 add %rdx,%rax ; rax = &array[0] + 4 * left 732: 8b 00 mov (%rax),%eax ; eax = array[left] 734: 39 45 f8 cmp %eax,-0x8(%rbp) ; cmp,array[left],pivot 737: 7d d9 jge 712 <partition+0x68> ; pivot >= array[left],第三个 while 循环 条件 2 满足。执行循环体。 ; if 代码块开始 739: 8b 45 f0 mov -0x10(%rbp),%eax ; eax = left 73c: 3b 45 f4 cmp -0xc(%rbp),%eax ; cmp right,left 73f: 7d 5f jge 7a0 <partition+0xf6> ; left >= right 进入下一轮循环 741: 8b 45 f0 mov -0x10(%rbp),%eax ; eax = left 744: 48 98 cltq 746: 48 8d 14 85 00 00 00 lea 0x0(,%rax,4),%rdx ; rdx = 4 * left 74d: 00 74e: 48 8b 45 e8 mov -0x18(%rbp),%rax ; rax = &array[0] 752: 48 01 d0 add %rdx,%rax ; rax = &array[0] + 4 * left 755: 8b 00 mov (%rax),%eax ; eax = array[left] 757: 89 45 fc mov %eax,-0x4(%rbp) ; temp = array[left] 75a: 8b 45 f4 mov -0xc(%rbp),%eax ; eax = right 75d: 48 98 cltq 75f: 48 8d 14 85 00 00 00 lea 0x0(,%rax,4),%rdx ; rdx = 4 * right 766: 00 767: 48 8b 45 e8 mov -0x18(%rbp),%rax ; rax = &array[0] 76b: 48 01 d0 add %rdx,%rax ; rax = &array[0] + 4 * right 76e: 8b 55 f0 mov -0x10(%rbp),%edx ; edx = left 771: 48 63 d2 movslq %edx,%rdx ; 774: 48 8d 0c 95 00 00 00 lea 0x0(,%rdx,4),%rcx ; rcx = 4 * left 77b: 00 77c: 48 8b 55 e8 mov -0x18(%rbp),%rdx ; rdx = &array[0] 780: 48 01 ca add %rcx,%rdx ; rdx = &array[0] + 4 * left 783: 8b 00 mov (%rax),%eax ; eax = array[right] 785: 89 02 mov %eax,(%rdx) ; array[left] = array[right] 787: 8b 45 f4 mov -0xc(%rbp),%eax ; eax = right 78a: 48 98 cltq 78c: 48 8d 14 85 00 00 00 lea 0x0(,%rax,4),%rdx ; rdx = 4 * right 793: 00 794: 48 8b 45 e8 mov -0x18(%rbp),%rax ; rax = &array[0] 798: 48 01 c2 add %rax,%rdx ; rdx = &array[0] + 4 * right 79b: 8b 45 fc mov -0x4(%rbp),%eax ; eax = temp; 79e: 89 02 mov %eax,(%rdx) ; array[right] = temp ; if 代码块结束 ; while(left != right) 进入循环的条件判断 7a0: 8b 45 f0 mov -0x10(%rbp),%eax ; eax = left 7a3: 3b 45 f4 cmp -0xc(%rbp),%eax ; cpm right, left 7a6: 0f 85 41 ff ff ff jne 6ed <partition+0x43> ; left != right 满足循环条件进入循环体 7ac: 8b 45 f0 mov -0x10(%rbp),%eax ; eax = left 不满足循环条件 left != right,此时循环结束。 ; pivot 归位 7af: 48 98 cltq 7b1: 48 8d 14 85 00 00 00 lea 0x0(,%rax,4),%rdx ; rdx = 4 * left 7b8: 00 7b9: 48 8b 45 e8 mov -0x18(%rbp),%rax ; rax = &array[0] 7bd: 48 01 d0 add %rdx,%rax ; rax = &array[0] + 4 * left 7c0: 8b 00 mov (%rax),%eax ; eax = array[left] 7c2: 89 45 fc mov %eax,-0x4(%rbp) ; temp = array[left] 7c5: 8b 45 f0 mov -0x10(%rbp),%eax ; eax = left 7c8: 48 98 cltq 7ca: 48 8d 14 85 00 00 00 lea 0x0(,%rax,4),%rdx ; rdx = 4 * left 7d1: 00 7d2: 48 8b 45 e8 mov -0x18(%rbp),%rax ; rax = &array[0] 7d6: 48 01 c2 add %rax,%rdx ; rdx = &array[0] + 4 * left 7d9: 8b 45 f8 mov -0x8(%rbp),%eax ; eax = pivot 7dc: 89 02 mov %eax,(%rdx) ; array[left] = pivot 7de: 8b 45 e4 mov -0x1c(%rbp),%eax ; eax = startIndex 7e1: 48 98 cltq 7e3: 48 8d 14 85 00 00 00 lea 0x0(,%rax,4),%rdx ; rdx = 4 * startIndex 7ea: 00 7eb: 48 8b 45 e8 mov -0x18(%rbp),%rax ; rax = &array[0] 7ef: 48 01 c2 add %rax,%rdx ; rdx = &array[0] + 4 * startIndex 7f2: 8b 45 fc mov -0x4(%rbp),%eax ; eax = temp 7f5: 89 02 mov %eax,(%rdx) ; array[startIndex] = temp 7f7: 8b 45 f0 mov -0x10(%rbp),%eax ; eax = left 返回值 7fa: 5d pop %rbp ; pop 调用者的 rbp 7fb: c3 retq ; 1. pop %rip 2.jmp %rip 00000000000007fc <quickSort>: 7fc: 55 push %rbp 7fd: 48 89 e5 mov %rsp,%rbp 800: 48 83 ec 20 sub $0x20,%rsp ;分配 32Bytes 空间 804: 48 89 7d e8 mov %rdi,-0x18(%rbp) ; &array[0] 808: 89 75 e4 mov %esi,-0x1c(%rbp) ; startIndex 80b: 89 55 e0 mov %edx,-0x20(%rbp) ; endIndex 80e: 8b 45 e4 mov -0x1c(%rbp),%eax ; eax = startIndex 811: 3b 45 e0 cmp -0x20(%rbp),%eax ; cmp endIndex,startIndex 814: 7d 47 jge 85d <quickSort+0x61> ; startIndex >= endIndex 不满足条件,销毁栈帧,结束调用。 816: 8b 55 e0 mov -0x20(%rbp),%edx ; edx = endIndex 第三个参数 能执行到这,说明 startIndex < endIndex 819: 8b 4d e4 mov -0x1c(%rbp),%ecx ; ecx = startIndex 81c: 48 8b 45 e8 mov -0x18(%rbp),%rax ; rax = &array[0] 820: 89 ce mov %ecx,%esi ; esi = startIndex 第二个参数 822: 48 89 c7 mov %rax,%rdi ; rdi = &array[0] 第一个参数 825: e8 80 fe ff ff callq 6aa <partition> 82a: 89 45 fc mov %eax,-0x4(%rbp) ; pivotIndex = eax partition 的返回值在 eax 里 82d: 8b 45 fc mov -0x4(%rbp),%eax ; eax = pivotIndex 830: 8d 50 ff lea -0x1(%rax),%edx ; edx = pivotIndex - 1 第三个参数 833: 8b 4d e4 mov -0x1c(%rbp),%ecx ; ecx = startIndex 836: 48 8b 45 e8 mov -0x18(%rbp),%rax ; rax = &array[0] 83a: 89 ce mov %ecx,%esi ; esi = startIndex 第二个参数 83c: 48 89 c7 mov %rax,%rdi ; rdi = &array[0] 第一个参数 83f: e8 b8 ff ff ff callq 7fc <quickSort> ; quickSort(array, startIndex, pivotIndex - 1) 844: 8b 45 fc mov -0x4(%rbp),%eax ; eax = pivotIndex 847: 8d 48 01 lea 0x1(%rax),%ecx ; ecx = pivotIndex + 1 84a: 8b 55 e0 mov -0x20(%rbp),%edx ; edx = endIndex 第三个参数 84d: 48 8b 45 e8 mov -0x18(%rbp),%rax ; rax = &array[0] 851: 89 ce mov %ecx,%esi ; esi = pivotIndex + 1 第二个参数 853: 48 89 c7 mov %rax,%rdi ; rdi = &array[0] 第一个参数 856: e8 a1 ff ff ff callq 7fc <quickSort> ; quickSort(array, pivotIndex + 1, endIndex) 85b: eb 01 jmp 85e <quickSort+0x62> 85d: 90 nop 85e: c9 leaveq 85f: c3 retq 0000000000000860 <main>: 860: 55 push %rbp 861: 48 89 e5 mov %rsp,%rbp 864: 48 83 ec 40 sub $0x40,%rsp ; 分配 64Bytes 空间。 868: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax 86f: 00 00 871: 48 89 45 f8 mov %rax,-0x8(%rbp) 875: 31 c0 xor %eax,%eax 877: c7 45 d0 04 00 00 00 movl $0x4,-0x30(%rbp) ; array[0] = 4 87e: c7 45 d4 07 00 00 00 movl $0x7,-0x2c(%rbp) ; array[1] = 7 885: c7 45 d8 06 00 00 00 movl $0x6,-0x28(%rbp) ; array[2] = 6 88c: c7 45 dc 05 00 00 00 movl $0x5,-0x24(%rbp) ; array[3] = 5 893: c7 45 e0 03 00 00 00 movl $0x3,-0x20(%rbp) ; array[4] = 3 89a: c7 45 e4 02 00 00 00 movl $0x2,-0x1c(%rbp) ; array[5] = 2 8a1: c7 45 e8 08 00 00 00 movl $0x8,-0x18(%rbp) ; array[6] = 8 8a8: c7 45 ec 01 00 00 00 movl $0x1,-0x14(%rbp) ; array[7] = 1 8af: 48 8d 45 d0 lea -0x30(%rbp),%rax ; rax = &array[0] 8b3: ba 07 00 00 00 mov $0x7,%edx ; edx = endIndex = 7 8b8: be 00 00 00 00 mov $0x0,%esi ; esi = startIndex = 0 8bd: 48 89 c7 mov %rax,%rdi ; rdi = rax = &array[0] 8c0: e8 37 ff ff ff callq 7fc <quickSort> 8c5: c7 45 cc 00 00 00 00 movl $0x0,-0x34(%rbp) ; i = 0 8cc: eb 20 jmp 8ee <main+0x8e> 8ce: 8b 45 cc mov -0x34(%rbp),%eax 8d1: 48 98 cltq 8d3: 8b 44 85 d0 mov -0x30(%rbp,%rax,4),%eax 8d7: 89 c6 mov %eax,%esi 8d9: 48 8d 3d b4 00 00 00 lea 0xb4(%rip),%rdi # 994 <_IO_stdin_used+0x4> 8e0: b8 00 00 00 00 mov $0x0,%eax 8e5: e8 96 fc ff ff callq 580 <printf@plt> 8ea: 83 45 cc 01 addl $0x1,-0x34(%rbp) 8ee: 83 7d cc 07 cmpl $0x7,-0x34(%rbp) 8f2: 7e da jle 8ce <main+0x6e> 8f4: b8 00 00 00 00 mov $0x0,%eax 8f9: 48 8b 4d f8 mov -0x8(%rbp),%rcx 8fd: 64 48 33 0c 25 28 00 xor %fs:0x28,%rcx 904: 00 00 906: 74 05 je 90d <main+0xad> 908: e8 63 fc ff ff callq 570 <__stack_chk_fail@plt> 90d: c9 leaveq 90e: c3 retq 90f: 90 nop 0000000000000910 <__libc_csu_init>: 910: 41 57 push %r15 912: 41 56 push %r14 914: 49 89 d7 mov %rdx,%r15 917: 41 55 push %r13 919: 41 54 push %r12 91b: 4c 8d 25 8e 04 20 00 lea 0x20048e(%rip),%r12 # 200db0 <__frame_dummy_init_array_entry> 922: 55 push %rbp 923: 48 8d 2d 8e 04 20 00 lea 0x20048e(%rip),%rbp # 200db8 <__init_array_end> 92a: 53 push %rbx 92b: 41 89 fd mov %edi,%r13d 92e: 49 89 f6 mov %rsi,%r14 931: 4c 29 e5 sub %r12,%rbp 934: 48 83 ec 08 sub $0x8,%rsp 938: 48 c1 fd 03 sar $0x3,%rbp 93c: e8 07 fc ff ff callq 548 <_init> 941: 48 85 ed test %rbp,%rbp 944: 74 20 je 966 <__libc_csu_init+0x56> 946: 31 db xor %ebx,%ebx 948: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1) 94f: 00 950: 4c 89 fa mov %r15,%rdx 953: 4c 89 f6 mov %r14,%rsi 956: 44 89 ef mov %r13d,%edi 959: 41 ff 14 dc callq *(%r12,%rbx,8) 95d: 48 83 c3 01 add $0x1,%rbx 961: 48 39 dd cmp %rbx,%rbp 964: 75 ea jne 950 <__libc_csu_init+0x40> 966: 48 83 c4 08 add $0x8,%rsp 96a: 5b pop %rbx 96b: 5d pop %rbp 96c: 41 5c pop %r12 96e: 41 5d pop %r13 970: 41 5e pop %r14 972: 41 5f pop %r15 974: c3 retq 975: 90 nop 976: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 97d: 00 00 00 0000000000000980 <__libc_csu_fini>: 980: f3 c3 repz retq Disassembly of section .fini: 0000000000000984 <_fini>: 984: 48 83 ec 08 sub $0x8,%rsp 988: 48 83 c4 08 add $0x8,%rsp 98c: c3 retq partition 分析 Before:: [4, 7, 6, 5, 3, 2, 8, 1] 第 1 次 partition [3, 1, 2, 4, 5, 6, 8, 7] returned index is: 3 第 2 次 partition [2, 1, 3, 4, 5, 6, 8, 7] returned index is: 2 第 3 次 partition [1, 2, 3, 4, 5, 6, 8, 7] returned index is: 1 第 4 次 partition [1, 2, 3, 4, 5, 6, 8, 7] returned index is: 4 第 5 次 partition [1, 2, 3, 4, 5, 6, 8, 7] returned index is: 5 第 6 次 partition [1, 2, 3, 4, 5, 6, 7, 8] returned index is: 7 After:: [1, 2, 3, 4, 5, 6, 7, 8] partition 逻辑图解

Read more →

April 14, 2020

algorithm-merge-sort

#algorithm#sort

merge sort merge sort C code #include <stdio.h> void merge(int* array, int start, int mid, int end){ // start = 0 // mid = 3 // end = 7 int tempArrayLength = end - start + 1; // 8 int tempArray[tempArrayLength]; // tempArray[8] int p1 = start; // 0 int p2 = mid + 1; // 4 int p = 0; // 比较两个小集合,依次放入大集合, 第一个 while 循环 while (p1 <= mid && p2 <= end){ p1 <=3 && p2 <=7 if(array[p1] <= array[p2]){ // 7 <= 5 XXX tempArray[p++] = array[p1++]; } else { tempArray[p++] = array[p2++]; // tempArray[0] = 5 } } // 左侧集合还有剩余,依次放入大集合, 第二个 while 循环 while (p1 <= mid){ // 2 <= 2 tempArray[p++] = array[p1++]; tempArray[1] = 7 } // 右侧集合还有剩余,依次放入大集合,第三个 while 循环 while (p2 <= end){ // 4 <= 3 XXX tempArray[p++] = array[p2++]; // tempArray[1] = 9 } // 大集合复制到原来的数组,for 循环 for (int i = 0; i < tempArrayLength; i++) { array[i + start] = tempArray[i]; // 3,9,5,7 } } void mergeSort(int* array, int start, int end){ if(start < end){ int mid = (start + end) / 2; mergeSort(array, start, mid); // mergeSort_L(array, start, mid); mergeSort(array, mid+1, end); // mergeSort_R(array, mid+1, end); merge(array, start, mid, end); } } int main(){ int array[8] = {9, 3, 7, 5, 8, 6, 4, 10}; mergeSort(array, 0 , 7); for (int i = 0; i < 8; i++) { printf("%d#",array[i]); } } x64 汇编代码分析 mergesort: file format elf64-x86-64 ; 64bits 汇编代码 Disassembly of section .init: 0000000000000548 <_init>: 548: 48 83 ec 08 sub $0x8,%rsp 54c: 48 8b 05 95 0a 20 00 mov 0x200a95(%rip),%rax # 200fe8 <__gmon_start__> 553: 48 85 c0 test %rax,%rax 556: 74 02 je 55a <_init+0x12> 558: ff d0 callq *%rax 55a: 48 83 c4 08 add $0x8,%rsp 55e: c3 retq Disassembly of section .plt: 0000000000000560 <.plt>: 560: ff 35 52 0a 20 00 pushq 0x200a52(%rip) # 200fb8 <_GLOBAL_OFFSET_TABLE_+0x8> 566: ff 25 54 0a 20 00 jmpq *0x200a54(%rip) # 200fc0 <_GLOBAL_OFFSET_TABLE_+0x10> 56c: 0f 1f 40 00 nopl 0x0(%rax) 0000000000000570 <__stack_chk_fail@plt>: 570: ff 25 52 0a 20 00 jmpq *0x200a52(%rip) # 200fc8 <__stack_chk_fail@GLIBC_2.4> 576: 68 00 00 00 00 pushq $0x0 57b: e9 e0 ff ff ff jmpq 560 <.plt> 0000000000000580 <printf@plt>: 580: ff 25 4a 0a 20 00 jmpq *0x200a4a(%rip) # 200fd0 <printf@GLIBC_2.2.5> 586: 68 01 00 00 00 pushq $0x1 58b: e9 d0 ff ff ff jmpq 560 <.plt> Disassembly of section .plt.got: 0000000000000590 <__cxa_finalize@plt>: 590: ff 25 62 0a 20 00 jmpq *0x200a62(%rip) # 200ff8 <__cxa_finalize@GLIBC_2.2.5> 596: 66 90 xchg %ax,%ax Disassembly of section .text: ; 代码区 00000000000005a0 <_start>: 5a0: 31 ed xor %ebp,%ebp ; ebp = 0 5a2: 49 89 d1 mov %rdx,%r9 5a5: 5e pop %rsi 5a6: 48 89 e2 mov %rsp,%rdx 5a9: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp 5ad: 50 push %rax 5ae: 54 push %rsp 5af: 4c 8d 05 aa 04 00 00 lea 0x4aa(%rip),%r8 # a60 <__libc_csu_fini> 5b6: 48 8d 0d 33 04 00 00 lea 0x433(%rip),%rcx # 9f0 <__libc_csu_init> 5bd: 48 8d 3d 79 03 00 00 lea 0x379(%rip),%rdi # 93d <main> 5c4: ff 15 16 0a 20 00 callq *0x200a16(%rip) # 200fe0 <__libc_start_main@GLIBC_2.2.5> 5ca: f4 hlt 5cb: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) 00000000000005d0 <deregister_tm_clones>: 5d0: 48 8d 3d 39 0a 20 00 lea 0x200a39(%rip),%rdi # 201010 <__TMC_END__> 5d7: 55 push %rbp 5d8: 48 8d 05 31 0a 20 00 lea 0x200a31(%rip),%rax # 201010 <__TMC_END__> 5df: 48 39 f8 cmp %rdi,%rax 5e2: 48 89 e5 mov %rsp,%rbp 5e5: 74 19 je 600 <deregister_tm_clones+0x30> 5e7: 48 8b 05 ea 09 20 00 mov 0x2009ea(%rip),%rax # 200fd8 <_ITM_deregisterTMCloneTable> 5ee: 48 85 c0 test %rax,%rax 5f1: 74 0d je 600 <deregister_tm_clones+0x30> 5f3: 5d pop %rbp 5f4: ff e0 jmpq *%rax 5f6: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 5fd: 00 00 00 600: 5d pop %rbp 601: c3 retq 602: 0f 1f 40 00 nopl 0x0(%rax) 606: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 60d: 00 00 00 0000000000000610 <register_tm_clones>: 610: 48 8d 3d f9 09 20 00 lea 0x2009f9(%rip),%rdi # 201010 <__TMC_END__> 617: 48 8d 35 f2 09 20 00 lea 0x2009f2(%rip),%rsi # 201010 <__TMC_END__> 61e: 55 push %rbp 61f: 48 29 fe sub %rdi,%rsi 622: 48 89 e5 mov %rsp,%rbp 625: 48 c1 fe 03 sar $0x3,%rsi 629: 48 89 f0 mov %rsi,%rax 62c: 48 c1 e8 3f shr $0x3f,%rax 630: 48 01 c6 add %rax,%rsi 633: 48 d1 fe sar %rsi 636: 74 18 je 650 <register_tm_clones+0x40> 638: 48 8b 05 b1 09 20 00 mov 0x2009b1(%rip),%rax # 200ff0 <_ITM_registerTMCloneTable> 63f: 48 85 c0 test %rax,%rax 642: 74 0c je 650 <register_tm_clones+0x40> 644: 5d pop %rbp 645: ff e0 jmpq *%rax 647: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1) 64e: 00 00 650: 5d pop %rbp 651: c3 retq 652: 0f 1f 40 00 nopl 0x0(%rax) 656: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 65d: 00 00 00 0000000000000660 <__do_global_dtors_aux>: 660: 80 3d a9 09 20 00 00 cmpb $0x0,0x2009a9(%rip) # 201010 <__TMC_END__> 667: 75 2f jne 698 <__do_global_dtors_aux+0x38> 669: 48 83 3d 87 09 20 00 cmpq $0x0,0x200987(%rip) # 200ff8 <__cxa_finalize@GLIBC_2.2.5> 670: 00 671: 55 push %rbp 672: 48 89 e5 mov %rsp,%rbp 675: 74 0c je 683 <__do_global_dtors_aux+0x23> 677: 48 8b 3d 8a 09 20 00 mov 0x20098a(%rip),%rdi # 201008 <__dso_handle> 67e: e8 0d ff ff ff callq 590 <__cxa_finalize@plt> 683: e8 48 ff ff ff callq 5d0 <deregister_tm_clones> 688: c6 05 81 09 20 00 01 movb $0x1,0x200981(%rip) # 201010 <__TMC_END__> 68f: 5d pop %rbp 690: c3 retq 691: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) 698: f3 c3 repz retq 69a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1) 00000000000006a0 <frame_dummy>: 6a0: 55 push %rbp 6a1: 48 89 e5 mov %rsp,%rbp 6a4: 5d pop %rbp 6a5: e9 66 ff ff ff jmpq 610 <register_tm_clones> 00000000000006aa <merge>: 6aa: 55 push %rbp 6ab: 48 89 e5 mov %rsp,%rbp ; rbp = rsp 6ae: 48 83 ec 50 sub $0x50,%rsp ; rsp = rsp - 0x50 开辟栈帧 6b2: 48 89 7d c8 mov %rdi,-0x38(%rbp) ; 第一个参数 &array[0] 6b6: 89 75 c4 mov %esi,-0x3c(%rbp) ; 第二个参数 start 6b9: 89 55 c0 mov %edx,-0x40(%rbp) ; 第三个参数 mid 6bc: 89 4d bc mov %ecx,-0x44(%rbp) ; 第四个参数 end 6bf: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax ; 哨兵值判定栈帧是否出了问题。 6c6: 00 00 6c8: 48 89 45 f8 mov %rax,-0x8(%rbp) ; 哨兵值 6cc: 31 c0 xor %eax,%eax ; eax = 0 6ce: 48 89 e0 mov %rsp,%rax ; rax = rsp 6d1: 48 89 c6 mov %rax,%rsi ; rsi = rax = rsp 记录这个 rsp 的值 6d4: 8b 45 bc mov -0x44(%rbp),%eax ; eax = end 6d7: 2b 45 c4 sub -0x3c(%rbp),%eax ; eax = end - start 6da: 83 c0 01 add $0x1,%eax ; tempArrayLength = eax = (end - start) + 1 6dd: 89 45 e4 mov %eax,-0x1c(%rbp) ; tempArrayLength = (end - start) + 1 复制到 rbp - 0x1c 内存处 6e0: 8b 45 e4 mov -0x1c(%rbp),%eax ; eax = tempArrayLength 6e3: 48 63 d0 movslq %eax,%rdx ; rdx = tempArrayLength, cltq 32bit 扩展为 64bit 6e6: 48 83 ea 01 sub $0x1,%rdx ; rdx = (tempArrayLength) - 1 = end - start 6ea: 48 89 55 e8 mov %rdx,-0x18(%rbp) ; end - start 复制到 rbp - 0x18 内存地址处 6ee: 48 63 d0 movslq %eax,%rdx ; rdx = (end - start) + 1 ? tempArrayLength 6f1: 49 89 d2 mov %rdx,%r10 ; r10 = (end - start) + 1 6f4: 41 bb 00 00 00 00 mov $0x0,%r11d ; r11d = 0 6fa: 48 63 d0 movslq %eax,%rdx ; rdx = (end - start) + 1 ? tempArrayLength 6fd: 49 89 d0 mov %rdx,%r8 ; r8 = (end - start) + 1 ? tempArrayLength 700: 41 b9 00 00 00 00 mov $0x0,%r9d ; r9d = 0 706: 48 98 cltq ; 相当于 movslq %eax,%rax. 708: 48 c1 e0 02 shl $0x2,%rax ; rax = ((end - start) + 1) * 4 70c: 48 8d 50 03 lea 0x3(%rax),%rdx ; rdx = 4 * ((end - start) + 1) + 3 710: b8 10 00 00 00 mov $0x10,%eax ; eax = 16 715: 48 83 e8 01 sub $0x1,%rax ; rax = 16 - 1 = 15 719: 48 01 d0 add %rdx,%rax ; rax = rax + rdx = 15 + 4 * ((end - start) + 1) + 3 = 4 * (end - start) + 22 71c: bf 10 00 00 00 mov $0x10,%edi ; edi = 16 721: ba 00 00 00 00 mov $0x0,%edx ; edx = 0 726: 48 f7 f7 div %rdi ; (rdx(high-32bit):rax(low-32bit))/rdi , quotient(商) in %rax, remainder(余数) in %rdx 729: 48 6b c0 10 imul $0x10,%rax,%rax ; rax = rax * 16 72d: 48 29 c4 sub %rax,%rsp ; rsp = rsp - rax 分配空间 730: 48 89 e0 mov %rsp,%rax ; rax = rsp 733: 48 83 c0 03 add $0x3,%rax ; rax = rsp + 3 737: 48 c1 e8 02 shr $0x2,%rax ; rax = (rsp + 3) >> 2 73b: 48 c1 e0 02 shl $0x2,%rax ; rax = ((rsp + 3) >> 2) <<2 73f: 48 89 45 f0 mov %rax,-0x10(%rbp) ; 743: 8b 45 c4 mov -0x3c(%rbp),%eax ; eax = start 746: 89 45 dc mov %eax,-0x24(%rbp) ; start 复制到 rbp - 0x24(p1) 处 749: 8b 45 c0 mov -0x40(%rbp),%eax ; eax = mid 74c: 83 c0 01 add $0x1,%eax ; eax = mid + 1 74f: 89 45 d8 mov %eax,-0x28(%rbp) ; mid + 1 复制到 rbp - 0x28(p2) 处 752: c7 45 d4 00 00 00 00 movl $0x0,-0x2c(%rbp) ; 0 复制到 rbp - 0x2c(p) 处 759: e9 90 00 00 00 jmpq 7ee <merge+0x144> ; 无条件跳转, 0x144 表示要跳转出也就是 7ee 距离 merge(6aa) 之间的所有指令字节数是 0x144。。。。。。 ; if(array[p1] <= array[p2]) 的判定 75e: 8b 45 dc mov -0x24(%rbp),%eax ; rax = p1 761: 48 98 cltq 763: 48 8d 14 85 00 00 00 lea 0x0(,%rax,4),%rdx ; rdx = 4 * p1 + 0 76a: 00 76b: 48 8b 45 c8 mov -0x38(%rbp),%rax ; rax = &array[0] 76f: 48 01 d0 add %rdx,%rax ; rax = &array[0] + 4 * p1 = &array[p1] 772: 8b 10 mov (%rax),%edx ; edx = array[p1] 774: 8b 45 d8 mov -0x28(%rbp),%eax ; eax = p2 777: 48 98 cltq 779: 48 8d 0c 85 00 00 00 lea 0x0(,%rax,4),%rcx ; rcx = 4 * rax = 4 * p2 780: 00 781: 48 8b 45 c8 mov -0x38(%rbp),%rax ; rax = &array[0] 785: 48 01 c8 add %rcx,%rax ; rax = &array[0] + 4 * p2 = &array[p2] 788: 8b 00 mov (%rax),%eax ; eax = array[p2] 78a: 39 c2 cmp %eax,%edx ; cmp array[p2],array[p1] 78c: 7f 31 jg 7bf <merge+0x115> ; array[p1] > array[p2] 跳到 else 78e: 8b 45 dc mov -0x24(%rbp),%eax ; eax = p1 791: 8d 50 01 lea 0x1(%rax),%edx ; edx = p1 + 1 794: 89 55 dc mov %edx,-0x24(%rbp) ; p1 = p1 + 1 797: 48 98 cltq 799: 48 8d 14 85 00 00 00 lea 0x0(,%rax,4),%rdx ; rdx = 4 * p1 7a0: 00 7a1: 48 8b 45 c8 mov -0x38(%rbp),%rax ; rax = &array[0] 7a5: 48 8d 0c 02 lea (%rdx,%rax,1),%rcx ; rcx = &array[0] + 4 * p1 = &array[p1] 7a9: 8b 45 d4 mov -0x2c(%rbp),%eax ; eax = p 7ac: 8d 50 01 lea 0x1(%rax),%edx ; edx = p + 1 7af: 89 55 d4 mov %edx,-0x2c(%rbp) ; p = p + 1 7b2: 8b 09 mov (%rcx),%ecx ; ecx = array[p1] 7b4: 48 8b 55 f0 mov -0x10(%rbp),%rdx ;rdx = &tempArray[0] 7b8: 48 98 cltq 7ba: 89 0c 82 mov %ecx,(%rdx,%rax,4) ; tempArray[p] = array[p1] 7bd: eb 2f jmp 7ee <merge+0x144> ; 开启下一轮判定>>>>>>> 7bf: 8b 45 d8 mov -0x28(%rbp),%eax ; eax = p2 $$$ begin else array[p1] > array[p2] 7c2: 8d 50 01 lea 0x1(%rax),%edx ; edx = p2 + 1 7c5: 89 55 d8 mov %edx,-0x28(%rbp) ; p2 = p2 + 1 7c8: 48 98 cltq 7ca: 48 8d 14 85 00 00 00 lea 0x0(,%rax,4),%rdx ; rdx = 4 * p2 7d1: 00 7d2: 48 8b 45 c8 mov -0x38(%rbp),%rax ; rax = &array[0] 7d6: 48 8d 0c 02 lea (%rdx,%rax,1),%rcx ; rcx = rdx + 1 * rax = &array[0] + 4 * p2 = &array[p2] 7da: 8b 45 d4 mov -0x2c(%rbp),%eax ; eax = p 7dd: 8d 50 01 lea 0x1(%rax),%edx ; edx = p + 1 7e0: 89 55 d4 mov %edx,-0x2c(%rbp) ; p = p + 1 7e3: 8b 09 mov (%rcx),%ecx ; ecx = array[p2] 7e5: 48 8b 55 f0 mov -0x10(%rbp),%rdx ; rdx = &tempArray[0] , 临时数组地址 7e9: 48 98 cltq 7eb: 89 0c 82 mov %ecx,(%rdx,%rax,4) ; tempArray[p] = array[p2] $$$$$ end else 7ee: 8b 45 dc mov -0x24(%rbp),%eax ; eax = p1 下一轮判定>>>>>>> 7f1: 3b 45 c0 cmp -0x40(%rbp),%eax ; cmp mid,p1 7f4: 7f 3d jg 833 <merge+0x189> ; p1 > mid 跳出去 7f6: 8b 45 d8 mov -0x28(%rbp),%eax ; eax = p2 此时 p1 <= mid, 判定 p2 <= end 吗? 7f9: 3b 45 bc cmp -0x44(%rbp),%eax ; cmp end,p2 7fc: 0f 8e 5c ff ff ff jle 75e <merge+0xb4> ; 此时 p1 <= mid,p2 <= end,进入 if。 802: eb 2f jmp 833 <merge+0x189>; 不满足第一个 while 循环,进入第二个 while 循环 ; p1 <= mid 循环体开始 804: 8b 45 dc mov -0x24(%rbp),%eax ; eax = p1 807: 8d 50 01 lea 0x1(%rax),%edx ; edx = p1 + 1 80a: 89 55 dc mov %edx,-0x24(%rbp) ; p1 = p1 + 1 #### 80d: 48 98 cltq ; movslq %eax,%rax 80f: 48 8d 14 85 00 00 00 lea 0x0(,%rax,4),%rdx ; rdx = 4 * p1 816: 00 817: 48 8b 45 c8 mov -0x38(%rbp),%rax ; rax = &array[0] 81b: 48 8d 0c 02 lea (%rdx,%rax,1),%rcx ; rcx = &array[p1] 81f: 8b 45 d4 mov -0x2c(%rbp),%eax ; eax = p 822: 8d 50 01 lea 0x1(%rax),%edx ; edx = p + 1 825: 89 55 d4 mov %edx,-0x2c(%rbp) ; p = p + 1 828: 8b 09 mov (%rcx),%ecx ; ecx = array[p1] 82a: 48 8b 55 f0 mov -0x10(%rbp),%rdx ; rdx = &tempArray[0] 82e: 48 98 cltq 830: 89 0c 82 mov %ecx,(%rdx,%rax,4) ; tempArray[p] = array[p1] ; 第二个 while 循环 也就是 while(p1 <= mid) 833: 8b 45 dc mov -0x24(%rbp),%eax ; eax = p1 836: 3b 45 c0 cmp -0x40(%rbp),%eax ; cmp mid, p1 判定 p1 <= mid 吗? 839: 7e c9 jle 804 <merge+0x15a> ; p1 <= mid ; p1 <= mid 循环体结束 83b: eb 2f jmp 86c <merge+0x1c2> ; 第二个 while 循环的 p1 <= mid不满足, 短路。直接进入第三个while(p2 <= end) ; p2 <= end 的循环体开始 83d: 8b 45 d8 mov -0x28(%rbp),%eax ; eax = p2 840: 8d 50 01 lea 0x1(%rax),%edx ; edx = p2 + 1 843: 89 55 d8 mov %edx,-0x28(%rbp) ; p = p2 + 1 846: 48 98 cltq 848: 48 8d 14 85 00 00 00 lea 0x0(,%rax,4),%rdx ; rdx = 4 * p2 84f: 00 850: 48 8b 45 c8 mov -0x38(%rbp),%rax ; rax = &array[0] 854: 48 8d 0c 02 lea (%rdx,%rax,1),%rcx ; rcx = &array[0] + 4 * p2 = &array[p2] 858: 8b 45 d4 mov -0x2c(%rbp),%eax ; eax = p 85b: 8d 50 01 lea 0x1(%rax),%edx ; eax = p + 1 85e: 89 55 d4 mov %edx,-0x2c(%rbp) ; p = p + 1 861: 8b 09 mov (%rcx),%ecx ; ecx = array[p2] 863: 48 8b 55 f0 mov -0x10(%rbp),%rdx ;rdx = &tempArray[0] 867: 48 98 cltq 869: 89 0c 82 mov %ecx,(%rdx,%rax,4) ; tempArray[p] = array[p2] ; 第三个 while 循环 86c: 8b 45 d8 mov -0x28(%rbp),%eax ; eax = p2 开始判定 p2 <= end 吗? 86f: 3b 45 bc cmp -0x44(%rbp),%eax ; cmp end, p2 872: 7e c9 jle 83d <merge+0x193> ; 满足 p2 <= end,第三个 while 循环 ; p2 > end 874: c7 45 e0 00 00 00 00 movl $0x0,-0x20(%rbp) ; 此时 p2 > end 了。i = 0 87b: eb 2d jmp 8aa <merge+0x200> ; 直接跳到 for 循环 ; for(int i = 0; i < tempArrayLength; i++) 开始 87d: 8b 55 e0 mov -0x20(%rbp),%edx ; edx = i 880: 8b 45 c4 mov -0x3c(%rbp),%eax ; eax = start 883: 01 d0 add %edx,%eax ; eax = start + i 885: 48 98 cltq 887: 48 8d 14 85 00 00 00 lea 0x0(,%rax,4),%rdx ; rdx = 4 * (start + i) 88e: 00 88f: 48 8b 45 c8 mov -0x38(%rbp),%rax ; rax = &array[0] 893: 48 8d 0c 02 lea (%rdx,%rax,1),%rcx ; rcx = array[start + i] 897: 48 8b 45 f0 mov -0x10(%rbp),%rax ; rax = &tempArray[0] 89b: 8b 55 e0 mov -0x20(%rbp),%edx ; edx = i 89e: 48 63 d2 movslq %edx,%rdx 8a1: 8b 04 90 mov (%rax,%rdx,4),%eax ; eax = tempArray[i] 8a4: 89 01 mov %eax,(%rcx) ; array[start + i] = tempArray[i]; 8a6: 83 45 e0 01 addl $0x1,-0x20(%rbp) ; i = i + 1 ; 判定 i < tempArrayLength 吗? 8aa: 8b 45 e0 mov -0x20(%rbp),%eax ; eax = i 8ad: 3b 45 e4 cmp -0x1c(%rbp),%eax ; cmp tempArrayLength, i 8b0: 7c cb jl 87d <merge+0x1d3> ; i < tempArrayLength ; for(int i = 0; i < tempArrayLength; i++) 结束 ; 此时 i >= tempArrayLength 了。 8b2: 48 89 f4 mov %rsi,%rsp ; rsp = rsi(记录的 rsp 的值) i >= tempArrayLength 8b5: 90 nop 8b6: 48 8b 45 f8 mov -0x8(%rbp),%rax ; rax = %fs:0x28 8ba: 64 48 33 04 25 28 00 xor %fs:0x28,%rax ;The OF and CF flags are cleared; the SF, ZF, and PF flags are set according to the result. The state of the AF flag is undefined. 8c1: 00 00 8c3: 74 05 je 8ca <merge+0x220> ; ZF = 0 说明栈帧没出问题,退出函数。 8c5: e8 a6 fc ff ff callq 570 <__stack_chk_fail@plt> ; 能执行到这说明栈帧出问题了。。。 8ca: c9 leaveq 8cb: c3 retq 00000000000008cc <mergeSort>: 8cc: 55 push %rbp 8cd: 48 89 e5 mov %rsp,%rbp ; rbp = rsp 8d0: 48 83 ec 20 sub $0x20,%rsp ; rsp = rsp - 0x20 8d4: 48 89 7d e8 mov %rdi,-0x18(%rbp) ;&array[0] 复制到 rbp - 0x18 地址处 8d8: 89 75 e4 mov %esi,-0x1c(%rbp) ;第二个参数 (start) 复制到 rbp -0x1c 地址处 8db: 89 55 e0 mov %edx,-0x20(%rbp) ;第三个参数 (end) 复制到 rbp -0x20 地址处 8de: 8b 45 e4 mov -0x1c(%rbp),%eax ;eax = start 8e1: 3b 45 e0 cmp -0x20(%rbp),%eax ;cmp end,start 8e4: 7d 54 jge 93a <mergeSort+0x6e> ; start >= end,直接退出函数。 8e6: 8b 55 e4 mov -0x1c(%rbp),%edx ; edx = start 此时 start < end 8e9: 8b 45 e0 mov -0x20(%rbp),%eax ; eax = end 8ec: 01 d0 add %edx,%eax ; eax = start + end 8ee: 89 c2 mov %eax,%edx ; edx = start + end 8f0: c1 ea 1f shr $0x1f,%edx ; edx = edx >> 31 (start + end)/pow(2,31) 相当于是 0 了😂 8f3: 01 d0 add %edx,%eax ; eax = (start + end) + 0 8f5: d1 f8 sar %eax ; eax = (start + end) / 2 算术右移一位,最高位补上 eax 的符号位 8f7: 89 45 fc mov %eax,-0x4(%rbp) ; mid = (start + end) / 2 复制到 rbp - 0x4 内存地址处 8fa: 8b 55 fc mov -0x4(%rbp),%edx ; edx = mid(start + end) / 2 也就是准备第三个参数 mid 8fd: 8b 4d e4 mov -0x1c(%rbp),%ecx ; ecx = start 900: 48 8b 45 e8 mov -0x18(%rbp),%rax ; rax = &array[0] 904: 89 ce mov %ecx,%esi ; esi = start ; 第二个参数 906: 48 89 c7 mov %rax,%rdi ; rdi = &array[0] ; 第一个参数 909: e8 be ff ff ff callq 8cc <mergeSort> ; 调用 mergeSort 左侧 mergeSort 90e: 8b 45 fc mov -0x4(%rbp),%eax ; eax = mid = (start + end) / 2 911: 8d 48 01 lea 0x1(%rax),%ecx ; mid = mid + 1 914: 8b 55 e0 mov -0x20(%rbp),%edx ; edx = end 第三个参数 917: 48 8b 45 e8 mov -0x18(%rbp),%rax ; rax = &array[0] 91b: 89 ce mov %ecx,%esi ; esi = mid 第二个参数 91d: 48 89 c7 mov %rax,%rdi ; rdi = &array[0] 第一个参数 920: e8 a7 ff ff ff callq 8cc <mergeSort> ; 调用 mergeSort 右侧 mergeSort 925: 8b 4d e0 mov -0x20(%rbp),%ecx ; ecx = end ; 第四个参数 928: 8b 55 fc mov -0x4(%rbp),%edx ; edx = mid = (start + end) / 2 第三个参数 92b: 8b 75 e4 mov -0x1c(%rbp),%esi ; esi = start ; 第二个参数 92e: 48 8b 45 e8 mov -0x18(%rbp),%rax ; rax = &array[0] 932: 48 89 c7 mov %rax,%rdi ; rdi = rax ; 第一个参数 935: e8 70 fd ff ff callq 6aa <merge> ; 调用 merge 开始 merge 93a: 90 nop ; 从此处销毁栈帧 93b: c9 leaveq // 销毁栈帧,相当于 rsp = rbp,pop rbp 93c: c3 retq 000000000000093d <main>: 93d: 55 push %rbp 93e: 48 89 e5 mov %rsp,%rbp 941: 48 83 ec 40 sub $0x40,%rsp 945: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax 94c: 00 00 94e: 48 89 45 f8 mov %rax,-0x8(%rbp) 952: 31 c0 xor %eax,%eax 954: c7 45 d0 09 00 00 00 movl $0x9,-0x30(%rbp) ; 0x9 复制到 rbp - 0x30 地址处。array[0] = 0x9 95b: c7 45 d4 03 00 00 00 movl $0x3,-0x2c(%rbp) ; 0x3 复制到 rbp - 0x2c 地址处。array[1] = 0x3 962: c7 45 d8 07 00 00 00 movl $0x7,-0x28(%rbp) ; 0x7 复制到 rbp - 0x28 地址处。array[2] = 0x7 969: c7 45 dc 05 00 00 00 movl $0x5,-0x24(%rbp) ; 0x5 复制到 rbp - 0x24 地址处。array[3] = 0x5 970: c7 45 e0 08 00 00 00 movl $0x8,-0x20(%rbp) ; 0x8 复制到 rbp - 0x20 地址处。array[4] = 0x8 977: c7 45 e4 06 00 00 00 movl $0x6,-0x1c(%rbp) ; 0x6 复制到 rbp - 0x1c 地址处。array[5] = 0x6 97e: c7 45 e8 04 00 00 00 movl $0x4,-0x18(%rbp) ; 0x4 复制到 rbp - 0x28 地址处。array[6] = 0x4 985: c7 45 ec 0a 00 00 00 movl $0xa,-0x14(%rbp) ; 0xa 复制到 rbp - 0x14 地址处。array[7] = 0xa 98c: 48 8d 45 d0 lea -0x30(%rbp),%rax ; rax = &array[0] 990: ba 07 00 00 00 mov $0x7,%edx ; 第三个参数 7 995: be 00 00 00 00 mov $0x0,%esi ; 第二个参数 0 99a: 48 89 c7 mov %rax,%rdi ; 第一个参数 &array[0] 99d: e8 2a ff ff ff callq 8cc <mergeSort> ; 调用 mergeSort,地址偏移是 0x8cc 9a2: c7 45 cc 00 00 00 00 movl $0x0,-0x34(%rbp) 9a9: eb 20 jmp 9cb <main+0x8e> 9ab: 8b 45 cc mov -0x34(%rbp),%eax 9ae: 48 98 cltq 9b0: 8b 44 85 d0 mov -0x30(%rbp,%rax,4),%eax 9b4: 89 c6 mov %eax,%esi 9b6: 48 8d 3d b7 00 00 00 lea 0xb7(%rip),%rdi # a74 <_IO_stdin_used+0x4> 9bd: b8 00 00 00 00 mov $0x0,%eax 9c2: e8 b9 fb ff ff callq 580 <printf@plt> 9c7: 83 45 cc 01 addl $0x1,-0x34(%rbp) 9cb: 83 7d cc 07 cmpl $0x7,-0x34(%rbp) 9cf: 7e da jle 9ab <main+0x6e> 9d1: b8 00 00 00 00 mov $0x0,%eax 9d6: 48 8b 4d f8 mov -0x8(%rbp),%rcx 9da: 64 48 33 0c 25 28 00 xor %fs:0x28,%rcx 9e1: 00 00 9e3: 74 05 je 9ea <main+0xad> 9e5: e8 86 fb ff ff callq 570 <__stack_chk_fail@plt> 9ea: c9 leaveq 9eb: c3 retq 9ec: 0f 1f 40 00 nopl 0x0(%rax) 00000000000009f0 <__libc_csu_init>: 9f0: 41 57 push %r15 9f2: 41 56 push %r14 9f4: 49 89 d7 mov %rdx,%r15 9f7: 41 55 push %r13 9f9: 41 54 push %r12 9fb: 4c 8d 25 ae 03 20 00 lea 0x2003ae(%rip),%r12 # 200db0 <__frame_dummy_init_array_entry> a02: 55 push %rbp a03: 48 8d 2d ae 03 20 00 lea 0x2003ae(%rip),%rbp # 200db8 <__init_array_end> a0a: 53 push %rbx a0b: 41 89 fd mov %edi,%r13d a0e: 49 89 f6 mov %rsi,%r14 a11: 4c 29 e5 sub %r12,%rbp a14: 48 83 ec 08 sub $0x8,%rsp a18: 48 c1 fd 03 sar $0x3,%rbp a1c: e8 27 fb ff ff callq 548 <_init> a21: 48 85 ed test %rbp,%rbp a24: 74 20 je a46 <__libc_csu_init+0x56> a26: 31 db xor %ebx,%ebx a28: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1) a2f: 00 a30: 4c 89 fa mov %r15,%rdx a33: 4c 89 f6 mov %r14,%rsi a36: 44 89 ef mov %r13d,%edi a39: 41 ff 14 dc callq *(%r12,%rbx,8) a3d: 48 83 c3 01 add $0x1,%rbx a41: 48 39 dd cmp %rbx,%rbp a44: 75 ea jne a30 <__libc_csu_init+0x40> a46: 48 83 c4 08 add $0x8,%rsp a4a: 5b pop %rbx a4b: 5d pop %rbp a4c: 41 5c pop %r12 a4e: 41 5d pop %r13 a50: 41 5e pop %r14 a52: 41 5f pop %r15 a54: c3 retq a55: 90 nop a56: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) a5d: 00 00 00 0000000000000a60 <__libc_csu_fini>: a60: f3 c3 repz retq Disassembly of section .fini: 0000000000000a64 <_fini>: a64: 48 83 ec 08 sub $0x8,%rsp a68: 48 83 c4 08 add $0x8,%rsp a6c: c3 retq 栈帧调用图解分析

Read more →

April 10, 2020

three-easy-pieces-4-process

#os#three easy pieces

我们知道一个计算机 CPU 数量有限, 但是却可以同时跑数量远远多于 CPU 数量的程序. 其实这就是 virtualizing. 怎样进行 CPU 虚拟化呢? 通过抽象出 process 这个基本概念, 也就是 running program. 一个没有运行的程序, 也就是磁盘上的一堆指令集和一些数据. 通过 time sharing 让一个 process stop, 然后去 run 另外一个 process. 重复这个 context switch 过程, 可以让多个程序同时运行, 这就是在virtualizing CPU. mechanisms are low-level methods or protocols that implements a needed piece of functionality. 类似于 java 中的接口, 就是我要提供什么功能. 比如 OS 中的进程的 context switch这个机制. policies are algorithms for making some kind of decision within the OS.类似 java 中实现类, 怎么实现这个接口定义的方法. 比如 OS 中的进程调度策略就是为了实现进程 context switch. mechanisms 和 policies 分离, 和 java 中接口和实现非常相似. 实际上这也是软件设计的原则. OS 本身也是软件.

Read more →

January 14, 2020

master-git

#git

git init Create an empty Git repository or reinitialize an existing one 也即是向 working directory 里添加 .git 文件夹 .git/ ├── branches # git 分支 ├── config # git 配置 ├── description ├── HEAD # HEAD 指针, 指向当前分支最新的 commit ├── hooks │ ├── applypatch-msg.sample │ ├── commit-msg.sample │ ├── fsmonitor-watchman.sample │ ├── post-update.sample │ ├── pre-applypatch.sample │ ├── pre-commit.sample │ ├── prepare-commit-msg.sample │ ├── pre-push.sample │ ├── pre-rebase.sample │ ├── pre-receive.sample │ └── update.sample ├── info │ └── exclude ├── objects # 存放不同种类的 git 对象,实现版本管理的关键 │ ├── info │ └── pack └── refs ├── heads └── tags # git 标签 第一次 git add | git commit git add Add file contents to the index 添加文件内容到 index 区

Read more →

December 28, 2019

katacoda-what-is-a-container

#docker

Processes Containers are just normal Linux Processes with additional configuration applied. 容器只是应用了附加配置的普通 Linux 进程。 redis container lanch redis-server process Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG…] docker run –help -d, –detach Run container in background and print container ID –name string Assign a name to the container

Read more →

December 24, 2019

tomcat-http-cookie

#tomcat#http

package javax.servlet.http; import java.io.Serializable; import java.security.AccessController; import java.security.PrivilegedAction; import java.text.MessageFormat; import java.util.BitSet; import java.util.Locale; import java.util.ResourceBundle; /** * Creates a cookie, a small amount of information sent by a servlet to a Web * browser, saved by the browser, and later sent back to the server. * 创建一个 cookie, servlet 发给浏览器的一个小信息,被浏览器保存。之后再发送给服务器。 * * A cookie's value can uniquely identify a client, so cookies are commonly used for * session management. * 一个 cookie 的值可以单独的标记出一个客户端,所以 cookies 一般被用来 session 管理。因为 * http 是一个 stateless 的协议。 * * <p> * A cookie has a name, a single value, and optional attributes such as a * comment, path and domain qualifiers, a maximum age, and a version number. * 一个 cookie 有一个 name,一个单独的 value,还有一些可选的属性,比如 注释,路径,域标记 * 最大存活时间和一个版本号。 * document.cookie 可以得到 httponly = false 的 cookie * * * Some Web browsers have bugs in how they handle the optional attributes, so * use them sparingly to improve the interoperability of your servlets. * 一些 web browsers 在处怎样处理可选的属性有 bugs。提高 servlets 的互操作性,请慎用。 * <p> * The servlet sends cookies to the browser by using the * {@link HttpServletResponse#addCookie} method, which adds fields to HTTP * response headers to send cookies to the browser, one at a time. The browser * is expected to support 20 cookies for each Web server, 300 cookies total, and * may limit cookie size to 4 KB each. * servlet 用 HttpServletResponse#addCookie 向 http 的相应头添加 field, 之后发送给浏览器. * 浏览器支持每一个 web server 保存 20 个 cookie. 每一个 cookie 的 size 可能被限制为 4 * * <p> * The browser returns cookies to the servlet by adding fields to HTTP request * headers. * 浏览器通过向 http 请求头添加 cookies 的方式返回给服务器. * * Cookies can be retrieved from a request by using the * {@link HttpServletRequest#getCookies} method. Several cookies might have the * same name but different path attributes. * 服务器通过 HttpServletRequest#getCookies 从请求中提取 cookies. * 一些 cookie 可能有相同的 name 但是有不同的 path attribute. * * <p> * Cookies affect the caching of the Web pages that use them. HTTP 1.0 does not * cache pages that use cookies created with this class. This class does not * support the cache control defined with HTTP 1.1. * <p> * This class supports both the RFC 2109 and the RFC 6265 specifications. * * By default, cookies are created using RFC 6265. * 默认的, cookie 生成方式采用 RFC 6265. 本质所有的 Cookie 都是按规范生成的. */ public class Cookie implements Cloneable, Serializable { // 校验 Cookie name private static final CookieNameValidator validation; static { boolean strictServletCompliance; // 严格的 servlet boolean strictNaming; boolean allowSlash; String propStrictNaming; String propFwdSlashIsSeparator; if (System.getSecurityManager() == null) { strictServletCompliance = Boolean.getBoolean( "org.apache.catalina.STRICT_SERVLET_COMPLIANCE"); propStrictNaming = System.getProperty( "org.apache.tomcat.util.http.ServerCookie.STRICT_NAMING"); propFwdSlashIsSeparator = System.getProperty( "org.apache.tomcat.util.http.ServerCookie.FWD_SLASH_IS_SEPARATOR"); } else { strictServletCompliance = AccessController.doPrivileged( new PrivilegedAction<Boolean>() { @Override public Boolean run() { return Boolean.valueOf(System.getProperty( "org.apache.catalina.STRICT_SERVLET_COMPLIANCE")); } } ).booleanValue(); propStrictNaming = AccessController.doPrivileged( new PrivilegedAction<String>() { @Override public String run() { return System.getProperty( "org.apache.tomcat.util.http.ServerCookie.STRICT_NAMING"); } } ); propFwdSlashIsSeparator = AccessController.doPrivileged( new PrivilegedAction<String>() { @Override public String run() { return System.getProperty( "org.apache.tomcat.util.http.ServerCookie.FWD_SLASH_IS_SEPARATOR"); } } ); } if (propStrictNaming == null) { strictNaming = strictServletCompliance; } else { strictNaming = Boolean.parseBoolean(propStrictNaming); } if (propFwdSlashIsSeparator == null) { allowSlash = !strictServletCompliance; } else { allowSlash = !Boolean.parseBoolean(propFwdSlashIsSeparator); } if (strictNaming) { validation = new RFC2109Validator(allowSlash); } else { validation = new RFC6265Validator(); } } private static final long serialVersionUID = 1L; private final String name; // cookie name 一旦创建不能被修改 private String value; // cookie value private int version = 0; // ;Version=1 ... means RFC 2109 style // 默认的是 RFC 6265 // // Attributes encoded in the header's cookie fields. // private String comment; // ;Comment=VALUE ... describes cookie's use private String domain; // ;Domain=VALUE ... domain that sees cookie 可以看到 cookie 的 domain private int maxAge = -1; // ;Max-Age=VALUE ... cookies auto-expire private String path; // ;Path=VALUE ... URLs that see the cookie 可以看到 cookie 的 urls private boolean secure; // ;Secure ... e.g. use SSL 启用 ssl private boolean httpOnly; // Not in cookie specs, but supported by browsers 不在 cookie 规范里, 但是被浏览器支持 /** * Constructs a cookie with a specified name and value. * <p> * The name must conform to RFC 2109. cookie name 必须遵循 RFC 2109. 没办法,规范就是牛啊 * That means it can contain only ASCII * alphanumeric characters and cannot contain commas, semicolons, or white * space or begin with a $ character. The cookie's name cannot be changed * after creation. * 这意味着 cookie name 只能包含 ASCII 的字母, 数字, 不能包括逗号, 分号, 空格, 或者以 * $ 开头. cookie name 一旦创建不能被修改. * * <p> * The value can be anything the server chooses to send. Its value is * probably of interest only to the server. The cookie's value can be * changed after creation with the <code>setValue</code> method. * server 可以通过 cookie value 发送任何东西. * <p> * By default, cookies are created according to the Netscape cookie * specification. The version can be changed with the * <code>setVersion</code> method. * * @param name * a <code>String</code> specifying the name of the cookie * @param value * a <code>String</code> specifying the value of the cookie * @throws IllegalArgumentException * if the cookie name contains illegal characters (for example, * a comma, space, or semicolon) or it is one of the tokens * reserved for use by the cookie protocol * @see #setValue * @see #setVersion */ public Cookie(String name, String value) { // 首先进行 cookie name 的校验 validation.validate(name); this.name = name; this.value = value; } /** * Specifies a comment that describes a cookie's purpose. * 描述这个 cookie 的目的 * The comment is useful if the browser presents the cookie to the user. Comments are not * supported by Netscape Version 0 cookies. * * @param purpose * a <code>String</code> specifying the comment to display to the * user * @see #getComment */ public void setComment(String purpose) { comment = purpose; } /** * Returns the comment describing the purpose of this cookie, or * <code>null</code> if the cookie has no comment. * * @return a <code>String</code> containing the comment, or * <code>null</code> if none * @see #setComment */ public String getComment() { return comment; } /** * Specifies the domain within which this cookie should be presented. * 指定这个 cookie 可以出现在那个 domain * <p> * The form of the domain name is specified by RFC 2109. A domain name * begins with a dot (<code>.foo.com</code>) and means that the cookie is * visible to servers in a specified Domain Name System (DNS) zone (for * example, <code>www.foo.com</code>, but not <code>a.b.foo.com</code>). By * default, cookies are only returned to the server that sent them. * * domain name 的形式说明在 RFC 2109. domain name 以 dot 开头, 这意味着在一个特定的 * DNS 这个 cookie 是可见的. 默认的, 那个服务器发送的 cookie 返回给哪个服务器. * * @param pattern * a <code>String</code> containing the domain name within which * this cookie is visible; form is according to RFC 2109 * @see #getDomain */ public void setDomain(String pattern) { domain = pattern.toLowerCase(Locale.ENGLISH); // IE allegedly needs this } /** * Returns the domain name set for this cookie. The form of the domain name * is set by RFC 2109. * * @return a <code>String</code> containing the domain name * @see #setDomain */ public String getDomain() { return domain; } /** * Sets the maximum age of the cookie in seconds. * cookie 最大存活的秒数 * <p> * A positive value indicates that the cookie will expire after that many * seconds have passed. Note that the value is the <i>maximum</i> age when * the cookie will expire, not the cookie's current age. * 一个正数表明 cookie 将在 maximun age 秒数后过期. * <p> * A negative value means that the cookie is not stored persistently and * will be deleted when the Web browser exits. A zero value causes the * cookie to be deleted. * * 一个负数表示 cookie 不会被永久存储, 浏览器退出时将被删除. * 0 删除这个 cookie * * @param expiry * an integer specifying the maximum age of the cookie in * seconds; if negative, means the cookie is not stored; if zero, * deletes the cookie * @see #getMaxAge */ public void setMaxAge(int expiry) { maxAge = expiry; } /** * Returns the maximum age of the cookie, specified in seconds, By default, * <code>-1</code> indicating the cookie will persist until browser * shutdown. * * @return an integer specifying the maximum age of the cookie in seconds; if * negative, means the cookie persists until browser shutdown * @see #setMaxAge */ public int getMaxAge() { return maxAge; } /** * Specifies a path for the cookie to which the client should return the * cookie. * 指定一个 path, 表示哪一个 client 应该把这个 cookie 返还给服务器. * * <p> * The cookie is visible to all the pages in the directory you specify, and * all the pages in that directory's subdirectories. A cookie's path must * include the servlet that set the cookie, for example, <i>/catalog</i>, * which makes the cookie visible to all directories on the server under * <i>/catalog</i>. * <p> * Consult RFC 2109 (available on the Internet) for more information on * setting path names for cookies. * * @param uri * a <code>String</code> specifying a path * @see #getPath */ public void setPath(String uri) { path = uri; } /** * Returns the path on the server to which the browser returns this cookie. * The cookie is visible to all subpaths on the server. * * @return a <code>String</code> specifying a path that contains a servlet * name, for example, <i>/catalog</i> * @see #setPath */ public String getPath() { return path; } /** * Indicates to the browser whether the cookie should only be sent using a * secure protocol, such as HTTPS or SSL. * <p> * The default value is <code>false</code>. * * @param flag * if <code>true</code>, sends the cookie from the browser to the * server only when using a secure protocol; if * <code>false</code>, sent on any protocol * @see #getSecure */ public void setSecure(boolean flag) { secure = flag; } /** * Returns <code>true</code> if the browser is sending cookies only over a * secure protocol, or <code>false</code> if the browser can send cookies * using any protocol. * * @return <code>true</code> if the browser uses a secure protocol; * otherwise, <code>true</code> * @see #setSecure */ public boolean getSecure() { return secure; } /** * Returns the name of the cookie. The name cannot be changed after * creation. * * @return a <code>String</code> specifying the cookie's name */ public String getName() { return name; } /** * Assigns a new value to a cookie after the cookie is created. If you use a * binary value, you may want to use BASE64 encoding. * cookie 被创建后, 给 value 指定一个值. 如果使用二进制的值, 采用 BASE64 的编码方式. * * <p> * With Version 0 cookies, values should not contain white space, brackets, * parentheses, equals signs, commas, double quotes, slashes, question * marks, at signs, colons, and semicolons. Empty values may not behave the * same way on all browsers. * * @param newValue * a <code>String</code> specifying the new value * @see #getValue * @see Cookie */ public void setValue(String newValue) { value = newValue; } /** * Returns the value of the cookie. * * @return a <code>String</code> containing the cookie's present value * @see #setValue * @see Cookie */ public String getValue() { return value; } /** * Returns the version of the protocol this cookie complies with. Version 1 * complies with RFC 2109, and version 0 complies with the original cookie * specification drafted by Netscape. Cookies provided by a browser use and * identify the browser's cookie version. * * @return 0 if the cookie complies with the original Netscape specification; * 1 if the cookie complies with RFC 2109 被 RFC 6265 淘汰 * @see #setVersion */ public int getVersion() { return version; } /** * Sets the version of the cookie protocol this cookie complies with. * Version 0 complies with the original Netscape cookie specification. * version 0 遵守原始的 netscape cookie 说明 * Version 1 complies with RFC 2109. * version 1 遵守 RFC 2109 规范 * <p> * Since RFC 2109 is still somewhat new, consider version 1 as experimental; * do not use it yet on production sites. * * @param v * 0 if the cookie should comply with the original Netscape * specification; 1 if the cookie should comply with RFC 2109 * @see #getVersion */ public void setVersion(int v) { version = v; } /** * Overrides the standard <code>java.lang.Object.clone</code> method to * return a copy of this cookie. */ @Override public Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { throw new RuntimeException(e); } } /** * Sets the flag that controls if this cookie will be hidden from scripts on * the client side. * * true 不能被 js document.cookie 操作 * * @param httpOnly The new value of the flag * * @since Servlet 3.0 */ public void setHttpOnly(boolean httpOnly) { this.httpOnly = httpOnly; } /** * Gets the flag that controls if this cookie will be hidden from scripts on * the client side. * * @return <code>true</code> if the cookie is hidden from scripts, else * <code>false</code> * @since Servlet 3.0 */ public boolean isHttpOnly() { return httpOnly; } } class CookieNameValidator { // 拿到 properties 文件的方法 ResourceBundle private static final String LSTRING_FILE = "javax.servlet.http.LocalStrings"; protected static final ResourceBundle lStrings = ResourceBundle.getBundle(LSTRING_FILE); protected final BitSet allowed; protected CookieNameValidator(String separators) { allowed = new BitSet(128); allowed.set(0x20, 0x7f); // any CHAR except CTLs or separators for (int i = 0; i < separators.length(); i++) { char ch = separators.charAt(i); allowed.clear(ch); } } void validate(String name) { // cookie name 不允许为 null 或者长度为 0 if (name == null || name.length() == 0) { throw new IllegalArgumentException(lStrings.getString("err.cookie_name_blank")); } if (!isToken(name)) { String errMsg = lStrings.getString("err.cookie_name_is_token"); throw new IllegalArgumentException(MessageFormat.format(errMsg, name)); } } private boolean isToken(String possibleToken) { int len = possibleToken.length(); for (int i = 0; i < len; i++) { char c = possibleToken.charAt(i); if (!allowed.get(c)) { return false; } } return true; } } class RFC6265Validator extends CookieNameValidator { private static final String RFC2616_SEPARATORS = "()<>@,;:\\\"/[]?={} \t"; RFC6265Validator() { super(RFC2616_SEPARATORS); } } class RFC2109Validator extends RFC6265Validator { RFC2109Validator(boolean allowSlash) { // special treatment to allow for FWD_SLASH_IS_SEPARATOR property if (allowSlash) { allowed.set('/'); } } @Override void validate(String name) { super.validate(name); // cookie name 不允许 $ 开头 if (name.charAt(0) == '$') { String errMsg = lStrings.getString("err.cookie_name_is_token"); throw new IllegalArgumentException(MessageFormat.format(errMsg, name)); } } }

Read more →

November 29, 2019

katacoda-what-is-a-container-image

#docker

container image A container image is a tar file containing tar files. Each of the tar file is a layer. Once all tar files have been extract into the same location then you have the container’s filesystem. container image 是一个 tar 文件. 每一个 tar 文件就是一个 layer docker pull 拉取一个镜像 docker pull redis:3.2.11-alpine 3.2.11-alpine: Pulling from library/redis ff3a5c916c92: Pull complete aae70a2e6027: Pull complete 87c655da471c: Pull complete bc3141806bdc: Pull complete 53616fb426d9: Pull complete 9791c5883c6a: Pull complete Digest: sha256:ebf1948b84dcaaa0f8a2849cce6f2548edb8862e2829e3e7d9e4cd5a324fb3b7 Status: Downloaded newer image for redis:3.2.11-alpine

Read more →

November 26, 2019

bloomfilter

#data structure

References bloom filter bloom filter https://coderscat.com/bloom-filter/

Read more →

November 22, 2019

x86-64-architecture

#x86

操作系统其实很大一部分面向 CPU 来编程的。一些 OS 的概念直接来源于 CPU 的术语,或者和 CPU 关联性非常大。要想彻底理解 OS ,无法绕过 CPU。因为 Intel 的 X86(Intel 80386 之后的一系列 CPU 称之为 X86 架构) 是业界的标准。掌握这个架构对于理解 OS 是非常必要的。因为 X86 系列的 CPU 向后兼容,所以本文使用 Intel 8086(16 bit) 和 Intel 80386(32 bit) 来试图理解 X86 架构。

Read more →

October 16, 2019

select_poll_epoll

#io

弄清楚 I/O Multiplexing 和 Linux 中 select, poll, epoll 之间的关系. multiplexer Multiplexer is a combinational circuit that has maximum of 2^n data inputs, n selection lines and single output line. One of these data inputs will be connected to the output based on the values of selection lines. Since there are n selection lines, there will be 2^n possible combinations of zeros and ones. So, each combination will select only one data input. Multiplexer is also called as Mux. 聚合多个输入, 通过 selection lines 来选择一个输出.

Read more →

September 19, 2019

wireshark

#network#tools

Wireshark Windows 配置 SSL Version 3.0.3 配置 SSLKEYLOGFILE 系统变量 配置 Wireshark 编辑 -> 首选项 -> Protocols -> TLS 重启 Wireshark 过滤器查看 视图 -> 内部 -> 支持的协议

Read more →

September 10, 2019

docker-practice

#docker

Centos7 Linux 运行的 Docker 容器是: mssql-node-docker-demo-app docker info #(docker-info) docker inspect [ { "Id": "405a378d6f88f903dda5972dbfb8f037efff22296c3aaf4c50d44ebd68ad8655", "Created": "2019-08-01T02:57:14.067532309Z", "Path": "/bin/sh", "Args": [ "-c", "/bin/bash ./entrypoint.sh" ], "State": { "Status": "running", "Running": true, "Paused": false, "Restarting": false, "OOMKilled": false, "Dead": false, "Pid": 12164, "ExitCode": 0, "Error": "", "StartedAt": "2019-08-22T06:08:43.334320939Z", "FinishedAt": "2019-08-21T09:25:32.130119566Z" }, "Image": "sha256:e600f86aa4e2aced43a193a28aa507651bfb77daa09ca8dbf286451a630cf27e", // node-web-app 的 docker 镜像 id "ResolvConfPath": "/var/lib/docker/containers/405a378d6f88f903dda5972dbfb8f037efff22296c3aaf4c50d44ebd68ad8655/resolv.conf", "HostnamePath": "/var/lib/docker/containers/405a378d6f88f903dda5972dbfb8f037efff22296c3aaf4c50d44ebd68ad8655/hostname", "HostsPath": "/var/lib/docker/containers/405a378d6f88f903dda5972dbfb8f037efff22296c3aaf4c50d44ebd68ad8655/hosts", "LogPath": "", "Name": "/friendly_hamilton", // docker container 的名称 "RestartCount": 0, "Driver": "overlay2", // storage driver "MountLabel": "", "ProcessLabel": "", "AppArmorProfile": "", "ExecIDs": null, "HostConfig": { "Binds": null, "ContainerIDFile": "", "LogConfig": { "Type": "journald", "Config": {} }, "NetworkMode": "default", "PortBindings": { "1433/tcp": [ { "HostIp": "", "HostPort": "1433" } ], "8080/tcp": [ { "HostIp": "", "HostPort": "8080" } ] }, "RestartPolicy": { "Name": "no", "MaximumRetryCount": 0 }, "AutoRemove": false, "VolumeDriver": "", "VolumesFrom": null, "CapAdd": null, "CapDrop": null, "Dns": [], "DnsOptions": [], "DnsSearch": [], "ExtraHosts": null, "GroupAdd": null, "IpcMode": "", "Cgroup": "", "Links": null, "OomScoreAdj": 0, "PidMode": "", "Privileged": false, "PublishAllPorts": false, "ReadonlyRootfs": false, "SecurityOpt": null, "UTSMode": "", "UsernsMode": "", "ShmSize": 67108864, "Runtime": "docker-runc", "ConsoleSize": [ 0, 0 ], "Isolation": "", "CpuShares": 0, "Memory": 0, "NanoCpus": 0, "CgroupParent": "", "BlkioWeight": 0, "BlkioWeightDevice": null, "BlkioDeviceReadBps": null, "BlkioDeviceWriteBps": null, "BlkioDeviceReadIOps": null, "BlkioDeviceWriteIOps": null, "CpuPeriod": 0, "CpuQuota": 0, "CpuRealtimePeriod": 0, "CpuRealtimeRuntime": 0, "CpusetCpus": "", "CpusetMems": "", "Devices": [], "DiskQuota": 0, "KernelMemory": 0, "MemoryReservation": 0, "MemorySwap": 0, "MemorySwappiness": -1, "OomKillDisable": false, "PidsLimit": 0, "Ulimits": null, "CpuCount": 0, "CpuPercent": 0, "IOMaximumIOps": 0, "IOMaximumBandwidth": 0 }, "GraphDriver": { "Name": "overlay2", "Data": { "LowerDir": "/var/lib/docker/overlay2/efead8cb8732e4ccfc24485c253d02838842d6dfd9a2ee60a9142c69cb54f4a2-init/diff:/var/lib/docker/overlay2/83b7194d94d42c0ef8f78a2f4105cc7a7a215a8e885b695a933a8f8212db9cfa/diff:/var/lib/docker/overlay2/9549118d3883d39414fadf0dc17e654d1408878be3296b294711ee65ef336b98/diff:/var/lib/docker/overlay2/8e85764472e79d42f469dd3681883cd415e85098d6c42fb3dd239471212f87b3/diff:/var/lib/docker/overlay2/8dc8ec519bade76b07994adc690d1e6fcad408147835198a250b4c66c489a151/diff:/var/lib/docker/overlay2/b07d1c7463b2a4ff25f7800729381fdf5b036c12a065973b9d079580c3a50a5e/diff:/var/lib/docker/overlay2/60c9257cc9d8a7ac4b66d1c4cae5ff994471976f0a344f8ac1856a4fba7b290e/diff:/var/lib/docker/overlay2/2a00c5b47427e151e000ffe05de8121e956dbf15b0d356cfc9ad2754dc5554d5/diff:/var/lib/docker/overlay2/3495bcc2d508cbdad81b1f3eb49645fe0eb05caf0e99fbb6310d40fbdd8118a2/diff:/var/lib/docker/overlay2/9df322481c6f8b91b3583016634664e6ad991b8b846a9585385227a02b898770/diff:/var/lib/docker/overlay2/163747850da2115bac28b39ac6d2e08ca5c0e409fe6cae624155f8e61489aacd/diff:/var/lib/docker/overlay2/52405978404b67e0a67ba95cb12682d0e8a8ae781fd2b21dc2ab94197e97c38b/diff:/var/lib/docker/overlay2/c987c31253bca839eb789feb3e4fe7bc247b1e88dc88c67e2b4209fc26025fe8/diff:/var/lib/docker/overlay2/ed663d4b2fffda783f9b69e5eb7c139f34142e0e2d868460a3c1e1d925ec3e7e/diff:/var/lib/docker/overlay2/a0e3d07a65b7ee70d3869fa41418ecf71056b9ac0ba1182170621c83c77bba94/diff:/var/lib/docker/overlay2/aa4c66b37aae4e55a94aa60ac763a60851af34271ccb1a80f547e3d90e7ac2bf/diff:/var/lib/docker/overlay2/527b1a014d302c1fe835d778be6cd008de6741d290fbc0f2e64e3f25f7a7b8d0/diff", "MergedDir": "/var/lib/docker/overlay2/efead8cb8732e4ccfc24485c253d02838842d6dfd9a2ee60a9142c69cb54f4a2/merged", "UpperDir": "/var/lib/docker/overlay2/efead8cb8732e4ccfc24485c253d02838842d6dfd9a2ee60a9142c69cb54f4a2/diff", "WorkDir": "/var/lib/docker/overlay2/efead8cb8732e4ccfc24485c253d02838842d6dfd9a2ee60a9142c69cb54f4a2/work" } }, "Mounts": [ { "Type": "volume", "Name": "7bc1a7ad23925077cf8463c2d7a21b0cafc7d91305d89504f85fa76c33138834", "Source": "/var/lib/docker/volumes/7bc1a7ad23925077cf8463c2d7a21b0cafc7d91305d89504f85fa76c33138834/_data", // host 主机的被挂在的目录 "Destination": "/var/opt/mssql", // Volume 挂载点 "Driver": "local", "Mode": "", "RW": true, "Propagation": "" } ], "Config": { "Hostname": "405a378d6f88", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "ExposedPorts": { "1433/tcp": {}, "8080/tcp": {} }, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "ACCEPT_EULA=Y", "SA_PASSWORD=Yukon900", "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ], "Cmd": [ "/bin/sh", "-c", "/bin/bash ./entrypoint.sh" ], "ArgsEscaped": true, "Image": "node-web-app", "Volumes": { "/var/opt/mssql": {} }, "WorkingDir": "/usr/src/app", "Entrypoint": null, "OnBuild": null, "Labels": { "com.microsoft.product": "Microsoft SQL Server", "com.microsoft.version": "14.0.3048.4", "vendor": "Microsoft" } }, "NetworkSettings": { "Bridge": "", "SandboxID": "d21ee4834e9078042da65677d8db9717748eb7f86a6954c5e4eee29636159aa7", "HairpinMode": false, "LinkLocalIPv6Address": "", "LinkLocalIPv6PrefixLen": 0, "Ports": { "1433/tcp": [ { "HostIp": "0.0.0.0", "HostPort": "1433" } ], "8080/tcp": [ { "HostIp": "0.0.0.0", "HostPort": "8080" } ] }, "SandboxKey": "/var/run/docker/netns/d21ee4834e90", "SecondaryIPAddresses": null, "SecondaryIPv6Addresses": null, "EndpointID": "46dac1ff81a297ede919100e0d06a743b845e34b802b54bca8cb8f02dcd33c85", "Gateway": "172.17.0.1", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "IPAddress": "172.17.0.2", "IPPrefixLen": 16, "IPv6Gateway": "", "MacAddress": "02:42:ac:11:00:02", "Networks": { "bridge": { "IPAMConfig": null, "Links": null, "Aliases": null, "NetworkID": "a8af0599996912141c3f2ce4b0a2bcc48eea9164a35672aac6307333450acb6b", //a8af05999969 "EndpointID": "46dac1ff81a297ede919100e0d06a743b845e34b802b54bca8cb8f02dcd33c85", "Gateway": "172.17.0.1", "IPAddress": "172.17.0.2", "IPPrefixLen": 16, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "MacAddress": "02:42:ac:11:00:02" } } } } ] docker volume mount "Mounts": [ { "Type": "volume", "Name": "7bc1a7ad23925077cf8463c2d7a21b0cafc7d91305d89504f85fa76c33138834", "Source": "/var/lib/docker/volumes/7bc1a7ad23925077cf8463c2d7a21b0cafc7d91305d89504f85fa76c33138834/_data", // host 主机的被挂载的目录 "Destination": "/var/opt/mssql", // Volume 挂载点 "Driver": "local", "Mode": "", "RW": true, "Propagation": "" } ] Local Docker container 网络 { "ResolvConfPath": "/var/lib/docker/containers/405a378d6f88f903dda5972dbfb8f037efff22296c3aaf4c50d44ebd68ad8655/resolv.conf", "HostnamePath": "/var/lib/docker/containers/405a378d6f88f903dda5972dbfb8f037efff22296c3aaf4c50d44ebd68ad8655/hostname", "HostsPath": "/var/lib/docker/containers/405a378d6f88f903dda5972dbfb8f037efff22296c3aaf4c50d44ebd68ad8655/hosts", } #(本地存储的容器的网络配置)

Read more →

September 3, 2019

clang-structure

#clang

size of structurereference flexible-array-members-structure-c

Read more →

July 17, 2019

asm-how-recursion-function-execute

#asm

斐波那契数列问题描述 第一个月初有一对刚诞生的兔子 第二个月之后(第三个月)它们可以生育 每月每对可生育的兔子会诞生下一对新兔子 兔子永不死 问第 n 月有多少对兔子?

Read more →

July 6, 2019

asm-clang-concepts

#asm

C 语言里的概念在 X86-64 汇编层面的分析. 汇编风格使用 AT&T 风格. 编译器是 gcc-x86-64-9.1 指针 A pointer is a programming language object that stores the memory address of another value located in computer memory. A pointer references a location in memory, and obtaining the value stored at that location is known as dereferencing the pointer.

Read more →

June 25, 2019

asm-how-x86-64-arguments-pass

#asm

x86-64 下函数参数传递, 汇编层面分析 To pass parameters to the subroutine, we put up to six of them into registers (in order: rdi, rsi, rdx, rcx, r8, r9). If there are more than six parameters to the subroutine, then push the rest onto the stack in reverse order (i.e. last parameter first) – since the stack grows down, the first of the extra parameters (really the seventh parameter) parameter will be stored at the lowest address (this inversion of parameters was historically used to allow functions to be passed a variable number of parameters).

Read more →

June 24, 2019

tools-for-me

#tools

programmingjava decompiler-Luyten decompiler-cfr byte-code-viewer jclasslib assembly godbolt json json-runoob json-online regexp regexp-jex.im regexp-regexr regexp-regexper hex hex converter hex editor html html beautify base64 base64 code format code format url json format unicode unicode for you shell oh-my-zsh starship workingpc snipaste mubu process on screen-recorder reinstall os multibootusb universal usb installer rufus entertainmentvideo online downloader-you-get downloader-motrix downloader-Xdown converter audio-converter movie cupfox agmov picture waifu2x papers-anwanqi ilovepapers file ilovepdf html to pdf typing practice typing https://qwerty.kaiyi.cool/ jobcompany tianyancha resume 木及简历

Read more →

June 17, 2019

master-ip

#network

MotivationThe Internet Protocol is designed for use in interconnected systems of packet-switched computer communication networks. Such a system has been called a “catenet”. The internet protocol provides for transmitting blocks of data called datagrams from sources to destinations, where sources and destinations are hosts identified by fixed length addresses. The internet protocol also provides for fragmentation and reassembly of long datagrams, if necessary, for transmission through “small packet” networks. IPv4 is a connectionless protocol for use on packet-switched networks. It operates on a best effort delivery model, in that it does not guarantee delivery, nor does it assure proper sequencing or avoidance of duplicate delivery. These aspects, including data integrity, are addressed by an upper layer transport protocol, such as the Transmission Control Protocol (TCP).

Read more →

June 4, 2019

linux-kernel-analysis-2

#linux-analysis

数据连续存储和选择读取

Read more →

May 31, 2019

asm-how-x86-function-execute

#asm

前一阵子去看 java 虚拟机原理, 忽然痛悟到虚拟机也是机器啊, 呵呵也就是个软件而已. 看到 java 方法调用太复杂. 字节码那一套又不太熟悉, 还不如直接去看 C 编译后的汇编代码. 目的: 搞明白 X86 架构下函数到底是怎么调用执行的. 这其实就是 Application Binary Interface 之 Function Calling Conventions。

Read more →

May 28, 2019

linux-kernel-analysis-1

#linux-analysis

analysis01设计理念 机制与策略分离 机制 – 提供什么样的功能 策略 – 如何使用这些功能 说实在的这句话第一次听到还是挺震撼的, 一时觉得大学里的操作系统都不知道在干嘛, 我们学的就是机制, 比如进程创建功能, 进程创建完成后具体如何使用与OS内核不再有关. 文件创建功能, 文件创建完,如何使用交给用户. 其实很类似编程中的接口, 接口定义功能, 实现负责具体的策略.

Read more →

May 28, 2019

ubuntu18.04-install-openjdk8

#openjdk

添加 openjdk8 的第三方源 sudo add-apt-repository ppa:openjdk-r/ppa ppa (Personal Package Achives) 执行更新 apt-get update 安装 openjdk8 sudo apt-get install openjdk-8-jdk 选择版本 sudo update-alternatives - -config java 确认安装成功 java -version

Read more →

May 25, 2019

master-tcp

#tcp

The Transmission Control Protocol (TCP) is intended for use as a highly reliable host-to-host protocol between hosts in packet-switched computer communication networks, and in interconnected systems of such networks. TCP header format basic data transfer reliability sequence number acknowledgement flow control window size multiplexing socket (ip, port) connections Each connection is uniquely specified by a pair of sockets identifying its two sides.(source ip, source port),(destination ip, destination port)

Read more →

May 22, 2019

git-commands

#git

git rebase -i HEAD~N 复制提交记录 git branch -f target-branch-name commit-id 切换到 target-branch-name 并指向 commit-id git cherry-pick commit-id1 commit-id2 重新排序提交的记录. cherry-pick 名字起得真是有意思啊. 像捡樱桃似的, 把一个个想要的记录捡到当前分支的后面.

Read more →

May 20, 2019

csapp-memory-hierarchy

#csapp

storageDisk Controller 我们知道定位一个磁盘空间需要三个参数(platter, track, sector). 但是 cpu 不使用这么麻烦的方式, cpu 使用的是逻辑盘号. 也就是磁盘控制器将逻辑盘号翻译成 platter, track, sector. 磁盘控制器充当一个中间层. 也就是只关心逻辑盘号, 不关心具体的(platter, track, sector). 通过逻辑盘号将三维的(platter, track, sector) 转换为一维数组, 这就是抽象的意义啊. 这就是降维思维嘛.

Read more →

May 20, 2019

building-docker-image

#docker

Docker images are built based on a Dockerfile. A Dockerfile defines all the steps required to create a Docker image with your application configured and ready to be run as a container. The image itself contains everything, from operating system to dependencies and configuration required to run your application. Having everything within the image allows you to migrate images between different environments and be confident that if it works in one environment, then it will work in another. The Dockerfile allows for images to be composable, enabling users to extend existing images instead of building from scratch. By building on an existing image, you only need to define the steps to setup your application. The base images can be basic operating system installations or configured systems which simply need some additional customisations.

Read more →

May 16, 2019

deploy-static-website

#docker

Create a Dockerfile Docker Images start from a base image. The base image should include the platform dependencies required by your application, for example, having the JVM or CLR installed. This base image is defined as an instruction in the Dockerfile. Docker Images are built based on the contents of a Dockerfile. The Dockerfile is a list of instructions describing how to deploy your application. # base image FROM nginx:alpine # copies the content of the current directory into a particular location (/usr/share/nginx/html)inside the container. COPY . /usr/share/nginx/html Build docker image The Dockerfile is used by the Docker CLI build command. The build command executes each instruction within the Dockerfile. The result is a built Docker Image that can be launched and run your configured app. The build command takes in some different parameters. The format is docker build -t build-directory. The -t parameter allows you to specify a friendly name for the image and a tag, commonly used as a version number. This allows you to track built images and be confident about which version is being started.

Read more →

May 16, 2019

katacoda-deploying-first-docker-container

#docker

Running a container background(detached)docker search image-name docker search redis docker run options image-name:version solution1: default latest version docker run -d redis solution2: version is 3.2

Read more →

May 16, 2019