最近在看 Linux 中双向链表的实现,发现大部分代码都是能看懂的,和上学时学的内容基本一致。

什么头插法,尾插法啊乱七八糟的。

但我注意到有一点似乎不一样,在学校时,我们学的链表包括数据域指针域,但在 Linux 中双向链表的节点是这样定义的:

1
2
3
struct list_head {
struct list_head *next, *prev;
};

没有数据域

没有数据域的链表该怎么使用呢?

Recently I’ve been reading the Linux doubly-linked list implementation, and found that most of the code is understandable — basically the same as what I learned in school.

Head insertion, tail insertion, and all that stuff.

But I noticed one thing seems different: in school, we learned that a linked list node includes a data field and a pointer field, but in Linux the doubly-linked list node is defined like this:

1
2
3
struct list_head {
struct list_head *next, *prev;
};

No data field

How do you use a linked list without a data field?

C/C++WikiLinuxKernel

Lesson 1

Words

  • Q1. 如何引起他人注意
  • Q2. 如何让对方再讲一遍
  • Q3. 当我谈单词时我谈些什么?
  1. excuse me
    打扰一下,用于引起别人的注意

借过一下,让一下,也用 Excuse me

  1. handbag n.
    手提包
  2. pardon
    没听清,再说一遍

sorry? 也有这个意思

  1. Thank you very(so) much
    非常感谢

Thank you very much 是比较正式的说法。
大多数情况下不必说 Thank you very much, Thank you 足够了。
e.g. Thank you, Sir! Thank you! Thank you, man

WikiEnglish

现在的工作可以说是一行代码也不写,WB 程序员,经历了才会懂。

为了避免手生以及进一步巩固基础知识,决定定期抄一抄代码。

Linux 核心工具 开始,学习如何优雅编程。

The current job can be said to involve writing not a single line of code. Only those who have been through it as a WB programmer can understand.

To avoid getting rusty and to further consolidate basic knowledge, I decided to copy some code regularly.

Starting with the Linux core utilities, let’s learn how to program elegantly.

C/C++WikiLinux

想当年 jsdelivr 在国内还能用的时候, GitHub 就是免费小网盘。

现在虽然国内访问不那么流畅了,但是用来存一些小的琐碎的日志文件还是不错的。

为了实现自动化,使用 Python 参考 GitHub API 文档 封装了一些常用功能。

Back when jsdelivr was still usable in China, GitHub was a free little online drive.

Although access from China is not as smooth now, it is still good for storing small, trivial log files.

To achieve automation, I used Python and referred to the GitHub API documentation to wrap some commonly used functions.

Wiki教程PythonGitHub

硬件和程序员的约定

CPU Reset 后寄存器会有确定的初始状态

  • EIP = 0x0000fff0
  • CR0 = 0x60000010
    • 处理器处于 16-bit 模式
  • EFLAGS = 0x00000002
    • interrupt disabled

Reset 后处理器从固定地址(Reset Vector)启动

  • MIPS: 0xbfc000000
    • Specification 规定
  • ARM: 0x00000000
    • Specification 规定
    • 允许配置 Reset Vector Base Address Register
  • RISC-V: Implementation defined
    • 给厂商最大程度的自由

The Convention Between Hardware and Programmers

After CPU Reset, registers have well-defined initial states

  • EIP = 0x0000fff0
  • CR0 = 0x60000010
    • The processor is in 16-bit mode
  • EFLAGS = 0x00000002
    • interrupt disabled

After Reset, the processor starts from a fixed address (the Reset Vector)

  • MIPS: 0xbfc000000
    • Specified by the Specification
  • ARM: 0x00000000
    • Specified by the Specification
    • Allows configuring the Reset Vector Base Address Register
  • RISC-V: Implementation defined
    • Gives vendors maximum freedom
C/C++WikiLinux

最小的 C 程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <sys/syscall.h>

.globl _start
_start:
movq $SYS_write, %rax // write(
movq $1, %rdi // fd=1,
movq $st, %rsi // buf=st,
movq $(ed - st), %rdx // count=ed-st
syscall // );

movq $SYS_exit, %rax // exit(
movq $1, %rdi // status=1
syscall // );

st:
.ascii "\033[01;31mHello, OS World\033[0m\n"
ed:

:这段代码是什么意思?

The Smallest C Program

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <sys/syscall.h>

.globl _start
_start:
movq $SYS_write, %rax // write(
movq $1, %rdi // fd=1,
movq $st, %rsi // buf=st,
movq $(ed - st), %rdx // count=ed-st
syscall // );

movq $SYS_exit, %rax // exit(
movq $1, %rdi // status=1
syscall // );

st:
.ascii "\033[01;31mHello, OS World\033[0m\n"
ed:

Q: What does this piece of code mean?

C/C++WikiLinux