I/O多路复用的理解 先讲一个大家都比较熟悉的例子吧 小时候咱们都喜欢看《亮剑》、《雪豹》这一类的抗日剧,里面八路军在自己的驻地周围都会24小时分布一些暗哨,每当有鬼子要进行扫荡或者清剿的时候暗哨就会赶紧告诉驻地的八路军,有敌人过来了,赶紧抄家伙干仗了。其实这就和咱们要讲的I/O多路复用有异曲同工之处。 在我们接触I/O多路复用以前,在处理一些比较多的连接或者请求的时候大多数人会去使用类似下面这种方式去处理: while(1) { int cli_fd = accept(listen_fd, (struct sockaddr*)&addrCli, sizeof(addrCli)); ...../*开启一个线程或者开启一个进程*/ } 这么做看着十分的清爽,而且实现起来也相当的简单,但是服务器的主程序会一直阻塞在accept这个函数上,然后会一直去等待connect的到来,这种方法虽然十分的简单,但是在轮询的过程中耗费了大量的CPU时间,并且效率还十分的低下,因此我们要想 继续阅读 >>


李佳灏 18/08/14 16:27:10
信号是由用户、系统或者进程发送给目标进程的信息,用来通知目标进程的状态改变或系统异常。 发送信号 kill #include <sys/types.h> #include <signal.h> int kill(pid_t pid, int sig); 该函数可以把sig信号发送给pid指定的目标进程 pid 参数 含义 pid > 0 信号发送给PID为pid的进程 pid = 0 信号发送给本进程组内的其他进程 pid = -1 信号发送给除init进程外的所有进程,但发送者需要拥有对目标发送信号的权限 pid < -1 信号发送给组ID为-pid的进程组中的所有成员 特别的如果sig为0的时候,kill函数不发送任何信号。 kill函数成功时返回0,失败返回-1,并设置errno errno 含义 EINVAL 无效的信号 EPERM 继续阅读 >>


李佳灏 18/08/13 15:26:36
生产者——消费者模型顾名思义,就是一个或多个线程往仓库生产东西,另外的线程从仓库拿东西,在咱们的线程池中也有所应用。咱们看看维基的解释: 生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。该问题描述了共享固定大小缓冲区的两个线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。 说了这么多,大家还是有点晕乎乎的,咱们看代码吧 #include<stdio.h> #include<unistd.h> #include<string.h> #include<pthread.h> //1 : 1 #defi 继续阅读 >>


李佳灏 18/08/13 08:34:37
介绍 时间轮顾名思义,就是将不同时间的定时任务放在一个轮子上,既然是轮子,肯定是会转动的,时间轮内指向槽的指针,以恒定的速度顺时针转动,每转动一步就指向下一个槽。,一次转动称为一次滴答(tick)。一个滴答的时间称为时间轮的槽间隔si,也就是心搏时间。一个时间轮若有N个槽,在它运转一周的时间是N * si。同一个槽上的定时器它们的定时时间相差N * si的整数倍。 对于时间轮来说,要提高精度,就要使si值足够小;要提高执行效率,则要求N值足够大。如图所示: 由图可知定时器在时间轮的槽上是以链表的形式存储的(双向链表),并且相同一条链(也就是同一个槽)上的定时器:它们的定时时间相差N*si的整数倍。时间轮就是利用这个关系将定时器散列到不同的链中。在插入槽中的时候采用的是头插的方法,这样可以减少不必要的遍历时间。但是正是因为一股脑的头插(无序),也造成了在我们每次转动的时候都不得不去遍历一遍链表。 对于时间轮来说,添加一个定时器的时间复杂度为O(1),删除一个定时器的时间复杂度也是O(1),执行一 继续阅读 >>


李佳灏 18/08/09 16:49:07
在《Linux高性能服务器编程》一书中为了帮助大家将书中的知识融汇到实际项目中,作者特意编写了一个较为完整的负载均衡服务器程序springsnail。里面用到了进程池、有限状态机这些知识点。自己是在网上找到的这个程序的源码,起初接触的时候,总共1400多行代码里面没有一行注释,网上也没有一篇博客去对这个项目进行解析,因此写这篇博客供大家一起分享学习。springsnail源码(带注释) 咱们从main函数开始,我们要介绍几个c语言中的两个宏 __FILE__:用以指示本行语句所在源文件的文件名 __LINE__:用以指示本行语句在源文件中的位置信息 这两个参数在后面咱们程序的调试中有着非常正要的作用。并且整个程序的日志系统也是依靠这两个宏和可变参的log()函数完成的。 接着大家需要了解getopt函数这个函数可以通过提取命令行参数对命令行参数进行解析。 接着后面是解析xml文件的一长串代码 vector< host > balance_srv; 继续阅读 >>


李佳灏 18/08/02 12:33:17
定义 策略模式:定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。 Strategy 模式典型的结构图为: 大家肯定看着很懵逼,其实第一次接触类图的时候我自己也是这样。 那么咱们举个例子来解释一下。 假设我们要实现一个角色游戏,context为所有角色的基类(例子的代码后面会实现,此处只是拿context举例,此处的context并不是基类),一个角色可以切换不同的武器。然后strategy则为不同的武器的基类,而不同的武器的攻击方式是不同的,斧头的攻击为砍,剑的攻击为刺,弓箭的话为射击。乍一看感觉好麻烦啊。难不成得给一个角色类把所有的武器类都包含进去,然后切换武器的时候删除掉之前的武器,然后再重新开辟一个新的武器类。这样子的话给我们设计会带来非常大的不方便。而且假如我们有了新的武器,比如魔法棒,那么我们不是应该给角色类里面再添加魔法棒类,这样的话会让角色类变得非常庞大,而且非常不利于后期的维护,我们不能每增加一个武器就给角色类添加一个武器类吧。所 继续阅读 >>


李佳灏 18/06/22 23:47:23
server.cpp #include<stdio.h> #include<sys/types.h> #include<sys/socket.h> #include<sys/epoll.h> #include<netinet/in.h> #include<arpa/inet.h> #include<assert.h> #include<unistd.h> #include<errno.h> #include<string.h> #include<fcntl.h> #include<stdlib.h> #include<sys/epoll.h> #define MAX_EVENT_NUMBER 1024 #define TCP_BUFFER_SIZE 512 #define UDP_BUFFER_SIZE 1024 int setnonblock 继续阅读 >>


李佳灏 18/03/15 21:53:26
#pragma once #include<iostream> #include<string.h> using std::ostream; using std::istream; class my_string { private: char *data; int len; public: static const int npos = -1; //返回错误时的验证值 //构造函数 my_string() { data = new char[1]; data[0] = '\0'; len = 0; } my_string(const char *str); my_string(const my_string &s); my_string(const my_string &s, int begin, int end 继续阅读 >>


李佳灏 17/12/23 13:13:04
题目描述 You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list. You may assume the two numbers do not contain any leading zero, except the number 0 itself. Example Input: (2 -> 4 -> 3) + (5 -> 6 -> 4) Output: 7 -> 0 -> 8 Explanation: 342 + 465 = 807. 这个题其实是大数相加的链表 继续阅读 >>


李佳灏 17/12/17 18:11:31
#include<stdio.h> #include<unistd.h> #include<stdlib.h> #include<pthread.h> #define COUNT 10 static int i = 1; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t even = PTHREAD_COND_INITIALIZER; pthread_cond_t uneven = PTHREAD_COND_INITIALIZER; //1 3 5 7 9 void* funA(void *arg) { while(i <= COUNT) { pthread_mutex_lock(&mutex); if(i % 2 != 0) { printf("funA 继续阅读 >>


李佳灏 17/12/10 19:06:37