版权声明:转载请注明来源 https://blog.csdn.net/u013702678/article/details/82928445
swoole_process提供的write方法用于向管道内写入数据,其使用的形式如下。
int swoole_process->write(string $data);
$data
的长度在Linux
系统下最大不超过8K
,MacOS/FreeBSD
下最大不超过2K
- 在子进程内调用
write
,父进程可以调用read
接收此数据 - 在父进程内调用
write
,子进程可以调用read
接收此数据
下面我们分析下其使用流程。
static PHP_METHOD(swoole_process, write)
{
char *data = NULL;
zend_size_t data_len = 0;
//解析输入参数,这里输入参数只有data字段,表示要发送的数据信息
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len) == FAILURE)
{
RETURN_FALSE;
}
if (data_len < 1)//发送数据的长度异常
{
swoole_php_fatal_error(E_WARNING, "the data to send is empty.");
RETURN_FALSE;
}
swWorker *process = swoole_get_object(getThis());//获取swoole内部封装对象
if (process->pipe == 0)
{
swoole_php_fatal_error(E_WARNING, "no pipe, can not write into pipe.");
RETURN_FALSE;
}
int ret;
//异步写,进程内使用了swoole_event_add等,这时将会通过多路复用监听去完成写操作
if (SwooleG.main_reactor)
{
swConnection *_socket = swReactor_get(SwooleG.main_reactor, process->pipe);//从多路复用管理器中获取连接信息
if (_socket && _socket->nonblock)//想要的管道可以写入,且有异步属性
{
ret = SwooleG.main_reactor->write(SwooleG.main_reactor, process->pipe, data, (size_t) data_len);//通过多路复用写入
}
else//其他
{
goto _blocking_read;//goto跳转到阻塞式写入
}
}
else//同步写,也就是阻塞式的写入,等待写入完成
{
_blocking_read: ret = swSocket_write_blocking(process->pipe, data, data_len);
}
if (ret < 0)
{
swoole_php_error(E_WARNING, "write() failed. Error: %s[%d]", strerror(errno), errno);
RETURN_FALSE;
}
ZVAL_LONG(return_value, ret);
}
int swSocket_write_blocking(int __fd, void *__data, int __len)
{
int n = 0;
int written = 0;
while (written < __len)
{
n = write(__fd, __data + written, __len - written);
if (n < 0)
{
if (errno == EINTR)
{
continue;
}
#ifdef HAVE_KQUEUE
else if (errno == EAGAIN || errno == ENOBUFS)
#else
else if (errno == EAGAIN)
#endif
{
swSocket_wait(__fd, SW_WORKER_WAIT_TIMEOUT, SW_EVENT_WRITE);
continue;
}
else
{
swSysError("write %d bytes failed.", __len);
return SW_ERR;
}
}
written += n;
}
return written;
}