- 博客(41)
- 收藏
- 关注
原创 条件控制,条件传送与__builtin_expect
如果我们现在要写一个函数,参数为两个整数,要求返回这两个整数差的绝对值,我们会有如下的写法。int diff(int a,int b){ if(a<b) return b-a; else return a-b;}现在给出另一种写法int diff(int a,int b){ int x1=a-b; int ...
2019-06-03 13:42:26
1183
2
原创 简单的TCP带宽测试工具TTCP
源码可以从陈硕的github上下载到,位置在muduo-master\examples\ace\ttcpTTCP是一个传统的测试TCP性能的工具,它主要测试两个机器之间TCP的吞吐量,在应用层模拟消息传递的过程——客户端发送一个包,服务端对包进行确认,并且在确认之前客户端不发送下一个包。可以设置发包的数量和每个包的大小,程序计算传输所有包所用的时间,然后计算出带宽。操作流程图以上发...
2019-05-07 14:42:14
5634
1
原创 剖析函数传递参数选择引用或值的区别
如果对ESP,EBP,栈帧等概念比较陌生,推荐先去了解一下函数调用的过程。推荐使用OD+VS自己实现一遍加深印象。(OD用来查看内存,VS用来看汇编代码和源代码的对应情况)mov与lea的区别指令:mov 操作对象:变量 有无[]没有区别,都是取值指令:mov 操作对象:寄存器 有[]表示取地址,没有[]表示取值指令:lea 操作对象:变量...
2019-05-04 18:57:48
555
原创 C中的强符号与弱符号
作用域c语言的作用域有两种,代码块作用域和文件作用域。代码块作用域是指由花括号限定的作用域,花括号以外的作用域就是文件作用域。这里指的花括号可以是函数的花括号,if,while,for,namespace的花括号,遵循的基本规则是花括号以里可以看到本花括号以外的东西,但是相反则不可以。int main(){ int y=4; { int x=3; ...
2019-04-27 16:14:10
917
原创 再探C++中的常量
什么是常量?相信绝大多数写过程序的人见到这两个字的第一反应就是——不能更改的量。没问题,书本上这样告诉我们,编译器也这样告诉我们,好像常量就真的是那么简单,纯粹,让人心安理得的去使用它,不需要任何顾虑。但事实并没有想象中的那么单纯。1.常量并不一定是常量int main(){ const int x=3;}这是一个“假常量”,当我们在下边敲出 x=4; 这样的代码时,编译...
2019-04-10 21:23:52
1363
原创 从汇编语言角度辨析char*str="abc"和char str[]="abc"
所以说想要从根本上理解这种语言上的trick就要直接看他的汇编代码,对着经验和现象猜来猜去就如同盲人摸象。 char*str="abc";01092BFE mov dword ptr [str],109CC70h char strr[]="abc";01092C05 mov eax,dword ptr ds:[0109CC70h] ...
2019-04-10 20:07:15
1764
原创 Linux内核计时器
linxu内核中完成的许多功能都需要感知时间的行进,比如定期把页面缓存中的数据写入磁盘,定期进行进程调度,提供获得当前时间的系统调用,还有计划任务的实现,让系统在某段时间之后执行某个程序,或者在某个时间点执行某个程序。以上这些功能对时间的把控都是由系统计时器完成的。 我们可以把系统计时器简单的看做一个按固定频率产生中断的硬件芯片,产生的中断就叫做定时器中断,而和时间相关的任务都在这个中断...
2019-04-09 15:10:45
997
原创 使用CAS操作实现的无锁栈
CAS(compare and set),是原子数支持的一种操作,假如我们有一个原子数类,那么他其中的CAS函数大致可以理解为这样bool compare_and_set(T&a,T&b){ if(*this==a) { *this=b; return true; } else { a=...
2019-04-07 17:58:16
618
原创 C++11线程池
线程池其实就是把任务队列和工作线程绑到一起,提供一个向任务队列中添加任务的接口,下面的代码为了表达更加清楚没有分成头文件和源文件,仅仅是提供思路。同步机制利用的互斥锁+条件变量,也可以使用C++11提供的原子数封装的自旋锁+条件变量。两种组合的区别在于,自旋锁比较适合当任务比较简单的时候使用,可以减少陷入内核的次数,但当任务比较复杂,线程需要较长时间等待的时候,自旋锁会把大量时间浪费在忙等待上...
2019-04-05 17:36:53
189
原创 从汇编语言角度剖析右值引用和左值引用的本质
右值引用着实让人很挠头,而他又很重要,看多了“右值是短暂的,左值是持久的”这种正确但是让人摸不到头脑的话,我觉得很有必要从右值引用和左值引用实现的层面进行一次区分。首先明确一点,左值引用和右值引用,都是指针。其实说白了他们都是编译器给我们提供的“功能”,也就是说,编译器在我们看不到的地方做了很多别的事情,让一个指针的用法变得如此丰富多彩。但是不管多么丰富多彩,他也只是一个指针而已。先来...
2019-04-05 10:53:01
1676
1
原创 tinyhttpd源码剖析
这是一个简单的服务器程序,只有五百多行。每次来一个请求就开一个线程去处理它,可以解析POST,GET而且可以执行CGI程序。服务器程序想要把自己收到的参数传给某些别的程序去执行,并且把这些程序产生的输出拿走,发给某个目标对象。CGI所处的位置就在“服务器把收到的参数传给别的程序”这个环节。它规定了一个标准的借口,我们只需要调用setenv()把收到的东西设置成条件变量,然后再通过execl执行...
2019-04-04 20:58:24
752
原创 shared_from_this的使用
当你想使用一个类的某个成员函数返回指向这个类的指针的时候,可以这样写class A{public: A(int y=0):x(y){ } A* getthis() { return this; } int x;};int main (void) { A a; cout<<a.x<<endl; A*p=a.getthis(); p->...
2019-04-04 12:51:51
6786
原创 auto_ptr和unique_ptr
auto_ptr是老版本的智能指针,当时还没有unique_ptr,shared_ptr,weak_ptr,现在auto_ptr已经被废弃,他有了更好用的替代品unique_ptr,相对于他的后继者,它有以下几个缺点。1.auto_ptr可以进行赋值和拷贝运算,但是他虽然名义上做的是赋值和拷贝,但是背后做的却是move语义做的事情,拷贝和赋值之后,源对象被置位空,这看起来十分反常。而uniqu...
2019-04-04 12:11:37
823
原创 C++智能指针自定义删除器
智能指针支持用户自定义删除方法,默认为delete或者delete[],不过当我们用一个裸指针定义一个智能指针,而裸指针指向的内存是malloc出来的时候,显然用delete删除会出问题,比如。struct A{ int a,b; int*p; A() { p=(int*)malloc(sizeof(int)); } ~A() { free(p); }};int...
2019-04-04 10:53:24
2852
4
原创 C++中的using关键字
罗列一下using的几种用法1.using namespace 这是最常见的用法,C++用命名空间把各种函数名字变量名字类名字保护起来。2.在子类里使用父类的private成员class A{public: int v;};class B: A{public: using A::v; void fun() { cout<<v<<end...
2019-04-03 21:30:49
2718
1
原创 epoll详解
IO复用函数统共有三个,select,poll,epoll,但是在大并发条件下,我们一般都会使用epoll,select和poll有下边两个缺点。每次在调用之前都要把所有需要监控的socket都传给内核 无论是在内核还是在用户空间select和poll都是采用轮询的方式检查所有socket而epoll正是在这两点上做出了改进,得到了比select和poll更高的效率。epoll的原理...
2019-04-03 20:24:20
573
原创 linux中的动态链接库
在使用动态链接库的时候并不会把动态库的代码全部copy到生成的程序中,而是在程序运行的时候再去加载对应的代码,所以使用同一个动态库的程序可以共用一份代码,而且当你对动态库进行升级的时候,也不用去修改使用它的代码。以上是动态库生成使用的全过程,可是当运行的时候却出现了这种错误。用ldd命令再看一下怎么会找不到,编译的时候不是加进去了吗,而且编译的时候也没有报错。因为程序编译的...
2019-04-03 12:38:41
16416
1
原创 linux中的静态链接库
C++编译四个步骤,预处理,编译,汇编,链接,所谓的静态链接库就是把部分写好的代码编译到汇编结束这个步骤,然后把它们打包起来,等到再写别的程序需要用到这里的某些函数的时候,只需要把这个程序和之前的库链接起来就可以了,简化了编译的步骤。不过静态链接库链接到某个程序这是一锤子买卖,可以认为只是单纯的在你生成的程序里复制了一块当时连接的静态库的代码,之后这个静态库改不改和你已经生成的程序已经没有关系了,...
2019-04-03 11:15:54
1317
原创 Redis底层的几种数据结构
在redis中有五种对象,分别是字符串对象,列表对象,哈希对象,集合对象,有序集合对象。五种对象的具体实现对应六种不同的存储结构,redis支持在不同的数据规模下为每种对象选取不同的存储结构,以达到最好的适应性。下面先介绍六种底层存储结构。SDS简单动态字符串redis用来存储字符串的数据结构,可以看作是一个vector维护的字符数组。和C字符串的区别在于存了字符长度,保证不会缓冲溢...
2019-04-01 20:33:34
479
原创 Linux中进程状态
linux进程描述符结构task_struct中的state域用来描述进程所处的状态,系统中的进程都必然处于这五种状态中的一种:TASK_RUNNING (运行)——进程是可执行的;它或者正在执行,或者在运行队列中等待执行。这是进程在用户空间中执行的唯一可能的状态;这种状态也可以应用到内核空间中正在执行的进程。 TASK_INTERRUPTIALBE (可中断)——进程正在睡眠(也就是说它被...
2019-03-31 19:19:39
848
原创 C++11多线程学习(3)条件变量
C++11中的条件变量支持把判断条件写到参数里。配合lamda表达式让程序代码更加清晰。第一个参数只支持unique_lock他和lock_guard的区别在于可以在作用域内加锁再解锁,而lock_gurad只能在构造和析构的时候加锁和解锁。下面是对cv的小应用,轮流打印AB#include <thread>#include <iostream>#includ...
2019-03-31 12:14:52
340
原创 C++11多线程学习(2)自旋锁任务队列
使用上一节的原子数构造成的自旋锁完成了一个任务队列的模型。因为condition_variable只能和mutex配合,想要让他和别的锁配合就要用condition_variable_any#include<iostream>#include<atomic>#include<thread>#include<vector>#include...
2019-03-30 15:01:04
620
原创 C++11多线程学习(1)atomic_flag
d学了这么久我才刚刚知道C++11居然对多线程有如此丰富的支持,一方面感慨自己学的还是太少了,一方面真的很开心可以告别自己封装mutex,线程,currentthread这些东西时代了。最重要的一点,在windows上写的代码和在linux上也可以编译运行,这意味着可以使用宇宙第一IDE来调试多线程程序。我会用这个系列记录自己学习C++11多线程的过程。C++11中引入了thread这个头文件...
2019-03-30 13:01:46
847
原创 求数组内最大的两个数字的与值
牛客看的腾讯面试题4.给一个数组A,求出A[i]&A[j](i!=j)最大 //n>=2写了一个没地方验证int find(vector<int>&v){ vector<int>temp; int res=0; for(int i=30;i>=0;i--) { int k=1<<i; ...
2019-03-29 20:04:33
965
7
原创 connect accept listen 与三次握手的关系
首先明确三次握手发生在什么时候。经过我的验证,在客户端执行connect的时候,便是向已经listen的服务器发出三次握手,等connect返回的时候,三次握手已经完成,和accept没有任何关系。验证过程如下。客户端程序只执行到connect,服务器端程序只执行到listen,然后用tcpdump对本地进行抓包。这里要注意tcpdump想抓本地还回的包需要监听 lo 也就是tcpdump...
2019-03-27 11:08:21
2320
2
原创 源码角度看memset初始化数组
memset经常被用来做初始化,memset(ptr,0,sizeof ptr)初始化为0,memset(ptr,-1,sizeof ptr)初始化为-1,除此以外的值很少用到,原因看memset的源码。void* memset(void* s,int c,size_t n){ const unsigned char uc=c; unsigned char* sc; ...
2019-03-23 19:37:23
246
原创 简述STL之萃取器
萃取器相当于对迭代器的功能扩展,有了它让我们得以通过迭代器获得迭代器所指的数据的类型。现在假设我们要实现一个算法,它接受一个迭代器作为参数,算法中需要定义一个变量,类型为迭代器所指的数据的类型。对于这个问题,我们并没有什么好办法,C++没有typeof()这种东西,typeid()也只能获得关于类型的信息,并不能用来声明变量。不过我们还是可以仰仗function templete的参数...
2019-03-23 16:39:35
809
原创 菱形继承下的虚函数表指针
本文基于VS2012编译器,不同的编译器结果可能有较大出入来看这样一段代码class A{ };class C:virtual public A{ };class B:virtual public A{ };class D:public C,public B{ };int main (){ cout<<sizeof(A)<<endl; cou...
2019-03-22 21:00:39
789
原创 C++对象中成员的绑定规则
先来看一段代码extern float x;class Point3d{public: Point3d(float,float,float); float X() const { return X; } void X(float new_x ) const { x=new_x; }private: float x,y,z;};现在如果有人问,X(...
2019-03-22 16:28:25
428
原创 C++多态用派生类指针调用基类虚函数
多态的使用方法是当基类指针指向派生类对象时,可以直接调用派生类重写的虚函数,而不是基类的虚函数。实现方法也是老生常谈,通过每个对象中的虚函数表指针,去找属于自己类的虚函数执行。那如果用派生类指针指向基类然后调用虚函数呢?#include<iostream>#include<vector>using namespace std;class A{public:...
2019-03-21 11:21:50
6996
1
原创 bind使用在shared_ptr上的细节
一句话总结,bind在把函数绑定到function上的时候,会让function持有一份传递的实参的拷贝,如果实参恰好是shared_ptr那就会让shared_ptr所指的对象生命期不会短于function。#include <iostream>#include <functional>#include<memory>#include<fu...
2019-03-17 13:37:00
1342
原创 简述muduo库中的Thread类
本文根据自己的看法对muduo库中的thread类进行了一定程度的简写。为什么要对线程进行封装?这是我在当初阅读这部分源码的时候萦绕在心头的一个问题。现在我想我可以对这个问题稍作解答。封装线程的目的是为其主线程构建一个方便操作副线程的接口。我们在进行多线程编程的时候,势必要对副线程进行管理,在理想情况下,程序里的线程都是用同一个class创建的,这样容易在线程的启动和销毁阶段做一些统一...
2019-03-15 17:33:25
1327
1
原创 muduo库发送数据简述
TCP连接发送数据和接收数据的处理方式略有不同,并没有让IO复用函数全权负责,这样做减少了程序从poll函数返回的次数,提高了服务器的效率。具体做法是,当消息产生可以像某个socket写入的时候,我们可以调用runInLoop,让IO线程在执行doPendlingFunctor的时候替我们做发送的操作。具体来看TcpConnection模块的代码。void TcpConnectio...
2019-03-15 11:03:15
1125
1
原创 关于muduo库中EventLoop的runInLoop功能
EventLoop可以在他的IO线程中执行某个用户任务回调,即EventLoop::runInLoop(const Functor& cb)其中Functor是boost::function<void()>。 如果用户在当前IO线程中调用这个函数,回调会同步进行;如果用户在其他线程调用runInLoop,cb会被加入队列,IO线程会被唤醒来调用这个Funct...
2019-03-14 13:33:07
1819
原创 为什么IO复用要搭配非阻塞IO和应用层buffer
为什么IO多路复用要搭配非阻塞IOselect、poll_wait、epoll_wait返回可读≠read去读的时候能读到。如果不用非阻塞,程序会永远卡在read上。以上情况可能出现在多进程同时监听一个socket,只有一个进程可以accept,别的都会block。假如socket的读缓冲区已经有足够多的数据,需要read多次才能读完,如果是非阻塞可以在循环里读取,不用担心阻塞在read上,...
2019-03-13 15:30:51
661
1
原创 常见的并发网络服务程序设计方案总结
0.非并发while(1){ clientsock=accept(); while(1) { str=recv.clientsock() //block if(str) send.clientsock(str); else { close(clientsock); break; } }}一次只服务一个客户,阻塞在recv上,浪费时间。1....
2019-03-13 14:42:54
180
原创 多线程环境下的高效异步日志系统
多线程双缓冲异步日志https://github.com/chenlujiu/High-Performence-AsyncLogStream.gitIntroduction仿照了MUDUO的日志设计,在原有的基础上做了简化,仅供学习。EnvoirmentOS: Ubuntu 14.04Complier: g++ 4.8Technical points异步实现这个日志模块用于多...
2019-03-13 12:05:47
1459
2
转载 CLOSE关闭连接的各种情况
由于涉及面太广,只作简单整理,有兴趣的可参考《UNIX Networking Programming》volum 1, Section 5.7, 5.12, 5.14, 5.15, 6.6 以及7.5 SO_LINGER选项。以一个简单的echo服务器为例,客户端从标准输入读入字符,发送给服务器,服务器收到后再原样返回,客户端收到后打印到标准输出。那么,关于套接字的关闭有以下几种情形:1,客...
2019-03-12 20:34:35
1830
原创 TCP产生复位报文段RST的三种情况
在某些特殊情况下,TCP连接的一端会向另一端发送携带RTS标志的报文段,即复位报文段,以通知对方关闭连接或重新建立连接。访问不存在的端口当客户端程序访问一个不存在的端口时,目标主机将给他发送一个复位报文段。异常终止连接TCP提供了异常终止连接的方法,即给对方发送一个复位报文段。一旦发送了复位报文段,发送端所有排队等待发送的数据都将被丢弃。应用程序可以使用socket选项SO_LINGER...
2019-03-12 20:06:15
1322
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人