协程库libgo原理探究hook原理

6 篇文章 0 订阅
1 篇文章 0 订阅

前言:最近学习使用协程,网上搜索一番,大多是讲协程在多个任务间切换有多好用,可能是我功底太薄,愣是摸索了很久才搞懂。现在分享下新手学习心得。

 

结论:对称协程就相当于状态机,各个协程就是各个任务,执行到阻塞操作时,比如sleep,调度的线程并不是真的一头扎进sleep函数,然后线程挂起,而是将这个任务设置为挂起状态,然后线程返回,执行其他任务去了,等sleep的时间到了,再调度过来执行后面的代码。很显然,sleep已经不是原来的sleep了,这儿是使用了hook函数(见hook函数解释)。那线程返回了,那些临时变量怎么办?sleep后回来执行怎么恢复这些数据?这里协程把临时变量声明也hook了,这些临时变量被分配保存到了堆空间。线程返回时根本就没释放!当然,协程执行完了就释放了。

hook函数:大概就是底层函数实现的时候,第一句就是判断有没设置了hook函数,就一个函数变量,如果是NULL,那就啥事没有执行具体操作,如果设置了,那就先调用你设置的函数。所以hook可以用来做木马病毒,hook了键盘输入,你输入的东西先复制一份发出去再继续交给系统处理。当然,我们的远程桌面工具也是用这个原理做的,把你鼠标键盘的输入劫持住,不传入系统,传到远程的电脑去了。具体可参考这篇博客:https://www.cnblogs.com/unnamedfish/p/8460441.html

 

验证:纸上得来终觉浅,写段代码辨假真,下面这段代码使用libgo库验证结论

执行结果是:

从上面运行结果可以看出:

一、3个任务死循环,看似要用3个线程才能完成,但使用协程一个线程就完成了,线程并没有卡在while中,证明了sleep被hook不是那个阻塞线程的sleep了。

二、主函数中的临时变量地址是0x6af270b8, 而协程中的临时变量都是0xed323e2c很大的,证明了协程中的临时变量是在堆空间中。

三、兰布达表达式调用的函数的临时变量地址也在堆中,所以协程中调用第三方库不用担心这个问题,不过动态库就不知道了。

四、go + 兰布达表达式只是添加了任务,必须co_sched.Start()后才开始调度,所以先打印了start...

五、Start()是阻塞的,一般要再开个线程执行co_sched.Start();

 

用途:协程主要是用来做网络编程,发出一个请求,就等着对方回响应,也不知道要等多久那种,如果每个请求都开个线程去执行然后等着,那系统可开不了太多线程,用协程随便开,这里协程hook了socket的操作,recv函数就不是真的阻塞了。但并不是所有操作都能被hook做成无阻塞,文件读写的操作就不行。使用协程,代码处理事务顺序逻辑很明显,开发维护都很方便。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值