下面是一份修复后的版本。主要改动:

  • 删除所有失效链接和纯外链引用;
  • 将 Python 2 相关内容更新为 Python 3;
  • 修正原文中容易误导或错误的表述;
  • 代码统一为 Python 3 可运行;
  • 保留原文档结构,但做了精简和勘误。

Python 语言特性(Python 3 修复版)#

1. Python 的函数参数传递#

Python 的参数传递既不是“值传递”,也不是“引用传递”,而是 对象引用传递(call by object reference)。

  • 变量名只是对象的引用;
  • 函数收到的是引用的副本;
  • 如果对象不可变(int、str、tuple、frozenset),函数内重新赋值不会影响外部;
  • 如果对象可变(list、dict、set),函数内原地修改会影响外部。
a = 1
def fun(a):
    a = 2
fun(a)
print(a)  # 1

a = []
def fun(a):
    a.append(1)
fun(a)
print(a)  # [1]

用 id 观察:

a = 1
def fun(a):
    print("func_in", id(a))
    a = 2
    print("re-point", id(a), id(2))
print("func_out", id(a), id(1))
fun(a)
print(a)  # 1

不可变对象重新赋值后,引用指向新对象;可变对象原地修改时,引用不变。

2. Python 中的元类(metaclass)#

元类是“创建类的类”。默认情况下,type 就是所有类的元类。元类常用于 ORM、框架等需要控制类创建过程的场景。日常业务开发很少直接使用。

3. @staticmethod 和 @classmethod#

Python 中有三种方法:

  • 实例方法:第一个参数是 self,通过实例调用;
  • 类方法:第一个参数是 cls,通过类或实例调用;
  • 静态方法:没有默认第一个参数,通过类或实例调用,本质上就是普通函数。
class A:
    def foo(self, x):
        print(f"executing foo({self}, {x})")

    @classmethod
    def class_foo(cls, x):
        print(f"executing class_foo({cls}, {x})")

    @staticmethod
    def static_foo(x):
        print(f"executing static_foo({x})")

a = A()
a.foo(1)
a.class_foo(1)
A.class_foo(1)
a.static_foo(1)
A.static_foo(1)

4. 类变量和实例变量#

  • 类变量:在类中定义,所有实例共享;
  • 实例变量:在 __init__ 中用 self.xxx 定义,每个实例独立。
class Test:
    num_of_instance = 0

    def __init__(self, name):
        self.name = name
        Test.num_of_instance += 1

print(Test.num_of_instance)  # 0
t1 = Test('jack')
print(Test.num_of_instance)  # 1
t2 = Test('lucy')
print(t1.name, t1.num_of_instance)  # jack 2
print(t2.name, t2.num_of_instance)  # lucy 2

注意:如果类变量是可变对象,所有实例共享它,容易出问题。

class Person:
    name = []

p1 = Person()
p2 = Person()
p1.name.append(1)
print(p1.name)  # [1]
print(p2.name)  # [1]
print(Person.name)  # [1]

5. Python 自省#

自省指运行时获取对象信息。常用函数:

  • type()
  • dir()
  • getattr()
  • hasattr()
  • isinstance()
a = [1, 2, 3]
b = {'a': 1, 'b': 2, 'c': 3}
c = True
print(type(a), type(b), type(c))
print(isinstance(a, list))  # True

6. 字典推导式#

d = {key: value for key, value in iterable.items()}

7. 单下划线和双下划线#

  • __foo__:Python 内部特殊方法,如 __init__、__del__;
  • _foo:约定私有,from module import * 不会导入;
  • __foo:名称改写(name mangling),解析器会变成 _类名__foo。
class MyClass:
    def __init__(self):
        self.__superprivate = "Hello"
        self._semiprivate = ", world!"

mc = MyClass()
# print(mc.__superprivate)  # AttributeError
print(mc._semiprivate)      # , world!
print(mc.__dict__)          # {'_MyClass__superprivate': 'Hello', '_semiprivate': ', world!'}
print(mc._MyClass__superprivate)  # Hello

8. 字符串格式化#

Python 3 推荐使用 f-string,其次 str.format(),% 仍可用但不推荐。

name = "小明"
age = 20
print(f"{name}的年龄是{age}岁!")

% 的问题:如果变量是元组,需要写成 "hi there %s" % (name,)。

9. 迭代器和生成器#

列表生成式用 [],生成器表达式用 ()。

L = [x * x for x in range(10)]
g = (x * x for x in range(10))
print(L)  # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
print(g)  # <generator object ...>

生成器边循环边计算,节省内存。yield 用于创建生成器。

10. *args 和 **kwargs#

  • *args:接收任意数量的位置参数,打包为元组;
  • **kwargs:接收任意数量的关键字参数,打包为字典。
def print_everything(*args):
    for count, thing in enumerate(args):
        print(f'{count}. {thing}')

def table_things(**kwargs):
    for name, value in kwargs.items():
        print(f'{name} = {value}')

print_everything('apple', 'banana', 'cabbage')
table_things(apple='fruit', cabbage='vegetable')

调用时也可以用 * 和 ** 解包。

11. 面向切面编程 AOP 和装饰器#

装饰器用于在不修改原函数代码的情况下增加功能,如日志、性能测试、事务处理。

import time

def count_time(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"耗时 {end - start:.4f}s")
        return result
    return wrapper

@count_time
def work():
    time.sleep(0.5)

work()

12. 鸭子类型#

“如果它走起来像鸭子,叫起来像鸭子,那它就是鸭子。”

Python 不关心对象的具体类型,只关心它是否具有所需的方法或行为。

class Duck:
    def quack(self):
        print("quack")

class Person:
    def quack(self):
        print("I can quack too")

def make_quack(obj):
    obj.quack()

make_quack(Duck())
make_quack(Person())

13. Python 中重载#

Python 不支持传统函数重载。因为 Python 可以接受任意类型参数,也可以用默认参数、可变参数处理不同参数个数。

如果需要按类型分派,可以用 functools.singledispatch。

14. 新式类和旧式类#

Python 3 中所有类都是新式类,默认继承 object。旧式类只存在于 Python 2。新式类使用 C3 算法计算 MRO。

15. new 和 init 的区别#

  • __new__:静态方法,创建并返回实例;
  • __init__:实例方法,初始化实例,无返回值;
  • 只有 __new__ 返回当前类实例时,才会调用 __init__。

16. 单例模式#

方法一:使用 new#

class Singleton:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

class MyClass(Singleton):
    a = 1

方法二:装饰器#

def singleton(cls):
    instances = {}
    def get_instance(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    return get_instance

@singleton
class MyClass:
    pass

方法三:模块天然单例#

Python 模块只会被导入一次,因此模块级变量天然是单例。

17. Python 中的作用域#

变量搜索顺序为 LEGB:

  • Local:本地作用域
  • Enclosing:嵌套函数的外层作用域
  • Global:全局/模块作用域
  • Built-in:内置作用域

18. GIL 线程全局锁#

GIL 是 CPython 解释器中的全局锁,保证同一进程内同一时刻只有一个线程执行 Python 字节码。

  • 对 I/O 密集型任务,多线程仍有效;
  • 对 CPU 密集型任务,多线程无法利用多核,建议用多进程或 concurrent.futures。

19. 协程#

协程是用户态轻量级线程,由程序自己控制切换,减少内核态切换开销。Python 3 中推荐使用 async / await。

import asyncio

async def hello():
    print("Hello")
    await asyncio.sleep(1)
    print("World")

asyncio.run(hello())

生成器也可以实现协程,但现代写法是 async / await。

20. 闭包#

闭包条件:

  1. 有内嵌函数;
  2. 内嵌函数引用外部函数的变量;
  3. 外部函数返回内嵌函数。
def outer(x):
    def inner(y):
        return x + y
    return inner

f = outer(10)
print(f(5))  # 15

闭包会让外部函数的变量在函数返回后继续存在。

21. lambda 函数#

匿名函数。

f = lambda x: x * x
print(f(4))  # 16

g = lambda x, y: x + y
print(g(1, 2))  # 3

22. Python 函数式编程#

  • filter(function, iterable):过滤;
  • map(function, iterable):映射;
  • reduce(function, iterable):在 functools 中,归约。
from functools import reduce

a = [1, 2, 3, 4, 5, 6, 7]
b = filter(lambda x: x > 5, a)
print(list(b))  # [6, 7]

c = map(lambda x: x * 2, [1, 2, 3])
print(list(c))  # [2, 4, 6]

print(reduce(lambda x, y: x * y, range(1, 4)))  # 6

23. Python 里的拷贝#

  • 赋值:传递对象引用;
  • 浅拷贝:创建新对象,但内部嵌套对象仍共享引用;
  • 深拷贝:递归复制所有层级,完全独立。
import copy

a = [1, 2, 3, 4, ['a', 'b']]
b = a
c = copy.copy(a)
d = copy.deepcopy(a)

a.append(5)
a[4].append('c')

print('a =', a)
print('b =', b)
print('c =', c)
print('d =', d)

输出:

a = [1, 2, 3, 4, ['a', 'b', 'c'], 5]
b = [1, 2, 3, 4, ['a', 'b', 'c'], 5]
c = [1, 2, 3, 4, ['a', 'b', 'c']]
d = [1, 2, 3, 4, ['a', 'b']]

24. Python 垃圾回收机制#

Python GC 主要使用:

  1. 引用计数:对象引用数为 0 时立即回收;
  2. 标记-清除:解决循环引用;
  3. 分代回收:将对象分为三代,越老的对象回收频率越低。

优点:实时性、简单;缺点:维护引用计数有开销,循环引用需要额外机制。

25. Python 的 List#

Python 列表是动态数组,支持随机访问、尾部追加高效,头部插入/删除较慢。底层是连续内存,扩容时按一定比例增长。

26. Python 的 is#

  • is:比较内存地址,即是否是同一个对象;
  • ==:比较值是否相等。

27. read、readline 和 readlines#

  • read():读取整个文件;
  • readline():读取下一行;
  • readlines():读取所有行,返回列表。

28. Python 2 和 3 的区别#

  • print 变成函数;
  • 字符串默认 Unicode;
  • range 返回惰性序列,xrange 被移除;
  • 除法 / 返回浮点数,整除用 //;
  • 异常语法 except Exception as e;
  • 字典 keys()、values()、items() 返回视图;
  • 推荐使用 f-string。

29. super init#

Python 3 中推荐:

class Child(Base):
    def __init__(self):
        super().__init__()

30. range 和 xrange#

Python 3 中只有 range,它返回惰性序列,类似 Python 2 的 xrange。xrange 已移除。


操作系统#

1. select、poll 和 epoll#

I/O 多路复用机制:

  • select:连接数受限,查找慢,有内核到用户态拷贝;
  • poll:改进了连接数限制;
  • epoll:Linux 下更高效,支持边沿触发和水平触发。

2. 调度算法#

  • 先来先服务 FCFS
  • 短作业优先 SJF
  • 最高优先权调度
  • 时间片轮转 RR
  • 多级反馈队列

实时调度:EDF、LLF。

3. 死锁#

必要条件:

  1. 互斥;
  2. 请求和保持;
  3. 不可剥夺;
  4. 循环等待。

处理方式:预防、避免(银行家算法)、检测、解除。

4. 程序编译与链接#

过程:

  1. 预处理:展开宏、包含头文件、删除注释;
  2. 编译:词法、语法、语义分析,生成汇编;
  3. 汇编:生成目标文件;
  4. 链接:地址分配、符号决议、重定位。

5. 静态链接和动态链接#

  • 静态链接:程序启动前确定地址,运行性能好,体积大;
  • 动态链接:运行时加载,初始化快,运行性能略低,节省空间。

6. 虚拟内存技术#

虚拟内存让程序可以使用比物理内存更大的地址空间,具有请求调入和置换功能。

7. 分页和分段#

  • 分页:固定大小,物理单位,一维地址;
  • 分段:可变大小,逻辑单位,二维地址。

8. 页面置换算法#

  • OPT:最佳置换,理论最优;
  • FIFO:先进先出;
  • LRU:最近最久未使用;
  • Clock:时钟算法。

9. 边沿触发和水平触发#

  • 边沿触发:状态变化时通知一次;
  • 水平触发:只要就绪就通知。

数据库#

1. 事务#

事务是一组要么全部成功、要么全部失败的操作。ACID:原子性、一致性、隔离性、持久性。

2. 数据库索引#

索引用于加速查询。常见结构:B+Tree、Hash。InnoDB 使用聚簇索引,MyISAM 使用非聚簇索引。最左前缀原则适用于联合索引。

3. Redis 原理#

Redis 是内存 key-value 数据库,支持字符串、哈希、列表、集合、有序集合等。特点:速度快、支持持久化、主从复制、分片。缺点:容量受内存限制,在线扩容复杂。

4. 乐观锁和悲观锁#

  • 悲观锁:假设会冲突,先加锁;
  • 乐观锁:假设不会冲突,提交时检查版本。

5. MVCC#

多版本并发控制。InnoDB 每行有创建版本和删除版本。读操作读取符合版本的快照,实现非阻塞读。写操作递增版本号,旧数据由 purge 线程清理。

6. MyISAM 和 InnoDB#

  • MyISAM:表锁,读多写少,COUNT(*) 快,不支持事务;
  • InnoDB:行锁,支持事务、外键,写并发更好。

网络#

1. 三次握手#

  1. 客户端发送 SYN;
  2. 服务器回复 SYN+ACK;
  3. 客户端发送 ACK。

2. 四次挥手#

  1. 主动关闭方发送 FIN;
  2. 被动方回复 ACK;
  3. 被动方发送 FIN;
  4. 主动方回复 ACK,进入 TIME_WAIT,等待 2MSL。

3. ARP 协议#

根据 IP 地址查询 MAC 地址。IPv6 中使用 NDP。

4. urllib 和 urllib2 的区别#

这是 Python 2 的概念。Python 3 中统一为 urllib.request、urllib.parse、urllib.error。

5. Post 和 Get#

  • GET:获取资源,参数在 URL,幂等;
  • POST:提交数据,参数在请求体,非幂等。
  • Cookie 存客户端,不安全;
  • Session 存服务器端,通常依赖 Cookie 保存 Session ID。

7. Apache 和 Nginx 的区别#

  • Nginx:轻量、异步非阻塞、高并发、配置简洁;
  • Apache:模块多、rewrite 强大、稳定,但高并发下资源消耗较高。

8. 网站用户密码保存#

推荐使用 bcrypt、argon2 等加盐哈希,不要明文保存,也不要只用 MD5。

9. HTTP 和 HTTPS#

状态码:

  • 1xx 信息
  • 2xx 成功
  • 3xx 重定向
  • 4xx 客户端错误
  • 5xx 服务器错误

HTTPS 使用 TLS/SSL,结合对称加密和非对称加密。

10. XSRF 和 XSS#

  • CSRF:跨站请求伪造,重点在请求;
  • XSS:跨站脚本攻击,重点在脚本。

11. 幂等#

幂等指一次和多次请求产生相同副作用。GET、PUT、DELETE 通常幂等,POST 不幂等。

12. RESTful 架构#

以资源为中心,使用 HTTP 方法表达操作。RPC -> SOAP -> RESTful 是常见演进路径。

13. SOAP#

基于 XML 的 Web 服务协议,较重。

14. RPC#

远程过程调用,像调用本地函数一样调用远程服务。

15. CGI 和 WSGI#

  • CGI:通用网关接口;
  • WSGI:Python Web 服务器和应用程序之间的接口规范。

16. 中间人攻击#

攻击者在通信两端之间分别建立连接,窃取或篡改数据。

17. c10k 问题#

服务器同时支持上万个连接的问题。解决思路:I/O 多路复用、异步、协程等。

18. socket#

Socket = IP 地址 + 协议 + 端口。

19. 浏览器缓存#

通过 Cache-Control、ETag、Last-Modified 等控制。304 Not Modified 表示缓存有效。

20. HTTP 1.0 和 HTTP 1.1#

HTTP/1.1 引入:

  • Host 头;
  • 长连接;
  • 断点续传;
  • 缓存和身份认证改进。

HTTP 方法:GET、HEAD、POST、PUT、DELETE、CONNECT、OPTIONS、TRACE、PATCH。

21. Ajax#

异步 JavaScript 和 XML,用于不刷新页面更新部分内容。现代常用 Fetch API 或 Axios。


*NIX#

下面是在上一版基础上,为每种 IPC 方式补充了更具体的使用场景的完整版本。你可以直接替换原文档中的“Unix 进程间通信方式(IPC)”一节。


Unix 进程间通信方式(IPC)#

进程间通信(Inter-Process Communication,IPC)指不同进程之间交换数据或同步动作的机制。Unix/Linux 提供了多种 IPC 方式,按用途大致可分为三类:

  • 数据传输类:管道、命名管道、消息队列、套接字;
  • 共享存储类:共享内存、内存映射;
  • 同步控制类:信号、信号量。 下面逐一说明

1. 管道(Pipe)#

  • 定义:匿名管道,由 pipe() 创建,返回两个文件描述符:一个读端、一个写端。
  • 特点:
    • 半双工,数据只能单向流动;
    • 只能用于具有亲缘关系的进程(父子、兄弟);
    • 基于字节流,没有消息边界;
    • 生命周期随进程,进程退出后自动消失;
    • 读写默认阻塞,缓冲区满时写阻塞,空时读阻塞。
  • 系统调用:pipe()、pipe2()。

典型使用场景:

  • Shell 命令管道:ls | grep .py、ps aux | sort -k 3 -nr | head。
  • 父子进程协作:父进程写数据,子进程读数据并处理。
  • 简单日志传递:一个进程产生日志,另一个进程负责写入文件。
  • 数据处理流水线:多个进程串行处理同一批数据。
int fd[2];
pipe(fd);
if (fork() == 0) {
    close(fd[0]);
    write(fd[1], "hello", 5);
} else {
    close(fd[1]);
    char buf[10];
    read(fd[0], buf, 5);
}

2. 命名管道(Named Pipe / FIFO)#

  • 定义:有名字的管道,在文件系统中表现为特殊文件,通过 mkfifo() 创建。
  • 特点:
    • 克服匿名管道只能用于亲缘进程的限制;
    • 无关进程也可通过打开同一个 FIFO 文件通信;
    • 仍然是半双工、字节流;
    • 打开 FIFO 时通常会阻塞,直到另一端也被打开。
  • 系统调用:mkfifo()、open()、read()、write()。

典型使用场景:

  • 不相关进程间通信:如监控进程和日志进程。
  • 简单的客户端-服务器模型:客户端写请求,服务器读请求。
  • Shell 脚本间传递数据:mkfifo /tmp/f; echo "data" > /tmp/f & cat /tmp/f。
  • 替代临时文件:避免磁盘 I/O,提高效率。
mkfifo /tmp/myfifo
echo "hello" > /tmp/myfifo &
cat /tmp/myfifo

3. 信号(Signal)#

  • 定义:异步通知机制,用于通知进程发生了某个事件。
  • 特点:
    • 信息量极少,通常只传信号编号;
    • 不携带数据,只表示“某事发生”;
    • 可靠信号(实时信号)支持排队,不可靠信号可能丢失;
    • 进程可选择忽略、捕获或使用默认处理。
  • 常用信号:SIGINT、SIGTERM、SIGKILL、SIGUSR1、SIGUSR2。
  • 系统调用:kill()、raise()、signal()、sigaction()、sigqueue()。

典型使用场景:

  • 终止/中断进程:Ctrl+C 发送 SIGINT,kill -9 发送 SIGKILL。
  • 配置热重载:如 nginx 收到 SIGHUP 后重新加载配置。
  • 父子进程通知:子进程退出时向父进程发送 SIGCHLD。
  • 自定义事件:进程间用 SIGUSR1、SIGUSR2 传递简单通知。
  • 超时/定时提醒:alarm() 触发 SIGALRM。
void handler(int sig) {
    printf("received signal %d\n", sig);
}
signal(SIGUSR1, handler);
kill(getpid(), SIGUSR1);

4. 消息队列(Message Queue)#

  • 定义:内核维护的消息链表,进程可发送和接收消息。
  • 特点:
    • 有消息边界,按类型或优先级读取;
    • 支持多进程读写;
    • 生命周期随内核,除非显式删除或系统重启;
    • 分为 System V 和 POSIX 两种。
  • System V 系统调用:msgget()、msgsnd()、msgrcv()、msgctl()。
  • POSIX 接口:mq_open()、mq_send()、mq_receive()、mq_close()、mq_unlink()。

典型使用场景:

  • 异步任务分发:生产者投递任务,多个消费者按类型领取。
  • 多进程日志收集:各进程写入同一消息队列,日志进程统一处理。
  • 模块解耦:不同模块通过消息队列通信,避免直接依赖。
  • 优先级消息:紧急消息优先处理,如告警系统。
// System V 示例
int msqid = msgget(IPC_PRIVATE, 0666 | IPC_CREAT);
msgsnd(msqid, &msg, size, 0);
msgrcv(msqid, &msg, size, type, 0);

5. 共享内存(Shared Memory)#

  • 定义:多个进程将同一块物理内存映射到各自地址空间,直接读写。
  • 特点:
    • 最快的 IPC 方式,无需用户态和内核态之间的数据拷贝;
    • 需配合同步机制(信号量、互斥锁)防止竞态;
    • 生命周期随内核,需显式删除;
    • 分为 System V 和 POSIX 共享内存。
  • System V 系统调用:shmget()、shmat()、shmdt()、shmctl()。
  • POSIX 接口:shm_open()、mmap()、munmap()、shm_unlink()。

典型使用场景:

  • 高性能数据交换:实时系统、金融交易、游戏服务器。
  • 大规模共享缓存:多个进程共享同一份数据,避免重复加载。
  • 数据库缓冲区:PostgreSQL、Redis 等使用共享内存做缓存。
  • 视频/图像处理:多进程共享帧数据,减少拷贝开销。
  • 科学计算:并行计算中共享中间结果。
int shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT | 0666);
void *ptr = shmat(shmid, NULL, 0);
strcpy(ptr, "hello");
shmdt(ptr);

6. 内存映射(Memory-mapped I/O / mmap)#

  • 定义:将文件或匿名内存区域映射到进程地址空间,进程可像访问内存一样访问文件。
  • 特点:
    • 可用于文件映射和匿名映射;
    • 匿名映射可用于亲缘进程间共享内存;
    • 文件映射可用于无关进程通过同一文件共享数据;
    • 支持写时复制(COW);
    • 常与 mmap()、munmap()、msync() 配合。
  • 系统调用:mmap()、munmap()、msync()。

典型使用场景:

  • 大文件读写:避免 read/write 的系统调用开销,如数据库、日志系统。
  • 动态库加载:操作系统加载 .so 文件时使用 mmap。
  • 进程间共享内存:MAP_SHARED | MAP_ANONYMOUS 实现父子进程共享。
  • 内存映射文件:多个进程映射同一文件,实现数据共享。
  • 零拷贝 I/O:网络传输、文件服务器中减少数据拷贝。
int fd = open("file", O_RDWR);
void *addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

7. 信号量(Semaphore)#

  • 定义:用于进程间或线程间同步的计数器,常用于保护共享资源。
  • 特点:
    • 本身不传递数据,只用于同步和互斥;
    • 分为 System V 和 POSIX 信号量;
    • POSIX 信号量又分命名和匿名;
    • 支持 P 操作(wait)和 V 操作(post)。
  • System V 系统调用:semget()、semop()、semctl()。
  • POSIX 接口:sem_init()、sem_wait()、sem_post()、sem_destroy()、sem_open()。

典型使用场景:

  • 保护共享内存:多个进程访问同一块共享内存时,用信号量互斥。
  • 生产者-消费者模型:缓冲区满/空时通过信号量阻塞和唤醒。
  • 资源计数:限制同时访问某资源的进程数量,如连接池、线程池。
  • 读写锁:通过信号量实现读写优先级控制。
  • 进程同步:确保多个进程按特定顺序执行。
sem_t sem;
sem_init(&sem, 1, 1);
sem_wait(&sem);
// 临界区
sem_post(&sem);
sem_destroy(&sem);

8. 套接字(Socket)#

  • 定义:通用的网络通信接口,也可用于本机进程间通信。
  • 特点:
    • 支持全双工通信;
    • 可用于不同主机之间的进程通信;
    • Unix 域套接字(AF_UNIX)用于本机,性能高于 TCP/IP;
    • 支持流式(SOCK_STREAM)和数据报(SOCK_DGRAM);
    • Unix 域套接字可传递文件描述符。
  • 系统调用:socket()、bind()、listen()、accept()、connect()、send()、recv()。

典型使用场景:

  • 网络服务:Web 服务器、数据库、消息队列等。
  • 本机高性能 IPC:Docker、systemd、X11 使用 Unix 域套接字。
  • 跨主机通信:微服务、分布式系统、RPC。
  • 文件描述符传递:Unix 域套接字可在进程间传递打开的 fd。
  • 实时通信:游戏、聊天、推送服务。
int sock = socket(AF_UNIX, SOCK_STREAM, 0);
struct sockaddr_un addr;
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, "/tmp/mysock");
bind(sock, (struct sockaddr*)&addr, sizeof(addr));

IPC 方式对比#

方式是否跨主机是否亲缘限制数据边界速度典型用途
管道否是字节流中父子进程简单通信
命名管道否否字节流中无关进程简单通信
信号否否无快事件通知
消息队列否否有中结构化消息
共享内存否否无最快高性能数据共享
内存映射否否无快文件共享、大内存
信号量否否无快同步互斥
套接字是否流/报文中网络、本机通用

如何选择 IPC 方式#

  • 只需要通知事件:用信号。
  • 父子进程简单传数据:用管道。
  • 无关进程简单传数据:用命名管道。
  • 需要结构化消息、异步处理:用消息队列。
  • 追求极致性能、大数据共享:用共享内存 + 信号量。
  • 需要文件共享、零拷贝:用内存映射。
  • 需要跨主机通信:用套接字。
  • 本机高性能、全双工:用 Unix 域套接字。

补充:现代 Linux 新增的 IPC 机制#

除了传统方式,Linux 还提供了一些更轻量、更高效的 IPC 机制:

  • eventfd:用于事件通知,常与 epoll 配合;
  • signalfd:将信号转换为文件描述符,便于统一事件循环;
  • timerfd:定时器通知;
  • memfd_create:创建匿名内存文件,可用于进程间共享内存;
  • io_uring:高性能异步 I/O 接口,也可用于进程间通信。

这些机制在高性能服务器、容器、微服务中越来越常见。


数据结构#

红黑树#

红黑树是非严格平衡二叉搜索树,增删旋转次数比 AVL 少。搜索多、增删少用 AVL;搜索和增删均衡用红黑树。


编程题#

1. 台阶问题 / 斐波那契#

def fib(n):
    a, b = 0, 1
    for _ in range(n):
        a, b = b, a + b
    return b

2. 变态台阶问题#

def fib(n):
    return n if n < 2 else 2 * fib(n - 1)

3. 矩形覆盖#

def cover(n):
    return 1 if n < 2 else cover(n - 1) + cover(n - 2)

4. 杨氏矩阵查找#

def find(matrix, target):
    if not matrix:
        return False
    rows, cols = len(matrix), len(matrix[0])
    r, c = 0, cols - 1
    while r < rows and c >= 0:
        val = matrix[r][c]
        if val == target:
            return True
        elif val > target:
            c -= 1
        else:
            r += 1
    return False

5. 去除列表中的重复元素#

def dedup(lst):
    return list(dict.fromkeys(lst))

6. 链表成对调换#

class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None

def swap_pairs(head):
    if head and head.next:
        nxt = head.next
        head.next = swap_pairs(nxt.next)
        nxt.next = head
        return nxt
    return head

7. 创建字典的方法#

d1 = {'name': 'earth', 'port': '80'}
d2 = dict([('name', 'earth'), ('port', '80')])
d3 = dict.fromkeys(('x', 'y'), -1)

8. 合并两个有序列表#

def merge_sorted(a, b):
    res = []
    i = j = 0
    while i < len(a) and j < len(b):
        if a[i] <= b[j]:
            res.append(a[i])
            i += 1
        else:
            res.append(b[j])
            j += 1
    res.extend(a[i:])
    res.extend(b[j:])
    return res

9. 交叉链表求交点#

class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None

def get_intersection(headA, headB):
    if not headA or not headB:
        return None
    pA, pB = headA, headB
    while pA != pB:
        pA = pA.next if pA else headB
        pB = pB.next if pB else headA
    return pA

10. 二分查找#

def binary_search(nums, target):
    low, high = 0, len(nums) - 1
    while low <= high:
        mid = (low + high) // 2
        if nums[mid] == target:
            return mid
        elif nums[mid] < target:
            low = mid + 1
        else:
            high = mid - 1
    return -1

11. 快排#

def quicksort(nums):
    if len(nums) < 2:
        return nums
    pivot = nums[0]
    less = [x for x in nums[1:] if x <= pivot]
    greater = [x for x in nums[1:] if x > pivot]
    return quicksort(less) + [pivot] + quicksort(greater)

12. 找零问题#

def coin_change(coins, amount):
    dp = [float('inf')] * (amount + 1)
    dp[0] = 0
    for coin in coins:
        for i in range(coin, amount + 1):
            dp[i] = min(dp[i], dp[i - coin] + 1)
    return dp[amount] if dp[amount] != float('inf') else -1

13. 广度遍历和深度遍历二叉树#

class Node:
    def __init__(self, data, left=None, right=None):
        self.data = data
        self.left = left
        self.right = right

def bfs(root):
    if not root:
        return
    queue = [root]
    while queue:
        node = queue.pop(0)
        print(node.data)
        if node.left:
            queue.append(node.left)
        if node.right:
            queue.append(node.right)

def dfs(root):
    if not root:
        return
    print(root.data)
    dfs(root.left)
    dfs(root.right)

14. 前中后序遍历#

def preorder(root):
    if root:
        print(root.data)
        preorder(root.left)
        preorder(root.right)

def inorder(root):
    if root:
        inorder(root.left)
        print(root.data)
        inorder(root.right)

def postorder(root):
    if root:
        postorder(root.left)
        postorder(root.right)
        print(root.data)

15. 求最大树深#

def max_depth(root):
    if not root:
        return 0
    return max(max_depth(root.left), max_depth(root.right)) + 1

16. 求两棵树是否相同#

def is_same_tree(p, q):
    if not p and not q:
        return True
    if not p or not q:
        return False
    return p.val == q.val and is_same_tree(p.left, q.left) and is_same_tree(p.right, q.right)

17. 前序中序求后序#

def rebuild(pre, inorder):
    if not pre:
        return None
    root = Node(pre[0])
    idx = inorder.index(pre[0])
    root.left = rebuild(pre[1:idx + 1], inorder[:idx])
    root.right = rebuild(pre[idx + 1:], inorder[idx + 1:])
    return root

def postorder(root):
    if not root:
        return
    postorder(root.left)
    postorder(root.right)
    print(root.data)

18. 单链表逆置#

def reverse_list(head):
    prev = None
    cur = head
    while cur:
        nxt = cur.next
        cur.next = prev
        prev = cur
        cur = nxt
    return prev

19. 两个字符串是否是变位词#

from collections import Counter

def is_anagram(s1, s2):
    return Counter(s1) == Counter(s2)

20. 动态规划#

动态规划适用于有重叠子问题和最优子结构的问题。步骤:

  1. 定义状态;
  2. 找状态转移方程;
  3. 初始化;
  4. 确定遍历顺序;
  5. 返回结果。

常见题:背包、最长公共子序列、最长递增子序列、编辑距离等。