网址为 https://github.com/docker/docker 。
介绍:Docker是一种操作系统层面的虚拟化技术,可以在操作系统和应用程序之间进行隔离,也可以称之为容器。Docker可以在一台物理服务器上快速运行一个或多个实例。例如,启动一个Cent OS操作系统,并在其内部命令行执行指令后结束,整个过程就像自己在操作系统一样高效。
2.golang项目
网址为 https://github.com/golang/go 。
介绍:Go语言的早期源码使用C语言和汇编语言写成。从Go 1.5版本自举后,完全使用Go语言自身进行编写。Go语言的源码对了解Go语言的底层调度有极大的参考意义,建议希望对Go语言有深入了解的读者读一读。
3.Kubernetes项目
网址为 https://github.com/kubernetes/kubernetes 。
介绍:Google公司开发的构建于Docker之上的容器调度服务,用户可以通过Kubernetes集群进行云端容器集群管理。
4.etcd项目
网址为 https://github.com/coreos/etcd 。
介绍:一款分布式、可靠的KV存储系统,可以快速进行云配置。
5.beego项目
网址为 https://github.com/astaxie/beego 。
介绍:beego是一个类似Python的Tornado框架,采用了RESTFul的设计思路,使用Go语言编写的一个极轻量级、高可伸缩性和高性能的Web应用框架。
6.martini项目
网址为 https://github.com/go-martini/martini 。
介绍:一款快速构建模块化的Web应用的Web框架。
7.codis项目
网址为 https://github.com/Codis Labs/codis。
介绍:国产的优秀分布式Redis解决方案。
8.delve项目
网址为 https://github.com/derekparker/delve 。
介绍:Go语言强大的调试器,被很多集成环境和编辑器整合。
golang学习笔记 https://github.com/piao100101/coding-with-go
频繁创建线程会造成不必要的开销,所以才有了线程池。在线程池中预先保存一定数量的线程,新任务发布到任务队列,线程池中的线程不断地从任务队列中取出任务并执行,可以有效的减少创建和销毁带来的开销。
过多的线程会导致争抢cpu资源,且上下文的切换的开销变大。而工作在用户态的协程能大大减少上下文切换的开销。协程调度器把可运行的协程逐个调度到线程中执行,同时即时把阻塞的协程调度出协程,从而有效地避免了线程的频繁切换,达到了少量线程实现高并发的效果。
多个协程分享操作系统分给线程的时间片,从而达到充分利用CPU的目的,协程调度器决定了则决定了协程运行的顺序。每个线程同一时刻只能运行一个协程。
go调度模型包含三个实体:
每个处理器维护者一个协程G的队列,处理器依次将协程G调度到M中执行。
每个P会周期性地查看全局队列中是否有G待运行并将其调度到M中执行,全局队列中的G主要来自系统调用中恢复的G.
如果协程发起系统调用,则整个工作线程M被阻塞,协程队列中的其他协程都会阻塞。
一般情况下M的个数会略大于P个数,多出来的M将会在G产生系统调用时发挥作用。与线程池类似,Go也提供M池子。当协程G1发起系统掉用时,M1会释放P,由 M1->P->G1 G2 ... 转变成 M1->G1 , M2会接管P的其他协程 M2->P->G2 G3 G4... 。
冗余的M可能来源于缓存池,也可能是新建的。
当G1结束系统调用后,根据M1是否获取到P,进行不用的处理。
多个处理P维护队列可能不均衡,导致部分处理器非常繁忙,而其余相对空闲。产生原因是有些协程自身不断地派生协程。
为此Go调度器提供了工作量窃取策略,当某个处理器P没有需要调度的协程时,将从其他处理中偷取协程,每次偷取一半。
抢占式调度,是指避免某个协程长时间执行,而阻碍其他协程被调度的机制。
调度器监控每个协程执行时间,一旦执行时间过长且有其他协程等待,会把协程暂停,转而调度等待的协程,以达到类似时间片轮转的效果。比如for循环会一直占用执行权。
在IO密集型应用,GOMAXPROCS大小设置大一些,获取性能会更好。
IO密集型会经常发生系统调用,会有一个新的M启用或创建,但由于Go调度器检测M到被阻塞有一定延迟。如果P数量多,则P管理协程队列会变小。
在前一小节中介绍了点亮第一个LED灯,这里我们准备进阶尝试下,输出第一段PWM波形。(PWM也就是脉宽调制,一种可调占空比的技术,得到的效果就是:如果用示波器测量引脚会发现有方波输出,而且高电平、低电平的时间是可调的。)
这里爪爪熊准备写成一个golang的库,并开源到github上,后续更新将直接更新到github中,如果你有兴趣可以和我联系。 github.com/dpawsbear/bear_rpi_go
我在很多的教程中都看到说树莓派的PWM(硬件)只有一个GPIO能够输出,就是 GPIO1 。这可是不小的打击,因为我想使用至少四个 PWM ,还是不死心,想通过硬件手册上找寻蛛丝马迹,看看究竟怎么回事。
手册上找寻东西稍等下讲述,这里先提供一种方法测试 树莓派3B 的 PWM 方法:用指令控制硬件PWM。
这里通过指令的方式掌握了基本的pwm设置技巧,决定去翻一下手册看看到底PWM怎么回事,这里因为没有 BCM2837 的手册,根据之前文章引用官网所说, BCM2835 和 BCM2837 应该是一样的。这里我们直接翻阅 BCM2835 的手册,直接找到 PWM 章节。找到了如下图:
图中可以看到在博通的命名规则中 GPIO 12、13、18、19、40、41、45、52、53 均可以作为PWM输出。但是只有两路PWM0 PWM1。根据我之前所学知识,不出意外应该是PWM0 和 PWM1可以输出不一样的占空比,但是频率应该是一样的。因为没有示波器,暂时不好测试。先找到下面对应图:
根据以上两个图对比可以发现如下规律:
对照上面的表可以看出从 BCM2837 中印出来的能够使用在PWM上的就这几个了。
为了验证个人猜想是否正确,这里先直接使用指令的模式,模拟配置下是否能够正常输出。
通过上面一系列指令模拟发现,(GPIO1、GPIO26)、(GPIO23、GPIO24)是绑定在一起的,调节任意一个,另外一个也会发生变化。也即是PWM0、PWM1虽然输出了两路,可以理解成两路其实都是连在一个输出口上。这里由于没有示波器或者逻辑分析仪这类设备(仅有一个LED灯),所以测试很简陋,下一步是使用示波器这类东西对频率以及信号稳定性进行下测试。
小节:树莓派具有四路硬件输出PWM能力,但是四路中只能输出两个独立(占空比独立)的PWM,同时四路输出的频率均是恒定的。
上面大概了解清楚了树莓派3B的PWM结构,接下来就是探究如何使用Go语言进行设置。
因为拿到了手册,这里我想直接操作寄存器的方式进行设置,也是顺便学习下Go语言处理寄存器的过程。首先需要拿到pwm 系列寄存器的基地址,但是翻了一圈手册,发现只有偏移,没有找到基地址。
经过了一段时间的努力后,决定写一个 树莓派3B golang包开源放在github上,只需要写相关程序进行调用就可以了,以下是相关demo(pwm)(在GPIO.12 上输出PWM波,放上LED灯会有呼吸灯的效果,具体多少频率还没有进行测试)
以下是demo(pwm) 源码