![]() |
1
dxatgp02 16 天前
学习一下
|
![]() |
2
heiher 14 天前
支持~ 我有一个 C 语言写的 SOCKS5 Server https://github.com/heiher/hev-socks5-server ,用项目中同样的性能测试方法简单测了一下 SOCKS5 的 TCP 转发性能,Linux x86_64 平台,内存使用始终稳定在 77M ,1 路连接上传、下载速率都在 32GB/s 左右,CPU 使用 63-90%,10 路连接并发速率在 130GB/s 左右,CPU 使用 870-890%。
|
![]() |
3
proxyai 14 天前
基本的身份认证如何使用?
|
![]() |
7
PTLin 1 天前
@heiher 这两天把你的协程库看了个大概。hev_task_execute 切换栈,hev_task_executer 和 hev_task_system_schedule 里 setjmp 前后对栈上 task/ctx 变量的维护和用其实现的协程切换确实很有意思。
不过我有个疑问,比如 x86 下 hev_task_executer 中,setjmp/longjmp 只会保存和恢复保留寄存器以及 rsp rip ,怎么保证 longjmp 切换上下文后,hev_task_executer 后续读取 task 变量一定从栈上读的,确保 task 变量不会被优化成寄存器变量呢? |
![]() |
9
heiher 1 天前
@PTLin 答案是各级函数调用的所有寄存器值切片都被保存并恢复了。具体展开来说,有通用寄存器的指令集架构一般会在调用约定中将寄存器分为 Caller-saved 和 Callee-saved 两类,在多级函数调用中每一级函数都可能会修改寄存器的值形成新的上下文状态。在函数中对于 Caller-saved 寄存器可以直接修改,因为 Caller 需要的寄存器旧值它自己保存了,而 Callee-saved 必须在修改前将旧值存入栈中。因此整个调用链绝大部分帧的寄存器值都已保存在栈中,只有最末级的 Callee 存在还未入栈的寄存器值。如果此时以这级作为 Caller 再调用 setjmp ,我们来考虑一下 setjmp 应该怎么实现,会发现它根本不需要保存 Caller-saved 寄存器,只需要保存 Callee-saved 寄存器以及一些并不属于以上分类且有可能被改变且影响上下文的寄存器,比如 sp 、pc 、各种 flags 等等。而后续 longjmp 回来恢复这个调用链的上下文时,也只需要再恢复 setjmp 中保存的那部分寄存器值,这样随着这个调用链再逐级弹出,所有寄存器值的完整切片均能被恢复出来。
|
![]() |
10
PTLin 15 小时 57 分钟前
@heiher 感谢回答,我也是太久没接触过调用规范了,一时间有点懵了。
总结下,这分为三种情况 1 变量在 setjmp 后从栈读取。 2 变量在 setjmp 前后都是从保留寄存器( callee saved )读取。 3 变量在 setjmp 前后都是从临时寄存器( caller saved )读取。 第一种情况自然万事大吉。 第二种情况,setjmp 会保存 callee saved ,longjmp 会恢复 callee saved ,所以寄存器值始终正确。 第三种情况,在 call setjmp 前就会把变量所在的 caller saved 寄存器压栈,而在 setjmp/longjmp 返回后会把变量代表的 caller saved 寄存器弹出。所以寄存器值始终正确。 |