GithubHelp home page GithubHelp logo

king-blog's People

Contributors

king-etc avatar

Stargazers

 avatar  avatar

Watchers

 avatar

king-blog's Issues

std::thread 详解

thread 构造方式

  • 默认构造
    std::thread T1;
  • 初始化构造函数
    std::thread T2(func,args...)
  • 深拷贝构造函数
    std::thread T3(T2) 注意 被标注delete 应舍弃
  • Move 构造函数
    std::thread T4(std::move(T2)) 注意 std::move之后 并不存在实例化之后的T2了,类似于
    std::string a="Example;"
    std:string b(std::move(a));
    此时 a等同于string a

赋值操作

  • std::move 赋值操作
    std::thread T5 = std::thread(func,args)
  • 深拷贝赋值操作
    std::thread T6 = T5 注意 被标注delete 应舍弃
函数名 功能 返回值
get_id() 获取线程ID std::thread::id
join() 阻塞当前线程直到调用的线程执行完毕 void
joinable() 检查线程是否可被join bool
detach() 使该线程与当前线程分离单独运行 void
swap() 交换线程对象所代表的底层句柄 void
native_handle() 返回线程句柄 native_handle_type
hardware_concurrency 当前平台所支持的并发数目 static unsigned int

this_thread

函数名 功能 返回值
yield() 当前进程放弃执行 void
sleep_until 线程休眠直到指定的时间点 void
sleep_for 线程休眠指定的时间 void

标注

  • join() 和 detach() 的区别
    join() 会阻塞当前进程等待指定进程结束。在此期间 joinable()==1;
    detach() 一旦脱离 除非使用其他方式(信号量etc) 否则无法获知运行状态,在此期间 joinable()==0;

  • thread 构建之后会立即运行。
    此后的join() detach 只能在线程运行期间有效。

HTTP 协议入门

HTTP协议入门

HTTP 协议是互联网的基础协议,也是网页开发的必备知识,最新版本 HTTP/2 更是让它成为技术热点。

本文介绍 HTTP 协议的历史演变和设计思路。

一、HTTP/0.9

HTTP 是基于 TCP/IP 协议的应用层协议。它不涉及数据包(packet)传输,主要规定了客户端和服务器之间的通信格式,默认使用80端口。

最早版本是1991年发布的0.9版。该版本极其简单,只有一个命令GET。

GET /index.html
上面命令表示,TCP 连接(connection)建立后,客户端向服务器请求(request)网页index.html。

协议规定,服务器只能回应HTML格式的字符串,不能回应别的格式。

<html>
  <body>Hello World</body>
</html>

服务器发送完毕,就关闭TCP连接。

二、HTTP/1.0

2.1 简介

1996年5月,HTTP/1.0 版本发布,内容大大增加。

首先,任何格式的内容都可以发送。这使得互联网不仅可以传输文字,还能传输图像、视频、二进制文件。这为互联网的大发展奠定了基础。

其次,除了GET命令,还引入了POST命令和HEAD命令,丰富了浏览器与服务器的互动手段。

再次,HTTP请求和回应的格式也变了。除了数据部分,每次通信都必须包括头信息(HTTP header),用来描述一些元数据。

其他的新增功能还包括状态码(status code)、多字符集支持、多部分发送(multi-part type)、权限(authorization)、缓存(cache)、内容编码(content encoding)等。

2.2 请求格式

下面是一个1.0版的HTTP请求的例子。

GET / HTTP/1.0
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5)
Accept: */*

可以看到,这个格式与0.9版有很大变化。

第一行是请求命令,必须在尾部添加协议版本(HTTP/1.0)。后面就是多行头信息,描述客户端的情况。

2.3 回应格式

服务器的回应如下。

HTTP/1.0 200 OK 
Content-Type: text/plain
Content-Length: 137582
Expires: Thu, 05 Dec 1997 16:00:00 GMT
Last-Modified: Wed, 5 August 1996 15:55:28 GMT
Server: Apache 0.84

<html>
  <body>Hello World</body>
</html>

回应的格式是"头信息 + 一个空行(\r\n) + 数据"。其中,第一行是"协议版本 + 状态码(status code) + 状态描述"。

2.4 Content-Type 字段

关于字符的编码,1.0版规定,头信息必须是 ASCII 码,后面的数据可以是任何格式。因此,服务器回应的时候,必须告诉客户端,数据是什么格式,这就是Content-Type字段的作用。

下面是一些常见的Content-Type字段的值。

text/plain
text/html
text/css
image/jpeg
image/png
image/svg+xml
audio/mp4
video/mp4
application/javascript
application/pdf
application/zip
application/atom+xml

这些数据类型总称为MIME type,每个值包括一级类型和二级类型,之间用斜杠分隔。

除了预定义的类型,厂商也可以自定义类型。

application/vnd.debian.binary-package
上面的类型表明,发送的是Debian系统的二进制数据包。
MIME type还可以在尾部使用分号,添加参数。
Content-Type: text/html; charset=utf-8
上面的类型表明,发送的是网页,而且编码是UTF-8。

客户端请求的时候,可以使用Accept字段声明自己可以接受哪些数据格式。
Accept: */*
上面代码中,客户端声明自己可以接受任何格式的数据。
MIME type不仅用在HTTP协议,还可以用在其他地方,比如HTML网页。

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<!-- 等同于 -->
<meta charset="utf-8" /> 

2.5 Content-Encoding 字段

由于发送的数据可以是任何格式,因此可以把数据压缩后再发送。Content-Encoding字段说明数据的压缩方法。

Content-Encoding: gzip
Content-Encoding: compress
Content-Encoding: deflate

客户端在请求时,用Accept-Encoding字段说明自己可以接受哪些压缩方法。
Accept-Encoding: gzip, deflate

2.6 缺点

HTTP/1.0 版的主要缺点是,每个TCP连接只能发送一个请求。发送数据完毕,连接就关闭,如果还要请求其他资源,就必须再新建一个连接。

TCP连接的新建成本很高,因为需要客户端和服务器三次握手,并且开始时发送速率较慢(slow start)。所以,HTTP 1.0版本的性能比较差。随着网页加载的外部资源越来越多,这个问题就愈发突出了。

为了解决这个问题,有些浏览器在请求时,用了一个非标准的Connection字段。

Connection: keep-alive
这个字段要求服务器不要关闭TCP连接,以便其他请求复用。服务器同样回应这个字段。

Connection: keep-alive
一个可以复用的TCP连接就建立了,直到客户端或服务器主动关闭连接。但是,这不是标准字段,不同实现的行为可能不一致,因此不是根本的解决办法。

三、HTTP/1.1

1997年1月,HTTP/1.1 版本发布,只比 1.0 版本晚了半年。它进一步完善了 HTTP 协议,一直用到了20年后的今天,直到现在还是最流行的版本。

3.1 持久连接

1.1 版的最大变化,就是引入了持久连接(persistent connection),即TCP连接默认不关闭,可以被多个请求复用,不用声明Connection: keep-alive。

客户端和服务器发现对方一段时间没有活动,就可以主动关闭连接。不过,规范的做法是,客户端在最后一个请求时,发送Connection: close,明确要求服务器关闭TCP连接。
Connection: close
目前,对于同一个域名,大多数浏览器允许同时建立6个持久连接。

3.2 管道机制

1.1 版还引入了管道机制(pipelining),即在同一个TCP连接里面,客户端可以同时发送多个请求。这样就进一步改进了HTTP协议的效率。

举例来说,客户端需要请求两个资源。以前的做法是,在同一个TCP连接里面,先发送A请求,然后等待服务器做出回应,收到后再发出B请求。管道机制则是允许浏览器同时发出A请求和B请求,但是服务器还是按照顺序,先回应A请求,完成后再回应B请求。

3.3 Content-Length 字段

一个TCP连接现在可以传送多个回应,势必就要有一种机制,区分数据包是属于哪一个回应的。这就是Content-length字段的作用,声明本次回应的数据长度。

Content-Length: 3495
上面代码告诉浏览器,本次回应的长度是3495个字节,后面的字节就属于下一个回应了。

在1.0版中,Content-Length字段不是必需的,因为浏览器发现服务器关闭了TCP连接,就表明收到的数据包已经全了。

3.4 分块传输编码

使用Content-Length字段的前提条件是,服务器发送回应之前,必须知道回应的数据长度。

对于一些很耗时的动态操作来说,这意味着,服务器要等到所有操作完成,才能发送数据,显然这样的效率不高。更好的处理方法是,产生一块数据,就发送一块,采用"流模式"(stream)取代"缓存模式"(buffer)。

因此,1.1版规定可以不使用Content-Length字段,而使用"分块传输编码"(chunked transfer encoding)。只要请求或回应的头信息有Transfer-Encoding字段,就表明回应将由数量未定的数据块组成。

Transfer-Encoding: chunked
每个非空的数据块之前,会有一个16进制的数值,表示这个块的长度。最后是一个大小为0的块,就表示本次回应的数据发送完了。下面是一个例子。

HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked

25
This is the data in the first chunk

1C
and this is the second one

3
con

8
sequence

0

3.5 其他功能

1.1版还新增了许多动词方法:PUT、PATCH、HEAD、 OPTIONS、DELETE。

另外,客户端请求的头信息新增了Host字段,用来指定服务器的域名。

Host: www.example.com
有了Host字段,就可以将请求发往同一台服务器上的不同网站,为虚拟主机的兴起打下了基础。

3.6 缺点

虽然1.1版允许复用TCP连接,但是同一个TCP连接里面,所有的数据通信是按次序进行的。服务器只有处理完一个回应,才会进行下一个回应。要是前面的回应特别慢,后面就会有许多请求排队等着。这称为"队头堵塞"(Head-of-line blocking)。

为了避免这个问题,只有两种方法:一是减少请求数,二是同时多开持久连接。这导致了很多的网页优化技巧,比如合并脚本和样式表、将图片嵌入CSS代码、域名分片(domain sharding)等等。如果HTTP协议设计得更好一些,这些额外的工作是可以避免的。

3.7 请求方法

  • GET
    向指定的资源发出“显示”请求。使用GET方法应该只用在读取数据,而不应当被用于产生“副作用”的操作中,例如在Web Application中。其中一个原因是GET可能会被网络蜘蛛等随意访问。参见安全方法
  • HEAD
    与GET方法一样,都是向服务器发出指定资源的请求。只不过服务器将不传回资源的本文部分。它的好处在于,使用这个方法可以在不必传输全部内容的情况下,就可以获取其中“关于该资源的信息”(元信息或称元数据)。
  • POST
    向指定资源提交数据,请求服务器进行处理(例如提交表单或者上传文件)。数据被包含在请求本文中。这个请求可能会创建新的资源或修改现有资源,或二者皆有。
  • PUT
    向指定资源位置上传其最新内容
  • DELETE
    请求服务器删除Request-URI所标识的资源。
  • TRACE
    回显服务器收到的请求,主要用于测试或诊断。
  • OPTIONS
    这个方法可使服务器传回该资源所支持的所有HTTP请求方法。用'*'来代替资源名称,向Web服务器发送OPTIONS请求,可以测试服务器功能是否正常运作。
  • CONNECT
    HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。通常用于SSL加密服务器的链接(经由非加密的HTTP代理服务器)。

四、SPDY 协议

2009年,谷歌公开了自行研发的 SPDY 协议,主要解决 HTTP/1.1 效率不高的问题。

这个协议在Chrome浏览器上证明可行以后,就被当作 HTTP/2 的基础,主要特性都在 HTTP/2 之中得到继承。

五、HTTP/2

2015年,HTTP/2 发布。它不叫 HTTP/2.0,是因为标准委员会不打算再发布子版本了,下一个新版本将是 HTTP/3。

5.1 二进制协议

HTTP/1.1 版的头信息肯定是文本(ASCII编码),数据体可以是文本,也可以是二进制。HTTP/2 则是一个彻底的二进制协议,头信息和数据体都是二进制,并且统称为"帧"(frame):头信息帧和数据帧。

二进制协议的一个好处是,可以定义额外的帧。HTTP/2 定义了近十种帧,为将来的高级应用打好了基础。如果使用文本实现这种功能,解析数据将会变得非常麻烦,二进制解析则方便得多。

5.2 多工

HTTP/2 复用TCP连接,在一个连接里,客户端和浏览器都可以同时发送多个请求或回应,而且不用按照顺序一一对应,这样就避免了"队头堵塞"。

举例来说,在一个TCP连接里面,服务器同时收到了A请求和B请求,于是先回应A请求,结果发现处理过程非常耗时,于是就发送A请求已经处理好的部分, 接着回应B请求,完成后,再发送A请求剩下的部分。

这样双向的、实时的通信,就叫做多工(Multiplexing)。

5.3 数据流

因为 HTTP/2 的数据包是不按顺序发送的,同一个连接里面连续的数据包,可能属于不同的回应。因此,必须要对数据包做标记,指出它属于哪个回应。

HTTP/2 将每个请求或回应的所有数据包,称为一个数据流(stream)。每个数据流都有一个独一无二的编号。数据包发送的时候,都必须标记数据流ID,用来区分它属于哪个数据流。另外还规定,客户端发出的数据流,ID一律为奇数,服务器发出的,ID为偶数。

数据流发送到一半的时候,客户端和服务器都可以发送信号(RST_STREAM帧),取消这个数据流。1.1版取消数据流的唯一方法,就是关闭TCP连接。这就是说,HTTP/2 可以取消某一次请求,同时保证TCP连接还打开着,可以被其他请求使用。

客户端还可以指定数据流的优先级。优先级越高,服务器就会越早回应。

5.4 头信息压缩

HTTP 协议不带有状态,每次请求都必须附上所有信息。所以,请求的很多字段都是重复的,比如Cookie和User Agent,一模一样的内容,每次请求都必须附带,这会浪费很多带宽,也影响速度。

HTTP/2 对这一点做了优化,引入了头信息压缩机制(header compression)。一方面,头信息使用gzip或compress压缩后再发送;另一方面,客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了。

5.5 服务器推送

HTTP/2 允许服务器未经请求,主动向客户端发送资源,这叫做服务器推送(server push)。

常见场景是客户端请求一个网页,这个网页里面包含很多静态资源。正常情况下,客户端必须收到网页后,解析HTML源码,发现有静态资源,再发出静态资源请求。其实,服务器可以预期到客户端请求网页后,很可能会再请求静态资源,所以就主动把这些静态资源随着网页一起发给客户端了。

六、参考链接

Journey to HTTP/2, by Kamran Ahmed
HTTP, by Wikipedia
HTTP/1.0 Specification
HTTP/2 Specification
(完)

来源于阮一峰

判断 Y 是否是2的n次方

因为 满足2的n次方的数 二进制表现为 10...0的形式。取反之后为01...1的形式 。所以满足
(Y != 0) && ((Y & (~Y + 1)) == Y)==true
或者
((Y&(Y-1))&&(Y!=0))==0

pem 证书权限问题

Permissions 0644 for '***.pem' are too open.
chmod 600 ***.pem
ssh -i identity_file user@hostname

柔性数组(Flexible Array)

  • 柔性数组(Flexible Array)也叫伸缩性数组
    柔性数组既数组大小待定的数组, C语言中结构体的最后一个元素可以是大小未知的数组,也就是所谓的0长度,所以我们可以用结构体来创建柔性数组。

  • 柔性数组有什么用途 ?
    它的主要用途是为了满足需要变长度的结构体,为了解决使用数组时内存的冗余和数组的越界问题。

  • 用法 :在一个结构体的最后 ,申明一个长度为空的数组,就可以使得这个结构体是可变长的。对于编译器来说,此时长度为0的数组并不占用空间,因为数组名

    本身不占空间,它只是一个偏移量, 数组名这个符号本身代 表了一个不可修改的地址常量 (注意:数组名永远都不会是指针! ),但对于这个数组的大小,我们

可以进行动态分配,对于编译器而言,数组名仅仅是一个符号,它不会占用任何空间,它在结构体中,只是代表了一个偏移量,代表一个不可修改的地址常量!

对于柔性数组的这个特点,很容易构造出变成结构体,如缓冲区,数据包等等:

typedef struct _SoftArray
{
    Int len;
    int array[];
}SoftArray;

这样的变长数组常用于网络通信中构造不定长数据包,不会浪费空间浪费网络流量,比如我要发送1024字节的数据,如果用定长包,假设定长包的长度为2048,就

会浪费1024个字节的空间,也会造成不必要的流量浪费。

linux 下 zip 使用

  • 分片压缩 m g k
    zip -s 100m -r file.zip foo/
  • 切分文件
    zip existing.zip --out new.zip -s 50m
  • 解压缩分卷文件
合并文件
zip -s 0 split.zip --out single.zip
解压文件
unzip single.zip

Memory Alignment

什么是内存对齐(memory alignment)

  • 执行进程是由一系列CPU指令构成的,CPU指令中有一些指令时需要访问内存的。最常见的就是“从内存读到寄存器”,以及“从寄存器写到内存”。在老的架构中(当然包括x86),也有一些运算指令是可以直接以内存为操作数,那么这些指令也隐含了内存的读取,在很多CPU架构下,这些指令都要求操作的内存地址(更准确的说,操作内存的起始地址)能够被操作的内存大小整除,满足这个要求的内存访问叫做访问对齐的内存(aligned memory access),否则就是访问未对齐的内存(unaligned memory access)
  • 举例描述 如果对于64bit数据总线的机器,从0x80读取8个字节,因为0x80能被64整除,所以一次读取0x80 ~ 0xc0就可以,如果,数据在0x81,必须读两次,第一次读 0x80 ~ 0xc0 第二次读取 0xc0 ~ 0x100

C++ 内存对齐机制

  • 在C++中每个类型都有两种属性,一个是size,另一个是alignment requirement,又称之为alignment,C++并没有规定每个类型的alignment,但一般都是这个规律。
  • 所有的基础类型对齐量等于这个类型的大小。
  • struct, class, union类型的对齐量等于他们的非静态成员变量中最大的对齐量。
  • 标准规定所有的对齐量必须是2的幂。
    举例
class MyObject
{
    char c;
    int i;
    short s;
}

alignment = 4;
内存分布:

0|1|2|3
c|
i------|
s--|
class MyObject
{
    char c;
    alignas(8) int i;
    short s;
}

alignment = 4;
内存分布为

0|1|2|3|4|5|6|7
c|
i------|s--|

git 基础知识

Tagging

  • 列出标签
    git tag

  • 列出特定的标签
    git tag -l 'v0.1*'

  • 创建标签(lightweight)
    git tag -a "tag-name"

  • 创建标签(annotated)
    git tag -a "tag-name" -m 'Notions'

  • 创建标签(指定提交)
    git tag -a "tag-name" commit-hash

  • 删除标签
    git tag -d "tag-name"

  • 上传标签
    git push origin "tag-name"

  • 删除远程标签
    git push origin :refs/tags/"tag-name"

Branch

  • 列出分支
    git branch -v 最后一次提交信息
  • 切换分支
    git checkout (-b) "branch-name" -b 新建分支并切换
  • 删除分支
    git branch -d "branch-name" -D 强制删除
  • 合并分支
    git merge "branch-name" 讲branch-name合并到当前分支
  • 查看当前分支尚未合并的工作
    git branch --no-merged

std::thread 中 sleep_for(0ns) 与 yield()的区别

区别

  • sleep_for(0ns)
    休眠0s 实际上也就是阻止运行0ns (有文章说类似于yield() 可实际上在MAC OS 或 Windows 上yield()消耗时间更多.差距可达3倍,所以我认为sleep_for(0ns)可能并没有让出这个时间片,而是在这个时间片中多次执行)
  • yield()
    放弃获得的时间片,重新进入就绪的队列中,等待下次调度
    可以让低于当前优先级的线程得以运行。可以通过返回值判断是否成功调度了其它线程。
    只能调度同一个处理器的线程,不能调度其它处理器的线程。当没有其它就绪的线程,会一直占用 CPU 时间片,造成 CPU 100%占用率。

哪些运算符可以被友元重载,为什么?

C++规定=,[ ],(),->这四个运算符只能被重载为类的非静态成员函数,其他的可以被友元重载,主要是因为其他的运算符重载函数都会根据参数类型或数目进行精确匹配,这四个不具有这种检查的功能,用友元定义就会出错。

map && unordered_map

对比

operation map unordered_map
Ordering increasing order (by default) No ordering
Implementation Self balancing BST (RBT) Hash Table
search time log(n) O(1) -> Average O(N)-> Worst Case
Insertion time log(n) + Rebalance Same as search
Deletion time log(n) + Rebalance Same as search

Use std::map when

  • You need ordered data.
  • You would have to print/access the data (in sorted order).
  • You need predecessor/successor of elements.
  • See advantages of BST over Hash Table for more cases.

Use std::unordered_map when

  • You need to keep count of some data (Example – strings) and no ordering is required.
  • You need single element access i.e. no traversal.

unordered_set && set

  • unordered_set 类似 于 unordered_map No ordering Hash Table
  • set: RBT

Code

std::map<int, std::string> ismap;
isunordered[100] = "test000";
isunordered[10] = "test001";
isunordered[110] = "test002";
isunordered[9] = "test003";
isunordered[1100] = "test004";
isunordered[107] = "test005";
ismap[100] = "test000";
ismap[10] = "test001";
ismap[110] = "test002";
ismap[9] = "test003";
ismap[1100] = "test004";
ismap[107] = "test005";
std::cout << "unordered :" << std::endl;
for (auto x : isunordered)
{
	std::cout << x.first << " : " << x.second.c_str() << std::endl;
}
std::cout << "map :" << std::endl;
for (auto x : ismap)
{
	std::cout << x.first << " : " << x.second.c_str() << std::endl;
}

Result :

unordered :
100 : test000
10 : test001
110 : test002
9 : test003
1100 : test004
107 : test005
map :
9 : test003
10 : test001
100 : test000
107 : test005
110 : test002
1100 : test004

逆向迭代器 reverse_iterator

正常迭代器

-- 0 -- -- 1 -- -- 2 -- -- 3 -- -- 4 -- -- 5 -- -- --
-- 1 -- -- 2 -- -- 3 -- -- 4 -- -- 5 -- -- 6 --
begin -- 1 -- -- 2 -- -- pos -- -- 4 -- -- 5 -- end

逆向迭代器

-- 0 -- -- 1 -- -- 2 -- -- 3 -- -- 4 -- -- 5 -- -- --
-- 1 -- -- 2 -- -- 3 -- -- 4 -- -- 5 -- -- 6 --
rend -- 1 -- -- 2 -- -- rpos -- -- 4 -- -- 5 -- rbegin
  • rend() 返回反向迭代的最末元素的下一位置,也就是真实只第一元素的前一个位置(拗口)
  • rbegin() 返回反向迭代的第一个元素的位置, 也就是真实之最末元素的位置

#原因
如果将一个迭代器转化为reverse迭代器时会发现返回值不同.这不是bug 这是特性, (侯捷STL第九章迭代器说明)
导致这个性质是因为区间的半开性.为了指出容器内所有元素,我们需要采用"最末元素的下一位置".然而对reverse迭代器而言,这个位置位于第一元素之前.糟糕的是,这个元素可能并不存在.因为容器并不要求其第一元素之前的位置也合法.
为此 reverse 迭代器的设计者运用了一个小技巧 : 他们实际倒置了"半开原则". Reverse 迭代器所定义的区间并不包括起点,反倒是包括了终点.然而逻辑上其行为一如往前

这样就明白了.也就是 当rpos 指向一个物理位置(element) 这是其value 是该物理位置前一个元素的值. 当访问rbegin()时 该pos位于end() 返回end()之前元素的值.

  • 把 reverse 迭代器转换成正常迭代器可以使用base()
    auto pos = rpos.base()

位域 (bit_field)

#include <iostream>
struct S {
    // 通常将占用 2 字节:
    // 3 位:b1 的值
    // 5 位:不使用
    // 6 位:b2 的值
    // 2 位:b3 的值
    unsigned char b1 : 3;
    unsigned char :0; // 开始新字节
    unsigned char b2 : 6;
    unsigned char b3 : 2;
};
  • 位域中的位数决定其能保存的数值极限

  • 多个相邻位域通常可以打包在一起
    但 不能跨字节(这个存疑 某些平台可以)

  • 特殊的零大小无名位域可用于强行打破填充。它指定下个位域始于新的字节开始

  • 位域的类型只能似乎静态数据成员

  • 位域不能是静态数据成员

  • 没有位域纯右值 也就是 左值到右值转换始终生成位域底层类型的对象。

  • 如果位域设置的位大小 超过一个字节大小,则多余的位为占位。(VC测试报错。)

C++ 文件读(普通方式)

第一种

std::ifstream ifs(filename, std::ios::binary);
std::string buffer;
if (ifs.is_open())
{
    buffer.resize(ifs.seekg(0, std::ios::end).tellg());
    ifs.seekg(0, std::ios::beg).read(&buffer[0], static_cast<std::streamsize>(buffer.size()));
    return buffer;
}

第二种

std::ifstream ifs(filename, std::ios::binary);
rturn string((std::istreambuf_iterator<char>(ifs)),
    (std::istreambuf_iterator<char>()));

第三种

ifstream ifs;
ifs.open(filename, std::ios::binary);//open the input file
stringstream strStream;
strStream << ifs.rdbuf();
return strStream.str();

以上省略判断文件打开失败情况和关闭文件.
根据测试(VS 2019 community)

二进制方式打开

read_0 time is : 282,039,300   number : 229799858
read_1 time is : 1,934,362,200   number : 229799858
read_2 time is : 1,656,453,300   number : 229799858

结论:

预先分配足量内存是这三种方法时间消耗的关键. 使用vector代替string速度会提高20%左右
使用文本方式打开速度会快于二进制打开.原因未知,但是对于二进制文件会出现截断情况.需要注意.

thread join() && detach()

  • join() 等待线程结束。阻塞状态。
  • detach() 该线程与执行该线程的对象分离。独立运行,无法获知其运行状态。不过 joinable() 返回 false 或者运行错误时抛出 std::system_error 注意。当我测试这个函数时 会产生 该线程未完成但程序流程直接正常结束的问题。如果使用这个函数务必检测其状态。

linux 快速清空文件

1、#echo "" > test.txt(文件大小被截为1字节)

2、# > test.txt(文件大小被截为0字节)

3、#cat/dev/null > test.txt(文件大小被截为0字节)

字节对齐

字节对齐

什么是字节对齐

内存的基本单位是byte,64位处理器一次可以提取8byte(64位)数据,32位处理器一次读取4byte(32位)数据.这样计算机就会对基本的数据类型的合法地址做出一些限制,
| A B C D E F G H | I G K L M M O P |
如果希望读取A B C D E F G H 那么读取一次就可以,I G K L M M O P 亦然,
若希望读取 F G H I G K L M那么一次读取是不可行的.必须读取两次才能得到.

对齐的规则

  • 结构体变量的首地址能被对齐字节数大小整除
  • 结构体每个成员相对结构体首地址的偏移都是成员大小的整数倍,如果不满足则在前一个成员结束地址后填充字节使之满足条件.
  • 结构体的总大小为结构体对齐字节数大小的整数倍,如不满足最后填充字节使之满足条件.

为什么要字节对齐?

  • 减少CPU访问内存的执行次数. 提高内存系统性能.如果不对齐的情况下,如上例中读取 F G H I G K L M,这时需要读取两次.
  • 程序在某些处理器会出现意想不到的crash.

如何对齐

  • 尝试调整成员变量顺序,使之自己对齐
  • 通过填充(缺点: 不同平台下需要填充的字节可能不一样)

跨平台通信

不同平台的对齐方式可能不同,所以通信时可能会发生错乱

  • 可以使用#pragma pack(N) (N字节对齐)
#pragma pack(N) //设置N字节对齐
#pragma pack()  //还原默认对齐
  • 使用gcc的__attribute__
__attribute__((aligned (n))) //让所作用的结构成员对齐在n字节自然边界上。如果结构中有成员的长度大于n,则按照最大成员的长度来对齐。
__attribute__ ((packed)) //取消结构在编译过程中的优化对齐,也可以认为是1字节对齐。
  • 填充 (要根据不同平台填充不同的长度)

总结

  • 结构体成员变量合理安排位置会节省空间提高性能
  • 跨平台的情况下可以考虑1字节对齐,节省了空间但是影响访问性能
  • 进行填充使之满足字节对齐的条件在不同平台需要填充不同的长度

宏定义问题 #宏定义

C++宏定义

无参宏

#define

  • #define NAME king

有参宏

  • #define <宏名>(参数)<宏体>
    • #define min(x,y)(x>y)?y:x

运算符

  • ##(连接)
    • #define Conn(a,b) x##b
  • #字符串化
    *#define SUM(a,b) printf(#a " + "#b" = %d\n",((a) + (b)))
    • 将参数a字符串化

可变宏 … 和 VA_ARGS

  • #define PR(...) printf(__VA_ARGS__)

后注

  • 重复定义
    • 如果两个头文件有相同的宏定义.会出错.
      • 使用 #ifdef #ifndef #endif
      • 使用 #pragma onece
  • #define 和 typedef 区别
    • #define 是简单的文本替换 在预处理阶段
    • typedef 类型的别名, 在编译阶段完成

linux 简单操作

mail 通知

  • 查看 mail
    ls -lth /var/spool/mail
  • 清空 mail
    cat /dev/null > /var/spool/mail/root
  • 关闭邮件自动提示
echo "unset MAILCHECK" >> /etc/profile
source /etc/profile

指定用户加入超级用户权限

  • 查找sudoers 位置
whereis sudoers
chmod u+w /etc/sudoers
"user-name" ALL=(ALL)ALL
chmod u-w /etc/sudoers

tar命令

tar [required argument][optional argument][file]

  • 解压/压缩
参数名 解释
-A 新增压缩文件到已存在的压缩
-B 设置区块大小
-W 确认压缩文件的正确性
-Z 支持compress解压文件
-c 设立新的压缩文件
-d 记录文件的差别
-j 支持bzip2解压文件
-k 保留原有文件不覆盖
-l 文件系统边界设置
-m 保留文件不被覆盖
-r 添加文件到已经压缩的文件
-t 显示压缩文件的内容
-u 添加改变了和现有的文件到已经存在的压缩文件
-v 显示操作过程
-x 从压缩文件中提取文件
-z 支持gzip解压文件
可选参数
-C 切换到指定目录
-b 设置区块数目
-f 指定压缩文件
--help 显示帮助信息
--version 显示版本信息

删除网卡/网桥

tunctl -d <虚拟网卡名>
ifconfig <网桥名>down//卸载
brctl delbr <网桥名>//删除

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.