随笔-系统编程-《Linux 环境高级编程》

https://courses.fmsoft.cn/aple

目录

一、内存管理

虚拟内存原理

  • MMU和页表
  • 页表:逻辑地址到物理地址的映射表,每个进程一个,也要占用内存空间

C/C++程序的堆/栈管理

API

常见:

  • C: malloc/calloc/realloc/free C++: new/delete

不常见:

  • alloca,VLA
  • posix_memalign/aligned_alloc
  • brk/sbrk
  • etext/edata/end

C/C++进程的内存布局

  • command-line arg and env var
  • stack/stack frame
  • ...
  • heap
  • uninitialized data segment (BSS, block started by symbol)
  • initialized data segment
  • text segment

常用工具

  • nm (name list, symbol table)
  • strings
  • size
  • readelf
  • objdump

其他分配内存的方法

  • 匿名内存映射 mmap()
  • memfd:memfd_create() # 可用来作为进程通信的手段
  • 问题:大块连续的虚拟内存,对应物理内存是否连续? 不一定连续,一般是不连续的

常⻅内存使用问题

  • 不对⻬访问(unaligned access)
  • 访问了不可访问的地址 # 越界访问或非法指针
  • OOM # 内存泄露 最终被系统kill掉
  • ...

二、文件和文件系统

STDIO vs 传统文件读写系统调用

问题:STDIO接口的主要功能有哪些?

fread/fwrite、sprintf/snprintf、scanf/sscanf、...

问题:读写文件时应使用 STDIO 还是系 统调用,哪个效率高?

A:STDIO 带有缓冲,如果read会多读

STDIO 的缓冲模式

默认行缓冲、可以设置无缓冲、块缓冲、完全缓冲

改变缓冲模式:setvbuf()/setbuf()/setbuffer()/setlinebuf()

问题:键盘上的输入何时才能被程序获得?

键盘产生中断,内核先处理,内核支持行编辑(输入、delete删除、回车),并在程序界面上显示你的输入,上层应用程序主动调相关接口才能获取到

基本的文件读写系统调用

creat()/open()、read()/write()、lseek()、close()、fcntl()

FILE 和 fd 互操作

  • fdopen():已知文件描述符创建流对象
  • fileno():已知流对象获取对应文件描述符

鲜为人知的STDIO接口

  • fmemopen():将内存区域抽象为流对象
  • freopen():关闭一个流对象并使用新模式打开
  • funopen():自定义流对象
  • fropen():自定义只读流对象
  • fwopen():自定义只写流对象

问题:fflush()/fpurge() 和 fsync() 有何区别?

stdio buffer:用户空间的东西,内核不知道,这个东西是为了减少系统调用的次数

内核也有自己的一个buffer cache,这个东西是为了减少读写磁盘

fflush是将用户空间buffer的内容刷到内核缓冲区

fsync行参是fd,是将内核空间的buffer cache刷到磁盘

文件描述符

文件共享、重定向及文件锁

父子进程共享所有数据和代码,也共享文件描述符

  • colse-on-exe 标志的重要性
  • 问题:fork() 的资源成本有多大?

通过 UNIX domain socket 发送文件描述符

  • 分配并共享大块内存

memfd_create() -> sendmsg() -> mmap()

重定向的实现

dup2()

文件锁

  • flock() 仅用于父子进程之间,且只是建议锁(advisory lock)
  • flock() 的锁粒度太大(整个文件)
  • fcntl()/lockf() 可实现强制锁(mandatory lock) 且可以只限定某一区域
  • 为什么方同学的代码没有出现写入混乱?

讨论:内核中打开的文件是以进程为单位维护还是全局的?

以进程为单位

文件系统操作

常用接口:

  • STDC: fopen(), remove(), rename()
  • POSIX: creat(), unlink(),rmdir(), renameat(), mkdir(), ...
  • 遍历目录项:opendir(), closedir(), readdir(), rewinddir(), scandir(), seekdir(), telldir(), ...
  • 文件属性:chmod(), chown(), stat(), umask(),
  • ...

三、信号和进程管理

四、进程间通讯

五、并发编程-多线程编程

并发编程:在同一时刻允许多个任务同时执行的编程方法

常⻅的并发编程模型

  • 单任务 IO 多路复用 (select/poll/epoll 在一个线程中管理多个fd的技术)
  • 事件驱动+回调函数 (select/poll/epoll 返回不同事件,不同事件调用不同的回调函数)
  • 多进程
  • 多线程
  • 多协程

多线程编程概要

  • 线程和进程的区别以及多线程带来的好处
  • 多线程编程接口:
    • POSIX Thread:<pthread.h>
    • C99:<thread.h>
  • 多线程同步机制:
    • 线程本身
    • 互斥量(mutex)、读写锁(read/write lock) 条件变量(condition variable)
    • 信号量(semaphore)
    • 其他 Linux 内核机制:文件锁、eventfd、System V 信号量等
  • 特有机制:单次函数、线程本地存储(TLS)

六、并发编程-多进程编程 - 略 多进程比较重,用得比较少

七、网络编程

套接字操作接口

#include <sys/types.h> /* See NOTES */ 
#include <sys/socket.h>

int socket(int domain, int type, int protocol); 
int bind(int sockfd, const struct sockaddr *addr, 
            socklen_t addrlen);
int listen(int sockfd, int backlog);
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); 
int connect(int sockfd, const struct sockaddr *addr,
                socklen_t addrlen);
  • 服务器进程调用 socket() 建立流套接字,获得流套接字文件描述符。
  • 服务器进程调用 bind() 函数将给定的套接字文件名称和文件描述符绑定在一起。
  • 服务器进程调用 listen() 函数在该文件描述符上监听连接请求。
  • 客户进程调用 socket() 建立流套接字,获得流套接字文件描述符。
  • 客户进程调用 bind() 函数将给定的套接字文件名称和文件描述符绑定在一起。
  • 客户进程调用connect() 将自己的流套接字文件描述符连接到服务器的套接字文件上。
  • 服务器收到该连接请求,调用 accept() 函数接受请求。该函数的返回一个新的文件描述符,该描述符就是流套接字在服 务器端的读写描述符。
  • 服务器接受连接请求之后,客户的connect() 函数返回。客户可以用先前建立的流套接字描述符来和服务器通讯了。

套接字的域、类型和协议

  • 常用套接字域(domain)

    • AF_UNIX/AF_LOCAL:UNIX域套接字
    • AF_INET:IPv4
    • AF_INET6:IPv6
    • AF_NETLINK:Linux netlink
  • 常用套接字类型(type)

    • SOCK_STREAM:流
    • SOCK_DGRAM:数据报
    • SOCK_RAW:裸网络协议访问
  • 套接字协议(protocol): ip, ipv6, tcp, udp 等;通常取 0。已知协议⻅:/etc/ protocols

套接字地址

struct sockaddr {
  sa_family_t sa_family;
  char sa_data[14];
}

这个结构只是一个别名。 不同的套接字域有不同的结构定义。 使用时需要强制做指针的强制类型转换。

套接字地址(AF_UNIX)/套接字地址(AF_INET)/套接字地址(AF_INET6)

套接字选项

网络地址转换

网络地址转换(IPv4专用)

字节序转换

网络接口枚举

八、高级输入输出

定位读写

多缓冲区/向量读写

在文件间快速传输或复制数据

异步和非阻塞读写

IO多路复用

九、沙箱、容器及其背后的技术 - TODO 用得比较少

十、性能分析及调试工具 - 略 自己本身比较熟悉

posted @ 2024-05-25 19:20  LiYanbin  阅读(4)  评论(0编辑  收藏  举报