从Go谈到socket API的一些思考

方圆 · · 1839 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

本文翻译自:https://idea.popcount.org/2017-02-23-socket-api-thoughts/

前一段时间,我写了篇关于select()系统调用发展历史的文章。 该文章引发了一些有趣的讨论。

文章和讨论花了我不少心思,但我最终明白了什么是核心问题:

Unix进程是否是CSP风格的进程? 文件描述符是CSP派生的“通道”吗? “select()”相当于ALT语句吗?

直接的答案是“不”。 CSP比Unix更年轻。 正如Tony Garnock-Jones指出的,关于CSP的第一篇文章发表于1978年,文件描述符自从Unix的早期就已经出现。

文件描述符不是通道,他们应该是什么? CSP channel通常是可组合的,而我认为Unix的select不是。 这是第二点:

使用“select()”的Unix程序不使用组合。 但也许他们可以用? “select()能否以允许组合性的方式实现”?

当在Golang中编程时,可以使用ALT语句和内置channel。 一般来说,golang channel是可组合的。 类似的事情在Erlang中 - 你可以通过巧妙地使用gen_server进程来避免复杂的状态机。

Unix进程模型为何不能如此? 为什么我们不能以组合Golang或Erlang相同的方式来组合Unix进程?

我会直觉地指责select系统调用,但问题更深入。

缓冲代理

我们不能放弃select? 我们可以没有它吗? 在前面的文章中我们提到了两个例子:

  • inet守护进程

  • 控制台复用

还有很多问题都离不开select。 David Wragg提到“缓冲代理”问题:

想象一个进行缓冲的进程。 考虑一个简单的程序,从一个流读取数据,缓冲它,并写入另一个流。 如果使用它们之间的管道将它拆分为两个进程,则会受到内核管道缓冲区大小的限制。 为了具有任意的缓冲区大小,它必须在单个进程中进行输入流的可读性和输出流的可写性的select操作。

克里斯·西本曼在2010年的博客中提到了同样的问题。

空闲连接的内存消耗

今年早些时候,Chris提到了另一个需要select的问题:“空闲连接的内存消耗”:

这篇文章是Evan Klitzke的文章的后续:

这个内存消耗的论点在Golang Bug跟踪器中提出:

net:在TCPConn上添加等待机制

对我来说,这听起来像在介绍回调地狱。

BSD Socket API 改造

最后,Martin Sustrick针对纯粹阻塞套接字API写了这个RFC提案:

本文没有通过推动select问题到下一层来解决问题:

该备忘录假设已经存在有效的并发实现,其创建新的轻量级进程需要最多几百纳秒并且上下文切换需要几十纳秒。 注意,已经部署了这样的并发系统。 一个着名的例子是Golang的goroutine,但也有其他可用的。

我非常喜欢只暴露阻塞API给用户的想法。

最终想法

虽然Unix socket模型和CSP已经存在了将近40年,但它们不是各自封闭的。 在这方面有很多新想法:优化内存使用,找到合适的可组合性抽象,回到暴露纯粹阻塞API。


有疑问加站长微信联系(非本文作者)

本文来自:微信公众平台

感谢作者:方圆

查看原文:从Go谈到socket API的一些思考

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1839 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传