× 警告!旧版文档已经暂停维护,请查看新版文档。点击前往新版文档

Process->write

向管道内写入数据。

function Process->write(string $data) int | bool;
  • 在子进程内调用write,父进程可以调用read接收此数据
  • 在父进程内调用write,子进程可以调用read接收此数据

Swoole底层使用Unix Socket实现通信,Unix Socket是内核实现的全内存通信,无任何IO消耗。在1进程write,1进程read,每次读写1024字节数据的测试中,100万次通信仅需1.02秒。

管道通信默认的方式是流式,write写入的数据在read可能会被底层合并。可以设置swoole_process构造函数的第三个参数为2改变为数据报式。

参数

  • $data要发送的数据,最大长度参见下方文档

返回值

  • 发送成功返回字节数
  • 发送失败返回false,可以使用swoole_last_error()获取错误码

Linux

Linux系统下,write最大可以发送的长度,取决于 net.core.wmem_maxnet.core.wmem_default的内核设置。

  • 未修改SNDBUF_SIZE Socket参数设置时,发送长度为net.core.wmem_default * 2
  • 可修改SNDBUF_SIZE,改变单次发送的上限,最大不超过4M

MacOS/FreeBSD

  • 设置net.local.dgram.maxdgram内核参数修改DGRAM类型管道最大单次发送长度
  • 设置net.local.dgram.recvspace内核参数修改DGRAM类型管道的发送缓存区长度
  • 设置net.local.stream.sendspacenet.local.stream.recvspace内核参数修改STREAM类型管道的发送和接收缓存区长度

异步模式

如果进程内使用了异步IO,比如swoole_event_add,进程内执行write操作将变为异步模式。swoole底层会监听可写事件,自动完成管道写入。

异步模式下如果SOCKET缓存区已满,Swoole的处理逻辑请参考 swoole_event_write

同步模式

进程内未使用任何异步IO,当前管道为同步阻塞模式,如果缓存区已满,将阻塞等待直到write操作完成。

  • Task进程就是同步阻塞的模式,如果管道的缓存区已满,调用write时会发生阻塞

乱序丢包

很多网络文章提到DGRAM模式下会出现丢包、乱序问题,实际上这些问题仅存在于Internet网络的UDP通信。UnixSocket是Linux内核实现的内存数据队列,不会出现丢包乱序问题。write写入和read读取的顺序是完全一致的。write返回成功后一定是可以read到的。


  • Bacysoft

    “在父进程内调用write,子进程可以调用read接收此数据”,请问,如果有多个子进程,怎么办?谁先读谁获取数据,还是所有子进程都能获得数据?

  • 古月扌高

    write写入的数据在read可能会被底层合并,意思是如果多个写入者同时写入,会造成读的时候紊乱? 使用为数据报就可以规避这种问题了吗?

  • 有明

    这是通过Process对象进行的调用,一个Process对象对应的就是一个子进程,自然数据发送到的就是这个子进程。

  • 有明

    同时写入的问题应该从写入者端进行控制和限制,和管道通信方式是无关的。

  • 杜飞

    不知道靠不靠谱 用过的朋友呢

  • 刘钢Gary

    这里的管道使用 socketpair实现. 两个socket一个父一个子只适合一对一的通信, 一对多就可能造成紊乱.

  • Petrie_

    “在父进程内调用write,子进程可以调用read接收此数据”,请问,如果有多个子进程,怎么办?谁先读谁获取数据,还是所有子进程都能获得数据???

  • dawn

    这里的意思是在父进程$process->write('laaa'), 在子进程$process->read()。这两各$process是同一个对象。所以实现的是一对一的通信。