linux系统编程最佳实践

最佳实践 - 线程

  1. 多线程程序中避免使用信号

线程同步问题 - 线程安全问题

  1. mutex + cond
  2. __thread

最佳实践 - 用户空间

文件io

glibc

特殊进程:timer

进程的生命周期

生命阶段
fork exec
繁殖
exit
抚养 waitpid

fork = mmap sbrk

IPC首选socket TCP - 可移植性和可靠性

进程内同步 - 信号屏蔽signalpending

各个线程的上下文,信号处理上下文。在各个上下文中可能访问 同一地址:需要保护

线程间的同步:mutex + cond

线程和信号处理间的同步:sigsuspend

共享方式 - 共享资源 同步方式
多线程共享 mutex + cond
进程的 正常控制流和 异常控制流(信号处理控制流) sigproc

进程的异常控制流 - 信号处理函数 - 多进程少用,信号不好处理

多进程和多线程 要处理和注意的东西太多了,少用,尽量少在里面处理太多

最佳实践 - 內核空间

  1. 内核同步。spin_lock, mutex
  2. 内核活动:线程、workqueue。首选workqueue
  3. 内存映射 mmap
  4. 异常控制流:上下半部

内核中,代码的几种实例(线程)化方式 首选workqueue

  1. 中断上下文。中断栈
    1. 硬中断上下文
    2. 软中断上下文
  2. 进程上下文。进程栈
    1. 内核线程。workqueue 是一种简化方便使用的内核线程,网卡驱动都是用这个。
    2. 正常进程。

内核空间和用户空间 同步的几种方式:阻塞和非阻塞

多核并行编程模型。首选 pthread + mutex + cond。

少用信号等其他IPC啥的,那些玩意只适合以前的单进程玩玩而已

内核同步

共享方式 - 共享资源 同步方式 - 实现互斥访问
进程 中断 争用 spin_lock spin_lock_bh
进程间 争用 mutex

琐碎

最好都是 多线程+mutex的编程模式。

内存屏障; 一定程度上相当于 内存访问操作的同步

同步的话,是针对一个动作来同步,针对一个访问动作来同步。发起动作的主体间 要做好协调同步。

如果针对的动作主体是 cpu指令。 那就是内存屏障同步。对图灵机来说,内存 就是共享内存。

如果动作主体是 进程,那需要 进程同步,首选 mutex + condition var

不同cpu间的cache同步,由硬件来支持了。

内存屏障

内存屏障的起因 就是 编译器和cpu 乱序执行 对 IO操作影响很大。

对IO影响的几个点。io的特点,要从源头去读写数据(内存地址)。

优化时机 读错位置 应对 啰嗦几句
编译时 寄存器 volatile var 从内存去取变量,而不是cpu寄存器,因为我们是io操作,内存上的变量可能已经发生变化了(操作者非本cpu,所以本cpu无法感知到,也就 优化上时出现信息盲区。)
运行时 cache cpu指令。可封装在mb() cpu去cache读变量,而不是内存,因为我们是io操作,内存上的变量可能已经被硬件设备给修改(能通过内存总线访问内存的设备,这是cpu无法感知的,这导致cpu在信息不全的情况下,做出优化,这是需要人工干预下。)
解除优化 mb 全能型。相当于 volatile + cpu屏障指令。 mb 禁止 从寄存器去读,要从源头去读

强制 刷新 读写的cache

asm volatile ("" ::: "memory");    # 編譯器标记这个变量在 内存地址空间

volatile,编译器 不要把变量从 临时的寄存器里 读取,而要从内存去读取。

volatile 只是一种声明而已,加入一个声明标记之后,编译器在编译时 会有所处理

内核抢占

preempt_count_equals用来判断是否在spinlock保护的区间里

irqs_disabled判断当前中断是否开启,即是否在中断上下文

ref: - https://www.yuanguohuo.com/2020/03/31/linux-preemption-mode/

你可能感兴趣的:(linux,运维,服务器)