零.计算机系统漫游
1.程序被翻译成不同的格式
- 预处理阶段 (#include<stdio.h> 得到另一个C程序)
- 编译阶段
- 汇编阶段
- 链接阶段
2.处理器
从程序计数器PC指向的存储器读取指令,解释指令中的位,执行指令指示的简单操作,然后更新指向新程序计数器的下一条指令
3.CPU在指令的要求下可能会执行这些操作
3.上下文
操作系统保存进程运行所需的所有状态信息,这种状态就是上下文。(PC 寄存器堆当前值,以及主存的内容)
当操作系统决定从当前进程转移控制权到某个新进程时,就会进行上下文切换,即保存当前进程的上下文,恢复新进程的上下文,然后将控制权转移到新进程。
4. 虚拟存储器
九.虚拟存储器
1. 页表
将虚拟地址空间映射到物理地址空间
2. 动态存储器分配
动态存储器分配器维护着一个进程的虚拟存储器区域,成为堆。内核维护着一个变量brk,指向堆的顶部
动态存储器分配器,可以通过mmap或者munmap显示分配,还可以使用sbrk函数
void *sbrk(intptr_t incr) 将内核的brk指针增加incr来扩展或收缩堆
3.垃圾回收机制
- 标记 删除(Mark-Sweep)、
- 引用计数算法
十一.系统级I/O
1. Unix I/O
- 每个进程开始时都有三个打开的文件:标准输入 标准输出 标准错误 STDIN_FILENO STDOUT_FILENO STDERR_FILENO
- 打开文件 int open(char *filename, int flags, mode_t mode);
fd = open("foo.txt", O_CREAT|O_TRUNC|O_WRONLY, DEF_MODE);
- 读写文件
ssize_t write(int fd, const void *buf, size_t n);
- 共享文件 (内核用三种相关的数据结构来表示已经打开的文件)
- I/O重定向
2. 标准I/O
标准库I/O将一个打开的文件模型化为一个流(stream),对于程序员,一个流就是一个指向类型为FILE结构的指针
十二.网络编程
1. 因特网连接
一个连接由它两端的套接字地址唯一确定,这对套接字地址叫做套接字对(socket pair)
2. Web服务器
Web服务器以两种不同的方式向客户端提供内容:
- 取一个磁盘文件并将它的内容放回给客户端。(静态内容)
- 运行一个可执行的文件,并将它的内容返回给客户端。(动态内容)
3. HTTP请求
一个HTTP请求是这样的:一个请求行,后面跟随零个或更多个请求报头,在跟随一个空的文本行来终止报头列表
<method><uri><version>
HTTP支持许多不同的方法,包括GET POST OPTIONS HEAD PUT DELETE TRACE。
GET / HTTP/1.1
host www.***.com
4. HTTP相应
<version> <status code> <status message>
十三.并发编程
控制逻辑流在时间上重叠,就是并发
1. 基于进程的并发服务器
void sigchld_hander(int sig) {
while (waitpid(-1, 0, WNOHANG) > 0) ;
return;
}
signal(SIGCHLD, sigchld_handler);
if (fork() == 0) {
close(listenfd);
...........
close(connfd);
exit(0);
}
2. 基于I/O多路复用的并发编程
使用seliect,使内核挂起进程,只有在一个或多个I/O事件发生后,才将控制返回给应用程序。 select处理类型为fd_set的集合(描述符集合),n位的掩码
3. 基于线程的并发编程
每个线程都有自己的线程上下文(线程ID, 栈,栈指针,程序计数器,通用目的寄存器,条件码),所有进程共享进程的整个虚拟地址空间,代码,数据,堆,共享库和打开的文件
(1). 线程执行模型
2. 分离线程
一个可结合的线程能够被其他线程收回资源和杀死,在被其他线程回收之前,它的存储器资源是不释放的。
一个分离的线程是不能被其他线程回收或杀死,它的存储器资源在它终止时由系统自动释放
int pthread_detach(pthread_t tid);
- 取一个磁盘文件并将它的内容放回给客户端。(静态内容)
- 运行一个可执行的文件,并将它的内容返回给客户端。(动态内容)
3. 初始化线程
pthread_once_t once_control = PTHREAD_ONCE_INIT;
int pthread_once(pthread_once_t *once_control, void (*init_routine)(void));
2. Posix信号量
#include <semaphore.h>
int sem_init(sem_t *sem, unsigned int value);
int sem_wait(sem_t *s); //P(s)
int sem_post(sem_t *s) //V(s)