# Swoole协程之旅-后篇
本篇我们开始深入PHP来分析Swoole协程的驱动部分,也就是C栈部分。
由于我们系统存在C栈和PHP栈两部分,约定名字:
* C协程 C栈管理部分,
* PHP协程 PHP栈管理部分。
增加C栈是4.x协程最重要也是最关键的部分,之前的版本种种无法完美支持PHP语法也是由于没有保存C栈信息。接下来我们将展开分析,C栈切换的支持最初我们是使用腾讯出品[libco](https://github.com/Tencent/libco "libco")来支持,但通过压测会有内存读写错误而且开源社区很不活跃,有问题无法得到及时的反馈处理,所以,我们剥离的c++ boost库的汇编部分,现在的协程C栈的驱动就是在这个基础上做的。
先来一张简单的系统架构图。
![Swoole4.x架构图](https://wiki.swoole.com/static/uploads/wiki/201901/29/421430900750.png "Swoole4.x架构图")可以发现,Swoole的角色是粘合在系统API和php ZendVM,给PHPer用户深度接口编写高性能的代码;不仅如此,也支持给C++/C用户开发使用,详细请参考文档[C++开发者如何使用Swoole](https://wiki.swoole.com/wiki/page/633.html "C++开发者如何使用Swoole")。 C部分的代码主要分为几个部分
1. 汇编ASM驱动
2. Conext 上下文封装
3. Socket协程套接字封装
4. PHP Stream系封装,可以无缝协程化PHP相关函数
5. ZendVM结合层
Swoole底层系统层次更加分明,Socket将作为整个网络驱动的基石,原来的版本中,每个客户端都要基于异步回调的方式维护上下文,所以4.x版本较之前版本比较,无论是从项目的复杂程度,还是系统的稳定性,可以说都有一个质的飞跃。 代码目录层级
~~~
$ tree swoole-src/src/coroutine/
swoole-src/src/coroutine/
├── base.cc //C协程API,可回调PHP协程API
├── channel.cc //channel
├── context.cc //协程实现 基于ASM make_fcontext jump_fcontext
├── hook.cc //hook
└── socket.cc //网络操作协程封装
swoole-src/swoole_coroutine.cc //ZendVM相关封装,PHP协程API
~~~
我们从用户层到系统至上而下有 PHP协程API, C协程API, ASM协程API。其中Socket层是兼容系统API的网络封装。我们至下而上进行分析。 ASM x86-64架构为例,共有16个64位通用寄存器,各寄存器及用途如下
* %rax 通常用于存储函数调用的返回结果,同时也用于乘法和除法指令中。在imul 指令中,两个64位的乘法最多会产生128位的结果,需要 %rax 与 %rdx 共同存储乘法结果,在div 指令中被除数是128 位的,同样需要%rax 与 %rdx 共同存储被除数。
* %rsp 是堆栈指针寄存器,通常会指向栈顶位置,堆栈的 pop 和push 操作就是通过改变 %rsp 的值即移动堆栈指针的位置来实现的。
* %rbp 是栈帧指针,用于标识当前栈帧的起始位置
* %rdi, %rsi, %rdx, %rcx,%r8, %r9 六个寄存器用于存储函数调用时的6个参数
* %rbx,%r12,%r13,%14,%15 用作数据存储,遵循被调用者使用规则
* %r10,%r11 用作数据存储,遵循调用者使用规则
也就是说在进入汇编函数后,第一个参数值已经放到了 %rdi 寄存器中,第二个参数值已经放到了 %rsi 寄存器中,并且栈指针 %rsp 指向的位置即栈顶中存储的是父函数的返回地址 x86-64使用swoole-src/thirdparty/boost/asm/make\_x86\_64\_sysv\_elf\_gas.S
~~~
//在当前栈顶创建一个上下文,用来执行执行第三个参数函数fn,返回初始化完成后的执行环境上下文
fcontext_t make_fcontext(void *sp, size_t size, void (*fn)(intptr_t));
make_fcontext:
/* first arg of make_fcontext() == top of context-stack */
movq %rdi, %rax
/* shift address in RAX to lower 16 byte boundary */
andq $-16, %rax
/* reserve space for context-data on context-stack */
/* size for fc_mxcsr .. RIP + return-address for context-function */
/* on context-function entry: (RSP -0x8) % 16 == 0 */
leaq -0x48(%rax), %rax
/* third arg of make_fcontext() == address of context-function */
movq %rdx, 0x38(%rax)
/* save MMX control- and status-word */
stmxcsr (%rax)
/* save x87 control-word */
fnstcw 0x4(%rax)
/* compute abs address of label finish */
leaq finish(%rip), %rcx
/* save address of finish as return-address for context-function */
/* will be entered after context-function returns */
movq %rcx, 0x40(%rax)
ret /* return pointer to context-data * 返回rax指向的栈底指针,作为context返回/
~~~
~~~
//将当前上下文(包括栈指针,PC程序计数器以及寄存器)保存至*ofc,从nfc恢复上下文并开始执行。
intptr_t jump_fcontext(fcontext_t *ofc, fcontext_t nfc, intptr_t vp, bool preserve_fpu = false);
jump_fcontext:
//保存当前寄存器,压栈
pushq %rbp /* save RBP */
pushq %rbx /* save RBX */
pushq %r15 /* save R15 */
pushq %r14 /* save R14 */
pushq %r13 /* save R13 */
pushq %r12 /* save R12 */
/* prepare stack for FPU */
leaq -0x8(%rsp), %rsp
/* test for flag preserve_fpu */
cmp $0, %rcx
je 1f
/* save MMX control- and status-word */
stmxcsr (%rsp)
/* save x87 control-word */
fnstcw 0x4(%rsp)
1:
/* store RSP (pointing to context-data) in RDI 保存当前栈顶到rdi 即:将当前栈顶指针保存到第一个参数%rdi ofc中*/
movq %rsp, (%rdi)
/* restore RSP (pointing to context-data) from RSI 修改栈顶地址,为新协程的地址 ,rsi为第二个参数地址 */
movq %rsi, %rsp
/* test for flag preserve_fpu */
cmp $0, %rcx
je 2f
/* restore MMX control- and status-word */
ldmxcsr (%rsp)
/* restore x87 control-word */
fldcw 0x4(%rsp)
2:
/* prepare stack for FPU */
leaq 0x8(%rsp), %rsp
// 寄存器恢复
popq %r12 /* restrore R12 */
popq %r13 /* restrore R13 */
popq %r14 /* restrore R14 */
popq %r15 /* restrore R15 */
popq %rbx /* restrore RBX */
popq %rbp /* restrore RBP */
/* restore return-address 将返回地址放到 r8 寄存器中 */
popq %r8
/* use third arg as return-value after jump*/
movq %rdx, %rax
/* use third arg as first arg in context function */
movq %rdx, %rdi
/* indirect jump to context */
jmp *%r8
~~~
context管理位于context.cc,是对ASM的封装,提供两个API
~~~
bool Context::SwapIn()
bool Context::SwapOut()
~~~
最终的协程API位于base.cc,最主要的API为
~~~
//创建一个c栈协程,并提供一个执行入口函数,并进入函数开始执行上下文
//例如PHP栈的入口函数Coroutine::create(PHPCoroutine::create_func, (void*) &php_coro_args);
long Coroutine::create(coroutine_func_t fn, void* args = nullptr);
//从当前上下文中切出,并且调用钩子函数 例如php栈切换函数 void PHPCoroutine::on_yield(void *arg)
void Coroutine::yield()
//从当前上下文中切入,并且调用钩子函数 例如php栈切换函数 void PHPCoroutine::on_resume(void *arg)
void Coroutine::resume()
//C协程执行结束,并且调用钩子函数 例如php栈清理 void PHPCoroutine::on_close(void *arg)
void Coroutine::close()
~~~
接下来是ZendVM的粘合层 位于swoole-src/swoole\_coroutine.cc
~~~
PHPCoroutine 供C协程或者底层接口调用
//PHP协程创建入口函数,参数为php函数
static long create(zend_fcall_info_cache *fci_cache, uint32_t argc, zval *argv);
//C协程创建API
static void create_func(void *arg);
//C协程钩子函数 上一部分base.cc的C协程会关联到以下三个钩子函数
static void on_yield(void *arg);
static void on_resume(void *arg);
static void on_close(void *arg);
//PHP栈管理
static inline void vm_stack_init(void);
static inline void vm_stack_destroy(void);
static inline void save_vm_stack(php_coro_task *task);
static inline void restore_vm_stack(php_coro_task *task);
//输出缓存管理相关
static inline void save_og(php_coro_task *task);
static inline void restore_og(php_coro_task *task);
~~~
有了以上基础部分的建设,结合我们上一篇文章中PHP内核执行栈管理,就可以从C协程驱动PHP协程,实现C栈+PHP栈的双栈的原生协程。
下一篇文章,我们将挑一个客户端实现分析socket层,把协程和Swoole事件驱动结合来分析C协程以及PHP协程在底层网络库的应用和实践。
- 序言
- 入门指引
- 环境依赖
- 编译安装
- 编译参数
- 常见错误
- Cygwin
- Linux二进制包
- 快速起步
- 创建TCP服务器
- 创建UDP服务器
- 创建Web服务器
- 创建WebSocket服务器
- 设置定时器
- 执行异步任务
- 创建同步TCP客户端
- 创建异步TCP客户端
- 网络通信协议设计
- 使用异步客户端
- 多进程共享数据
- 使用协程客户端
- 协程:并发 shell_exec
- 协程:Go + Chan + Defer
- 协程:实现 Go 语言风格的 defer
- 协程:实现 sync.WaitGroup 功能
- 编程须知
- sleep/usleep的影响
- exit/die函数的影响
- while循环的影响
- stat缓存清理
- mt_rand随机数
- 进程隔离
- 版本更新记录
- 4.3.1
- 4.3.0 [大版本]
- 4.2.13
- 4.2.12
- 4.2.11
- 4.2.10
- 4.2.9
- 4.2.8
- 4.2.7
- 4.2.0
- 4.1.0
- 4.0.1
- 4.0.0
- 向下不兼容改动
- 新特性使用
- 4.3.0 在 Process 中使用协程
- 4.3.0 延时事件机制改进
- 2.1.2 进程池模块的使用
- 1.9.24 调度支持 Stream 模式
- 1.9.24 异步客户端自动解析域名
- 1.9.17 支持异步安全重启特性
- 1.9.14 使用异步客户端超时机制
- 1.8.0 使用内置Http异步客户端
- 1.7.16 使用迭代器遍历Server所有连接
- 1.7.5 在Server中使用swoole_table
- 1.7.5 swoole_client支持sendfile接口
- 1.7.4 SSL隧道加密TCP-Server
- 1.7.4 task进程中使用毫秒定时器
- 1.7.3 固定包头+包体协议自动分包
- 1.7.3 onTask直接return取代finish函数
- 1.7.2 swoole_process多进程模块的使用
- 1.7.2 task进程使用消息队列
- 项目路线图
- php.ini选项
- 内核参数调整
- 开发者列表
- 衍生开源项目
- 框架
- 工具
- 分布式
- 通信协议
- 用户与案例
- 物联网项目
- 网络游戏
- 腾讯(Tencent)
- 百度(Baidu.com)
- 阅文集团
- BiliBili(哔哩哔哩)
- 车轮互联(chelun.com)
- (捞月狗) 游戏社区
- 儒博(roobo.com)
- 提交错误报告
- 常见问题
- 升级swoole版本的常见问题
- 生成可分发的二进制swoole版本
- 在phpinfo中有在php -m中没有
- Connection refused是怎么回事
- Resource temporarily unavailable [11]
- Cannot assign requested address [99]
- swoole与node.js相比有哪些优势
- swoole与golang相比有哪些优势
- pcre.h: No such file or directory
- undefined symbol: __sync_bool_compare_and_swap_4
- 学习Swoole需要掌握哪些基础知识
- 同步阻塞与异步非阻塞适用场景
- PHP7环境下出现zend_mm_heap corrupted
- Swoole 项目起源和名字由来
- '__builtin_saddl_overflow' was not declared in this scope
- Server
- 函数列表
- Server::__construct
- Server->set
- Server->on
- Server->addListener
- Server->addProcess
- Server->listen
- Server->start
- Server->reload
- Server->stop
- Server->shutdown
- Server->tick
- Server->after
- Server->defer
- Server->clearTimer
- Server->close
- Server->send
- Server->sendfile
- Server->sendto
- Server->sendwait
- Server->sendMessage
- Server->exist
- Server->pause
- Server->resume
- Server->getClientInfo
- Server->getClientList
- Server->bind
- Server->stats
- Server->task
- Server->taskwait
- Server->taskWaitMulti
- Server->taskCo
- Server->finish
- Server->heartbeat
- Server->getLastError
- Server->getSocket
- Server->protect
- Server->confirm
- 属性列表
- Server::$setting
- Server::$master_pid
- Server::$manager_pid
- Server::$worker_id
- Server::$worker_pid
- Server::$taskworker
- Server::$connections
- Server::$ports
- 配置选项
- reactor_num
- worker_num
- max_request
- max_conn (max_connection)
- task_worker_num
- task_ipc_mode
- task_max_request
- task_tmpdir
- dispatch_mode
- dispatch_func
- message_queue_key
- daemonize
- backlog
- log_file
- log_level
- heartbeat_check_interval
- heartbeat_idle_time
- open_eof_check
- open_eof_split
- package_eof
- open_length_check
- package_length_type
- package_length_func
- package_max_length
- open_cpu_affinity
- cpu_affinity_ignore
- open_tcp_nodelay
- tcp_defer_accept
- ssl_cert_file
- ssl_method
- ssl_ciphers
- user
- group
- chroot
- pid_file
- pipe_buffer_size
- buffer_output_size
- socket_buffer_size
- enable_unsafe_event
- discard_timeout_request
- enable_reuse_port
- enable_delay_receive
- open_http_protocol
- open_http2_protocol
- open_websocket_protocol
- open_mqtt_protocol
- open_websocket_close_frame
- reload_async
- tcp_fastopen
- request_slowlog_file
- enable_coroutine
- max_coroutine
- task_enable_coroutine
- ssl_verify_peer
- 监听端口
- 可选参数
- 可选回调
- 连接迭代器
- 预定义常量
- 事件回调函数
- onStart
- onShutdown
- onWorkerStart
- onWorkerStop
- onWorkerExit
- onConnect
- onReceive
- onPacket
- onClose
- onBufferFull
- onBufferEmpty
- onTask
- onFinish
- onPipeMessage
- onWorkerError
- onManagerStart
- onManagerStop
- 高级特性
- 改变Worker进程的用户/组
- 回调函数中的 reactor_id 和 fd
- Length_Check 和 EOF_Check 的使用
- Worker与Reactor通信模式
- TCP-Keepalive死连接检测
- TCP服务器心跳维持方案
- 多端口监听的使用
- 捕获Server运行期致命错误
- Server内存管理机制
- Server的两种运行模式介绍
- Server中对象的4层生命周期
- 在worker进程内监听一个Server端口
- 在php-fpm/apache中使用task功能
- 常见问题
- 为什么不要send完后立即close
- 如何在回调函数中访问外部的变量
- 是否可以共用1个redis或mysql连接
- 关于onConnect/onReceive/onClose顺序
- 4种PHP回调函数风格
- 不同的Server程序实例间如何通信
- 错误信息:ERROR (9006)
- eventLoop has already been created. unable to create swoole_server
- 压力测试
- 并发10万TCP连接的测试
- PHP7+Swoole/Nginx/Golang性能对比
- 全球Web框架权威性能测试 Techempower Web Framework Benchmarks
- Coroutine
- Coroutine
- Coroutine::set
- Coroutine::stats
- Coroutine::create
- Coroutine::exist
- Coroutine::getCid
- Coroutine::getPcid
- Coroutine::getContext
- Coroutine::defer
- Coroutine::list
- Coroutine::getBackTrace
- Coroutine::yield
- Coroutine::resume
- Coroutine::fread
- Coroutine::fgets
- Coroutine::fwrite
- Coroutine::sleep
- Coroutine::gethostbyname
- Coroutine::getaddrinfo
- Coroutine::exec
- Coroutine::readFile
- Coroutine::writeFile
- Coroutine::statvfs
- Coroutine\Channel
- Coroutine\Channel->__construct
- Coroutine\Channel->push
- Coroutine\Channel->pop
- Coroutine\Channel->stats
- Coroutine\Channel->close
- Coroutine\Channel->length
- Coroutine\Channel->isEmpty
- Coroutine\Channel->isFull
- Coroutine\Channel->$capacity
- Coroutine\Channel->$errCode
- Coroutine\Client
- Coroutine\Client->connect
- Coroutine\Client->send
- Coroutine\Client->recv
- Coroutine\Client->close
- Coroutine\Client->peek
- Coroutine\Http\Client
- 属性列表
- Coroutine\Http\Client->get
- Coroutine\Http\Client->post
- Coroutine\Http\Client->upgrade
- Coroutine\Http\Client->push
- Coroutine\Http\Client->recv
- Coroutine\Http\Client->addFile
- Coroutine\Http\Client->addData
- Coroutine\Http\Client->download
- Coroutine\Http2\Client
- Coroutine\Http2\Client->__construct
- Coroutine\Http2\Client->set
- Coroutine\Http2\Client->connect
- Coroutine\Http2\Client->send
- Coroutine\Http2\Client->write
- Coroutine\Http2\Client->recv
- Coroutine\Http2\Client->close
- Coroutine\Redis
- Coroutine\Redis::__construct
- Coroutine\Redis::setOptions
- 属性列表
- 事务模式
- 订阅模式
- Coroutine\Socket
- Coroutine\Socket::__construct
- Coroutine\Socket->bind
- Coroutine\Socket->listen
- Coroutine\Socket->accept
- Coroutine\Socket->connect
- Coroutine\Socket->send
- Coroutine\Socket->sendAll
- Coroutine\Socket->recv
- Coroutine\Socket->recvAll
- Coroutine\Socket->sendto
- Coroutine\Socket->recvfrom
- Coroutine\Socket->getsockname
- Coroutine\Socket->getpeername
- Coroutine\Socket->close
- Coroutine\MySQL
- 属性列表
- Coroutine\MySQL->connect
- Coroutine\MySQL->query
- Coroutine\MySQL->prepare
- Coroutine\MySQL->escape
- Coroutine\MySQL->begin
- Coroutine\MySQL->commit
- Coroutine\MySQL->rollback
- Coroutine\MySQL\Statement->execute
- Coroutine\MySQL\Statement->fetch
- Coroutine\MySQL\Statement->fetchAll
- Coroutine\MySQL\Statement->nextResult
- Coroutine\PostgreSQL
- Coroutine\PostgreSQL->connect
- Coroutine\PostgreSQL->query
- Coroutine\PostgreSQL->fetchAll
- Coroutine\PostgreSQL->affectedRows
- Coroutine\PostgreSQL->numRows
- Coroutine\PostgreSQL->fetchObject
- Coroutine\PostgreSQL->fetchAssoc
- Coroutine\PostgreSQL->fetchArray
- Coroutine\PostgreSQL->fetchRow
- Coroutine\PostgreSQL->metaData
- Coroutine\PostgreSQL->prepare
- Server
- 并发调用
- setDefer 机制
- 子协程+通道
- 实现原理
- 协程与线程
- 发送数据协程调度
- 协程内存开销
- 4.0 协程实现原理
- 协程客户端超时规则
- 协程执行流程
- 常见问题
- 运行中出现 Fatal error: Maximum function nesting level of '1000' reached, aborting!
- 为什么只能在回调函数中使用协程客户端
- 支持协程的回调方法列表
- 错误信息: XXXX client has already been bound to another coroutine
- Swoole4 协程与 PHP 的 Yield/Generator 协程有什么区别
- Swoole4 协程与 Go 协程有哪些区别
- 编程须知
- 在多个协程间共用同一个协程客户端
- 禁止使用协程 API 的场景(2.x 版本)
- 使用类静态变量/全局变量保存上下文
- 退出协程
- 异常处理
- 扩展组件
- MongoDB
- 编程调试
- Runtime
- 文件操作
- 睡眠函数
- 开关选项
- 严格模式
- Timer
- swoole_timer_tick
- swoole_timer_after
- swoole_timer_clear
- Memory
- Lock
- swoole_lock->__construct
- swoole_lock->lock
- swoole_lock->trylock
- swoole_lock->unlock
- swoole_lock->lock_read
- swoole_lock->trylock_read
- swoole_lock->lockwait
- Buffer
- swoole_buffer->__construct
- swoole_buffer->append
- swoole_buffer->substr
- swoole_buffer->clear
- swoole_buffer->expand
- swoole_buffer->write
- swoole_buffer->read
- swoole_buffer->recycle
- Table
- Table->__construct
- Table->column
- Table->create
- Table->set
- Table->incr
- Table->decr
- Table->get
- Table->exist
- Table->count
- Table->del
- Atomic
- swoole_atomic->__construct
- swoole_atomic->add
- swoole_atomic->sub
- swoole_atomic->get
- swoole_atomic->set
- swoole_atomic->cmpset
- swoole_atomic->wait
- swoole_atomic->wakeup
- mmap
- swoole_mmap::open
- Channel
- Channel->__construct
- Channel->push
- Channel->pop
- Channel->stats
- Serialize
- swoole_serialize::pack
- swoole_serialize::unpack
- Http\Server
- Http\Server
- Http\Server->on
- Http\Server->start
- Http\Request
- Http\Request->$header
- Http\Request->$server
- Http\Request->$get
- Http\Request->$post
- Http\Request->$cookie
- Http\Request->$files
- Http\Request->rawContent
- Http\Request->getData
- Http\Response
- Http\Response->header
- Http\Response->cookie
- Http\Response->status
- Http\Response->gzip
- Http\Response->redirect
- Http\Response->write
- Http\Response->sendfile
- Http\Response->end
- Http\Response->detach
- Http\Response::create
- 配置选项
- upload_tmp_dir
- http_parse_post
- document_root
- http_compression
- 常见问题
- CURL发送POST请求服务器端超时
- 使用Chrome访问服务器会产生2次请求
- GET/POST请求的最大尺寸
- WebSocket\Server
- 回调函数
- onHandShake
- onOpen
- onMessage
- 函数列表
- WebSocket\Server->push
- WebSocket\Server->exist
- WebSocket\Server::pack
- WebSocket\Server::unpack
- WebSocket\Server->disconnect
- WebSocket\Server->isEstablished
- 预定义常量
- 常见问题
- 配置选项
- WebSocket\Frame
- Redis\Server
- 方法
- Redis\Server->setHandler
- Redis\Server::format
- 常量
- Process
- Process::__construct
- Process->start
- Process->name
- Process->exec
- Process->write
- Process->read
- Process->setTimeout
- Process->setBlocking
- Process->useQueue
- Process->statQueue
- Process->freeQueue
- Process->push
- Process->pop
- Process->close
- Process->exit
- Process::kill
- Process::wait
- Process::daemon
- Process::signal
- Process::alarm
- Process::setAffinity
- Process::exportSocket
- Process\Pool
- Process\Pool::__construct
- Process\Pool->on
- Process\Pool->listen
- Process\Pool->write
- Process\Pool->start
- Process\Pool->getProcess
- Client
- 方法列表
- swoole_client::__construct
- swoole_client->set
- swoole_client->on
- swoole_client->connect
- swoole_client->isConnected
- swoole_client->getSocket
- swoole_client->getSockName
- swoole_client->getPeerName
- swoole_client->getPeerCert
- swoole_client->send
- swoole_client->sendto
- swoole_client->sendfile
- swoole_client->recv
- swoole_client->close
- swoole_client->sleep
- swoole_client->wakeup
- swoole_client->enableSSL
- 回调函数
- onConnect
- onError
- onReceive
- onClose
- onBufferFull
- onBufferEmpty
- 属性列表
- swoole_client->errCode
- swoole_client->sock
- swoole_client->reuse
- 并行
- swoole_client_select
- TCP客户端异步连接
- SWOOLE_KEEP建立TCP长连接
- 常量
- 配置选项
- ssl_verify_peer
- ssl_host_name
- ssl_cafile
- ssl_capath
- package_length_func
- http_proxy_host
- 常见问题
- Event
- swoole_event_add
- swoole_event_set
- swoole_event_isset
- swoole_event_write
- swoole_event_del
- swoole_event_exit
- swoole_event_defer
- swoole_event_cycle
- swoole_event_wait
- swoole_event_dispatch
- 常见问题
- epoll_wait 偶尔会用很长时间
- 异步回调
- 异步文件系统IO
- swoole_async_readfile
- swoole_async_writefile
- swoole_async_read
- swoole_async_write
- swoole_async_dns_lookup
- swoole_async::exec
- 异步MySQL客户端
- swoole_mysql->__construct
- swoole_mysql->on
- swoole_mysql->connect
- swoole_mysql->escape
- swoole_mysql->query
- swoole_mysql->begin
- swoole_mysql->commit
- swoole_mysql->rollback
- swoole_mysql->close
- 异步Redis客户端
- swoole_redis->__construct
- swoole_redis->on
- swoole_redis->connect
- swoole_redis->__call
- swoole_redis->close
- 异步Http/WebSocket客户端
- swoole_http_client->__construct
- swoole_http_client->set
- swoole_http_client->setMethod
- swoole_http_client->setHeaders
- swoole_http_client->setCookies
- swoole_http_client->setData
- swoole_http_client->addFile
- swoole_http_client->get
- swoole_http_client->post
- swoole_http_client->upgrade
- swoole_http_client->push
- swoole_http_client->execute
- swoole_http_client->download
- swoole_http_client->close
- 异步Http2.0客户端
- swoole_http2_client->__construct
- swoole_http2_client->get
- swoole_http2_client->post
- swoole_http2_client->setHeaders
- swoole_http2_client->setCookies
- 高级
- Swoole的实现
- Reactor线程
- Manager进程
- Worker进程
- Reactor、Worker、TaskWorker的关系
- Task/Finish特性的用途
- 在php-fpm或apache中使用swoole
- Swoole异步与同步的选择
- TCP/UDP压测工具
- swoole服务器如何做到无人值守100%可用
- MySQL的连接池、异步、断线重连
- PHP中哪些函数是同步阻塞的
- 守护进程程序常用数据结构
- 队列(Queue)
- 堆(Heap)
- 定长数组(SplFixedArray)
- 使用jemalloc优化swoole内存分配性能
- C开发者如何使用Swoole
- C++开发者如何使用Swoole
- 使用systemd管理swoole服务
- 网卡中断设置
- 将Swoole静态编译内嵌到PHP
- 异步回调程序内存管理
- 日志等级控制
- 使用 asan 内存检测
- Windows编译
- Swoole协程之旅-前篇
- Swoole协程之旅-中篇
- Swoole协程之旅-后篇
- 协程CPU密集场景调度实现
- 其他
- 函数列表
- swoole_set_process_name
- swoole_version
- swoole_strerror
- swoole_errno
- swoole_get_local_ip
- swoole_clear_dns_cache
- swoole_get_local_mac
- swoole_cpu_num
- swoole_last_error
- Swoole社区
- Swoole技术会议
- 工作组(Working Groups)
- 参与开源项目指引
- 捐赠Swoole项目
- 加入Swoole开发组
- 非协程特性独立扩展 (swoole_async)
- 附录:Linux信号列表
- 附录:Linux错误码(errno)列表
- 附录:Swoole错误码列表
- 附录:TCP连接的状态
- 附录:tcpdump抓包工具的使用
- 附录:strace工具的使用
- 附录:gdb工具的使用
- 附录:lsof工具的使用
- 附录:perf工具的使用
- 附录:编译PHP扩展的相关工具
- 备用:已移除的历史特性
- swoole_server->handler
- task_worker_max
- swoole_server->addtimer
- swoole_server->deltimer
- onTimer
- swoole_timer_add
- swoole_timer_del
- swoole_get_mysqli_sock
- swoole_mysql_query
- onMasterConnect
- onMasterClose
- Nginx/Golang/Swoole/Node.js的性能对比
- Coroutine::call_user_func
- Coroutine::call_user_func_array
- Coroutine\Channel::select
- task_async
- 历史:版本更新记录(1.x)
- 1.10.3
- 1.10.2
- 1.10.1
- 1.10.0
- 1.9.23
- 1.9.22
- 1.9.19
- 1.9.18
- 1.9.17
- 1.9.16
- 1.9.15
- 1.9.14
- 1.9.12
- 1.9.11
- 1.9.9
- 1.9.7
- 1.9.6
- 1.9.5
- 1.9.4
- 1.9.3
- 1.9.2
- 1.9.1
- 1.9.0
- 1.8.13
- 1.8.12
- 1.8.11
- 1.8.10
- 1.8.9
- 1.8.8
- 1.8.7
- 1.8.6
- 1.8.5
- 1.8.4
- 1.8.3
- 1.8.2
- 1.8.1
- 1.8.0
- 1.7.22
- 1.7.21
- 1.7.20
- 1.7.19
- 1.7.18
- 1.7.17
- 1.7.16
- 1.7.15
- 1.7.14
- 1.7.13
- 1.7.12
- 1.7.11
- 1.7.10
- 1.7.9
- 1.7.8
- 1.7.7
- 1.7.6
- 1.7.5
- v1.5
- v1.6
- v1.7
- 历史:版本更新记录(2.x)
- 2.0.1-Alpha
- 2.0.5
- 2.0.9
- 1.9.21
- 2.0.10
- 2.0.11
- 2.0.12
- 2.0.13
- 2.1.1
- 2.1.2
- 2.2.0
- 3.0.0
- 历史:版本更新记录(4.x)
- 4.0.3
- 4.0.2
- 4.0.4
- 4.1.1
- 4.1.2
- 4.2.1
- 4.2.2
- 4.2.3
- 4.2.4
- 4.2.5
- 4.2.6
- 4.2.7
- 4.2.9
- 4.2.8
- 社区文档版权申明
- 社区文档编辑条例