Kqueue背景

Kqueue是unix系统上高效的IO多路复用技术,关于IO多路复用的原理网上有很多优秀的理解,这里不再赘述。
常见的io复用有select、poll、epoll、kqueue等。其中epoll为Linux系统独有,kqueue则在众多unix系统中存在,我们这里选择Kqueue进行切入主要是方便mac上IDE即时编译调试,其原理与epoll类似。

Kqueue参数概览

go语言中kqueue相关代码位于syscall库中
event_tKevent()操作的最基本的事件结构。
kqueuefreebsd内核中的一个事件队列kernel queue
Kevent()是一个系统调用,也是kqueue的用户界面,是对kqueue进行添加,删除操作的用户态的界面。

接下来介绍event_t这个结构体成员和Kevent的参数

type Kevent_t struct {Ident  uint64  //该事件关联的描述符,常见的有socket fd,file fd, signal fd等Filter int16  //事件的类型,比如读事件EVFILT_READ,写事件EVFILT_WRITE,信号事件EVFILT_SIGNALFlags  uint16    //事件的行为,也就是对kqueue的操作,下面介绍几个常用的//如EV_ADD:添加到kqueue中,EV_DELETE从kqueue中删除//EV_ONESHOT:一次性或事件,kevent返回后从kqueue中删除//EV_CLEAR:事件通知给用户后,事件的状态会重置,Fflags uint32Data   int64Udata  *byte //用户指定的数据
}
func Kevent(kq int,                 //Kqueue返回的唯一参数值,标记着一个内核队列changes,               //需要对kqueue进行修改的事件集合,kqueue通过此参数完成对事件的修改events []Kevent_t,       //返回的已经就绪的事件列表timeout *Timespec)        //超时控制,不指定事件表示一直等待事件发生,否则只等待一段时间(n int, err error) {  //返回已经就绪的事件数量
...
...
}

kqueue实现的echo服务示例

下面利用kqueue实现一个简单的echo服务(github地址),完全以IO复用的方式将标准输入流中的数据直接输出到标准输出中。

package mainimport ("io/ioutil""log""os""syscall"
)const BufferSize = 1024//完全以io复用的方式从标准输入流读数据,将数据输出到标准输出流中
func main() {var changes []syscall.Kevent_tevents := make([]syscall.Kevent_t, 128)kq, err := syscall.Kqueue() //创建kqueueif err!=nil {panic(err)}stdinFd := syscall.StdinstdoutFd := syscall.Stdout //设备从标准输入和标准输出流中读入数据changes = append(changes, syscall.Kevent_t{Ident: uint64(stdinFd), Filter: syscall.EVFILT_READ, Flags: syscall.EV_ADD})changes = append(changes, syscall.Kevent_t{Ident: uint64(stdoutFd), Filter: syscall.EVFILT_WRITE, Flags: syscall.EV_ADD})//设置读写事件并加入到监听事件列表中var nev, nread, nwrite int //准备就绪的事件数、已读字节数、已写字节数var buffer []bytefor {nev, err = syscall.Kevent(kq, changes, events, nil)if err != nil && err != syscall.EINTR {log.Fatal(err)}for i := 0; i<nev; i++ {event := events[i]ev_fd := int(event.Ident)if err := syscall.SetNonblock(ev_fd, true); err != nil {//设置为非阻塞模式,保证输入输出缓冲区有数据就绪就写入写出,避免阻塞影响性能panic(err)}if ev_fd == syscall.Stdin && nread < BufferSize { //输入流就绪且缓冲区还有数据继续读buffer, err = ioutil.ReadAll(os.Stdin)   //存疑,不知道为什么直接调用systm.Read无法从标准输入读取数据//if err != nil {// panic(err)//}if len(buffer) == 0 {panic("no data read!")}nread += len(buffer)}if ev_fd == syscall.Stdout && nread > 0 {  //输出流就绪且缓冲区还能继续写入nwrite, err = syscall.Write(ev_fd, buffer)if err != nil {panic(err)}if nwrite <= 0 {panic("no data write")}buffer = buffer[nwrite:]nread -= nwrite}}}}

程序运行结果

可以看到,程序会检测标准输入或者输出的就绪状态,将标准输入的数据存到buffer中,并在标准输出就绪且buffer内存有值时直接输出到标准输出流。
注意将stdin和stdout设置为非阻塞,这是因为我们希望数据有多少就绪就读多少,能写进多少就写多少,避免read和write函数阻塞影响性能。

go实现Kqueue和IO复用相关推荐

  1. 使用多线程还是用IO复用select/epoll? epoll 或者 kqueue 的原理是什么?

    原作者:蓝形参 原文:http://www.zhihu.com/question/20114168/answer/14024115 使用多线程还是用IO复用select/epoll? 多线程模型适用于 ...

  2. 多路IO复用模型 select epoll 等

    同步阻塞IO在等待数据就绪上花去太多时间,而传统的同步非阻塞IO虽然不会阻塞进程,但是结合轮询来判断数据是否就绪仍然会耗费大量的CPU时间. 多路IO复用提供了对大量文件描述符进行就绪检查的高性能方案 ...

  3. 深入理解Linux IO复用之epoll

    作者:后端技术指南针 来自:后端技术指南针 0.概述 通过本篇文章将了解到以下内容: I/O复用的定义和产生背景Linux系统的I/O复用工具epoll设计的基本构成epoll高性能的底层实现epol ...

  4. Linux小知识---常见的IO复用技术

    IO即为网络I/O,多路即为多个TCP连接,复用即为共用一个线程或者进程,模型最大的优势是系统开销小,不必创建也不必维护过多的线程或进程. 简单来说,就是一个线程,负责处理多路数据.即监视一组描述符, ...

  5. Redis网络多路IO复用以及底层原理

    老早听说过Redis是单线程,但指的是什么单线程,为什么单线程,底层实现原理是什么? 单线程指的是Redis中处理网络请求的模块是单线程处理的,并非指整一个Redis软件都是单线程,肯定有其它线程做其 ...

  6. Linux非阻塞IO(二)网络编程中非阻塞IO与IO复用模型结合

    上文描述了最简易的非阻塞IO,采用的是轮询的方式,这节我们使用IO复用模型. 阻塞IO 过去我们使用IO复用与阻塞IO结合的时候,IO复用模型起到的作用是并发监听多个fd. 以简单的回射服务器为例,我 ...

  7. Select、Poll、Epoll IO复用技术

    我们之前采用的多进程方式实现的服务器端,一次创建多个工作子进程来给客户端提供服务.其实这种方式是存在问题的. 可以打个比方:如果我们先前创建的几个进程承载不了目前快速发展的业务的话,是不是还得增加进程 ...

  8. linux io端口复用,Linux系统IO复用接口(select、poll、epoll)

    epoll仅仅是一个异步事件的通知机制,其本身并不作任何的IO读写操作,它只负责告诉你是不是可以读或可以写了,而具体的读写操作,还要应用程序自己来完成.epoll仅提供这种机制是非常好的,它保持了事件 ...

  9. java io复用_学习Java编程-IO复用

    原标题:学习Java编程-IO复用 对于服务器的并发处理能力,我们需要的是:每一毫秒服务器都能及时处理这一毫秒内收到的数百个不同TCP连接上的报文,与此同时,可能服务器上还有数以十万计的最近几秒没有收 ...

最新文章

  1. 设计模式之工厂模式和抽象工厂模式
  2. python3 爬虫 requests安装_BOSS直聘招聘信息获取之爬虫工具分析
  3. XML和HTML的不同点
  4. phpcms ajax 调取文章内容,Phpcms V9列表页使用GET标签调用指定文章内容的方法
  5. L1-008. 求整数段和-PAT团体程序设计天梯赛GPLT
  6. PR Lumetri颜色
  7. 看完浪曦相关视频后的感受
  8. Markdown编辑器——Editor.md的使用
  9. Fiddler设置服务代理后手机不能上网的问题
  10. Validation校验属性格式
  11. 如何提高网页的加载速度 ——优化网页图片加载
  12. 交互设计师需要具备什么样的专业能力
  13. JavaScript中栈内存与堆内存分别是什么?
  14. 液化气瓶爆炸总发生,要为监管敲警钟
  15. EMC测试中的电流探头
  16. MySQL学习笔记——第3章 数据表的管理和表中数据操纵
  17. CMU 15-445/645-Note6-执行篇-Query Execution
  18. 屏幕小于6英寸的手机_6寸以上屏幕手机有哪些?
  19. CS5211eDP转LVDS转接板方案|CS5211eDP转LVDS接口方案设计参考电路图
  20. 贝尔商道赚钱思维36道第26道:全球欠缺的财商教育

热门文章

  1. 公交IC卡对乘客不利的15个方面
  2. 在 1G 内存的计算机中能否 malloc(1.2G)
  3. WordPress网站如何进行gzip压缩
  4. 9.针对Linux的8种最佳免费防病毒程序
  5. 网络安全应急响应流程图
  6. js 区分鼠标左右键点击
  7. 常见的计算机网络面试题
  8. JMeter循环控制器的使用
  9. wxpython应用程序对象与顶级窗口_wxPython学习笔记(二)
  10. SwiftUI入门推荐