muduo
线程安全的对象生命周期管理析构函数&多线程多线程共享对象,对象的线程安全特性可以由对象内的同步原语保护。但是对象的析构没法通过内部的同步原语保护。(猜测要通过外部的同步原语保护)
比如如何保证在执行成员函数期间,对象不会被其他线程析构。
线程安全线程安全的类满足如下三个条件:
多线程可以同时访问,表现正常。
无论这些线程的执行顺序如何交织。
调用端无需同步操作。
C++大部分类,string,vector都不是线程安全的,也可以理解,毕竟需要线程安全的时间也不多,没必要增加额外的开销。
对象构造&线程安全如何保证对象构造的线程安全:在构造期间不要泄露this指针。
可以使用两段式构造。
对象销毁&线程安全很难解决的问题。文章从面对对象程序设计的角度提出了一些问题。
对象的关系包括三种:
composition(组合):如struct A{struct B b;};b的生命周期由A决定,A对象被析构时,b也被析构。
association(关联):在形式上与下面一条很类似,生命周期独立。
aggregation(聚合):如stru ...
xv6
操作系统接口文件描述符每个进程有一个私有的文件描述符表,这是shell可以执行IO重定向以及管道的基础。
每个文件描述符都有一个与文件关联的偏移。
fork后,子进程拥有和父进程一致的文件描述符表,再次执行exec后,也仍然会保留该文件描述符表(除了使用closeonexec选项)。这允许了IO重定向,使得不同的进程可以访问相同的文件描述符。比如cat的实现:cat < input.txt
12345678char *argv[2];argv[0] = "cat";argv[1] = 0;if(fork() == 0) { close(0); open("input.txt", O_RDONLY); exec("cat", argv);}
open默认返回最小未使用的文件描述符:0。
为什么不直接给一个创建新进程的接口,而是分为先fork,再exec,因为这样创建的子进程在fork之后exec之前,还有一段时间,这里可以执行一些任务,比如可以修改文件描述符。(其实exec执行的 ...
Linux高性能服务器编程
1-4章又介绍了TCP/IP协议
TCP/IP协议簇
上面这图很具有误导性,比如ICMP是作为数据封装到IP内,但把他们画到同一层。ARP是作为数据封装到数据链路(比如以太网帧)内,但把他们画到同一层
TCP: 可靠的、面向连接的、基于流的。
UDP: 不可靠、无连接、基于数据报的。
封装&分用:分用指的解析本层书籍,将处理后的数据往上层传。
复位报文段产生复位报文段的三种情况:
访问不存在的端口访问不存在的端口或者该端口处于TIME_WAIT状态,客户端会收到复位报文段。
异常终止连接TCP提供了异常终止一个连接的方式,即向对方发送一个复位报文段。对方收到后,会丢弃所有排队等待发送的数据。
处理半打开连接比如服务端和客户端已经连接上,但是服务端网线被拔了,重新接上后。只有客户端维护着连接,当他往管道写入数据时,会受到一个复位报文段。
TCP交互数据流TCP连接的应用数据分为两类:交互数据和成块数据。
比如通telnet访问服务器,会经过如下过程
每键入一个字符,会将该字符用TCP包发给服务器,服务器回发了确认消息以及数据,客户端立刻回发确认消 ...
图解HTTP
。
实体主体:应该是未压缩时的数据
报文主体:应该是压缩后的数据,
多部分对象集合描述数据类型时,使用multipart格式。
multipart/form-data 在 Web 表单文件上传时使用。
multipart/byteranges 状态码 206(Partial Content,部分内容)响应报文包含了多个范 围的内容时使用。
状态码200表示从客户端发来的请求在服务器端被正常处理了。
204该状态码代表服务器接收的请求已成功处理,但在返回的响应报文中 不含实体的主体部分。
206该状态码表示客户端进行了范围请求,而服务器成功执行了这部分的 GET 请求。响应报文中包含由 Content-Range 指定范围的实体内容。
3XX 重定向3XX 响应结果表明浏览器需要执行某些特殊的处理以正确处理请 求。
301 Moved Permanently永久性重定向。该状态码表示请求的资源已被分配了新的 URI,以后 应使用资源现在所指的 URI。
302 Found和 301 Moved Permanently 状态码相似,但 302 ...
自顶向下方法
计算机网络与因特网应用层安全套接字层(SSL),位于应用层,可以对数据加密。
网络应用:Web应用,电子邮件应用
应用层协议:HTTP, SMTP
本章讨论物种应用:Web、文件传输、电子邮件、目录服务、流式视频与P2P。
DNS
递归查询
将任务交给一个DNS服务器就不管了,最终会得到查询的结果。
迭代查询
将任务交给一个DNS服务器后,DNS服务器会返回新的DNS服务器,这些需要本机自己去查。
查询通常遵 循图2-18 中的模式: 从请求主机到本地 DNS 服务器的查询是递归的、其余的查询 根DNS服务器是迭代的。1,8是递归的,其他是迭代的
运输层UDP
长度 ,首部+数据
校验和,对所有16比特数据进行求和、回卷、反码计算。
可靠传输基于完全可行信道传输rdt1.0不用担心差错随便发
基于有比特差错信道的可靠数据传输(信道上发送的包某些位可能改变,但信道不会有其他问题,比如丢包等)rdt2.0接收方通过ACK和NAK来确认,有NAK就会重传。
本协议基本可行,但有一个缺陷:数据发送方收到了出错的ACK和NAK包怎么办,数据发送方当然可以重发前一个包,但发 ...
程序员的自我修养-第十一章
运行库
入口函数和程序初始化程序从main开始吗
程序员的自我修养-第十章
内存
程序的内存布局
栈与调用惯例什么是栈
栈会保存一个函数调用所需要的维护信息(又名堆栈帧或活动记录),它包含:
函数的返回地址和参数
临时变量
保存的上下文(应该是自己的上下文,而不是调用自己的函数的上下文吧)
活动记录由ebp和esp这两个寄存器来划分范围。
感觉上图ebp的位置有一点问题,应该指向old ebp才对,看下面的i386函数体开头
之所以活动记录是这样的,是因为函数调用本身就是这么设计的:
i386下的函数调用:
把所有或一部分参数压入栈中,如果有其他参数没有入栈,那么使用某些特定的寄存器传递。
把当前指令的下一条指令的地址压入栈中。
跳转到函数体执行。
i386下的函数体开头
push ebp:把 ebp 压入栈中(称为 old ebp)。
mov ebp, esp:ebp = esp(这时 ebp 指向栈顶,而此时栈顶就是 old ebp)。
【可选】sub esp, XXX:在栈上分配 XXX 字节的临时空间。
【可选】push XXX:如有必要,保存名为 XXX 寄存器(可重复多个)。
函数返回的标准结尾
【可 ...
linux内核设计与实现
内核简介单内核&微内核单内核:作为一个单独的大过程运行,运行在单独的地址空间上(不就是单个进程吗?),内核之间的通信很方便。
微内核:内核的功能被划分为多个单独的过程,每一个过程叫做一个服务器,某些服务器运行在用户空间,有些运行在内核空间中,所以不同服务器之间的通过消息传递机制通信:系统采用了IPC机制。但是,IPC特别消耗资源,所以现在的微内核的服务器都运行在内核空间上,可以直接进行通信。
Linux内核的特点
可以动态加载内核模块
支持SMP机制,
内核可以抢占,在内核的任务优先执行
对线程的支持,内核不区分线程、进程,只是有些共享资源而已
进程管理进程描述符与任务结构内核将进程的列表存放在叫任务队列的双向循环链表中,链表的每一项都是类型为task_struct的进程描述符的东西(ucos的TCB)。他其中包含的内容有:打开的文件、地址空间、挂起的信号等。
分配进程描述符在内核栈的尾端会存放任务的thread_info, 他其中会包含指向进程描述符的指针:
进程描述符的存放进程描述符中的state描述了当前的状态,包含如下五个:
运行:可执行的;要么正在执行,要么在 ...
操作系统-精髓与设计原理
概述指令的执行最简单指令处理包含两步:读取执行、执行指令。PC保存下一次要取的指令地址。取到的指令放到IR中。指令执行的动作分为四类:
从处理器到存储器传数据
从处理器到IO传数据
处理数据,加减
控制,指定下一次指令从某个地方读取
中断中断和指令周期
长IO等待:IO程序执行的时间太长,导致新WRITE调用来了,旧的WRITE操作还没有完全完成,所有新WRITE操作必须阻塞,等到第一次WRITE完成才行。
对于右侧的长IO等待,在IO操作未完成时,与用户指令的执行有重叠,正是这部分指令导致了效率的提高。
中断处理中断激活了很多事件,包括处理器硬件的事件和软件的事件(要注意那些是硬件完成的,哪些是软件完成的,廖总经常强调的)。
多个中断一种是在中断运行时禁止其他中断,只有当处理器完成当前中断时,才由处理器检查是否有中断。
另一种是定义中断优先级,允许高优先级打断低优先级中断。
存储器的层次结构存储器的目标可以归纳为三个问题:多大容量,多快速度,多贵价格。
通常既需要快速的又需要大容量的存储器。这不能使用单一存储器来实现,而是使用存储器层次结构。
访问的局 ...